]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
8787ab6b147f6352040b1d730a5792026b588870
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2010 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.common.storage.jpa;
25
26 import org.collectionspace.services.common.context.ServiceContextProperties;
27 import java.util.ArrayList;
28 import java.util.Date;
29 import java.util.List;
30 import java.util.UUID;
31 import javax.persistence.EntityManager;
32 import javax.persistence.EntityManagerFactory;
33 import javax.persistence.NoResultException;
34 import javax.persistence.Query;
35 import org.collectionspace.services.common.context.ServiceContext;
36 import org.collectionspace.services.common.document.BadRequestException;
37 import org.collectionspace.services.common.document.DocumentException;
38 import org.collectionspace.services.common.document.DocumentFilter;
39 import org.collectionspace.services.common.document.DocumentHandler;
40 import org.collectionspace.services.common.document.DocumentHandler.Action;
41 import org.collectionspace.services.common.document.DocumentNotFoundException;
42 import org.collectionspace.services.common.document.DocumentWrapper;
43 import org.collectionspace.services.common.document.DocumentWrapperImpl;
44 import org.collectionspace.services.common.document.JaxbUtils;
45
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 /**
50  * JpaRelationshipStorageClient deals with a relationship
51  * in persistent storage. This storage client deals with bulk operations, i.e.
52  * create/post inserts multiple tuples between the given object and subjects
53  * get retrieves all subjects for the given object in relationship
54  * delete deletes all subjects for the given object in relationship
55  * @author 
56  */
57 public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
58
59     private final Logger logger = LoggerFactory.getLogger(JpaRelationshipStorageClient.class);
60
61     public JpaRelationshipStorageClient() {
62     }
63
64     /**
65      * create of a relationship creates one or more relationships between
66      * permission and role
67      * the object and subjects of the relationship is chosen (by doc handler) from
68      * the payload
69      * @param ctx
70      * @param handler
71      * @return
72      * @throws BadRequestException
73      * @throws DocumentException
74      */
75     @Override
76     public String create(ServiceContext ctx,
77             DocumentHandler handler) throws BadRequestException,
78             DocumentException {
79
80         if (ctx == null) {
81             throw new IllegalArgumentException(
82                     "create : ctx is missing");
83         }
84         if (handler == null) {
85             throw new IllegalArgumentException(
86                     "create: handler is missing");
87         }
88         EntityManagerFactory emf = null;
89         EntityManager em = null;
90         try {
91             handler.prepare(Action.CREATE);
92             List<T> rl = new ArrayList<T>();
93             DocumentWrapper<List<T>> wrapDoc =
94                     new DocumentWrapperImpl<List<T>>(rl);
95             handler.handle(Action.CREATE, wrapDoc);
96             emf = JpaStorageUtils.getEntityManagerFactory();
97             em = emf.createEntityManager();
98             em.getTransaction().begin();
99             for (T r : rl) {
100                 JaxbUtils.setValue(r, "setCreatedAtItem", Date.class, new Date());
101                 em.persist(r);
102             }
103             em.getTransaction().commit();
104             handler.complete(Action.CREATE, wrapDoc);
105             return UUID.randomUUID().toString(); //filler, not useful
106         } catch (BadRequestException bre) {
107             if (em != null && em.getTransaction().isActive()) {
108                 em.getTransaction().rollback();
109             }
110             throw bre;
111         } catch (Exception e) {
112             if (em != null && em.getTransaction().isActive()) {
113                 em.getTransaction().rollback();
114             }
115             if (logger.isDebugEnabled()) {
116                 logger.debug("Caught exception ", e);
117             }
118             throw new DocumentException(e);
119         } finally {
120             if (em != null) {
121                 JpaStorageUtils.releaseEntityManagerFactory(emf);
122             }
123         }
124     }
125
126     /**
127      * get retrieves all relationships for the object in the relationship
128      * identified by the id. the object could be a permission or a role
129      * @param ctx
130      * @param id of the object in the relationship
131      * @param handler
132      * @throws DocumentNotFoundException
133      * @throws DocumentException
134      */
135     @Override
136     public void get(ServiceContext ctx, String id, DocumentHandler handler)
137             throws DocumentNotFoundException, DocumentException {
138         if (ctx == null) {
139             throw new IllegalArgumentException(
140                     "get: ctx is missing");
141         }
142         if (handler == null) {
143             throw new IllegalArgumentException(
144                     "get: handler is missing");
145         }
146         if (getObject(ctx, id) == null) {
147             String msg = "get: "
148                     + "could not find the object with id=" + id;
149             logger.error(msg);
150             throw new DocumentNotFoundException(msg);
151         }
152         String objectId = getObjectId(ctx);
153         if (logger.isDebugEnabled()) {
154             logger.debug("get: using objectId=" + objectId);
155         }
156         Class objectClass = getObjectClass(ctx);
157         if (logger.isDebugEnabled()) {
158             logger.debug("get: using object class=" + objectClass.getName());
159         }
160         DocumentFilter docFilter = handler.getDocumentFilter();
161         if (docFilter == null) {
162             docFilter = handler.createDocumentFilter();
163         }
164         EntityManagerFactory emf = null;
165         EntityManager em = null;
166         try {
167             handler.prepare(Action.GET);
168             StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
169             queryStrBldr.append(getEntityName(ctx));
170             queryStrBldr.append(" a");
171
172             queryStrBldr.append(" WHERE " + objectId + " = :objectId");
173             String where = docFilter.getWhereClause();
174             if ((null != where) && (where.length() > 0)) {
175                 queryStrBldr.append(" AND " + where);
176             }
177             emf = JpaStorageUtils.getEntityManagerFactory();
178             em = emf.createEntityManager();
179             String queryStr = queryStrBldr.toString(); //for debugging
180             if (logger.isDebugEnabled()) {
181                 logger.debug("get: jql=" + queryStr.toString());
182             }
183             Query q = em.createQuery(queryStr);
184             q.setParameter("objectId", id);
185
186             List<T> rl = new ArrayList<T>();
187             try {
188                 //require transaction for get?
189                 em.getTransaction().begin();
190                 rl = q.getResultList();
191                 em.getTransaction().commit();
192             } catch (NoResultException nre) {
193                 if (em != null && em.getTransaction().isActive()) {
194                     em.getTransaction().rollback();
195                 }
196                 String msg = "get(1): "
197                         + " could not find relationships for object class="
198                         + objectClass.getName() + " id=" + id;
199                 if (logger.isDebugEnabled()) {
200                     logger.debug(msg, nre);
201                 }
202             }
203             if (rl.size() == 0) {
204                 String msg = "get(2): "
205                         + " could not find relationships for object class="
206                         + objectClass.getName() + " id=" + id;
207                 if (logger.isDebugEnabled()) {
208                     logger.debug(msg);
209                 }
210             }
211             DocumentWrapper<List<T>> wrapDoc =
212                     new DocumentWrapperImpl<List<T>>(rl);
213             handler.handle(Action.GET, wrapDoc);
214             handler.complete(Action.GET, wrapDoc);
215         } catch (DocumentException de) {
216             throw de;
217         } catch (Exception e) {
218             if (logger.isDebugEnabled()) {
219                 logger.debug("Caught exception ", e);
220             }
221             throw new DocumentException(e);
222         } finally {
223             if (emf != null) {
224                 JpaStorageUtils.releaseEntityManagerFactory(emf);
225             }
226         }
227     }
228
229     /**
230      * delete removes all the relationships for the object in the relationship
231      * identified by the id. the object could be a permission or a role
232      * @param ctx
233      * @param id of the object in the relationship
234      * @throws DocumentNotFoundException
235      * @throws DocumentException
236      */
237     @Override
238     public void delete(ServiceContext ctx, String id)
239             throws DocumentNotFoundException,
240             DocumentException {
241
242         if (ctx == null) {
243             throw new IllegalArgumentException(
244                     "delete : ctx is missing");
245         }
246         if (getObject(ctx, id) == null) {
247             String msg = "delete : "
248                     + "could not find the object with id=" + id;
249             logger.error(msg);
250             throw new DocumentNotFoundException(msg);
251         }
252         String objectId = getObjectId(ctx);
253         if (logger.isDebugEnabled()) {
254             logger.debug("delete: using objectId=" + objectId);
255         }
256         Class objectClass = getObjectClass(ctx);
257         if (logger.isDebugEnabled()) {
258             logger.debug("delete: using object class=" + objectClass.getName());
259         }
260         EntityManagerFactory emf = null;
261         EntityManager em = null;
262         try {
263             StringBuilder deleteStr = new StringBuilder("DELETE FROM ");
264             String entityName = getEntityName(ctx);
265             deleteStr.append(entityName);
266             deleteStr.append(" WHERE " + objectId + " = :objectId");
267             emf = JpaStorageUtils.getEntityManagerFactory();
268             em = emf.createEntityManager();
269             if (logger.isDebugEnabled()) {
270                 logger.debug("delete: jql=" + deleteStr.toString());
271             }
272             Query q = em.createQuery(deleteStr.toString());
273             q.setParameter("objectId", id);
274             int rcount = 0;
275             em.getTransaction().begin();
276             rcount = q.executeUpdate();
277             if (logger.isDebugEnabled()) {
278                 logger.debug("deleted " + rcount + " relationships for entity " + entityName
279                         + " with objectId=" + objectId);
280             }
281             em.getTransaction().commit();
282
283         } catch (Exception e) {
284             if (logger.isDebugEnabled()) {
285                 logger.debug("Caught exception ", e);
286             }
287             if (em != null && em.getTransaction().isActive()) {
288                 em.getTransaction().rollback();
289             }
290             throw new DocumentException(e);
291         } finally {
292             if (emf != null) {
293                 JpaStorageUtils.releaseEntityManagerFactory(emf);
294             }
295         }
296     }
297
298     /**
299      * getObjectId returns the id of the object in a relationship
300      * @param ctx
301      * @return
302      */
303     protected String getObjectId(ServiceContext ctx) {
304         String objectId = (String) ctx.getProperty(ServiceContextProperties.OBJECT_ID);
305         if (objectId == null) {
306             String msg = ServiceContextProperties.OBJECT_ID
307                     + " property is missing in the context";
308             logger.error(msg);
309             throw new IllegalArgumentException(msg);
310         }
311
312         return objectId;
313     }
314
315     /**
316      * getObjectClass returns the class of the object in a relationship
317      * @param ctx
318      * @return
319      */
320     protected Class getObjectClass(ServiceContext ctx) {
321         Class objectClass = (Class) ctx.getProperty(ServiceContextProperties.OBJECT_CLASS);
322         if (objectClass == null) {
323             String msg = ServiceContextProperties.OBJECT_CLASS
324                     + " property is missing in the context";
325             logger.error(msg);
326             throw new IllegalArgumentException(msg);
327         }
328         return objectClass;
329     }
330
331     /**
332      * getObject returns the object in the relationship
333      * @param ctx
334      * @param id
335      * @return
336      */
337     protected Object getObject(ServiceContext ctx, String id) {
338         Class objectClass = getObjectClass(ctx);
339         return JpaStorageUtils.getEntity(id, objectClass);
340     }
341 }