]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-3900 More support for invoking Batch processes. Refactored the invocation...
authorPatrick Schmitz <pschmitz@berkeley.edu>
Sat, 28 May 2011 02:11:08 +0000 (02:11 +0000)
committerPatrick Schmitz <pschmitz@berkeley.edu>
Sat, 28 May 2011 02:11:08 +0000 (02:11 +0000)
14 files changed:
services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batch.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batch1.xml
services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchBadInvContext.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchBadInvContextList.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchInvContextList.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchInvContextSingle.xml [new file with mode: 0644]
services/IntegrationTests/src/test/resources/test-data/xmlreplay/xml-replay-master.xml
services/batch/3rdparty/nuxeo-platform-cs-batch/src/main/resources/schemas/batch_common.xsd
services/batch/jaxb/src/main/java/org/collectionspace/services/BatchJAXBSchema.java
services/batch/service/src/main/java/org/collectionspace/services/batch/BatchResource.java
services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/CreateAndLinkLoanOutBatchJob.java
services/client/src/main/java/org/collectionspace/services/client/CollectionSpaceClientUtils.java
services/common/src/main/java/org/collectionspace/services/common/invocable/Invocable.java
services/jaxb/src/main/resources/invocationContext.xsd

index cce9951daa516f9327cbfbe5f8073050c23de64c..9a61e97b6a6a500a7e3757c0d1f49f346517d3ba 100644 (file)
@@ -1,42 +1,72 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <xmlReplay>\r
-    <auths>\r
-        <!-- IMPORTANT: THESE ARE STICKY :: THEY STICK AROUND UNTIL RESET, IN EXEC ORDER OF THIS FILE. -->\r
-        <auth ID="admin@collectionspace.org">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>\r
-        <auth ID="testAdministator">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>\r
-    </auths>\r
-   \r
-    <testGroup ID="primary" autoDeletePOSTS="false">\r
-       <test ID="ba1"  auth="test">\r
-             <method>POST</method>\r
-             <uri>/cspace-services/batch/</uri>\r
-             <filename>batch/batch1.xml</filename>\r
-         </test>\r
-       <test ID="ba2"  auth="test">\r
-             <method>POST</method>\r
-             <uri>/cspace-services/collectionobjects/</uri>\r
-             <filename>batch/collObj1.xml</filename>\r
-         </test>\r
-       <test ID="ba3"  auth="test">\r
-             <method>POST</method>\r
-             <uri>/cspace-services/batch/${ba1.CSID}</uri>\r
-             <filename>batch/batch1InvContext.xml</filename>\r
-             <vars>\r
-                <var ID="CollObj1">${ba2.CSID}</var>\r
-             </vars>\r
-                        </test>\r
-     </testGroup>       \r
-\r
+       <auths>\r
+               <!-- IMPORTANT: THESE ARE STICKY :: THEY STICK AROUND UNTIL RESET, IN EXEC ORDER OF THIS FILE. -->\r
+               <auth ID="admin@collectionspace.org">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>\r
+               <auth ID="testAdministator">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>\r
+       </auths>\r
+       <testGroup ID="testSingle" autoDeletePOSTS="true">\r
+               <test ID="createCollObj1" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/batch/</uri>\r
+                       <filename>batch/batch1.xml</filename>\r
+               </test>\r
+               <test ID="createCollObj2" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/batch/</uri>\r
+                       <filename>batch/batch1.xml</filename>\r
+               </test>\r
+               <test ID="createBatch" auth="test">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/collectionobjects/</uri>\r
+                       <filename>batch/collObj1.xml</filename>\r
+               </test>\r
+               <test ID="testInvokeSingle" auth="test" autoDeletePOSTS="false">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/batch/${createCollObj1.CSID}</uri>\r
+                       <filename>batch/batchInvContextSingle.xml</filename>\r
+                       <vars>\r
+                               <var ID="CollObj1">${createBatch.CSID}</var>\r
+                       </vars>\r
+               </test>\r
+               <test ID="testInvokeList" auth="test" autoDeletePOSTS="false">\r
+                       <method>POST</method>\r
+                       <uri>/cspace-services/batch/${createCollObj1.CSID}</uri>\r
+                       <filename>batch/batchInvContextList.xml</filename>\r
+                       <vars>\r
+                               <var ID="CollObj1">${createBatch.CSID}</var>\r
+                       </vars>\r
+               </test>\r
+               <test ID="testBadInvoke" auth="test" autoDeletePOSTS="false">\r
+                       <method>POST</method>\r
+                       <expectedCodes>400</expectedCodes>\r
+                       <uri>/cspace-services/batch/${createCollObj1.CSID}</uri>\r
+                       <filename>batch/batchBadInvContext.xml</filename>\r
+                       <vars>\r
+                               <var ID="CollObj1">${createBatch.CSID}</var>\r
+                       </vars>\r
+               </test>\r
+               <test ID="testInvokeEmptyList" auth="test" autoDeletePOSTS="false">\r
+                       <method>POST</method>\r
+                       <expectedCodes>400</expectedCodes>\r
+                       <uri>/cspace-services/batch/${createCollObj1.CSID}</uri>\r
+                       <filename>batch/batchBadInvContextList.xml</filename>\r
+                       <vars>\r
+                               <var ID="CollObj1">${createBatch.CSID}</var>\r
+                       </vars>\r
+               </test>\r
+       </testGroup>\r
+       <!-- \r
      <testGroup ID="cleanup" autoDeletePOSTS="true">\r
          <test ID="cl1"  auth="test">\r
              <method>DELETE</method>\r
