import org.collectionspace.services.common.query.QueryManager;
import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityServiceUtils;
import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
import org.collectionspace.services.config.ClientType;
import org.collectionspace.services.jaxb.AbstractCommonList;
parentspecifier, method, op, uriInfo);
return tempResult.CSID;
}
+
+ protected String lookupParentCSID(ServiceContext ctx, String parentspecifier, String method,
+ String op, UriInfo uriInfo) throws Exception {
+ CsidAndShortIdentifier tempResult = lookupParentCSIDAndShortIdentifer(ctx,
+ parentspecifier, method, op, uriInfo);
+ return tempResult.CSID;
+ }
+
private CsidAndShortIdentifier lookupParentCSIDAndShortIdentifer(
- ServiceContext itemServiceCtx,
+ ServiceContext itemServiceCtx, // Ok to be null
String parentSpecifier,
String method,
String op,
Response response = Response.status(Response.Status.NOT_MODIFIED).entity(result).type("text/plain").build();
throw new CSWebApplicationException(response);
}
-
- return result;
+ return result;
+ }
+
+ /**
+ * We override the base method, so we can decide if we need to update the rev number. We won't
+ * if we are performing a synchronization with the SAS.
+ * @param csid
+ * @param theUpdate
+ * @param ctx
+ * @return
+ * @throws Exception
+ */
+ @Override
+ protected PoxPayloadOut update(String csid,
+ PoxPayloadIn theUpdate, // not used in this method, but could be used by an overriding method
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx)
+ throws Exception {
+ AuthorityDocumentModelHandler handler = (AuthorityDocumentModelHandler) createDocumentHandler(ctx);
+ handler.setShouldUpdateRevNumber(this.shouldUpdateRevNumber(ctx));
+ getRepositoryClient(ctx).update(ctx, csid, handler);
+ return ctx.getOutput();
+ }
+
+ /**
+ * Look for a property in the current context to determine if we're handling a sync request.
+ * @param ctx
+ * @return
+ */
+ private boolean shouldUpdateRevNumber(ServiceContext ctx) {
+ boolean result = true;
+
+ Boolean flag = (Boolean) ctx.getProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY);
+ if (flag != null) {
+ result = flag.booleanValue();
+ }
+
+ return result;
}
/**
}
}
- protected Response createAuthorityItem(ServiceContext ctx, String parentspecifier) throws Exception {
+ protected Response createAuthorityItem(ServiceContext ctx, String parentspecifier, boolean shouldUpdateRevNumber) throws Exception {
Response result = null;
// Note: must have the parentShortId, to do the create.
- CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(null, parentspecifier, "createAuthorityItem", "CREATE_ITEM", null);
- DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler =
- createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
+ CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(ctx, parentspecifier, "createAuthorityItem", "CREATE_ITEM", null);
+ AuthorityItemDocumentModelHandler handler =
+ (AuthorityItemDocumentModelHandler) createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
+ handler.setShouldUpdateRevNumber(shouldUpdateRevNumber);
String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
UriBuilder path = UriBuilder.fromResource(resourceClass);
path.path(parent.CSID + "/items/" + itemcsid);
*/
public Response createAuthorityItemWithParentContext(ServiceContext parentCtx,
String parentspecifier,
- PoxPayloadIn input) throws Exception {
+ PoxPayloadIn input,
+ boolean shouldUpdateRevNumber) throws Exception {
Response result = null;
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), input,
if (parentCtx.getCurrentRepositorySession() != null) {
ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession());
}
- result = this.createAuthorityItem(ctx, parentspecifier);
+ result = this.createAuthorityItem(ctx, parentspecifier, shouldUpdateRevNumber);
return result;
}
try {
PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), input, resourceMap, uriInfo);
- result = this.createAuthorityItem(ctx, parentspecifier);
+ result = this.createAuthorityItem(ctx, parentspecifier, AuthorityServiceUtils.UPDATE_REV);
} catch (Exception e) {
throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
}
}
//FIXME: This method is almost identical to the method org.collectionspace.services.common.updateWorkflowWithTransition() so
- // they should be consolidated -be DRY (don't repeat yourself).
+ // they should be consolidated -be DRY (D)on't (R)epeat (Y)ourself.
@PUT
@Path("{csid}/items/{itemcsid}" + WorkflowClient.SERVICE_PATH + "/{transition}")
public byte[] updateItemWorkflowWithTransition(
String itemIdentifier) throws Exception {
PoxPayloadOut result = null;
- String parentcsid = lookupParentCSID(parentIdentifier, "getAuthorityItem(parent)", "GET_ITEM", null);
+ String parentcsid = lookupParentCSID(ctx, parentIdentifier, "getAuthorityItem(parent)", "GET_ITEM", null);
// We omit the parentShortId, only needed when doing a create...
DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createItemDocumentHandler(ctx, parentcsid, null);
CsidAndShortIdentifier parent;
boolean neededSync = false;
- parent = lookupParentCSIDAndShortIdentifer(null, parentIdentifier, "syncAuthorityItem(parent)", "SYNC_ITEM", null);
+ parent = lookupParentCSIDAndShortIdentifer(ctx, parentIdentifier, "syncAuthorityItem(parent)", "SYNC_ITEM", null);
AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
Specifier parentSpecifier = getSpecifier(parent.CSID, "getAuthority", "GET");
Specifier itemSpecifier = getSpecifier(itemIdentifier, "getAuthorityItem", "GET");
try {
PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
- result = updateAuthorityItem(null, resourceMap, uriInfo, parentSpecifier, itemSpecifier, theUpdate, true); // passing TRUE so parent authority rev num increases
+ result = updateAuthorityItem(null, resourceMap, uriInfo, parentSpecifier, itemSpecifier, theUpdate,
+ AuthorityServiceUtils.UPDATE_REV); // passing TRUE so rev num increases
} catch (Exception e) {
throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
}
}
public PoxPayloadOut updateAuthorityItem(
- ServiceContext itemServiceCtx, // Ok to be null
+ ServiceContext 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 shouldUpdateParentRev) throws Exception {
+ boolean shouldUpdateRevNumber) throws Exception {
PoxPayloadOut result = null;
CsidAndShortIdentifier csidAndShortId = lookupParentCSIDAndShortIdentifer(itemServiceCtx, parentspecifier, "updateAuthorityItem(parent)", "UPDATE_ITEM", null);
// We omit the parentShortId, only needed when doing a create...
AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parentcsid, parentShortId);
- handler.setShouldUpdateParentRevNumber(shouldUpdateParentRev);
+ handler.setShouldUpdateRevNumber(shouldUpdateRevNumber);
getRepositoryClient(ctx).update(ctx, itemcsid, handler);
result = ctx.getOutput();
*/
public abstract class AuthorityDocumentModelHandler<AuthCommon>
extends NuxeoDocumentModelHandler<AuthCommon> {
-
- private final Logger logger = LoggerFactory.getLogger(AuthorityDocumentModelHandler.class);
- protected String authorityCommonSchemaName;
+
+ private final Logger logger = LoggerFactory.getLogger(AuthorityDocumentModelHandler.class);
+
+ protected String authorityCommonSchemaName;
protected String authorityItemCommonSchemaName;
+ protected boolean shouldUpdateRevNumber;
public AuthorityDocumentModelHandler(String authorityCommonSchemaName, String authorityItemCommonSchemaName) {
this.authorityCommonSchemaName = authorityCommonSchemaName;
this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
}
+ public void setShouldUpdateRevNumber(boolean flag) {
+ this.shouldUpdateRevNumber = flag;
+ }
+
+ public boolean getShouldUpdateRevNumber() {
+ return this.shouldUpdateRevNumber;
+ }
+
/**
* The entity type expected from the JAX-RS Response object
*/
Long sasRev = getRevision(sasPayloadIn);
if (sasRev > rev) {
+ //
+ // First, sync all the authority items
+ //
syncAllItems(ctx, sasSpecifier);
+ //
+ // Next, sync the authority resource/record itself
+ //
ResourceMap resourceMap = ctx.getResourceMap();
String resourceName = ctx.getClient().getServiceName();
AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
- PoxPayloadOut payloadOut = authorityResource.update(ctx, resourceMap, null, docModel.getName(), sasPayloadIn);
+ ctx.setProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY, // Since it is a sync, don't update the rev. Instead use the rev from the SAS
+ new Boolean(AuthorityServiceUtils.DONT_UPDATE_REV));
+ PoxPayloadOut payloadOut = authorityResource.update(ctx, resourceMap, ctx.getUriInfo(), docModel.getName(),
+ sasPayloadIn);
if (payloadOut != null) {
ctx.setOutput(payloadOut);
result = true;
List<Element> itemList = getItemList(sasPayloadInItemList);
if (itemList != null) {
for (Element e:itemList) {
- String remoteRefName = XmlTools.getElementValue(e, "//refName");
+ String remoteRefName = XmlTools.getElementValue(e, "refName");
long status = syncRemoteItemWithLocalItem(ctx, remoteRefName);
if (status == 1) {
created++;
ResourceMap resourceMap = ctx.getResourceMap();
String resourceName = ctx.getClient().getServiceName();
AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
- Response response = authorityResource.createAuthorityItemWithParentContext(ctx, authoritySpecifier.value, sasPayloadIn);
+ Response response = authorityResource.createAuthorityItemWithParentContext(ctx, authoritySpecifier.value,
+ sasPayloadIn, AuthorityServiceUtils.DONT_UPDATE_REV);
if (response.getStatus() != Response.Status.CREATED.getStatusCode()) {
throw new DocumentException(String.format("Could not create new authority item '%s' during synchronization of the '%s' authority.",
itemIdentifier, parentIdentifier));
//
// If we get here, we know the item exists both locally and remotely, so we need to synchronize them
//
- authorityResource.synchronizeItemWithParentContext(ctx, parentIdentifier, itemIdentifier);
- result = 0;
+ PoxPayloadOut theUpdate = authorityResource.synchronizeItemWithParentContext(ctx, parentIdentifier, itemIdentifier);
+ if (theUpdate != null) {
+ result = 0; // mean we neeed to sync this item with SAS
+ logger.debug(String.format("Sync'd authority item parent='%s' id='%s with SAS. Updated payload is: \n%s",
+ parentIdentifier, itemIdentifier, theUpdate.getXmlPayload()));
+ }
- return result;
+ return result; // -1 = no sync needed, 0 = sync'd, 1 = created new item
}
private PoxPayloadIn getPayloadInItemList(ServiceContext ctx, Specifier specifier) throws Exception {
public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
super.fillAllParts(wrapDoc, action);
//
- // Update the record's revision number on both CREATE and UPDATE actions
+ // Update the record's revision number on both CREATE and UPDATE actions, but not on SYNC
//
- updateRevNumbers(wrapDoc);
+ if (this.getShouldUpdateRevNumber() == true) { // We won't update rev numbers on synchronization with SAS
+ updateRevNumbers(wrapDoc);
+ }
}
protected void updateRevNumbers(DocumentWrapper<DocumentModel> wrapDoc) {
public String getShortIdentifier(String authCSID, String schemaName) throws Exception {
String shortIdentifier = null;
CoreSessionInterface repoSession = null;
+ boolean releaseSession = false;
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = this.getServiceContext();
RepositoryClientImpl nuxeoRepoClient = (RepositoryClientImpl)this.getRepositoryClient(ctx);
protected String authorityCommonSchemaName;
protected String authorityItemCommonSchemaName;
private String authorityItemTermGroupXPathBase;
- private boolean shouldUpdateParentRevNumber = true;
+ private boolean shouldUpdateRevNumber = true;
/**
* inVocabulary is the parent Authority for this context
*/
abstract public String getParentCommonSchemaName();
- public boolean getShouldUpdateParentRevNumber() {
- return this.shouldUpdateParentRevNumber;
+ public boolean getShouldUpdateRevNumber() {
+ return this.shouldUpdateRevNumber;
}
- public void setShouldUpdateParentRevNumber(boolean flag) {
- this.shouldUpdateParentRevNumber = flag;
+ public void setShouldUpdateRevNumber(boolean flag) {
+ this.shouldUpdateRevNumber = flag;
}
@Override
// Get the rev number of the authority item so we can compare with rev number of shared authority
//
DocumentModel itemDocModel = NuxeoUtils.getDocFromSpecifier(ctx, getRepositorySession(), getAuthorityItemCommonSchemaName(),
- authorityItemSpecifier.getItemSpecifier());
+ authorityItemSpecifier);
if (itemDocModel == null) {
throw new DocumentNotFoundException(String.format("Could not find authority item resource with CSID='%s'",
authorityItemSpecifier.getItemSpecifier().value));
AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
PoxPayloadOut payloadOut = authorityResource.updateAuthorityItem(ctx,
resourceMap,
- null,
+ ctx.getUriInfo(),
authorityDocModel.getName(), // parent's CSID
itemDocModel.getName(), // item's CSID
sasPayloadIn, // the payload from the SAS
//
// Update the record's revision number on both CREATE and UPDATE actions
//
- updateRevNumbers(wrapDoc);
+ if (this.getShouldUpdateRevNumber() == true) { // We won't update rev numbers on synchronization with SAS
+ updateRevNumbers(wrapDoc);
+ }
}
+ /**
+ * Update the revision number of both the item and the item's parent.
+ * @param wrapDoc
+ * @throws Exception
+ */
protected void updateRevNumbers(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
DocumentModel documentModel = wrapDoc.getWrappedObject();
Long rev = (Long)documentModel.getProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.REV);
//
// Next, update the inAuthority (the parent's) rev number
//
- if (this.shouldUpdateParentRevNumber == true) {
- DocumentModel inAuthorityDocModel = NuxeoUtils.getDocFromCsid(getServiceContext(), getRepositorySession(), getInAuthority());
- Long parentRev = (Long)inAuthorityDocModel.getProperty(getParentCommonSchemaName(), AuthorityJAXBSchema.REV);
- if (parentRev == null) {
- parentRev = new Long(0);
- }
- parentRev++;
- inAuthorityDocModel.setProperty(getParentCommonSchemaName(), AuthorityJAXBSchema.REV, parentRev);
- getRepositorySession().saveDocument(inAuthorityDocModel);
+ DocumentModel inAuthorityDocModel = NuxeoUtils.getDocFromCsid(getServiceContext(), getRepositorySession(), getInAuthority());
+ Long parentRev = (Long)inAuthorityDocModel.getProperty(getParentCommonSchemaName(), AuthorityJAXBSchema.REV);
+ if (parentRev == null) {
+ parentRev = new Long(0);
}
+ parentRev++;
+ inAuthorityDocModel.setProperty(getParentCommonSchemaName(), AuthorityJAXBSchema.REV, parentRev);
+ getRepositorySession().saveDocument(inAuthorityDocModel);
}
/**
public class AuthorityServiceUtils {
private static final Logger logger = LoggerFactory.getLogger(AuthorityIdentifierUtils.class);
+ public static final String SHOULD_UPDATE_REV_PROPERTY = "SHOULD_UPDATE_REV_PROPERTY";
+ public static final boolean DONT_UPDATE_REV = false;
+ public static final boolean UPDATE_REV = true;
+
static public PoxPayloadIn getPayloadIn(AuthorityItemSpecifier specifier, String serviceName, Class responseType) throws Exception {
PoxPayloadIn result = null;
cspace.auth=true
# default user
#cspace.user=admin@core.collectionspace.org
-cspace.user=admin@core.collectionspace.org
+cspace.user=admin@testsci.collectionspace.org
cspace.password=Administrator
# default tenant
cspace.tenant=1
ctx.setResourceMap(resourceMap);
if (parentCtx != null && parentCtx.getCurrentRepositorySession() != null) {
ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession()); // Reuse the current repo session if one exists
+ ctx.setProperties(parentCtx.getProperties()); // transfer all the parent properties to the current context
}
result = update(csid, theUpdate, ctx); //==> CALL implementation method, which subclasses may override.
+ ":" + AuthorityItemJAXBSchema.SHORT_IDENTIFIER
+ "='" + name + "' AND "
+ authorityItemCommonSchemaName + ":"
- + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
+ + AuthorityItemJAXBSchema.IN_AUTHORITY + "=" // parent value must be a CSID, not a URN short ID form
+ "'" + parentcsid + "'";
}
import org.collectionspace.services.common.document.DocumentUtils;
import org.collectionspace.services.common.query.QueryContext;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.SpecifierForm;
import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentException;
return result;
}
+ static public DocumentModel getDocFromSpecifier(
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
+ CoreSessionInterface repoSession,
+ String schemaName,
+ AuthorityItemSpecifier specifier) throws Exception {
+ DocumentModel result = null;
+
+ if (specifier.getItemSpecifier().form == SpecifierForm.CSID) {
+ result = getDocFromCsid(ctx, repoSession, specifier.getItemSpecifier().value);
+ } else {
+ //
+ // The parent part of the specifier must be a CSID form.
+ //
+ if (specifier.getParentSpecifier().form != SpecifierForm.CSID) {
+ throw new DocumentException(String.format("Specifier for item parent must be of CSID form but was '%s'",
+ specifier.getParentSpecifier().value));
+ }
+ //
+ // Build the query to get the authority item. Parent value must be a CSID.
+ //
+ String whereClause = RefNameServiceUtils.buildWhereForAuthItemByName(schemaName,
+ specifier.getItemSpecifier().value, specifier.getParentSpecifier().value); // parent value must be a CSID
+ QueryContext queryContext = new QueryContext(ctx, whereClause);
+ //
+ // Set of query context using the current service context, but change the document type
+ // to be the base Nuxeo document type so we can look for the document across service workspaces
+ //
+ queryContext.setDocType(NuxeoUtils.BASE_DOCUMENT_TYPE);
+
+ DocumentModelList docModelList = null;
+ //
+ // Since we're doing a query, we get back a list so we need to make sure there is only
+ // a single result since CSID values are supposed to be unique.
+ String query = buildNXQLQuery(ctx, queryContext);
+ docModelList = repoSession.query(query);
+ long resultSize = docModelList.totalSize();
+ if (resultSize == 1) {
+ result = docModelList.get(0);
+ } else if (resultSize > 1) {
+ throw new DocumentException("Found more than 1 document with specifier ID = " + specifier.getItemSpecifier().value);
+ }
+ }
+
+ return result;
+ }
+
static public DocumentModel getDocFromSpecifier(
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
CoreSessionInterface repoSession,