source: mauRepo/MolesManager/trunk/cedaMoles/libs/migration/processor/deployment.py @ 8554

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/mauRepo/MolesManager/trunk/cedaMoles/libs/migration/processor/deployment.py@8554
Revision 8554, 38.5 KB checked in by mnagni, 7 years ago (diff)

Incomplete - # 22551: List resources / display single file
 http://team.ceda.ac.uk/trac/ceda/ticket/22551

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: Maurizio Nagni
32'''
33from cedaMoles.libs.migration.processor.commons import find_moles_lineage, \
34    create_mo_responsible_party_info,\
35    DO_BADC, DO_NEODC, find_authors_in_resource, \
36    create_md_identifier, extract_summary, extract_quality, \
37    has_mo_same_hash, get_atom_document_hash_by_mo, extract_title,\
38        create_ceda_result,\
39    create_ex_geographic_boundingbox, extract_ge_in_migration_doc, \
40    find_download_links_in_migration_document,\
41    extract_content, create_ci_citation, create_ci_date, create_date,\
42    create_tm_position, create_tm_instant, extract_moles_creation_date,\
43    create_datetime, isoDateTimeStringToTimeDate, extract_moles_provider_id,\
44    DO_UKSSDC, create_mo_organization,\
45    create_ci_contact, create_ci_address, create_ci_onlineresource,\
46    create_ci_telephone, extract_moles_temporal_range,\
47    find_access_links_in_migration_document,\
48    find_links_in_deployment, create_md_legal_constraints,\
49    create_dq_element, create_dq_conformance_result, find_updated_date,\
50    create_md_metadata, create_mo_online_resource, create_ceda_review, calculate_hash,\
51    create_ci_responsible_party, extract_update_frequency,\
52    find_links_in_migration_document, find_subtype_in_dpt, extract_moles_published_date,\
53    create_md_keywords, has_mo_been_processed, create_mo_individual,\
54    from_date_string_to_pt, \
55    compare_phenomenon_times, compareGeographicBoundingBoxes
56from cedaMoles.libs.epb import EPB
57from cedaMoles.libs.migration.processor.deployment_data import DeploymentDataProcessor
58from cedaMoles.libs.migration.exception.exceptions import NoDataLineage, \
59    NoAssociatedAuthor, NoAssociatedDeployments,\
60    NoGeographicalExtensionException
61from cedaMoles.libs.migration.authors import authors
62from logging import StreamHandler
63import logging
64from datetime import date
65from ea_model.iso_19115_2006_metadata_corrigendum.\
66    citation_and_responsible_party_information.ci_onlinefunctioncode \
67        import CI_OnLineFunctionCode
68from ea_model.iso_19115_2006_metadata_corrigendum.\
69    citation_and_responsible_party_information.ci_datetypecode \
70        import CI_DateTypeCode
71from ea_model.iso_19115_2006_metadata_corrigendum.\
72    constraint_information.md_restrictioncode import MD_RestrictionCode
73from copy import deepcopy
74import datetime
75from cedaMoles.MolesManager.ceda_guid import CedaGUID
76from ea_model.iso_19115_2006_metadata_corrigendum.\
77    citation_and_responsible_party_information.ci_rolecode import CI_RoleCode
78from ea_model.iso_19115_2006_metadata_corrigendum.\
79    maintenance_information.md_maintenancefrequencycode \
80        import MD_MaintenanceFrequencyCode
81from cedaMoles.MolesManager.codelist import MM_RoleValue, \
82    MM_ObservationPublicationStateValue, getCLValue
83from ea_model.ceda_metadatamodel.ceda_observation.ceda_observation \
84    import CEDA_Observation
85from ea_model.ceda_metadatamodel.ceda_result.ceda_curationvalue \
86    import CEDA_CurationValue
87from ea_model.ceda_metadatamodel.ceda_utilities.ceda_reviewstatusvalue \
88    import CEDA_ReviewStatusValue
89from ea_model.ceda_metadatamodel.ceda_utilities.ceda_reviewfrequencyvalue \
90    import CEDA_ReviewFrequencyValue
91
92MET_GEO_FEATURE = 'Meteorological geographical features'
93ORTHOIMAGERY = 'Orthoimagery'
94
95def get_fatcat_online_resource(online_resources = None):
96    """
97        Extracts from a list of MO_OnlineResource the instance
98        representing a Fatcat reference
99       
100        **RETURN**
101        The required instance, `None` otherwise
102    """
103    function = getCLValue(CI_OnLineFunctionCode.cl_search)
104    if online_resources is None:
105        return None 
106    for online_res in online_resources:
107        if online_res.function == function:
108            return online_res
109           
110class DeploymentProcessor(object):
111    '''
112        Migrates a deployment element in a CEDA_Observation entity
113    '''
114    publisherName = 'CEDA'
115   
116    log = logging.getLogger('DeploymentProcessor')
117    log.addHandler(StreamHandler())
118    log.setLevel(logging.INFO)   
119    def __init__(self, data_entity_migration, deployment_migration, epbRepo):
120        '''
121            Initializes the class
122            @param dataEntityMigration: a DataEntityMigration instance
123            @param deploymentMigration: the DeploymentMigration instance
124            @param epbRepo: an instance of EPBRepo             
125        '''             
126        self._data_entity_migration = data_entity_migration
127        self._deployment_migration = deployment_migration
128        self.epbRepo = epbRepo
129        self._dataEntityHasSameHash = has_mo_same_hash(self._data_entity_migration)
130        self._deploymentHasSameHash = has_mo_same_hash(self._deployment_migration)
131        self._deploymentHasBeenProcessed = has_mo_been_processed(self._deployment_migration)
132        self._report = []
133
134    def _addResponsiblePartyInfo(self, oldResponsiblePartyInfos, newResponsiblePartyInfo):
135        opi = None
136        for oldPartyInfo in oldResponsiblePartyInfos:
137            if oldPartyInfo.role == newResponsiblePartyInfo.role:
138                opi = oldPartyInfo
139                break
140           
141        if len(oldResponsiblePartyInfos) == 0 or opi is None:
142            oldResponsiblePartyInfos.append(newResponsiblePartyInfo)
143       
144        if opi is not None: 
145            for np in newResponsiblePartyInfo.party:
146                opi.party.append(np)
147       
148
149
150
151    def _extractIndividualsAndOrganizations(self, tmp_auth, whereAreAuthors):
152        if whereAreAuthors is None:
153            raise NoAssociatedDeployments("migrationObject is None")
154        try:
155            if tmp_auth['author'] == 'unknown':
156                doc_authors = find_authors_in_resource(self._data_entity_migration)
157                tmp_auth = authors[doc_authors['authors']]
158           
159            ret = {'ind': [], 'org': [], 'co_ind': [], 'co_org': []}
160            if tmp_auth['type'] == 'ind':
161                ret['ind'].append(tmp_auth['author'])
162            elif tmp_auth['type'] == 'org':
163                ret['org'].append(tmp_auth['author'])           
164               
165            if tmp_auth['author'] == 'unknown':
166                DeploymentProcessor.log.debug("%s %s %s has unknown author" \
167                                             % (whereAreAuthors.doc_status, \
168                                                whereAreAuthors.doc_owner, \
169                                                whereAreAuthors.doc_name))       
170
171            for item in tmp_auth['co_author_type']:           
172                if (tmp_auth['co_author'][tmp_auth['co_author_type'].index(item)] \
173                        == 'unknown'):
174                    doc_authors = find_authors_in_resource(self._data_entity_migration)
175                    tmp_auth = authors[doc_authors['contributors']]
176                    break
177                 
178            for index in range(len(tmp_auth['co_author_type'])): 
179                ptype = tmp_auth['co_author_type'][index]               
180                if ptype == 'ind':
181                    ret['co_ind'].append(tmp_auth['co_author'][index])
182                elif ptype == 'org':
183                    ret['co_org'].append(tmp_auth['co_author'][index])
184           
185                if (tmp_auth['co_author'][index] == 'unknown'):
186                    DeploymentProcessor.log.info("%s %s %s has unknown author" \
187                                                 % (whereAreAuthors.doc_status, \
188                                                    whereAreAuthors.doc_owner, \
189                                                    whereAreAuthors.doc_name))
190        except Exception as e:
191            print e
192        return ret
193       
194       
195    def updateObservation(self):
196        return EPB.searchOrCreate(CEDA_Observation, self._deployment_migration.ceda_observation_id)
197
198    def assignDOI(self, observation, doi):
199        if doi and doi.has_key('href'):
200            doi = doi['href'][22:]           
201           
202            #Check if a doi has been already assigned
203            observation = self.epbRepo.moles3EPB.loadAttributes(observation, 'identifier')
204            obs_identifier = observation.identifier
205            if obs_identifier:
206                for ident in obs_identifier:
207                    if ident.code == doi:
208                        return
209           
210            py_date = None
211            cited_responsible = \
212                create_ci_responsible_party(role=getCLValue(CI_RoleCode.cl_publisher), \
213                           organizationName='NERC - British Atmospheric Data Centre')
214            if doi.upper() == '10.5285/E8F43A51-0198-4323-A926-FE69225D57DD':
215                py_date = date(2011, 4, 1)
216            elif doi.upper() == '10.5285/78114093-E2BD-4601-8AE5-3551E62AEF2B':
217                py_date = date(2011, 11, 29)               
218            elif doi.upper() == '10.5285/DB8D8981-1A51-4D6E-81C0-CCED9B921390':
219                py_date = date(2012, 4, 16)
220            elif doi.upper() == '10.5285/639A3714-BC74-46A6-9026-64931F355E07':
221                py_date = date(2012, 4, 16)               
222               
223            if py_date:   
224                dt = create_date(py_date)
225                ci_date = create_ci_date(getCLValue(CI_DateTypeCode.cl_publication), \
226                                         date = dt)
227                i_authority = create_ci_citation("DOI", date = ci_date)
228                identifier = create_md_identifier(code = doi, authority=i_authority)
229                self.epbRepo.moles3EPB.updateCedaObject(observation, \
230                                                        {'identifier': identifier})
231                DeploymentProcessor.log.info("DOI: %s" % (doi))                                 
232
233    def _assignKeywords(self, ceda_observation):
234        if self._deploymentHasSameHash:
235            return
236       
237        provider_id = extract_moles_provider_id(self._deployment_migration)
238        i_keywords = []
239        if provider_id == DO_BADC:
240            i_keywords.append(MET_GEO_FEATURE)
241        if provider_id == DO_NEODC:
242            i_keywords.append(ORTHOIMAGERY)
243        if len(i_keywords) > 0:
244            #Is a first time process?
245            if not self._deploymentHasBeenProcessed: 
246                ceda_observation.keywords.append(create_md_keywords(i_keywords))
247            else:
248                ceda_observation.keywords.keyword = i_keywords         
249
250    def _assignLineage(self, observation):
251        if self._deploymentHasSameHash:
252            return
253       
254        data_lineage = find_moles_lineage(self._data_entity_migration)
255        if data_lineage is None:
256            raise NoDataLineage(self._data_entity_migration)
257       
258        if data_lineage != observation.dataLineage:
259            observation.dataLineage = data_lineage 
260
261    def _fatcat_online_resource(self):
262        function = getCLValue(CI_OnLineFunctionCode.cl_search)               
263        tools = find_links_in_migration_document(self._deployment_migration, 'TOOLS')
264        for tool in tools:
265            if 'FAtCatID' not in tool['href']:
266                continue
267           
268            addr, opt = tool['href'].split('?')           
269            return create_mo_online_resource(linkage = tool['href'], \
270                            name = tool['title'], \
271                            function = function, \
272                            description = opt.split(':')[1], \
273                            applicationProfile = None)       
274
275    def _download_online_resource(self, i_sources):
276        download = find_download_links_in_migration_document(self._deployment_migration)
277        content = None
278        if len(download) == 0:
279            download = find_download_links_in_migration_document(self._data_entity_migration)
280            content = extract_content(self._data_entity_migration)
281        else:
282            content = extract_content(self._deployment_migration)
283        for dwn in download:
284            int_description = None
285            int_applicationProfile = None
286            if content.has_key('formats'):
287                #int_applicationProfile = content['formats']
288                pass
289            if dwn['href'].startswith('http://badc.nerc.ac.uk/browse') \
290                    or dwn['href'].startswith('http://neodc.nerc.ac.uk/browse'):
291                int_description = "download directly from archive"
292                 
293            i_sources.append(create_mo_online_resource(linkage = dwn['href'], \
294                            name = dwn['title'], \
295                            function = getCLValue(CI_OnLineFunctionCode.cl_download), \
296                            description = int_description, \
297                            applicationProfile = int_applicationProfile))
298
299    def _assignResult(self, observation):
300        # If both the deployment and the dataentity are unchanged skip the execution
301        if self._deploymentHasSameHash and self._dataEntityHasSameHash:
302            return
303
304        #Delete all the old result without committing
305        if hasattr(observation, 'id') and observation.id is not None \
306                and hasattr(observation, 'result'):
307                    self.epbRepo.moles3EPB.deleteInstance(observation.result)
308
309        i_sources = []
310               
311        fatcat_online_resource = self._fatcat_online_resource()
312        if fatcat_online_resource is not None:
313            i_sources.append(fatcat_online_resource)
314
315        self._download_online_resource(i_sources)       
316           
317        dataentity_id = '%s__ATOM__%s' % (self._data_entity_migration.doc_owner, \
318                                          self._data_entity_migration.doc_name)
319        dataentity_id = dataentity_id.replace('.atom', '')           
320        infodb_de = self.epbRepo.infodbEPB.getCedaInfoApp_dataentityByDE_ID(dataentity_id)
321        i_logical_path = '/dummy'
322        if infodb_de is None:
323            i_logical_path = 'mailto:support@ceda.ac.uk?subject=Link to archive required \
324                %s' %  dataentity_id
325       
326        if infodb_de and infodb_de.has_key('logical_path'):
327            i_logical_path = infodb_de['logical_path']
328               
329        i_category = getCLValue(CEDA_CurationValue.cl_a)                                 
330        if infodb_de and infodb_de.has_key('category') and infodb_de['category']:
331            i_category = getCLValue(CEDA_CurationValue.\
332                                    from_string(infodb_de['category'].lower()))     
333
334                     
335        observation.result = create_ceda_result(i_category, \
336                                                i_logical_path, \
337                                                source = i_sources)                       
338
339    def _assignPublisherCurator(self, observation):
340        if self._deploymentHasSameHash:
341            return
342           
343        provider_id = extract_moles_provider_id(self._deployment_migration)
344        party = None
345        if provider_id == DO_BADC:
346            i_linkage = 'http://badc.rl.ac.uk'
347            i_onlineResources = create_ci_onlineresource(linkage = i_linkage, \
348                                        name = 'British Atmospheric Data Centre Website')
349            i_address = create_ci_address(deliveryPoint = ['British Atmospheric Data Centre, STFC Rutherford Appleton Laboratory'], \
350                                         electronicMailAddress=['badc@rl.ac.uk'], \
351                                         postalCode='OX11 0QX', \
352                                         country='UK', \
353                                         city='Harwell Oxford')                                   
354            i_phone = create_ci_telephone(voice=['+44(0)1235 446432'])                                 
355            contact = create_ci_contact(phone=i_phone, \
356                                        address=i_address, \
357                                        onlineResource=i_onlineResources)                       
358            party = create_mo_organization(name = "NERC - British Atmospheric Data Centre", \
359                                           contactInfo = [contact])
360        elif provider_id == DO_NEODC:
361            i_linkage = 'http://www.neodc.rl.ac.uk'
362            i_onlineResources = create_ci_onlineresource(linkage = i_linkage, \
363                                    name = 'NERC Earth Observation Data Centre website')
364            i_address = create_ci_address(deliveryPoint = ['NERC - Earth Observation Data Centre, STFC Rutherford Appleton Laboratory'], \
365                                         electronicMailAddress=['neodc@rl.ac.uk'], \
366                                         postalCode='OX11 0QX', \
367                                         country='UK', \
368                                         city='Harwell Oxford')                                   
369            i_phone = create_ci_telephone(voice=['+44(0)1235 446432'])                                 
370            contact = create_ci_contact(phone=i_phone, \
371                                        address=i_address, \
372                                        onlineResource=i_onlineResources)                       
373            party = create_mo_organization(name = 'NERC - Earth Observation Data Centre', \
374                                           contactInfo = [contact])
375        elif provider_id == DO_UKSSDC:
376            i_linkage = 'http://www.ukssdc.rl.ac.uk'
377            i_onlineResources = create_ci_onlineresource(linkage = i_linkage, \
378                                            name = 'UK Solar System Data Centre website')
379            i_address = create_ci_address(deliveryPoint = ['UK Solar System Data Centre, STFC Rutherford Appleton Laboratory'], \
380                                         electronicMailAddress=['support@rl.ac.uk'], \
381                                         postalCode='OX11 0QX', \
382                                         country='UK', \
383                                         city='Harwell Oxford')                                   
384            i_phone = create_ci_telephone(voice=['+44(0)1235 445173'])                                 
385            contact = create_ci_contact(phone=i_phone, \
386                                        address=i_address, \
387                                        onlineResource=i_onlineResources)                       
388            party = create_mo_organization(name = 'NERC - UK Solar System Data Centre', \
389                                           contactInfo = [contact])
390       
391        if party and not self._deploymentHasBeenProcessed:
392            newrp = []
393            newrp.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_publisher), [party]))
394            newrp.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_custodian), deepcopy([party])))
395            newrp.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_distributor), deepcopy([party])))
396            newrp.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_pointofcontact), deepcopy([party])))
397            newrp.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_metadataowner), deepcopy([party])))
398            newrp.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_curator), deepcopy([party])))
399            self.epbRepo.moles3EPB.updateCedaObject(observation, {'relatedParty': newrp})           
400            return       
401        #Still have to update observation.result.source
402
403    def _assignQuality(self, observation):
404        if self._dataEntityHasSameHash:
405            return
406               
407        doc_quality = extract_quality(self._data_entity_migration)
408        doc_date = find_updated_date(self._data_entity_migration)
409        ci_dates = []           
410        if doc_date:
411            i_date = create_date(isoDateTimeStringToTimeDate(doc_date))               
412            ci_dates.append(create_ci_date(getCLValue(CI_DateTypeCode.cl_revision), \
413                                           date = i_date))           
414        else:
415            i_date = create_date(isoDateTimeStringToTimeDate(datetime.datetime.now()))
416            ci_dates.append(create_ci_date(getCLValue(CI_DateTypeCode.cl_creation), \
417                                           date = i_date))
418
419        i_specification = create_ci_citation(title = "CEDA Data Quality Statement", \
420                                             date=ci_dates)
421        i_dq_result = create_dq_conformance_result(doc_quality, True, i_specification)
422        i_quality_element = create_dq_element(i_dq_result)
423       
424        if not self._deploymentHasBeenProcessed:     
425            observation.resultQuality.append(i_quality_element)
426            return               
427        #Still have to update observation.result.source
428
429    def _assignDescription(self, observation):
430        if self._dataEntityHasSameHash and self._deploymentHasSameHash:
431            return
432       
433        description = extract_summary(self._deployment_migration)
434        if description is None:
435            description = extract_summary(self._data_entity_migration)
436           
437        if description:
438            observation.description = description
439
440    def _assignTitle(self, observation): 
441        if self._dataEntityHasSameHash and self._deploymentHasSameHash:
442            return
443                     
444        doc_title = extract_title(self._deployment_migration)
445        if doc_title is None:
446            doc_title = extract_title(self._data_entity_migration)
447       
448        if doc_title.startswith('deployment_') or doc_title.startswith('Deployment_'):
449            links = find_links_in_migration_document(self._deployment_migration)
450            dptList = links['DPT']
451            if links.has_key('DPT'):
452                doc_title = 'Data from ' + dptList[0]['title']
453                if len(dptList) > 2:
454                    for dpt in dptList[1:-2]:
455                        doc_title += ', ' + dpt['title']
456                    if len(dptList) > 1:
457                        doc_title += ' and ' + dptList[-1]
458                                                       
459            links = find_links_in_deployment(self._deployment_migration)
460            if links.has_key('OBS'):
461                obsList = []
462                for obs in links['OBS']:
463                    observationStation = self.epbRepo.migrationEPB.get_deployment_data_migration_by_name(self._deployment_migration, obs + '.atom')
464                    obsList.append((extract_title(observationStation), find_subtype_in_dpt(observationStation)))
465               
466                if obsList[0][1] in ['stationary platform' ,'moving platform', 'ship','aircraft','satellite','computer']:
467                    doc_title += ' on '
468                else : 
469                    doc_title += ' at '
470                    doc_title += obsList[0][0]
471                if len(obsList) > 2:
472                    for obs in obsList[1:-2]:
473                        doc_title += ', ' + obs[0]
474                    if len(obsList) > 1:
475                        doc_title += ' and ' + obsList[-1][0]
476           
477            if links.has_key('ACTIVITY'):             
478                for link in links['ACTIVITY']:
479                    activity = self.epbRepo.migrationEPB.get_deployment_data_migration_by_name(self._deployment_migration, link + '.atom')                   
480     
481                    projSubType = find_subtype_in_dpt(activity)
482                    doc_title += ' for the ' + extract_title(activity)
483                    if projSubType[0:14] == 'dgActivityData':
484                        doc_title += ' ' + projSubType[14:]
485                    else :
486                        doc_title += ' ' + projSubType                                                   
487        else:             
488            if doc_title[0:10] != 'Data from' :
489                doc_title = "Data from " + doc_title           
490        auth = create_ci_citation(title = 'ceda_title')                 
491        identifier = create_md_identifier(code = doc_title, authority = auth)
492       
493        if not self._deploymentHasBeenProcessed: 
494            observation.identifier.append(identifier)
495            return           
496        #Still have to update observation.identifier         
497
498    def _assignGeographicExtent(self, observation):
499        if self._dataEntityHasSameHash and self._deploymentHasSameHash:
500            return 
501       
502        ge = extract_ge_in_migration_doc(self._deployment_migration)       
503        if ge is None:
504            ge = extract_ge_in_migration_doc(self._data_entity_migration)
505       
506        if ge is None:
507            self._report.append(NoGeographicalExtensionException(self._deployment_migration))
508            self._report.append(NoGeographicalExtensionException(self._data_entity_migration))
509            return
510       
511        geographicExtent = create_ex_geographic_boundingbox(ge['east'], \
512                                                            ge['north'], \
513                                                            ge['west'], \
514                                                            ge['south'])
515
516        if len(observation.geographicExtent) == 0 or \
517            (len(observation.geographicExtent) > 0 and \
518             not compareGeographicBoundingBoxes(geographicExtent, \
519                observation.geographicExtent[0])):
520            self.epbRepo.moles3EPB.updateCedaObject(observation, \
521                                                {'geographicExtent': geographicExtent})             
522           
523    def _assignCreationDate(self, observation):
524        if self._deploymentHasSameHash:
525            return 
526       
527        creation_date = extract_moles_published_date(self._deployment_migration)
528        if creation_date is None:
529            creation_date = extract_moles_creation_date(self._deployment_migration)
530        py_datetime = isoDateTimeStringToTimeDate(creation_date)
531        date_time = create_datetime(py_datetime)   
532        tm_position = create_tm_position(dateTime8601 = date_time)
533       
534        if not self._deploymentHasBeenProcessed: 
535            observation.resultTime = create_tm_instant(tm_position)
536            return       
537        #Still have to update observation.geographicExtent
538
539    def _assignPhenomenonTime(self, observation):
540        if self._deploymentHasSameHash and getattr(observation, 'phenomenonTime') != None:
541            return 
542             
543        doc_phenomenon_time = extract_moles_temporal_range(self._deployment_migration)
544       
545        start, end = doc_phenomenon_time, None
546        if '/' in doc_phenomenon_time:
547            start, end = doc_phenomenon_time.split('/')
548        pt = from_date_string_to_pt(start, end) 
549        if self._deploymentHasBeenProcessed \
550                or observation.phenomenonTime is not None \
551                and not compare_phenomenon_times(pt,observation.phenomenonTime):
552            self.epbRepo.moles3EPB.updateCedaObject(observation, {'phenomenonTime': pt})
553            #Now update phenomenonTime but has to remove the previous phenomenonTime       
554        elif not self._deploymentHasBeenProcessed:
555            observation.phenomenonTime = pt               
556    def _assignPermission(self, observation):
557        if self._deploymentHasSameHash and self._dataEntityHasSameHash:
558            return 
559       
560        access_link = find_access_links_in_migration_document(self._deployment_migration)
561        dwn_link = find_download_links_in_migration_document(self._deployment_migration)
562        if len(access_link) == 0:
563            access_link = find_access_links_in_migration_document(self._data_entity_migration) 
564
565        i_accessConstraints = []
566        i_use_limitation = []
567       
568        permission = None
569        if len(access_link) == 0:
570            if len(dwn_link) == 0:
571                dwn_link = find_download_links_in_migration_document(self._data_entity_migration)
572                if dwn_link and len(dwn_link) == 1:               
573                    i_use_limitation.append("These data are open access and available through %s." % (dwn_link[0]['href']) )
574                    #i_accessConstraints.append(MD_RestrictionCode.cl_)
575                    observation.permission = create_md_legal_constraints(useLimitation = i_use_limitation, accessConstrains = i_accessConstraints)
576        else:
577            if access_link and len(access_link) == 1:
578                i_use_limitation.append("Access to these data is restricted. To obtain access please apply for access at: %s" % (access_link[0]['href']))
579                i_accessConstraints.append(getCLValue(MD_RestrictionCode.cl_restricted))
580                observation.permission = create_md_legal_constraints(useLimitation = i_use_limitation, accessConstrains = i_accessConstraints)
581               
582        if not self._deploymentHasBeenProcessed:
583            observation.permission = permission       
584        #Still have to update observation.permission
585                                   
586        '''                               
587        contentDict = extract_content(self._deployment_migration)
588        if not contentDict.has_key('access-restricted'):
589            contentDict = extract_content(self._data_entity_migration)
590        '''           
591
592    def _assignMoles2Link(self, ceda_observation):
593        if self._deploymentHasSameHash:
594            return 
595               
596        i_code = 'http://badc.nerc.ac.uk/view/%s__ATOM__%s' % (self._deployment_migration.doc_owner, self._deployment_migration.doc_name)
597        i_code = i_code.replace('.atom', '')
598        i_authority = create_ci_citation('moles2url')
599        identifier = create_md_identifier(code = i_code, authority = i_authority)
600        if not self._deploymentHasBeenProcessed:             
601            ceda_observation.identifier.append(identifier)
602        #Still have to update observation.permission           
603
604    def _assignInternalReview(self, ceda_observation):
605        if self._deploymentHasBeenProcessed:             
606            return
607               
608        i_party = create_mo_individual(name = 'Graham Parton')
609        i_reviewer = create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_processor), [i_party])
610        ceda_observation.metadataManagement.append( \
611            create_ceda_review(reviewer=i_reviewer, reviewFrequency=getCLValue(CEDA_ReviewFrequencyValue.cl_yearly), \
612                              reviewStatus=getCLValue(CEDA_ReviewStatusValue.cl_required))) 
613
614    def _assignLanguage(self, ceda_observation):
615        if self._deploymentHasBeenProcessed:             
616            return
617       
618        i_date_stamp = create_date(datetime.datetime.now())
619        #i_contact = createCI_Citation("", date = i_date_stamp)
620        i_contact = create_ci_responsible_party(getCLValue(CI_RoleCode.cl_user))
621        ceda_observation.metadata = create_md_metadata(date_stamp=i_date_stamp, contact = [i_contact], language = "English")
622                       
623    def _processResultAccumulation(self, ceda_observation): 
624        if self._dataEntityHasSameHash:             
625            return                     
626
627            updateFrequency = extract_update_frequency(self._data_entity_migration)
628            if updateFrequency:
629                resultAccumulation = MD_MaintenanceFrequencyCode.from_string(updateFrequency)
630                if not self._deploymentHasBeenProcessed:
631                    self.epbRepo.moles3EPB.updateCedaObject(ceda_observation, {'resultAccumulation': resultAccumulation})             
632                    return
633        #Still have to update observation.permission
634                   
635    def _assignName(self, observation):       
636        '''
637            @param relatedPartyInfos: a MO_ResponsiblePartyInfo list
638            @return True if the documents changed, False otherwise
639        '''
640        if self._deploymentHasSameHash and self._dataEntityHasSameHash:
641            return 
642       
643        whereAreAuthors = self._deployment_migration       
644        doc_authors = find_authors_in_resource(self._deployment_migration)       
645        if doc_authors['authors'] in [DO_BADC, DO_NEODC]:
646            doc_authors = find_authors_in_resource(self._data_entity_migration)
647            whereAreAuthors = self._data_entity_migration
648               
649        ind_names = []
650        org_names = []
651        if authors.has_key(doc_authors['authors']):
652            tmp_auth = authors[doc_authors['authors']]
653            ret = self._extractIndividualsAndOrganizations(tmp_auth, whereAreAuthors)
654
655            if len(ret['ind']) > 0:
656                i_party = create_mo_individual(name = ret['ind'][0])
657                observation.relatedParty.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_author), [i_party]))                 
658            if len(ret['org']) > 0:
659                i_party = create_mo_organization(name = ret['org'][0])
660                observation.relatedParty.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_author), [i_party]))
661           
662            if len(ret['ind']) > 1:
663                ind_names.extend(ret['ind'][1:])                                                       
664            if len(ret['org']) > 1:
665                org_names.extend(ret['org'][1:])
666            if len(ret['co_ind']) > 0:                               
667                ind_names.extend(ret['co_ind'])
668            if len(ret['co_org']) > 0:                               
669                org_names.extend(ret['co_org'])                   
670                       
671        else:
672            raise NoAssociatedAuthor(doc_authors['authors'], migrationObject = whereAreAuthors)
673                     
674        if doc_authors['contributors'] and authors.has_key(doc_authors['contributors']):
675            tmp_auth = authors[doc_authors['contributors']]           
676            ret = self._extractIndividualsAndOrganizations(tmp_auth, whereAreAuthors)
677            ind_names.extend(ret['ind'])
678            ind_names.extend(ret['co_ind'])
679            org_names.extend(ret['org'])
680            org_names.extend(ret['co_org'])
681           
682        i_party = []
683        for nm in ind_names:
684            i_party.append(create_mo_individual(name = nm))
685               
686        for nm in org_names:
687            i_party.append(create_mo_organization(name = nm))
688           
689        if i_party:
690            if not self._deploymentHasBeenProcessed:
691                rp = create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_coinvestigator), i_party)
692                self.epbRepo.moles3EPB.updateCedaObject(observation, {'relatedParty': rp})
693                return
694        #Still have to update observation.permission
695   
696    def _execute(self, ceda_observation):
697        self._assignKeywords(ceda_observation)
698        self._assignLineage(ceda_observation)
699        self._assignResult(ceda_observation)
700        self._assignPublisherCurator(ceda_observation)                       
701        self._assignQuality(ceda_observation)       
702        self._assignDescription(ceda_observation)
703        self._assignTitle(ceda_observation)   
704        self._assignGeographicExtent(ceda_observation)               
705        self._assignCreationDate(ceda_observation)       
706        self._assignPhenomenonTime(ceda_observation)       
707        self._assignPermission(ceda_observation)       
708        self._assignMoles2Link(ceda_observation)               
709        self._assignInternalReview(ceda_observation)       
710        self._assignLanguage(ceda_observation)
711        self._processResultAccumulation(ceda_observation)           
712        self._assignName(ceda_observation)
713        #self._assignDOI(ceda_observation)       
714       
715        #Is a first time process?
716        if not has_mo_been_processed(self._deployment_migration):
717            ceda_observation.publicationState = getCLValue(MM_ObservationPublicationStateValue.cl_working)         
718            docHash = get_atom_document_hash_by_mo(self._data_entity_migration)
719            self.epbRepo.moles3EPB.persistInstance(ceda_observation)       
720            self.epbRepo.migrationEPB.updateMigrationObject(self._deployment_migration, \
721                {'ceda_observation_id': ceda_observation.id,
722                 'doc_hash': docHash})               
723       
724        #Has a proper CEDAGUID?
725        if self.epbRepo.moles3EPB.retrieveGUIDFromInstance(ceda_observation) is None:       
726            ceda_guid = CedaGUID()
727            ceda_guid.id = calculate_hash(self._deployment_migration.depl_id)
728            ceda_guid.ceda_observation = ceda_observation.id
729            self.epbRepo.moles3EPB.persistInstance(ceda_guid)
730            DeploymentProcessor.log.info("GUID for this Observation: %s" % (ceda_guid.id))
731
732        if not self._deploymentHasBeenProcessed:               
733            deploymentDataProcessor = DeploymentDataProcessor(self._deployment_migration, self.epbRepo)               
734            procedure = deploymentDataProcessor.createProcess()
735            project = deploymentDataProcessor.createProject() 
736            self.epbRepo.moles3EPB.updateCedaObject(ceda_observation, {'procedure': procedure, 'inSupportOf': project})
737
738
739        #Still have to update observation.procedure
740        #Still have to update observation.project
741       
742        return ceda_observation
743       
744    def process(self):
745        self._report = []
746        ceda_observation = None
747        #Moles3 object exists...
748        if self._deployment_migration.ceda_observation_id:
749            ceda_observation = self.epbRepo.moles3EPB.search(CEDA_Observation, self._deployment_migration.ceda_observation_id)
750        else:
751            #... does not exist so create it
752            ceda_observation = CEDA_Observation()
753   
754        self._execute(ceda_observation)   
755        return self._report, ceda_observation
Note: See TracBrowser for help on using the repository browser.