-             <uri>/cspace-services/batch/${ba1.CSID}</uri>\r
+             <uri>/cspace-services/batch/${createCollObj1.CSID}</uri>\r
          </test>\r
          <test ID="cl2"  auth="test">\r
              <method>DELETE</method>\r
-             <uri>/cspace-services/collectionobjects/${ba2.CSID}</uri>\r
+             <uri>/cspace-services/collectionobjects/${createBatch.CSID}</uri>\r
          </test>\r
                         </testGroup>\r
-    \r
-\r
+                        -->\r
 </xmlReplay>\r
+\r
index e68dd183e588ed17f46ef0ed8e5de60d5a424ca2..7e6f5ef8d0b2fa31ca50f65b80dddd6f1be94075 100644 (file)
@@ -6,7 +6,8 @@
                <name>TestCreateAndLinkLoanOutBatchJob</name>\r
                <notes>This should be interesting</notes>\r
                <forDocType>CollectionObject</forDocType>\r
-               <forSingleDoc>true</forSingleDoc>\r
+               <supportsSingleDoc>true</supportsSingleDoc>\r
+               <supportsDocList>true</supportsDocList>\r
                <createsNewFocus>true</createsNewFocus>\r
                <className>org.collectionspace.services.batch.nuxeo.CreateAndLinkLoanOutBatchJob</className>\r
        </ns2:batch_common>\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchBadInvContext.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchBadInvContext.xml
