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 Regents of the University of California
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
15 * https://source.collectionspace.org/collection-space/LICENSE.txt
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
24 package org.collectionspace.services.collectionobject.client.sample;
26 import java.io.StringWriter;
27 import java.util.ArrayList;
28 import java.util.List;
30 import javax.ws.rs.core.MediaType;
31 import javax.ws.rs.core.MultivaluedMap;
32 import javax.ws.rs.core.Response;
33 import javax.xml.bind.JAXBContext;
34 import javax.xml.bind.Marshaller;
36 import org.collectionspace.services.client.CollectionObjectClient;
37 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
38 import org.collectionspace.services.collectionobject.CollectionobjectsCommonList;
39 import org.collectionspace.services.collectionobject.ResponsibleDepartmentList;
40 import org.collectionspace.services.collectionobject.domain.naturalhistory.CollectionobjectsNaturalhistory;
42 import org.jboss.resteasy.client.ClientResponse;
43 import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
44 import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
45 import org.jboss.resteasy.plugins.providers.multipart.InputPart;
46 import org.jboss.resteasy.plugins.providers.multipart.OutputPart;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
52 * Sample, sample client code for creating and accessing
53 * CollectionObject records.
55 * $LastChangedRevision: $
60 private static final Logger logger =
61 LoggerFactory.getLogger(Sample.class);
63 // Instance variables specific to this test.
64 private CollectionObjectClient client = new CollectionObjectClient();
65 final String SERVICE_PATH_COMPONENT = "collectionobjects";
68 // ---------------------------------------------------------------
70 // ---------------------------------------------------------------
72 public String createCollectionObject() {
74 // Create a CollectionObject record to submit to the service.
75 MultipartOutput multipart = createCollectionObjectInstance();
77 // Submit a 'create' request to the service, sending the new
78 // CollectionObject record to be created, and store the response.
79 ClientResponse<Response> res = client.create(multipart);
81 // Get the status code from the response and check it against
82 // the expected status code.
83 if (res.getStatus() != Response.Status.CREATED.getStatusCode()) {
84 logger.error("Error creating new CollectionObject. Status code = " +
88 logger.info("CollectionObject created successfully.");
91 // Return the new record number for the newly-created record.
92 return extractId(res);
96 // ---------------------------------------------------------------
98 // ---------------------------------------------------------------
100 public MultipartInput readCollectionObject(String resourceId) throws Exception {
102 if (resourceId == null || resourceId.trim().isEmpty()) {
103 throw new IllegalArgumentException(
104 "Resource ID must not be null or empty.");
107 // Submit the read ("get") request to the service and store the response.
108 // The resourceId is a unique identifier for the CollectionObject
109 // record we're reading.
110 ClientResponse<MultipartInput> res = client.read(resourceId);
112 // Get the status code from the response and check it against
113 // the expected status code.
114 if (res.getStatus() != Response.Status.OK.getStatusCode()) {
115 logger.error("Error reading CollectionObject with" +
116 "resource ID " + resourceId + ". Status code = " +
121 // Get the entity body of the response from the service.
122 MultipartInput input = (MultipartInput) res.getEntity();
128 private CollectionobjectsCommonList readCollectionObjectList()
131 // Submit the read list request to the service and store the response.
132 ClientResponse<CollectionobjectsCommonList> res = client.readList();
134 // Get the status code from the response and check it against
135 // the expected status code.
136 if (res.getStatus() != Response.Status.OK.getStatusCode()) {
137 logger.error("Error reading list of CollectionObjects. Status code = " +
142 CollectionobjectsCommonList list = res.getEntity();
148 // ---------------------------------------------------------------
150 // ---------------------------------------------------------------
152 private void deleteCollectionObject(String resourceId) {
154 if (resourceId == null || resourceId.trim().isEmpty()) {
155 throw new IllegalArgumentException(
156 "Resource ID must not be null or empty.");
159 ClientResponse res = client.delete(resourceId);
161 // Get the status code from the response and check it against
162 // the expected status code.
163 if (res.getStatus() != Response.Status.OK.getStatusCode()) {
164 logger.error("Error deleting CollectionObject with" +
165 "resource ID " + resourceId + ". Status code = " +
172 private void deleteAllCollectionObjects() throws Exception {
174 int recordsDeleted = 0;
175 for (String resourceId : getAllResourceIds()) {
177 ClientResponse res = client.delete(resourceId);
179 // Get the status code from the response and check it against
180 // the expected status code.
181 if (res.getStatus() != Response.Status.OK.getStatusCode()) {
182 logger.error("Error deleting CollectionObject with" +
183 "resource ID " + resourceId + ". Status code = " +
190 if (logger.isInfoEnabled()) {
191 logger.info("Deleted " + recordsDeleted + " CollectionObject record(s).");
196 // ---------------------------------------------------------------
198 // ---------------------------------------------------------------
200 private MultipartOutput createCollectionObjectInstance() {
202 // Create the Common part of a CollectionObject and add data to its fields.
204 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
205 collectionObject.setObjectNumber("some object number here");
206 collectionObject.getObjectNameList().getObjectNameGroup().get(0).setObjectName("some object name here");
209 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
210 List<String> depts = deptList.getResponsibleDepartment();
211 // @TODO Use properly formatted refNames for representative departments
212 // in this example test record. The following are mere placeholders.
213 depts.add("urn:org.collectionspace.services.department:Registrar");
214 depts.add("urn:org.walkerart.department:Fine Art");
215 collectionObject.setAge(""); // Test using an empty String.
216 collectionObject.getBriefDescriptions().getBriefDescription().add("Papier mache bird mask with horns, " +
217 "painted red with black and yellow spots. " +
218 "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
219 MultipartOutput multipart = new MultipartOutput();
220 OutputPart commonPart = multipart.addPart(collectionObject,
221 MediaType.APPLICATION_XML_TYPE);
222 commonPart.getHeaders().add("label", getCommonPartName());
224 if (logger.isInfoEnabled()) {
225 logger.info("CollectionObject Common part to be created:");
226 logger.info(objectAsXmlString(collectionObject,
227 CollectionobjectsCommon.class));
230 // Create a "domain" part of a CollectionObject and add data to its fields.
231 // This part might come from a community or consortia in a particular domain.
232 // There could potentially be multiple "domain" parts in a CollectionObject record.
234 // This example adds data to fields for a hypothetical Natural History domain,
235 // as in the case of the test fields below ...
237 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
238 conh.setNhString("test-string");
240 conh.setNhLong(9999);
242 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
243 nhPart.getHeaders().add("label", getNHPartName());
245 if (logger.isInfoEnabled()) {
246 logger.info("CollectionObject Natural History part to be created:");
247 logger.info(objectAsXmlString(conh,
248 CollectionobjectsNaturalhistory.class));
251 // Return the multipart entity body that will be submitted in the
252 // 'create' request, above.
256 private Object extractPart(MultipartInput input, String label,
257 Class clazz) throws Exception {
259 String partLabel = "";
260 List<InputPart> parts = input.getParts();
261 if (parts.size() == 0) {
262 logger.warn("No parts found in multipart body.");
264 if(logger.isInfoEnabled()){
265 logger.info("Parts:");
266 for(InputPart part : parts){
267 partLabel = part.getHeaders().getFirst("label");
268 logger.info("part = " + partLabel);
271 boolean partLabelMatched = false;
272 for(InputPart part : parts){
273 partLabel = part.getHeaders().getFirst("label");
274 if(label.equalsIgnoreCase(partLabel)){
275 partLabelMatched = true;
276 if(logger.isInfoEnabled()){
277 logger.info("found part" + partLabel);
279 String partStr = part.getBodyAsString();
280 if (partStr == null || partStr.trim().isEmpty()) {
281 logger.warn("Part '" + label + "' in multipart body is empty.");
283 if (logger.isInfoEnabled()){
284 logger.info("extracted part as str=\n" + partStr);
286 obj = part.getBody(clazz, null);
287 if(logger.isInfoEnabled()){
288 logger.info("extracted part as obj=\n",
289 objectAsXmlString(obj, clazz));
295 if (! partLabelMatched) {
296 logger.warn("Could not find part '" + label + "' in multipart body.");
297 // Handle a potential condition where getBodyAsString() or getBody(),
298 // above, do *not* throw an IOException, but getBody() nonetheless
299 // retrieves a null object.
301 // This *may* be effectively unreachable, but is here as a precaution.
302 } else if (obj == null) {
303 logger.warn("Could not extract part '" + label +
304 "' in multipart body as an object.");
309 public void displayCollectionObject(MultipartInput input)
313 throw new IllegalArgumentException(
314 "Could not display null CollectionObject record.");
317 // Extract each part of the record, and convert it from
318 // its XML representation to its associated Java object.
320 // Read the Common part of the record.
321 CollectionobjectsCommon collectionObject =
322 (CollectionobjectsCommon) extractPart(input,
323 client.getCommonPartName(), CollectionobjectsCommon.class);
325 if (logger.isInfoEnabled()) {
326 logger.info("CollectionObject Common part read:");
327 logger.info(objectAsXmlString(collectionObject,
328 CollectionobjectsCommon.class));
331 // Read the Natural History part of the record.
332 CollectionobjectsNaturalhistory conh =
333 (CollectionobjectsNaturalhistory) extractPart(input,
334 getNHPartName(), CollectionobjectsNaturalhistory.class);
336 if (logger.isInfoEnabled()) {
337 logger.info("CollectionObject Natural History part read:");
338 logger.info(objectAsXmlString(conh,
339 CollectionobjectsNaturalhistory.class));
345 private String getCommonPartName() {
346 return client.getCommonPartName();
349 private String getNHPartName() {
350 return "collectionobjects_naturalhistory";
353 private List<String> getAllResourceIds() throws Exception {
355 CollectionobjectsCommonList list = readCollectionObjectList();
356 List<String> resourceIds = new ArrayList();
357 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
358 list.getCollectionObjectListItem();
360 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
361 resourceIds.add(item.getCsid());
367 private String extractId(ClientResponse<Response> res) {
368 MultivaluedMap<String, Object> mvm = res.getMetadata();
369 String uri = (String) ((ArrayList<Object>) mvm.get("Location")).get(0);
370 if(logger.isInfoEnabled()){
371 logger.info("extractId:uri=" + uri);
373 String[] segments = uri.split("/");
374 String id = segments[segments.length - 1];
375 if(logger.isInfoEnabled()){
376 logger.info("id=" + id);
381 private String objectAsXmlString(Object o, Class clazz) {
382 StringWriter sw = new StringWriter();
384 JAXBContext jc = JAXBContext.newInstance(clazz);
385 Marshaller m = jc.createMarshaller();
386 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
392 return sw.toString();
395 public static void main(String[] args) throws Exception {
397 Sample sample = new Sample();
399 // Optionally first delete all existing collection object records.
400 boolean ENABLE_DELETE_ALL = false;
401 if (ENABLE_DELETE_ALL) {
402 logger.info("Deleting all CollectionObject records ...");
403 sample.deleteAllCollectionObjects();
406 logger.info("Creating a new CollectionObject record ...");
407 String newRecordId = sample.createCollectionObject();
409 if (newRecordId == null || newRecordId.trim().isEmpty()) {
410 logger.error("Could not create new record.");
414 logger.info("Reading the new CollectionObject record ...");
415 MultipartInput corecord = sample.readCollectionObject(newRecordId);
416 sample.displayCollectionObject(corecord);
418 logger.info("Deleting the new CollectionObject record ...");
419 sample.deleteCollectionObject(newRecordId);