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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2010 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.common.storage.jpa;
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;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
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
57 public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
59 private final Logger logger = LoggerFactory.getLogger(JpaRelationshipStorageClient.class);
61 public JpaRelationshipStorageClient() {
65 * create of a relationship creates one or more relationships between
67 * the object and subjects of the relationship is chosen (by doc handler) from
72 * @throws BadRequestException
73 * @throws DocumentException
76 public String create(ServiceContext ctx,
77 DocumentHandler handler) throws BadRequestException,
81 throw new IllegalArgumentException(
82 "create : ctx is missing");
84 if (handler == null) {
85 throw new IllegalArgumentException(
86 "create: handler is missing");
88 EntityManagerFactory emf = null;
89 EntityManager em = null;
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();
100 JaxbUtils.setValue(r, "setCreatedAtItem", Date.class, new Date());
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();
111 } catch (Exception e) {
112 if (em != null && em.getTransaction().isActive()) {
113 em.getTransaction().rollback();
115 if (logger.isDebugEnabled()) {
116 logger.debug("Caught exception ", e);
118 throw new DocumentException(e);
121 JpaStorageUtils.releaseEntityManagerFactory(emf);
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
130 * @param id of the object in the relationship
132 * @throws DocumentNotFoundException
133 * @throws DocumentException
136 public void get(ServiceContext ctx, String id, DocumentHandler handler)
137 throws DocumentNotFoundException, DocumentException {
139 throw new IllegalArgumentException(
140 "get: ctx is missing");
142 if (handler == null) {
143 throw new IllegalArgumentException(
144 "get: handler is missing");
146 if (getObject(ctx, id) == null) {
148 + "could not find the object entity with id=" + id;
150 throw new DocumentNotFoundException(msg);
152 DocumentFilter docFilter = handler.getDocumentFilter();
153 if (docFilter == null) {
154 docFilter = handler.createDocumentFilter();
156 EntityManagerFactory emf = null;
157 EntityManager em = null;
159 handler.prepare(Action.GET);
160 StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
161 queryStrBldr.append(getEntityName(ctx));
162 queryStrBldr.append(" a");
163 String objectId = getObjectId(ctx);
164 if (logger.isDebugEnabled()) {
165 logger.debug("get: using objectId=" + objectId);
167 queryStrBldr.append(" WHERE " + objectId + " = :objectId");
168 String where = docFilter.getWhereClause();
169 if ((null != where) && (where.length() > 0)) {
170 queryStrBldr.append(" AND " + where);
172 emf = JpaStorageUtils.getEntityManagerFactory();
173 em = emf.createEntityManager();
174 String queryStr = queryStrBldr.toString(); //for debugging
175 if (logger.isDebugEnabled()) {
176 logger.debug("get: jql=" + queryStr.toString());
178 Query q = em.createQuery(queryStr);
179 q.setParameter("objectId", id);
181 List<T> rl = new ArrayList<T>();
183 //require transaction for get?
184 em.getTransaction().begin();
185 rl = q.getResultList();
186 em.getTransaction().commit();
187 } catch (NoResultException nre) {
188 if (em != null && em.getTransaction().isActive()) {
189 em.getTransaction().rollback();
192 + " could not find entity with id=" + id;
193 logger.error(msg, nre);
194 throw new DocumentNotFoundException(msg, nre);
196 if (rl.size() == 0) {
198 + " could not find entity with id=" + id;
200 throw new DocumentNotFoundException(msg);
202 DocumentWrapper<List<T>> wrapDoc =
203 new DocumentWrapperImpl<List<T>>(rl);
204 handler.handle(Action.GET, wrapDoc);
205 handler.complete(Action.GET, wrapDoc);
206 } catch (DocumentException de) {
208 } catch (Exception e) {
209 if (logger.isDebugEnabled()) {
210 logger.debug("Caught exception ", e);
212 throw new DocumentException(e);
215 JpaStorageUtils.releaseEntityManagerFactory(emf);
221 * delete removes all the relationships for the object in the relationship
222 * identified by the id. the object could be a permission or a role
224 * @param id of the object in the relationship
225 * @throws DocumentNotFoundException
226 * @throws DocumentException
229 public void delete(ServiceContext ctx, String id)
230 throws DocumentNotFoundException,
234 throw new IllegalArgumentException(
235 "delete : ctx is missing");
237 if (getObject(ctx, id) == null) {
238 String msg = "delete : "
239 + "could not find the object entity with id=" + id;
241 throw new DocumentNotFoundException(msg);
243 EntityManagerFactory emf = null;
244 EntityManager em = null;
246 StringBuilder deleteStr = new StringBuilder("DELETE FROM ");
247 String entityName = getEntityName(ctx);
248 deleteStr.append(entityName);
249 String objectId = getObjectId(ctx);
250 if (logger.isDebugEnabled()) {
251 logger.debug("delete: using objectId=" + objectId);
253 deleteStr.append(" WHERE " + objectId + " = :objectId");
254 emf = JpaStorageUtils.getEntityManagerFactory();
255 em = emf.createEntityManager();
256 if (logger.isDebugEnabled()) {
257 logger.debug("delete: jql=" + deleteStr.toString());
259 Query q = em.createQuery(deleteStr.toString());
260 q.setParameter("objectId", id);
262 em.getTransaction().begin();
263 rcount = q.executeUpdate();
264 if (logger.isDebugEnabled()) {
265 logger.debug("deleted " + rcount + " relationships for entity " + entityName
266 + " with objectId=" + objectId);
268 em.getTransaction().commit();
270 } catch (Exception e) {
271 if (logger.isDebugEnabled()) {
272 logger.debug("Caught exception ", e);
274 if (em != null && em.getTransaction().isActive()) {
275 em.getTransaction().rollback();
277 throw new DocumentException(e);
280 JpaStorageUtils.releaseEntityManagerFactory(emf);
286 * getObjectId returns the id of the object in a relationship
290 protected String getObjectId(ServiceContext ctx) {
291 String objectId = (String) ctx.getProperty(ServiceContextProperties.OBJECT_ID);
292 if (objectId == null) {
293 String msg = ServiceContextProperties.OBJECT_ID +
294 " property is missing in the context";
296 throw new IllegalArgumentException(msg);
303 * getObject returns the object in the relationship
308 protected Object getObject(ServiceContext ctx, String id) {
309 Class objectClass = (Class) ctx.getProperty(ServiceContextProperties.OBJECT_CLASS);
310 if (objectClass == null) {
311 String msg = ServiceContextProperties.OBJECT_CLASS +
312 " property is missing in the context";
314 throw new IllegalArgumentException(msg);
316 return JpaStorageUtils.getEntity(id, objectClass);