new file mode 100644 (file)
index 0000000..f07f708
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<ns2:invocationContext\r
+xmlns:ns2="http://collectionspace.org/services/common/invocable"\r
+xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+  <mode>garbage</mode>\r
+       <docType>CollectionObject</docType>\r
+       <listCSIDs>\r
+               <csids>${CollObj1}</csids>\r
+       </listCSIDs>\r
+</ns2:invocationContext>\r
+\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchBadInvContextList.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchBadInvContextList.xml
new file mode 100644 (file)
index 0000000..007b010
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<ns2:invocationContext\r
+xmlns:ns2="http://collectionspace.org/services/common/invocable"\r
+xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+  <mode>list</mode>\r
+       <docType>CollectionObject</docType>\r
+       <listCSIDs>\r
+       </listCSIDs>\r
+</ns2:invocationContext>\r
+\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchInvContextList.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchInvContextList.xml
new file mode 100644 (file)
index 0000000..26b0069
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<ns2:invocationContext\r
+xmlns:ns2="http://collectionspace.org/services/common/invocable"\r
+xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+  <mode>list</mode>\r
+       <docType>CollectionObject</docType>\r
+       <listCSIDs>\r
+               <csid>${CollObj1}</csid>\r
+       </listCSIDs>\r
+</ns2:invocationContext>\r
+\r
+\r
diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchInvContextSingle.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/batch/batchInvContextSingle.xml
new file mode 100644 (file)
index 0000000..fb3ac7b
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
+<ns2:invocationContext\r
+xmlns:ns2="http://collectionspace.org/services/common/invocable"\r
+xmlns:ns3="http://collectionspace.org/services/jaxb">\r
+  <mode>single</mode>\r
+       <docType>CollectionObject</docType>\r
+       <singleCSID>${CollObj1}</singleCSID>\r
+</ns2:invocationContext>\r
+\r
+\r
index 78f961dcd394e1fdf283a7b5bc1e4a2a799cee2e..fdd89e3da6336d3129fe378a95cb600bbb229a93 100755 (executable)
@@ -46,6 +46,7 @@
     <run controlFile="person/person.xml" testGroup="PersonAddRelsDeleteRels" />\r
     <run controlFile="location/location-hierarchy.xml" testGroup="HierarchicLocation" />\r
     <run controlFile="organization/organization-hierarchy.xml" testGroup="HierarchicOrganization" />\r
+               <run controlFile="batch/batch.xml" />\r
         \r
     \r
     \r
index 6ce08a59f330b7e981790e94953c2d0388ebbbf6..3e5b3f7c5357116e7e24ccf8c56d147ec3edef9f 100644 (file)
     <xs:element name="name" type="xs:string"/>\r
        <xs:element name="notes" type="xs:string"/>\r
        <xs:element name="forDocType" type="xs:string"/>\r
-       <xs:element name="forSingleDoc" type="xs:boolean"/>\r
+       <xs:element name="supportsSingleDoc" type="xs:boolean"/>\r
+       <xs:element name="supportsDocList" type="xs:boolean"/>\r
+       <xs:element name="supportsGroup" type="xs:boolean"/>\r
+       <!-- NYI <xs:element name="supportsQuery" type="xs:boolean"/>  -->\r
        <xs:element name="createsNewFocus" type="xs:boolean"/>\r
        <xs:element name="className" type="xs:string"/>\r
 </xs:schema>\r
index 122e79eb0bafcdbe5aaef5f39a31da281086650f..da083363c90c136bef6d103d6cc666bcb371357f 100644 (file)
@@ -7,7 +7,10 @@ public interface BatchJAXBSchema {
     final static String BATCH_NAME = "name";
     final static String BATCH_NOTES = "notes";
     final static String BATCH_FOR_DOC_TYPE = "forDocType";
-    final static String BATCH_FOR_SINGLE_DOC = "forSingleDoc";
+    final static String BATCH_SUPPORTS_SINGLE_DOC = "supportsSingleDoc";
+    final static String BATCH_SUPPORTS_DOC_LIST = "supportsDocList";
+    final static String BATCH_SUPPORTS_GROUP = "supportsGroup";
+    // NYI final static String BATCH_SUPPORTS_SINGLE_DOC = "supportsSingleDoc";
     final static String BATCH_CREATES_NEW_FOCUS = "createsNewFocus";
     final static String BATCH_CLASS_NAME = "className";
 }
index 3cf7b675177ccbe19210a0d5ac0c959354beaeba..55ef6ff0d0de3a3178b6064e5cd66a6c1d45597f 100644 (file)
@@ -33,10 +33,12 @@ import org.collectionspace.services.common.ResourceBase;
 import org.collectionspace.services.common.ResourceMap;
 import org.collectionspace.services.common.ServiceMessages;
 import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.ValidatorHandler;
 import org.collectionspace.services.common.invocable.Invocable;
