source: TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/browse/ServiceBinding.py @ 1211

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI07-MOLES/trunk/StubB/XSLT/browse/portal/cgi/browse/ServiceBinding.py@1211
Revision 1211, 8.2 KB checked in by lawrence, 13 years ago (diff)

More tiny modifications ..

RevLine 
[1150]1#
2# There are (at least) two classes of service map issues which NDG needs to support.
3# Firstly, one can expect that given a specific NDG record, there is a native
4# service for that record ... eg. for an A record, the native service is the
5# data extractor, but there may be others ... at some point we need to be
6# able to find those out (this is a processing affordance issue, and something
7# that we want to use registries for) ... anyway, meanwhile, we have these "native"
8# service types.
9# Secondly, in D  we have related URL's, which are essentially mappings to
10# services which may exist on the dataset described by that D-catalogue record.
11# This is a special case of the generic case described above ...
12#
13# This module provides classes to support these activities.
14
[1175]15from Utilities import myConfig
[1150]16from htmlUtilities import hyperlink,image
[1175]17from ETxmlView import nsdumb,et2text
[1150]18
[1175]19def idconvert(e,helper=None):
20    ''' Converts an XML ndg identifier into a uri version '''
21    if helper is None:
22        helper=nsdumb()
23    s='%s:%s:%s'%(helper.getText(e,'repositoryIdentifier'),
24                    helper.getText(e,'schemeIdentifier'),
25                    helper.getText(e,'localIdentifier'))
26    return s
27
[1150]28class ServiceMap(myConfig):
29    ''' This should itself eventually be a service that can be looked up, or maybe
30    even use the dns '''
31    def __init__(self,serviceFile='cgi/serviceMap.config'):
32        myConfig.__init__(self,serviceFile)
[1182]33        self.seticon('RELATED')
34    def seticon(self,t):
35        ''' Set icon type t, or if it doesn't exist, use RELATED '''
36        self.icon=self.get(t,'icon')
37        if self.icon is None:
38            self.seticon('RELATED')
39        else: self.iconalt=self.get(t,'icon_alt')
[1150]40    def do(self,serviceType,dataProvider):
41        '''  Return an actual endpoint for a given service from the data provider, e.g.
42        for ndg_a_service,badc.nerc.ac.uk get http://superglue.badc.rl.ac.uk/cgi-bin/browse.py '''
[1158]43        serviceType=serviceType.upper() # ought to be redundant ...
[1150]44        r=self.get(serviceType,dataProvider)
45        if r is None:
[1152]46            # just return the URL
[1150]47            if dataProvider[0:4]!='http':
[1182]48                r='http://%s'%dataProvider
49            else: r=dataProvider
50        self.seticon(serviceType)
51        return r
[1150]52       
[938]53class Service:
[1150]54    ''' This simple class simply holds the service information known in a DIF ''' 
[938]55    def __init__(self):
[1150]56        self.type='dif_related_url'
[938]57        self.name=''
58        self.url=''
59        self.description=''
60
61class ServiceBinding (Service):
[1175]62        ''' Given a specific entryID, we can go from the scheme identifier to the
[1150]63        native service which one expects to be able to operate upon it, for example,
64        an NDG-A type identifier should expect the NDG-A-Service running at the
[1175]65        specific repository. Note that we support the NDG id in the abbreviated format
66        entryID is a repository:scheme:localidentifier string '''
[1182]67        def __init__(self,n='',entryID=None,serviceFile='serviceMap.config'):
[1150]68            Service.__init__(self)
69            # regrettably we used different things in our ID's than we did in
70            # our difs :
[1161]71            self.mapping={'NDG-A0':'NDG_A_SERVICE','NDG-B0':'NDG_B_SERVICE',
[1173]72            'NDG-B1':'NDG_B_SERVICE','DIF':'DISCOVERY'}
[1151]73            self.serviceMap=ServiceMap(serviceFile=serviceFile)
[1150]74            self.name=n
[1175]75            if entryID is not None:
76                self.fromEntry(entryID)
77        def fromNative(self,nativeID,helper=None,seqno=1):
78            ''' Support native XML ID form of entryID, see also fromEntry '''
79            entryID=idconvert(nativeID,helper)
80            return self.fromEntry(entryID,seqno)
81        def fromEntry(self,entryID,seqno=1):
82            ''' Given an entryID, get the native service '''
83            #e.g. badc.nerc.ac.uk:NDG-A0:someLocalIdentifier
84            s,r,l,b=self.__getsrlb(entryID)
[1158]85            uri=self.__makeuri(s,r,l)
[1171]86            self.url=self.__makeurl(s,b,uri,seqno)
[1152]87            self.serviceType=s
[1211]88            self.uri=uri
[1150]89            return self
[1175]90        def fromRelated(self,elem,entryID,helper=None,seqno=1):
91            ''' Given a DIF related URL, get a service binding,
92            using an instantiated ET helper that's available
93            to avoid problems with namespaces '''
[1150]94            # e.g:
95            #<Related_URL>
96            #<URL_Content_Type>NDG_B_Service</URL_Content_Type>
97            #<URL>badc.nerc.ac.uk</URL>
98            #</Related_URL>
99            #<Related_URL>
100            #<URL>http://badc.nerc.ac.uk/browse/badc/CDs/spade9293</URL>
101            #</Related_URL>
[1182]102            #following call simply sets some defaults
[1175]103            s,r,l,b=self.__getsrlb(entryID)
[1182]104            #which we now overwrite with detail from this particular rleated url
105            #following helps us avoid namespace problems
[1175]106            if helper is None:helper=nsdumb()
107            self.description=helper.getText(elem,'Description')
108            s=helper.getText(elem,'URL_Content_Type').upper()
[1158]109            self.serviceType=s
110            if s!='':
[1182]111                #we (NDG) know about this type of URL ...
[1175]112                r=helper.getText(elem,'URL')
[1158]113                b=self.serviceMap.do(s,r)
114                uri=self.__makeuri(s,r,l)
[1171]115                self.url=self.__makeurl(s,b,uri,seqno)
[1150]116            else:
[1182]117                #unknown type
118                self.serviceType='RELATED'
119                self.url=self.serviceMap.do(self.serviceType,helper.getText(elem,'URL'))
[1211]120                uri=url
121            self.uri=uri
[1150]122            return self
123        def __str__(self):
124            ''' return string only html link '''
125            return hyperlink(self.name,self.url)
126        def icon(self):
[1158]127            ''' return html icon linking to specific service '''
[1150]128            return hyperlink(image(self.serviceMap.icon,self.serviceMap.iconalt),self.url)
[1175]129        def __makeuri(self,s,r,l):
[1171]130            ''' Actually create the URI '''
[1175]131            if r=='': return l
[1173]132            if s in ('NDG_B_SERVICE','DISCOVERY'):
[1175]133                uri='%s/%s'%(r,l)
[1158]134            else:
135                uri=l
136            return uri
[1171]137        def __makeurl(self,s,b,uri,seqno):
[1175]138            ''' Actually create the URL, which may be sequentially
139            numbered if it's going to the data extractor (and so
140            iType read from config file will have a %s in it ) '''
[1171]141            iType=self.serviceMap.get(s,'instance','uri')
142            if '%s' in iType: iType=iType%seqno
143            return '%s?%s=%s'%(b,iType,uri)
[1175]144        def __getsrlb(self,entryID):
145            '''Take an entry ID, and parse it for NDG identifiers otherwise
146            and if not, do something sensible '''
147            try:
148                r,s,l=entryID.split(':')
149                if s in self.mapping: s=self.mapping[s].upper()
150                b=self.serviceMap.do(s,r)
151            except:
152                #not from NDG ... provide only discovery binding
153                s,r,l='DISCOVERY','',entryID
154                b=self.serviceMap.get(s,'default')
[1182]155                self.serviceMap.seticon(s)
[1175]156            return s,r,l,b
[1158]157           
[911]158if __name__=="__main__":
159        import ElementTree as ET
160        s='''<dataModelID>
161                <schemeIdentifier>NDG-A0</schemeIdentifier>
162                <repositoryIdentifier>badc.nerc.ac.uk</repositoryIdentifier>
163                <localIdentifier>acsoe_badc_eae96_macehead_mcf_1</localIdentifier>
164            </dataModelID>'''
[1150]165        idelem=ET.fromstring(s)
[1175]166        entryID=idconvert(idelem)
167        n=ServiceBinding('macehead',entryID=entryID,serviceFile='serviceMap.config')
[1150]168        maceheadServices=[n]
169        s='''<dummy><Related_URL>
170        <URL_Content_Type>NDG_B_Service</URL_Content_Type>
171        <URL>badc.nerc.ac.uk</URL>
172        </Related_URL>
173        <Related_URL>
174        <URL>http://badc.nerc.ac.uk/browse/badc/CDs/spade9293</URL>
175        </Related_URL>
176        <Related_URL>
177        <URL_Content_Type>NDG_A_Service</URL_Content_Type>
178        <URL>glue.badc.rl.ac.uk/somelongpath</URL>
179        <Description> dummy dx example </Description>
180        </Related_URL></dummy>
181        '''
182        stuff=ET.fromstring(s)
183        for x in stuff.findall('Related_URL'):
[1151]184            n=ServiceBinding('macehead',serviceFile='serviceMap.config')
[1175]185            maceheadServices.append(n.fromRelated(x,idelem))
[1150]186        for i in maceheadServices: 
187            print str(i)
188            print i.icon()
Note: See TracBrowser for help on using the repository browser.