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.IQueryManager;
50 import org.collectionspace.services.client.PoxPayloadIn;
51 import org.collectionspace.services.client.PoxPayloadOut;
52 //import org.collectionspace.services.common.imaging.nuxeo.NuxeoImageUtils; //FIXME: REM - Please remove all unneeded imports
53 import org.collectionspace.services.common.AbstractMultiPartCollectionSpaceResourceImpl;
54 import org.collectionspace.services.common.authorityref.AuthorityRefList;
55 //import org.collectionspace.services.common.context.MultipartServiceContext;
56 import org.collectionspace.services.common.context.MultipartServiceContextImpl;
57 import org.collectionspace.services.common.context.ServiceBindingUtils;
58 import org.collectionspace.services.common.context.ServiceContext;
59 import org.collectionspace.services.common.document.BadRequestException;
60 import org.collectionspace.services.common.document.DocumentFilter;
61 import org.collectionspace.services.common.document.DocumentHandler;
62 import org.collectionspace.services.common.document.DocumentNotFoundException;
63 import org.collectionspace.services.common.document.DocumentWrapper;
64 //import org.collectionspace.services.common.query.IQueryManager;
65 import org.collectionspace.services.common.query.QueryManager;
66 import org.collectionspace.services.common.security.UnauthorizedException;
67 import org.collectionspace.services.intake.IntakeResource;
68 import org.collectionspace.services.intake.IntakesCommonList;
69 //import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
70 import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
71 import org.collectionspace.services.relation.RelationResource;
72 import org.collectionspace.services.relation.RelationsCommonList;
73 import org.collectionspace.services.relation.RelationshipType;
74 import org.collectionspace.services.common.profile.Profiler;
76 import org.jboss.resteasy.util.HttpResponseCodes;
78 //FIXME: There should be no direct dependency on Nuxeo in our resource classes.
79 import org.nuxeo.ecm.core.api.DocumentModel;
80 //import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
81 //import org.nuxeo.ecm.core.api.ClientException;
83 import org.slf4j.Logger;
84 import org.slf4j.LoggerFactory;
87 * The Class CollectionObjectResource.
89 @Path(CollectionObjectClient.SERVICE_PATH_COMPONENT)
90 @Consumes("application/xml")
91 @Produces("application/xml")
92 public class CollectionObjectResource
93 extends AbstractMultiPartCollectionSpaceResourceImpl {
96 final Logger logger = LoggerFactory.getLogger(CollectionObjectResource.class);
99 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getVersionString()
102 public String getVersionString() {
103 /** The last change revision. */
104 final String lastChangeRevision = "$LastChangedRevision$";
105 return lastChangeRevision;
109 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getServiceName()
112 public String getServiceName() {
113 return CollectionObjectClient.SERVICE_PATH_COMPONENT;
117 * @see org.collectionspace.services.common.CollectionSpaceResource#getCommonPartClass()
120 public Class<CollectionobjectsCommon> getCommonPartClass() {
121 return CollectionobjectsCommon.class;
125 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#createDocumentHandler(org.collectionspace.services.common.context.ServiceContext)
128 // public DocumentHandler createDocumentHandler(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) throws Exception {
129 // DocumentHandler docHandler = ctx.getDocumentHandler();
130 // if (ctx.getInput() != null) {
131 // Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(),
132 // CollectionobjectsCommon.class);
133 // if (obj != null) {
134 // docHandler.setCommonPart((CollectionobjectsCommon) obj);
137 // return docHandler;
141 * Creates the collection object.
143 * @param input the input
145 * @return the response
148 public Response createCollectionObject(@Context HttpServletRequest req,
151 PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
152 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(input);
153 DocumentHandler handler = createDocumentHandler(ctx);
154 String csid = getRepositoryClient(ctx).create(ctx, handler);
155 UriBuilder path = UriBuilder.fromResource(CollectionObjectResource.class);
156 path.path("" + csid);
157 Response response = Response.created(path.build()).build();
159 } catch (BadRequestException bre) {
160 Response response = Response.status(
161 Response.Status.BAD_REQUEST).entity("Create failed reason " + bre.getErrorReason()).type("text/plain").build();
162 throw new WebApplicationException(response);
163 } catch (UnauthorizedException ue) {
164 Response response = Response.status(
165 Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
166 throw new WebApplicationException(response);
167 } catch (Exception e) {
168 if (logger.isDebugEnabled()) {
169 logger.debug("Caught exception in createCollectionObject", e);
171 Response response = Response.status(
172 Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
173 throw new WebApplicationException(response);
178 * Gets the collection object.
180 * @param csid the csid
182 * @return the collection object
186 public byte[] getCollectionObject(
187 @PathParam("csid") String csid) {
188 if (logger.isDebugEnabled()) {
189 logger.debug("getCollectionObject with csid=" + csid);
191 if (csid == null || "".equals(csid)) {
192 logger.error("getCollectionObject: missing csid!");
193 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
194 "get failed on CollectionObject csid=" + csid).type(
195 "text/plain").build();
196 throw new WebApplicationException(response);
198 PoxPayloadOut result = null;
200 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
201 DocumentHandler handler = createDocumentHandler(ctx);
202 getRepositoryClient(ctx).get(ctx, csid, handler);
203 result = ctx.getOutput();
204 } catch (UnauthorizedException ue) {
205 Response response = Response.status(
206 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
207 throw new WebApplicationException(response);
208 } catch (DocumentNotFoundException dnfe) {
209 if (logger.isDebugEnabled()) {
210 logger.debug("getCollectionObject", dnfe);
212 Response response = Response.status(Response.Status.NOT_FOUND).entity(
213 "Get failed on CollectionObject csid=" + csid).type(
214 "text/plain").build();
215 throw new WebApplicationException(response);
216 } catch (Exception e) {
217 if (logger.isDebugEnabled()) {
218 logger.debug("getCollectionObject", e);
220 Response response = Response.status(
221 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
222 throw new WebApplicationException(response);
225 if (result == null) {
226 Response response = Response.status(Response.Status.NOT_FOUND).entity(
227 "Get failed, the requested CollectionObject CSID:" + csid + ": was not found.").type(
228 "text/plain").build();
229 throw new WebApplicationException(response);
232 return result.getBytes();
236 * Gets the collection object list.
239 * @param keywords the keywords
241 * @return the collection object list
244 @Produces("application/xml")
245 public CollectionobjectsCommonList getCollectionObjectList(@Context UriInfo ui,
246 @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords) {
247 Profiler profiler = new Profiler("getCollectionObjectList():", 1);
249 CollectionobjectsCommonList result = null;
250 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
251 if (keywords != null) {
252 result = searchCollectionObjects(queryParams, keywords);
254 result = getCollectionObjectList(queryParams);
261 * Gets the collection object list.
263 private CollectionobjectsCommonList getCollectionObjectList(MultivaluedMap<String, String> queryParams) {
264 CollectionobjectsCommonList collectionObjectList;
265 Profiler profiler = new Profiler(this, 1);
269 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
270 DocumentHandler handler = createDocumentHandler(ctx);
271 getRepositoryClient(ctx).getFiltered(ctx, handler);
272 collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
273 } catch (UnauthorizedException ue) {
274 Response response = Response.status(
275 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
276 throw new WebApplicationException(response);
277 } catch (Exception e) {
278 if (logger.isDebugEnabled()) {
279 logger.debug("Caught exception in getCollectionObjectList", e);
281 Response response = Response.status(
282 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
283 throw new WebApplicationException(response);
287 return collectionObjectList;
291 * Update collection object.
293 * @param csid the csid
294 * @param xmlText an XML representation of the data to be used in the update
296 * @return an XML representation of the updated object
300 public String updateCollectionObject(
301 @PathParam("csid") String csid,
303 if (logger.isDebugEnabled()) {
304 logger.debug("updateCollectionObject with csid=" + csid);
306 if (csid == null || "".equals(csid)) {
307 logger.error("updateCollectionObject: missing csid!");
308 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
309 "update failed on CollectionObject csid=" + csid).type(
310 "text/plain").build();
311 throw new WebApplicationException(response);
313 PoxPayloadOut result = null;
315 PoxPayloadIn update = new PoxPayloadIn(xmlText);
316 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(update);
317 DocumentHandler handler = createDocumentHandler(ctx);
318 getRepositoryClient(ctx).update(ctx, csid, handler);
319 result = ctx.getOutput();
320 } catch (BadRequestException bre) {
321 Response response = Response.status(
322 Response.Status.BAD_REQUEST).entity("Update failed reason " + bre.getErrorReason()).type("text/plain").build();
323 throw new WebApplicationException(response);
324 } catch (UnauthorizedException ue) {
325 Response response = Response.status(
326 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
327 throw new WebApplicationException(response);
328 } catch (DocumentNotFoundException dnfe) {
329 if (logger.isDebugEnabled()) {
330 logger.debug("Caught exception in updateCollectionObject", dnfe);
332 Response response = Response.status(Response.Status.NOT_FOUND).entity(
333 "Update failed on CollectionObject csid=" + csid).type(
334 "text/plain").build();
335 throw new WebApplicationException(response);
336 } catch (Exception e) {
337 Response response = Response.status(
338 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
339 throw new WebApplicationException(response);
341 return result.toXML();
345 * Delete collection object.
347 * @param csid the csid
349 * @return the response
353 public Response deleteCollectionObject(@PathParam("csid") String csid) {
355 if (logger.isDebugEnabled()) {
356 logger.debug("deleteCollectionObject with csid=" + csid);
358 if (csid == null || "".equals(csid)) {
359 logger.error("deleteCollectionObject: missing csid!");
360 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
361 "delete failed on CollectionObject csid=" + csid).type(
362 "text/plain").build();
363 throw new WebApplicationException(response);
366 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
367 getRepositoryClient(ctx).delete(ctx, csid);
368 return Response.status(HttpResponseCodes.SC_OK).build();
369 } catch (UnauthorizedException ue) {
370 Response response = Response.status(
371 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
372 throw new WebApplicationException(response);
373 } catch (DocumentNotFoundException dnfe) {
374 if (logger.isDebugEnabled()) {
375 logger.debug("caught exception in deleteCollectionObject", dnfe);
377 Response response = Response.status(Response.Status.NOT_FOUND).entity(
378 "Delete failed on CollectionObject csid=" + csid).type(
379 "text/plain").build();
380 throw new WebApplicationException(response);
381 } catch (Exception e) {
382 Response response = Response.status(
383 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
384 throw new WebApplicationException(response);
389 // FIXME AR: should the method below be deprecated?
392 * Gets the intakes common list.
395 * @param csid the csid
397 * @return the intakes common list
400 @Path("{csid}/intakes")
401 @Produces("application/xml")
402 public IntakesCommonList getIntakesCommonList(@Context UriInfo ui,
403 @PathParam("csid") String csid) {
404 IntakesCommonList result = null;
405 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
409 // Find all the intake-related relation records.
411 String subjectCsid = csid;
412 String predicate = RelationshipType.COLLECTIONOBJECT_INTAKE.value();
413 String objectCsid = null;
414 RelationResource relationResource = new RelationResource();
415 RelationsCommonList relationsCommonList = (RelationsCommonList)relationResource.getRelationList(queryParams,
417 null, /*subjectType*/
420 null /*objectType*/);
423 // Create an array of Intake csid's
425 List<RelationsCommonList.RelationListItem> relationsListItems = relationsCommonList.getRelationListItem();
426 List<String> intakeCsidList = new ArrayList<String>();
427 for (RelationsCommonList.RelationListItem relationsListItem : relationsListItems) {
428 intakeCsidList.add(relationsListItem.getObjectCsid());
432 // Get a response list for the Intake records from the Intake resource
434 IntakeResource intakeResource = new IntakeResource();
435 result = intakeResource.getIntakeList(intakeCsidList);
436 } catch (Exception e) {
437 if (logger.isDebugEnabled()) {
438 logger.debug("Caught exception in getIntakeList", e);
440 Response response = Response.status(
441 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
442 throw new WebApplicationException(response);
449 * Gets the authority refs.
451 * @param csid the csid
454 * @return the authority refs
457 @Path("{csid}/authorityrefs")
458 @Produces("application/xml")
459 public AuthorityRefList getAuthorityRefs(
460 @PathParam("csid") String csid,
461 @Context UriInfo ui) {
462 AuthorityRefList authRefList = null;
464 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
465 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
466 DocumentWrapper<DocumentModel> docWrapper =
467 getRepositoryClient(ctx).getDoc(ctx, csid);
468 DocumentModelHandler<PoxPayloadIn, PoxPayloadOut> docHandler =
469 (DocumentModelHandler<PoxPayloadIn, PoxPayloadOut>)createDocumentHandler(ctx);
470 List<String> authRefFields =
471 ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(
472 ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);
473 authRefList = docHandler.getAuthorityRefs(docWrapper, authRefFields);
474 } catch (UnauthorizedException ue) {
475 Response response = Response.status(
476 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
477 throw new WebApplicationException(response);
478 } catch (Exception e) {
479 if (logger.isDebugEnabled()) {
480 logger.debug("Caught exception in getAuthorityRefs", e);
482 Response response = Response.status(
483 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
484 throw new WebApplicationException(response);
492 * This is an intentionally empty method used for getting a rough time estimate
493 * of the overhead required for a client->server request/response cycle.
494 * @param ms - milliseconds to delay
496 * @return the response
499 @Path("/{ms}/roundtrip")
500 @Produces("application/xml")
501 public Response roundtrip(
502 @PathParam("ms") String ms) {
503 Response result = null;
505 Profiler profiler = new Profiler("roundtrip():", 1);
507 result = Response.status(HttpResponseCodes.SC_OK).build();
514 * This method is deprecated. Use SearchCollectionObjects() method instead.
515 * Keywords search collection objects.
518 * @param keywords the keywords
520 * @return the collectionobjects common list
524 @Produces("application/xml")
526 public CollectionobjectsCommonList keywordsSearchCollectionObjects(@Context UriInfo ui,
527 @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS) String keywords) {
528 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
529 return searchCollectionObjects(queryParams, keywords);
533 * Search collection objects.
535 * @param keywords the keywords
537 * @return the collectionobjects common list
539 private CollectionobjectsCommonList searchCollectionObjects(
540 MultivaluedMap<String, String> queryParams,
542 CollectionobjectsCommonList collectionObjectList;
544 Profiler profiler = new Profiler("searchCollectionObjects():", 1);
546 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
547 DocumentHandler handler = createDocumentHandler(ctx);
549 // perform a keyword search
550 if (keywords != null && !keywords.isEmpty()) {
551 String whereClause = QueryManager.createWhereClauseFromKeywords(keywords);
552 DocumentFilter documentFilter = handler.getDocumentFilter();
553 documentFilter.setWhereClause(whereClause);
554 if (logger.isDebugEnabled()) {
555 logger.debug("The WHERE clause is: " + documentFilter.getWhereClause());
559 getRepositoryClient(ctx).getFiltered(ctx, handler);
560 collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
561 } catch (UnauthorizedException ue) {
562 Response response = Response.status(
563 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
564 throw new WebApplicationException(response);
565 } catch (Exception e) {
566 if (logger.isDebugEnabled()) {
567 logger.debug("Caught exception in getCollectionObjectList", e);
569 Response response = Response.status(
570 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
571 throw new WebApplicationException(response);
573 return collectionObjectList;