2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
24 package org.collectionspace.services.contact;
26 import java.util.HashMap;
28 import javax.ws.rs.Consumes;
29 import javax.ws.rs.DELETE;
30 import javax.ws.rs.GET;
31 import javax.ws.rs.POST;
32 import javax.ws.rs.PUT;
33 import javax.ws.rs.Path;
34 import javax.ws.rs.PathParam;
35 import javax.ws.rs.Produces;
36 import javax.ws.rs.WebApplicationException;
37 import javax.ws.rs.core.Context;
38 import javax.ws.rs.core.MultivaluedMap;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.UriBuilder;
41 import javax.ws.rs.core.UriInfo;
42 import org.collectionspace.services.client.*;
43 import org.collectionspace.services.common.StoredValuesUriTemplate;
44 import org.collectionspace.services.common.UriTemplateFactory;
45 import org.collectionspace.services.common.vocabulary.AuthorityResource;
46 import org.collectionspace.services.common.context.ServiceContext;
47 import org.collectionspace.services.common.document.DocumentFilter;
48 import org.collectionspace.services.common.document.DocumentHandler;
49 import org.collectionspace.services.contact.ContactResource;
50 import org.collectionspace.services.contact.ContactsCommon;
51 import org.collectionspace.services.contact.ContactJAXBSchema;
52 import org.collectionspace.services.contact.nuxeo.ContactConstants;
53 import org.collectionspace.services.contact.nuxeo.ContactDocumentModelHandler;
54 import org.collectionspace.services.jaxb.AbstractCommonList;
55 import org.jboss.resteasy.util.HttpResponseCodes;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
60 * The Class AuthorityResourceWithContacts.
62 @Consumes("application/xml")
63 @Produces("application/xml")
64 public abstract class AuthorityResourceWithContacts<AuthCommon, AuthItemHandler> extends //FIXME: REM - Why is this resource in this package instead of somewhere in 'common'?
65 AuthorityResource<AuthCommon, AuthItemHandler> {
67 private ContactResource contactResource = new ContactResource(); // Warning: ContactResource is a singleton.
68 final Logger logger = LoggerFactory.getLogger(AuthorityResourceWithContacts.class);
70 public AuthorityResourceWithContacts(
71 Class<AuthCommon> authCommonClass, Class<?> resourceClass,
72 String authorityCommonSchemaName, String authorityItemCommonSchemaName) {
73 super(authCommonClass, resourceClass,
74 authorityCommonSchemaName, authorityItemCommonSchemaName);
77 public abstract String getItemServiceName();
79 public String getContactServiceName() {
80 return contactResource.getServiceName();
83 private DocumentHandler createContactDocumentHandler(
84 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String inAuthority,
85 String inItem) throws Exception {
87 return createContactDocumentHandler(ctx, inAuthority, inItem, ui);
90 private DocumentHandler createContactDocumentHandler(
91 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String inAuthority,
92 String inItem, UriInfo ui) throws Exception {
93 ContactDocumentModelHandler docHandler = (ContactDocumentModelHandler) createDocumentHandler(
95 ctx.getCommonPartLabel(getContactServiceName()),
96 ContactsCommon.class);
97 docHandler.setInAuthority(inAuthority);
98 docHandler.setInItem(inItem);
99 docHandler.getServiceContext().setUriInfo(ui);
103 /*************************************************************************
104 * Contact parts - this is a sub-resource of the AuthorityItem
105 * @param parentspecifier either a CSID or one of the urn forms
106 * @param itemspecifier either a CSID or one of the urn forms
108 *************************************************************************/
110 @Path("{parentcsid}/items/{itemcsid}/contacts")
111 public Response createContact(
112 @PathParam("parentcsid") String parentspecifier,
113 @PathParam("itemcsid") String itemspecifier,
115 @Context UriInfo ui) {
117 PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
118 String parentcsid = lookupParentCSID(parentspecifier, "createContact(authority)", "CREATE_ITEM_CONTACT", null);
120 ServiceContext itemCtx = createServiceContext(getItemServiceName());
121 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "createContact(item)", "CREATE_ITEM_CONTACT", itemCtx);
123 // Note that we have to create the service context and document
124 // handler for the Contact service, not the main service.
125 ServiceContext ctx = createServiceContext(getContactServiceName(), input);
126 DocumentHandler handler = createContactDocumentHandler(ctx, parentcsid, itemcsid, ui);
127 String csid = getRepositoryClient(ctx).create(ctx, handler);
128 UriBuilder path = UriBuilder.fromResource(resourceClass);
129 path.path("" + parentcsid + "/items/" + itemcsid + "/contacts/" + csid);
130 Response response = Response.created(path.build()).build();
132 } catch (Exception e) {
134 "Create Contact failed; one of the requested specifiers for authority:"
135 + parentspecifier + ": and item:" + itemspecifier + ": was not found.",
141 * Gets the contact list.
143 * @param parentspecifier either a CSID or one of the urn forms
144 * @param itemspecifier either a CSID or one of the urn forms
147 * @return the contact list
150 @Produces({"application/xml"})
151 @Path("{parentcsid}/items/{itemcsid}/contacts/")
152 public AbstractCommonList getContactList(
153 @PathParam("parentcsid") String parentspecifier,
154 @PathParam("itemcsid") String itemspecifier,
155 @Context UriInfo ui) {
156 AbstractCommonList contactObjectList = new AbstractCommonList();
158 String parentcsid = lookupParentCSID(parentspecifier, "getContactList(parent)", "GET_CONTACT_LIST", null);
160 ServiceContext itemCtx = createServiceContext(getItemServiceName());
161 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "getContactList(item)", "GET_CONTACT_LIST", itemCtx);
163 MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
164 ServiceContext ctx = createServiceContext(getContactServiceName(), queryParams);
165 DocumentHandler handler = createContactDocumentHandler(ctx, parentcsid, itemcsid, ui);
166 DocumentFilter myFilter = handler.getDocumentFilter(); //new DocumentFilter();
167 myFilter.appendWhereClause(ContactJAXBSchema.CONTACTS_COMMON + ":"
168 + ContactJAXBSchema.IN_AUTHORITY
169 + "='" + parentcsid + "'"
170 + IQueryManager.SEARCH_QUALIFIER_AND
171 + ContactJAXBSchema.CONTACTS_COMMON + ":"
172 + ContactJAXBSchema.IN_ITEM
173 + "='" + itemcsid + "'",
174 IQueryManager.SEARCH_QUALIFIER_AND); // "AND" this clause to any existing
175 getRepositoryClient(ctx).getFiltered(ctx, handler);
176 contactObjectList = (AbstractCommonList) handler.getCommonPartList();
177 } catch (Exception e) {
179 "Get ContactList failed; one of the requested specifiers for authority:"
180 + parentspecifier + ": and item:" + itemspecifier + ": was not found.",
183 return contactObjectList;
189 * @param parentspecifier either a CSID or one of the urn forms
190 * @param itemspecifier either a CSID or one of the urn forms
191 * @param csid the csid
193 * @return the contact
196 @Path("{parentcsid}/items/{itemcsid}/contacts/{csid}")
197 public String getContact(
198 @PathParam("parentcsid") String parentspecifier,
199 @PathParam("itemcsid") String itemspecifier,
200 @PathParam("csid") String csid) {
201 PoxPayloadOut result = null;
203 String parentcsid = lookupParentCSID(parentspecifier, "getContact(parent)", "GET_ITEM_CONTACT", null);
205 ServiceContext itemCtx = createServiceContext(getItemServiceName());
206 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "getContact(item)", "GET_ITEM_CONTACT", itemCtx);
208 // Note that we have to create the service context and document handler for the Contact service, not the main service.
209 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getContactServiceName());
210 DocumentHandler handler = createContactDocumentHandler(ctx, parentcsid, itemcsid);
211 getRepositoryClient(ctx).get(ctx, csid, handler);
212 result = ctx.getOutput();
213 } catch (Exception e) {
214 throw bigReThrow(e, "Get failed, the requested Contact CSID:" + csid
215 + ": or one of the specifiers for authority:" + parentspecifier
216 + ": and item:" + itemspecifier + ": was not found.",
219 if (result == null) {
220 Response response = Response.status(Response.Status.NOT_FOUND).entity("Get failed, the requested Contact CSID:" + csid + ": was not found.").type("text/plain").build();
221 throw new WebApplicationException(response);
223 return result.toXML();
229 * @param parentspecifier either a CSID or one of the urn forms
230 * @param itemspecifier either a CSID or one of the urn forms
231 * @param csid the csid
233 * @return the multipart output
236 @Path("{parentcsid}/items/{itemcsid}/contacts/{csid}")
237 public String updateContact(
238 @PathParam("parentcsid") String parentspecifier,
239 @PathParam("itemcsid") String itemspecifier,
240 @PathParam("csid") String csid,
242 PoxPayloadOut result = null;
244 PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
245 String parentcsid = lookupParentCSID(parentspecifier, "updateContact(authority)", "UPDATE_CONTACT", null);
247 ServiceContext itemCtx = createServiceContext(getItemServiceName());
248 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "updateContact(item)", "UPDATE_CONTACT", itemCtx);
250 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
251 // Note that we have to create the service context and document handler for the Contact service, not the main service.
252 ctx = createServiceContext(getContactServiceName(), theUpdate);
253 DocumentHandler handler = createContactDocumentHandler(ctx, parentcsid, itemcsid);
254 getRepositoryClient(ctx).update(ctx, csid, handler);
255 result = ctx.getOutput();
256 } catch (Exception e) {
257 throw bigReThrow(e, "Update failed, the requested Contact CSID:" + csid
258 + ": or one of the specifiers for authority:" + parentspecifier
259 + ": and item:" + itemspecifier + ": was not found.",
262 return result.toXML();
268 * @param parentspecifier either a CSID or one of the urn forms
269 * @param itemspecifier either a CSID or one of the urn forms
270 * @param csid the csid
272 * @return the response
275 @Path("{parentcsid}/items/{itemcsid}/contacts/{csid}")
276 public Response deleteContact(
277 @PathParam("parentcsid") String parentspecifier,
278 @PathParam("itemcsid") String itemspecifier,
279 @PathParam("csid") String csid) {
281 String parentcsid = lookupParentCSID(parentspecifier, "deleteContact(authority)", "DELETE_CONTACT", null);
283 ServiceContext itemCtx = createServiceContext(getItemServiceName());
284 String itemcsid = lookupItemCSID(itemspecifier, parentcsid, "deleteContact(item)", "DELETE_CONTACT", itemCtx);
285 //NOTE: itemcsid is not used below. Leaving the above call in for possible side effects??? CSPACE-3175
287 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
288 // Note that we have to create the service context for the Contact service, not the main service.
289 ctx = createServiceContext(getContactServiceName());
290 DocumentHandler handler = createDocumentHandler(ctx);
291 getRepositoryClient(ctx).delete(ctx, csid, handler);
292 return Response.status(HttpResponseCodes.SC_OK).build();
293 } catch (Exception e) {
294 throw bigReThrow(e, "DELETE failed, the requested Contact CSID:" + csid
295 + ": or one of the specifiers for authority:" + parentspecifier
296 + ": and item:" + itemspecifier + ": was not found.", csid);
300 protected String getContactDocType() {
301 return ContactConstants.NUXEO_DOCTYPE;
305 * Constructs and returns a map of URI templates for the current resource,
306 * for the specified tenant
308 * @param tenantId a tenant ID
309 * @return a map of URI templates for the current resource, for the specified tenant
311 // FIXME: This method currently populates only one entry in the UriTemplateRegistry
312 // for the Contacts docType, even though contacts can be a sub-resource of
313 // multiple authority item resources. (This method may be called more than once,
314 // but each time the existing item with the same key in the map is overwritten.)
316 protected Map<String,StoredValuesUriTemplate> getUriTemplateMap(String tenantId) {
317 // Get the resource and item URI templates from the superclass
318 Map<String,StoredValuesUriTemplate> uriTemplateMap = super.getUriTemplateMap(tenantId);
319 // Add the contact URI template here, and return all three templates in the map
320 String contactDocType = getContactDocType();
321 if (contactDocType == null) {
322 return uriTemplateMap; // return map as obtained from superclass
324 StoredValuesUriTemplate contactUriTemplate = getUriTemplate(UriTemplateFactory.CONTACT);
325 if (contactUriTemplate == null) {
326 return uriTemplateMap; // return map as obtained from superclass
328 // Remove any service name value stored in the template, as the service name
329 // for contact resources will vary, and must be provided at URI build time
330 contactUriTemplate.getStoredValuesMap().put(UriTemplateFactory.SERVICENAME_VAR, "");
331 uriTemplateMap.put(contactDocType, contactUriTemplate);
332 return uriTemplateMap;