Skip to content

Commit

Permalink
[Fixes #6963] Removal of GeoNetwork support (#6964)
Browse files Browse the repository at this point in the history
* [Fixes #6963] Removal of GeoNetwork support

* - flake8 issues

Co-authored-by: Giovanni Allegri <giohappy@gmail.com>
  • Loading branch information
Alessio Fabiani and giohappy committed Feb 19, 2021
1 parent 431e6a3 commit 7e1b7a0
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 305 deletions.
174 changes: 5 additions & 169 deletions geonode/catalogue/backends/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@
import re
import logging

from urllib.request import (
build_opener,
Request,
HTTPCookieProcessor,
HTTPRedirectHandler
)
from urllib.parse import urlparse, urlencode

from django.conf import settings
Expand Down Expand Up @@ -90,31 +84,10 @@ def __exit__(self, *args, **kwargs):
self.logout()

def login(self):
if self.type == 'geonetwork':
url = "%sgeonetwork/srv/en/xml.user.login" % self.base
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "text/plain"
}
post = urlencode({
"username": self.user,
"password": self.password
})
request = Request(url, post, headers)
self.opener = build_opener(
HTTPCookieProcessor(),
HTTPRedirectHandler())
response = self.opener.open(request)
doc = dlxml.fromstring(response.read())
assert doc.tag == 'ok', "GeoNetwork login failed!"
self.connected = True
NotImplemented

def logout(self):
if self.type == 'geonetwork':
url = "%sgeonetwork/srv/en/xml.user.logout" % self.base
request = Request(url)
response = self.opener.open(request) # noqa
self.connected = False
NotImplemented

def get_by_uuid(self, uuid):
try:
Expand Down Expand Up @@ -183,42 +156,13 @@ def csw_gen_anytext(self, xml):
return ' '.join([value.strip() for value in xml.xpath('//text()')])

def csw_request(self, layer, template):

md_doc = self.csw_gen_xml(layer, template)

if self.type == 'geonetwork':
headers = {
"Content-Type": "application/xml; charset=UTF-8",
"Accept": "text/plain"
}
request = Request(self.url, md_doc, headers)
response = self.urlopen(request)
else:
response = http_post(self.url, md_doc, timeout=TIMEOUT)
response = http_post(self.url, md_doc, timeout=TIMEOUT)
return response

def create_from_layer(self, layer):
response = self.csw_request(layer, "catalogue/transaction_insert.xml")
response = self.csw_request(layer, "catalogue/transaction_insert.xml") # noqa
# TODO: Parse response, check for error report

if self.type == 'geonetwork':

# set layer.uuid based on what GeoNetwork returns
# this is needed for inserting FGDC metadata in GN

exml = dlxml.fromstring(response.read())
identifier = exml.find(
'{%s}InsertResult/{%s}BriefRecord/identifier' %
(namespaces['csw'], namespaces['csw'])).text
layer.uuid = identifier

# Turn on the "view" permission (aka publish) for
# the "all" group in GeoNetwork so that the layer
# will be searchable via CSW without admin login.
# all other privileges are set to False for all
# groups.
self.set_metadata_privs(layer.uuid, {"all": {"view": True}})

return self.url_for_uuid(layer.uuid, namespaces['gmd'])

def delete_layer(self, layer):
Expand All @@ -227,108 +171,9 @@ def delete_layer(self, layer):

def update_layer(self, layer):
tmpl = 'catalogue/transaction_update.xml'

if self.type == 'geonetwork':
tmpl = 'catalogue/transaction_update_gn.xml'

response = self.csw_request(layer, tmpl) # noqa

# TODO: Parse response, check for error report

def set_metadata_privs(self, uuid, privileges):
"""
set the full set of geonetwork privileges on the item with the
specified uuid based on the dictionary given of the form:
{
'group_name1': {'operation1': True, 'operation2': True, ...},
'group_name2': ...
}
all unspecified operations and operations for unspecified groups
are set to False.
"""

# XXX This is a fairly ugly workaround that makes
# requests similar to those made by the GeoNetwork
# admin based on the recommendation here:
# http://bit.ly/ccVEU7

if self.type == 'geonetwork':
get_dbid_url = '%sgeonetwork/srv/en/portal.search.present?%s' % \
(self.base, urlencode({'uuid': uuid}))

# get the id of the data.
request = Request(get_dbid_url)
response = self.urlopen(request)
doc = dlxml.fromstring(response.read())
data_dbid = doc.find(
'metadata/{http://www.fao.org/geonetwork}info/id').text

# update group and operation info if needed
if len(self._group_ids) == 0:
self._group_ids = self._geonetwork_get_group_ids()
if len(self._operation_ids) == 0:
self._operation_ids = self._geonetwork_get_operation_ids()

# build params that represent the privilege configuration
priv_params = {
"id": data_dbid, # "uuid": layer.uuid, # you can say this instead in newer versions of GN
}

for group, privs in privileges.items():
group_id = self._group_ids[group.lower()]
for op, state in privs.items():
if state is not True:
continue
op_id = self._operation_ids[op.lower()]
priv_params['_%s_%s' % (group_id, op_id)] = 'on'

# update all privileges
update_privs_url = "%sgeonetwork/srv/en/metadata.admin?%s" % (
self.base, urlencode(priv_params))
request = Request(update_privs_url)
response = self.urlopen(request)

# TODO: check for error report

def _geonetwork_get_group_ids(self):
"""
helper to fetch the set of geonetwork
groups.
"""
# get the ids of the groups.
get_groups_url = "%sgeonetwork/srv/en/xml.info?%s" % (
self.base, urlencode({'type': 'groups'}))
request = Request(get_groups_url)
response = self.urlopen(request)
doc = dlxml.fromstring(response.read())
groups = {}
for gp in doc.findall('groups/group'):
groups[gp.find('name').text.lower()] = gp.attrib['id']
return groups

def _geonetwork_get_operation_ids(self):
"""
helper to fetch the set of geonetwork
'operations' (privileges)
"""
# get the ids of the operations
get_ops_url = "%sgeonetwork/srv/en/xml.info?%s" % (
self.base, urlencode({'type': 'operations'}))
request = Request(get_ops_url)
response = self.urlopen(request)
doc = dlxml.fromstring(response.read())
ops = {}
for op in doc.findall('operations/operation'):
ops[op.find('name').text.lower()] = op.attrib['id']
return ops

def urlopen(self, request):
if self.opener is None:
raise Exception("No URL opener defined in geonetwork module!!")
else:
return self.opener.open(request)

def search(self, keywords, startposition, maxrecords, bbox):
"""CSW search wrapper"""
formats = []
Expand All @@ -344,16 +189,7 @@ def search(self, keywords, startposition, maxrecords, bbox):
esn='full')

