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(
188 @PathParam("csid") String csid) {
189 if (logger.isDebugEnabled()) {
190 logger.debug("getCollectionObject with csid=" + csid);
192 if (csid == null || "".equals(csid)) {
193 logger.error("getCollectionObject: missing csid!");
194 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
195 "get failed on CollectionObject csid=" + csid).type(
196 "text/plain").build();
197 throw new WebApplicationException(response);
199 PoxPayloadOut result = null;
201 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
202 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
203 DocumentHandler handler = createDocumentHandler(ctx);
204 getRepositoryClient(ctx).get(ctx, csid, handler);
205 result = ctx.getOutput();
206 } catch (UnauthorizedException ue) {
207 Response response = Response.status(
208 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
209 throw new WebApplicationException(response);
210 } catch (DocumentNotFoundException dnfe) {
211 if (logger.isDebugEnabled()) {
212 logger.debug("getCollectionObject", dnfe);
214 Response response = Response.status(Response.Status.NOT_FOUND).entity(
215 "Get failed on CollectionObject csid=" + csid).type(
216 "text/plain").build();
217 throw new WebApplicationException(response);
218 } catch (Exception e) {
219 if (logger.isDebugEnabled()) {
220 logger.debug("getCollectionObject", e);
222 Response response = Response.status(
223 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
224 throw new WebApplicationException(response);
227 if (result == null) {
228 Response response = Response.status(Response.Status.NOT_FOUND).entity(
229 "Get failed, the requested CollectionObject CSID:" + csid + ": was not found.").type(
230 "text/plain").build();
231 throw new WebApplicationException(response);
234 return result.getBytes();
238 * Gets the collection object list.
241 * @param keywords the keywords
243 * @return the collection object list
246 @Produces("application/xml")
247 public CollectionobjectsCommonList getCollectionObjectList(@Context UriInfo ui,
248 @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS_KW) String keywords) {
249 Profiler profiler = new Profiler("getCollectionObjectList():", 1);
251 CollectionobjectsCommonList result = null;
252 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
253 if (keywords != null) {
254 result = searchCollectionObjects(queryParams, keywords);
256 result = getCollectionObjectList(queryParams);
263 * Gets the collection object list.
265 private CollectionobjectsCommonList getCollectionObjectList(MultivaluedMap<String, String> queryParams) {
266 CollectionobjectsCommonList collectionObjectList;
267 Profiler profiler = new Profiler(this, 1);
271 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
272 DocumentHandler handler = createDocumentHandler(ctx);
273 getRepositoryClient(ctx).getFiltered(ctx, handler);
274 collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
275 } catch (UnauthorizedException ue) {
276 Response response = Response.status(
277 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
278 throw new WebApplicationException(response);
279 } catch (Exception e) {
280 if (logger.isDebugEnabled()) {
281 logger.debug("Caught exception in getCollectionObjectList", e);
283 Response response = Response.status(
284 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
285 throw new WebApplicationException(response);
289 return collectionObjectList;
293 * Update collection object.
295 * @param csid the csid
296 * @param xmlText an XML representation of the data to be used in the update
298 * @return an XML representation of the updated object
302 public String updateCollectionObject(
303 @PathParam("csid") String csid,
305 if (logger.isDebugEnabled()) {
306 logger.debug("updateCollectionObject with csid=" + csid);
308 if (csid == null || "".equals(csid)) {
309 logger.error("updateCollectionObject: missing csid!");
310 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
311 "update failed on CollectionObject csid=" + csid).type(
312 "text/plain").build();
313 throw new WebApplicationException(response);
315 PoxPayloadOut result = null;
317 PoxPayloadIn update = new PoxPayloadIn(xmlText);
318 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(update);
319 DocumentHandler handler = createDocumentHandler(ctx);
320 getRepositoryClient(ctx).update(ctx, csid, handler);
321 result = ctx.getOutput();
322 } catch (BadRequestException bre) {
323 Response response = Response.status(
324 Response.Status.BAD_REQUEST).entity("Update failed reason " + bre.getErrorReason()).type("text/plain").build();
325 throw new WebApplicationException(response);
326 } catch (UnauthorizedException ue) {
327 Response response = Response.status(
328 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
329 throw new WebApplicationException(response);
330 } catch (DocumentNotFoundException dnfe) {
331 if (logger.isDebugEnabled()) {
332 logger.debug("Caught exception in updateCollectionObject", dnfe);
334 Response response = Response.status(Response.Status.NOT_FOUND).entity(
335 "Update failed on CollectionObject csid=" + csid).type(
336 "text/plain").build();
337 throw new WebApplicationException(response);
338 } catch (Exception e) {
339 Response response = Response.status(
340 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
341 throw new WebApplicationException(response);
343 return result.toXML();
347 * Delete collection object.
349 * @param csid the csid
351 * @return the response
355 public Response deleteCollectionObject(@PathParam("csid") String csid) {
357 if (logger.isDebugEnabled()) {
358 logger.debug("deleteCollectionObject with csid=" + csid);
360 if (csid == null || "".equals(csid)) {
361 logger.error("deleteCollectionObject: missing csid!");
362 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
363 "delete failed on CollectionObject csid=" + csid).type(
364 "text/plain").build();
365 throw new WebApplicationException(response);
368 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
369 getRepositoryClient(ctx).delete(ctx, csid);
370 return Response.status(HttpResponseCodes.SC_OK).build();
371 } catch (UnauthorizedException ue) {
372 Response response = Response.status(
373 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
374 throw new WebApplicationException(response);
375 } catch (DocumentNotFoundException dnfe) {
376 if (logger.isDebugEnabled()) {
377 logger.debug("caught exception in deleteCollectionObject", dnfe);
379 Response response = Response.status(Response.Status.NOT_FOUND).entity(
380 "Delete failed on CollectionObject csid=" + csid).type(
381 "text/plain").build();
382 throw new WebApplicationException(response);
383 } catch (Exception e) {
384 Response response = Response.status(
385 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
386 throw new WebApplicationException(response);
391 // FIXME AR: should the method below be deprecated?
394 * Gets the intakes common list.
397 * @param csid the csid
399 * @return the intakes common list
402 @Path("{csid}/intakes")
403 @Produces("application/xml")
404 public IntakesCommonList getIntakesCommonList(@Context UriInfo ui,
405 @PathParam("csid") String csid) {
406 IntakesCommonList result = null;
407 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
411 // Find all the intake-related relation records.
413 String subjectCsid = csid;
414 String predicate = RelationshipType.COLLECTIONOBJECT_INTAKE.value();
415 String objectCsid = null;
416 RelationResource relationResource = new RelationResource();
417 RelationsCommonList relationsCommonList = relationResource.getRelationList(queryParams,
419 null, /*subjectType*/
422 null /*objectType*/);
425 // Create an array of Intake csid's
427 List<RelationsCommonList.RelationListItem> relationsListItems = relationsCommonList.getRelationListItem();
428 List<String> intakeCsidList = new ArrayList<String>();
429 for (RelationsCommonList.RelationListItem relationsListItem : relationsListItems) {
430 intakeCsidList.add(relationsListItem.getObjectCsid());
434 // Get a response list for the Intake records from the Intake resource
436 IntakeResource intakeResource = new IntakeResource();
437 result = intakeResource.getIntakeList(intakeCsidList);
438 } catch (Exception e) {
439 if (logger.isDebugEnabled()) {
440 logger.debug("Caught exception in getIntakeList", e);
442 Response response = Response.status(
443 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
444 throw new WebApplicationException(response);
451 * Gets the authority refs.
453 * @param csid the csid
456 * @return the authority refs
459 @Path("{csid}/authorityrefs")
460 @Produces("application/xml")
461 public AuthorityRefList getAuthorityRefs(
462 @PathParam("csid") String csid,
463 @Context UriInfo ui) {
464 AuthorityRefList authRefList = null;
466 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
467 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
468 DocumentWrapper<DocumentModel> docWrapper =
469 getRepositoryClient(ctx).getDoc(ctx, csid);
470 DocumentModelHandler<PoxPayloadIn, PoxPayloadOut> docHandler =
471 (DocumentModelHandler<PoxPayloadIn, PoxPayloadOut>)createDocumentHandler(ctx);
472 List<String> authRefFields =
473 ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(
474 ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);
475 authRefList = docHandler.getAuthorityRefs(docWrapper, authRefFields);
476 } catch (UnauthorizedException ue) {
477 Response response = Response.status(
478 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
479 throw new WebApplicationException(response);
480 } catch (Exception e) {
481 if (logger.isDebugEnabled()) {
482 logger.debug("Caught exception in getAuthorityRefs", e);
484 Response response = Response.status(
485 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
486 throw new WebApplicationException(response);
494 * This is an intentionally empty method used for getting a rough time estimate
495 * of the overhead required for a client->server request/response cycle.
496 * @param ms - milliseconds to delay
498 * @return the response
501 @Path("/{ms}/roundtrip")
502 @Produces("application/xml")
503 public Response roundtrip(
504 @PathParam("ms") String ms) {
505 Response result = null;
507 Profiler profiler = new Profiler("roundtrip():", 1);
509 result = Response.status(HttpResponseCodes.SC_OK).build();
516 * This method is deprecated. Use SearchCollectionObjects() method instead.
517 * Keywords search collection objects.
520 * @param keywords the keywords
522 * @return the collectionobjects common list
526 @Produces("application/xml")
528 public CollectionobjectsCommonList keywordsSearchCollectionObjects(@Context UriInfo ui,
529 @QueryParam(IQueryManager.SEARCH_TYPE_KEYWORDS) String keywords) {
530 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
531 return searchCollectionObjects(queryParams, keywords);
535 * Search collection objects.
537 * @param keywords the keywords
539 * @return the collectionobjects common list
541 private CollectionobjectsCommonList searchCollectionObjects(
542 MultivaluedMap<String, String> queryParams,
544 CollectionobjectsCommonList collectionObjectList;
546 Profiler profiler = new Profiler("searchCollectionObjects():", 1);
548 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
549 DocumentHandler handler = createDocumentHandler(ctx);
551 // perform a keyword search
552 if (keywords != null && !keywords.isEmpty()) {
553 String whereClause = QueryManager.createWhereClauseFromKeywords(keywords);
554 DocumentFilter documentFilter = handler.getDocumentFilter();
555 documentFilter.appendWhereClause(whereClause, IQueryManager.SEARCH_QUALIFIER_AND);
556 if (logger.isDebugEnabled()) {
557 logger.debug("The WHERE clause is: " + documentFilter.getWhereClause());
561 getRepositoryClient(ctx).getFiltered(ctx, handler);
562 collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList();
563 } catch (UnauthorizedException ue) {
564 Response response = Response.status(
565 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
566 throw new WebApplicationException(response);
567 } catch (Exception e) {
568 if (logger.isDebugEnabled()) {
569 logger.debug("Caught exception in getCollectionObjectList", e);
571 Response response = Response.status(
572 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
573 throw new WebApplicationException(response);
575 return collectionObjectList;