cap_interface.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. """!
  2. @package web_services.cap_interface
  3. @brief Provides common interface for GUI web_services.widgets to capabilities data of web services.
  4. List of classes:
  5. - cap_interface::CapabilitiesBase
  6. - cap_interface::LayerBase
  7. - cap_interface::WMSCapabilities
  8. - cap_interface::WMSLayer
  9. - cap_interface::WMTSCapabilities
  10. - cap_interface::WMTSLayer
  11. - cap_interface::OnEarthCapabilities
  12. - cap_interface::OnEarthLayer
  13. (C) 2012 by the GRASS Development Team
  14. This program is free software under the GNU General Public License
  15. (>=v2). Read the file COPYING that comes with GRASS for details.
  16. @author Stepan Turek <stepan.turek seznam.cz> (Mentor: Martin Landa)
  17. """
  18. import os
  19. import sys
  20. WMSLibPath = os.path.join(os.getenv("GISBASE"), "etc", "r.in.wms")
  21. sys.path.append(WMSLibPath)
  22. from wms_cap_parsers import WMSCapabilitiesTree, \
  23. WMTSCapabilitiesTree, \
  24. OnEarthCapabilitiesTree
  25. class CapabilitiesBase:
  26. def GetLayerByName(self, name):
  27. """!Find layer by name
  28. """
  29. for l in self.layers_by_id:
  30. if name == l.GetLayerData('name'):
  31. return l
  32. return None
  33. def GetRootLayer(self):
  34. """!Get children layers
  35. """
  36. if self.layers_by_id:
  37. return self.layers_by_id[0]
  38. else:
  39. return None
  40. class LayerBase:
  41. def GetId(self):
  42. """!Get layer id
  43. """
  44. return self.id
  45. def GetChildren(self):
  46. """!Get children layers
  47. """
  48. return self.child_layers
  49. def GetLayerNode(self):
  50. """!Get layer node
  51. """
  52. return self.layer_node
  53. def AddChildLayer(self, layer):
  54. """!Add child layer
  55. """
  56. self.child_layers.append(layer)
  57. class WMSCapabilities(CapabilitiesBase, WMSCapabilitiesTree):
  58. def __init__(self, cap_file, force_version = None):
  59. """!Create common interface for web_services.widgets to WMS capabilities data
  60. """
  61. # checks all elements needed for creation of GetMap requests
  62. # by r.in.wms/d.wms modules, invalid elements are removed
  63. WMSCapabilitiesTree.__init__(self, cap_file, force_version)
  64. self.cap_node = self.getroot().find(self.xml_ns.Ns("Capability"))
  65. self.root_layer = self.cap_node.find(self.xml_ns.Ns("Layer"))
  66. self.layers_by_id = {}
  67. self._initializeLayerTree(self.root_layer)
  68. def _initializeLayerTree(self, parent_layer, id = 0):
  69. """!Build tree, which represents layers
  70. """
  71. if id == 0:
  72. parent_layer = WMSLayer(parent_layer, id, self)
  73. self.layers_by_id[id] = parent_layer
  74. id += 1
  75. layer_nodes = parent_layer.GetLayerNode().findall((self.xml_ns.Ns("Layer")))
  76. for l in layer_nodes:
  77. layer = WMSLayer(l, id, self)
  78. parent_layer.AddChildLayer(layer)
  79. self.layers_by_id[id] = layer
  80. id += 1
  81. id = self._initializeLayerTree(layer, id)
  82. return id
  83. def GetFormats(self):
  84. """!Get supported formats
  85. """
  86. request_node = self.cap_node.find(self.xml_ns.Ns("Request"))
  87. get_map_node = request_node.find(self.xml_ns.Ns("GetMap"))
  88. format_nodes = get_map_node.findall(self.xml_ns.Ns("Format"))
  89. formats = []
  90. for node in format_nodes:
  91. formats.append(node.text)
  92. return formats
  93. class WMSLayer(LayerBase):
  94. def __init__(self, layer_node, id, cap):
  95. """!Common interface for web_services.widgets to WMS capabilities <Layer> element
  96. """
  97. self.id = id
  98. self.cap = cap
  99. self.child_layers = []
  100. self.layer_node = layer_node
  101. self.xml_ns = self.cap.getxmlnshandler()
  102. def GetLayerData(self, param):
  103. """!Get layer data"""
  104. title = self.xml_ns.Ns("Title")
  105. name = self.xml_ns.Ns("Name")
  106. if param == 'title':
  107. title_node = self.layer_node.find(title)
  108. if title_node is not None:
  109. return title_node.text
  110. else:
  111. return None
  112. if param == 'name':
  113. name_node = self.layer_node.find(name)
  114. if name_node is not None:
  115. return name_node.text
  116. else:
  117. return None
  118. if param == 'format':
  119. return self.cap.GetFormats()
  120. if param == 'styles':
  121. styles = []
  122. style = self.xml_ns.Ns("Style")
  123. for style_node in self.layer_node.findall(style):
  124. style_name = ''
  125. style_title = ''
  126. if style_node.find(title) is not None:
  127. style_title = style_node.find(title).text
  128. if style_node.find(name) is not None:
  129. style_name = style_node.find(name).text
  130. styles.append({'title' : style_title,
  131. 'name' : style_name,
  132. 'isDefault' : False})
  133. return styles
  134. if param == 'srs':
  135. projs_nodes = self.layer_node.findall(self.xml_ns.Ns(self.cap.getprojtag()))
  136. projs = []
  137. if projs_nodes is None:
  138. return projs
  139. for p in projs_nodes:
  140. projs.append(p.text.strip())
  141. return projs
  142. def IsRequestable(self):
  143. """!Is it possible to use the layer for WMS GetMap request?
  144. """
  145. name = self.xml_ns.Ns("Name")
  146. name_node = self.layer_node.find(name)
  147. if name_node is not None:
  148. return True
  149. else:
  150. return False
  151. class WMTSCapabilities(CapabilitiesBase, WMTSCapabilitiesTree):
  152. def __init__(self, cap_file):
  153. """!Create common interface for web_services.widgets to WMTS capabilities data
  154. """
  155. # checks all elements needed for creation of GetTile requests
  156. # by r.in.wms/d.wms modules, invalid elements are removed
  157. WMTSCapabilitiesTree.__init__(self, cap_file)
  158. contents = self._find(self.getroot(), 'Contents', self.xml_ns.NsWmts)
  159. layers = self._findall(contents, 'Layer', self.xml_ns.NsWmts)
  160. self.layers_by_id = {}
  161. id = 0
  162. root_layer = WMTSLayer(None, id, self)
  163. self.layers_by_id[id] = root_layer
  164. for layer_node in layers:
  165. id += 1
  166. self.layers_by_id[id] = WMTSLayer(layer_node, id, self)
  167. root_layer.child_layers.append(self.layers_by_id[id])
  168. class WMTSLayer(LayerBase):
  169. def __init__(self, layer_node, id, cap):
  170. """!Common interface for web_services.widgets to WMTS capabilities <Layer> element
  171. """
  172. self.id = id
  173. self.cap = cap
  174. self.child_layers = []
  175. self.layer_node = layer_node
  176. self.xml_ns = self.cap.getxmlnshandler()
  177. self.projs = self._getProjs()
  178. def GetLayerData(self, param):
  179. """!Get layer data
  180. """
  181. title = self.xml_ns.NsOws("Title")
  182. name = self.xml_ns.NsOws("Identifier")
  183. if self.layer_node is None and param in ['title', 'name']:
  184. return None
  185. elif self.layer_node is None:
  186. return []
  187. if param == 'title':
  188. title_node = self.layer_node.find(title)
  189. if title_node is not None:
  190. return title_node.text
  191. else:
  192. return None
  193. if param == 'name':
  194. name_node = self.layer_node.find(name)
  195. if name_node is not None:
  196. return name_node.text
  197. else:
  198. return None
  199. if param == 'styles':
  200. styles = []
  201. for style_node in self.layer_node.findall(self.xml_ns.NsWmts("Style")):
  202. style_name = ''
  203. style_title = ''
  204. if style_node.find(title) is not None:
  205. style_title = style_node.find(title).text
  206. if style_node.find(name) is not None:
  207. style_name = style_node.find(name).text
  208. is_def = False
  209. if 'isDefault' in style_node.attrib and\
  210. style_node.attrib['isDefault'] == 'true':
  211. is_def = True
  212. styles.append({'title' : style_title,
  213. 'name' : style_name,
  214. 'isDefault' : is_def})
  215. return styles
  216. if param == 'format':
  217. formats = []
  218. for frmt in self.layer_node.findall(self.xml_ns.NsWmts('Format')):
  219. formats.append(frmt.text.strip())
  220. return formats
  221. if param == 'srs':
  222. return self.projs
  223. def _getProjs(self):
  224. """!Get layer projections
  225. """
  226. layer_projs = []
  227. if self.layer_node is None:
  228. return layer_projs
  229. mat_set_links = self.layer_node.findall(self.xml_ns.NsWmts('TileMatrixSetLink'))
  230. contents = self.cap.getroot().find(self.xml_ns.NsWmts('Contents'))
  231. tileMatrixSets = contents.findall(self.xml_ns.NsWmts('TileMatrixSet'))
  232. for link in mat_set_links:
  233. mat_set_link_id = link.find(self.xml_ns.NsWmts('TileMatrixSet')).text
  234. if not mat_set_link_id:
  235. continue
  236. for mat_set in tileMatrixSets:
  237. mat_set_id = mat_set.find(self.xml_ns.NsOws('Identifier')).text
  238. if mat_set_id and mat_set_id != mat_set_link_id:
  239. continue
  240. mat_set_srs = mat_set.find(self.xml_ns.NsOws('SupportedCRS')).text.strip()
  241. layer_projs.append(mat_set_srs)
  242. return layer_projs
  243. def IsRequestable(self):
  244. """!Is it possible to use the layer for WMTS request?
  245. """
  246. if self.layer_node is None:
  247. return False
  248. else:
  249. return True
  250. class OnEarthCapabilities(CapabilitiesBase, OnEarthCapabilitiesTree):
  251. def __init__(self, cap_file):
  252. """!Create Common interface for web_services.widgets to NASA OnEarth
  253. tile service data (equivalent to WMS, WMTS capabilities data)
  254. """
  255. # checks all elements needed for creation of GetMap requests
  256. # by r.in.wms/d.wms modules, invalid elements are removed
  257. OnEarthCapabilitiesTree.__init__(self, cap_file)
  258. self.layers_by_id = {}
  259. self._initializeLayerTree(self.getroot())
  260. def _initializeLayerTree(self, parent_layer, id = 0):
  261. """!Build tree, which represents layers
  262. """
  263. if id == 0:
  264. tiled_patterns = parent_layer.find('TiledPatterns')
  265. layer_nodes = tiled_patterns.findall('TiledGroup')
  266. layer_nodes += tiled_patterns.findall('TiledGroups')
  267. parent_layer = OnEarthLayer(None, None, id, self)
  268. self.layers_by_id[id] = parent_layer
  269. id += 1
  270. else:
  271. layer_nodes = parent_layer.layer_node.findall('TiledGroup')
  272. layer_nodes += parent_layer.layer_node.findall('TiledGroups')
  273. for layer_node in layer_nodes:
  274. layer = OnEarthLayer(layer_node, parent_layer, id, self)
  275. self.layers_by_id[id] = layer
  276. id += 1
  277. parent_layer.child_layers.append(layer)
  278. if layer_node.tag == 'TiledGroups':
  279. id = self._initializeLayerTree(layer, id)
  280. return id
  281. class OnEarthLayer(LayerBase):
  282. def __init__(self, layer_node, parent_layer, id, cap):
  283. """!Common interface for web_services.widgets to NASA Earth
  284. capabilities <TiledGroup>\<TiledGroups> element
  285. (equivalent to WMS, WMTS <Layer> element)
  286. """
  287. self.id = id
  288. self.cap = cap
  289. self.layer_node = layer_node
  290. self.child_layers = []
  291. self.parent_layer = parent_layer
  292. def IsRequestable(self):
  293. """!Is it possible to use the layer for NASA OnEarth GetMap request?
  294. """
  295. if self.layer_node is None or \
  296. self.layer_node.tag == 'TiledGroups':
  297. return False
  298. else:
  299. return True
  300. def GetLayerData(self, param):
  301. """!Get layer data
  302. """
  303. if self.layer_node is None and param in ['title', 'name']:
  304. return None
  305. elif self.layer_node is None:
  306. return []
  307. if param == 'title':
  308. title_node = self.layer_node.find("Title")
  309. if title_node is not None:
  310. return title_node.text
  311. else:
  312. return None
  313. if param == 'name':
  314. name_node = self.layer_node.find("Name")
  315. if name_node is not None:
  316. return name_node.text
  317. else:
  318. return None
  319. if param == 'styles':
  320. return []
  321. if param == 'format':
  322. return []
  323. if param == 'srs':
  324. return []