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

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

Complete - # 22528: Migration of FAtCat Open Search link for HPFeld
 http://team.ceda.ac.uk/trac/ceda/ticket/22528
Adds a ceda_timestamp column to the tm_instant table to simplify the search-by-time in cedamoles.
The code has been changed consequently to use the new parameter.

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       
510        geographicExtent = create_ex_geographic_boundingbox(ge['east'], \
511                                                            ge['north'], \
512                                                            ge['west'], \
513                                                            ge['south'])
514
515        if len(observation.geographicExtent) == 0 or \
516            (len(observation.geographicExtent) > 0 and \
517             not compareGeographicBoundingBoxes(geographicExtent, \
518                observation.geographicExtent[0])):
519            self.epbRepo.moles3EPB.updateCedaObject(observation, \
520                                                {'geographicExtent': geographicExtent})             
521           
522    def _assignCreationDate(self, observation):
523        if self._deploymentHasSameHash:
524            return 
525       
526        creation_date = extract_moles_published_date(self._deployment_migration)
527        if creation_date is None:
528            creation_date = extract_moles_creation_date(self._deployment_migration)
529        py_datetime = isoDateTimeStringToTimeDate(creation_date)
530        date_time = create_datetime(py_datetime)   
531        tm_position = create_tm_position(dateTime8601 = date_time)
532       
533        if not self._deploymentHasBeenProcessed: 
534            observation.resultTime = create_tm_instant(tm_position)
535            return       
536        #Still have to update observation.geographicExtent
537
538    def _assignPhenomenonTime(self, observation):
539        if self._deploymentHasSameHash and getattr(observation, 'phenomenonTime') != None:
540            return 
541             
542        doc_phenomenon_time = extract_moles_temporal_range(self._deployment_migration)
543       
544        start, end = doc_phenomenon_time, None
545        if '/' in doc_phenomenon_time:
546            start, end = doc_phenomenon_time.split('/')
547        pt = from_date_string_to_pt(start, end) 
548        if self._deploymentHasBeenProcessed \
549                or observation.phenomenonTime is not None \
550                and not compare_phenomenon_times(pt,observation.phenomenonTime):
551            self.epbRepo.moles3EPB.updateCedaObject(observation, {'phenomenonTime': pt})
552            #Now update phenomenonTime but has to remove the previous phenomenonTime       
553        elif not self._deploymentHasBeenProcessed:
554            observation.phenomenonTime = pt               
555    def _assignPermission(self, observation):
556        if self._deploymentHasSameHash and self._dataEntityHasSameHash:
557            return 
558       
559        access_link = find_access_links_in_migration_document(self._deployment_migration)
560        dwn_link = find_download_links_in_migration_document(self._deployment_migration)
561        if len(access_link) == 0:
562            access_link = find_access_links_in_migration_document(self._data_entity_migration) 
563
564        i_accessConstraints = []
565        i_use_limitation = []
566       
567        permission = None
568        if len(access_link) == 0:
569            if len(dwn_link) == 0:
570                dwn_link = find_download_links_in_migration_document(self._data_entity_migration)
571                if dwn_link and len(dwn_link) == 1:               
572                    i_use_limitation.append("These data are open access and available through %s." % (dwn_link[0]['href']) )
573                    #i_accessConstraints.append(MD_RestrictionCode.cl_)
574                    observation.permission = create_md_legal_constraints(useLimitation = i_use_limitation, accessConstrains = i_accessConstraints)
575        else:
576            if access_link and len(access_link) == 1:
577                i_use_limitation.append("Access to these data is restricted. To obtain access please apply for access at: %s" % (access_link[0]['href']))
578                i_accessConstraints.append(getCLValue(MD_RestrictionCode.cl_restricted))
579                observation.permission = create_md_legal_constraints(useLimitation = i_use_limitation, accessConstrains = i_accessConstraints)
580               
581        if not self._deploymentHasBeenProcessed:
582            observation.permission = permission       
583        #Still have to update observation.permission
584                                   
585        '''                               
586        contentDict = extract_content(self._deployment_migration)
587        if not contentDict.has_key('access-restricted'):
588            contentDict = extract_content(self._data_entity_migration)
589        '''           
590
591    def _assignMoles2Link(self, ceda_observation):
592        if self._deploymentHasSameHash:
593            return 
594               
595        i_code = 'http://badc.nerc.ac.uk/view/%s__ATOM__%s' % (self._deployment_migration.doc_owner, self._deployment_migration.doc_name)
596        i_code = i_code.replace('.atom', '')
597        i_authority = create_ci_citation('moles2url')
598        identifier = create_md_identifier(code = i_code, authority = i_authority)
599        if not self._deploymentHasBeenProcessed:             
600            ceda_observation.identifier.append(identifier)
601        #Still have to update observation.permission           
602
603    def _assignInternalReview(self, ceda_observation):
604        if self._deploymentHasBeenProcessed:             
605            return
606               
607        i_party = create_mo_individual(name = 'Graham Parton')
608        i_reviewer = create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_processor), [i_party])
609        ceda_observation.metadataManagement.append( \
610            create_ceda_review(reviewer=i_reviewer, reviewFrequency=getCLValue(CEDA_ReviewFrequencyValue.cl_yearly), \
611                              reviewStatus=getCLValue(CEDA_ReviewStatusValue.cl_required))) 
612
613    def _assignLanguage(self, ceda_observation):
614        if self._deploymentHasBeenProcessed:             
615            return
616       
617        i_date_stamp = create_date(datetime.datetime.now())
618        #i_contact = createCI_Citation("", date = i_date_stamp)
619        i_contact = create_ci_responsible_party(getCLValue(CI_RoleCode.cl_user))
620        ceda_observation.metadata = create_md_metadata(date_stamp=i_date_stamp, contact = [i_contact], language = "English")
621                       
622    def _processResultAccumulation(self, ceda_observation): 
623        if self._dataEntityHasSameHash:             
624            return                     
625
626            updateFrequency = extract_update_frequency(self._data_entity_migration)
627            if updateFrequency:
628                resultAccumulation = MD_MaintenanceFrequencyCode.from_string(updateFrequency)
629                if not self._deploymentHasBeenProcessed:
630                    self.epbRepo.moles3EPB.updateCedaObject(ceda_observation, {'resultAccumulation': resultAccumulation})             
631                    return
632        #Still have to update observation.permission
633                   
634    def _assignName(self, observation):       
635        '''
636            @param relatedPartyInfos: a MO_ResponsiblePartyInfo list
637            @return True if the documents changed, False otherwise
638        '''
639        if self._deploymentHasSameHash and self._dataEntityHasSameHash:
640            return 
641       
642        whereAreAuthors = self._deployment_migration       
643        doc_authors = find_authors_in_resource(self._deployment_migration)       
644        if doc_authors['authors'] in [DO_BADC, DO_NEODC]:
645            doc_authors = find_authors_in_resource(self._data_entity_migration)
646            whereAreAuthors = self._data_entity_migration
647               
648        ind_names = []
649        org_names = []
650        if authors.has_key(doc_authors['authors']):
651            tmp_auth = authors[doc_authors['authors']]
652            ret = self._extractIndividualsAndOrganizations(tmp_auth, whereAreAuthors)
653
654            if len(ret['ind']) > 0:
655                i_party = create_mo_individual(name = ret['ind'][0])
656                observation.relatedParty.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_author), [i_party]))                 
657            if len(ret['org']) > 0:
658                i_party = create_mo_organization(name = ret['org'][0])
659                observation.relatedParty.append(create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_author), [i_party]))
660           
661            if len(ret['ind']) > 1:
662                ind_names.extend(ret['ind'][1:])                                                       
663            if len(ret['org']) > 1:
664                org_names.extend(ret['org'][1:])
665            if len(ret['co_ind']) > 0:                               
666                ind_names.extend(ret['co_ind'])
667            if len(ret['co_org']) > 0:                               
668                org_names.extend(ret['co_org'])                   
669                       
670        else:
671            raise NoAssociatedAuthor(doc_authors['authors'], migrationObject = whereAreAuthors)
672                     
673        if doc_authors['contributors'] and authors.has_key(doc_authors['contributors']):
674            tmp_auth = authors[doc_authors['contributors']]           
675            ret = self._extractIndividualsAndOrganizations(tmp_auth, whereAreAuthors)
676            ind_names.extend(ret['ind'])
677            ind_names.extend(ret['co_ind'])
678            org_names.extend(ret['org'])
679            org_names.extend(ret['co_org'])
680           
681        i_party = []
682        for nm in ind_names:
683            i_party.append(create_mo_individual(name = nm))
684               
685        for nm in org_names:
686            i_party.append(create_mo_organization(name = nm))
687           
688        if i_party:
689            if not self._deploymentHasBeenProcessed:
690                rp = create_mo_responsible_party_info(getCLValue(MM_RoleValue.cl_coinvestigator), i_party)
691                self.epbRepo.moles3EPB.updateCedaObject(observation, {'relatedParty': rp})
692                return
693        #Still have to update observation.permission
694   
695    def _execute(self, ceda_observation):
696        self._assignKeywords(ceda_observation)
697        self._assignLineage(ceda_observation)
698        self._assignResult(ceda_observation)
699        self._assignPublisherCurator(ceda_observation)                       
700        self._assignQuality(ceda_observation)       
701        self._assignDescription(ceda_observation)
702        self._assignTitle(ceda_observation)   
703        self._assignGeographicExtent(ceda_observation)               
704        self._assignCreationDate(ceda_observation)       
705        self._assignPhenomenonTime(ceda_observation)       
706        self._assignPermission(ceda_observation)       
707        self._assignMoles2Link(ceda_observation)               
708        self._assignInternalReview(ceda_observation)       
709        self._assignLanguage(ceda_observation)
710        self._processResultAccumulation(ceda_observation)           
711        self._assignName(ceda_observation)
712        #self._assignDOI(ceda_observation)       
713       
714        #Is a first time process?
715        if not has_mo_been_processed(self._deployment_migration):
716            ceda_observation.publicationState = getCLValue(MM_ObservationPublicationStateValue.cl_working)         
717            docHash = get_atom_document_hash_by_mo(self._data_entity_migration)
718            self.epbRepo.moles3EPB.persistInstance(ceda_observation)       
719            self.epbRepo.migrationEPB.updateMigrationObject(self._deployment_migration, \
720                {'ceda_observation_id': ceda_observation.id,
721                 'doc_hash': docHash})               
722       
723        #Has a proper CEDAGUID?
724        if self.epbRepo.moles3EPB.retrieveGUIDFromInstance(ceda_observation) is None:       
725            ceda_guid = CedaGUID()
726            ceda_guid.id = calculate_hash(self._deployment_migration.depl_id)
727            ceda_guid.ceda_observation = ceda_observation.id
728            self.epbRepo.moles3EPB.persistInstance(ceda_guid)
729            DeploymentProcessor.log.info("GUID for this Observation: %s" % (ceda_guid.id))
730
731        if not self._deploymentHasBeenProcessed:               
732            deploymentDataProcessor = DeploymentDataProcessor(self._deployment_migration, self.epbRepo)               
733            procedure = deploymentDataProcessor.createProcess()
734            project = deploymentDataProcessor.createProject() 
735            self.epbRepo.moles3EPB.updateCedaObject(ceda_observation, {'procedure': procedure, 'inSupportOf': project})
736
737
738        #Still have to update observation.procedure
739        #Still have to update observation.project
740       
741        return ceda_observation
742       
743    def process(self):
744        self._report = []
745        ceda_observation = None
746        #Moles3 object exists...
747        if self._deployment_migration.ceda_observation_id:
748            ceda_observation = self.epbRepo.moles3EPB.search(CEDA_Observation, self._deployment_migration.ceda_observation_id)
749        else:
750            #... does not exist so create it
751            ceda_observation = CEDA_Observation()
752   
753        self._execute(ceda_observation)   
754        return self._report, ceda_observation
Note: See TracBrowser for help on using the repository browser.