]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
328067fe09920ecdba9f75d1b7ca07c852ca509d
[tmp/jakarta-migration.git] /
1 /**
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:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
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.
23  */
24 package org.collectionspace.services.common.vocabulary;
25
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.ServiceMain;
34 import org.collectionspace.services.common.ServiceMessages;
35 import org.collectionspace.services.common.XmlTools;
36 import org.collectionspace.services.common.api.RefName;
37 import org.collectionspace.services.common.api.Tools;
38 import org.collectionspace.services.common.authorityref.AuthorityRefDocList;
39 import org.collectionspace.services.common.authorityref.AuthorityRefList;
40 import org.collectionspace.services.common.context.JaxRsContext;
41 import org.collectionspace.services.common.context.MultipartServiceContext;
42 import org.collectionspace.services.common.context.MultipartServiceContextImpl;
43 import org.collectionspace.services.common.context.RemoteServiceContext;
44 import org.collectionspace.services.common.context.ServiceBindingUtils;
45 import org.collectionspace.services.common.context.ServiceContext;
46 import org.collectionspace.services.common.document.DocumentException;
47 import org.collectionspace.services.common.document.DocumentFilter;
48 import org.collectionspace.services.common.document.DocumentHandler;
49 import org.collectionspace.services.common.document.DocumentNotFoundException;
50 import org.collectionspace.services.common.document.DocumentWrapper;
51 import org.collectionspace.services.common.query.QueryManager;
52 import org.collectionspace.services.common.repository.RepositoryClient;
53 import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
54 import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
55 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
56 import org.collectionspace.services.jaxb.AbstractCommonList;
57 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
58 import org.collectionspace.services.relation.RelationResource;
59 import org.collectionspace.services.relation.RelationsCommonList;
60 import org.collectionspace.services.relation.RelationshipType;
61 import org.jboss.resteasy.util.HttpResponseCodes;
62 import org.nuxeo.ecm.core.api.DocumentModel;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 import javax.ws.rs.Consumes;
67 import javax.ws.rs.DELETE;
68 import javax.ws.rs.GET;
69 import javax.ws.rs.POST;
70 import javax.ws.rs.PUT;
71 import javax.ws.rs.Path;
72 import javax.ws.rs.PathParam;
73 import javax.ws.rs.Produces;
74 import javax.ws.rs.QueryParam;
75 import javax.ws.rs.WebApplicationException;
76 import javax.ws.rs.core.Context;
77 import javax.ws.rs.core.MultivaluedMap;
78 import javax.ws.rs.core.Request;
79 import javax.ws.rs.core.Response;
80 import javax.ws.rs.core.UriBuilder;
81 import javax.ws.rs.core.UriInfo;
82
83 import java.util.ArrayList;
84 import java.util.List;
85
86 /**
87  * The Class AuthorityResource.
88  */
89 @Consumes("application/xml")
90 @Produces("application/xml")
91 public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
92         extends ResourceBase {
93
94         protected Class<AuthCommon> authCommonClass;
95         protected Class<?> resourceClass;
96         protected String authorityCommonSchemaName;
97         protected String authorityItemCommonSchemaName;
98
99         final static ClientType CLIENT_TYPE = ServiceMain.getInstance().getClientType();
100         
101         final static String URN_PREFIX = "urn:cspace:";
102         final static int URN_PREFIX_LEN = URN_PREFIX.length();
103         final static String URN_PREFIX_NAME = "name(";
104         final static int URN_NAME_PREFIX_LEN = URN_PREFIX_LEN + URN_PREFIX_NAME.length();
105         final static String URN_PREFIX_ID = "id(";
106         final static int URN_ID_PREFIX_LEN = URN_PREFIX_LEN + URN_PREFIX_ID.length();
107         final static String FETCH_SHORT_ID = "_fetch_";
108         
109     final Logger logger = LoggerFactory.getLogger(AuthorityResource.class);
110     
111     public enum SpecifierForm { CSID, URN_NAME };
112     
113     public class Specifier {
114         public SpecifierForm form;
115         public String value;
116         Specifier(SpecifierForm form, String value) {
117                 this.form = form;
118                 this.value = value;
119         }
120     }
121     
122     protected Specifier getSpecifier(String specifierIn, String method, String op) throws WebApplicationException {
123                 if (logger.isDebugEnabled()) {
124                         logger.debug("getSpecifier called by: "+method+" with specifier: "+specifierIn);
125                 }
126                 if (specifierIn != null) {
127                         if(!specifierIn.startsWith(URN_PREFIX)) {
128                                 // We'll assume it is a CSID and complain if it does not match
129                                 return new Specifier(SpecifierForm.CSID, specifierIn);
130                         } else { 
131                                 if(specifierIn.startsWith(URN_PREFIX_NAME, URN_PREFIX_LEN)) {
132                                         int closeParen = specifierIn.indexOf(')', URN_NAME_PREFIX_LEN);
133                                         if(closeParen>=0) {
134                                                 return new Specifier(SpecifierForm.URN_NAME,
135                                                                         specifierIn.substring(URN_NAME_PREFIX_LEN, closeParen));
136                                         }
137                                 } else if(specifierIn.startsWith(URN_PREFIX_ID, URN_PREFIX_LEN)) {
138                                         int closeParen = specifierIn.indexOf(')', URN_ID_PREFIX_LEN);
139                                         if(closeParen>=0) {
140                                                 return new Specifier(SpecifierForm.CSID,
141                                                                 specifierIn.substring(URN_ID_PREFIX_LEN, closeParen));
142                                         }
143                                 }
144                         }
145                 }
146                 logger.error(method+": bad or missing specifier!");
147                 Response response = Response.status(Response.Status.BAD_REQUEST).entity(
148                                 op+" failed on bad or missing Authority specifier").type(
149                                 "text/plain").build();
150                 throw new WebApplicationException(response);
151     }
152
153     /**
154          * Instantiates a new Authority resource.
155          */
156         public AuthorityResource(Class<AuthCommon> authCommonClass, Class<?> resourceClass,
157                         String authorityCommonSchemaName, String authorityItemCommonSchemaName) {
158                 this.authCommonClass = authCommonClass;
159                 this.resourceClass = resourceClass;
160                 this.authorityCommonSchemaName = authorityCommonSchemaName;
161                 this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
162         }
163         
164         public abstract String getItemServiceName();
165
166         @Override
167         protected String getVersionString() {
168                 return "$LastChangedRevision: 2617 $";
169         }
170
171         @Override
172         public Class<AuthCommon> getCommonPartClass() {
173                 return authCommonClass;
174         }
175
176         /**
177          * Creates the item document handler.
178          * 
179          * @param ctx the ctx
180          * @param inAuthority the in vocabulary
181          * 
182          * @return the document handler
183          * 
184          * @throws Exception the exception
185          */
186         protected DocumentHandler createItemDocumentHandler(
187                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
188                         String inAuthority, String parentShortIdentifier)
189         throws Exception {
190                 String authorityRefNameBase;
191                 AuthorityItemDocumentModelHandler<?> docHandler;
192                 
193                 if(parentShortIdentifier==null) {
194                         authorityRefNameBase = null;
195                 } else {
196                         ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = 
197                                 createServiceContext(getServiceName());
198                         if(parentShortIdentifier.equals(FETCH_SHORT_ID)) {
199                                 // Get from parent document
200                                 parentShortIdentifier = getAuthShortIdentifier(parentCtx, inAuthority);
201                         }
202                         authorityRefNameBase = buildAuthorityRefNameBase(parentCtx, parentShortIdentifier);
203                 }
204
205                 docHandler = (AuthorityItemDocumentModelHandler<?>)createDocumentHandler(ctx,
206                                 ctx.getCommonPartLabel(getItemServiceName()),
207                                 authCommonClass);       
208                 docHandler.setInAuthority(inAuthority);
209                 docHandler.setAuthorityRefNameBase(authorityRefNameBase);
210
211                 return docHandler;
212         }
213         
214     public String getAuthShortIdentifier(
215             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String authCSID)
216             throws DocumentNotFoundException, DocumentException {
217         String shortIdentifier = null;
218         try {
219             DocumentWrapper<DocumentModel> wrapDoc = getRepositoryClient(ctx).getDocFromCsid(ctx, authCSID);
220             AuthorityDocumentModelHandler<?> handler = 
221                 (AuthorityDocumentModelHandler<?>)createDocumentHandler(ctx);
222             shortIdentifier = handler.getShortIdentifier(wrapDoc, authorityCommonSchemaName);
223         } catch (Exception e) {
224             if (logger.isDebugEnabled()) {
225                 logger.debug("Caught exception ", e);
226             }
227             throw new DocumentException(e);
228         }
229         return shortIdentifier;
230     }
231
232         
233         protected String buildAuthorityRefNameBase(
234                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String shortIdentifier) {
235         RefName.Authority authority = RefName.buildAuthority(ctx.getTenantName(),
236                 ctx.getServiceName(), shortIdentifier, null);
237         return authority.toString();
238         }
239
240     public static class CsidAndShortIdentifier {
241         String CSID;
242         String shortIdentifier;
243     }
244
245     public String lookupParentCSID (String parentspecifier, String method, String op, MultivaluedMap<String, String> queryParams)
246     throws Exception {
247          CsidAndShortIdentifier tempResult = lookupParentCSIDAndShortIdentifer(parentspecifier, method, op, queryParams);
248         return tempResult.CSID;
249     }
250
251     public CsidAndShortIdentifier lookupParentCSIDAndShortIdentifer (String parentspecifier, String method, String op, MultivaluedMap<String, String> queryParams)
252     throws Exception {
253         CsidAndShortIdentifier result = new CsidAndShortIdentifier();
254         Specifier parentSpec = getSpecifier(parentspecifier, method, op);
255         // Note that we have to create the service context for the Items, not the main service
256         String parentcsid;
257         String parentShortIdentifier;
258         if(parentSpec.form==SpecifierForm.CSID) {
259             parentShortIdentifier = null;
260             parentcsid = parentSpec.value;
261             // Uncomment when app layer is ready to integrate
262                 // parentShortIdentifier = FETCH_SHORT_ID;
263         } else {
264             parentShortIdentifier = parentSpec.value;
265             String whereClause = buildWhereForAuthByName(parentSpec.value);
266             ServiceContext ctx = createServiceContext(getServiceName(), queryParams);
267             parentcsid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause); //FIXME: REM - If the parent has been soft-deleted, should we be looking for the item?
268         }
269         result.CSID = parentcsid;
270         return result;
271     }
272
273     public String lookupItemCSID (String itemspecifier, String parentcsid, String method, String op, ServiceContext ctx)
274     throws DocumentException {
275         String itemcsid;
276         Specifier itemSpec = getSpecifier(itemspecifier, method, op);
277         if(itemSpec.form==SpecifierForm.CSID) {
278             itemcsid = itemSpec.value;
279         } else {
280             String itemWhereClause = buildWhereForAuthItemByName(itemSpec.value, parentcsid);
281             itemcsid = getRepositoryClient(ctx).findDocCSID(ctx, itemWhereClause); //FIXME: REM - Should we be looking for the 'wf_deleted' query param and filtering on it?
282         }
283         return itemcsid;
284     }
285
286         @POST
287         public Response createAuthority(String xmlPayload) {
288                 try {
289                         PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
290                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(input);
291                         DocumentHandler handler = createDocumentHandler(ctx);
292                         String csid = getRepositoryClient(ctx).create(ctx, handler);
293                         UriBuilder path = UriBuilder.fromResource(resourceClass);
294                         path.path("" + csid);
295                         Response response = Response.created(path.build()).build();
296                         return response;
297                 } catch (Exception e) {
298                         throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
299                 }
300         }
301
302         protected String buildWhereForAuthByName(String name) {
303                 return authorityCommonSchemaName+
304                                 ":"+AuthorityJAXBSchema.SHORT_IDENTIFIER+
305                                 "='"+name+"'";
306         }
307
308         protected String buildWhereForAuthItemByName(String name, String parentcsid) {
309         return
310                 authorityItemCommonSchemaName+
311                 ":"+AuthorityItemJAXBSchema.SHORT_IDENTIFIER+
312                 "='"+name+"' AND "
313                         + authorityItemCommonSchemaName + ":"
314                         + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
315                         + "'" + parentcsid + "'";
316         }
317
318         /**
319          * Gets the authority.
320          * 
321          * @param specifier either a CSID or one of the urn forms
322          * 
323          * @return the authority
324          */
325         @GET
326         @Path("{csid}")
327         @Override
328         public byte[] get( // getAuthority(
329                 @Context UriInfo ui,
330                         @PathParam("csid") String specifier) {
331                 PoxPayloadOut result = null;
332                 try {
333                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
334             DocumentHandler handler = createDocumentHandler(ctx);
335
336             Specifier spec = getSpecifier(specifier, "getAuthority", "GET");
337             if(spec.form == SpecifierForm.CSID) {
338                                 if (logger.isDebugEnabled()) {
339                                         logger.debug("getAuthority with csid=" + spec.value);
340                                 }
341                                 getRepositoryClient(ctx).get(ctx, spec.value, handler);
342                         } else {
343                                 String whereClause = buildWhereForAuthByName(spec.value);
344                                 DocumentFilter myFilter = new DocumentFilter(whereClause, 0, 1);
345                                 handler.setDocumentFilter(myFilter);
346                                 getRepositoryClient(ctx).get(ctx, handler);
347                         }
348                         result = ctx.getOutput();
349
350                 } catch (Exception e) {
351             throw bigReThrow(e, ServiceMessages.GET_FAILED, specifier);
352                 }
353
354                 if (result == null) {
355                         Response response = Response.status(Response.Status.NOT_FOUND).entity(
356                                         "Get failed, the requested Authority specifier:" + specifier + ": was not found.").type(
357                                         "text/plain").build();
358                         throw new WebApplicationException(response);
359                 }
360
361                 return result.getBytes();
362         }
363
364         /**
365          * Finds and populates the authority list.
366          * 
367          * @param ui the ui
368          * 
369          * @return the authority list
370          */
371     @GET
372     @Produces("application/xml")
373     public AbstractCommonList getAuthorityList(@Context UriInfo ui) {
374                 try {
375                         MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
376                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(queryParams);
377                         DocumentHandler handler = createDocumentHandler(ctx);
378                         DocumentFilter myFilter = handler.getDocumentFilter();
379                         String nameQ = queryParams.getFirst("refName");
380                         if (nameQ != null) {
381                                 myFilter.setWhereClause(authorityCommonSchemaName+":refName='" + nameQ + "'");
382                         }
383                         getRepositoryClient(ctx).getFiltered(ctx, handler);
384                         return (AbstractCommonList) handler.getCommonPartList();
385         } catch (Exception e) {
386             throw bigReThrow(e, ServiceMessages.GET_FAILED);
387                 }
388         }
389
390         /**
391          * Update authority.
392          *
393          * @param specifier the csid or id
394          *
395          * @return the multipart output
396          */
397         @PUT
398         @Path("{csid}")
399         public byte[] updateAuthority(
400                         @PathParam("csid") String specifier,
401                         String xmlPayload) {
402                 PoxPayloadOut result = null;
403                 try {
404                         PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
405                         Specifier spec = getSpecifier(specifier, "updateAuthority", "UPDATE");
406                         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(theUpdate);
407                         DocumentHandler handler = createDocumentHandler(ctx);
408                         String csid;
409                         if(spec.form==SpecifierForm.CSID) {
410                                 csid = spec.value;
411                         } else {
412                                 String whereClause = buildWhereForAuthByName(spec.value);
413                                 csid = getRepositoryClient(ctx).findDocCSID(ctx, whereClause);
414                         }
415                         getRepositoryClient(ctx).update(ctx, csid, handler);
416                         result = ctx.getOutput();
417                 } catch (Exception e) {
418                         throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
419                 }
420                 return result.getBytes();
421         }
422
423         /**
424          * Delete authority.
425          * 
426          * @param csid the csid
427          * 
428          * @return the response
429          */
430         @DELETE
431         @Path("{csid}")
432         public Response deleteAuthority(@PathParam("csid") String csid) {
433                 if (logger.isDebugEnabled()) {
434                         logger.debug("deleteAuthority with csid=" + csid);
435                 }
436                 try {
437             ensureCSID(csid, ServiceMessages.DELETE_FAILED, "Authority.csid");
438             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
439                         getRepositoryClient(ctx).delete(ctx, csid);
440                         return Response.status(HttpResponseCodes.SC_OK).build();
441                 } catch (Exception e) {
442             throw bigReThrow(e, ServiceMessages.DELETE_FAILED, csid);
443                 }
444         }
445
446         /*************************************************************************
447          * Create an AuthorityItem - this is a sub-resource of Authority
448          * @param specifier either a CSID or one of the urn forms
449          * @return Authority item response
450          *************************************************************************/
451         @POST
452         @Path("{csid}/items")
453         public Response createAuthorityItem(@Context UriInfo ui, @PathParam("csid") String specifier, String xmlPayload) {
454                 try {
455                         PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
456             ServiceContext ctx = createServiceContext(getItemServiceName(), input);
457             ctx.setUriInfo(ui);    //Laramie
458
459             // Note: must have the parentShortId, to do the create.
460             CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(specifier,"createAuthorityItem", "CREATE_ITEM", null);
461             DocumentHandler handler = createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
462                         String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
463                         UriBuilder path = UriBuilder.fromResource(resourceClass);
464                         path.path(parent.CSID + "/items/" + itemcsid);
465                         Response response = Response.created(path.build()).build();
466                         return response;
467                 } catch (Exception e) {
468             throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
469                 }
470         }
471         
472     @GET
473     @Path("{csid}/items/{itemcsid}" + WorkflowClient.SERVICE_PATH)
474     public byte[] getItemWorkflow(
475             @PathParam("csid") String csid,
476             @PathParam("itemcsid") String itemcsid) {
477         PoxPayloadOut result = null;
478
479         try {           
480             ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(getItemServiceName());
481             String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
482                 
483                 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME);
484                 WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
485                 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
486             getRepositoryClient(ctx).get(ctx, itemcsid, handler);
487             result = ctx.getOutput();
488         } catch (Exception e) {
489             throw bigReThrow(e, ServiceMessages.READ_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
490         }
491         return result.getBytes();
492     }
493
494     @PUT
495     @Path("{csid}/items/{itemcsid}" + WorkflowClient.SERVICE_PATH)
496     public byte[] updateWorkflow(
497             @PathParam("csid") String csid,
498             @PathParam("itemcsid") String itemcsid,
499                 String xmlPayload) {
500         PoxPayloadOut result = null;
501         try {
502                 ServiceContext<PoxPayloadIn, PoxPayloadOut> parentCtx = createServiceContext(getItemServiceName());
503                 String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName();
504
505                 PoxPayloadIn workflowUpdate = new PoxPayloadIn(xmlPayload);
506                 MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, workflowUpdate);
507             WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx);
508                 ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace
509                 getRepositoryClient(ctx).update(ctx, itemcsid, handler);
510                 result = ctx.getOutput();
511         } catch (Exception e) {
512             throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid);
513         }
514         return result.getBytes();
515     }
516
517
518         /**
519          * Gets the authority item.
520          * 
521          * @param parentspecifier either a CSID or one of the urn forms
522          * @param itemspecifier either a CSID or one of the urn forms
523          * 
524          * @return the authority item
525          */
526         @GET
527         @Path("{csid}/items/{itemcsid}")
528         public byte[] getAuthorityItem(
529                 @Context Request request,
530             @Context UriInfo ui,
531                         @PathParam("csid") String parentspecifier,
532                         @PathParam("itemcsid") String itemspecifier) {
533                 PoxPayloadOut result = null;
534                 try {                   
535                 JaxRsContext jaxRsContext = new JaxRsContext(request, ui);
536             MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
537             String parentcsid = lookupParentCSID(parentspecifier, "getAuthorityItem(parent)", "GET_ITEM", queryParams);
538
539             RemoteServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
540                         ctx = (RemoteServiceContext)createServiceContext(getItemServiceName(), queryParams);
541                         ctx.setJaxRsContext(jaxRsContext);
542
543                         ctx.setUriInfo(ui); //ARG!   must pass this or subsequent calls will not have a ui.
544
545                         // We omit the parentShortId, only needed when doing a create...
546                         DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null);
547
548             Specifier itemSpec = getSpecifier(itemspecifier, "getAuthorityItem(item)", "GET_ITEM");
549                         if(itemSpec.form==SpecifierForm.CSID) {
550                                 getRepositoryClient(ctx).get(ctx, itemSpec.value, handler);
551                         } else {
552                                 String itemWhereClause = 
553                                         buildWhereForAuthItemByName(itemSpec.value, parentcsid);
554                     DocumentFilter myFilter = new DocumentFilter(itemWhereClause, 0, 1);
555                     handler.setDocumentFilter(myFilter);
556                     getRepositoryClient(ctx).get(ctx, handler);
557                         }
558                         // TODO should we assert that the item is in the passed vocab?
559                         result = ctx.getOutput();
560                 } catch (Exception e) {
561                         throw bigReThrow(e, ServiceMessages.GET_FAILED);
562                 }
563                 if (result == null) {
564                         Response response = Response.status(Response.Status.NOT_FOUND).entity(
565                                         "Get failed, the requested AuthorityItem specifier:" + itemspecifier + ": was not found.").type(
566                                         "text/plain").build();
567                         throw new WebApplicationException(response);
568                 }
569                 return result.getBytes();
570         }
571
572         /**
573          * Gets the authorityItem list for the specified authority
574          * If partialPerm is specified, keywords will be ignored.
575          * 
576          * @param specifier either a CSID or one of the urn forms
577          * @param partialTerm if non-null, matches partial terms
578          * @param keywords if non-null, matches terms in the keyword index for items
579          * @param ui passed to include additional parameters, like pagination controls
580          * 
581          * @return the authorityItem list
582          */
583         @GET
584         @Path("{csid}/items")
585         @Produces("application/xml")
586         public AbstractCommonList getAuthorityItemList(@PathParam("csid") String specifier,
587                         @Context UriInfo ui) {
588                 try {
589                         MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
590                 String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
591                 String keywords = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
592                 String advancedSearch = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_AS);
593                 
594                 String qualifiedDisplayNameField = authorityItemCommonSchemaName + ":"
595                                                                                         + AuthorityItemJAXBSchema.DISPLAY_NAME;
596                 
597             // Note that docType defaults to the ServiceName, so we're fine with that.
598             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
599
600             String parentcsid = lookupParentCSID(specifier, "getAuthorityItemList", "LIST", queryParams);
601
602                         ctx = createServiceContext(getItemServiceName(), queryParams);
603                         // We omit the parentShortId, only needed when doing a create...
604                         DocumentHandler handler = createItemDocumentHandler(ctx, 
605                                                                                 parentcsid, null);
606                         DocumentFilter myFilter = handler.getDocumentFilter();
607                 // Need to make the default sort order for authority items
608                         // be on the displayName field
609                 String sortBy = queryParams.getFirst(IClientQueryParams.SORT_BY_PARAM);
610                 if(sortBy==null || sortBy.isEmpty()) {
611                         myFilter.setOrderByClause(qualifiedDisplayNameField);
612                 }
613                         
614                         myFilter.appendWhereClause(authorityItemCommonSchemaName + ":" +
615                                         AuthorityItemJAXBSchema.IN_AUTHORITY + "=" + 
616                                         "'" + parentcsid + "'",
617                                         IQueryManager.SEARCH_QUALIFIER_AND);
618
619                         // AND vocabularyitems_common:displayName LIKE '%partialTerm%'
620                         // NOTE: Partial terms searches are mutually exclusive to keyword and advanced-search, but
621                         // the PT query param trumps the KW and AS query params.
622                         if (partialTerm != null && !partialTerm.isEmpty()) {
623                                 String ptClause = QueryManager.createWhereClauseForPartialMatch(
624                                                 qualifiedDisplayNameField, partialTerm );
625                                 myFilter.appendWhereClause(ptClause, IQueryManager.SEARCH_QUALIFIER_AND);
626                         } else if (keywords != null || advancedSearch != null) {
627 //                              String kwdClause = QueryManager.createWhereClauseFromKeywords(keywords);
628 //                              myFilter.appendWhereClause(kwdClause, IQueryManager.SEARCH_QUALIFIER_AND);
629                                 return search(ctx, handler, queryParams, keywords, advancedSearch);
630                         }
631                         if (logger.isDebugEnabled()) {
632                                 logger.debug("getAuthorityItemList filtered WHERE clause: "
633                                                 + myFilter.getWhereClause());
634                         }
635                         getRepositoryClient(ctx).getFiltered(ctx, handler);
636                         return (AbstractCommonList) handler.getCommonPartList();
637                 } catch (Exception e) {
638                         throw bigReThrow(e, ServiceMessages.LIST_FAILED);
639                 }
640         }
641
642     /**
643      * Gets the entities referencing this Authority item instance. The service type
644      * can be passed as a query param "type", and must match a configured type
645      * for the service bindings. If not set, the type defaults to
646      * ServiceBindingUtils.SERVICE_TYPE_PROCEDURE.
647      *
648          * @param parentspecifier either a CSID or one of the urn forms
649          * @param itemspecifier either a CSID or one of the urn forms
650      * @param ui the ui
651      * 
652      * @return the info for the referencing objects
653      */
654     @GET
655     @Path("{csid}/items/{itemcsid}/refObjs")
656     @Produces("application/xml")
657     public AuthorityRefDocList getReferencingObjects(
658                         @PathParam("csid") String parentspecifier,
659                         @PathParam("itemcsid") String itemspecifier,
660                 @Context UriInfo ui) {
661         AuthorityRefDocList authRefDocList = null;
662         try {
663                 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
664
665             String parentcsid = lookupParentCSID(parentspecifier, "getReferencingObjects(parent)", "GET_ITEM_REF_OBJS", queryParams);
666
667             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), queryParams);
668             String itemcsid = lookupItemCSID(itemspecifier, parentcsid,  "getReferencingObjects(item)", "GET_ITEM_REF_OBJS", ctx);
669
670             // Note that we have to create the service context for the Items, not the main service
671                         // We omit the parentShortId, only needed when doing a create...
672                 DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null);
673                 RepositoryClient repoClient = getRepositoryClient(ctx); 
674                 DocumentFilter myFilter = handler.getDocumentFilter();
675                 String serviceType = ServiceBindingUtils.SERVICE_TYPE_PROCEDURE;
676                 List<String> list = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP);
677                 if (list != null) {
678                         serviceType = list.get(0);
679                 }
680                 DocumentWrapper<DocumentModel> docWrapper = repoClient.getDoc(ctx, itemcsid);
681                 DocumentModel docModel = docWrapper.getWrappedObject();
682                 String refName = (String)docModel.getPropertyValue(AuthorityItemJAXBSchema.REF_NAME);
683
684                 authRefDocList = RefNameServiceUtils.getAuthorityRefDocs(ctx,
685                                 repoClient, 
686                                 serviceType,
687                                 refName,
688                                 myFilter.getPageSize(), myFilter.getStartPage(), true /*computeTotal*/ );
689         } catch (Exception e) {
690                         throw bigReThrow(e, ServiceMessages.GET_FAILED);
691                 }
692         if (authRefDocList == null) {
693                 Response response = Response.status(Response.Status.NOT_FOUND).entity(
694                                 "Get failed, the requested Item CSID:" + itemspecifier + ": was not found.").type(
695                                 "text/plain").build();
696                 throw new WebApplicationException(response);
697         }
698         return authRefDocList;
699     }
700
701     /**
702      * Gets the authority terms used in the indicated Authority item.
703      *
704          * @param parentspecifier either a CSID or one of the urn forms
705          * @param itemspecifier either a CSID or one of the urn forms
706          * @param ui passed to include additional parameters, like pagination controls
707      *
708      * @return the authority refs for the Authority item.
709      */
710     @GET
711     @Path("{csid}/items/{itemcsid}/authorityrefs")
712     @Produces("application/xml")
713     public AuthorityRefList getAuthorityItemAuthorityRefs(
714                 @PathParam("csid") String parentspecifier,
715                 @PathParam("itemcsid") String itemspecifier,
716                 @Context UriInfo ui) {
717         AuthorityRefList authRefList = null;
718         try {
719                         // Note that we have to create the service context for the Items, not the main service
720             MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
721             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
722
723             String parentcsid = lookupParentCSID(parentspecifier, "getAuthorityItemAuthRefs(parent)", "GET_ITEM_AUTH_REFS", queryParams);
724
725             ctx = createServiceContext(getItemServiceName(), queryParams);
726             // We omit the parentShortId, only needed when doing a create...
727             RemoteDocumentModelHandlerImpl handler =
728                 (RemoteDocumentModelHandlerImpl) createItemDocumentHandler(ctx, parentcsid, null);
729
730             String itemcsid = lookupItemCSID(itemspecifier, parentcsid,  "getAuthorityItemAuthRefs(item)", "GET_ITEM_AUTH_REFS", ctx);
731
732             DocumentWrapper<DocumentModel> docWrapper = getRepositoryClient(ctx).getDoc(ctx, itemcsid);
733             List<String> authRefFields =
734                 ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(
735                 ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES);
736             authRefList = handler.getAuthorityRefs(docWrapper, authRefFields);
737         } catch (Exception e) {
738                         throw bigReThrow(e, ServiceMessages.GET_FAILED  + " parentspecifier: "+parentspecifier + " itemspecifier:" +itemspecifier);
739                 }return authRefList;
740     }
741
742         /**
743          * Update authorityItem.
744          * 
745          * @param parentspecifier either a CSID or one of the urn forms
746          * @param itemspecifier either a CSID or one of the urn forms
747          *
748          * @return the multipart output
749          */
750         @PUT
751         @Path("{csid}/items/{itemcsid}")
752         public byte[] updateAuthorityItem(
753             @Context UriInfo ui,
754                         @PathParam("csid") String parentspecifier,
755                         @PathParam("itemcsid") String itemspecifier,
756                         String xmlPayload) {
757                 PoxPayloadOut result = null;
758                 try {
759                         PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
760             // Note that we have to create the service context for the Items, not the main service
761             //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
762             String parentcsid = lookupParentCSID(parentspecifier, "updateAuthorityItem(parent)", "UPDATE_ITEM", null);
763
764             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), theUpdate);
765             String itemcsid = lookupItemCSID(itemspecifier, parentcsid,   "updateAuthorityItem(item)", "UPDATE_ITEM", ctx);
766
767                         // We omit the parentShortId, only needed when doing a create...
768                         DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null);
769             ctx.setUriInfo(ui);
770                         getRepositoryClient(ctx).update(ctx, itemcsid, handler);
771                         result = ctx.getOutput();
772
773                 } catch (Exception e) {
774             throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
775                 }
776                 return result.getBytes();
777         }
778
779         /**
780          * Delete authorityItem.
781          * 
782          * @param parentcsid the parentcsid
783          * @param itemcsid the itemcsid
784          * 
785          * @return the response
786          */
787         @DELETE
788         @Path("{csid}/items/{itemcsid}")
789         public Response deleteAuthorityItem(
790                         @PathParam("csid") String parentcsid,
791                         @PathParam("itemcsid") String itemcsid) {
792                 //try{
793         if (logger.isDebugEnabled()) {
794             logger.debug("deleteAuthorityItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
795         }
796         try {
797                     ensureCSID(parentcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.parentcsid");
798             ensureCSID(itemcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.itemcsid");
799         //Laramie, removing this catch, since it will surely fail below, since itemcsid or parentcsid will be null.
800         // }catch (Throwable t){
801         //    System.out.println("ERROR in setting up DELETE: "+t);
802         // }
803         // try {
804                         // Note that we have to create the service context for the Items, not the main service
805                         ServiceContext ctx = createServiceContext(getItemServiceName());
806                         getRepositoryClient(ctx).delete(ctx, itemcsid);
807                         return Response.status(HttpResponseCodes.SC_OK).build();
808         } catch (Exception e) {
809                         throw bigReThrow(e, ServiceMessages.DELETE_FAILED + "  itemcsid: " + itemcsid+ " parentcsid:" + parentcsid);
810                 }
811         }
812
813     public final static String hierarchy = "hierarchy";
814     @GET
815     @Path("{csid}/items/{itemcsid}/"+hierarchy)
816     @Produces("application/xml")
817     public String getHierarchy(@PathParam("csid") String csid,
818                                            @PathParam("itemcsid") String itemcsid,
819                                            @Context UriInfo ui) throws Exception {
820         try {
821             // 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...?
822             String calledUri = ui.getPath();
823             String uri = "/"+calledUri.substring(0, (calledUri.length()-("/"+hierarchy).length()));
824             ServiceContext ctx = createServiceContext(getItemServiceName());
825             ctx.setUriInfo(ui);
826             String direction = ui.getQueryParameters().getFirst(Hierarchy.directionQP);
827             if (Tools.notBlank(direction) && Hierarchy.direction_parents.equals(direction)){
828                 return Hierarchy.surface(ctx, itemcsid, uri);
829             } else {
830                 return Hierarchy.dive(ctx, itemcsid, uri);
831             }
832         } catch (Exception e){
833             throw bigReThrow(e, "Error showing hierarchy", itemcsid);
834         }
835     }
836
837
838     
839 }