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.setObjectName("some object name here");
207 ResponsibleDepartmentList deptList = new ResponsibleDepartmentList();
208 List<String> depts = deptList.getResponsibleDepartment();
209 // @TODO Use properly formatted refNames for representative departments
210 // in this example test record. The following are mere placeholders.
211 depts.add("urn:org.collectionspace.services.department:Registrar");
212 depts.add("urn:org.walkerart.department:Fine Art");
213 collectionObject.setAge(""); // Test using an empty String.
214 collectionObject.setBriefDescription("Papier mache bird mask with horns, " +
215 "painted red with black and yellow spots. " +
216 "Puerto Rico. ca. 8" high, 6" wide, projects 10" (with horns).");
218 MultipartOutput multipart = new MultipartOutput();
219 OutputPart commonPart = multipart.addPart(collectionObject,
220 MediaType.APPLICATION_XML_TYPE);
221 commonPart.getHeaders().add("label", getCommonPartName());
223 if (logger.isInfoEnabled()) {
224 logger.info("CollectionObject Common part to be created:");
225 logger.info(objectAsXmlString(collectionObject,
226 CollectionobjectsCommon.class));
229 // Create a "domain" part of a CollectionObject and add data to its fields.
230 // This part might come from a community or consortia in a particular domain.
231 // There could potentially be multiple "domain" parts in a CollectionObject record.
233 // This example adds data to fields for a hypothetical Natural History domain,
234 // as in the case of the test fields below ...
236 CollectionobjectsNaturalhistory conh = new CollectionobjectsNaturalhistory();
237 conh.setNhString("test-string");
239 conh.setNhLong(9999);
241 OutputPart nhPart = multipart.addPart(conh, MediaType.APPLICATION_XML_TYPE);
242 nhPart.getHeaders().add("label", getNHPartName());
244 if (logger.isInfoEnabled()) {
245 logger.info("CollectionObject Natural History part to be created:");
246 logger.info(objectAsXmlString(conh,
247 CollectionobjectsNaturalhistory.class));
250 // Return the multipart entity body that will be submitted in the
251 // 'create' request, above.
255 private Object extractPart(MultipartInput input, String label,
256 Class clazz) throws Exception {
258 String partLabel = "";
259 List<InputPart> parts = input.getParts();
260 if (parts.size() == 0) {
261 logger.warn("No parts found in multipart body.");
263 if(logger.isInfoEnabled()){
264 logger.info("Parts:");
265 for(InputPart part : parts){
266 partLabel = part.getHeaders().getFirst("label");
267 logger.info("part = " + partLabel);
270 boolean partLabelMatched = false;
271 for(InputPart part : parts){
272 partLabel = part.getHeaders().getFirst("label");
273 if(label.equalsIgnoreCase(partLabel)){
274 partLabelMatched = true;
275 if(logger.isInfoEnabled()){
276 logger.info("found part" + partLabel);
278 String partStr = part.getBodyAsString();
279 if (partStr == null || partStr.trim().isEmpty()) {
280 logger.warn("Part '" + label + "' in multipart body is empty.");
282 if (logger.isInfoEnabled()){
283 logger.info("extracted part as str=\n" + partStr);
285 obj = part.getBody(clazz, null);
286 if(logger.isInfoEnabled()){
287 logger.info("extracted part as obj=\n",
288 objectAsXmlString(obj, clazz));
294 if (! partLabelMatched) {
295 logger.warn("Could not find part '" + label + "' in multipart body.");
296 // Handle a potential condition where getBodyAsString() or getBody(),
297 // above, do *not* throw an IOException, but getBody() nonetheless
298 // retrieves a null object.
300 // This *may* be effectively unreachable, but is here as a precaution.
301 } else if (obj == null) {
302 logger.warn("Could not extract part '" + label +
303 "' in multipart body as an object.");
308 public void displayCollectionObject(MultipartInput input)
312 throw new IllegalArgumentException(
313 "Could not display null CollectionObject record.");
316 // Extract each part of the record, and convert it from
317 // its XML representation to its associated Java object.
319 // Read the Common part of the record.
320 CollectionobjectsCommon collectionObject =
321 (CollectionobjectsCommon) extractPart(input,
322 client.getCommonPartName(), CollectionobjectsCommon.class);
324 if (logger.isInfoEnabled()) {
325 logger.info("CollectionObject Common part read:");
326 logger.info(objectAsXmlString(collectionObject,
327 CollectionobjectsCommon.class));
330 // Read the Natural History part of the record.
331 CollectionobjectsNaturalhistory conh =
332 (CollectionobjectsNaturalhistory) extractPart(input,
333 getNHPartName(), CollectionobjectsNaturalhistory.class);
335 if (logger.isInfoEnabled()) {
336 logger.info("CollectionObject Natural History part read:");
337 logger.info(objectAsXmlString(conh,
338 CollectionobjectsNaturalhistory.class));
344 private String getCommonPartName() {
345 return client.getCommonPartName();
348 private String getNHPartName() {
349 return "collectionobjects_naturalhistory";
352 private List<String> getAllResourceIds() throws Exception {
354 CollectionobjectsCommonList list = readCollectionObjectList();
355 List<String> resourceIds = new ArrayList();
356 List<CollectionobjectsCommonList.CollectionObjectListItem> items =
357 list.getCollectionObjectListItem();
359 for (CollectionobjectsCommonList.CollectionObjectListItem item : items) {
360 resourceIds.add(item.getCsid());
366 private String extractId(ClientResponse<Response> res) {
367 MultivaluedMap<String, Object> mvm = res.getMetadata();
368 String uri = (String) ((ArrayList<Object>) mvm.get("Location")).get(0);
369 if(logger.isInfoEnabled()){
370 logger.info("extractId:uri=" + uri);
372 String[] segments = uri.split("/");
373 String id = segments[segments.length - 1];
374 if(logger.isInfoEnabled()){
375 logger.info("id=" + id);
380 private String objectAsXmlString(Object o, Class clazz) {
381 StringWriter sw = new StringWriter();
383 JAXBContext jc = JAXBContext.newInstance(clazz);
384 Marshaller m = jc.createMarshaller();
385 m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
391 return sw.toString();
394 public static void main(String[] args) throws Exception {
396 Sample sample = new Sample();
398 // Optionally first delete all existing collection object records.
399 boolean ENABLE_DELETE_ALL = false;
400 if (ENABLE_DELETE_ALL) {
401 logger.info("Deleting all CollectionObject records ...");
402 sample.deleteAllCollectionObjects();
405 logger.info("Creating a new CollectionObject record ...");
406 String newRecordId = sample.createCollectionObject();
408 if (newRecordId == null || newRecordId.trim().isEmpty()) {
409 logger.error("Could not create new record.");
413 logger.info("Reading the new CollectionObject record ...");
414 MultipartInput corecord = sample.readCollectionObject(newRecordId);
415 sample.displayCollectionObject(corecord);
417 logger.info("Deleting the new CollectionObject record ...");
418 sample.deleteCollectionObject(newRecordId);