tgis_abstract_datasets.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. """!@package grass.script.tgis_abstract_datasets
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS related functions to be used in temporal GIS Python library package.
  4. Usage:
  5. @code
  6. from grass.script import tgis_abstract_datasets as grass
  7. ...
  8. @endcode
  9. (C) 2008-2011 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Soeren Gebbert
  14. """
  15. import uuid
  16. from tgis_temporal_extent import *
  17. from tgis_spatial_extent import *
  18. from tgis_metadata import *
  19. class abstract_dataset(object):
  20. """This is the base class for all datasets (raster, vector, raster3d, strds, stvds, str3ds)"""
  21. def get_type(self):
  22. """Return the type of this class"""
  23. raise IOError("This method must be implemented in the subclasses")
  24. def get_new_instance(self, ident):
  25. """Return a new instance with the type of this class"""
  26. raise IOError("This method must be implemented in the subclasses")
  27. def get_id(self):
  28. return self.base.get_id()
  29. def get_absolute_time(self):
  30. """Returns a tuple of the start, the end valid time and the timezone of the map
  31. @return A tuple of (start_time, end_time, timezone)
  32. """
  33. start = self.absolute_time.get_start_time()
  34. end = self.absolute_time.get_end_time()
  35. tz = self.absolute_time.get_timezone()
  36. return (start, end, tz)
  37. def get_relative_time(self):
  38. """Returns the relative time interval or None if not present"""
  39. return self.relative_time.get_interval()
  40. def get_temporal_type(self):
  41. """Return the temporal type of this dataset"""
  42. return self.base.get_ttype()
  43. def get_spatial_extent(self):
  44. """Return a tuple of spatial extent (north, south, east, west, top, bottom) """
  45. north = self.spatial_extent.get_north()
  46. south = self.spatial_extent.get_south()
  47. east = self.spatial_extent.get_east()
  48. west = self.spatial_extent.get_west()
  49. top = self.spatial_extent.get_top()
  50. bottom = self.spatial_extent.get_bottom()
  51. return (north, south, east, west, top, bottom)
  52. def select(self, dbif=None):
  53. """Select temporal dataset entry from database and fill up the internal structure"""
  54. self.base.select(dbif)
  55. if self.is_time_absolute():
  56. self.absolute_time.select(dbif)
  57. if self.is_time_relative():
  58. self.relative_time.select(dbif)
  59. self.spatial_extent.select(dbif)
  60. self.metadata.select(dbif)
  61. def is_in_db(self, dbif=None):
  62. """Check if the temporal dataset entry is in the database"""
  63. return self.base.is_in_db(dbif)
  64. def delete(self):
  65. """Delete temporal dataset entry from database if it exists"""
  66. raise IOError("This method must be implemented in the subclasses")
  67. def insert(self, dbif=None):
  68. """Insert temporal dataset entry into database from the internal structure"""
  69. self.base.insert(dbif)
  70. if self.is_time_absolute():
  71. self.absolute_time.insert(dbif)
  72. if self.is_time_relative():
  73. self.relative_time.insert(dbif)
  74. self.spatial_extent.insert(dbif)
  75. self.metadata.insert(dbif)
  76. def update(self, dbif=None):
  77. """Update temporal dataset entry of database from the internal structure"""
  78. self.base.update(dbif)
  79. if self.is_time_absolute():
  80. self.absolute_time.update(dbif)
  81. if self.is_time_relative():
  82. self.relative_time.update(dbif)
  83. self.spatial_extent.update(dbif)
  84. self.metadata.update(dbif)
  85. def print_self(self):
  86. """Print the content of the internal structure to stdout"""
  87. self.base.print_self()
  88. if self.is_time_absolute():
  89. self.absolute_time.print_self()
  90. if self.is_time_relative():
  91. self.relative_time.print_self()
  92. self.spatial_extent.print_self()
  93. self.metadata.print_self()
  94. def print_info(self):
  95. """Print information about this class in human readable style"""
  96. if self.get_type() == "raster":
  97. # 1 2 3 4 5 6 7
  98. # 0123456789012345678901234567890123456789012345678901234567890123456789012345678
  99. print ""
  100. print " +-------------------- Raster Dataset ----------------------------------------+"
  101. if self.get_type() == "raster3d":
  102. # 1 2 3 4 5 6 7
  103. # 0123456789012345678901234567890123456789012345678901234567890123456789012345678
  104. print ""
  105. print " +-------------------- Raster3d Dataset --------------------------------------+"
  106. if self.get_type() == "vector":
  107. # 1 2 3 4 5 6 7
  108. # 0123456789012345678901234567890123456789012345678901234567890123456789012345678
  109. print ""
  110. print " +-------------------- Vector Dataset ----------------------------------------+"
  111. if self.get_type() == "strds":
  112. # 1 2 3 4 5 6 7
  113. # 0123456789012345678901234567890123456789012345678901234567890123456789012345678
  114. print ""
  115. print " +-------------------- Space Time Raster Dataset -----------------------------+"
  116. if self.get_type() == "str3ds":
  117. # 1 2 3 4 5 6 7
  118. # 0123456789012345678901234567890123456789012345678901234567890123456789012345678
  119. print ""
  120. print " +-------------------- Space Time Raster3d Dataset ---------------------------+"
  121. if self.get_type() == "stvds":
  122. # 1 2 3 4 5 6 7
  123. # 0123456789012345678901234567890123456789012345678901234567890123456789012345678
  124. print ""
  125. print " +-------------------- Space Time Vector Dataset -----------------------------+"
  126. print " | |"
  127. self.base.print_info()
  128. if self.is_time_absolute():
  129. self.absolute_time.print_info()
  130. if self.is_time_relative():
  131. self.relative_time.print_info()
  132. self.spatial_extent.print_info()
  133. self.metadata.print_info()
  134. print " +----------------------------------------------------------------------------+"
  135. def print_shell_info(self):
  136. """Print information about this class in shell style"""
  137. self.base.print_shell_info()
  138. if self.is_time_absolute():
  139. self.absolute_time.print_shell_info()
  140. if self.is_time_relative():
  141. self.relative_time.print_shell_info()
  142. self.spatial_extent.print_shell_info()
  143. self.metadata.print_shell_info()
  144. def set_time_to_absolute(self):
  145. self.base.set_ttype("absolute")
  146. def set_time_to_relative(self):
  147. self.base.set_ttype("relative")
  148. def is_time_absolute(self):
  149. if self.base.D.has_key("temporal_type"):
  150. return self.base.get_ttype() == "absolute"
  151. else:
  152. return None
  153. def is_time_relative(self):
  154. if self.base.D.has_key("temporal_type"):
  155. return self.base.get_ttype() == "relative"
  156. else:
  157. return None
  158. def temporal_relation(self, map):
  159. """Return the temporal relation of this and the provided temporal map"""
  160. if self.is_time_absolute() and map.is_time_absolute():
  161. return self.absolute_time.temporal_relation(map.absolute_time)
  162. if self.is_time_relative() and map.is_time_relative():
  163. return self.relative_time.temporal_relation(map.absolute_time)
  164. return None
  165. ###############################################################################
  166. class abstract_map_dataset(abstract_dataset):
  167. """This is the base class for all maps (raster, vector, raster3d)
  168. providing additional function to set the valid time and the spatial extent.
  169. """
  170. def get_new_stds_instance(self, ident):
  171. """Return a new space time dataset instance in which maps are stored with the type of this class"""
  172. raise IOError("This method must be implemented in the subclasses")
  173. def get_stds_register(self):
  174. """Return the space time dataset register table name in which stds are listed in which this map is registered"""
  175. raise IOError("This method must be implemented in the subclasses")
  176. def set_stds_register(self, name):
  177. """Set the space time dataset register table name in which stds are listed in which this map is registered"""
  178. raise IOError("This method must be implemented in the subclasses")
  179. def set_absolute_time(self, start_time, end_time=None, timezone=None):
  180. """Set the absolute time interval with start time and end time
  181. @start_time a datetime object specifying the start time of the map
  182. @end_time a datetime object specifying the end time of the map
  183. @timezone Thee timezone of the map
  184. """
  185. self.base.set_ttype("absolute")
  186. self.absolute_time.set_start_time(start_time)
  187. self.absolute_time.set_end_time(end_time)
  188. self.absolute_time.set_timezone(timezone)
  189. def update_absolute_time(self, start_time, end_time=None, timezone=None, dbif = None):
  190. """Update the absolute time
  191. @start_time a datetime object specifying the start time of the map
  192. @end_time a datetime object specifying the end time of the map
  193. @timezone Thee timezone of the map
  194. """
  195. connect = False
  196. if dbif == None:
  197. dbif = sql_database_interface()
  198. dbif.connect()
  199. connect = True
  200. self.set_absolute_time(start_time, end_time, timezone)
  201. self.absolute_time.update(dbif)
  202. self.base.update(dbif)
  203. if connect == True:
  204. dbif.close()
  205. def set_relative_time(self, interval):
  206. """Set the relative time interval
  207. @interval A double value in days
  208. """
  209. self.base.set_ttype("relative")
  210. self.relative_time.set_interval(interval)
  211. def update_relative_time(self, interval, dbif = None):
  212. """Set the relative time interval
  213. @interval A double value in days
  214. """
  215. connect = False
  216. if dbif == None:
  217. dbif = sql_database_interface()
  218. dbif.connect()
  219. connect = True
  220. self.set_relative_time(interval)
  221. self.relative_time.update(dbif)
  222. self.base.update(dbif)
  223. if connect == True:
  224. dbif.close()
  225. def set_spatial_extent(self, north, south, east, west, top=0, bottom=0):
  226. """Set the spatial extent of the map"""
  227. self.spatial_extent.set_spatial_extent(north, south, east, west, top, bottom)
  228. def delete(self, dbif=None):
  229. """Delete a map entry from database if it exists
  230. Remove dependent entries:
  231. * Remove the map entry in each space time dataset in which this map is registered
  232. * Remove the space time dataset register table
  233. """
  234. connect = False
  235. if dbif == None:
  236. dbif = sql_database_interface()
  237. dbif.connect()
  238. connect = True
  239. if self.is_in_db(dbif):
  240. # First we unregister from all dependent space time datasets
  241. self.unregister(dbif)
  242. # Remove the strds register table
  243. sql = "DROP TABLE " + self.get_stds_register()
  244. #print sql
  245. dbif.cursor.execute(sql)
  246. core.verbose("Delete " + self.get_type() + " dataset <" + self.get_id() + "> from temporal database")
  247. # Delete yourself from the database, trigger functions will take care of dependencies
  248. self.base.delete(dbif)
  249. if connect == True:
  250. dbif.close()
  251. def unregister(self, dbif=None):
  252. """ Remove the map entry in each space time dataset in which this map is registered
  253. """
  254. core.verbose("Unregister " + self.get_type() + " dataset <" + self.get_id() + "> from space time datasets")
  255. connect = False
  256. if dbif == None:
  257. dbif = sql_database_interface()
  258. dbif.connect()
  259. connect = True
  260. # Get all datasets in which this map is registered
  261. rows = self.get_registered_datasets(dbif)
  262. # For each stds in which the map is registered
  263. if rows:
  264. for row in rows:
  265. # Create a space time dataset object to remove the map
  266. # from its register
  267. stds = self.get_new_stds_instance(row["id"])
  268. stds.select(dbif)
  269. stds.unregister_map(self, dbif)
  270. # Take care to update the space time dataset after
  271. # the map has been unregistred
  272. stds.update_from_registered_maps(dbif)
  273. if connect == True:
  274. dbif.close()
  275. def get_registered_datasets(self, dbif=None):
  276. """Return all space time dataset ids in which this map is registered as
  277. sqlite3 rows with column "id" or None if this map is not registered in any
  278. space time dataset.
  279. """
  280. connect = False
  281. if dbif == None:
  282. dbif = sql_database_interface()
  283. dbif.connect()
  284. connect = True
  285. # Select all data from the database
  286. self.select(dbif)
  287. rows = None
  288. # Remove the map from all registered space time datasets
  289. if self.get_stds_register() != None:
  290. # Select all stds tables in which this map is registered
  291. sql = "SELECT id FROM " + self.get_stds_register()
  292. #print sql
  293. dbif.cursor.execute(sql)
  294. rows = dbif.cursor.fetchall()
  295. if connect == True:
  296. dbif.close()
  297. return rows
  298. ###############################################################################
  299. class abstract_space_time_dataset(abstract_dataset):
  300. """Abstract space time dataset class
  301. This class represents a space time dataset. Convenient functions
  302. to select, update, insert or delete objects of this type int the SQL
  303. temporal database exists as well as functions to register or unregister
  304. raster maps.
  305. Parts of the temporal logic are implemented in the SQL temporal database,
  306. like the computation of the temporal and spatial extent as well as the
  307. collecting of metadata.
  308. """
  309. def __init__(self, ident):
  310. self.reset(ident)
  311. def get_new_instance(self, ident):
  312. """Return a new instance with the type of this class"""
  313. raise IOError("This method must be implemented in the subclasses")
  314. def get_new_map_instance(self, ident):
  315. """Return a new instance of a map dataset which is associated with the type of this class"""
  316. raise IOError("This method must be implemented in the subclasses")
  317. def get_map_register(self):
  318. """Return the name of the map register table"""
  319. raise IOError("This method must be implemented in the subclasses")
  320. def set_map_register(self, name):
  321. """Set the name of the map register table"""
  322. raise IOError("This method must be implemented in the subclasses")
  323. def reset(self, ident):
  324. """Reset the internal structure and set the identifier"""
  325. raise IOError("This method must be implemented in the subclasses")
  326. def set_initial_values(self, granularity, temporal_type, semantic_type, \
  327. title=None, description=None):
  328. if temporal_type == "absolute":
  329. self.set_time_to_absolute()
  330. self.absolute_time.set_granularity(granularity)
  331. elif temporal_type == "relative":
  332. self.set_time_to_relative()
  333. self.relative_time.set_granularity(granularity)
  334. else:
  335. core.fatal("Unknown temporal type \"" + temporal_type + "\"")
  336. self.base.set_semantic_type(semantic_type)
  337. self.metadata.set_title(title)
  338. self.metadata.set_description(description)
  339. def delete(self, dbif=None):
  340. """Delete a space time dataset from the database"""
  341. # First we need to check if maps are registered in this dataset and
  342. # unregister them
  343. core.verbose("Delete space time " + self.get_new_map_instance(ident=None).get_type() + " dataset <" + self.get_id() + "> from temporal database")
  344. connect = False
  345. if dbif == None:
  346. dbif = sql_database_interface()
  347. dbif.connect()
  348. connect = True
  349. if self.get_map_register():
  350. sql = "SELECT id FROM " + self.get_map_register()
  351. dbif.cursor.execute(sql)
  352. rows = dbif.cursor.fetchall()
  353. # Unregister each registered map in the table
  354. if rows:
  355. for row in rows:
  356. # Unregister map
  357. map = self.get_new_map_instance(row["id"])
  358. self.unregister_map(map, dbif)
  359. # Drop remove the map register table
  360. sql = "DROP TABLE " + self.get_map_register()
  361. dbif.cursor.execute(sql)
  362. # Remove the primary key, the foreign keys will be removed by trigger
  363. self.base.delete(dbif)
  364. if connect == True:
  365. dbif.close()
  366. def register_map(self, map, dbif=None):
  367. """Register a map in the space time dataset.
  368. This method takes care of the registration of a map
  369. in a space time dataset.
  370. In case the map is already registered this function will break with a warning
  371. and return False
  372. """
  373. connect = False
  374. if dbif == None:
  375. dbif = sql_database_interface()
  376. dbif.connect()
  377. connect = True
  378. if map.is_in_db(dbif) == False:
  379. core.fatal("Only maps with absolute or relative valid time can be registered")
  380. core.verbose("Register " + map.get_type() + " map: " + map.get_id() + " in space time " + map.get_type() + " dataset <" + self.get_id() + ">")
  381. # First select all data from the database
  382. map.select(dbif)
  383. map_id = map.base.get_id()
  384. map_name = map.base.get_name()
  385. map_mapset = map.base.get_mapset()
  386. map_register_table = map.get_stds_register()
  387. #print "Map register table", map_register_table
  388. # Get basic info
  389. stds_name = self.base.get_name()
  390. stds_mapset = self.base.get_mapset()
  391. stds_register_table = self.get_map_register()
  392. #print "STDS register table", stds_register_table
  393. if stds_mapset != map_mapset:
  394. core.fatal("Only maps from the same mapset can be registered")
  395. # Check if map is already registred
  396. if stds_register_table:
  397. sql = "SELECT id FROM " + stds_register_table + " WHERE id = (?)"
  398. dbif.cursor.execute(sql, (map_id,))
  399. row = dbif.cursor.fetchone()
  400. # In case of no entry make a new one
  401. if row and row[0] == map_id:
  402. core.warning("Map " + map_id + "is already registered.")
  403. return False
  404. # Create tables
  405. sql_path = get_sql_template_path()
  406. # We need to create the stmap raster register table bevor we can register the map
  407. if map_register_table == None:
  408. # Create a unique id
  409. uuid_rand = "map_" + str(uuid.uuid4()).replace("-", "")
  410. # Read the SQL template
  411. sql = open(os.path.join(sql_path, "map_stds_register_table_template.sql"), 'r').read()
  412. # Create the raster, raster3d and vector tables
  413. sql = sql.replace("GRASS_MAP", map.get_type())
  414. sql = sql.replace("MAP_NAME", map_name + "_" + map_mapset )
  415. sql = sql.replace("TABLE_NAME", uuid_rand )
  416. sql = sql.replace("MAP_ID", map_id)
  417. sql = sql.replace("STDS", self.get_type())
  418. dbif.cursor.executescript(sql)
  419. map_register_table = uuid_rand + "_" + self.get_type() + "_register"
  420. # Set the stds register table name and put it into the DB
  421. map.set_stds_register(map_register_table)
  422. map.metadata.update(dbif)
  423. core.verbose("Created register table <" + map_register_table + "> for " + map.get_type() + " map <" + map.get_id() + ">")
  424. # We need to create the table and register it
  425. if stds_register_table == None:
  426. # Read the SQL template
  427. sql = open(os.path.join(sql_path, "stds_map_register_table_template.sql"), 'r').read()
  428. # Create the raster, raster3d and vector tables
  429. sql = sql.replace("GRASS_MAP", map.get_type())
  430. sql = sql.replace("SPACETIME_NAME", stds_name + "_" + stds_mapset )
  431. sql = sql.replace("SPACETIME_ID", self.base.get_id())
  432. sql = sql.replace("STDS", self.get_type())
  433. sql_script = ""
  434. sql_script += "BEGIN TRANSACTION;\n"
  435. sql_script += sql
  436. sql_script += "\n"
  437. sql_script += "END TRANSACTION;"
  438. dbif.cursor.executescript(sql_script)
  439. # Trigger have been disabled due to peformance issues while registration
  440. ## We need raster specific trigger
  441. #sql = open(os.path.join(sql_path, "stds_" + map.get_type() + "_register_trigger_template.sql"), 'r').read()
  442. #sql = sql.replace("GRASS_MAP", map.get_type())
  443. #sql = sql.replace("SPACETIME_NAME", stds_name + "_" + stds_mapset )
  444. #sql = sql.replace("SPACETIME_ID", self.base.get_id())
  445. #sql = sql.replace("STDS", self.get_type())
  446. #sql_script = ""
  447. #sql_script += "BEGIN TRANSACTION;\n"
  448. #sql_script += sql
  449. #sql_script += "\n"
  450. #sql_script += "END TRANSACTION;"
  451. #dbif.cursor.executescript(sql_script)
  452. stds_register_table = stds_name + "_" + stds_mapset + "_" + map.get_type() + "_register"
  453. # Set the map register table name and put it into the DB
  454. self.set_map_register(stds_register_table)
  455. self.metadata.update(dbif)
  456. core.verbose("Created register table <" + stds_register_table + "> for space time " + map.get_type() + " dataset <" + self.get_id() + ">")
  457. # Register the stds in the map stds register table
  458. # Check if the entry is already there
  459. sql = "SELECT id FROM " + map_register_table + " WHERE id = ?"
  460. dbif.cursor.execute(sql, (self.base.get_id(),))
  461. row = dbif.cursor.fetchone()
  462. # In case of no entry make a new one
  463. if row == None:
  464. sql = "INSERT INTO " + map_register_table + " (id) " + "VALUES (?)"
  465. #print sql
  466. dbif.cursor.execute(sql, (self.base.get_id(),))
  467. # Now put the raster name in the stds map register table
  468. sql = "INSERT INTO " + stds_register_table + " (id) " + "VALUES (?)"
  469. #print sql
  470. dbif.cursor.execute(sql, (map_id,))
  471. if connect == True:
  472. dbif.close()
  473. return True
  474. def unregister_map(self, map, dbif = None):
  475. """Unregister a map from the space time dataset.
  476. This method takes care of the unregistration of a map
  477. from a space time dataset.
  478. """
  479. connect = False
  480. if dbif == None:
  481. dbif = sql_database_interface()
  482. dbif.connect()
  483. connect = True
  484. if map.is_in_db(dbif) == False:
  485. core.fatal("Unable to find map <" + map.get_id() + "> in temporal database")
  486. core.info("Unregister " + map.get_type() + " map: " + map.get_id())
  487. # First select all data from the database
  488. map.select(dbif)
  489. map_id = map.base.get_id()
  490. map_register_table = map.get_stds_register()
  491. # Get basic info
  492. stds_register_table = self.get_map_register()
  493. # Check if the map is registered in the space time raster dataset
  494. sql = "SELECT id FROM " + map_register_table + " WHERE id = ?"
  495. dbif.cursor.execute(sql, (self.base.get_id(),))
  496. row = dbif.cursor.fetchone()
  497. # Break if the map is not registered
  498. if row == None:
  499. core.warning("Map " + map_id + " is not registered in space time dataset " + self.base.get_id())
  500. return False
  501. # Remove the space time raster dataset from the raster dataset register
  502. if map_register_table != None:
  503. sql = "DELETE FROM " + map_register_table + " WHERE id = ?"
  504. dbif.cursor.execute(sql, (self.base.get_id(),))
  505. # Remove the raster map from the space time raster dataset register
  506. if stds_register_table != None:
  507. sql = "DELETE FROM " + stds_register_table + " WHERE id = ?"
  508. dbif.cursor.execute(sql, (map_id,))
  509. if connect == True:
  510. dbif.close()
  511. def update_from_registered_maps(self, dbif = None):
  512. """This methods updates the spatial and temporal extent as well as
  513. type specific metadata. It should always been called after maps are registered
  514. or unregistered/deleted from the space time dataset.
  515. An other solution to automate this is to use the diactivated trigger
  516. in the SQL files. But this will result in a huge performance issue
  517. in case many maps are registred (>1000).
  518. """
  519. core.info("Update metadata, spatial and temporal extent from all registered maps of <" + self.get_id() + ">")
  520. connect = False
  521. if dbif == None:
  522. dbif = sql_database_interface()
  523. dbif.connect()
  524. connect = True
  525. # Get basic info
  526. stds_name = self.base.get_name()
  527. stds_mapset = self.base.get_mapset()
  528. sql_path = get_sql_template_path()
  529. #We create a transaction
  530. sql_script = ""
  531. sql_script += "BEGIN TRANSACTION;\n"
  532. # Update the spatial and temporal extent from registered maps
  533. # Read the SQL template
  534. sql = open(os.path.join(sql_path, "update_stds_spatial_temporal_extent_template.sql"), 'r').read()
  535. sql = sql.replace("GRASS_MAP", self.get_new_map_instance(None).get_type())
  536. sql = sql.replace("SPACETIME_NAME", stds_name + "_" + stds_mapset )
  537. sql = sql.replace("SPACETIME_ID", self.base.get_id())
  538. sql = sql.replace("STDS", self.get_type())
  539. sql_script += sql
  540. sql_script += "\n"
  541. # Update type specific metadata
  542. sql = open(os.path.join(sql_path, "update_" + self.get_type() + "_metadata_template.sql"), 'r').read()
  543. sql = sql.replace("GRASS_MAP", self.get_new_map_instance(None).get_type())
  544. sql = sql.replace("SPACETIME_NAME", stds_name + "_" + stds_mapset )
  545. sql = sql.replace("SPACETIME_ID", self.base.get_id())
  546. sql = sql.replace("STDS", self.get_type())
  547. sql_script += sql
  548. sql_script += "\n"
  549. sql_script += "END TRANSACTION;"
  550. dbif.cursor.executescript(sql_script)
  551. if connect == True:
  552. dbif.close()