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 package org.collectionspace.services.vocabulary;
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.DELETE;
28 import javax.ws.rs.GET;
29 import javax.ws.rs.POST;
30 import javax.ws.rs.PUT;
31 import javax.ws.rs.Path;
32 import javax.ws.rs.PathParam;
33 import javax.ws.rs.Produces;
34 import javax.ws.rs.QueryParam;
35 import javax.ws.rs.WebApplicationException;
36 import javax.ws.rs.core.Context;
37 import javax.ws.rs.core.MultivaluedMap;
38 import javax.ws.rs.core.Response;
39 import javax.ws.rs.core.UriBuilder;
40 import javax.ws.rs.core.UriInfo;
42 import org.collectionspace.services.VocabularyItemJAXBSchema;
43 import org.collectionspace.services.common.AbstractCollectionSpaceResource;
44 import org.collectionspace.services.common.ClientType;
45 import org.collectionspace.services.common.ServiceMain;
46 import org.collectionspace.services.common.context.MultipartServiceContext;
47 import org.collectionspace.services.common.context.MultipartServiceContextFactory;
48 import org.collectionspace.services.common.context.ServiceContext;
49 import org.collectionspace.services.common.document.DocumentFilter;
50 import org.collectionspace.services.common.document.DocumentHandler;
51 import org.collectionspace.services.common.document.DocumentNotFoundException;
52 import org.collectionspace.services.common.query.IQueryManager;
53 import org.collectionspace.services.common.security.UnauthorizedException;
54 import org.collectionspace.services.common.query.IQueryManager;
55 import org.collectionspace.services.vocabulary.nuxeo.VocabularyHandlerFactory;
56 import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemDocumentModelHandler;
57 import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemHandlerFactory;
58 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
59 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
60 import org.jboss.resteasy.util.HttpResponseCodes;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
64 @Path("/vocabularies")
65 @Consumes("multipart/mixed")
66 @Produces("multipart/mixed")
67 public class VocabularyResource extends AbstractCollectionSpaceResource {
69 private final static String vocabularyServiceName = "vocabularies";
70 private final static String vocabularyItemServiceName = "vocabularyitems";
71 final Logger logger = LoggerFactory.getLogger(VocabularyResource.class);
72 //FIXME retrieve client type from configuration
73 final static ClientType CLIENT_TYPE = ServiceMain.getInstance().getClientType();
75 public VocabularyResource() {
80 protected String getVersionString() {
81 /** The last change revision. */
82 final String lastChangeRevision = "$LastChangedRevision$";
83 return lastChangeRevision;
87 public String getServiceName() {
88 return vocabularyServiceName;
91 public String getItemServiceName() {
92 return vocabularyItemServiceName;
96 public RemoteServiceContext createItemServiceContext(MultipartInput input) throws Exception {
97 RemoteServiceContext ctx = new RemoteServiceContextImpl(getItemServiceName());
103 public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
104 DocumentHandler docHandler = VocabularyHandlerFactory.getInstance().getHandler(
105 ctx.getRepositoryClientType().toString());
106 docHandler.setServiceContext(ctx);
107 if (ctx.getInput() != null) {
108 Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), VocabulariesCommon.class);
110 docHandler.setCommonPart((VocabulariesCommon) obj);
116 private DocumentHandler createItemDocumentHandler(
118 String inVocabulary) throws Exception {
119 DocumentHandler docHandler = VocabularyItemHandlerFactory.getInstance().getHandler(
120 ctx.getRepositoryClientType().toString());
121 docHandler.setServiceContext(ctx);
122 ((VocabularyItemDocumentModelHandler) docHandler).setInVocabulary(inVocabulary);
123 if (ctx.getInput() != null) {
124 Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()),
125 VocabularyitemsCommon.class);
127 docHandler.setCommonPart((VocabularyitemsCommon) obj);
134 public Response createVocabulary(MultipartInput input) {
136 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(input, getServiceName());
137 DocumentHandler handler = createDocumentHandler(ctx);
138 String csid = getRepositoryClient(ctx).create(ctx, handler);
139 //vocabularyObject.setCsid(csid);
140 UriBuilder path = UriBuilder.fromResource(VocabularyResource.class);
141 path.path("" + csid);
142 Response response = Response.created(path.build()).build();
144 } catch (UnauthorizedException ue) {
145 Response response = Response.status(
146 Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
147 throw new WebApplicationException(response);
148 } catch (Exception e) {
149 if (logger.isDebugEnabled()) {
150 logger.debug("Caught exception in createVocabulary", e);
152 Response response = Response.status(
153 Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
154 throw new WebApplicationException(response);
160 public MultipartOutput getVocabulary(@PathParam("csid") String csid) {
161 String idValue = null;
163 logger.error("getVocabulary: missing csid!");
164 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
165 "get failed on Vocabulary csid=" + csid).type(
166 "text/plain").build();
167 throw new WebApplicationException(response);
169 if (logger.isDebugEnabled()) {
170 logger.debug("getVocabulary with path(id)=" + csid);
172 MultipartOutput result = null;
174 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
175 DocumentHandler handler = createDocumentHandler(ctx);
176 getRepositoryClient(ctx).get(ctx, csid, handler);
177 result = (MultipartOutput) ctx.getOutput();
178 } catch (UnauthorizedException ue) {
179 Response response = Response.status(
180 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
181 throw new WebApplicationException(response);
182 } catch (DocumentNotFoundException dnfe) {
183 if (logger.isDebugEnabled()) {
184 logger.debug("getVocabulary", dnfe);
186 Response response = Response.status(Response.Status.NOT_FOUND).entity(
187 "Get failed on Vocabulary csid=" + csid).type(
188 "text/plain").build();
189 throw new WebApplicationException(response);
190 } catch (Exception e) {
191 if (logger.isDebugEnabled()) {
192 logger.debug("getVocabulary", e);
194 Response response = Response.status(
195 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
196 throw new WebApplicationException(response);
198 if (result == null) {
199 Response response = Response.status(Response.Status.NOT_FOUND).entity(
200 "Get failed, the requested Vocabulary CSID:" + csid + ": was not found.").type(
201 "text/plain").build();
202 throw new WebApplicationException(response);
208 @Produces("application/xml")
209 public VocabulariesCommonList getVocabularyList(@Context UriInfo ui) {
210 VocabulariesCommonList vocabularyObjectList = new VocabulariesCommonList();
212 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
213 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
214 DocumentHandler handler = createDocumentHandler(ctx);
215 DocumentFilter myFilter = new DocumentFilter();
216 myFilter.setPagination(queryParams);
217 String nameQ = queryParams.getFirst("refName");
219 myFilter.setWhereClause("vocabularies_common:refName='" + nameQ + "'");
221 handler.setDocumentFilter(myFilter);
222 getRepositoryClient(ctx).getFiltered(ctx, handler);
223 vocabularyObjectList = (VocabulariesCommonList) handler.getCommonPartList();
224 } catch (UnauthorizedException ue) {
225 Response response = Response.status(
226 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
227 throw new WebApplicationException(response);
228 } catch (Exception e) {
229 if (logger.isDebugEnabled()) {
230 logger.debug("Caught exception in getVocabularyList", e);
232 Response response = Response.status(
233 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
234 throw new WebApplicationException(response);
236 return vocabularyObjectList;
241 public MultipartOutput updateVocabulary(
242 @PathParam("csid") String csid,
243 MultipartInput theUpdate) {
244 if (logger.isDebugEnabled()) {
245 logger.debug("updateVocabulary with csid=" + csid);
247 if (csid == null || "".equals(csid)) {
248 logger.error("updateVocabulary: missing csid!");
249 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
250 "update failed on Vocabulary csid=" + csid).type(
251 "text/plain").build();
252 throw new WebApplicationException(response);
254 MultipartOutput result = null;
256 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(theUpdate, getServiceName());
257 DocumentHandler handler = createDocumentHandler(ctx);
258 getRepositoryClient(ctx).update(ctx, csid, handler);
259 result = (MultipartOutput) ctx.getOutput();
260 } catch (UnauthorizedException ue) {
261 Response response = Response.status(
262 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
263 throw new WebApplicationException(response);
264 } catch (DocumentNotFoundException dnfe) {
265 if (logger.isDebugEnabled()) {
266 logger.debug("caugth exception in updateVocabulary", dnfe);
268 Response response = Response.status(Response.Status.NOT_FOUND).entity(
269 "Update failed on Vocabulary csid=" + csid).type(
270 "text/plain").build();
271 throw new WebApplicationException(response);
272 } catch (Exception e) {
273 Response response = Response.status(
274 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
275 throw new WebApplicationException(response);
282 public Response deleteVocabulary(@PathParam("csid") String csid) {
284 if (logger.isDebugEnabled()) {
285 logger.debug("deleteVocabulary with csid=" + csid);
287 if (csid == null || "".equals(csid)) {
288 logger.error("deleteVocabulary: missing csid!");
289 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
290 "delete failed on Vocabulary csid=" + csid).type(
291 "text/plain").build();
292 throw new WebApplicationException(response);
295 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
296 getRepositoryClient(ctx).delete(ctx, csid);
297 return Response.status(HttpResponseCodes.SC_OK).build();
298 } catch (UnauthorizedException ue) {
299 Response response = Response.status(
300 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
301 throw new WebApplicationException(response);
302 } catch (DocumentNotFoundException dnfe) {
303 if (logger.isDebugEnabled()) {
304 logger.debug("caught exception in deleteVocabulary", dnfe);
306 Response response = Response.status(Response.Status.NOT_FOUND).entity(
307 "Delete failed on Vocabulary csid=" + csid).type(
308 "text/plain").build();
309 throw new WebApplicationException(response);
310 } catch (Exception e) {
311 Response response = Response.status(
312 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
313 throw new WebApplicationException(response);
318 /*************************************************************************
319 * VocabularyItem parts - this is a sub-resource of Vocabulary
320 *************************************************************************/
322 @Path("{csid}/items")
323 public Response createVocabularyItem(@PathParam("csid") String parentcsid, MultipartInput input) {
325 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(input, getItemServiceName());
326 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
327 String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
328 UriBuilder path = UriBuilder.fromResource(VocabularyResource.class);
329 path.path(parentcsid + "/items/" + itemcsid);
330 Response response = Response.created(path.build()).build();
332 } catch (UnauthorizedException ue) {
333 Response response = Response.status(
334 Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
335 throw new WebApplicationException(response);
336 } catch (Exception e) {
337 if (logger.isDebugEnabled()) {
338 logger.debug("Caught exception in createVocabularyItem", e);
340 Response response = Response.status(
341 Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
342 throw new WebApplicationException(response);
347 @Path("{csid}/items/{itemcsid}")
348 public MultipartOutput getVocabularyItem(
349 @PathParam("csid") String parentcsid,
350 @PathParam("itemcsid") String itemcsid) {
351 if (logger.isDebugEnabled()) {
352 logger.debug("getVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
354 if (parentcsid == null || "".equals(parentcsid)) {
355 logger.error("getVocabularyItem: missing csid!");
356 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
357 "get failed on VocabularyItem csid=" + parentcsid).type(
358 "text/plain").build();
359 throw new WebApplicationException(response);
361 if (itemcsid == null || "".equals(itemcsid)) {
362 logger.error("getVocabularyItem: missing itemcsid!");
363 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
364 "get failed on VocabularyItem itemcsid=" + itemcsid).type(
365 "text/plain").build();
366 throw new WebApplicationException(response);
368 MultipartOutput result = null;
370 // Note that we have to create the service context for the Items, not the main service
371 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName());
372 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
373 getRepositoryClient(ctx).get(ctx, itemcsid, handler);
374 // TODO should we assert that the item is in the passed vocab?
375 result = (MultipartOutput) ctx.getOutput();
376 } catch (UnauthorizedException ue) {
377 Response response = Response.status(
378 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
379 throw new WebApplicationException(response);
380 } catch (DocumentNotFoundException dnfe) {
381 if (logger.isDebugEnabled()) {
382 logger.debug("getVocabularyItem", dnfe);
384 Response response = Response.status(Response.Status.NOT_FOUND).entity(
385 "Get failed on VocabularyItem csid=" + itemcsid).type(
386 "text/plain").build();
387 throw new WebApplicationException(response);
388 } catch (Exception e) {
389 if (logger.isDebugEnabled()) {
390 logger.debug("getVocabularyItem", e);
392 Response response = Response.status(
393 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
394 throw new WebApplicationException(response);
396 if (result == null) {
397 Response response = Response.status(Response.Status.NOT_FOUND).entity(
398 "Get failed, the requested VocabularyItem CSID:" + itemcsid + ": was not found.").type(
399 "text/plain").build();
400 throw new WebApplicationException(response);
406 @Path("{csid}/items")
407 @Produces("application/xml")
408 public VocabularyitemsCommonList getVocabularyItemList(
409 @PathParam("csid") String parentcsid,
410 @QueryParam (IQueryManager.SEARCH_TYPE_PARTIALTERM) String partialTerm,
411 @Context UriInfo ui) {
412 VocabularyitemsCommonList vocabularyItemObjectList = new VocabularyitemsCommonList();
414 // Note that docType defaults to the ServiceName, so we're fine with that.
415 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName());
416 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
417 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
418 DocumentFilter myFilter = new DocumentFilter();
419 myFilter.setPagination(queryParams);
420 // "vocabularyitems_common:inVocabulary='" + parentcsid + "'");
421 myFilter.setWhereClause(
422 VocabularyItemJAXBSchema.VOCABULARYITEMS_COMMON + ":" +
423 VocabularyItemJAXBSchema.IN_VOCABULARY + "=" +
424 "'" + parentcsid + "'");
426 // AND vocabularyitems_common:displayName LIKE '%partialTerm%'
427 if (partialTerm != null && !partialTerm.isEmpty()) {
428 String ptClause = "AND " +
429 VocabularyItemJAXBSchema.VOCABULARYITEMS_COMMON + ":" +
430 VocabularyItemJAXBSchema.DISPLAY_NAME +
432 "'%" + partialTerm + "%'";
433 myFilter.appendWhereClause(ptClause);
436 if (logger.isDebugEnabled()) {
437 logger.debug("getVocabularyItemList filtered WHERE clause: " +
438 myFilter.getWhereClause());
441 handler.setDocumentFilter(myFilter);
442 getRepositoryClient(ctx).getFiltered(ctx, handler);
444 vocabularyItemObjectList = (VocabularyitemsCommonList) handler.getCommonPartList();
445 } catch (UnauthorizedException ue) {
446 Response response = Response.status(
447 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
448 throw new WebApplicationException(response);
449 } catch (Exception e) {
450 if (logger.isDebugEnabled()) {
451 logger.debug("Caught exception in getVocabularyItemList", e);
453 Response response = Response.status(
454 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
455 throw new WebApplicationException(response);
457 return vocabularyItemObjectList;
461 @Path("{csid}/items/{itemcsid}")
462 public MultipartOutput updateVocabularyItem(
463 @PathParam("csid") String parentcsid,
464 @PathParam("itemcsid") String itemcsid,
465 MultipartInput theUpdate) {
466 if (logger.isDebugEnabled()) {
467 logger.debug("updateVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
469 if (parentcsid == null || "".equals(parentcsid)) {
470 logger.error("updateVocabularyItem: missing csid!");
471 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
472 "update failed on VocabularyItem parentcsid=" + parentcsid).type(
473 "text/plain").build();
474 throw new WebApplicationException(response);
476 if (itemcsid == null || "".equals(itemcsid)) {
477 logger.error("updateVocabularyItem: missing itemcsid!");
478 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
479 "update failed on VocabularyItem=" + itemcsid).type(
480 "text/plain").build();
481 throw new WebApplicationException(response);
483 MultipartOutput result = null;
485 // Note that we have to create the service context for the Items, not the main service
486 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(theUpdate, getItemServiceName());
487 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
488 getRepositoryClient(ctx).update(ctx, itemcsid, handler);
489 result = (MultipartOutput) ctx.getOutput();
490 } catch (UnauthorizedException ue) {
491 Response response = Response.status(
492 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
493 throw new WebApplicationException(response);
494 } catch (DocumentNotFoundException dnfe) {
495 if (logger.isDebugEnabled()) {
496 logger.debug("caugth exception in updateVocabularyItem", dnfe);
498 Response response = Response.status(Response.Status.NOT_FOUND).entity(
499 "Update failed on VocabularyItem csid=" + itemcsid).type(
500 "text/plain").build();
501 throw new WebApplicationException(response);
502 } catch (Exception e) {
503 Response response = Response.status(
504 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
505 throw new WebApplicationException(response);
511 @Path("{csid}/items/{itemcsid}")
512 public Response deleteVocabularyItem(
513 @PathParam("csid") String parentcsid,
514 @PathParam("itemcsid") String itemcsid) {
515 if (logger.isDebugEnabled()) {
516 logger.debug("deleteVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
518 if (parentcsid == null || "".equals(parentcsid)) {
519 logger.error("deleteVocabularyItem: missing csid!");
520 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
521 "delete failed on VocabularyItem parentcsid=" + parentcsid).type(
522 "text/plain").build();
523 throw new WebApplicationException(response);
525 if (itemcsid == null || "".equals(itemcsid)) {
526 logger.error("deleteVocabularyItem: missing itemcsid!");
527 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
528 "delete failed on VocabularyItem=" + itemcsid).type(
529 "text/plain").build();
530 throw new WebApplicationException(response);
533 // Note that we have to create the service context for the Items, not the main service
534 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName());
535 getRepositoryClient(ctx).delete(ctx, itemcsid);
536 return Response.status(HttpResponseCodes.SC_OK).build();
537 } catch (UnauthorizedException ue) {
538 Response response = Response.status(
539 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
540 throw new WebApplicationException(response);
541 } catch (DocumentNotFoundException dnfe) {
542 if (logger.isDebugEnabled()) {
543 logger.debug("caught exception in deleteVocabulary", dnfe);
545 Response response = Response.status(Response.Status.NOT_FOUND).entity(
546 "Delete failed on VocabularyItem itemcsid=" + itemcsid).type(
547 "text/plain").build();
548 throw new WebApplicationException(response);
549 } catch (Exception e) {
550 Response response = Response.status(
551 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
552 throw new WebApplicationException(response);