+import org.collectionspace.services.common.invocable.Invocable.InvocationError;
 import org.collectionspace.services.common.invocable.InvocationContext;
 import org.collectionspace.services.common.invocable.InvocationResults;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -48,14 +50,18 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 @Path(BatchClient.SERVICE_PATH)
 @Produces({"application/xml"})
 @Consumes({"application/xml"})
 public class BatchResource extends ResourceBase {
+       
+       protected final int BAD_REQUEST_STATUS = Response.Status.BAD_REQUEST.getStatusCode();
 
     @Override
     public String getServiceName(){
@@ -90,6 +96,23 @@ public class BatchResource extends ResourceBase {
             DocumentWrapper<DocumentModel> wrapper = 
                getRepositoryClient(ctx).getDoc(ctx, csid);
                DocumentModel docModel = wrapper.getWrappedObject();
+               String invocationMode = invContext.getMode();
+               String modeProperty = null;
+               if(BatchInvocable.INVOCATION_MODE_SINGLE.equalsIgnoreCase(invocationMode)) {
+                       modeProperty = BatchJAXBSchema.BATCH_SUPPORTS_SINGLE_DOC;
+               } else if(BatchInvocable.INVOCATION_MODE_LIST.equalsIgnoreCase(invocationMode)) {
+                       modeProperty = BatchJAXBSchema.BATCH_SUPPORTS_DOC_LIST;
+               } else if(BatchInvocable.INVOCATION_MODE_GROUP.equalsIgnoreCase(invocationMode)) {
+                       modeProperty = BatchJAXBSchema.BATCH_SUPPORTS_GROUP;
+               } else {
+                       throw new BadRequestException("BatchResource: unknown Invocation Mode: "
+                               +invocationMode);
+               }
+               Boolean supports = (Boolean)docModel.getPropertyValue(modeProperty);
+               if(!supports) {
+                       throw new BadRequestException("BatchResource: This Batch Job does not support Invocation Mode: "
+                               +invocationMode);
+               }
                String className = 
                        (String)docModel.getPropertyValue(BatchJAXBSchema.BATCH_CLASS_NAME);
                className = className.trim();
@@ -103,15 +126,15 @@ public class BatchResource extends ResourceBase {
             } else {
                BatchInvocable batchInstance = (BatchInvocable)c.newInstance();
                List<String> modes = batchInstance.getSupportedInvocationModes();
-               if(!modes.contains(invContext.getMode())) {
-                       throw new RuntimeException(
+               if(!modes.contains(invocationMode)) {
+                       throw new BadRequestException(
                                        "BatchResource: Invoked with unsupported context mode: "
-                                       +invContext.getMode());
+                                       +invocationMode);
                }
                        String forDocType = 
                                (String)docModel.getPropertyValue(BatchJAXBSchema.BATCH_FOR_DOC_TYPE);
                if(!forDocType.equalsIgnoreCase(invContext.getDocType())) {
-                       throw new RuntimeException(
+                       throw new BadRequestException(
                                        "BatchResource: Invoked with unsupported document type: "
                                        +invContext.getDocType());
                }
@@ -130,9 +153,17 @@ public class BatchResource extends ResourceBase {
                batchInstance.run();
                int status = batchInstance.getCompletionStatus();
                if(status == Invocable.STATUS_ERROR) {
-                       throw new RuntimeException(
+                       InvocationError error = batchInstance.getErrorInfo();
+                       if(error.getResponseCode() == BAD_REQUEST_STATUS) {
+                               throw new BadRequestException(
                                        "BatchResouce: batchProcess encountered error: "
                                        +batchInstance.getErrorInfo());
+                       } else {
+                               throw new RuntimeException(
+                                               "BatchResouce: batchProcess encountered error: "
+                                               +batchInstance.getErrorInfo());
+
+                       }
                }
                InvocationResults results = batchInstance.getResults();
                return results;
index b0f77f4e3089133c324d07b7369871226a12d821..77fdad9b661a7871748aae78a278d2603105a2d0 100644 (file)
@@ -4,9 +4,13 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
+import javax.ws.rs.core.Response;
+
 import org.collectionspace.services.batch.BatchInvocable;
+import org.collectionspace.services.client.CollectionSpaceClientUtils;
 import org.collectionspace.services.common.ResourceBase;
 import org.collectionspace.services.common.ResourceMap;
+import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
 import org.collectionspace.services.common.invocable.InvocationContext;
 import org.collectionspace.services.common.invocable.InvocationResults;
 
@@ -15,9 +19,15 @@ public class CreateAndLinkLoanOutBatchJob implements BatchInvocable {
        private static ArrayList<String> invocationModes = null;
        private InvocationContext context;
        private int completionStatus;
-       private HashMap<String,ResourceBase> resourceMap;
+       private ResourceMap resourceMap;
        private InvocationResults results;
-       private String errorInfo;
+       private InvocationError errorInfo;
+       private final String RELATION_TYPE = "affects"; 
+       private final String LOAN_DOCTYPE = "LoanOut"; 
+       private final String RELATION_PREDICATE_DISP = "affects"; 
+       protected final int CREATED_STATUS = Response.Status.CREATED.getStatusCode();
+       protected final int BAD_REQUEST_STATUS = Response.Status.BAD_REQUEST.getStatusCode();
+       protected final int INT_ERROR_STATUS = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
        
        public CreateAndLinkLoanOutBatchJob() {
                CreateAndLinkLoanOutBatchJob.setupClassStatics();
@@ -25,13 +35,14 @@ public class CreateAndLinkLoanOutBatchJob implements BatchInvocable {
                completionStatus = STATUS_UNSTARTED;
                resourceMap = null;
                results = new InvocationResults();
-               errorInfo = "";
+               errorInfo = null;
        }
 
        private static void setupClassStatics() {
                if(invocationModes == null ) {
                        invocationModes = new ArrayList<String>(1);
                        invocationModes.add(INVOCATION_MODE_SINGLE);
+                       invocationModes.add(INVOCATION_MODE_LIST);
                }
        }
 
@@ -55,20 +66,108 @@ public class CreateAndLinkLoanOutBatchJob implements BatchInvocable {
         * @param context an instance of InvocationContext.
         */
        public void setResourceMap(ResourceMap resourceMap) {
+               this.resourceMap = resourceMap;
        }
 
        /**
         * The main work logic of the batch job. Will be called after setContext.
         */
        public void run() {
-               completionStatus = STATUS_UNSTARTED;
+               completionStatus = STATUS_MIN_PROGRESS;
+
                try {
-                       Thread.sleep(1000);
-               } catch(Exception e) {}
-               results.setPrimaryURICreated(null);
-               results.setNumAffected(0);
-               results.setUserNote("CreateAndLinkLoanOutBatchJob pretended to do work, and completed");
-               completionStatus = STATUS_COMPLETE;
+                       // First, create the Loanout
+                       if(createLoan() != STATUS_ERROR) {
+                               if(INVOCATION_MODE_SINGLE.equalsIgnoreCase(context.getMode())) {
+                                       if(createRelation(results.getPrimaryURICreated(), 
+                                                                               context.getSingleCSID()) != STATUS_ERROR) {
+                                               results.setNumAffected(1);
+                                               results.setUserNote("CreateAndLinkLoanOutBatchJob created new Loanout: "
+                                                               +results.getPrimaryURICreated()+" with a link to the passed "+context.getDocType());
+                                               completionStatus = STATUS_COMPLETE;
+                                       }
+                               } else if(INVOCATION_MODE_LIST.equalsIgnoreCase(context.getMode())) {
+                                       InvocationContext.ListCSIDs listWrapper = context.getListCSIDs();
+                                       List<String> csids = listWrapper.getCsid();
+                                       if(csids.size()==0) {
+                                               completionStatus = STATUS_ERROR;
+                                               errorInfo = new InvocationError(BAD_REQUEST_STATUS,
+                                                               "CreateAndLinkLoanOutBatchJob: no CSIDs in list of documents!");
+                                               results.setUserNote(errorInfo.getMessage());
+                                       }
+                                       String loanCSID = results.getPrimaryURICreated();
+                                       int nCreated = 0;
+                                       for(String csid:csids) {
+                                               if(createRelation(loanCSID, csid) == STATUS_ERROR) {
+                                                       break;
+                                               } else {
+                                                       nCreated++;
+                                               }
+                                       }
+                                       if(completionStatus!=STATUS_ERROR) {
+                                               results.setNumAffected(nCreated);
+                                               results.setUserNote("CreateAndLinkLoanOutBatchJob created new Loanout: "
+                                                               +results.getPrimaryURICreated()+" with "+nCreated+" link(s) to "+context.getDocType());
+                                               completionStatus = STATUS_COMPLETE;
+                                       }
+                               }
+                       }
+               } catch(Exception e) {
+                       completionStatus = STATUS_ERROR;
+                       errorInfo = new InvocationError(INT_ERROR_STATUS,
+                                       "CreateAndLinkLoanOutBatchJob problem creating new Loanout: "+e.getLocalizedMessage());
+                       results.setUserNote(errorInfo.getMessage());
+               }
+       }
+       
+       private int createLoan() {
+               String newLoanNumber = "NewLoan-"+ GregorianCalendarDateTimeUtils.timestampUTC();
+
+               String loanoutPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+                       +"<document name=\"loansout\">"
+                         +"<ns2:loansout_common xmlns:ns2=\"http://collectionspace.org/services/loanout\""
+                                       +" xmlns:ns3=\"http://collectionspace.org/services/jaxb\">"
+                   +"<loanOutNumber>"+newLoanNumber+"</loanOutNumber>"
+                 +"</ns2:loansout_common></document>";
+
+               // First, create the Loanout
+               ResourceBase resource = 
+                       resourceMap.get("org.collectionspace.services.loanout.LoanoutResource");
+               Response response = resource.create(null, loanoutPayload);
+               if(response.getStatus() != CREATED_STATUS) {
+                       completionStatus = STATUS_ERROR;
+                       errorInfo = new InvocationError(INT_ERROR_STATUS,
+                                       "CreateAndLinkLoanOutBatchJob problem creating new Loanout!");
+                       results.setUserNote(errorInfo.getMessage());
+               } else {
+                       String newId = CollectionSpaceClientUtils.extractId(response);
+                       results.setPrimaryURICreated(newId);
+               }
+               return completionStatus;
+       }
+       
+       private int createRelation(String loanCSID, String toCSID) {
+               // Now, create the relation that links the input object to the loanout
+               String relationPayload = "<document name=\"relations\">"
+                       + "<ns2:relations_common xmlns:ns2=\"http://collectionspace.org/services/relation\"" 
+                       +               " xmlns:ns3=\"http://collectionspace.org/services/jaxb\">"
+                       +   "<documentId1>"+loanCSID+"</documentId1>"
+                       +   "<documentType1>"+LOAN_DOCTYPE+"</documentType1>"
+                       +   "<documentId2>"+toCSID+"</documentId2>"
+                       +   "<documentType2>"+context.getDocType()+"</documentType2>"
+                       +   "<relationshipType>"+RELATION_TYPE+"</relationshipType>"
+                       +   "<predicateDisplayName>"+RELATION_PREDICATE_DISP+"</predicateDisplayName>"
+                       + "</ns2:relations_common></document>";
+               ResourceBase resource = 
+                       resourceMap.get("org.collectionspace.services.relation.RelationResource");
+               Response response = resource.create(null, relationPayload);
+               if(response.getStatus() != CREATED_STATUS) {
+                       completionStatus = STATUS_ERROR;
+                       errorInfo = new InvocationError(INT_ERROR_STATUS,
+                       "CreateAndLinkLoanOutBatchJob problem creating new relation!");
+                       results.setUserNote(errorInfo.getMessage());
+               }
+               return completionStatus;
        }
 
        /**
@@ -93,7 +192,7 @@ public class CreateAndLinkLoanOutBatchJob implements BatchInvocable {
         * @return a user-presentable note when an error occurs in batch processing. Will only
         * be called if getCompletionStatus() returns STATUS_ERROR.
         */
-       public String getErrorInfo() {
+       public InvocationError getErrorInfo() {
                return errorInfo;
        }
 
index 4cd6764e713e36c5fe80368b25aae73ab21f2b81..8f2bf0b8fe8f15f2133f27dbcda5f5014c7f769b 100644 (file)
@@ -79,7 +79,23 @@ public class CollectionSpaceClientUtils {
      */\r
     static public String extractId(ClientResponse<Response> res) {\r
         MultivaluedMap<String, Object> mvm = res.getMetadata();\r
-        String uri = (String) ((List<Object>) mvm.get("Location")).get(0);\r
+        return extractIdFromResponseMetadata(mvm);\r
+    }\r
\r
+    /**\r
+     * Extract id.\r
+     *\r
+     * @param res the res\r
+     * @return the string\r
+     */\r
+    static public String extractId(Response res) {\r
+        MultivaluedMap<String, Object> mvm = res.getMetadata();\r
+        return extractIdFromResponseMetadata(mvm);\r
+    }\r
\r
+    static protected String extractIdFromResponseMetadata(MultivaluedMap<String, Object> mvm) {\r
+       // mvm may return a java.net.URI which complains about casting to String...\r
+       String uri = ((List<Object>) mvm.get("Location")).get(0).toString();\r
         if (logger.isDebugEnabled()) {\r
             logger.debug("extractId:uri=" + uri);\r
         }\r
index 16212a812869bc36265e862840d4ddc0f8702b25..c5c2f6669a2898f05ea0f15fcf17ae5163345a23 100644 (file)
@@ -34,6 +34,32 @@ import java.util.List;
  * $LastChangedDate: $
  */
 public interface Invocable {
+       
+       public class InvocationError {
+               int responseCode;
+               String message;
+               
+               public InvocationError(int responseCode, String message) {
+                       this.responseCode = responseCode;
+                       this.message = message;
+               }
+
+               public int getResponseCode() {
+                       return responseCode;
+               }
+
+               public void setResponseCode(int responseCode) {
+                       this.responseCode = responseCode;
+               }
+
+               public String getMessage() {
+                       return message;
+               }
+
+               public void setMessage(String message) {
+                       this.message = message;
+               }
+       }
 
        public String INVOCATION_MODE_SINGLE = "single";
        public String INVOCATION_MODE_GROUP = "group";
@@ -77,6 +103,6 @@ public interface Invocable {
         * @return a user-presentable note when an error occurs in batch processing. Will only
         * be called if getCompletionStatus() returns STATUS_ERROR.
         */
-       public String getErrorInfo();
+       public InvocationError getErrorInfo();
 
 }
index 0f1c0b9bd1c816b6d4db9244f9e89717f937bf85..8c5089af9e06a4ba67045d239c20e276f823f1b4 100644 (file)
@@ -26,7 +26,7 @@
                                <xs:element name="listCSIDs">
                                        <xs:complexType>
                                                <xs:sequence>
-                                                       <xs:element name="csids" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+                                                       <xs:element name="csid" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
                                                </xs:sequence>
                                        </xs:complexType>
                                </xs:element>