def normalize_bbox(self, bbox):
"""
fix bbox axis order
GeoNetwork accepts x/y
pycsw accepts y/x
"""

if self.type == 'geonetwork':
return bbox
else: # swap coords per standard
return [bbox[1], bbox[0], bbox[3], bbox[2]]
return [bbox[1], bbox[0], bbox[3], bbox[2]]

def metadatarecord2dict(self, rec):
"""
Expand Down
30 changes: 0 additions & 30 deletions geonode/catalogue/backends/geonetwork.py

This file was deleted.

14 changes: 0 additions & 14 deletions geonode/catalogue/templates/catalogue/transaction_update_gn.xml

This file was deleted.

9 changes: 0 additions & 9 deletions geonode/local_settings.py.geoserver.sample
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,11 @@ CATALOGUE = {
'ENGINE': 'geonode.catalogue.backends.pycsw_local',
# pycsw in non-local mode
# 'ENGINE': 'geonode.catalogue.backends.pycsw_http',
# GeoNetwork opensource
# 'ENGINE': 'geonode.catalogue.backends.geonetwork',
# deegree and others
# 'ENGINE': 'geonode.catalogue.backends.generic',

# The FULLY QUALIFIED base url to the CSW instance for this GeoNode
'URL': urljoin(SITEURL, '/catalogue/csw'),
# 'URL': 'http://localhost:8080/geonetwork/srv/en/csw',
# 'URL': 'http://localhost:8080/deegree-csw-demo-3.0.4/services',

# login credentials (for GeoNetwork)
# 'USER': 'admin',
# 'PASSWORD': 'admin',

# 'ALTERNATES_ONLY': True,
}
}
Expand Down
8 changes: 0 additions & 8 deletions geonode/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -1072,20 +1072,12 @@
'ENGINE': 'geonode.catalogue.backends.pycsw_local',
# pycsw in non-local mode
# 'ENGINE': 'geonode.catalogue.backends.pycsw_http',
# GeoNetwork opensource
# 'ENGINE': 'geonode.catalogue.backends.geonetwork',
# deegree and others
# 'ENGINE': 'geonode.catalogue.backends.generic',

# The FULLY QUALIFIED base url to the CSW instance for this GeoNode
'URL': urljoin(SITEURL, '/catalogue/csw'),
# 'URL': 'http://localhost:8080/geonetwork/srv/en/csw',
# 'URL': 'http://localhost:8080/deegree-csw-demo-3.0.4/services',

# login credentials (for GeoNetwork)
# 'USER': 'admin',
# 'PASSWORD': 'admin',

# 'ALTERNATES_ONLY': True,
}
}
Expand Down
54 changes: 18 additions & 36 deletions geonode/tests/csw.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,40 +205,30 @@ def test_csw_outputschema_iso(self):

def test_csw_outputschema_dc_bbox(self):
"""Verify that GeoNode CSW can handle ISO metadata BBOX model with Dublin Core outputSchema"""

# GeoNetwork is not to spec for DC BBOX output
# once ticket http://trac.osgeo.org/geonetwork/ticket/730 is fixed
# we can remove this condition

csw = get_catalogue()
if csw.catalogue.type != 'geonetwork':
# search for 'san_andres_y_providencia_location', output as Dublin
# Core
csw.catalogue.getrecords(
typenames='gmd:MD_Metadata',
keywords=['san_andres_y_providencia_location'],
outputschema='http://www.opengis.net/cat/csw/2.0.2',
esn='full')
# search for 'san_andres_y_providencia_location', output as Dublin
# Core
csw.catalogue.getrecords(
typenames='gmd:MD_Metadata',
keywords=['san_andres_y_providencia_location'],
outputschema='http://www.opengis.net/cat/csw/2.0.2',
esn='full')

record = list(csw.catalogue.records.values())[0]
record = list(csw.catalogue.records.values())[0]

# test CRS constructs in Dublin Core
self.assertEqual(record.bbox.crs.code, 4326)
# test BBOX properties in Dublin Core
from decimal import Decimal
logger.debug([Decimal(record.bbox.minx), Decimal(record.bbox.miny),
Decimal(record.bbox.maxx), Decimal(record.bbox.maxy)])
self.assertAlmostEqual(Decimal(record.bbox.minx), Decimal('-81.859356'), places=3)
self.assertAlmostEqual(Decimal(record.bbox.miny), Decimal('12.166532'), places=3)
self.assertAlmostEqual(Decimal(record.bbox.maxx), Decimal('-81.356409'), places=3)
self.assertAlmostEqual(Decimal(record.bbox.maxy), Decimal('13.396306'), places=3)
# test CRS constructs in Dublin Core
self.assertEqual(record.bbox.crs.code, 4326)
# test BBOX properties in Dublin Core
from decimal import Decimal
logger.debug([Decimal(record.bbox.minx), Decimal(record.bbox.miny),
Decimal(record.bbox.maxx), Decimal(record.bbox.maxy)])
self.assertAlmostEqual(Decimal(record.bbox.minx), Decimal('-81.859356'), places=3)
self.assertAlmostEqual(Decimal(record.bbox.miny), Decimal('12.166532'), places=3)
self.assertAlmostEqual(Decimal(record.bbox.maxx), Decimal('-81.356409'), places=3)
self.assertAlmostEqual(Decimal(record.bbox.maxy), Decimal('13.396306'), places=3)

def test_csw_outputschema_fgdc(self):
"""Verify that GeoNode CSW can handle ISO metadata with FGDC outputSchema"""

# GeoNetwork and deegree do not transform ISO <-> FGDC
# once this is implemented we can remove this condition

csw = get_catalogue()
if csw.catalogue.type in {'pycsw_http', 'pycsw_local'}:
# get all ISO records in FGDC schema
Expand Down Expand Up @@ -270,10 +260,6 @@ def test_csw_query_bbox(self):

def test_csw_upload_fgdc(self):
"""Verify that GeoNode CSW can handle FGDC metadata upload"""

# GeoNetwork and deegree do not transform ISO <-> FGDC
# once this is implemented we can remove this condition

csw = get_catalogue()
if csw.catalogue.type == 'pycsw_http':
# upload a native FGDC metadata document
Expand Down Expand Up @@ -336,10 +322,6 @@ def test_csw_upload_fgdc(self):

def test_csw_bulk_upload(self):
"""Verify that GeoNode CSW can handle bulk upload of ISO and FGDC metadata"""

# GeoNetwork and deegree do not transform ISO <-> FGDC
# once this is implemented we can remove this condition

csw = get_catalogue()
if csw.catalogue.type == 'pycsw_http':

Expand Down
2 changes: 1 addition & 1 deletion geonode/tests/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ def test_delete_layer(self):
from geonode.catalogue import get_catalogue
catalogue = get_catalogue()

# Verify that it no longer exists in GeoNetwork
# Verify that it no longer exists in Catalogue
shp_layer_gn_info = catalogue.get_record(uuid)
assert shp_layer_gn_info is None

Expand Down
Loading

0 comments on commit 7e1b7a0

Please sign in to comment.