source: mauRepo/MolesManager/trunk/src/libs/migration/processor/commons.py @ 8433

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/mauRepo/MolesManager/trunk/src/libs/migration/processor/commons.py@8433
Revision 8433, 36.3 KB checked in by mnagni, 8 years ago (diff)

Two main new features:
1) the migration generate a report. The report is sent by mail to the subscribers defined in the settings.py
2) require to display a missing observation adds a message on the page and hides the some fields in the html form
3) a new javascript library (commons.js)

Line 
1'''
2BSD Licence
3Copyright (c) 2012, Science & Technology Facilities Council (STFC)
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without modification,
7are permitted provided that the following conditions are met:
8
9    * Redistributions of source code must retain the above copyright notice,
10        this list of conditions and the following disclaimer.
11    * Redistributions in binary form must reproduce the above copyright notice,
12        this list of conditions and the following disclaimer in the documentation
13        and/or other materials provided with the distribution.
14    * Neither the name of the Science & Technology Facilities Council (STFC)
15        nor the names of its contributors may be used to endorse or promote
16        products derived from this software without specific prior written permission.
17
18THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29Created on 15 Nov 2011
30
31@author: mnagni
32'''
33from ea_model.moles3_4.utilities.mo_responsiblepartyinfo import MO_ResponsiblePartyInfo
34from httplib import HTTPConnection
35from xml.etree.ElementTree import XML, tostring
36import time, datetime
37from libs.migration.exception.exceptions import NoDataLineage
38from hashlib import md5
39from xml.sax.saxutils import unescape, escape
40import html5lib
41from html5lib import treebuilders
42from ea_model.moles3_4.result.mo_onlineresource import MO_OnlineResource
43from ea_model.iso_19115_2006_metadata_corrigendum.reference_system_information.md_identifier import MD_Identifier
44from ea_model.iso_19115_2006_metadata_corrigendum.identification_information.md_keywords import MD_Keywords
45from ea_model.iso_19103_2005_schema_language.basic_types.primitive.date_and_time.datetime import DateTime
46from ea_model.iso_19103_2005_schema_language.basic_types.primitive.date_and_time.date import Date
47from ea_model.iso_19108_2006_temporal_schema.temporal_reference_system.tm_position import TM_Position
48from ea_model.iso_19108_2006_temporal_schema.temporal_objects.tm_instant import TM_Instant
49from ea_model.iso_19108_2006_temporal_schema.temporal_objects.tm_period import TM_Period
50from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_address import CI_Address
51from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_onlineresource import CI_OnlineResource
52from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_telephone import CI_Telephone
53from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_contact import CI_Contact
54from ea_model.moles3_4.utilities.mo_individual import MO_Individual
55from ea_model.moles3_4.utilities.mo_organisation import MO_Organisation
56from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_date import CI_Date
57from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_citation import CI_Citation
58from ea_model.iso_19115_2006_metadata_corrigendum.constraint_information.md_constraints import MD_Constraints
59from ea_model.iso_19115_2006_metadata_corrigendum.constraint_information.md_legalconstraints import MD_LegalConstraints
60from ea_model.iso_19115_2006_metadata_corrigendum.citation_and_responsible_party_information.ci_responsibleparty import CI_ResponsibleParty
61from ea_model.iso_19115_2006_metadata_corrigendum.metadata_entity_set_information.md_metadata import MD_Metadata
62from ea_model.iso_19115_2006_metadata_corrigendum.data_quality_information.dq_conformanceresult import DQ_ConformanceResult
63from ea_model.iso_19115_2006_metadata_corrigendum.extent_information.ex_geographicboundingbox import EX_GeographicBoundingBox
64from ea_model.iso_19115_2006_metadata_corrigendum.data_quality_information.dq_element import DQ_Element
65from ea_model.ceda_metadatamodel.ceda_project.ceda_project import CEDA_Project
66from ea_model.ceda_metadatamodel.ceda_utilities.ceda_review import CEDA_Review
67from ea_model.ceda_metadatamodel.ceda_acquisition.ceda_acquisition import CEDA_Acquisition
68from ea_model.ceda_metadatamodel.ceda_observationprocess.ceda_compositeprocess import CEDA_CompositeProcess
69from ea_model.ceda_metadatamodel.ceda_acquisition.ceda_instrument import CEDA_Instrument
70from ea_model.ceda_metadatamodel.ceda_computation.ceda_processing import CEDA_Processing
71from ea_model.ceda_metadatamodel.ceda_result.ceda_result import CEDA_Result
72
73base = '/exist/rest/atoms'
74
75DS_pUBLISHED = 'published'
76DS_WORKING = 'working'
77DS_PUBLISHED = 'Published'
78DOC_STATUS = (DS_pUBLISHED, DS_WORKING, DS_PUBLISHED)
79
80DT_DEPLOYMENTS = 'deployments'
81DT_DATA_ENTITIES = 'data_entities'
82DT_DEPLOYMENT_DATA = 'deployment_data'
83DT_DATA_GRANULES = 'data_granules'
84DOC_TYPES = (DT_DEPLOYMENTS, DT_DATA_ENTITIES, DT_DEPLOYMENT_DATA, DT_DATA_GRANULES)
85
86DO_BADC = 'badc.nerc.ac.uk'
87DO_NEODC = 'neodc.nerc.ac.uk'
88DO_UKSSDC = 'ukssdc.ac.uk'
89
90CEDA = 'Centre for Environmental Data Archive'
91docOwners = (DO_BADC, DO_NEODC, DO_UKSSDC)
92
93atomNS = "{http://www.w3.org/2005/Atom}"
94existNS = "{http://exist.sourceforge.net/NS/exist}"
95molesNS = "{http://ndg.nerc.ac.uk/schema/moles2beta}"
96htmlNS = "{http://www.w3.org/1999/xhtml}"
97georssNS="{http://www.georss.org/georss/10}"
98gmlNS="{http://www.opengis.net/gml}"
99date_format = '%Y-%m-%d'
100datetime_format = date_format + 'T%H:%M:%SZ'
101ihost = 'bora.badc.rl.ac.uk'
102iport = '8080'
103
104linkMarkers = ['Deployment', 'DOWNLOAD', 'DOCUMENTATION', 'ACCESS', 'LOGO', 'ACTIVITY', 'DPT', 'OBS']
105
106#MD_Identifier codes
107MD_CODE_MOLES2_CITATION = 'ceda_moles2_citation'
108
109htmlParser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("etree"), namespaceHTMLElements=False)
110
111def calculateHash(text):
112    """
113        Returns an md5 hexadecimal representation of the given text
114        @param text: the string to encode
115        @return: the hexadecimal md5 value of the given text
116    """
117    encoder = md5()
118    encoder.update(text)
119    return encoder.hexdigest()
120
121def buildExistDocPath(docStatus, docType, docOwner, docName):
122    '''
123        @param docStatus: one value from commons.docStatus
124        @param docType: one value from commons.docTypes
125        @param docOwner: one value from commons.docOwners
126        @param docName: one value from commons.docOwners       
127    '''       
128    return '%s/%s' % (buildExistOwnerPath(docStatus, docType, docOwner), docName)
129
130def buildExistOwnerPath(docStatus, docType, docOwner):
131    '''
132        @param docStatus: one value from commons.docStatus
133        @param docType: one value from commons.docCollections
134        @param docOwner: one value from commons.docOwners
135    '''       
136    return '%s/%s' % (buildExistTypePath(docStatus, docType), docOwner)
137
138def buildExistTypePath(docStatus, docType):
139    '''
140        @param docStatus: one value from commons.docStatus
141        @param docType: one value from commons.docCollections
142    '''       
143    return '%s/%s' % (buildExistStatusPath(docStatus), docType)
144
145def buildExistStatusPath(docStatus):
146    '''
147        @param docStatus: one value from commons.docStatus
148    '''       
149    return '/exist/rest/atoms/%s' % (docStatus)
150
151def getAtomDocumentByMO(migrationObject):
152    if migrationObject is None:
153        raise Exception("migrationObject is None")
154    mo_typeDict = {'DeploymentsMigration': DT_DEPLOYMENTS, 'DataEntityMigration': DT_DATA_ENTITIES, 'DeploymentDataMigration': DT_DEPLOYMENT_DATA}     
155    return getAtomDocumentAsElementtree(migrationObject.doc_status, mo_typeDict[type(migrationObject).__name__], migrationObject.doc_owner, migrationObject.doc_name)
156
157def getAtomDocumentHashByMO(migrationObject):
158    if migrationObject is None:
159        raise Exception("migrationObject is None")   
160    mo_typeDict = {'DeploymentsMigration': DT_DEPLOYMENTS, 'DataEntityMigration': DT_DATA_ENTITIES, 'DeploymentDataMigration': DT_DEPLOYMENT_DATA}     
161    text = _getAtomDocumentAsText(migrationObject.doc_status, mo_typeDict[type(migrationObject).__name__], migrationObject.doc_owner, migrationObject.doc_name)
162    return calculateHash(text)
163
164def getAtomDocumentHash(docStatus, docType, docOwner, docName):
165    source = buildExistDocPath(docStatus, docType, docOwner, docName)
166    text = _getDocument(source)
167    return calculateHash(text)
168
169def hasMOBeenProcessed(migrationObject):
170    '''
171        Checks if a migration object has been already processed.
172        @param migrationObject: an instance of DataEntityMigration or DeploymentsMigration
173        @return True if has been processed, otherwise False
174    '''
175    if migrationObject is None:
176        return False
177   
178    if not hasattr(migrationObject, 'doc_hash'):
179        return False
180    else:
181        if migrationObject.doc_hash is None:
182            return False
183       
184    return True
185
186def hasMOSameHash(migrationObject):
187    '''
188        Checks if a migration object has changed.
189        @param migrationObject: an instance of DataEntityMigration or DeploymentsMigration or DeploymentDataMigration
190        @return True if the hash of the actual document is the same of the migrationObject, otherwise False
191    '''
192    if not hasMOBeenProcessed(migrationObject):
193        return False
194    return getAtomDocumentHashByMO(migrationObject) == migrationObject.doc_hash
195
196def getAtomDocumentByType(migrationObject, docType):
197    if migrationObject is None:
198        raise Exception("migrationObject is None")   
199    return getAtomDocumentAsElementtree(migrationObject.doc_status, docType, migrationObject.doc_owner, migrationObject.doc_name)
200
201def _getAtomDocumentAsText(docStatus, docType, docOwner, docName):
202    source = buildExistDocPath(docStatus, docType, docOwner, docName)
203    return _getDocument(source)
204
205def getAtomDocumentAsElementtree(docStatus, docType, docOwner, docName):
206    source = buildExistDocPath(docStatus, docType, docOwner, docName)
207    return _getXMLDocument(source)
208
209def _getXMLDocument(source):
210    return XML(_getDocument(source))
211
212def stringToTimestamp(timestring):
213    '''
214        Return a timestamp such as is returned by time.time().
215        @param timestring: a time string formatted as '%Y-%m-%dT%H:%M:%SZ'
216    '''   
217    return datetime.datetime.fromtimestamp(time.mktime(time.strptime(timestring, datetime_format)))
218
219def isoDateStringToTimeDate(datestring):
220    '''
221        Return a datatime.datatime instance.
222        @param datestring: a date string formatted as '%Y-%m-%d'
223    '''
224    return datetime.datetime.strptime(datestring, date_format)
225
226def isoDateTimeStringToTimeDate(timestring):
227    '''
228        Return a datatime.datatime instance.
229        @param timestring: a time string formatted as '%Y-%m-%dT%H:%M:%SZ'
230    '''
231    return datetime.datetime.strptime(timestring, datetime_format)
232
233def _getDocument(source):
234    conn = HTTPConnection(host = ihost, port = iport)
235    conn.connect()
236    req = conn.request('GET', source)
237    res = conn.getresponse()
238    xmlDoc = res.read()
239    '''
240    print (xmlDoc)
241    '''
242    conn.close()
243    return xmlDoc
244
245def _returnNotNoneText(element):
246    if element is None:
247        return None
248    return element.text
249
250def findMolesCreationDate(resourceXML):
251    creationDate = resourceXML.find('%sentity/%smolesISO/%screated' % (molesNS, molesNS, molesNS))
252    return _returnNotNoneText(creationDate)
253
254def findMolesPublishedDate(resourceXML):
255    creationDate = resourceXML.find('%sentity/%smolesISO/%spublished' % (molesNS, molesNS, molesNS))
256    return _returnNotNoneText(creationDate)
257
258def findMolesLineage(dataEntityMigration):
259    resourceXML = getAtomDocumentByMO(dataEntityMigration)
260    lineage = resourceXML.find('%sentity/%smolesISO/%slineage' % (molesNS, molesNS, molesNS))
261    if lineage is None:
262        raise NoDataLineage(dataEntityMigration)
263    return lineage.text
264
265def extractMolesProviderID(migrationObject):
266    resourceXML = getAtomDocumentByMO(migrationObject)
267    provider_id = resourceXML.find('%sentity/%smolesISO/%sproviderID' % (molesNS, molesNS, molesNS))
268    return _returnNotNoneText(provider_id)
269
270def extractMolesQuality(migrationObject):
271    resourceXML = getAtomDocumentByMO(migrationObject)
272    quality = resourceXML.find('%sentity/%smolesISO/%squality' % (molesNS, molesNS, molesNS))
273    return _returnNotNoneText(quality)
274
275def extractMolesTemporalRange(migrationObject):
276    resourceXML = getAtomDocumentByMO(migrationObject)
277    temporal_range = resourceXML.find('%stemporalRange' % (molesNS))
278    return _returnNotNoneText(temporal_range)
279
280def extractMolesCreationDate(migrationObject):
281    resourceXML = getAtomDocumentByMO(migrationObject)
282    return findMolesCreationDate(resourceXML)
283
284def extractMolesPublishedDate(migrationObject):
285    resourceXML = getAtomDocumentByMO(migrationObject)
286    return findMolesPublishedDate(resourceXML)
287
288def extractQuality(dataEntityMigration):
289    resourceXML = getAtomDocumentByMO(dataEntityMigration)
290    quality = resourceXML.find('%sentity/%smolesISO/%squality' % (molesNS, molesNS, molesNS))
291    return _returnNotNoneText(quality)
292
293def extractUpdateFrequency(dataEntityMigration):
294    resourceXML = getAtomDocumentByMO(dataEntityMigration)
295    update_frequency = resourceXML.find('%sentity/%smolesISO/%supdateFrequency' % (molesNS, molesNS, molesNS))
296    return _returnNotNoneText(update_frequency)
297
298def extractContent(dataEntityMigration):
299    """
300        Returns a dictionary containing the div composing the
301        <content> element in a dataentity document.
302    """
303    resourceXML = getAtomDocumentByMO(dataEntityMigration)
304    content = resourceXML.find('%scontent' % (atomNS))
305    text = _returnNotNoneText(content)
306    contentDict = {}
307    if text:
308        doc = htmlParser.parse(unescape(text))
309        for el in doc.findall('body//div'):   
310            prop = el.get('property')
311            if prop:
312                if prop.startswith('cedacat'):
313                    contentDict[prop.split(':')[1]] = escape(tostring(el))
314    return contentDict
315
316def _extractAuthors(authorsCSV):
317    if authorsCSV is None:
318        return []
319    authors = authorsCSV.split(',')
320    for index in range(len(authors)):
321        authors[index] = authors[index].strip()
322        if len(authors[index]) == 0:
323            authors.remove(authors[index])
324    return authors
325
326def findAuthorsInResource(resourceMigration):
327    '''
328        Returns a dictionary with the following keys:
329        'authors': a list of string representing the authors
330        'contributors': a list of string representing the contributors
331    '''
332    ret = {}   
333    resourceXML = getAtomDocumentByMO(resourceMigration)
334    ret['authors'] = findAuthorInResource(resourceXML)
335    ret['contributors'] = findContributorInResource(resourceXML)
336    return ret
337
338def findAuthorInResource(resourceXML): 
339    author = resourceXML.find('%sauthor/%sname' % (atomNS, atomNS))
340    return _returnNotNoneText(author)
341
342def findContributorInResource(resourceXML): 
343    contributors = resourceXML.find('%scontributor/%sname' % (atomNS, atomNS))
344    return _returnNotNoneText(contributors)
345
346def findPublishedDate(resourceMigration):
347    resourceXML = getAtomDocumentByMO(resourceMigration)
348    publishedDate = resourceXML.find('%spublished' % (atomNS))
349    return _returnNotNoneText(publishedDate)
350
351def findUpdatedDate(resourceMigration):
352    resourceXML = getAtomDocumentByMO(resourceMigration)
353    publishedDate = resourceXML.find('%supdated' % (atomNS))
354    return _returnNotNoneText(publishedDate)
355
356def findSummary(resourceMigration):
357    """
358        Returns the <entry><summary> tag of an atom document
359        @param resourceMigration: a MigrationObject instance
360        @return: the <summary> value or None if empty
361    """
362    resourceXML = getAtomDocumentByMO(resourceMigration)
363    summary = resourceXML.find('%ssummary' % (atomNS))
364    return _returnNotNoneText(summary)
365
366def findID(dataEntXML):
367    ent_id = dataEntXML.find('%sid' % (atomNS))
368    return _returnNotNoneText(ent_id)
369
370def _updateLinksDict(linksDict, link, linkMarker):
371    if not linksDict.has_key(linkMarker):
372        linksDict[linkMarker] = []
373    rel = link.get('rel')
374    if rel and rel.endswith('/' + linkMarker):
375        linksDict[linkMarker].append({'href': link.get('href'), 'title': link.get('title')}) 
376
377def _extractLinks(dataEntXML, markers):
378    linksDict = {}
379    links = dataEntXML.findall('%slink' % (atomNS))
380    for link in links:
381        for marker in markers:
382            _updateLinksDict(linksDict, link, marker)       
383    return linksDict
384
385def findLinksInMigrationDocument(dataEntityMigration):
386    dataEntXML = getAtomDocumentByMO(dataEntityMigration)
387    linksDict = _extractLinks(dataEntXML, linkMarkers)
388    return linksDict
389
390
391
392def findDownloadLinksInMigrationDocument(migrationObject):
393    """
394        Return a list of dictionaries describing a <link rel="...DOWNLOAD..."> tag type
395        Each dictionary has two keys: 'href' and 'title'
396        @param migrationObject: the migration instance to retrieve and parse
397        @return: a list of dictionaries
398    """
399    linksDict = findLinksInMigrationDocument(migrationObject)
400    if linksDict.has_key('DOWNLOAD'):
401        return linksDict['DOWNLOAD']   
402    return {}       
403
404def findAccessLinksInMigrationDocument(migrationObject):
405    """
406        Return a list of dictionaries describing a <link rel="...ACCESS..."> tag type
407        Each dictionary has two keys: 'href' and 'title'
408        @param migrationObject: the migration instance to retrieve and parse
409        @return: a list of dictionaries
410    """
411    linksDict = findLinksInMigrationDocument(migrationObject)
412    if linksDict.has_key('ACCESS'):
413        return linksDict['ACCESS']     
414    return {}   
415
416def findDocumentationInMigrationDocument(migrationObject):
417    """
418        Return a list of dictionaries describing a <link rel="...DOCUMENTATION..."> tag type
419        Each dictionary has two keys: 'href' and 'title'
420        @param migrationObject: the migration instance to retrieve and parse
421        @return: a list of dictionaries
422    """
423    linksDict = findLinksInMigrationDocument(migrationObject)
424    if linksDict.has_key('DOCUMENTATION'):
425        return linksDict['DOCUMENTATION']     
426    return {}
427
428def findDOIInMigrationDocument(migrationObject):
429    """
430        Return a dictionary describing a <link rel="...DOCUMENTATION..."> tag type
431        The dictionary has two keys: 'href' and 'title'
432        @param migrationObject: the migration instance to retrieve and parse
433        @return: a dictionary relative to the DOI, None otherwise
434    """
435    for link in findDocumentationInMigrationDocument(migrationObject):
436        if link['href'].startswith('http://dx.doi.org/doi:'):
437            return link
438    return None
439
440def findDeploymentsInDE(dataEntityMigration):
441    linksDict = findLinksInMigrationDocument(dataEntityMigration)
442    links = _extractLinksByMarker(linksDict, 'Deployment')
443    return [depName + '.atom' for depName in links]
444
445def findSubTypeInDPT(resourceMigration):
446    resourceXML = getAtomDocumentByMO(resourceMigration)
447    categories = resourceXML.findall('%scategory' % (atomNS))
448    for category in categories:
449        if category.get("term") == "ATOM_SUBTYPE":
450            return category.get("label")   
451       
452def extractTitle(deploymentMigration):
453    resourceXML = getAtomDocumentByMO(deploymentMigration)
454    title = resourceXML.find('%stitle' % (atomNS))
455    return _returnNotNoneText(title)
456
457def extractSummary(migrationObject):
458    resourceXML = getAtomDocumentByMO(migrationObject)
459    summary = resourceXML.find('%ssummary' % (atomNS))
460    return _returnNotNoneText(summary)
461
462def extractGeographicExtentInMigrationDocument(migrationObject):
463    """
464        Extracts if existing the georss:where/gel:Enveloper/upper-lowerCorner elements.
465        @param migrationObject: a migration object to retrieve to parse for data
466        @return: None if no data are found, otherwise a dictionary with keys: 'east', 'north', 'west', 'south' where
467        the values are float
468    """
469    resourceXML = getAtomDocumentByMO(migrationObject)
470    upperCorner = resourceXML.find('%swhere/%sEnvelope/%supperCorner' % (georssNS, gmlNS, gmlNS))
471    lowerCorner = resourceXML.find('%swhere/%sEnvelope/%slowerCorner' % (georssNS, gmlNS, gmlNS))
472    ret = None
473    if upperCorner != None and lowerCorner != None:
474        upperCornerData = upperCorner.text.split()
475        lowerCornerData = lowerCorner.text.split()
476        ret = {'east': float(upperCornerData[0]), 'north': float(upperCornerData[1]), 'west': float(lowerCornerData[0]), 'south': float(lowerCornerData[1])}
477    return ret
478
479def findLinksInDeployment(migrationObject):
480    """
481        Returns a dictionary of links owned by the given dataEntity document
482        @param deploymentMigration: a MigrationObject instance
483        @return: a dictionary of links.
484    """
485    links = {}
486    linksDict = findLinksInMigrationDocument(migrationObject)
487    for marker in linkMarkers:   
488        links[marker] = _extractLinksByMarker(linksDict, marker)
489    return links
490
491def _extractLinksByMarker(linksDict, marker):
492    dpt = []
493    if linksDict.has_key(marker):
494        for link in linksDict[marker]:
495            try:
496                linkLongName = link['href'].split('/')[-1]
497                if '__ATOM__' in linkLongName:
498                    linkName = linkLongName.rsplit('__ATOM__')[1]
499                else:
500                    linkName = linkLongName
501                dpt.append(linkName)
502            except Exception as ex:
503                print "WARN - Cannot extractLinksByMarker %s" % (link)
504    return dpt
505
506
507def getResourceRefs(deploymentRefs):
508    '''
509        Returns a list of Elements representing the inner resource reference items
510        @param resourceRefs: the name of the eXist collection name below the 'deployments' one
511    ''' 
512    XMLDepl = _getXMLDocument(deploymentRefs)
513    return XMLDepl.findall('%scollection/%sresource' % (existNS, existNS))
514
515def getOwnerRefs(docStatus, docType, docOwner):
516    '''
517        Returns a list of Elements representing the inner resource reference items
518        @param resourceRefs: the name of the eXist collection name below the 'deployments' one
519    '''     
520    XMLDepl = _getXMLDocument(buildExistOwnerPath(docStatus, docType, docOwner))
521    return XMLDepl.findall('%scollection/%sresource' % (existNS, existNS))
522
523def getTypeRefs(docStatus, docType):
524    '''
525        Returns a list of Elements representing the inner resource reference items
526        @param resourceRefs: the name of the eXist collection name below the 'deployments' one
527    '''     
528    XMLDepl = _getXMLDocument(buildExistTypePath(docStatus, docType))
529    return XMLDepl.findall('%scollection/%sresource' % (existNS, existNS))
530
531
532
533def getCollectionRefs(publishedRefs):
534    '''
535        Returns a list of Elements representing the inner deployment reference items
536        @param basePublished: the name of the eXist collection name below the 'published' one
537    ''' 
538    XMLPubl = _getXMLDocument(publishedRefs)
539    return XMLPubl.findall('%scollection/%scollection' % (existNS, existNS))
540
541def getResource(source, resourceName):
542    resourceSource = '%s/%s' % (source, resourceName)
543    resourceDoc = _getDocument(resourceSource)
544    return XML(resourceDoc)
545
546def createMD_Keywords(keywords, k_type=None, thesaurusName=None):
547    '''
548        Creates a new MD_Keywords instance.
549        @param keywords: a String array       
550    '''   
551    md_keywords = MD_Keywords()
552    md_keywords.keyword.extend(keywords)
553    if k_type:
554        md_keywords.type = k_type
555    if thesaurusName:
556        md_keywords.thesaurusName = thesaurusName       
557    return md_keywords
558   
559
560def createDateTime(datetime):
561    '''
562        Creates a new DateTime instance.
563        @param datetime: a datetime.datetime instance       
564    '''
565    dateTime = DateTime()
566    dateTime.century = (datetime.year / 100) + 1
567    dateTime.year = datetime.year
568    dateTime.month = datetime.month       
569    dateTime.day = datetime.day
570    dateTime.hour = datetime.hour
571    dateTime.minute = datetime.minute
572    dateTime.second = datetime.second
573    dateTime.timeZone = datetime.tzinfo       
574    return dateTime       
575       
576def createDate(date):
577    '''
578        Creates a new Date instance.
579        @param date: a datetime.datetime instance
580    '''
581    idate = Date()
582    idate.century = (date.year / 100) + 1
583    idate.year = date.year
584    idate.month = date.month       
585    idate.day = date.day       
586    return idate       
587       
588def createTM_Position(anyOther = None, date8601 = None, dateTime8601 = None, time8601 = None):
589    '''
590        Creates a new TM_Position instance
591        @param anyOther: a TM_TemporalPosition instance
592        @param date8601: a Date instance
593        @param dateTime8601:a DateTime instance
594        @param time8601: a Time instance   
595    '''
596    tm_position = TM_Position()
597    if anyOther:
598        tm_position.anyOther = anyOther
599    if date8601:
600        tm_position.date8601 = date8601 
601    if dateTime8601:
602        tm_position.dateTime8601 = dateTime8601
603    if time8601:
604        tm_position.time8601 = time8601
605    return tm_position           
606
607def createTM_Instant(position):
608    '''
609        Creates a new TM_Position instance
610        @param position: a TM_Position instance
611    '''
612    tm_instant = TM_Instant()
613    tm_instant.position = position
614    return tm_instant
615
616def createTM_Period(begin, end):
617    '''
618        Creates a new TM_Position instance
619        @param position: a TM_Position instance
620    '''
621    tm_period = TM_Period()
622    tm_period.begin = begin
623    tm_period.end = end   
624    return tm_period
625
626def createCI_Address(deliveryPoint = None, electronicMailAddress = None, city = None, country = None, postalCode = None):
627    '''
628        Creates a new CI_Address instance
629        @param deliveryPoint: an array of Strings
630        @param electronicMailAddress: an array of Strings
631        @param city: a string
632        @param country: a string               
633        @param postalCode: a string       
634    '''
635    ci_address = CI_Address()
636    if deliveryPoint:
637        ci_address.deliveryPoint = deliveryPoint
638    if electronicMailAddress:
639        ci_address.electronicMailAddress = electronicMailAddress       
640    if postalCode:
641        ci_address.postalCode = postalCode       
642    if city:
643        ci_address.city = city       
644    if country:
645        ci_address.country = country       
646    if postalCode:
647        ci_address.postalCode = postalCode       
648    return ci_address
649
650def createCI_OnlineResource(linkage, name=None):
651    '''
652        Creates a new CI_OnlineResource instance
653        @param linkage: a string (the URL class is associated with a String)
654        @param name: a String
655    '''
656    ci_online_resource = CI_OnlineResource()
657    ci_online_resource.linkage = linkage
658    if name:
659        ci_online_resource.name = name
660    return ci_online_resource
661
662def createCI_Telephone(voice=None, facsimile=None):
663    '''
664        Creates a new CI_Telephone instance
665        @param voice: an array of strings       
666        @param facsimile: an array of strings
667    '''
668    ci_telephone = CI_Telephone()
669    if voice:
670        ci_telephone.voice = voice
671    if facsimile:
672        ci_telephone.facsimile = voice       
673    return ci_telephone
674
675def createCI_Contact(phone, address = None, onlineResource = None):
676    '''
677        Creates a new CI_Contact instance
678        @param phone: a CI_Telephone instance       
679        @param address: a CI_Address instance
680        @param onlineResource: a CI_OnlineResource instance
681    '''
682    ci_contact = CI_Contact()
683    ci_contact.phone = phone
684    if address:
685        ci_contact.address = address
686    if onlineResource:
687        ci_contact.onlineResource = onlineResource       
688    return ci_contact
689
690def createMO_Individual(name = None, contactInfo = None):
691    '''
692        Creates a new MO_Individual instance
693        @param name: a String
694        @param contactInfo: an array of CI_Contact       
695    '''   
696    ci_party = MO_Individual()
697    if name:
698        ci_party.name = name
699    if contactInfo:
700        ci_party.contactInfo = contactInfo       
701    return ci_party
702
703def createMO_Organization(name = None, contactInfo = None):
704    '''
705        Creates a new MO_Organization instance.
706        @param name: a String
707        @param contactInfo: an array of CI_Contact       
708    '''       
709    ci_party = MO_Organisation()
710    if name:
711        ci_party.name = name
712    if contactInfo:
713        ci_party.contactInfo.extend(contactInfo)         
714    return ci_party
715
716def createMO_ResponsiblePartyInfo(role, i_party):
717    """
718        @param role: a CI_RoleCode/MO_RoleValue assigned to this ResponsibleParty
719        @param party: a list of MO_Organization/CI_Individual instances
720    """
721    mo_responsableInfo = MO_ResponsiblePartyInfo()
722    mo_responsableInfo.role = role
723    mo_responsableInfo.party.extend(i_party)
724    return mo_responsableInfo
725
726
727def createCI_Date(dateType, date = None):
728    """
729        Creates a new CI_Date
730        @param dateType: a CI_DateTypeCode value
731        @param date: a DateTime instance
732    """
733    ci_date = CI_Date()
734    ci_date.dateType = dateType
735    if date:
736        ci_date.date = date
737    return ci_date
738
739def createCI_Citation(title, date = None, icitedResponsibleParty = None):
740    """
741        Creates a new CI_Citation
742        @param title: the CI_Citation title
743        @param date: an array of CI_Date instances
744        @param icitedResponsibleParty: a list of CI_ResponsibleParty instances
745    """   
746    ci_citation = CI_Citation()
747    ci_citation.title = title
748    if date and type(date) == list:
749        ci_citation.date.extend(date)
750    if icitedResponsibleParty:
751        ci_citation.citedResponsibleParty.extend(icitedResponsibleParty)
752    return ci_citation
753
754def createMD_Constraints(useLimitation = None):
755    """
756        Creates a new MD_Constrains
757        @param useLimitation: a string array
758    """ 
759    md_constraints = MD_Constraints()
760    if useLimitation and type(useLimitation) == list:
761        md_constraints.useLimitation = useLimitation
762    return md_constraints
763
764def createMD_LegalConstraints(useLimitation = None, accessConstrains = None):
765    """
766        Creates a new MD_LegalConstrains
767        @param useLimitation: a string array
768        @param accessConstrains: an MD_RestrictionCode array
769    """ 
770    md_legalconstraints = MD_LegalConstraints()
771    if useLimitation and type(useLimitation) == list:
772        md_legalconstraints.useLimitation = useLimitation
773    if accessConstrains and type(accessConstrains) == list:
774        md_legalconstraints.accessConstrains = accessConstrains       
775    return md_legalconstraints
776
777def createMD_Identifier(code, authority = None):
778    """
779        Creates a new MD_Identifier
780        @param code: a String
781        @param authority: a CI_Citation instance
782    """
783    md_identifier = MD_Identifier()
784    if code == None:
785        raise NoNullableElement()
786    md_identifier.code = code
787    if authority:
788        md_identifier.authority = authority
789    return md_identifier
790
791def createCI_ResponsibleParty(role, organizationName = None, individualName = None):
792    """
793        Creates a new CI_ResponsibeParty
794        @param role: a CI_RoleCode
795    """
796    ci_responsible_party = CI_ResponsibleParty()
797    ci_responsible_party.role = role
798    if organizationName:
799        ci_responsible_party.organisationName = organizationName
800    if individualName:
801        ci_responsible_party.individualName = individualName   
802    return ci_responsible_party
803
804def createMD_Metadata(date_stamp, contact, language = None):
805    """
806        Creates a new MD_Metadata
807        @param date_stamp: a Date instance
808        @param contacts: a CI_ResponsibleParty array instances
809        @param language: a string
810    """   
811    md_metadata = MD_Metadata()
812    md_metadata.dateStamp = date_stamp
813    for item in contact:
814        md_metadata.contact.append(item)
815    if language:
816        md_metadata.language = language   
817    return md_metadata
818
819def createMO_OnlineResource(linkage, instance = None, name = None, function = None, description = None, applicationProfile = None):
820    """
821        Creates a new CEDA_Result
822        @param linkage: the MO_OnlineResource.linkage.url.??? field
823        @param name: the MO_OnlineResource.linkage.name field
824        @param function: the MO_OnlineResource.function field
825        @param description: the MO_OnlineResource.description field
826        @param applicationProfile: the MO_OnlineResource.applicationProfile field
827    """
828    if instance is None:
829        on_line_resource = MO_OnlineResource()
830         
831    on_line_resource.linkage = linkage
832    if name and on_line_resource.name != name:         
833        on_line_resource.name = name
834    if function and on_line_resource.function != function:
835        on_line_resource.function = function
836    if description and on_line_resource.description != description:
837        on_line_resource.description = description
838    if applicationProfile and on_line_resource.applicationProfile != applicationProfile:
839        on_line_resource.applicationProfile = applicationProfile
840    return on_line_resource       
841
842def createCEDA_Result(curation_category, internal_path, source = None):
843    """
844        Creates a new CEDA_Result
845        @param curation_category: a CEDA_CurationValue instance
846        @param internal_path: a String
847        @param source: an array of MO_OnlineResource instances
848    """
849    ceda_result = CEDA_Result()
850    ceda_result.curationCategory = curation_category
851    ceda_result.internalPath = internal_path           
852    if source: 
853        ceda_result.source = source
854    return ceda_result
855
856
857
858def createDQ_ConformanceResult(explanation, pass_, specification):
859    """
860        Creates a DQ_ConformanceResult instance
861        @param explanation: a String
862        @param pass_: a boolean value
863        @param specification: a CI_Citation instance 
864    """
865    dq_conformanceResult = DQ_ConformanceResult()
866    dq_conformanceResult.explanation = explanation
867    dq_conformanceResult.pass_ = pass_
868    dq_conformanceResult.specification = specification
869    return dq_conformanceResult
870
871def createDQ_Element(result):
872    """
873        Creates a DQ_Element instance
874        @param result: a DQ_Result array (mix 1, max 2 items)
875    """
876    dq_element = DQ_Element()
877    if result and (type(result) == list) and (len(result) >= 1 and len(result) <= 2):
878        dq_element.result = result
879    return dq_element
880
881def createEX_GeographicBoundingBox(east, north, west, south):
882    """
883        Creates an EX_GeographicBoundingBox instance
884        @param east: the eastBoundLongitude attribute as float
885        @param north: the northBoundLongitude attribute as float
886        @param west: the westBoundLongitude attribute as float
887        @param south: the southBoundLongitude attribute as float               
888    """
889    ex_geographic_bb = EX_GeographicBoundingBox()
890    ex_geographic_bb.eastBoundLongitude = east
891    ex_geographic_bb.northBoundLatitude = north
892    ex_geographic_bb.westBoundLongitude = west
893    ex_geographic_bb.southBoundLatitude = south
894    return ex_geographic_bb
895   
896def createCEDA_Processing():
897    ceda_processing = CEDA_Processing()
898    return ceda_processing
899
900
901def createCEDA_Instrument():
902    ceda_instrument = CEDA_Instrument()
903    return ceda_instrument
904
905def createCEDA_CompositeProcess():
906    ceda_cp = CEDA_CompositeProcess()
907    return ceda_cp
908
909def createCEDA_Acquisition():
910    ceda_acquisition = CEDA_Acquisition()
911    return ceda_acquisition
912
913def createCEDA_Review(reviewer, reviewFrequency, reviewStatus):
914    """
915        Returns a new CEDA_Review
916        @param reviewer: an MO_ResponsibilityPartyInfo
917        @param reviewFrequency: a CEDA_ReviewFrequencyValue
918        @param reviewStatus: a CEDA_ReviewStatusValue
919    """
920    ceda_review = CEDA_Review()
921    ceda_review.reviewer = reviewer
922    ceda_review.reviewFrequency = reviewFrequency
923    ceda_review.reviewStatus = reviewStatus           
924    return ceda_review
925
926def createCEDA_Project(abstract = None, publication_state = None, documentation = None, project_resource=None):
927    ceda_project = CEDA_Project()
928    if abstract:
929        ceda_project.abstract = abstract
930    if publication_state:
931        ceda_project.publicationState = publication_state       
932    if documentation and type(documentation) == list:
933        ceda_project.documentation = documentation
934    if project_resource and type(project_resource) == list:
935        ceda_project.projectResource = project_resource   
936    return ceda_project
937   
Note: See TracBrowser for help on using the repository browser.