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.common.vocabulary;
26 import org.collectionspace.services.client.IClientQueryParams;
27 import org.collectionspace.services.client.IQueryManager;
28 import org.collectionspace.services.client.PoxPayloadIn;
29 import org.collectionspace.services.client.PoxPayloadOut;
30 import org.collectionspace.services.client.workflow.WorkflowClient;
31 import org.collectionspace.services.common.ClientType;
32 import org.collectionspace.services.common.ResourceBase;
33 import org.collectionspace.services.common.ResourceMap;
34 import org.collectionspace.services.common.ServiceMain;
35 import org.collectionspace.services.common.ServiceMessages;
36 import org.collectionspace.services.common.XmlTools;
37 import org.collectionspace.services.common.api.RefName;
38 import org.collectionspace.services.common.api.Tools;
39 import org.collectionspace.services.common.authorityref.AuthorityRefDocList;
40 import org.collectionspace.services.common.authorityref.AuthorityRefList;
41 import org.collectionspace.services.common.context.JaxRsContext;
42 import org.collectionspace.services.common.context.MultipartServiceContext;
43 import org.collectionspace.services.common.context.MultipartServiceContextImpl;
44 import org.collectionspace.services.common.context.RemoteServiceContext;
45 import org.collectionspace.services.common.context.ServiceBindingUtils;
46 import org.collectionspace.services.common.context.ServiceContext;
47 import org.collectionspace.services.common.document.DocumentException;
48 import org.collectionspace.services.common.document.DocumentFilter;
49 import org.collectionspace.services.common.document.DocumentHandler;
50 import org.collectionspace.services.common.document.DocumentNotFoundException;
51 import org.collectionspace.services.common.document.DocumentWrapper;
52 import org.collectionspace.services.common.query.QueryManager;
53 import org.collectionspace.services.common.repository.RepositoryClient;
54 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
55 import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
56 import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
57 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
58 import org.collectionspace.services.jaxb.AbstractCommonList;
59 import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
60 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
61 import org.collectionspace.services.relation.RelationResource;
62 import org.collectionspace.services.relation.RelationsCommonList;
63 import org.collectionspace.services.relation.RelationshipType;
64 import org.jboss.resteasy.util.HttpResponseCodes;
65 import org.nuxeo.ecm.core.api.DocumentModel;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
69 import javax.ws.rs.Consumes;
70 import javax.ws.rs.DELETE;
71 import javax.ws.rs.GET;
72 import javax.ws.rs.POST;
73 import javax.ws.rs.PUT;
74 import javax.ws.rs.Path;
75 import javax.ws.rs.PathParam;
76 import javax.ws.rs.Produces;
77 import javax.ws.rs.QueryParam;
78 import javax.ws.rs.WebApplicationException;
79 import javax.ws.rs.core.Context;
80 import javax.ws.rs.core.MultivaluedMap;
81 import javax.ws.rs.core.Request;
82 import javax.ws.rs.core.Response;
83 import javax.ws.rs.core.UriBuilder;
84 import javax.ws.rs.core.UriInfo;
86 import java.util.ArrayList;
87 import java.util.List;
90 * The Class AuthorityResource.
96 * @param <AuthItemHandler>
101 * @param <AuthCommon>
102 * @param <AuthItemHandler>
104 @Consumes("application/xml")
105 @Produces("application/xml")
106 public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
107 extends ResourceBase {
109 final static String SEARCH_TYPE_TERMSTATUS = "ts";
111 protected Class<AuthCommon> authCommonClass;
112 protected Class<?> resourceClass;
113 protected String authorityCommonSchemaName;
114 protected String authorityItemCommonSchemaName;
115 final static ClientType CLIENT_TYPE = ServiceMain.getInstance().getClientType();
116 final static String URN_PREFIX = "urn:cspace:";
117 final static int URN_PREFIX_LEN = URN_PREFIX.length();
118 final static String URN_PREFIX_NAME = "name(";
119 final static int URN_NAME_PREFIX_LEN = URN_PREFIX_LEN + URN_PREFIX_NAME.length();
120 final static String URN_PREFIX_ID = "id(";
121 final static int URN_ID_PREFIX_LEN = URN_PREFIX_LEN + URN_PREFIX_ID.length();
122 final static String FETCH_SHORT_ID = "_fetch_";
123 final Logger logger = LoggerFactory.getLogger(AuthorityResource.class);
125 public enum SpecifierForm {
130 public class Specifier {
132 public SpecifierForm form;
135 Specifier(SpecifierForm form, String value) {
141 protected Specifier getSpecifier(String specifierIn, String method, String op) throws WebApplicationException {
142 if (logger.isDebugEnabled()) {
143 logger.debug("getSpecifier called by: " + method + " with specifier: " + specifierIn);
145 if (specifierIn != null) {
146 if (!specifierIn.startsWith(URN_PREFIX)) {
147 // We'll assume it is a CSID and complain if it does not match
148 return new Specifier(SpecifierForm.CSID, specifierIn);
150 if (specifierIn.startsWith(URN_PREFIX_NAME, URN_PREFIX_LEN)) {
151 int closeParen = specifierIn.indexOf(')', URN_NAME_PREFIX_LEN);
152 if (closeParen >= 0) {
153 return new Specifier(SpecifierForm.URN_NAME,
154 specifierIn.substring(URN_NAME_PREFIX_LEN, closeParen));
156 } else if (specifierIn.startsWith(URN_PREFIX_ID, URN_PREFIX_LEN)) {
157 int closeParen = specifierIn.indexOf(')', URN_ID_PREFIX_LEN);
158 if (closeParen >= 0) {
159 return new Specifier(SpecifierForm.CSID,
160 specifierIn.substring(URN_ID_PREFIX_LEN, closeParen));
165 logger.error(method + ": bad or missing specifier!");
166 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
167 op + " failed on bad or missing Authority specifier").type(
168 "text/plain").build();
169 throw new WebApplicationException(response);
173 * Instantiates a new Authority resource.
175 public AuthorityResource(Class<AuthCommon> authCommonClass, Class<?> resourceClass,
176 String authorityCommonSchemaName, String authorityItemCommonSchemaName) {
177 this.authCommonClass = authCommonClass;
178 this.resourceClass = resourceClass;
179 this.authorityCommonSchemaName = authorityCommonSchemaName;
180 this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
183 public abstract String getItemServiceName();
186 protected String getVersionString() {
187 return "$LastChangedRevision: 2617 $";
191 public Class<AuthCommon> getCommonPartClass() {
192 return authCommonClass;
196 * Creates the item document handler.
199 * @param inAuthority the in vocabulary
201 * @return the document handler
203 * @throws Exception the exception
205 protected DocumentHandler createItemDocumentHandler(
206 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
207 String inAuthority, String parentShortIdentifier)
209 String authorityRefNameBase;
210 AuthorityItemDocumentModelHandler<?> docHandler;
212 if (parentShortIdentifier == null) {
213 authorityRefNameBase = null;
215 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx =
216 createServiceContext(getServiceName());
217 if (parentShortIdentifier.equals(FETCH_SHORT_ID)) {
218 // Get from parent document
219 parentShortIdentifier = getAuthShortIdentifier(parentCtx, inAuthority);
221 authorityRefNameBase = buildAuthorityRefNameBase(parentCtx, parentShortIdentifier);
224 docHandler = (AuthorityItemDocumentModelHandler<?>) createDocumentHandler(ctx,
225 ctx.getCommonPartLabel(getItemServiceName()),
227 docHandler.setInAuthority(inAuthority);
228 docHandler.setAuthorityRefNameBase(authorityRefNameBase);
233 public String getAuthShortIdentifier(
234 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String authCSID)
235 throws DocumentNotFoundException, DocumentException {
236 String shortIdentifier = null;
238 AuthorityDocumentModelHandler<?> handler =
239 (AuthorityDocumentModelHandler<?>) createDocumentHandler(ctx);
240 shortIdentifier = handler.getShortIdentifier(authCSID, authorityCommonSchemaName);
241 } catch (Exception e) {
242 if (logger.isDebugEnabled()) {
243 logger.debug("Caught exception ", e);
245 throw new DocumentException(e);
247 return shortIdentifier;
250 protected String buildAuthorityRefNameBase(
251 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String shortIdentifier) {
252 RefName.Authority authority = RefName.buildAuthority(ctx.getTenantName(),
253 ctx.getServiceName(), shortIdentifier, null);
254 return authority.toString();
257 public static class CsidAndShortIdentifier {
260 String shortIdentifier;
263 public String lookupParentCSID(String parentspecifier, String method, String op, MultivaluedMap<String, String> queryParams)
265 CsidAndShortIdentifier tempResult = lookupParentCSIDAndShortIdentifer(parentspecifier, method, op, queryParams);
266 return tempResult.CSID;
269 public CsidAndShortIdentifier lookupParentCSIDAndShortIdentifer(String parentspecifier, String method, String op, MultivaluedMap<String, String> queryParams)
271 CsidAndShortIdentifier result = new CsidAndShortIdentifier();
272 Specifier parentSpec = getSpecifier(parentspecifier, method, op);
273 // Note that we have to create the service context for the Items, not the main service
275 String parentShortIdentifier;
276 if (parentSpec.form == SpecifierForm.CSID) {
277 parentShortIdentifier = null;
278 parentcsid = parentSpec.value;
279 // Uncomment when app layer is ready to integrate
280 // Uncommented since refNames are currently only generated if not present - ADR CSPACE-3178
281 parentShortIdentifier = FETCH_SHORT_ID;
283 parentShortIdentifier = parentSpec.value;
284 String whereClause = buildWhereForAuthByName(parentSpec.value);
285 ServiceContext ctx = createServiceContext(getServiceName(), queryParams);
286 parentcsid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause); //FIXME: REM - If the parent has been soft-deleted, should we be looking for the item?
288 result.CSID = parentcsid;
289 result.shortIdentifier = parentShortIdentifier;
293 public String lookupItemCSID(String itemspecifier, String parentcsid, String method, String op, ServiceContext ctx)
294 throws DocumentException {
296 Specifier itemSpec = getSpecifier(itemspecifier, method, op);
297 if (itemSpec.form == SpecifierForm.CSID) {
298 itemcsid = itemSpec.value;
300 String itemWhereClause = buildWhereForAuthItemByName(itemSpec.value, parentcsid);
301 itemcsid = getRepositoryClient(ctx).findDocCSID(ctx, itemWhereClause); //FIXME: REM - Should we be looking for the 'wf_deleted' query param and filtering on it?
307 * Generally, callers will first call RefName.AuthorityItem.parse with a refName, and then
308 * use the returned item.inAuthority.resource and a resourceMap to get a service-specific
309 * Resource. They then call this method on that resource.
312 public DocumentModel getDocModelForAuthorityItem(RefName.AuthorityItem item)
313 throws Exception, DocumentNotFoundException {
317 String whereClause = buildWhereForAuthByName(item.getParentShortIdentifier());
318 // Ensure we have the right context.
319 ServiceContext ctx = createServiceContext(item.inAuthority.resource);
321 String parentcsid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause);
323 String itemWhereClause = buildWhereForAuthItemByName(item.getShortIdentifier(), parentcsid);
324 ctx = createServiceContext(getItemServiceName());
325 DocumentWrapper<DocumentModel> docWrapper = getRepositoryClient(ctx).findDoc(ctx, itemWhereClause);
326 DocumentModel docModel = docWrapper.getWrappedObject();
332 public Response createAuthority(String xmlPayload) {
334 PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
335 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(input);
336 DocumentHandler handler = createDocumentHandler(ctx);
337 String csid = getRepositoryClient(ctx).create(ctx, handler);
338 UriBuilder path = UriBuilder.fromResource(resourceClass);
339 path.path("" + csid);
340 Response response = Response.created(path.build()).build();
342 } catch (Exception e) {
343 throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
347 protected String buildWhereForAuthByName(String name) {
348 return authorityCommonSchemaName
349 + ":" + AuthorityJAXBSchema.SHORT_IDENTIFIER
353 protected String buildWhereForAuthItemByName(String name, String parentcsid) {
354 return authorityItemCommonSchemaName
355 + ":" + AuthorityItemJAXBSchema.SHORT_IDENTIFIER
356 + "='" + name + "' AND "
357 + authorityItemCommonSchemaName + ":"
358 + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
359 + "'" + parentcsid + "'";
363 * Gets the authority.
365 * @param specifier either a CSID or one of the urn forms
367 * @return the authority
372 public byte[] get( // getAuthority(
374 @PathParam("csid") String specifier) {
375 PoxPayloadOut result = null;
377 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
378 DocumentHandler handler = createDocumentHandler(ctx);
380 Specifier spec = getSpecifier(specifier, "getAuthority", "GET");
381 if (spec.form == SpecifierForm.CSID) {
382 if (logger.isDebugEnabled()) {
383 logger.debug("getAuthority with csid=" + spec.value);
385 getRepositoryClient(ctx).get(ctx, spec.value, handler);
387 String whereClause = buildWhereForAuthByName(spec.value);
388 DocumentFilter myFilter = new DocumentFilter(whereClause, 0, 1);
389 handler.setDocumentFilter(myFilter);
390 getRepositoryClient(ctx).get(ctx, handler);
392 result = ctx.getOutput();
394 } catch (Exception e) {
395 throw bigReThrow(e, ServiceMessages.GET_FAILED, specifier);
398 if (result == null) {
399 Response response = Response.status(Response.Status.NOT_FOUND).entity(
400 "Get failed, the requested Authority specifier:" + specifier + ": was not found.").type(
401 "text/plain").build();
402 throw new WebApplicationException(response);
405 return result.getBytes();
409 * Finds and populates the authority list.
413 * @return the authority list
416 @Produces("application/xml")
417 public AbstractCommonList getAuthorityList(@Context UriInfo ui) {
419 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
420 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
421 DocumentHandler handler = createDocumentHandler(ctx);
422 DocumentFilter myFilter = handler.getDocumentFilter();
423 // Need to make the default sort order for authority items
424 // be on the displayName field
425 String sortBy = queryParams.getFirst(IClientQueryParams.SORT_BY_PARAM);
426 if (sortBy == null || sortBy.isEmpty()) {
427 String qualifiedDisplayNameField = authorityCommonSchemaName + ":"
428 + AuthorityItemJAXBSchema.DISPLAY_NAME;
429 myFilter.setOrderByClause(qualifiedDisplayNameField);
431 String nameQ = queryParams.getFirst("refName");
433 myFilter.setWhereClause(authorityCommonSchemaName + ":refName='" + nameQ + "'");
435 getRepositoryClient(ctx).getFiltered(ctx, handler);
436 return (AbstractCommonList) handler.getCommonPartList();
437 } catch (Exception e) {
438 throw bigReThrow(e, ServiceMessages.GET_FAILED);
445 * @param specifier the csid or id
447 * @return the multipart output
451 public byte[] updateAuthority(
452 @PathParam("csid") String specifier,
454 PoxPayloadOut result = null;
456 PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
457 Specifier spec = getSpecifier(specifier, "updateAuthority", "UPDATE");
458 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(theUpdate);
459 DocumentHandler handler = createDocumentHandler(ctx);
461 if (spec.form == SpecifierForm.CSID) {
464 String whereClause = buildWhereForAuthByName(spec.value);
465 csid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause);
467 getRepositoryClient(ctx).update(ctx, csid, handler);
468 result = ctx.getOutput();
469 } catch (Exception e) {
470 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
472 return result.getBytes();
478 * @param csid the csid
480 * @return the response
484 public Response deleteAuthority(@PathParam("csid") String csid) {
485 if (logger.isDebugEnabled()) {
486 logger.debug("deleteAuthority with csid=" + csid);
489 ensureCSID(csid, ServiceMessages.DELETE_FAILED, "Authority.csid");
490 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
491 getRepositoryClient(ctx).delete(ctx, csid);
492 return Response.status(HttpResponseCodes.SC_OK).build();
493 } catch (Exception e) {
494 throw bigReThrow(e, ServiceMessages.DELETE_FAILED, csid);
498 /*************************************************************************
499 * Create an AuthorityItem - this is a sub-resource of Authority
500 * @param specifier either a CSID or one of the urn forms
501 * @return Authority item response
502 *************************************************************************/
504 @Path("{csid}/items")
505 public Response createAuthorityItem(@Context ResourceMap resourceMap, @Context UriInfo ui,
506 @PathParam("csid") String specifier, String xmlPayload) {
508 PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
509 ServiceContext ctx = createServiceContext(getItemServiceName(), input);
510 ctx.setResourceMap(resourceMap);
511 ctx.setUriInfo(ui); //Laramie
513 // Note: must have the parentShortId, to do the create.
514 CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(specifier, "createAuthorityItem", "CREATE_ITEM", null);
515 DocumentHandler handler = createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
516 String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
517 UriBuilder path = UriBuilder.fromResource(resourceClass);
518 path.path(parent.CSID + "/items/" + itemcsid);
519 Response response = Response.created(path.build()).build();
521 } catch (Exception e) {
522 throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
527 @Path("{csid}/items/{itemcsid}" + WorkflowClient.SERVICE_PATH)
528 public byte[] getItemWorkflow(
529 @PathParam("csid") String csid,
530 @PathParam("itemcsid") String itemcsid) {
531 PoxPayloadOut result = null;
534 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(getItemServiceName());
535 String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
537 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME);
538 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
539 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
540 getRepositoryClient(ctx).get(ctx, itemcsid, handler);
541 result = ctx.getOutput();
542 } catch (Exception e) {
543 throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
545 return result.getBytes();
549 @Path("{csid}/items/{itemcsid}" + WorkflowClient.SERVICE_PATH)
550 public byte[] updateWorkflow(
551 @PathParam("csid") String csid,
552 @PathParam("itemcsid") String itemcsid,
554 PoxPayloadOut result = null;
556 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(getItemServiceName());
557 String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
559 PoxPayloadIn workflowUpdate = new PoxPayloadIn(xmlPayload);
560 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, workflowUpdate);
561 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
562 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
563 getRepositoryClient(ctx).update(ctx, itemcsid, handler);
564 result = ctx.getOutput();
565 } catch (Exception e) {
566 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
568 return result.getBytes();
572 * Gets the authority item.
574 * @param parentspecifier either a CSID or one of the urn forms
575 * @param itemspecifier either a CSID or one of the urn forms
577 * @return the authority item
580 @Path("{csid}/items/{itemcsid}")
581 public byte[] getAuthorityItem(
582 @Context Request request,
584 @PathParam("csid") String parentspecifier,
585 @PathParam("itemcsid") String itemspecifier) {
586 PoxPayloadOut result = null;
588 JaxRsContext jaxRsContext = new JaxRsContext(request, ui);
589 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
590 String parentcsid = lookupParentCSID(parentspecifier, "getAuthorityItem(parent)", "GET_ITEM", queryParams);
592 RemoteServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
593 ctx = (RemoteServiceContext) createServiceContext(getItemServiceName(), queryParams);
594 ctx.setJaxRsContext(jaxRsContext);
596 ctx.setUriInfo(ui); //ARG! must pass this or subsequent calls will not have a ui.
598 // We omit the parentShortId, only needed when doing a create...
599 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null);
601 Specifier itemSpec = getSpecifier(itemspecifier, "getAuthorityItem(item)", "GET_ITEM");
602 if (itemSpec.form == SpecifierForm.CSID) {
603 getRepositoryClient(ctx).get(ctx, itemSpec.value, handler);
605 String itemWhereClause =
606 buildWhereForAuthItemByName(itemSpec.value, parentcsid);
607 DocumentFilter myFilter = new DocumentFilter(itemWhereClause, 0, 1);
608 handler.setDocumentFilter(myFilter);
609 getRepositoryClient(ctx).get(ctx, handler);
611 // TODO should we assert that the item is in the passed vocab?
612 result = ctx.getOutput();
613 } catch (Exception e) {
614 throw bigReThrow(e, ServiceMessages.GET_FAILED);
616 if (result == null) {
617 Response response = Response.status(Response.Status.NOT_FOUND).entity(
618 "Get failed, the requested AuthorityItem specifier:" + itemspecifier + ": was not found.").type(
619 "text/plain").build();
620 throw new WebApplicationException(response);
622 return result.getBytes();
626 * Gets the authorityItem list for the specified authority
627 * If partialPerm is specified, keywords will be ignored.
629 * @param specifier either a CSID or one of the urn forms
630 * @param partialTerm if non-null, matches partial terms
631 * @param keywords if non-null, matches terms in the keyword index for items
632 * @param ui passed to include additional parameters, like pagination controls
634 * @return the authorityItem list
637 @Path("{csid}/items")
638 @Produces("application/xml")
639 public AbstractCommonList getAuthorityItemList(@PathParam("csid") String specifier,
640 @Context UriInfo ui) {
642 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
643 String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
644 String termStatus = queryParams.getFirst(SEARCH_TYPE_TERMSTATUS);
645 String keywords = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
646 String advancedSearch = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_AS);
648 String qualifiedDisplayNameField = authorityItemCommonSchemaName + ":"
649 + AuthorityItemJAXBSchema.DISPLAY_NAME;
651 // Note that docType defaults to the ServiceName, so we're fine with that.
652 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
654 String parentcsid = lookupParentCSID(specifier, "getAuthorityItemList", "LIST", queryParams);
656 ctx = createServiceContext(getItemServiceName(), queryParams);
657 // We omit the parentShortId, only needed when doing a create...
658 DocumentHandler handler = createItemDocumentHandler(ctx,
660 DocumentFilter myFilter = handler.getDocumentFilter();
661 // Need to make the default sort order for authority items
662 // be on the displayName field
663 String sortBy = queryParams.getFirst(IClientQueryParams.SORT_BY_PARAM);
664 if (sortBy == null || sortBy.isEmpty()) {
665 myFilter.setOrderByClause(qualifiedDisplayNameField);
668 myFilter.appendWhereClause(authorityItemCommonSchemaName + ":"
669 + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
670 + "'" + parentcsid + "'",
671 IQueryManager.SEARCH_QUALIFIER_AND);
673 if (Tools.notBlank(termStatus)) {
674 // Start with the qualified termStatus field
675 String qualifiedTermStatusField = authorityItemCommonSchemaName + ":"
676 + AuthorityItemJAXBSchema.TERM_STATUS;
677 String[] filterTerms = termStatus.trim().split("\\|");
678 String tsClause = QueryManager.createWhereClauseToFilterFromStringList(qualifiedTermStatusField, filterTerms, IQueryManager.FILTER_EXCLUDE);
679 myFilter.appendWhereClause(tsClause, IQueryManager.SEARCH_QUALIFIER_AND);
682 // AND vocabularyitems_common:displayName LIKE '%partialTerm%'
683 // NOTE: Partial terms searches are mutually exclusive to keyword and advanced-search, but
684 // the PT query param trumps the KW and AS query params.
685 if (partialTerm != null && !partialTerm.isEmpty()) {
686 String ptClause = QueryManager.createWhereClauseForPartialMatch(
687 qualifiedDisplayNameField, partialTerm);
688 myFilter.appendWhereClause(ptClause, IQueryManager.SEARCH_QUALIFIER_AND);
689 } else if (keywords != null || advancedSearch != null) {
690 // String kwdClause = QueryManager.createWhereClauseFromKeywords(keywords);
691 // myFilter.appendWhereClause(kwdClause, IQueryManager.SEARCH_QUALIFIER_AND);
692 return search(ctx, handler, queryParams, keywords, advancedSearch);
694 if (logger.isDebugEnabled()) {
695 logger.debug("getAuthorityItemList filtered WHERE clause: "
696 + myFilter.getWhereClause());
698 getRepositoryClient(ctx).getFiltered(ctx, handler);
699 return (AbstractCommonList) handler.getCommonPartList();
700 } catch (Exception e) {
701 throw bigReThrow(e, ServiceMessages.LIST_FAILED);
706 * @return the name of the property used to specify references for items in this type of
707 * authority. For most authorities, it is ServiceBindingUtils.AUTH_REF_PROP ("authRef").
708 * Some types (like Vocabulary) use a separate property.
710 protected String getRefPropName() {
711 return ServiceBindingUtils.AUTH_REF_PROP;
715 * Gets the entities referencing this Authority item instance. The service type
716 * can be passed as a query param "type", and must match a configured type
717 * for the service bindings. If not set, the type defaults to
718 * ServiceBindingUtils.SERVICE_TYPE_PROCEDURE.
720 * @param parentspecifier either a CSID or one of the urn forms
721 * @param itemspecifier either a CSID or one of the urn forms
724 * @return the info for the referencing objects
727 @Path("{csid}/items/{itemcsid}/refObjs")
728 @Produces("application/xml")
729 public AuthorityRefDocList getReferencingObjects(
730 @PathParam("csid") String parentspecifier,
731 @PathParam("itemcsid") String itemspecifier,
732 @Context UriInfo ui) {
733 AuthorityRefDocList authRefDocList = null;
735 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
737 String parentcsid = lookupParentCSID(parentspecifier, "getReferencingObjects(parent)", "GET_ITEM_REF_OBJS", queryParams);
739 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), queryParams);
740 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "getReferencingObjects(item)", "GET_ITEM_REF_OBJS", ctx);
742 // Note that we have to create the service context for the Items, not the main service
743 // We omit the parentShortId, only needed when doing a create...
744 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null);
745 RepositoryClient repoClient = getRepositoryClient(ctx);
746 DocumentFilter myFilter = handler.getDocumentFilter();
747 String serviceType = ServiceBindingUtils.SERVICE_TYPE_PROCEDURE;
748 List<String> list = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP);
750 serviceType = list.get(0);
752 DocumentWrapper<DocumentModel> docWrapper = repoClient.getDoc(ctx, itemcsid);
753 DocumentModel docModel = docWrapper.getWrappedObject();
754 String refName = (String) docModel.getPropertyValue(AuthorityItemJAXBSchema.REF_NAME);
756 // Could be smarter about using the list from above, and/or allowing multiple
757 ArrayList<String> serviceTypes = new ArrayList<String>(1);
758 serviceTypes.add(serviceType);
760 authRefDocList = RefNameServiceUtils.getAuthorityRefDocs(ctx,
765 myFilter.getPageSize(), myFilter.getStartPage(), true /*computeTotal*/);
766 } catch (Exception e) {
767 throw bigReThrow(e, ServiceMessages.GET_FAILED);
769 if (authRefDocList == null) {
770 Response response = Response.status(Response.Status.NOT_FOUND).entity(
771 "Get failed, the requested Item CSID:" + itemspecifier + ": was not found.").type(
772 "text/plain").build();
773 throw new WebApplicationException(response);
775 return authRefDocList;
779 * Gets the authority terms used in the indicated Authority item.
781 * @param parentspecifier either a CSID or one of the urn forms
782 * @param itemspecifier either a CSID or one of the urn forms
783 * @param ui passed to include additional parameters, like pagination controls
785 * @return the authority refs for the Authority item.
788 @Path("{csid}/items/{itemcsid}/authorityrefs")
789 @Produces("application/xml")
790 public AuthorityRefList getAuthorityItemAuthorityRefs(
791 @PathParam("csid") String parentspecifier,
792 @PathParam("itemcsid") String itemspecifier,
793 @Context UriInfo ui) {
794 AuthorityRefList authRefList = null;
796 // Note that we have to create the service context for the Items, not the main service
797 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
798 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
800 String parentcsid = lookupParentCSID(parentspecifier, "getAuthorityItemAuthRefs(parent)", "GET_ITEM_AUTH_REFS", queryParams);
802 ctx = createServiceContext(getItemServiceName(), queryParams);
803 // We omit the parentShortId, only needed when doing a create...
804 DocumentModelHandler handler =
805 (DocumentModelHandler)createItemDocumentHandler(ctx, parentcsid, null);
807 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "getAuthorityItemAuthRefs(item)", "GET_ITEM_AUTH_REFS", ctx);
809 List<RefNameServiceUtils.AuthRefConfigInfo> authRefsInfo = RefNameServiceUtils.getConfiguredAuthorityRefs(ctx);
810 authRefList = handler.getAuthorityRefs(itemcsid, authRefsInfo);
811 } catch (Exception e) {
812 throw bigReThrow(e, ServiceMessages.GET_FAILED + " parentspecifier: " + parentspecifier + " itemspecifier:" + itemspecifier);
818 * Update authorityItem.
820 * @param parentspecifier either a CSID or one of the urn forms
821 * @param itemspecifier either a CSID or one of the urn forms
823 * @return the multipart output
826 @Path("{csid}/items/{itemcsid}")
827 public byte[] updateAuthorityItem(
828 @Context ResourceMap resourceMap,
830 @PathParam("csid") String parentspecifier,
831 @PathParam("itemcsid") String itemspecifier,
833 PoxPayloadOut result = null;
835 PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
836 // Note that we have to create the service context for the Items, not the main service
837 //Laramie CSPACE-3175. passing null for queryParams, because prior to this refactor, the code moved to lookupParentCSID in this instance called the version of getServiceContext() that passes null
838 String parentcsid = lookupParentCSID(parentspecifier, "updateAuthorityItem(parent)", "UPDATE_ITEM", null);
840 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), theUpdate);
841 ctx.setResourceMap(resourceMap);
842 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "updateAuthorityItem(item)", "UPDATE_ITEM", ctx);
844 // We omit the parentShortId, only needed when doing a create...
845 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null);
847 getRepositoryClient(ctx).update(ctx, itemcsid, handler);
848 result = ctx.getOutput();
850 } catch (Exception e) {
851 throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
853 return result.getBytes();
857 * Delete authorityItem.
859 * @param parentcsid the parentcsid
860 * @param itemcsid the itemcsid
862 * @return the response
865 @Path("{csid}/items/{itemcsid}")
866 public Response deleteAuthorityItem(
867 @PathParam("csid") String parentcsid,
868 @PathParam("itemcsid") String itemcsid) {
870 if (logger.isDebugEnabled()) {
871 logger.debug("deleteAuthorityItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
874 ensureCSID(parentcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.parentcsid");
875 ensureCSID(itemcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.itemcsid");
876 //Laramie, removing this catch, since it will surely fail below, since itemcsid or parentcsid will be null.
877 // }catch (Throwable t){
878 // System.out.println("ERROR in setting up DELETE: "+t);
881 // Note that we have to create the service context for the Items, not the main service
882 ServiceContext ctx = createServiceContext(getItemServiceName());
883 getRepositoryClient(ctx).delete(ctx, itemcsid);
884 return Response.status(HttpResponseCodes.SC_OK).build();
885 } catch (Exception e) {
886 throw bigReThrow(e, ServiceMessages.DELETE_FAILED + " itemcsid: " + itemcsid + " parentcsid:" + parentcsid);
889 public final static String hierarchy = "hierarchy";
892 @Path("{csid}/items/{itemcsid}/" + hierarchy)
893 @Produces("application/xml")
894 public String getHierarchy(@PathParam("csid") String csid,
895 @PathParam("itemcsid") String itemcsid,
896 @Context UriInfo ui) throws Exception {
898 // All items in dive can look at their child uri's to get uri. So we calculate the very first one. We could also do a GET and look at the common part uri field, but why...?
899 String calledUri = ui.getPath();
900 String uri = "/" + calledUri.substring(0, (calledUri.length() - ("/" + hierarchy).length()));
901 ServiceContext ctx = createServiceContext(getItemServiceName());
903 String direction = ui.getQueryParameters().getFirst(Hierarchy.directionQP);
904 if (Tools.notBlank(direction) && Hierarchy.direction_parents.equals(direction)) {
905 return Hierarchy.surface(ctx, itemcsid, uri);
907 return Hierarchy.dive(ctx, itemcsid, uri);
909 } catch (Exception e) {
910 throw bigReThrow(e, "Error showing hierarchy", itemcsid);