source: mauRepo/MolesManager/trunk/src/libs/epb.py @ 8480

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

Fixed a bug in objectEncoding

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 10 Jan 2012
30
31@author: Maurizio Nagni
32'''
33from sqlalchemy.orm import subqueryload
34from sqlalchemy.sql.expression import text
35from sqlalchemy.orm.util import identity_key
36from MolesManager.djencoder import methodsWithDecorator
37
38class EPB(object):
39
40    @classmethod
41    def buildFilter(cls, key, keyValue):
42        try:
43            return '%s = \'%s\'' % (key, keyValue)
44        except RuntimeError as er:
45            print er
46
47    @classmethod
48    def search(cls, clazz, inst_key, session):
49        """
50            Searches a required instance by id
51            @param clazz: the class type to search for
52            @param inst_key: the instance id for which the search is done. If None return a query object
53            @param session: a session to use for the query
54            @return the required instance
55        """
56        if inst_key:
57            res = session.query(clazz).get(inst_key)
58        else:
59            res = session.query(clazz)
60           
61        if res is None:
62            return None
63        return res           
64       
65
66
67    @classmethod
68    def searchEager(cls, clazz, inst_id, session):
69        """
70            Searches a required instance by id loading eagerly ALL its field. Please use carefully because \
71            it could impact the performance
72            @param clazz: the class type to search for
73            @param inst_id: the instance id for which the search is done
74            @param session: a session to use for the query   
75            @return the required instance                   
76        """
77        res = session.query(clazz).options(subqueryload('*')).get(inst_id)
78        if res is None:
79            return None
80           
81        return res
82
83    @classmethod
84    def searchSelectiveLoad(cls, clazz, inst_id, attrs, session):
85        """
86            Searches a required instance by id loading \
87            the specified fields. The parameter "attrs" is a single string or a list of attributes
88            owned by the instance of "clazz". Furthermore such list may contain
89            also the children of the main attributes. For example "attrs" may look
90            like
91            ['resultAccumulation', 'identifier.authority', 'resultTime.position.dateTime8601.month', \
92                      'relatedParty.party', 'result.source.function', 'permission', \
93                      'geographicExtent', 'phenomenonTime', 'keywords', 'description', \
94                      'inSupportOf.abstract', 'dataLineage']
95            the first parameter refers to the main class so is equivalent to
96            clazz.resultAccumulation
97            the second parameter is equivalent to invoke
98            clazz.identifier.authority
99            As single string "attrs" could be as well just 'identifier.authority'
100            @param clazz: the class type to search for
101            @param inst_id: the instance id for which the search is done
102            @param attrs: a single string or a list of attributes to load
103            @param session: a session to use for the query
104            @return the required instance             
105        """         
106        if session is None:
107            raise Exception("Session is None!")       
108        res = EPB.search(clazz, inst_id, session)
109        if res is None:
110            return None
111        EPB._drillData(res, attrs)
112        return res
113
114    @classmethod
115    def loadAttributes(cls, instance, attributes, session):
116        """
117            Loads the given instance with the required attributes.
118            The parameter "attributes" is a single string or a list of attributes
119            owned by the instance of "clazz". Furthermore such list may contain
120            also the children of the main attributes. For example "attrs" may look
121            like
122            ['resultAccumulation', 'identifier.authority', 'resultTime.position.dateTime8601.month', \
123                      'relatedParty.party', 'result.source.function', 'permission', \
124                      'geographicExtent', 'phenomenonTime.*', 'keywords', 'description', \
125                      'inSupportOf.abstract', 'dataLineage']
126            the first parameter refers to the main class so is equivalent to
127            instance.resultAccumulation
128            the second parameter is equivalent to invoke
129            instance.identifier.authority
130            As single string "attributes" could be as well just 'identifier.authority'
131            An universal marker '*' can be used to request a full loading from the attribute downward
132            It does not return anything because it does not close the session
133            @param instance: an instance containing the appropriate id
134            @param attributes: a single string or a list of attributes to load
135            @param session: the session to use for the operation                             
136        """
137        if instance is None:
138            raise Exception("Instance is None!")
139        if session is None:
140            raise Exception("Session is None!")
141        session.merge(instance)
142        EPB._drillData(instance, attributes)                   
143
144
145    @classmethod   
146    def searchOrCreate(cls, clazz, session, clazz_id = None):
147        if clazz_id is not None:
148            return EPB.search(clazz, clazz_id, session)
149        else:                       
150            return clazz()
151       
152
153    @classmethod
154    def getAllObjects(cls, clazz, session):     
155        res = session.query(clazz)
156        if res is None:
157            return None
158        return res
159
160    @classmethod
161    def persistInstance(cls, instance, session):
162        """
163            Adds a new migration object.
164            @param migrationObj: the migration object to add
165            @param session: an sqlalchemy Session object. If None (default) the method creates
166            @return an updated, session independant, object instance reflecting the new persisted object
167        """       
168        session.add(instance)
169        session.commit()
170        id_key = identity_key(instance=instance)
171        instance = EPB.search(id_key[0], id_key[1], session)
172        #instance = ret
173
174    @classmethod
175    def executeNative(self, sqlNative, session):
176        return session.execute(text(sqlNative))     
177
178    @classmethod
179    def _getSession(cls, dbManager, session = None):
180        if session:
181            return session       
182        return dbManager.createDbSession()
183
184    @classmethod
185    def _drillData(cls, obj, attrs):
186        """
187            @param obj: its an instance already living inside an SQLAlchemy session
188            @param attrs: a list of attributes owned by the obj parameter. It accepts dot separated attributes as childern of obj attributes.
189        """
190        #if is a single field wrap it in a list and recalls itself
191        if not isinstance(attrs, list):
192            EPB._drillData(obj, [attrs])
193        for item in attrs:
194            attr = item.split('.')[0] 
195            if attr == '*':
196                EPB._drillALLData(obj)         
197            elif isinstance(obj, list):
198                for element in obj:
199                    EPB._drillData(element, [item])
200            else:
201                if hasattr(obj, attr):
202                    nobj = getattr(obj, attr) 
203                    if len(attr) != len(item):
204                        EPB._drillData(nobj, [item[len(attr) + 1:]])
205
206    @classmethod
207    def _drillALLData(cls, obj):
208        if obj is None or isPrimitive(obj):
209            return
210       
211        if isinstance(obj, list):
212            for element in obj:
213                EPB._drillALLData(element)
214        else:
215            keys = dir(obj)
216            keys.extend(list(methodsWithDecorator(type(obj), "property")))
217            for key in keys:
218                try:
219                    if '_' not in key:
220                        nobj = getattr(obj, key)
221                        EPB._drillALLData(nobj)
222                except Exception as e:
223                    pass
224       
225def isPrimitive(obj):
226    # Is a simple primitive?
227    return obj is None \
228            or isinstance(obj, str) \
229            or isinstance(obj, int) \
230            or isinstance(obj, unicode)
Note: See TracBrowser for help on using the repository browser.