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 2009 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 * $LastChangedRevision$
26 package org.collectionspace.services.collectionobject;
28 import java.util.ArrayList;
29 import java.util.List;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.POST;
36 import javax.ws.rs.PUT;
37 import javax.ws.rs.Path;
38 import javax.ws.rs.PathParam;
39 import javax.ws.rs.Produces;
40 import javax.ws.rs.QueryParam;
41 import javax.ws.rs.WebApplicationException;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.Response;
44 import javax.ws.rs.core.UriBuilder;
45 import javax.ws.rs.core.UriInfo;
46 import javax.ws.rs.core.MultivaluedMap;
48 import org.collectionspace.services.client.CollectionObjectClient;
49 import org.collectionspace.services.client.PoxPayloadIn;
50 import org.collectionspace.services.client.PoxPayloadOut;
51 //import org.collectionspace.services.common.imaging.nuxeo.NuxeoImageUtils; //FIXME: REM - Please remove all unneeded imports
52 import org.collectionspace.services.common.AbstractMultiPartCollectionSpaceResourceImpl;
53 import org.collectionspace.services.common.authorityref.AuthorityRefList;
54 //import org.collectionspace.services.common.context.MultipartServiceContext;
55 import org.collectionspace.services.common.context.MultipartServiceContextImpl;
56 import org.collectionspace.services.common.context.ServiceBindingUtils;
57 import org.collectionspace.services.common.context.ServiceContext;
58 import org.collectionspace.services.common.document.BadRequestException;
59 import org.collectionspace.services.common.document.DocumentFilter;
60 import org.collectionspace.services.common.document.DocumentHandler;
61 import org.collectionspace.services.common.document.DocumentNotFoundException;
62 import org.collectionspace.services.common.document.DocumentWrapper;
63 import org.collectionspace.services.common.query.IQueryManager;
64 import org.collectionspace.services.common.query.QueryManager;
65 import org.collectionspace.services.common.security.UnauthorizedException;
66 import org.collectionspace.services.intake.IntakeResource;
67 import org.collectionspace.services.intake.IntakesCommonList;
68 //import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
69 import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
70 import org.collectionspace.services.relation.RelationResource;
71 import org.collectionspace.services.relation.RelationsCommonList;
72 import org.collectionspace.services.relation.RelationshipType;
73 import org.collectionspace.services.common.profile.Profiler;
75 import org.jboss.resteasy.util.HttpResponseCodes;
77 //FIXME: There should be no direct dependency on Nuxeo in our resource classes.
78 import org.nuxeo.ecm.core.api.DocumentModel;
79 //import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
80 //import org.nuxeo.ecm.core.api.ClientException;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
86 * The Class CollectionObjectResource.
88 @Path(CollectionObjectClient.SERVICE_PATH_COMPONENT)
89 @Consumes("application/xml")
90 @Produces("application/xml")
91 public class CollectionObjectResource
92 extends AbstractMultiPartCollectionSpaceResourceImpl {
95 final Logger logger = LoggerFactory.getLogger(CollectionObjectResource.class);
98 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getVersionString()
101 public String getVersionString() {
102 /** The last change revision. */
103 final String lastChangeRevision = "$LastChangedRevision$";
104 return lastChangeRevision;
108 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getServiceName()
111 public String getServiceName() {
112 return CollectionObjectClient.SERVICE_PATH_COMPONENT;
116 * @see org.collectionspace.services.common.CollectionSpaceResource#getCommonPartClass()
119 public Class<CollectionobjectsCommon> getCommonPartClass() {
120 return CollectionobjectsCommon.class;
124 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#createDocumentHandler(org.collectionspace.services.common.context.ServiceContext)
127 // public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
128 // DocumentHandler docHandler = ctx.getDocumentHandler();
129 // if (ctx.getInput() != null) {
130 // Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(),
131 // CollectionobjectsCommon.class);
132 // if (obj != null) {
133 // docHandler.setCommonPart((CollectionobjectsCommon) obj);
136 // return docHandler;
140 * Creates the collection object.
142 * @param input the input
144 * @return the response
147 public Response createCollectionObject(@Context HttpServletRequest req,
150 PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
151 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(input);
152 DocumentHandler handler = createDocumentHandler(ctx);
153 String csid = getRepositoryClient(ctx).create(ctx, handler);
154 UriBuilder path = UriBuilder.fromResource(CollectionObjectResource.class);
155 path.path("" + csid);
156 Response response = Response.created(path.build()).build();
158 } catch (BadRequestException bre) {
159 Response response = Response.status(
160 Response.Status.BAD_REQUEST).entity("Create failed reason " + bre.getErrorReason()).type("text/plain").build();
161 throw new WebApplicationException(response);
162 } catch (UnauthorizedException ue) {
163 Response response = Response.status(
164 Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
165 throw new WebApplicationException(response);
166 } catch (Exception e) {
167 if (logger.isDebugEnabled()) {
168 logger.debug("Caught exception in createCollectionObject", e);
170 Response response = Response.status(
171 Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
172 throw new WebApplicationException(response);
177 * Gets the collection object.
179 * @param csid the csid
181 * @return the collection object
185 public byte[] getCollectionObject(
186 @PathParam("csid") String csid) {
187 if (logger.isDebugEnabled()) {
188 logger.debug("getCollectionObject with csid=" + csid);
190 if (csid == null || "".equals(csid)) {
191 logger.error("getCollectionObject: missing csid!");
192 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
193 "get failed on CollectionObject csid=" + csid).type(
194 "text/plain").build();
195 throw new WebApplicationException(response);
197 PoxPayloadOut result = null;
199 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
200 DocumentHandler handler = createDocumentHandler(ctx);
201 getRepositoryClient(ctx).get(ctx, csid, handler);
202 result = ctx.getOutput();
203 } catch (UnauthorizedException ue) {
204 Response response = Response.status(
205 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
206 throw new WebApplicationException(response);
207 } catch (DocumentNotFoundException dnfe) {
208 if (logger.isDebugEnabled()) {
209 logger.debug("getCollectionObject", dnfe);
211 Response response = Response.status(Response.Status.NOT_FOUND).entity(
212 "Get failed on CollectionObject csid=" + csid).type(
213 "text/plain").build();
214 throw new WebApplicationException(response);
215 } catch (Exception e) {
216 if (logger.isDebugEnabled()) {
217 logger.debug("getCollectionObject", e);
219 Response response = Response.status(
220 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
221 throw new WebApplicationException(response);
224 if (result == null) {
225 Response response = Response.status(Response.Status.NOT_FOUND).entity(
226 "Get failed, the requested CollectionObject CSID:" + csid + ": was not found.").type(
227 "text/plain").build();
228 throw new WebApplicationException(response);
231 return result.getBytes();
235 * Gets the collection object list.
238 * @param keywords the keywords
240 * @return the collection object list
243 @Produces("application/xml")
244 public CollectionobjectsCommonList getCollectionObjectList(@Context UriInfo ui,
245 @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords) {
246 Profiler profiler = new Profiler("getCollectionObjectList():", 1);
248 CollectionobjectsCommonList result = null;
249 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
250 if (keywords != null) {
251 result = searchCollectionObjects(queryParams, keywords);
253 result = getCollectionObjectList(queryParams);
260 * Gets the collection object list.
262 private CollectionobjectsCommonList getCollectionObjectList(MultivaluedMap<String, String> queryParams) {
263 CollectionobjectsCommonList collectionObjectList;
264 Profiler profiler = new Profiler(this, 1);
268 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
269 DocumentHandler handler = createDocumentHandler(ctx);
270 getRepositoryClient(ctx).getFiltered(ctx, handler);
271 collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
272 } catch (UnauthorizedException ue) {
273 Response response = Response.status(
274 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
275 throw new WebApplicationException(response);
276 } catch (Exception e) {
277 if (logger.isDebugEnabled()) {
278 logger.debug("Caught exception in getCollectionObjectList", e);
280 Response response = Response.status(
281 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
282 throw new WebApplicationException(response);
286 return collectionObjectList;
290 * Update collection object.
292 * @param csid the csid
293 * @param xmlText an XML representation of the data to be used in the update
295 * @return an XML representation of the updated object
299 public String updateCollectionObject(
300 @PathParam("csid") String csid,
302 if (logger.isDebugEnabled()) {
303 logger.debug("updateCollectionObject with csid=" + csid);
305 if (csid == null || "".equals(csid)) {
306 logger.error("updateCollectionObject: missing csid!");
307 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
308 "update failed on CollectionObject csid=" + csid).type(
309 "text/plain").build();
310 throw new WebApplicationException(response);
312 PoxPayloadOut result = null;
314 PoxPayloadIn update = new PoxPayloadIn(xmlText);
315 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(update);
316 DocumentHandler handler = createDocumentHandler(ctx);
317 getRepositoryClient(ctx).update(ctx, csid, handler);
318 result = ctx.getOutput();
319 } catch (BadRequestException bre) {
320 Response response = Response.status(
321 Response.Status.BAD_REQUEST).entity("Update failed reason " + bre.getErrorReason()).type("text/plain").build();
322 throw new WebApplicationException(response);
323 } catch (UnauthorizedException ue) {
324 Response response = Response.status(
325 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
326 throw new WebApplicationException(response);
327 } catch (DocumentNotFoundException dnfe) {
328 if (logger.isDebugEnabled()) {
329 logger.debug("Caught exception in updateCollectionObject", dnfe);
331 Response response = Response.status(Response.Status.NOT_FOUND).entity(
332 "Update failed on CollectionObject csid=" + csid).type(
333 "text/plain").build();
334 throw new WebApplicationException(response);
335 } catch (Exception e) {
336 Response response = Response.status(
337 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
338 throw new WebApplicationException(response);
340 return result.toXML();
344 * Delete collection object.
346 * @param csid the csid
348 * @return the response
352 public Response deleteCollectionObject(@PathParam("csid") String csid) {
354 if (logger.isDebugEnabled()) {
355 logger.debug("deleteCollectionObject with csid=" + csid);
357 if (csid == null || "".equals(csid)) {
358 logger.error("deleteCollectionObject: missing csid!");
359 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
360 "delete failed on CollectionObject csid=" + csid).type(
361 "text/plain").build();
362 throw new WebApplicationException(response);
365 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
366 getRepositoryClient(ctx).delete(ctx, csid);
367 return Response.status(HttpResponseCodes.SC_OK).build();
368 } catch (UnauthorizedException ue) {
369 Response response = Response.status(
370 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
371 throw new WebApplicationException(response);
372 } catch (DocumentNotFoundException dnfe) {
373 if (logger.isDebugEnabled()) {
374 logger.debug("caught exception in deleteCollectionObject", dnfe);
376 Response response = Response.status(Response.Status.NOT_FOUND).entity(
377 "Delete failed on CollectionObject csid=" + csid).type(
378 "text/plain").build();
379 throw new WebApplicationException(response);
380 } catch (Exception e) {
381 Response response = Response.status(
382 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
383 throw new WebApplicationException(response);
388 // FIXME AR: should the method below be deprecated?
391 * Gets the intakes common list.
394 * @param csid the csid
396 * @return the intakes common list
399 @Path("{csid}/intakes")
400 @Produces("application/xml")
401 public IntakesCommonList getIntakesCommonList(@Context UriInfo ui,
402 @PathParam("csid") String csid) {
403 IntakesCommonList result = null;
404 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
408 // Find all the intake-related relation records.
410 String subjectCsid = csid;
411 String predicate = RelationshipType.COLLECTIONOBJECT_INTAKE.value();
412 String objectCsid = null;
413 RelationResource relationResource = new RelationResource();
414 RelationsCommonList relationsCommonList = relationResource.getRelationList(queryParams,
416 null, /*subjectType*/
419 null /*objectType*/);
422 // Create an array of Intake csid's
424 List<RelationsCommonList.RelationListItem> relationsListItems = relationsCommonList.getRelationListItem();
425 List<String> intakeCsidList = new ArrayList<String>();
426 for (RelationsCommonList.RelationListItem relationsListItem : relationsListItems) {
427 intakeCsidList.add(relationsListItem.getObjectCsid());
431 // Get a response list for the Intake records from the Intake resource
433 IntakeResource intakeResource = new IntakeResource();
434 result = intakeResource.getIntakeList(intakeCsidList);
435 } catch (Exception e) {
436 if (logger.isDebugEnabled()) {
437 logger.debug("Caught exception in getIntakeList", e);
439 Response response = Response.status(
440 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
441 throw new WebApplicationException(response);
448 * Gets the authority refs.
450 * @param csid the csid
453 * @return the authority refs
456 @Path("{csid}/authorityrefs")
457 @Produces("application/xml")
458 public AuthorityRefList getAuthorityRefs(
459 @PathParam("csid") String csid,
460 @Context UriInfo ui) {
461 AuthorityRefList authRefList = null;
463 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
464 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
465 DocumentWrapper<DocumentModel> docWrapper =
466 getRepositoryClient(ctx).getDoc(ctx, csid);
467 DocumentModelHandler<PoxPayloadIn, PoxPayloadOut> docHandler =
468 (DocumentModelHandler<PoxPayloadIn, PoxPayloadOut>)createDocumentHandler(ctx);
469 List<String> authRefFields =
470 ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(
471 ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);
472 authRefList = docHandler.getAuthorityRefs(docWrapper, authRefFields);
473 } catch (UnauthorizedException ue) {
474 Response response = Response.status(
475 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
476 throw new WebApplicationException(response);
477 } catch (Exception e) {
478 if (logger.isDebugEnabled()) {
479 logger.debug("Caught exception in getAuthorityRefs", e);
481 Response response = Response.status(
482 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
483 throw new WebApplicationException(response);
491 * This is an intentionally empty method used for getting a rough time estimate
492 * of the overhead required for a client->server request/response cycle.
493 * @param ms - milliseconds to delay
495 * @return the response
498 @Path("/{ms}/roundtrip")
499 @Produces("application/xml")
500 public Response roundtrip(
501 @PathParam("ms") String ms) {
502 Response result = null;
504 Profiler profiler = new Profiler("roundtrip():", 1);
506 result = Response.status(HttpResponseCodes.SC_OK).build();
513 * This method is deprecated. Use SearchCollectionObjects() method instead.
514 * Keywords search collection objects.
517 * @param keywords the keywords
519 * @return the collectionobjects common list
523 @Produces("application/xml")
525 public CollectionobjectsCommonList keywordsSearchCollectionObjects(@Context UriInfo ui,
526 @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS) String keywords) {
527 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
528 return searchCollectionObjects(queryParams, keywords);
532 * Search collection objects.
534 * @param keywords the keywords
536 * @return the collectionobjects common list
538 private CollectionobjectsCommonList searchCollectionObjects(
539 MultivaluedMap<String, String> queryParams,
541 CollectionobjectsCommonList collectionObjectList;
543 Profiler profiler = new Profiler("searchCollectionObjects():", 1);
545 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
546 DocumentHandler handler = createDocumentHandler(ctx);
548 // perform a keyword search
549 if (keywords != null && !keywords.isEmpty()) {
550 String whereClause = QueryManager.createWhereClauseFromKeywords(keywords);
551 DocumentFilter documentFilter = handler.getDocumentFilter();
552 documentFilter.setWhereClause(whereClause);
553 if (logger.isDebugEnabled()) {
554 logger.debug("The WHERE clause is: " + documentFilter.getWhereClause());
558 getRepositoryClient(ctx).getFiltered(ctx, handler);
559 collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
560 } catch (UnauthorizedException ue) {
561 Response response = Response.status(
562 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
563 throw new WebApplicationException(response);
564 } catch (Exception e) {
565 if (logger.isDebugEnabled()) {
566 logger.debug("Caught exception in getCollectionObjectList", e);
568 Response response = Response.status(
569 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
570 throw new WebApplicationException(response);
572 return collectionObjectList;