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 java.util.ArrayList;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.UUID;
30 import javax.persistence.EntityManager;
31 import javax.persistence.EntityManagerFactory;
32 import javax.persistence.NoResultException;
33 import javax.persistence.Query;
34 import org.collectionspace.services.common.context.ServiceContext;
35 import org.collectionspace.services.common.document.BadRequestException;
36 import org.collectionspace.services.common.document.DocumentException;
37 import org.collectionspace.services.common.document.DocumentFilter;
38 import org.collectionspace.services.common.document.DocumentHandler;
39 import org.collectionspace.services.common.document.DocumentHandler.Action;
40 import org.collectionspace.services.common.document.DocumentNotFoundException;
41 import org.collectionspace.services.common.document.DocumentWrapper;
42 import org.collectionspace.services.common.document.DocumentWrapperImpl;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * JpaRelationshipStorageClient deals with a relationship
49 * in persistent storage. This storage client deals with bulk operations, i.e.
50 * create/post inserts multiple tuples between the given object and subjects
51 * get retrieves all subjects for the given object in relationship
52 * delete deletes all subjects for the given object in relationship
55 public class JpaRelationshipStorageClient<T> extends JpaStorageClientImpl {
57 private final Logger logger = LoggerFactory.getLogger(JpaRelationshipStorageClient.class);
59 public JpaRelationshipStorageClient() {
63 * create of a relationship creates one or more relationships between
65 * the object and subjects of the relationship is chosen (by doc handler) from
70 * @throws BadRequestException
71 * @throws DocumentException
74 public String create(ServiceContext ctx,
75 DocumentHandler handler) throws BadRequestException,
79 throw new IllegalArgumentException(
80 "JpaRelationshipStorageClient.create : ctx is missing");
82 if (handler == null) {
83 throw new IllegalArgumentException(
84 "JpaRelationshipStorageClient.create: handler is missing");
86 EntityManagerFactory emf = null;
87 EntityManager em = null;
89 handler.prepare(Action.CREATE);
90 List<T> rl = new ArrayList<T>();
91 DocumentWrapper<List<T>> wrapDoc =
92 new DocumentWrapperImpl<List<T>>(rl);
93 handler.handle(Action.CREATE, wrapDoc);
94 emf = JpaStorageUtils.getEntityManagerFactory();
95 em = emf.createEntityManager();
96 em.getTransaction().begin();
98 setValue(r, "setCreatedAtItem", Date.class, new Date());
101 em.getTransaction().commit();
102 handler.complete(Action.CREATE, wrapDoc);
103 return UUID.randomUUID().toString(); //filler, not useful
104 } catch (BadRequestException bre) {
105 if (em != null && em.getTransaction().isActive()) {
106 em.getTransaction().rollback();
109 } catch (Exception e) {
110 if (em != null && em.getTransaction().isActive()) {
111 em.getTransaction().rollback();
113 if (logger.isDebugEnabled()) {
114 logger.debug("Caught exception ", e);
116 throw new DocumentException(e);
119 JpaStorageUtils.releaseEntityManagerFactory(emf);
125 * get retrieves all relationships for the object in the relationship
126 * identified by the id. the object could be a permission or a role
128 * @param id of the object in the relationship
130 * @throws DocumentNotFoundException
131 * @throws DocumentException
134 public void get(ServiceContext ctx, String id, DocumentHandler handler)
135 throws DocumentNotFoundException, DocumentException {
137 throw new IllegalArgumentException(
138 "JpaRelationshipStorageClient.get: ctx is missing");
140 if (handler == null) {
141 throw new IllegalArgumentException(
142 "JpaRelationshipStorageClient.get: handler is missing");
144 if (getObject(ctx, id) == null) {
145 String msg = "JpaRelationshipStorageClient.get: "
146 + "could not find the object entity with id=" + id;
148 throw new DocumentNotFoundException(msg);
150 DocumentFilter docFilter = handler.getDocumentFilter();
151 if (docFilter == null) {
152 docFilter = handler.createDocumentFilter();
154 EntityManagerFactory emf = null;
155 EntityManager em = null;
157 handler.prepare(Action.GET);
158 StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM ");
159 queryStrBldr.append(getEntityName(ctx));
160 queryStrBldr.append(" a");
161 String objectId = getObjectId(ctx);
162 if (logger.isDebugEnabled()) {
163 logger.debug("get: using objectId=" + objectId);
165 queryStrBldr.append(" WHERE " + objectId + " = :objectId");
166 String where = docFilter.getWhereClause();
167 if ((null != where) && (where.length() > 0)) {
168 queryStrBldr.append(" AND " + where);
170 emf = JpaStorageUtils.getEntityManagerFactory();
171 em = emf.createEntityManager();
172 String queryStr = queryStrBldr.toString(); //for debugging
173 if (logger.isDebugEnabled()) {
174 logger.debug("get: jql=" + queryStr.toString());
176 Query q = em.createQuery(queryStr);
177 q.setParameter("objectId", id);
179 List<T> rl = new ArrayList<T>();
181 //require transaction for get?
182 em.getTransaction().begin();
183 rl = q.getResultList();
184 em.getTransaction().commit();
185 } catch (NoResultException nre) {
186 if (em != null && em.getTransaction().isActive()) {
187 em.getTransaction().rollback();
189 String msg = "JpaRelationshipStorageClient.get: "
190 + " could not find entity with id=" + id;
191 logger.error(msg, nre);
192 throw new DocumentNotFoundException(msg, nre);
194 if (rl.size() == 0) {
195 String msg = "JpaRelationshipStorageClient.get: "
196 + " could not find entity with id=" + id;
198 throw new DocumentNotFoundException(msg);
200 DocumentWrapper<List<T>> wrapDoc =
201 new DocumentWrapperImpl<List<T>>(rl);
202 handler.handle(Action.GET, wrapDoc);
203 handler.complete(Action.GET, wrapDoc);
204 } catch (DocumentException de) {
206 } catch (Exception e) {
207 if (logger.isDebugEnabled()) {
208 logger.debug("Caught exception ", e);
210 throw new DocumentException(e);
213 JpaStorageUtils.releaseEntityManagerFactory(emf);
219 * delete removes all the relationships for the object in the relationship
220 * identified by the id. the object could be a permission or a role
222 * @param id of the object in the relationship
223 * @throws DocumentNotFoundException
224 * @throws DocumentException
227 public void delete(ServiceContext ctx, String id)
228 throws DocumentNotFoundException,
232 throw new IllegalArgumentException(
233 "JpaRelationshipStorageClient.delete : ctx is missing");
235 if (getObject(ctx, id) == null) {
236 String msg = "JpaRelationshipStorageClient.delete : "
237 + "could not find the object entity with id=" + id;
239 throw new DocumentNotFoundException(msg);
241 EntityManagerFactory emf = null;
242 EntityManager em = null;
244 StringBuilder deleteStr = new StringBuilder("DELETE FROM ");
245 String entityName = getEntityName(ctx);
246 deleteStr.append(entityName);
247 String objectId = getObjectId(ctx);
248 if (logger.isDebugEnabled()) {
249 logger.debug("delete: using objectId=" + objectId);
251 deleteStr.append(" WHERE " + objectId + " = :objectId");
252 emf = JpaStorageUtils.getEntityManagerFactory();
253 em = emf.createEntityManager();
254 if (logger.isDebugEnabled()) {
255 logger.debug("delete: jql=" + deleteStr.toString());
257 Query q = em.createQuery(deleteStr.toString());
258 q.setParameter("objectId", id);
260 em.getTransaction().begin();
261 rcount = q.executeUpdate();
262 if (logger.isDebugEnabled()) {
263 logger.debug("deleted " + rcount + " relationships for entity " + entityName
264 + " with objectId=" + objectId);
266 em.getTransaction().commit();
268 } catch (Exception e) {
269 if (logger.isDebugEnabled()) {
270 logger.debug("Caught exception ", e);
272 if (em != null && em.getTransaction().isActive()) {
273 em.getTransaction().rollback();
275 throw new DocumentException(e);
278 JpaStorageUtils.releaseEntityManagerFactory(emf);
283 protected String getObjectId(ServiceContext ctx) {
284 String objectId = (String) ctx.getProperty("object-id");
285 if (objectId == null) {
286 String msg = "object-id is missing in the context";
288 throw new IllegalArgumentException(msg);
295 * getObject returns the object in the relationship
300 protected Object getObject(ServiceContext ctx, String id) {
301 Class objectClass = (Class) ctx.getProperty("object-class");
302 if (objectClass == null) {
303 String msg = "object-class is missing in the context";
305 throw new IllegalArgumentException(msg);
307 return JpaStorageUtils.getEntity(id, objectClass);