import org.apache.commons.cli.*;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.collectionspace.services.common.api.Tools;
import org.dom4j.*;
for (ServiceResult pr : serviceResultsMap.values()) {
try {
if (pr.autoDelete == true && Tools.notEmpty(pr.deleteURL)){
- ServiceResult deleteResult = XmlReplayTransport.doDELETE(pr.deleteURL, defaultAuths.getDefaultAuth(), pr.testID, "[autodelete:"+logName+"]");
+ ServiceResult deleteResult = XmlReplayTransport.doDELETE(pr.deleteURL, pr.adminAuth, pr.testID, "[autodelete:"+logName+"]");
if (deleteResult.gotExpectedResult() == false || deleteResult.responseCode != 200) {
reattemptList.put(REATTEMPT_KEY + deleteFailures++, pr); // We need to try again after our dependents have been deleted. cow()
}
String startElement = "";
String label = "";
- public static PartsStruct readParts(Node testNode, final String testID, String xmlReplayBaseDir){
- PartsStruct resultPartsStruct = new PartsStruct();
- resultPartsStruct.responseFilename = testNode.valueOf("filename");
- resultPartsStruct.startElement = testNode.valueOf("startElement");
- resultPartsStruct.label = testNode.valueOf("label");
- String responseFilename = testNode.valueOf("filename");
- if (Tools.notEmpty(responseFilename)){
- resultPartsStruct.responseFilename = xmlReplayBaseDir + '/' + responseFilename;
- List<Node> varNodes = testNode.selectNodes("vars/var");
- readVars(testNode, varNodes, resultPartsStruct);
- }
- return resultPartsStruct;
- }
+ public static PartsStruct readParts(Node testNode, final String testID, String xmlReplayBaseDir) {
+ PartsStruct resultPartsStruct = new PartsStruct();
+ resultPartsStruct.responseFilename = testNode.valueOf("filename");
+ resultPartsStruct.startElement = testNode.valueOf("startElement");
+ resultPartsStruct.label = testNode.valueOf("label");
+ String responseFilename = testNode.valueOf("filename");
+ if (Tools.notEmpty(responseFilename)) {
+ resultPartsStruct.responseFilename = xmlReplayBaseDir + '/' + responseFilename;
+ List<Node> varNodes = testNode.selectNodes("vars/var");
+ readVars(testNode, varNodes, resultPartsStruct);
+ }
+ return resultPartsStruct;
+ }
- private static void readVars(Node testNode, List<Node> varNodes, PartsStruct resultPartsStruct){
+ private static void readVars(Node testNode, List<Node> varNodes, PartsStruct resultPartsStruct) {
Map<String,String> vars = new HashMap<String,String>();
resultPartsStruct.varsList.add(vars);
//System.out.println("### vars: "+vars.size()+" ########");
public static List<ServiceResult> runXmlReplayFile(String xmlReplayBaseDir,
String controlFileName,
- String testGroupID,
+ String targetedTestGroupID,
String oneTestID,
Map<String, ServiceResult> serviceResultsMap,
boolean param_autoDeletePOSTS,
authsMapINFO = "Using AuthsMap from control file: "+authsMap;
}
- report.addTestGroup(testGroupID, controlFileName); //controlFileName is just the short name, without the full path.
+ report.addTestGroup(targetedTestGroupID, controlFileName); //controlFileName is just the short name, without the full path.
String xmlReplayHeader = "========================================================================"
+"\r\nXmlReplay running:"
+"\r\n controlFile: "+ (new File(controlFile).getCanonicalPath())
+"\r\n protoHostPort: "+protoHostPort
- +"\r\n testGroup: "+testGroupID
+ +"\r\n testGroup: "+targetedTestGroupID
+ (Tools.notEmpty(oneTestID) ? "\r\n oneTestID: "+oneTestID : "")
+"\r\n AuthsMap: "+authsMapINFO
+"\r\n param_autoDeletePOSTS: "+param_autoDeletePOSTS
System.out.println(xmlReplayHeader);
String autoDeletePOSTS = "";
+ String authIDForCleanup = "";
List<Node> testgroupNodes;
- if (Tools.notEmpty(testGroupID)){
- testgroupNodes = document.selectNodes("//testGroup[@ID='"+testGroupID+"']");
+ if (Tools.notEmpty(targetedTestGroupID)){
+ testgroupNodes = document.selectNodes("//testGroup[@ID='"+targetedTestGroupID+"']");
} else {
testgroupNodes = document.selectNodes("//testGroup");
}
evalStruct.jexl = jexl;
for (Node testgroup : testgroupNodes) {
-
+ String testGroupID = testgroup.valueOf("@autoDeletePOSTS");
XmlReplayEval.MapContextWKeys jc = new XmlReplayEval.MapContextWKeys();//MapContext(); //Get a new JexlContext for each test group.
evalStruct.jc = jc;
-
autoDeletePOSTS = testgroup.valueOf("@autoDeletePOSTS");
+ //
+ // Decide which auth to use for POST request cleanups
+ //
+ String authForCleanup = null;
+ authIDForCleanup = testgroup.valueOf("@authForCleanup");
+ if (Tools.isEmpty(authIDForCleanup) == false) {
+ authForCleanup = authsMap.map.get(authIDForCleanup);
+ if (Tools.isEmpty(authForCleanup)) {
+ String msg = String.format("The 'authForCleanup' attribute value '%s' declared for test group '%s' is not defined.",
+ authIDForCleanup, testGroupID);
+ throw new Exception(msg);
+ }
+ }
+ authForCleanup = authForCleanup != null ? authForCleanup : defaultAuths.getDefaultAuth();
+
List<Node> tests;
if (Tools.notEmpty(oneTestID)){
tests = testgroup.selectNodes("test[@ID='"+oneTestID+"']");
String currentAuthForTest = null;
String authIDForTest = testNode.valueOf("@auth");
-
- if (Tools.notEmpty(authIDForTest)){
+ if (Tools.notEmpty(authIDForTest)) {
currentAuthForTest = authsMap.map.get(authIDForTest);
+ if (currentAuthForTest == null) {
+ String msg = String.format("The 'auth' attribute value '%s' declared for test '%s' is not defined.",
+ authIDForTest, testIDLabel);
+ throw new Exception(msg);
+ }
} else {
String tokenAuthExpression = testNode.valueOf("@tokenauth");
if (Tools.notEmpty(tokenAuthExpression)){
}
}
- if (Tools.notEmpty(currentAuthForTest)){
+ if (Tools.notEmpty(currentAuthForTest)) {
authForTest = currentAuthForTest; //else just run with current from last loop;
}
- if (Tools.isEmpty(authForTest)){
+ if (Tools.isEmpty(authForTest)) {
authForTest = defaultAuths.getDefaultAuth();
- }
+ }
if (uri.indexOf("$")>-1){
uri = XmlReplayEval.eval(uri, serviceResultsMap, null, jexl, jc);
serviceResult.testID = testID;
serviceResult.fullURL = fullURL;
serviceResult.auth = authForTest;
+ serviceResult.adminAuth = authForCleanup;
serviceResult.method = method;
if (expectedCodes.size()>0){
serviceResult.expectedCodes = expectedCodes;
//=== Now spit out the HTML report file ===
File m = new File(controlFileName);
String localName = m.getName();//don't instantiate, just use File to extract file name without directory.
- String reportName = localName+'-'+testGroupID+".html";
+ String reportName = localName+'-'+targetedTestGroupID+".html";
File resultFile = report.saveReport(xmlReplayBaseDir, reportsDir, reportName);
if (resultFile!=null) {
String toc = report.getTOC(reportName);
reportsList.add(toc);
}
- //================================
return results;
}
- private static String timeString() {
- java.util.Date date= new java.util.Date();
- java.sql.Timestamp ts = new java.sql.Timestamp(date.getTime());
- return ts.toString();
- }
-
+ private static String timeString() {
+ java.util.Date date = new java.util.Date();
+ java.sql.Timestamp ts = new java.sql.Timestamp(date.getTime());
+ return ts.toString();
+ }
//======================== MAIN ===================================================================
* uri = eval(uri, serviceResultsMap, jexl, jc); <br />
* RESULT: "/cspace-services/orgauthorities/43a2739c-4f40-49c8-a6d5/items/"
*/
- public static String eval(String inputJexlExpression, Map<String, ServiceResult> serviceResultsMap, Map<String,String> vars, JexlEngine jexl, JexlContext jc) {
- //System.out.println("\r\n---- REPLACE.init-uri: "+inputJexlExpression);
- String result;
- try {
- jc.set("itemCSID", "${itemCSID}"); //noiseless passthru.
- //System.out.println("eval :: serviceResultsMap "+serviceResultsMap.size());
- for (ServiceResult serviceResult : serviceResultsMap.values()) {
- jc.set(serviceResult.testID, serviceResult);
- //System.out.println("eval :: "+serviceResult.testID+"==>"+serviceResult.minimal());
- }
- if (vars!=null){
- for (Map.Entry<String,String> entry: vars.entrySet()) {
- String value = entry.getValue();
- String key = entry.getKey();
- try {
- value = parse(value, jexl, jc);
- vars.put(key, value); //replace template value with actual value.
- } catch (Exception e){
- value = "ERROR: "+e;
- }
- jc.set(key, value);
- }
- }
- result = parse(inputJexlExpression, jexl, jc);
- } catch (Throwable t) {
- System.err.println("ERROR: " + t);
- result = "ERROR";
- }
- //System.out.println("---- REPLACE.uri: "+result+"\r\n");
- return result;
- }
+ public static String eval(String inputJexlExpression, Map<String, ServiceResult> serviceResultsMap,
+ Map<String, String> vars, JexlEngine jexl, JexlContext jc) {
+ // System.out.println("\r\n---- REPLACE.init-uri:
+ // "+inputJexlExpression);
+ String result;
+ try {
+ jc.set("itemCSID", "${itemCSID}"); // noiseless passthru.
+ // System.out.println("eval :: serviceResultsMap
+ // "+serviceResultsMap.size());
+
+ if (serviceResultsMap != null) {
+ for (ServiceResult serviceResult : serviceResultsMap.values()) {
+ jc.set(serviceResult.testID, serviceResult);
+ // System.out.println("eval ::
+ // "+serviceResult.testID+"==>"+serviceResult.minimal());
+ }
+ }
+
+ if (vars != null) {
+ for (Map.Entry<String, String> entry : vars.entrySet()) {
+ String value = entry.getValue();
+ String key = entry.getKey();
+ try {
+ value = parse(value, jexl, jc);
+ vars.put(key, value); // replace template value with
+ // actual value.
+ } catch (Exception e) {
+ value = "ERROR: " + e;
+ }
+ jc.set(key, value);
+ }
+ }
+ result = parse(inputJexlExpression, jexl, jc);
+ } catch (Throwable t) {
+ System.err.println("ERROR: " + t);
+ result = "ERROR";
+ }
+ // System.out.println("---- REPLACE.uri: "+result+"\r\n");
+ return result;
+ }
private static String parse(String in, JexlEngine jexl, JexlContext jc) {
StringBuffer result = new StringBuffer();
*/
/** Use this overload for NON-multipart messages, that is, regular POSTs. */
- public static ServiceResult doPOST_PUTFromXML(String fileName,
- Map<String,String> vars,
- String protoHostPort,
- String uri,
- String method,
- String contentType,
- XmlReplayEval evalStruct,
- String authForTest,
- String fromTestID)
- throws Exception {
- byte[] b = FileUtils.readFileToByteArray(new File(fileName));
- String xmlString = new String(b);
- String contentRaw = xmlString;
- xmlString = evalStruct.eval(xmlString, evalStruct.serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc);
- String urlString = protoHostPort+uri;
- return doPOST_PUT(urlString, xmlString, contentRaw, BOUNDARY, method, contentType, authForTest, fromTestID); //method is POST or PUT.
- }
+ public static ServiceResult doPOST_PUTFromXML(
+ String fileName,
+ Map<String,
+ String> vars,
+ String protoHostPort,
+ String uri,
+ String method,
+ String contentType,
+ XmlReplayEval evalStruct,
+ String authForTest,
+ String fromTestID) throws Exception {
+ byte[] b = FileUtils.readFileToByteArray(new File(fileName));
+ String xmlString = new String(b);
+ String contentRaw = xmlString;
+ //
+ // Add the test ID so we can substitute instances of "${testID}" in the
+ // payload with the test ID.
+ //
+ String testId = fromTestID.split("\\.")[1]; // Get the unqualified (without the group ID part) test name
+ vars.put("Test.ID", testId);
+
+ xmlString = evalStruct.eval(xmlString, evalStruct.serviceResultsMap, vars, evalStruct.jexl, evalStruct.jc);
+ String urlString = protoHostPort + uri;
+
+ return doPOST_PUT(urlString, xmlString, contentRaw, BOUNDARY, method, contentType, authForTest, fromTestID); // method is POST or PUT.
+ }
//HACK for speed testing in doPOST_PUT.
// Result: XmlReplay takes 9ms to process one test
//if (true) return result;
//END-HACK
- public static ServiceResult doPOST_PUT(String urlString,
- String content,
- String contentRaw,
- String boundary,
- String method,
- String contentType,
- String authForTest,
- String fromTestID) throws Exception {
+ private static ServiceResult doPOST_PUT(
+ String urlString,
+ String content,
+ String contentRaw,
+ String boundary,
+ String method,
+ String contentType,
+ String authForTest,
+ String fromTestID) throws Exception {
ServiceResult result = new ServiceResult();
result.method = method;
+
String deleteURL = "";
String location = "";
+
try {
URL url = new URL(urlString);
HttpURLConnection conn;
} catch (Throwable t2){
result.error = "ERROR in XmlReplayTransport: "+t2;
}
+
return result;
}
- public static ServiceResult doPOST_PUT_PostMethod(String urlString, String content, Map<String,String> contentRaw,
- String boundary, String method, String contentType,
- String authForTest, String fromTestID) throws Exception {
- ServiceResult result = new ServiceResult();
- result.method = method;
- String deleteURL = "";
- String location = "";
- try {
- HttpClient client = new HttpClient();
- PostMethod postMethod = new PostMethod(urlString);
- postMethod.setRequestHeader("Accept", "multipart/mixed");
- postMethod.addRequestHeader("Accept", "application/xml");
- postMethod.setRequestHeader("Authorization", formatAuth(authForTest));
- postMethod.setRequestHeader("X-XmlReplay-fromTestID", fromTestID);
- //this method takes an array of params. Not sure what they expect us to do with a raw post:
- // postMethod.setRequestBody();
- int statusCode1 = 0;
- String res = "";
- try {
- statusCode1 = client.executeMethod(postMethod);
- result.responseCode = statusCode1;
- //System.out.println("statusCode: "+statusCode1+" statusLine ==>" + postMethod.getStatusLine());
- result.responseMessage = postMethod.getStatusText();
- res = postMethod.getResponseBodyAsString();
- Header[] headers = postMethod.getResponseHeaders("Location");
- if (headers.length>0) {
- System.out.println("headers[0]: "+headers[0]);
- String locationZero = headers[0].getValue();
- if (locationZero != null){
- String[] segments = locationZero.split("/");
- location = segments[segments.length - 1];
- deleteURL = Tools.glue(urlString, "/", location);
- }
- }
- postMethod.releaseConnection();
- } catch (Throwable t){
- result.error = t.toString();
- }
- result.result = res;
- result.location = location;
- result.deleteURL = deleteURL;
- result.CSID = location;
- } catch (Throwable t2){
- result.error = "ERROR in XmlReplayTransport: "+t2;
- }
- return result;
- }
+ @Deprecated
+ /**
+ * This method is not used and is a good candidate for removal.
+ *
+ * @param urlString
+ * @param content
+ * @param contentRaw
+ * @param boundary
+ * @param method
+ * @param contentType
+ * @param authForTest
+ * @param fromTestID
+ * @return
+ * @throws Exception
+ */
+ private static ServiceResult doPOST_PUT_PostMethod(
+ String urlString,
+ String content,
+ Map<String, String> contentRaw,
+ String boundary,
+ String method,
+ String contentType,
+ String authForTest,
+ String fromTestID)
+ throws Exception {
+ ServiceResult result = new ServiceResult();
+ result.method = method;
+ String deleteURL = "";
+ String location = "";
+
+ try {
+ HttpClient client = new HttpClient();
+ PostMethod postMethod = new PostMethod(urlString);
+ postMethod.setRequestHeader("Accept", "multipart/mixed");
+ postMethod.addRequestHeader("Accept", "application/xml");
+ postMethod.setRequestHeader("Authorization", formatAuth(authForTest));
+ postMethod.setRequestHeader("X-XmlReplay-fromTestID", fromTestID);
+ // this method takes an array of params. Not sure what they expect
+ // us to do with a raw post:
+ // postMethod.setRequestBody();
+ int statusCode1 = 0;
+ String res = "";
+ try {
+ statusCode1 = client.executeMethod(postMethod);
+ result.responseCode = statusCode1;
+ // System.out.println("statusCode: "+statusCode1+" statusLine
+ // ==>" + postMethod.getStatusLine());
+ result.responseMessage = postMethod.getStatusText();
+ res = postMethod.getResponseBodyAsString();
+ Header[] headers = postMethod.getResponseHeaders("Location");
+ if (headers.length > 0) {
+ System.out.println("headers[0]: " + headers[0]);
+ String locationZero = headers[0].getValue();
+ if (locationZero != null) {
+ String[] segments = locationZero.split("/");
+ location = segments[segments.length - 1];
+ deleteURL = Tools.glue(urlString, "/", location);
+ }
+ }
+ postMethod.releaseConnection();
+ } catch (Throwable t) {
+ result.error = t.toString();
+ }
+ result.result = res;
+ result.location = location;
+ result.deleteURL = deleteURL;
+ result.CSID = location;
+ } catch (Throwable t2) {
+ result.error = "ERROR in XmlReplayTransport: " + t2;
+ }
+
+ return result;
+ }
private static void readStream(HttpURLConnection conn, ServiceResult result) throws Throwable {
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
--- /dev/null
+<document name="vocabularies">
+ <ns2:vocabularies_common xmlns:ns2="http://collectionspace.org/services/vocabulary" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <rev>6</rev>
+ <shortIdentifier>createEmptyVocab100</shortIdentifier>
+ <csid>${csid}</csid>
+ <displayName>createEmptyVocab100 Vocabulary</displayName>
+ <description>
+ This is a test vocabulary for test createEmptyVocab100
+ </description>
+ <source>createEmptyVocab100</source>
+ <refName>
+ urn:cspace:testsci.collectionspace.org:vocabularies:name(createEmptyVocab100)'createEmptyVocab100 Vocabulary'
+ </refName>
+ <vocabType>enum</vocabType>
+ </ns2:vocabularies_common>
+ <ns2:abstract-common-list xmlns:ns2="http://collectionspace.org/services/jaxb">
+ <pageNum>0</pageNum>
+ <pageSize>2500</pageSize>
+ <itemsInPage>0</itemsInPage>
+ <totalItems>0</totalItems>
+ <fieldsReturned>
+ csid|uri|refName|updatedAt|workflowState|rev|sourcePage|sas|proposed|deprecated|termStatus|description|source|order|displayName|shortIdentifier
+ </fieldsReturned>
+ </ns2:abstract-common-list>
+</document>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<document name="objectexit">
+ <ns2:objectexit_common
+ xmlns:ns2="http://collectionspace.org/services/objectexit"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <exitNumber>${exitNumber}</exitNumber>
+ </ns2:objectexit_common>
+ <ns2:objectexit_testsci
+ xmlns:ns2="http://collectionspace.org/services/objectexit"
+ xmlns:ns3="http://collectionspace.org/services/jaxb">
+ <testField>${itemRefName}</testField>
+ </ns2:objectexit_testsci>
+</document>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<document name="vocabularies">
+ <ns3:vocabularies_common xmlns:ns3="http://collectionspace.org/services/vocabulary" xmlns:ns2="http://collectionspace.org/services/jaxb">
+ <displayName>Updated createReplaceVocabItems Vocabulary</displayName>
+ <shortIdentifier>createReplaceVocabItems</shortIdentifier>
+ <description>This is an updated test vocabulary created in the createReplaceVocabItems XMLReplay test group</description>
+ <source>Some updated mythical book posted with item terms in createReplaceVocabItems test group</source>
+ </ns3:vocabularies_common>
+ <ns2:abstract-common-list xmlns:ns2="http://collectionspace.org/services/jaxb">
+ <list-item>
+ <order>1</order>
+ <displayName>Replacement item A</displayName>
+ <shortIdentifier>replacementitema</shortIdentifier>
+ </list-item>
+ <list-item>
+ <order>2</order>
+ <displayName>Replacement item B</displayName>
+ <shortIdentifier>replacementitemb</shortIdentifier>
+ </list-item>
+ <list-item>
+ <order>3</order>
+ <displayName>Replacement item C</displayName>
+ <shortIdentifier>replacementitemc</shortIdentifier>
+ </list-item>
+ </ns2:abstract-common-list>
+</document>
--- /dev/null
+<document name="vocabularies">
+ <ns2:vocabularies_common xmlns:ns2="http://collectionspace.org/services/vocabulary" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <rev>6</rev>
+ <shortIdentifier>createReplaceVocabItems</shortIdentifier>
+ <csid>${csid}</csid>
+ <displayName>createReplaceVocabItems Vocabulary</displayName>
+ <description>
+ This is a test vocabulary for test createReplaceVocabItems
+ </description>
+ <source>createReplaceVocabItems</source>
+ <refName>
+ urn:cspace:testsci.collectionspace.org:vocabularies:name(createReplaceVocabItems)'createReplaceVocabItems Vocabulary'
+ </refName>
+ <vocabType>enum</vocabType>
+ </ns2:vocabularies_common>
+ <ns2:abstract-common-list xmlns:ns2="http://collectionspace.org/services/jaxb">
+ <pageNum>0</pageNum>
+ <pageSize>2500</pageSize>
+ <itemsInPage>0</itemsInPage>
+ <totalItems>0</totalItems>
+ <fieldsReturned>
+ csid|uri|refName|updatedAt|workflowState|rev|sourcePage|sas|proposed|deprecated|termStatus|description|source|order|displayName|shortIdentifier
+ </fieldsReturned>
+ </ns2:abstract-common-list>
+</document>
\ No newline at end of file
xmlns:ns2="http://collectionspace.org/services/jaxb">
<displayName>${displayName}</displayName>
<shortIdentifier>${itemID}</shortIdentifier>
- <refName>urn:cspace:org.collectionspace.demo:vocabulary:name(TestOrderVocab):item:name(${itemID})'${displayName}'</refName>
<order>${order}</order>
<description>This is a test vocabulary item</description>
<source>Some mythical book</source>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<document name="vocabularyitems">
+ <ns3:vocabularyitems_common xmlns:ns3="http://collectionspace.org/services/vocabulary" xmlns:ns2="http://collectionspace.org/services/jaxb">
+ <displayName>${Test.ID}</displayName>
+ <shortIdentifier>${Test.ID}</shortIdentifier>
+ <order>${order}</order>
+ <description>This is a test vocabulary item for test ${Test.ID}</description>
+ <source>Some mythical book for test ${Test.ID}</source>
+ <sourcePage>The page should match the order:${order}</sourcePage>
+ </ns3:vocabularyitems_common>
+</document>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Use this template to create a new vocabulary. Instances of ${Test.ID} will get substituted with the ID of the test using this template.
+-->
+<document name="vocabularies">
+ <ns3:vocabularies_common xmlns:ns3="http://collectionspace.org/services/vocabulary" xmlns:ns2="http://collectionspace.org/services/jaxb">
+ <displayName>${Test.ID} Vocabulary</displayName>
+ <shortIdentifier>${Test.ID}</shortIdentifier>
+ <vocabType>enum</vocabType>
+ <description>This is a test vocabulary for test ${Test.ID}</description>
+ <source>${Test.ID}</source>
+ </ns3:vocabularies_common>
+</document>
<auths>
<!-- IMPORTANT: THESE ARE STICKY :: THEY STICK AROUND UNTIL RESET, IN EXEC ORDER OF THIS FILE. -->
<auth ID="admin@core.collectionspace.org">YWRtaW5AY29yZS5jb2xsZWN0aW9uc3BhY2Uub3JnOkFkbWluaXN0cmF0b3I=</auth>
- <auth ID="testAdministator">YWRtaW5AY29sbGVjdGlvbnNwYWNlLm9yZzpBZG1pbmlzdHJhdG9y</auth>
+ <auth ID="admin@testsci.collectionspace.org">YWRtaW5AdGVzdHNjaS5jb2xsZWN0aW9uc3BhY2Uub3JnOkFkbWluaXN0cmF0b3I=</auth>
</auths>
+ <!--
+ Test replace a vocabulary's terms with an entirely new set of terms.
+ -->
+ <testGroup ID="ReplaceVocabItems" autoDeletePOSTS="true" authForCleanup="admin@testsci.collectionspace.org">
+ <test ID="createReplaceVocabItems" auth="admin@testsci.collectionspace.org">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/</uri>
+ <filename>vocabulary/vocab-Template.xml</filename>
+ </test>
+ <test ID="createItem101">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">1</var>
+ </vars>
+ </test>
+ <test ID="createItem201">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">2</var>
+ </vars>
+ </test>
+ <test ID="createItem301">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">3</var>
+ </vars>
+ </test>
+ <test ID="updateReplaceVocabItems" auth="admin@testsci.collectionspace.org">
+ <method>PUT</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}</uri>
+ <filename>vocabulary/ReplaceVocabItems/ReplaceVocabItems.res.xml</filename>
+ </test>
+<!--
+ <test ID="deleteReplaceVocabItems">
+ <method>DELETE</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}/items</uri>
+ </test>
+ <test ID="getReplaceVocabItems">
+ <method>GET</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}</uri>
+ </test>
+ <test ID="getReplaceVocabItems">
+ <method>GET</method>
+ <uri>/cspace-services/vocabularies/${createReplaceVocabItems.CSID}?showItems=true</uri>
+ <response>
+ <vars>
+ <var ID="csid">${createReplaceVocabItems.CSID}</var>
+ </vars>
+ <expected level="ADDOK" />
+ <label>vocabularies_common</label>
+ <filename>vocabulary/ReplaceVocabItems/responses/ReplaceVocabItems.res.xml</filename>
+ </response>
+ </test>
+ -->
+ </testGroup>
+
+ <testGroup ID="DeleteVocabJustItems" autoDeletePOSTS="true" authForCleanup="admin@testsci.collectionspace.org">
+ <test ID="createEmptyVocab100" auth="admin@testsci.collectionspace.org">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/</uri>
+ <filename>vocabulary/vocab-Template.xml</filename>
+ </test>
+ <test ID="createItem10">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab100.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">1</var>
+ </vars>
+ </test>
+ <test ID="createItem20">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab100.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">2</var>
+ </vars>
+ </test>
+ <test ID="createItem30">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab100.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">3</var>
+ </vars>
+ </test>
+ <test ID="deleteEmptyVocab100">
+ <method>DELETE</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab100.CSID}/items</uri>
+ </test>
+ <test ID="getEmptyVocab100">
+ <method>GET</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab100.CSID}</uri>
+ </test>
+ <test ID="getEmptyVocab100Items">
+ <method>GET</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab100.CSID}?showItems=true</uri>
+ <response>
+ <vars>
+ <var ID="csid">${createEmptyVocab100.CSID}</var>
+ </vars>
+ <expected level="ADDOK" />
+ <label>vocabularies_common</label>
+ <filename>vocabulary/DeleteVocabJustItems/responses/DeleteVocabJustItems.res.xml</filename>
+ </response>
+ </test>
+ </testGroup>
+
+ <!--
+ Test trying to delete an authority (and its terms) when one or more of its terms
+ is being reference in another record.
+
+ 1. Create a new authority and add 3 items to it.
+ 2. Create an ObjectExit record referencing one of the items
+ 3. Try to delete the authority (should fail)
+ 4. Delete the ObjectExit record.
+ 5. Delete to the authority (should work now).
+ -->
+ <testGroup ID="DeleteVocabWithReferencedItem" autoDeletePOSTS="true">
+ <test ID="createEmptyVocab" auth="admin@testsci.collectionspace.org">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/</uri>
+ <filename>vocabulary/vocab-Template.xml</filename>
+ </test>
+ <test ID="createItem1">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">1</var>
+ </vars>
+ </test>
+ <test ID="createItem2">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">2</var>
+ </vars>
+ </test>
+ <test ID="createItem3">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">3</var>
+ </vars>
+ </test>
+ <test ID="createObjectExit">
+ <method>POST</method>
+ <uri>/cspace-services/objectexit</uri>
+ <filename>vocabulary/DeleteVocabWithItems/objectExit.xml</filename>
+ <vars>
+ <var ID="exitNumber">2</var>
+ <var ID="itemRefName">urn:cspace:testsci.collectionspace.org:vocabularies:name(createEmptyVocab):item:name(createItem2)'createItem2'</var>
+ </vars>
+ </test>
+ <test ID="deleteEmptyVocab">
+ <expectedCodes>409</expectedCodes>
+ <method>DELETE</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}</uri>
+ </test>
+ <test ID="deleteObjectExit">
+ <method>DELETE</method>
+ <uri>/cspace-services/objectexit/${createObjectExit.CSID}</uri>
+ </test>
+ <test ID="deleteEmptyVocab">
+ <method>DELETE</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}</uri>
+ </test>
+ <test ID="getEmptyVocab">
+ <expectedCodes>404</expectedCodes>
+ <method>GET</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}</uri>
+ </test>
+ </testGroup>
+
+ <!--
+ 1. Create a new vocabulary.
+ 2. Add three terms to it.
+ 3. Delete the vocabulary (all items should automatically get deleted as well)
+ 4. Try to get the deleted vocabulary (expect a 404)
+ -->
+ <testGroup ID="DeleteVocabWithItems" autoDeletePOSTS="false">
+ <test ID="createEmptyVocab" auth="admin@core.collectionspace.org">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/</uri>
+ <filename>vocabulary/vocab-Template.xml</filename>
+ </test>
+ <test ID="createItem1" auth="cpw">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">1</var>
+ </vars>
+ </test>
+ <test ID="createItem2">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">2</var>
+ </vars>
+ </test>
+ <test ID="createItem3">
+ <method>POST</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}/items/</uri>
+ <filename>vocabulary/vocab-Item-template.xml</filename>
+ <vars>
+ <var ID="order">3</var>
+ </vars>
+ </test>
+ <test ID="deleteEmptyVocab">
+ <method>DELETE</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}</uri>
+ </test>
+ <test ID="getEmptyVocab">
+ <expectedCodes>404</expectedCodes>
+ <method>GET</method>
+ <uri>/cspace-services/vocabularies/${createEmptyVocab.CSID}</uri>
+ </test>
+ </testGroup>
+
<!--
Test creation of Vocabulary (TermList) that includes (via an abstract-common-list element) term items.
-->
<uri>/cspace-services/vocabularies/</uri>
<filename>vocabulary/ShowItems/showItems-vocab.xml</filename>
</test>
- <test ID="createItem1" auth="test">
+ <test ID="createItem1">
<method>POST</method>
<uri>/cspace-services/vocabularies/${createShowItemsVocab.CSID}/items/</uri>
<filename>vocabulary/ShowItems/showItems-item-template.xml</filename>
<var ID="displayName">ShowsItems item ${itemID}</var>
</vars>
</test>
- <test ID="createItem2" auth="test">
+ <test ID="createItem2">
<method>POST</method>
<uri>/cspace-services/vocabularies/${createShowItemsVocab.CSID}/items/</uri>
<filename>vocabulary/ShowItems/showItems-item-template.xml</filename>
<var ID="displayName">ShowsItems item ${itemID}</var>
</vars>
</test>
- <test ID="createItem3" auth="test">
+ <test ID="createItem3">
<method>POST</method>
<uri>/cspace-services/vocabularies/${createShowItemsVocab.CSID}/items/</uri>
<filename>vocabulary/ShowItems/showItems-item-template.xml</filename>
</vars>
<expected level="ADDOK" />
<label>vocabularies_common</label>
- <filename>vocabulary/ShowItems/res/showVocab.res.xml</filename>
+ <filename>vocabulary/ShowItems/responses/showVocab.res.xml</filename>
</response>
</test>
<test ID="getShowItemsVocabWithItems">
<var ID="createItem3">${createItem3.CSID}</var>
</vars>
<expected level="ADDOK" />
- <filename>vocabulary/ShowItems/res/showVocabWithItems.res.xml</filename>
+ <filename>vocabulary/ShowItems/responses/showVocabWithItems.res.xml</filename>
</response>
</test>
<test ID="getShowItemsVocabWithItemsPaged">
<var ID="createItem3">${createItem3.CSID}</var>
</vars>
<expected level="ADDOK" />
- <filename>vocabulary/ShowItems/res/showVocabWithItemsPaged.res.xml</filename>
+ <filename>vocabulary/ShowItems/responses/showVocabWithItemsPaged.res.xml</filename>
</response>
</test>
<test ID="getShowItemsVocabWithItemsLastPage">
<var ID="createItem3">${createItem3.CSID}</var>
</vars>
<expected level="ADDOK" />
- <filename>vocabulary/ShowItems/res/showVocabWithLastPage.res.xml</filename>
+ <filename>vocabulary/ShowItems/responses/showVocabWithLastPage.res.xml</filename>
</response>
</test>
</testGroup>
- <!--
- Comments needed to describe this test group.
- -->
+ <!--
+ The purpose of this testGroup is to test the new "order" field
+ that was added in http://issues.collectionspace.org/browse/CSPACE-573
+ and to ensure that this order field is returned in list results,
+ and that duplicate values for the order field is accepted.
+ -->
<testGroup ID="TestOrder" autoDeletePOSTS="true">
- <!-- The purpose of this testGroup is to test the new "order" field
- that was added in http://issues.collectionspace.org/browse/CSPACE-573
- and to ensure that this order field is returned in list results,
- and that duplicate values for the order field is accepted.
- -->
- <test ID="Vocabulary1" auth="test">
+ <test ID="Vocabulary1">
<method>POST</method>
<uri>/cspace-services/vocabularies/</uri>
<filename>vocabulary/1-vocab.xml</filename>
</test>
- <test ID="Item1" auth="test">
+ <test ID="Item1">
<method>POST</method>
<uri>/cspace-services/vocabularies/${Vocabulary1.CSID}/items/</uri>
<filename>vocabulary/2-item.xml</filename>
<var ID="displayName">TestOrder item ${itemID} order ${order}</var>
</vars>
</test>
- <test ID="Item2" auth="test">
+ <test ID="Item2">
<method>POST</method>
<uri>/cspace-services/vocabularies/${Vocabulary1.CSID}/items/</uri>
<filename>vocabulary/2-item.xml</filename>
<var ID="displayName">TestOrder item ${itemID} order ${order}</var>
</vars>
</test>
- <test ID="Item3DupeOrder" auth="test">
+ <test ID="Item3DupeOrder">
<method>POST</method>
<uri>/cspace-services/vocabularies/${Vocabulary1.CSID}/items/</uri>
<filename>vocabulary/2-item.xml</filename>
</vars>
</test>
- <test ID="GetVocabularies" auth="admin@core.collectionspace.org">
+ <test ID="GetVocabularies">
<method>GET</method>
<uri>/cspace-services/vocabularies/</uri>
</test>
- <test ID="GetVocabularyItems" auth="admin@core.collectionspace.org">
+ <test ID="GetVocabularyItems">
<method>GET</method>
<uri>/cspace-services/vocabularies/${Vocabulary1.CSID}/items/</uri>
<response>
<expected level="ADDOK"/>
- <filename>vocabulary/res/GetVocabularyItems.res.xml</filename>
+ <filename>vocabulary/responses/GetVocabularyItems.res.xml</filename>
<vars>
<var ID="I3displayName">${Item3DupeOrder.displayName}</var>
</vars>
</response>
</test>
- <test ID="GetVocabularyItem" auth="admin@core.collectionspace.org">
+ <test ID="GetVocabularyItem">
<method>GET</method>
<uri>/cspace-services/vocabularies/${Vocabulary1.CSID}/items/${Item1.CSID}</uri>
</test>
- <test ID="GetVocabularyItemRefObjs" auth="admin@core.collectionspace.org">
+ <test ID="GetVocabularyItemRefObjs">
<method>GET</method>
<uri>/cspace-services/vocabularies/${Vocabulary1.CSID}/items/${Item1.CSID}/refObjs</uri>
</test>
import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.document.Hierarchy;
import org.collectionspace.services.common.query.QueryManager;
+import org.collectionspace.services.common.repository.RepositoryClient;
import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
import org.collectionspace.services.config.ClientType;
import org.collectionspace.services.config.service.ServiceBindingType;
import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.jaxb.AbstractCommonList.ListItem;
import org.collectionspace.services.lifecycle.TransitionDef;
import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
/**
* The Class AuthorityResource.
@PUT
@Path("{csid}")
public byte[] updateAuthority(
+ @Context ResourceMap resourceMap,
+ @Context UriInfo uriInfo,
@PathParam("csid") String specifier,
String xmlPayload) {
PoxPayloadOut result = null;
return result.getBytes();
}
+ /**
+ * Delete all the items in an authority list.
+ *
+ * @param specifier
+ * @param uriInfo
+ * @return
+ */
+ @DELETE
+ @Path("{csid}/items")
+ public Response deleteAuthorityItemList(@PathParam("csid") String specifier,
+ @Context UriInfo uriInfo) {
+ uriInfo = new UriInfoWrapper(uriInfo);
+
+ try {
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(uriInfo);
+ RepositoryClient<PoxPayloadIn, PoxPayloadOut> repoClient = this.getRepositoryClient(ctx);
+
+ CoreSessionInterface repoSession = repoClient.getRepositorySession(ctx);
+ try {
+ DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
+ //
+ // Delete all the items one by one
+ //
+ AbstractCommonList itemsList = this.getAuthorityItemList(ctx, specifier, uriInfo);
+ for (ListItem item : itemsList.getListItem()) {
+ deleteAuthorityItem(ctx, specifier, getCsid(item), AuthorityServiceUtils.UPDATE_REV);
+ }
+ } catch (Throwable t) {
+ repoSession.setTransactionRollbackOnly();
+ throw t;
+ } finally {
+ repoClient.releaseRepositorySession(ctx, repoSession);
+ }
+
+ return Response.status(HttpResponseCodes.SC_OK).build();
+ } catch (Exception e) {
+ throw bigReThrow(e, ServiceMessages.DELETE_FAILED, specifier);
+ }
+ }
+
/**
* Delete authority
*
try {
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(uriInfo);
- DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
-
Specifier spec = Specifier.getSpecifier(specifier, "getAuthority", "GET");
- if (spec.form == SpecifierForm.CSID) {
- if (logger.isDebugEnabled()) {
- logger.debug("deleteAuthority with csid=" + spec.value);
- }
- ensureCSID(spec.value, ServiceMessages.DELETE_FAILED, "Authority.csid");
- getRepositoryClient(ctx).delete(ctx, spec.value, handler);
- } else {
- if (logger.isDebugEnabled()) {
- logger.debug("deleteAuthority with specifier=" + spec.value);
- }
- String whereClause = RefNameServiceUtils.buildWhereForAuthByName(authorityCommonSchemaName, spec.value);
- getRepositoryClient(ctx).deleteWithWhereClause(ctx, whereClause, handler);
- }
+ RepositoryClient<PoxPayloadIn, PoxPayloadOut> repoClient = this.getRepositoryClient(ctx);
+ CoreSessionInterface repoSession = repoClient.getRepositorySession(ctx);
+ try {
+ DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
+ //
+ // First try to delete all the items
+ //
+ AbstractCommonList itemsList = this.getAuthorityItemList(ctx, specifier, uriInfo);
+ for (ListItem item : itemsList.getListItem()) {
+ deleteAuthorityItem(ctx, specifier, getCsid(item), AuthorityServiceUtils.UPDATE_REV);
+ }
+
+ //
+ // Lastly, delete the parent/container
+ //
+ if (spec.form == SpecifierForm.CSID) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("deleteAuthority with csid=" + spec.value);
+ }
+ ensureCSID(spec.value, ServiceMessages.DELETE_FAILED, "Authority.csid");
+ getRepositoryClient(ctx).delete(ctx, spec.value, handler);
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("deleteAuthority with specifier=" + spec.value);
+ }
+ String whereClause = RefNameServiceUtils.buildWhereForAuthByName(authorityCommonSchemaName, spec.value);
+ getRepositoryClient(ctx).deleteWithWhereClause(ctx, whereClause, handler);
+ }
+ } catch (Throwable t) {
+ repoSession.setTransactionRollbackOnly();
+ throw t;
+ } finally {
+ repoClient.releaseRepositorySession(ctx, repoSession);
+ }
+
return Response.status(HttpResponseCodes.SC_OK).build();
} catch (Exception e) {
throw bigReThrow(e, ServiceMessages.DELETE_FAILED, specifier);
}
}
- /**
+ private String getCsid(ListItem item) {
+ String result = null;
+
+ for (Element ele : item.getAny()) {
+ String elementName = ele.getTagName().toLowerCase();
+ if (elementName.equals("csid")) {
+ result = ele.getTextContent();
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
*
* @param ctx
* @param parentspecifier - ID of the container. Can be URN or CSID form
return result;
}
+
+ public PoxPayloadOut updateAuthorityItem(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> itemServiceCtx, // Ok to be null. Will be null on PUT calls, but not on sync calls
+ ResourceMap resourceMap,
+ UriInfo uriInfo,
+ String parentspecifier,
+ String itemspecifier,
+ PoxPayloadIn theUpdate,
+ boolean shouldUpdateRevNumber,
+ Boolean isProposed,
+ Boolean isSASItem
+ ) throws Exception {
+ PoxPayloadOut result = null;
+
+ CsidAndShortIdentifier csidAndShortId = lookupParentCSIDAndShortIdentifer(itemServiceCtx, parentspecifier, "updateAuthorityItem(parent)", "UPDATE_ITEM", null);
+ String parentcsid = csidAndShortId.CSID;
+ String parentShortId = csidAndShortId.shortIdentifier;
+ //
+ // If the itemServiceCtx context is not null, use it. Otherwise, create a new context
+ //
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = itemServiceCtx;
+ if (ctx == null) {
+ ctx = createServiceContext(getItemServiceName(), theUpdate, resourceMap, uriInfo);
+ } else {
+ ctx.setInput(theUpdate); // the update payload
+ }
+
+ String itemcsid = lookupItemCSID(ctx, itemspecifier, parentcsid, "updateAuthorityItem(item)", "UPDATE_ITEM"); //use itemServiceCtx if it is not null
+
+ // We omit the parentShortId, only needed when doing a create...
+ AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parentcsid, parentShortId);
+ handler.setShouldUpdateRevNumber(shouldUpdateRevNumber);
+ if (isProposed != null) {
+ handler.setIsProposed(isProposed);
+ }
+ if (isSASItem != null) {
+ handler.setIsSASItem(isSASItem);
+ }
+ getRepositoryClient(ctx).update(ctx, itemcsid, handler);
+ result = ctx.getOutput();
+
+ return result;
+ }
/**
* Called with an existing context.
return result.getBytes();
}
- public PoxPayloadOut updateAuthorityItem(
- ServiceContext<PoxPayloadIn, PoxPayloadOut> itemServiceCtx, // Ok to be null. Will be null on PUT calls, but not on sync calls
- ResourceMap resourceMap,
- UriInfo uriInfo,
- String parentspecifier,
- String itemspecifier,
- PoxPayloadIn theUpdate,
- boolean shouldUpdateRevNumber,
- Boolean isProposed,
- Boolean isSASItem
- ) throws Exception {
- PoxPayloadOut result = null;
-
- CsidAndShortIdentifier csidAndShortId = lookupParentCSIDAndShortIdentifer(itemServiceCtx, parentspecifier, "updateAuthorityItem(parent)", "UPDATE_ITEM", null);
- String parentcsid = csidAndShortId.CSID;
- String parentShortId = csidAndShortId.shortIdentifier;
- //
- // If the itemServiceCtx context is not null, use it. Otherwise, create a new context
- //
- ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = itemServiceCtx;
- if (ctx == null) {
- ctx = createServiceContext(getItemServiceName(), theUpdate, resourceMap, uriInfo);
- } else {
- ctx.setInput(theUpdate); // the update payload
- }
-
- String itemcsid = lookupItemCSID(ctx, itemspecifier, parentcsid, "updateAuthorityItem(item)", "UPDATE_ITEM"); //use itemServiceCtx if it is not null
- // We omit the parentShortId, only needed when doing a create...
- AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parentcsid, parentShortId);
- handler.setShouldUpdateRevNumber(shouldUpdateRevNumber);
- if (isProposed != null) {
- handler.setIsProposed(isProposed);
- }
- if (isSASItem != null) {
- handler.setIsSASItem(isSASItem);
- }
- getRepositoryClient(ctx).update(ctx, itemcsid, handler);
- result = ctx.getOutput();
-
- return result;
- }
/**
* Delete authorityItem.
try {
parentcsid = lookupParentCSID(ctx, parentIdentifier, "deleteAuthorityItem(parent)", "DELETE_ITEM", null);
} catch (DocumentNotFoundException de) {
- logger.warn(String.format("Could not find parent with ID='%s' when trying to delete item ID='%s'",
- parentIdentifier, itemIdentifier));
+ String msg = String.format("Could not find parent with ID='%s' when trying to delete item ID='%s'",
+ parentIdentifier, itemIdentifier);
+ logger.warn(msg);
+ throw de;
}
String itemCsid = lookupItemCSID(ctx, itemIdentifier, parentcsid, "deleteAuthorityItem(item)", "DELETE_ITEM"); //use itemServiceCtx if it is not null
*
*/
private static final long serialVersionUID = 1L;
- final public static int HTTP_CODE = 500;
+ final public static int HTTP_CODE = 409; // Conflict response. There may be a dependency issue. For example, trying to delete a term from an authority that is being referenced in another record.
/**
* Creates a new instance of <code>DocumentNotFoundException</code> without detail message.
import org.collectionspace.services.common.repository.RepositoryClient;
import org.collectionspace.services.common.vocabulary.AuthorityResource;
import org.collectionspace.services.common.vocabulary.AuthorityServiceUtils;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.SpecifierForm;
import org.collectionspace.services.jaxb.AbstractCommonList;
import org.collectionspace.services.jaxb.AbstractCommonList.ListItem;
import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
public class VocabularyResource extends
AuthorityResource<VocabulariesCommon, VocabularyItemDocumentModelHandler> {
+ private enum Method {
+ POST, PUT;
+ }
+
private final static String vocabularyServiceName = VocabularyClient.SERVICE_PATH_COMPONENT;
private final static String VOCABULARIES_COMMON = "vocabularies_common";
VOCABULARIES_COMMON, VOCABULARYITEMS_COMMON);
}
- @Override
@POST
+ @Override
public Response createAuthority(
@Context ResourceMap resourceMap,
@Context UriInfo uriInfo,
try {
DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
String csid = repoClient.create(ctx, handler);
- handleItemsPayload(repoSession, csid, resourceMap, uriInfo, input);
+ handleItemsPayload(Method.POST, repoSession, csid, resourceMap, uriInfo, input);
UriBuilder path = UriBuilder.fromResource(resourceClass);
path.path("" + csid);
Response response = Response.created(path.build()).build();
}
}
}
+
+ @PUT
+ @Path("{csid}")
+ @Override
+ public byte[] updateAuthority(
+ @Context ResourceMap resourceMap,
+ @Context UriInfo uriInfo,
+ @PathParam("csid") String specifier,
+ String xmlPayload) {
+ PoxPayloadOut result = null;
+ try {
+ PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
+ Specifier spec = Specifier.getSpecifier(specifier, "updateAuthority", "UPDATE");
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(theUpdate);
+ RepositoryClient<PoxPayloadIn, PoxPayloadOut> repoClient = this.getRepositoryClient(ctx);
+
+ CoreSessionInterface repoSession = repoClient.getRepositorySession(ctx);
+ try {
+ DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
+ String csid;
+ if (spec.form == SpecifierForm.CSID) {
+ csid = spec.value;
+ } else {
+ String whereClause = RefNameServiceUtils.buildWhereForAuthByName(authorityCommonSchemaName, spec.value);
+ csid = getRepositoryClient(ctx).findDocCSID(null, ctx, whereClause);
+ }
+ getRepositoryClient(ctx).update(ctx, csid, handler);
+ handleItemsPayload(Method.PUT, repoSession, csid, resourceMap, uriInfo, theUpdate);
+ result = ctx.getOutput();
+ } catch (Throwable t) {
+ repoSession.setTransactionRollbackOnly();
+ throw t;
+ } finally {
+ repoClient.releaseRepositorySession(ctx, repoSession);
+ }
+ } catch (Exception e) {
+ throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
+ }
+ return result.getBytes();
+ }
- private void handleItemsPayload(CoreSessionInterface repoSession,
+ private boolean handleItemsPayload(
+ Method method,
+ CoreSessionInterface repoSession,
String parentIdentifier,
ResourceMap resourceMap,
UriInfo uriInfo,
PoxPayloadIn input) throws Exception {
+ boolean result = true;
+
PayloadInputPart abstractCommonListPart = input.getPart(PoxPayload.ABSTRACT_COMMON_LIST_ROOT_ELEMENT_LABEL);
if (abstractCommonListPart != null) {
AbstractCommonList itemsList = (AbstractCommonList) abstractCommonListPart.getBody();
for (ListItem item : itemsList.getListItem()) {
+ String errMsg = null;
+ boolean success = true;
+ Response response = null;
+ PoxPayloadOut payloadOut = null;
PoxPayloadIn itemXmlPayload = getItemXmlPayload(item);
- Response res = this.createAuthorityItem(repoSession, resourceMap, uriInfo, parentIdentifier, itemXmlPayload);
+ switch (method) {
+ case POST:
+ response = this.createAuthorityItem(repoSession, resourceMap, uriInfo, parentIdentifier, itemXmlPayload);
+ if (response.getStatus() != Response.Status.CREATED.getStatusCode()) {
+ success = false;
+ errMsg = String.format("Could not create the term list payload of vocabuary '%s'.", parentIdentifier);
+ }
+ break;
+ case PUT:
+ String itemSpecifier = getSpecifier(item);
+ if (itemSpecifier != null) {
+ payloadOut = updateAuthorityItem(repoSession, resourceMap, uriInfo, parentIdentifier, itemSpecifier, itemXmlPayload);
+ if (payloadOut == null) {
+ success = false;
+ errMsg = String.format("Could not update the term list payload of vocabuary '%s'.", parentIdentifier);
+ }
+ } else {
+ success = false;
+ errMsg = String.format("Could not update the term list payload of vocabuary '%s' because one of the item is missing a CSID or short identifier value.",
+ parentIdentifier);
+ }
+ break;
+ }
+ //
+ // Throw an exception as soon as we have problems with any item
+ //
+ if (success == false) {
+ throw new DocumentException(errMsg);
+ }
}
}
- }
+ return result;
+ }
/**
+ * We'll return null if we can create a specifier from the list item.
+ *
+ * @param item
+ * @return
+ */
+ private String getSpecifier(ListItem item) {
+ String result = null;
+
+ String csid = null;
+ for (Element ele : item.getAny()) {
+ String fieldName = ele.getTagName();
+ String fieldValue = ele.getTextContent();
+ if (fieldName.equalsIgnoreCase("csid")) {
+ result = csid = fieldValue;
+ break;
+ }
+ }
+
+ if (csid == null) {
+ String shortId = null;
+ for (Element ele : item.getAny()) {
+ String fieldName = ele.getTagName();
+ String fieldValue = ele.getTextContent();
+ if (fieldName.equalsIgnoreCase("shortIdentifier")) {
+ shortId = fieldValue;
+ break;
+ }
+ }
+
+ if (shortId != null) {
+ result = Specifier.createShortIdURNValue(shortId);
+ }
+ }
+
+ return result;
+ }
+
+ /**
* This is very brittle. If the class VocabularyitemsCommon changed with new fields we'd have to
* update this method.
*
case "description":
vocabularyItem.setDescription(fieldValue);
+ break;
+ case "csid":
+ vocabularyItem.setCsid(fieldValue);
+ break;
+
default:
throw new DocumentException(String.format("Unknown field '%s' in vocabulary item payload.",
fieldName));
return result;
}
-
+
+ private PoxPayloadOut updateAuthorityItem(
+ CoreSessionInterface repoSession,
+ ResourceMap resourceMap,
+ UriInfo uriInfo,
+ String parentSpecifier, // Either a CSID or a URN form -e.g., a8ad38ec-1d7d-4bf2-bd31 or urn:cspace:name(bugsbunny)
+ String itemSpecifier, // Either a CSID or a URN form.
+ PoxPayloadIn theUpdate) throws Exception {
+ PoxPayloadOut result = null;
+
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), theUpdate, resourceMap, uriInfo);
+ ctx.setCurrentRepositorySession(repoSession);
+
+ result = updateAuthorityItem(ctx, resourceMap, uriInfo, parentSpecifier, itemSpecifier, theUpdate,
+ AuthorityServiceUtils.UPDATE_REV, // passing TRUE so rev num increases, passing
+ AuthorityServiceUtils.NO_CHANGE, // don't change the state of the "proposed" field -we could be performing a sync or just a plain update
+ AuthorityServiceUtils.NO_CHANGE); // don't change the state of the "sas" field -we could be performing a sync or just a plain update
+
+ return result;
+ }
@GET
@Path("{csid}")