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.AbstractCollectionSpaceResourceImpl;
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.security.UnauthorizedException;
53 import org.collectionspace.services.common.query.IQueryManager;
54 import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemDocumentModelHandler;
55 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
56 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
57 import org.jboss.resteasy.util.HttpResponseCodes;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
61 @Path("/vocabularies")
62 @Consumes("multipart/mixed")
63 @Produces("multipart/mixed")
64 public class VocabularyResource extends AbstractCollectionSpaceResourceImpl {
66 private final static String vocabularyServiceName = "vocabularies";
67 private final static String vocabularyItemServiceName = "vocabularyitems";
68 final Logger logger = LoggerFactory.getLogger(VocabularyResource.class);
69 //FIXME retrieve client type from configuration
70 final static ClientType CLIENT_TYPE = ServiceMain.getInstance().getClientType();
72 public VocabularyResource() {
77 protected String getVersionString() {
78 /** The last change revision. */
79 final String lastChangeRevision = "$LastChangedRevision$";
80 return lastChangeRevision;
84 public String getServiceName() {
85 return vocabularyServiceName;
88 public String getItemServiceName() {
89 return vocabularyItemServiceName;
93 public RemoteServiceContext createItemServiceContext(MultipartInput input) throws Exception {
94 RemoteServiceContext ctx = new RemoteServiceContextImpl(getItemServiceName());
100 public DocumentHandler createDocumentHandler(ServiceContext ctx) throws Exception {
101 DocumentHandler docHandler = ctx.getDocumentHandler();
102 if (ctx.getInput() != null) {
103 Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), VocabulariesCommon.class);
105 docHandler.setCommonPart((VocabulariesCommon) obj);
111 private DocumentHandler createItemDocumentHandler(
113 String inVocabulary) throws Exception {
114 DocumentHandler docHandler = ctx.getDocumentHandler();
115 ((VocabularyItemDocumentModelHandler) docHandler).setInVocabulary(inVocabulary);
116 if (ctx.getInput() != null) {
117 Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()),
118 VocabularyitemsCommon.class);
120 docHandler.setCommonPart((VocabularyitemsCommon) obj);
127 public Response createVocabulary(MultipartInput input) {
129 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(input, getServiceName());
130 DocumentHandler handler = createDocumentHandler(ctx);
131 String csid = getRepositoryClient(ctx).create(ctx, handler);
132 //vocabularyObject.setCsid(csid);
133 UriBuilder path = UriBuilder.fromResource(VocabularyResource.class);
134 path.path("" + csid);
135 Response response = Response.created(path.build()).build();
137 } catch (UnauthorizedException ue) {
138 Response response = Response.status(
139 Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
140 throw new WebApplicationException(response);
141 } catch (Exception e) {
142 if (logger.isDebugEnabled()) {
143 logger.debug("Caught exception in createVocabulary", e);
145 Response response = Response.status(
146 Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
147 throw new WebApplicationException(response);
153 public MultipartOutput getVocabulary(@PathParam("csid") String csid) {
154 String idValue = null;
156 logger.error("getVocabulary: missing csid!");
157 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
158 "get failed on Vocabulary csid=" + csid).type(
159 "text/plain").build();
160 throw new WebApplicationException(response);
162 if (logger.isDebugEnabled()) {
163 logger.debug("getVocabulary with path(id)=" + csid);
165 MultipartOutput result = null;
167 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
168 DocumentHandler handler = createDocumentHandler(ctx);
169 getRepositoryClient(ctx).get(ctx, csid, handler);
170 result = (MultipartOutput) ctx.getOutput();
171 } catch (UnauthorizedException ue) {
172 Response response = Response.status(
173 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
174 throw new WebApplicationException(response);
175 } catch (DocumentNotFoundException dnfe) {
176 if (logger.isDebugEnabled()) {
177 logger.debug("getVocabulary", dnfe);
179 Response response = Response.status(Response.Status.NOT_FOUND).entity(
180 "Get failed on Vocabulary csid=" + csid).type(
181 "text/plain").build();
182 throw new WebApplicationException(response);
183 } catch (Exception e) {
184 if (logger.isDebugEnabled()) {
185 logger.debug("getVocabulary", e);
187 Response response = Response.status(
188 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
189 throw new WebApplicationException(response);
191 if (result == null) {
192 Response response = Response.status(Response.Status.NOT_FOUND).entity(
193 "Get failed, the requested Vocabulary CSID:" + csid + ": was not found.").type(
194 "text/plain").build();
195 throw new WebApplicationException(response);
201 @Produces("application/xml")
202 public VocabulariesCommonList getVocabularyList(@Context UriInfo ui) {
203 VocabulariesCommonList vocabularyObjectList = new VocabulariesCommonList();
205 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
206 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
207 DocumentHandler handler = createDocumentHandler(ctx);
208 DocumentFilter myFilter = new DocumentFilter();
209 myFilter.setPagination(queryParams);
210 String nameQ = queryParams.getFirst("refName");
212 myFilter.setWhereClause("vocabularies_common:refName='" + nameQ + "'");
214 handler.setDocumentFilter(myFilter);
215 getRepositoryClient(ctx).getFiltered(ctx, handler);
216 vocabularyObjectList = (VocabulariesCommonList) handler.getCommonPartList();
217 } catch (UnauthorizedException ue) {
218 Response response = Response.status(
219 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
220 throw new WebApplicationException(response);
221 } catch (Exception e) {
222 if (logger.isDebugEnabled()) {
223 logger.debug("Caught exception in getVocabularyList", e);
225 Response response = Response.status(
226 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
227 throw new WebApplicationException(response);
229 return vocabularyObjectList;
234 public MultipartOutput updateVocabulary(
235 @PathParam("csid") String csid,
236 MultipartInput theUpdate) {
237 if (logger.isDebugEnabled()) {
238 logger.debug("updateVocabulary with csid=" + csid);
240 if (csid == null || "".equals(csid)) {
241 logger.error("updateVocabulary: missing csid!");
242 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
243 "update failed on Vocabulary csid=" + csid).type(
244 "text/plain").build();
245 throw new WebApplicationException(response);
247 MultipartOutput result = null;
249 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(theUpdate, getServiceName());
250 DocumentHandler handler = createDocumentHandler(ctx);
251 getRepositoryClient(ctx).update(ctx, csid, handler);
252 result = (MultipartOutput) ctx.getOutput();
253 } catch (UnauthorizedException ue) {
254 Response response = Response.status(
255 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
256 throw new WebApplicationException(response);
257 } catch (DocumentNotFoundException dnfe) {
258 if (logger.isDebugEnabled()) {
259 logger.debug("caugth exception in updateVocabulary", dnfe);
261 Response response = Response.status(Response.Status.NOT_FOUND).entity(
262 "Update failed on Vocabulary csid=" + csid).type(
263 "text/plain").build();
264 throw new WebApplicationException(response);
265 } catch (Exception e) {
266 Response response = Response.status(
267 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
268 throw new WebApplicationException(response);
275 public Response deleteVocabulary(@PathParam("csid") String csid) {
277 if (logger.isDebugEnabled()) {
278 logger.debug("deleteVocabulary with csid=" + csid);
280 if (csid == null || "".equals(csid)) {
281 logger.error("deleteVocabulary: missing csid!");
282 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
283 "delete failed on Vocabulary csid=" + csid).type(
284 "text/plain").build();
285 throw new WebApplicationException(response);
288 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
289 getRepositoryClient(ctx).delete(ctx, csid);
290 return Response.status(HttpResponseCodes.SC_OK).build();
291 } catch (UnauthorizedException ue) {
292 Response response = Response.status(
293 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
294 throw new WebApplicationException(response);
295 } catch (DocumentNotFoundException dnfe) {
296 if (logger.isDebugEnabled()) {
297 logger.debug("caught exception in deleteVocabulary", dnfe);
299 Response response = Response.status(Response.Status.NOT_FOUND).entity(
300 "Delete failed on Vocabulary csid=" + csid).type(
301 "text/plain").build();
302 throw new WebApplicationException(response);
303 } catch (Exception e) {
304 Response response = Response.status(
305 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
306 throw new WebApplicationException(response);
311 /*************************************************************************
312 * VocabularyItem parts - this is a sub-resource of Vocabulary
313 *************************************************************************/
315 @Path("{csid}/items")
316 public Response createVocabularyItem(@PathParam("csid") String parentcsid, MultipartInput input) {
318 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(input, getItemServiceName());
319 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
320 String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
321 UriBuilder path = UriBuilder.fromResource(VocabularyResource.class);
322 path.path(parentcsid + "/items/" + itemcsid);
323 Response response = Response.created(path.build()).build();
325 } catch (UnauthorizedException ue) {
326 Response response = Response.status(
327 Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
328 throw new WebApplicationException(response);
329 } catch (Exception e) {
330 if (logger.isDebugEnabled()) {
331 logger.debug("Caught exception in createVocabularyItem", e);
333 Response response = Response.status(
334 Response.Status.INTERNAL_SERVER_ERROR).entity("Create failed").type("text/plain").build();
335 throw new WebApplicationException(response);
340 @Path("{csid}/items/{itemcsid}")
341 public MultipartOutput getVocabularyItem(
342 @PathParam("csid") String parentcsid,
343 @PathParam("itemcsid") String itemcsid) {
344 if (logger.isDebugEnabled()) {
345 logger.debug("getVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
347 if (parentcsid == null || "".equals(parentcsid)) {
348 logger.error("getVocabularyItem: missing csid!");
349 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
350 "get failed on VocabularyItem csid=" + parentcsid).type(
351 "text/plain").build();
352 throw new WebApplicationException(response);
354 if (itemcsid == null || "".equals(itemcsid)) {
355 logger.error("getVocabularyItem: missing itemcsid!");
356 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
357 "get failed on VocabularyItem itemcsid=" + itemcsid).type(
358 "text/plain").build();
359 throw new WebApplicationException(response);
361 MultipartOutput result = null;
363 // Note that we have to create the service context for the Items, not the main service
364 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName());
365 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
366 getRepositoryClient(ctx).get(ctx, itemcsid, handler);
367 // TODO should we assert that the item is in the passed vocab?
368 result = (MultipartOutput) ctx.getOutput();
369 } catch (UnauthorizedException ue) {
370 Response response = Response.status(
371 Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build();
372 throw new WebApplicationException(response);
373 } catch (DocumentNotFoundException dnfe) {
374 if (logger.isDebugEnabled()) {
375 logger.debug("getVocabularyItem", dnfe);
377 Response response = Response.status(Response.Status.NOT_FOUND).entity(
378 "Get failed on VocabularyItem csid=" + itemcsid).type(
379 "text/plain").build();
380 throw new WebApplicationException(response);
381 } catch (Exception e) {
382 if (logger.isDebugEnabled()) {
383 logger.debug("getVocabularyItem", e);
385 Response response = Response.status(
386 Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build();
387 throw new WebApplicationException(response);
389 if (result == null) {
390 Response response = Response.status(Response.Status.NOT_FOUND).entity(
391 "Get failed, the requested VocabularyItem CSID:" + itemcsid + ": was not found.").type(
392 "text/plain").build();
393 throw new WebApplicationException(response);
399 @Path("{csid}/items")
400 @Produces("application/xml")
401 public VocabularyitemsCommonList getVocabularyItemList(
402 @PathParam("csid") String parentcsid,
403 @QueryParam(IQueryManager.SEARCH_TYPE_PARTIALTERM) String partialTerm,
404 @Context UriInfo ui) {
405 VocabularyitemsCommonList vocabularyItemObjectList = new VocabularyitemsCommonList();
407 // Note that docType defaults to the ServiceName, so we're fine with that.
408 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName());
409 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
410 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
411 DocumentFilter myFilter = new DocumentFilter();
412 myFilter.setPagination(queryParams);
413 // "vocabularyitems_common:inVocabulary='" + parentcsid + "'");
414 myFilter.setWhereClause(
415 VocabularyItemJAXBSchema.VOCABULARYITEMS_COMMON + ":"
416 + VocabularyItemJAXBSchema.IN_VOCABULARY + "="
417 + "'" + parentcsid + "'");
419 // AND vocabularyitems_common:displayName LIKE '%partialTerm%'
420 if (partialTerm != null && !partialTerm.isEmpty()) {
421 String ptClause = "AND "
422 + VocabularyItemJAXBSchema.VOCABULARYITEMS_COMMON + ":"
423 + VocabularyItemJAXBSchema.DISPLAY_NAME
425 + "'%" + partialTerm + "%'";
426 myFilter.appendWhereClause(ptClause);
429 if (logger.isDebugEnabled()) {
430 logger.debug("getVocabularyItemList filtered WHERE clause: "
431 + myFilter.getWhereClause());
434 handler.setDocumentFilter(myFilter);
435 getRepositoryClient(ctx).getFiltered(ctx, handler);
437 vocabularyItemObjectList = (VocabularyitemsCommonList) handler.getCommonPartList();
438 } catch (UnauthorizedException ue) {
439 Response response = Response.status(
440 Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build();
441 throw new WebApplicationException(response);
442 } catch (Exception e) {
443 if (logger.isDebugEnabled()) {
444 logger.debug("Caught exception in getVocabularyItemList", e);
446 Response response = Response.status(
447 Response.Status.INTERNAL_SERVER_ERROR).entity("Index failed").type("text/plain").build();
448 throw new WebApplicationException(response);
450 return vocabularyItemObjectList;
454 @Path("{csid}/items/{itemcsid}")
455 public MultipartOutput updateVocabularyItem(
456 @PathParam("csid") String parentcsid,
457 @PathParam("itemcsid") String itemcsid,
458 MultipartInput theUpdate) {
459 if (logger.isDebugEnabled()) {
460 logger.debug("updateVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
462 if (parentcsid == null || "".equals(parentcsid)) {
463 logger.error("updateVocabularyItem: missing csid!");
464 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
465 "update failed on VocabularyItem parentcsid=" + parentcsid).type(
466 "text/plain").build();
467 throw new WebApplicationException(response);
469 if (itemcsid == null || "".equals(itemcsid)) {
470 logger.error("updateVocabularyItem: missing itemcsid!");
471 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
472 "update failed on VocabularyItem=" + itemcsid).type(
473 "text/plain").build();
474 throw new WebApplicationException(response);
476 MultipartOutput result = null;
478 // Note that we have to create the service context for the Items, not the main service
479 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(theUpdate, getItemServiceName());
480 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid);
481 getRepositoryClient(ctx).update(ctx, itemcsid, handler);
482 result = (MultipartOutput) ctx.getOutput();
483 } catch (UnauthorizedException ue) {
484 Response response = Response.status(
485 Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build();
486 throw new WebApplicationException(response);
487 } catch (DocumentNotFoundException dnfe) {
488 if (logger.isDebugEnabled()) {
489 logger.debug("caugth exception in updateVocabularyItem", dnfe);
491 Response response = Response.status(Response.Status.NOT_FOUND).entity(
492 "Update failed on VocabularyItem csid=" + itemcsid).type(
493 "text/plain").build();
494 throw new WebApplicationException(response);
495 } catch (Exception e) {
496 Response response = Response.status(
497 Response.Status.INTERNAL_SERVER_ERROR).entity("Update failed").type("text/plain").build();
498 throw new WebApplicationException(response);
504 @Path("{csid}/items/{itemcsid}")
505 public Response deleteVocabularyItem(
506 @PathParam("csid") String parentcsid,
507 @PathParam("itemcsid") String itemcsid) {
508 if (logger.isDebugEnabled()) {
509 logger.debug("deleteVocabularyItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
511 if (parentcsid == null || "".equals(parentcsid)) {
512 logger.error("deleteVocabularyItem: missing csid!");
513 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
514 "delete failed on VocabularyItem parentcsid=" + parentcsid).type(
515 "text/plain").build();
516 throw new WebApplicationException(response);
518 if (itemcsid == null || "".equals(itemcsid)) {
519 logger.error("deleteVocabularyItem: missing itemcsid!");
520 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
521 "delete failed on VocabularyItem=" + itemcsid).type(
522 "text/plain").build();
523 throw new WebApplicationException(response);
526 // Note that we have to create the service context for the Items, not the main service
527 ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName());
528 getRepositoryClient(ctx).delete(ctx, itemcsid);
529 return Response.status(HttpResponseCodes.SC_OK).build();
530 } catch (UnauthorizedException ue) {
531 Response response = Response.status(
532 Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build();
533 throw new WebApplicationException(response);
534 } catch (DocumentNotFoundException dnfe) {
535 if (logger.isDebugEnabled()) {
536 logger.debug("caught exception in deleteVocabulary", dnfe);
538 Response response = Response.status(Response.Status.NOT_FOUND).entity(
539 "Delete failed on VocabularyItem itemcsid=" + itemcsid).type(
540 "text/plain").build();
541 throw new WebApplicationException(response);
542 } catch (Exception e) {
543 Response response = Response.status(
544 Response.Status.INTERNAL_SERVER_ERROR).entity("Delete failed").type("text/plain").build();
545 throw new WebApplicationException(response);