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