import org.collectionspace.services.account.AccountResource;
import org.collectionspace.services.account.TenantResource;
import org.collectionspace.services.blob.BlobResource;
++import org.collectionspace.services.client.PoxPayloadIn;
++import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.collectionobject.CollectionObjectResource;
import org.collectionspace.services.id.IDResource;
import org.collectionspace.services.media.MediaResource;
import java.util.HashSet;
import java.util.Set;
++
++
//import org.collectionspace.services.common.FileUtils;
import org.collectionspace.services.authorization.PermissionResource;
import org.collectionspace.services.authorization.RoleResource;
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
-- private ResourceMap resourceMap = new ResourceMapImpl();
++ private ResourceMap<PoxPayloadIn, PoxPayloadOut> resourceMap = new ResourceMapImpl();
private ServletContext servletContext = null;
public CollectionSpaceJaxRsApplication() {
throw bigReThrow(e, ServiceMessages.DELETE_FAILED, accCsid);
}
}
--
}
final Logger logger = LoggerFactory.getLogger(AuthorityResource.class);
- protected Specifier getSpecifier(String specifierIn, String method, String op) throws CSWebApplicationException {
- if (logger.isDebugEnabled()) {
- logger.debug("getSpecifier called by: " + method + " with specifier: " + specifierIn);
- }
- if (specifierIn != null) {
- if (!specifierIn.startsWith(URN_PREFIX)) {
- // We'll assume it is a CSID and complain if it does not match
- return new Specifier(SpecifierForm.CSID, specifierIn);
- } else {
- if (specifierIn.startsWith(URN_PREFIX_NAME, URN_PREFIX_LEN)) {
- int closeParen = specifierIn.indexOf(')', URN_NAME_PREFIX_LEN);
- if (closeParen >= 0) {
- return new Specifier(SpecifierForm.URN_NAME,
- specifierIn.substring(URN_NAME_PREFIX_LEN, closeParen));
- }
- } else if (specifierIn.startsWith(URN_PREFIX_ID, URN_PREFIX_LEN)) {
- int closeParen = specifierIn.indexOf(')', URN_ID_PREFIX_LEN);
- if (closeParen >= 0) {
- return new Specifier(SpecifierForm.CSID,
- specifierIn.substring(URN_ID_PREFIX_LEN, closeParen));
- }
- }
- }
- }
- logger.error(method + ": bad or missing specifier!");
- Response response = Response.status(Response.Status.BAD_REQUEST).entity(
- op + " failed on bad or missing Authority specifier").type(
- "text/plain").build();
- throw new CSWebApplicationException(response);
- }
--
/**
* Instantiates a new Authority resource.
*/
try {
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(ui);
AuthorityDocumentModelHandler handler = (AuthorityDocumentModelHandler)createDocumentHandler(ctx);
- specifier = getSpecifier(csid, "getAuthority", "GET");
+ specifier = Specifier.getSpecifier(csid, "getAuthority", "GET");
+ handler.setShouldUpdateRevNumber(AuthorityServiceUtils.DONT_UPDATE_REV); // Never update rev number on sync calls
neededSync = getRepositoryClient(ctx).synchronize(ctx, specifier, handler);
payloadOut = ctx.getOutput();
} catch (Exception e) {
throws Exception {
AuthorityDocumentModelHandler handler = (AuthorityDocumentModelHandler) createDocumentHandler(ctx);
Boolean shouldUpdateRev = (Boolean) ctx.getProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY);
-- if (shouldUpdateRev != null && shouldUpdateRev == true) {
-- handler.setShouldUpdateRevNumber(true);
++ if (shouldUpdateRev != null) {
++ handler.setShouldUpdateRevNumber(shouldUpdateRev);
}
getRepositoryClient(ctx).update(ctx, csid, handler);
return ctx.getOutput();
}
}
- protected Response createAuthorityItem(ServiceContext ctx, String parentIdentifier, boolean shouldUpdateRevNumber) throws Exception {
+ /**
+ *
+ * @param ctx
+ * @param parentspecifier - ID of the container. Can be URN or CSID form
+ * @param shouldUpdateRevNumber - Indicates if the revision number should be updated on create -won't do this when synching with SAS
+ * @param proposed - In a shared authority context, indicates if this item just a proposed item and not yet part of the SAS authority
+ * @return
+ * @throws Exception
+ */
- protected Response createAuthorityItem(ServiceContext ctx, String parentspecifier,
++ protected Response createAuthorityItem(ServiceContext ctx, String parentIdentifier,
+ boolean shouldUpdateRevNumber,
+ boolean proposed) throws Exception {
Response result = null;
// Note: must have the parentShortId, to do the create.
AuthorityItemDocumentModelHandler handler =
(AuthorityItemDocumentModelHandler) createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
handler.setShouldUpdateRevNumber(shouldUpdateRevNumber);
+ handler.setIsProposed(proposed);
+ // Make the client call
String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
+
+ // Build the JAX-RS response
UriBuilder path = UriBuilder.fromResource(resourceClass);
path.path(parent.CSID + "/items/" + itemcsid);
result = Response.created(path.build()).build();
* @throws Exception
*/
public Response createAuthorityItemWithParentContext(ServiceContext parentCtx,
- String parentspecifier,
+ String parentIdentifier,
PoxPayloadIn input,
- boolean shouldUpdateRevNumber) throws Exception {
+ boolean shouldUpdateRevNumber,
+ boolean isProposed) throws Exception {
Response result = null;
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), input,
if (parentCtx.getCurrentRepositorySession() != null) {
ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession());
}
- result = this.createAuthorityItem(ctx, parentIdentifier, shouldUpdateRevNumber);
- result = this.createAuthorityItem(ctx, parentspecifier, shouldUpdateRevNumber, isProposed);
++ result = this.createAuthorityItem(ctx, parentIdentifier, shouldUpdateRevNumber, isProposed);
return result;
}
try {
PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), input, resourceMap, uriInfo);
- result = this.createAuthorityItem(ctx, parentIdentifier, AuthorityServiceUtils.UPDATE_REV);
- result = this.createAuthorityItem(ctx, parentspecifier, AuthorityServiceUtils.UPDATE_REV,
++ result = this.createAuthorityItem(ctx, parentIdentifier, AuthorityServiceUtils.UPDATE_REV,
+ AuthorityServiceUtils.PROPOSED);
} catch (Exception e) {
throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
}
handler.setDocumentFilter(myFilter);
getRepositoryClient(ctx).get(ctx, handler);
}
- // TODO should we assert that the item is in the passed vocab?
+
result = (PoxPayloadOut) ctx.getOutput();
- String inAuthority = XmlTools.getElementValue(result.getDOMDocument(), AuthorityItemJAXBSchema.REF_NAME);
+ if (result != null) {
++ String inAuthority = XmlTools.getElementValue(result.getDOMDocument(), "//" + AuthorityItemJAXBSchema.IN_AUTHORITY);
+ if (inAuthority.equalsIgnoreCase(parentcsid) == false) {
+ throw new Exception(String.format("Looked up item = '%s' and found with inAuthority = '%s', but expected inAuthority = '%s'.",
+ itemSpec.value, inAuthority, parentcsid));
+ }
+ }
+
return result;
}
}
/**
- * Return a paged list of authority items.
+ * Gets the authorityItem list for the specified authority
+ * If partialPerm is specified, keywords will be ignored.
*
- * @param existingContext
- * @param specifier
- * @param uriInfo
- * @return
- * @throws Exception
+ * @param specifier either a CSID or one of the urn forms
+ * @param partialTerm if non-null, matches partial terms
+ * @param keywords if non-null, matches terms in the keyword index for items
+ * @param ui passed to include additional parameters, like pagination controls
- *
- * @return the authorityItem list
++ *
*/
- @GET
- @Path("{csid}/items")
- @Produces("application/xml")
- public AbstractCommonList getAuthorityItemList(@PathParam("csid") String specifier,
- @Context UriInfo uriInfo) {
+ public AbstractCommonList getAuthorityItemList(ServiceContext existingContext,
+ String specifier,
+ UriInfo uriInfo) throws Exception {
AbstractCommonList result = null;
-
- ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
- MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
+
- try {
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
+ MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
+ if (existingContext != null && existingContext.getCurrentRepositorySession() != null) { // Merge some of the existing context properties with our new context
+ ctx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession());
+ ctx.setProperties(existingContext.getProperties());
+ }
-
- String orderBy = queryParams.getFirst(IClientQueryParams.ORDER_BY_PARAM);
- String termStatus = queryParams.getFirst(SEARCH_TYPE_TERMSTATUS);
- String keywords = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
- String advancedSearch = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_AS);
- String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
+
+ String orderBy = queryParams.getFirst(IClientQueryParams.ORDER_BY_PARAM);
+ String termStatus = queryParams.getFirst(SEARCH_TYPE_TERMSTATUS);
+ String keywords = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
+ String advancedSearch = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_AS);
+ String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
- // For the wildcard case, parentcsid is null, but docHandler will deal with this.
- // We omit the parentShortId, only needed when doing a create...
- String parentcsid = PARENT_WILDCARD.equals(specifier) ? null :
- lookupParentCSID(specifier, "getAuthorityItemList", "LIST", uriInfo);
- DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler =
- createItemDocumentHandler(ctx, parentcsid, null);
-
- DocumentFilter myFilter = handler.getDocumentFilter();
- // If we are not wildcarding the parent, add a restriction
- if (parentcsid != null) {
- myFilter.appendWhereClause(authorityItemCommonSchemaName + ":"
- + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
- + "'" + parentcsid + "'",
- IQueryManager.SEARCH_QUALIFIER_AND);
- }
+ // For the wildcard case, parentcsid is null, but docHandler will deal with this.
+ // We omit the parentShortId, only needed when doing a create...
+ String parentcsid = PARENT_WILDCARD.equals(specifier) ? null :
+ lookupParentCSID(specifier, "getAuthorityItemList", "LIST", uriInfo);
+ DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler =
+ createItemDocumentHandler(ctx, parentcsid, null);
+
+ DocumentFilter myFilter = handler.getDocumentFilter();
+ // If we are not wildcarding the parent, add a restriction
+ if (parentcsid != null) {
+ myFilter.appendWhereClause(authorityItemCommonSchemaName + ":"
+ + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
+ + "'" + parentcsid + "'",
+ IQueryManager.SEARCH_QUALIFIER_AND);
+ }
- if (Tools.notBlank(termStatus)) {
- // Start with the qualified termStatus field
- String qualifiedTermStatusField = authorityItemCommonSchemaName + ":"
- + AuthorityItemJAXBSchema.TERM_STATUS;
- String[] filterTerms = termStatus.trim().split("\\|");
- String tsClause = QueryManager.createWhereClauseToFilterFromStringList(qualifiedTermStatusField, filterTerms, IQueryManager.FILTER_EXCLUDE);
- myFilter.appendWhereClause(tsClause, IQueryManager.SEARCH_QUALIFIER_AND);
- }
+ if (Tools.notBlank(termStatus)) {
+ // Start with the qualified termStatus field
+ String qualifiedTermStatusField = authorityItemCommonSchemaName + ":"
+ + AuthorityItemJAXBSchema.TERM_STATUS;
+ String[] filterTerms = termStatus.trim().split("\\|");
+ String tsClause = QueryManager.createWhereClauseToFilterFromStringList(qualifiedTermStatusField, filterTerms, IQueryManager.FILTER_EXCLUDE);
+ myFilter.appendWhereClause(tsClause, IQueryManager.SEARCH_QUALIFIER_AND);
+ }
- result = search(ctx, handler, uriInfo, orderBy, keywords, advancedSearch, partialTerm);
+ result = search(ctx, handler, uriInfo, orderBy, keywords, advancedSearch, partialTerm);
+
+ return result;
+ }
+
+ /**
+ * Gets the authorityItem list for the specified authority
+ * If partialPerm is specified, keywords will be ignored.
+ *
+ * @param specifier either a CSID or one of the urn forms
+ * @param partialTerm if non-null, matches partial terms
+ * @param keywords if non-null, matches terms in the keyword index for items
+ * @param ui passed to include additional parameters, like pagination controls
+ *
+ * @return the authorityItem list
+ */
+ @GET
+ @Path("{csid}/items")
+ @Produces("application/xml")
+ public AbstractCommonList getAuthorityItemList(@PathParam("csid") String specifier,
+ @Context UriInfo uriInfo) {
+ AbstractCommonList result = null;
+
+ try {
+ result = getAuthorityItemList(NULL_CONTEXT, specifier, uriInfo);
} catch (Exception e) {
throw bigReThrow(e, ServiceMessages.LIST_FAILED);
}
@Context UriInfo uriInfo) {
AuthorityRefDocList authRefDocList = null;
try {
- ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
- MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
- //
+ authRefDocList = getReferencingObjects(null, parentSpecifier, itemSpecifier, uriTemplateRegistry, uriInfo);
+ } catch (Exception e) {
+ throw bigReThrow(e, ServiceMessages.GET_FAILED);
+ }
+
+ if (authRefDocList == null) {
+ Response response = Response.status(Response.Status.NOT_FOUND).entity(
+ "Get failed, the requested Item CSID:" + itemSpecifier + ": was not found.").type(
+ "text/plain").build();
+ throw new CSWebApplicationException(response);
+ }
+ return authRefDocList;
+ }
+
+ public AuthorityRefDocList getReferencingObjects(
+ ServiceContext existingContext,
+ String parentspecifier,
+ String itemspecifier,
+ UriTemplateRegistry uriTemplateRegistry,
+ UriInfo uriInfo) throws Exception {
+ AuthorityRefDocList authRefDocList = null;
+
- String parentcsid = lookupParentCSID(parentspecifier, "getReferencingObjects(parent)", "GET_ITEM_REF_OBJS", uriInfo);
- String itemcsid = lookupItemCSID(ctx, itemspecifier, parentcsid, "getReferencingObjects(item)", "GET_ITEM_REF_OBJS");
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
+ MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
+
+ // Merge parts of existing context with our new context
+ //
+ if (existingContext != null && existingContext.getCurrentRepositorySession() != null) {
+ ctx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession()); // If one exists, use the existing repo session
+ ctx.setProperties(existingContext.getProperties());
+ }
+
+ String parentcsid = lookupParentCSID(parentspecifier, "getReferencingObjects(parent)", "GET_ITEM_REF_OBJS", uriInfo);
+ String itemcsid = lookupItemCSID(ctx, itemspecifier, parentcsid, "getReferencingObjects(item)", "GET_ITEM_REF_OBJS");
- List<String> serviceTypes = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP);
- if(serviceTypes == null || serviceTypes.isEmpty()) {
- serviceTypes = ServiceBindingUtils.getCommonServiceTypes(true); //CSPACE-5359: Should now include objects, procedures, and authorities
- }
-
- // Note that we have to create the service handler for the Items, not the main parent resource
- // We omit the parentShortId, only needed when doing a create...
+ List<String> serviceTypes = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP);
+ if(serviceTypes == null || serviceTypes.isEmpty()) {
+ serviceTypes = ServiceBindingUtils.getCommonServiceTypes(true); //CSPACE-5359: Should now include objects, procedures, and authorities
+ }
+
+ // Note that we have to create the service context for the Items, not the main service
+ // We omit the parentShortId, only needed when doing a create...
- AuthorityItemDocumentModelHandler<?> handler = (AuthorityItemDocumentModelHandler<?>)
- createItemDocumentHandler(ctx, parentcsid, null);
+ AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parentcsid, null);
+ authRefDocList = handler.getReferencingObjects(ctx, uriTemplateRegistry, serviceTypes, getRefPropName(), itemcsid);
- authRefDocList = handler.getReferencingObjects(ctx, uriTemplateRegistry, serviceTypes, getRefPropName(), itemcsid);
- } catch (Exception e) {
- throw bigReThrow(e, ServiceMessages.GET_FAILED);
- }
- if (authRefDocList == null) {
- Response response = Response.status(Response.Status.NOT_FOUND).entity(
- "Get failed, the requested Item CSID:" + itemspecifier + ": was not found.").type(
- "text/plain").build();
- throw new CSWebApplicationException(response);
- }
- return authRefDocList;
+ return authRefDocList;
}
/**
String itemIdentifier) throws Exception {
PoxPayloadOut result = null;
AuthorityItemSpecifier specifier;
-- CsidAndShortIdentifier parent;
boolean neededSync = false;
-- parent = lookupParentCSIDAndShortIdentifer(ctx, parentIdentifier, "syncAuthorityItem(parent)", "SYNC_ITEM", null);
++ CsidAndShortIdentifier 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");
+ handler.setIsProposed(AuthorityServiceUtils.NOT_PROPOSED); // In case it was formally locally proposed, clear the proposed flag
+ // Create an authority item specifier
+ Specifier parentSpecifier = Specifier.getSpecifier(parent.CSID, "getAuthority", "GET");
+ Specifier itemSpecifier = Specifier.getSpecifier(itemIdentifier, "getAuthorityItem", "GET");
specifier = new AuthorityItemSpecifier(parentSpecifier, itemSpecifier);
//
neededSync = getRepositoryClient(ctx).synchronize(ctx, specifier, handler);
* Using the parent and item ID, sync the local item with the SAS (shared authority server)
* Used by the AuthorityItemDocumentModelHandler when synchronizing a list of remote authority items with a
* local authority. The parent context was created for the authority (parent) because the sync started there.
-- * @param parentCtx
++ * @param existingCtx
* @param parentIdentifier
* @param itemIdentifier
* @return
* @throws Exception
*/
-- public PoxPayloadOut synchronizeItemWithParentContext(
-- ServiceContext parentCtx,
++ public PoxPayloadOut synchronizeItemWithExistingContext(
++ ServiceContext existingCtx,
String parentIdentifier,
String itemIdentifier
) throws Exception {
PoxPayloadOut result = null;
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(),
-- parentCtx.getResourceMap(),
-- parentCtx.getUriInfo());
-- if (parentCtx.getCurrentRepositorySession() != null) {
-- ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession());
++ existingCtx.getResourceMap(),
++ existingCtx.getUriInfo());
++ if (existingCtx.getCurrentRepositorySession() != null) {
++ ctx.setCurrentRepositorySession(existingCtx.getCurrentRepositorySession());
}
result = synchronizeItem(ctx, parentIdentifier, itemIdentifier);
public Response deleteAuthorityItem(
@PathParam("csid") String parentcsid,
@PathParam("itemcsid") String itemcsid) {
-
+ Response result = null;
+ //try{
if (logger.isDebugEnabled()) {
logger.debug("deleteAuthorityItem with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid);
}
+
try {
- ensureCSID(parentcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.parentcsid");
- ensureCSID(itemcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.itemcsid");
+ deleteAuthorityItem(null, parentcsid, itemcsid);
+ result = Response.status(HttpResponseCodes.SC_OK).build();
+ } catch (Exception e) {
+ throw bigReThrow(e, ServiceMessages.DELETE_FAILED + " itemcsid: " + itemcsid + " parentcsid:" + parentcsid);
+ }
-
+ //Laramie, removing this catch, since it will surely fail below, since itemcsid or parentcsid will be null.
+ return result;
+ }
-
+ // }catch (Throwable t){
+ public void deleteAuthorityItem(ServiceContext existingCtx,
+ String parentcsid,
+ String itemcsid) throws Exception {
+ Response result = null;
-
+ // System.out.println("ERROR in setting up DELETE: "+t);
+ ensureCSID(parentcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.parentcsid");
+ ensureCSID(itemcsid, ServiceMessages.DELETE_FAILED, "AuthorityItem.itemcsid");
- // Note that we have to create the service context for the Items, not the main service
- ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName());
+ // }
- // try {
- // Note that we have to create the service context for the Items, not the main service
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName());
+ if (existingCtx != null && existingCtx.getCurrentRepositorySession() != null) {
+ ctx.setCurrentRepositorySession(existingCtx.getCurrentRepositorySession()); // Use existing repo session if one exists
+ ctx.setProperties(existingCtx.getProperties());
+ }
- DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
- getRepositoryClient(ctx).delete(ctx, itemcsid, handler);
- }
-
+ DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
+ getRepositoryClient(ctx).delete(ctx, itemcsid, handler);
- return Response.status(HttpResponseCodes.SC_OK).build();
- } catch (Exception e) {
- throw bigReThrow(e, ServiceMessages.DELETE_FAILED + " itemcsid: " + itemcsid + " parentcsid:" + parentcsid);
+ }
- }
- public final static String hierarchy = "hierarchy";
+
@GET
@Path("{csid}/items/{itemcsid}/" + hierarchy)
@Produces("application/xml")
public class AuthorityServiceUtils {
private static final Logger logger = LoggerFactory.getLogger(AuthorityIdentifierUtils.class);
-
+ //
- // Revision property statics
- //
+ // Used to keep track if an authority item's is deprecated
+ public static final String IS_DEPRECATED_PROPERTY = "IS_DEPRECATED_PROPERTY";
+ public static final Boolean DEPRECATED = true;
+ public static final Boolean NOT_DEPRECATED = !DEPRECATED;
+
+ // Used to keep track if an authority item's rev number should be updated
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;
-
+ public static final boolean DONT_UPDATE_REV = !UPDATE_REV;
++
+ // Used to keep track if an authority item is a locally proposed member of a SAS authority
+ public static final String IS_PROPOSED_PROPERTY = "IS_PROPOSED";
+ public static final Boolean PROPOSED = true;
+ public static final Boolean NOT_PROPOSED = !PROPOSED;
+ public static final Boolean NO_CHANGE = null;
- //
- // Makes a call to the SAS server for a authority payload
- //
static public PoxPayloadIn requestPayloadIn(ServiceContext ctx, Specifier specifier, Class responseType) throws Exception {
PoxPayloadIn result = null;
AuthorityClient client = (AuthorityClient) ctx.getClient();
-- Response res = client.read(specifier.value);
++ Response res = client.read(specifier.getURNValue());
try {
int statusCode = res.getStatus();
//
// Using the short ID of the local authority, create a URN specifier to retrieve the SAS authority
//
- Specifier sasSpecifier = new Specifier(SpecifierForm.URN_NAME, Specifier.createShortIdURNValue(shortId));
- Specifier sasSpecifier = new Specifier(SpecifierForm.URN_NAME, RefNameUtils.createShortIdRefName(shortId));
++ Specifier sasSpecifier = new Specifier(SpecifierForm.URN_NAME, shortId);
PoxPayloadIn sasPayloadIn = AuthorityServiceUtils.requestPayloadIn(ctx, sasSpecifier, getEntityResponseType());
//
- // Compare revision number of local authority with that of the shared authority on the SAS.
// If the authority on the SAS is newer, synch all the items and then the authority record as well
//
++ //
Long sasRev = getRevision(sasPayloadIn);
if (sasRev > localRev) {
//
//
// Next, sync the authority resource/record itself
//
- ResourceMap resourceMap = ctx.getResourceMap();
- String resourceName = ctx.getClient().getServiceName();
- AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
- // Set this context property since we don't want to update the revision number on sync updates
- ctx.setProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY, AuthorityServiceUtils.DONT_UPDATE_REV);
- PoxPayloadOut payloadOut = authorityResource.update(ctx, resourceMap, ctx.getUriInfo(), docModel.getName(),
+ AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
++ ctx.setProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY, AuthorityServiceUtils.DONT_UPDATE_REV); // Don't update the rev number, use the rev number for the SAS instance instead
+ PoxPayloadOut payloadOut = authorityResource.update(ctx, ctx.getResourceMap(), ctx.getUriInfo(), docModel.getName(),
sasPayloadIn);
if (payloadOut != null) {
ctx.setOutput(payloadOut);
//
// Iterate over the list of items/terms in the remote authority
//
- PoxPayloadIn sasPayloadInItemList = getPayloadInItemList(ctx, sasAuthoritySpecifier);
- PoxPayloadIn sasPayloadInItemList = getPayloadInItemList(ctx, sasSpecifier);
++ PoxPayloadIn sasPayloadInItemList = requestPayloadInItemList(ctx, sasAuthoritySpecifier);
List<Element> itemList = getItemList(sasPayloadInItemList);
if (itemList != null) {
for (Element e:itemList) {
totalItemsProcessed++;
}
}
- //
+ // Now see if we need to deprecate or delete items that have been hard-deleted from the SAS but still exist
+ // locally. Subtract (remove) the list of remote items from the list of local items to determine which
+ // of the remote items have been hard deleted.
+ //
- ArrayList<String> itemsInLocalAuthority = getItemsInLocalAuthority(ctx, sasSpecifier);
++ ArrayList<String> itemsInLocalAuthority = getItemsInLocalAuthority(ctx, sasAuthoritySpecifier);
+ if (itemsInLocalAuthority.removeAll(itemsInRemoteAuthority) == true) {
+ ArrayList<String> remainingItems = itemsInLocalAuthority; // now a subset of local items
+ //
+ // We now need to either hard-deleted or deprecate the remaining authorities
+ //
+ deleteOrDeprecateItems(ctx, remainingItems);
+ }
+
logger.info(String.format("Total number of items processed during sync: %d", totalItemsProcessed));
logger.info(String.format("Number of items synchronized: %d", synched));
return result;
}
-
++
++ /**
++ *
++ * @param ctx
++ * @param refNameList
++ * @return
++ * @throws Exception
++ */
+ private long deleteOrDeprecateItems(ServiceContext ctx, ArrayList<String> refNameList) throws Exception {
+ long result = 0;
- ArrayList<String> failureList = new ArrayList<String>();
+
++ ArrayList<String> failureList = new ArrayList<String>();
+ for (String refName:refNameList) {
+ AuthorityTermInfo itemInfo = RefNameUtils.parseAuthorityTermInfo(refName);
+ AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
+ try {
+ authorityResource.deleteAuthorityItem(ctx, itemInfo.inAuthority.csid, itemInfo.csid);
+ result++;
+ } catch (DocumentException de) {
- //
- // If we can't delete the item, it might be because there are existing records referencing it. So
- // we need to mark the item as deprecated
- //
+ logger.info(String.format("Hit document exception trying to delete or deprecate '%s' during sync",
+ refName), de);
+ boolean marked = markAuthorityItemAsDeprecated(ctx, itemInfo);
+ if (marked == true) {
+ result++;
+ }
+ } catch (Exception e) {
+ logger.warn(String.format("Unable to delete authority item '%s'", refName), e);
+ }
+ }
-
++
+ if (logger.isWarnEnabled() == true) {
+ if (result != refNameList.size()) {
- logger.warn(String.format("Unable to delete or deprecate some authority items during synchronization with SAS. Deleted or deprecated %d of %d",
++ logger.warn(String.format("Unable to delete or deprecate some authority items during synchronization with SAS. Deleted or deprecated %d of %d. See the services log file for details.",
+ result, refNameList.size()));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Mark the authority item as deprecated.
+ *
+ * @param ctx
+ * @param itemInfo
+ * @throws Exception
+ */
+ private boolean markAuthorityItemAsDeprecated(ServiceContext ctx, AuthorityTermInfo itemInfo) throws Exception {
+ boolean result = false;
+
+ try {
+ String itemCsid = itemInfo.csid;
+ DocumentModel docModel = NuxeoUtils.getDocFromCsid(ctx, (CoreSessionInterface)ctx.getCurrentRepositorySession(), itemCsid);
+ docModel.setProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.DEPRECATED,
+ new Boolean(AuthorityServiceUtils.DEPRECATED));
++ CoreSessionInterface session = (CoreSessionInterface) ctx.getCurrentRepositorySession();
++ session.saveDocument(docModel);
+ result = true;
+ } catch (Exception e) {
+ logger.warn(String.format("Could not mark item '%s' as deprecated.", itemInfo.name), e);
+ }
+
+ return result;
+ }
+
+ /**
+ * Gets the list of SAS related items in the local authority. We exlude items with the "proposed" flags because
+ * we want a list with only SAS created items.
+ *
+ * We need to add pagination support to this call!!!
+ *
+ * @param ctx
+ * @param specifier
+ * @return
+ * @throws Exception
+ */
+ private ArrayList<String> getItemsInLocalAuthority(ServiceContext ctx, Specifier specifier) throws Exception {
+ ArrayList<String> result = new ArrayList<String>();
+
+ ResourceMap resourceMap = ctx.getResourceMap();
+ String resourceName = ctx.getClient().getServiceName();
+ AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
+ AbstractCommonList acl = authorityResource.getAuthorityItemList(ctx, specifier.value, ctx.getUriInfo());
+ List<ListItem> listItemList = acl.getListItem();
+ for (ListItem listItem:listItemList) {
+ Boolean proposed = getBooleanValue(listItem, AuthorityItemJAXBSchema.PROPOSED);
+ if (proposed == false) { // exclude "proposed" (i.e., local-only items)
+ result.add(AbstractCommonListUtils.ListItemGetElementValue(listItem, AuthorityItemJAXBSchema.REF_NAME));
+ }
+ }
+
+ return result;
+ }
+
+ private Boolean getBooleanValue(ListItem listItem, String name) {
+ Boolean result = null;
+
+ String value = AbstractCommonListUtils.ListItemGetElementValue(listItem, name);
+ if (value != null) {
+ result = Boolean.valueOf(value);
+ }
+
+ return result;
+ }
+
+ private String getStringValue(ListItem listItem, String name) {
+ return AbstractCommonListUtils.ListItemGetElementValue(listItem, AuthorityItemJAXBSchema.REF_NAME);
+ }
/**
* This is a sync method.
//
// Using the payload from the remote server, create a local copy of the item
//
- ResourceMap resourceMap = ctx.getResourceMap();
- String resourceName = ctx.getClient().getServiceName();
- AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
- Response response = authorityResource.createAuthorityItemWithParentContext(ctx, authoritySpecifier.value,
+ AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
+ Response response = authorityResource.createAuthorityItemWithParentContext(ctx, authoritySpecifier.getURNValue(),
- sasPayloadIn, AuthorityServiceUtils.DONT_UPDATE_REV);
+ sasPayloadIn, AuthorityServiceUtils.DONT_UPDATE_REV, AuthorityServiceUtils.NOT_PROPOSED);
//
// Check the response for successful POST result
//
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));
+ }
//
- // Handle the workflow state by "locking" this new copy of the SAS item.
+ // Handle the workflow state
//
- }
+ authorityResource.updateItemWorkflowWithTransition(ctx, parentIdentifier, itemIdentifier,
+ WorkflowClient.WORKFLOWTRANSITION_LOCK, AuthorityServiceUtils.DONT_UPDATE_REV);
- }
+ }
/**
* Try to synchronize a remote item (using its refName) with a local item. If the local doesn't yet
return 1; // exit with status of 1 means we created a new authority item
}
//
- // If we get here, we know the item exists both locally and remotely, so we need to synchronize them.
- // We synchronize by calling the authority resource (the JAX-RS resource) class' sync method for an item.
+ // If we get here, we know the item exists both locally and remotely, so we need to synchronize them
+ //
- PoxPayloadOut theUpdate = authorityResource.synchronizeItemWithParentContext(ctx, parentIdentifier, itemIdentifier);
- if (theUpdate != null) {
- result = 0; // means we needed 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()));
+ //
- 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()));
++ try {
++ PoxPayloadOut theUpdate = authorityResource.synchronizeItemWithExistingContext(ctx, parentIdentifier, itemIdentifier);
++ if (theUpdate != null) {
++ result = 0; // means we needed 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()));
++ }
++ } catch (DocumentException de) {
++ cow();
}
return result; // -1 = no sync needed, 0 = sync'd, 1 = created new item
}
-- private PoxPayloadIn getPayloadInItemList(ServiceContext ctx, Specifier specifier) throws Exception {
++ private PoxPayloadIn requestPayloadInItemList(ServiceContext ctx, Specifier specifier) throws Exception {
PoxPayloadIn result = null;
AuthorityClient client = (AuthorityClient) ctx.getClient();
-- Response res = client.readItemList(specifier.value,
++ Response res = client.readItemList(specifier.getURNValue(),
null, // partial term string
null // keyword string
);
import org.collectionspace.services.common.document.DocumentException;
import org.collectionspace.services.common.document.DocumentFilter;
import org.collectionspace.services.common.document.DocumentNotFoundException;
++import org.collectionspace.services.common.document.DocumentReferenceException;
import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.repository.RepositoryClient;
import org.collectionspace.services.common.vocabulary.AuthorityJAXBSchema;
if (this.getShouldUpdateRevNumber() == true) { // We don't update the rev number of synchronization requests
updateRevNumbers(wrapDoc);
}
++
++ DocumentModel docModel = wrapDoc.getWrappedObject();
++ if (this.hasReferencingObjects(this.getServiceContext(), docModel) == true) {
++
++ }
}
/**
- * This method synchronizes/updates a single authority item resource with the corresponding SAS items.
- * The argument 'wrapDoc' in most CSpace methods usually contains a resource payload -like a nuxeo document model. However,
+ * This method synchronizes/updates a single authority item resource.
+ * for the handleSync method, the wrapDoc argument contains a authority item specifier.
*/
@Override
public boolean handleSync(DocumentWrapper<Object> wrapDoc) throws Exception {
authorityItemSpecifier.getItemSpecifier().value));
}
Long localItemRev = (Long) NuxeoUtils.getProperyValue(itemDocModel, AuthorityItemJAXBSchema.REV);
+ Boolean localIsProposed = (Boolean) NuxeoUtils.getProperyValue(itemDocModel, AuthorityItemJAXBSchema.PROPOSED);
String localItemCsid = itemDocModel.getName();
- String localItemWorkflowState = (String) NuxeoUtils.getProperyValue(itemDocModel, CollectionSpaceClient.CORE_WORKFLOWSTATE);
+ String localItemWorkflowState = itemDocModel.getCurrentLifeCycleState();
String itemShortId = (String) NuxeoUtils.getProperyValue(itemDocModel, AuthorityItemJAXBSchema.SHORT_IDENTIFIER);
//
Long sasRev = getRevision(sasPayloadIn);
String sasWorkflowState = getWorkflowState(sasPayloadIn);
//
- // Update the local item if the shared authority item is newer or if the local item is a proposed item that is now becoming a true SAS item
+ // If the shared authority item is newer, update our local copy
//
- if (sasRev > localItemRev) {
- AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
+ if (sasRev > localItemRev || localIsProposed) {
- ResourceMap resourceMap = ctx.getResourceMap();
- String resourceName = this.getAuthorityServicePath();
- AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
++ AuthorityResource authorityResource = (AuthorityResource) ctx.getResource(getAuthorityServicePath());
PoxPayloadOut payloadOut = authorityResource.updateAuthorityItem(ctx,
- resourceMap,
+ ctx.getResourceMap(),
ctx.getUriInfo(),
- localParentCsid, // parent's CSID
- localItemCsid, // item's CSID
- sasPayloadIn, // the payload from the remote SAS
+ localParentCsid, // parent's CSID
+ localItemCsid, // item's CSID
+ sasPayloadIn, // the payload from the remote SAS
- AuthorityServiceUtils.DONT_UPDATE_REV); // don't update the parent's revision number
+ AuthorityServiceUtils.DONT_UPDATE_REV, // don't update the parent's revision number
+ AuthorityServiceUtils.NOT_PROPOSED); // The items is not proposed, make it a real SAS item now
if (payloadOut != null) {
ctx.setOutput(payloadOut);
result = true;
// If the workflow states are different, we need to update the local's to reflects the remote's
//
if (localItemWorkflowState.equalsIgnoreCase(sasWorkflowState) == false) {
- AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
- ResourceMap resourceMap = ctx.getResourceMap();
- String resourceName = this.getAuthorityServicePath();
- AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
++ AuthorityResource authorityResource = (AuthorityResource) ctx.getResource(getAuthorityServicePath()); // Get the authority (parent) client not the item client
//
- // We need to move the local item to the SAS workflow state -i.e., the locked state.
+ // We need to move the local item to the SAS workflow state. This might involve multiple transitions.
//
List<String> transitionList = getTransitionList(sasWorkflowState, localItemWorkflowState);
for (String transition:transitionList) {
++ if (transition.equalsIgnoreCase(WorkflowClient.WORKFLOWTRANSITION_DELETE) == true) {
++ if (hasReferencingObjects(ctx, itemDocModel)) {
++ throw new DocumentReferenceException(String.format("Cannot soft-delete authority item '%s' because it still has records in the system that are referencing it. See the service layer log file for details.",
++ itemDocModel.getName()));
++ }
++ }
authorityResource.updateItemWorkflowWithTransition(ctx, localParentCsid, localItemCsid, transition, AuthorityServiceUtils.DONT_UPDATE_REV);
}
+ result = true;
}
return result;
*/
private List<String> getTransitionList(String sasWorkflowState, String localItemWorkflowState) {
List<String> result = new ArrayList<String>();
- // TO BE COMPLETELED
++
+ //
+ // If the SAS authority items is soft-deleted, we need to mark the local item as soft-deleted
+ //
- if (sasWorkflowState.contains(WorkflowClient.WORKFLOWSTATE_DELETED) == true) {
++ if (sasWorkflowState.contains(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
++ } else if (sasWorkflowState.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
++ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ }
++
+ //
- // Ensure the local item is in a "locked" state. Items sync'd with a SAS should always be locked
++ // Ensure the local item is always in a "locked" state. Items sync'd with a SAS should always be locked
+ //
- if (localItemWorkflowState.contains(WorkflowClient.WORKFLOWSTATE_LOCKED) != true) {
++ if (localItemWorkflowState.contains(WorkflowClient.WORKFLOWSTATE_LOCKED) != true) { // REM - This may be a bad assumption to make.
+ result.add(WorkflowClient.WORKFLOWTRANSITION_LOCK);
+ }
+
return result;
}
// Ensure we have required fields set properly
handleInAuthority(wrapDoc.getWrappedObject());
}
-
- /* This method ensures that before we delete an authority item, there are no records in the system that reference it.
+
++ /*
++ * This method gets called after the primary update to an authority item has happened. If the authority item's refName
++ * has changed, then we need to updated all the records that use that refname with the new/updated version
+ *
+ * (non-Javadoc)
- * @see org.collectionspace.services.common.document.DocumentHandler#handleDelete(org.collectionspace.services.common.document.DocumentWrapper)
+ */
+ @Override
+ public void handleDelete(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
- UriTemplateRegistry uriTemplateRegistry = ServiceMain.getInstance().getUriTemplateRegistry();
+ ServiceContext ctx = getServiceContext();
+ DocumentModel docModel = wrapDoc.getWrappedObject();
++
++ if (hasReferencingObjects(ctx, docModel) == true) {
++ throw new DocumentReferenceException(String.format("Cannot delete authority item '%s' because it still has records in the system that are referencing it. See the service layer log file for details.",
++ docModel.getName()));
++ }
++ }
++
++ /**
++ * Checks to see if an authority item has referencing objects.
++ *
++ * @param ctx
++ * @param docModel
++ * @return
++ * @throws Exception
++ */
++ private boolean hasReferencingObjects(ServiceContext ctx, DocumentModel docModel) throws Exception {
++ boolean result = false;
++
+ String inAuthorityCsid = (String) docModel.getProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.IN_AUTHORITY);
++ AuthorityResource authorityResource = (AuthorityResource)ctx.getResource(getAuthorityServicePath());
+ String itemCsid = docModel.getName();
-
- ResourceMap resourceMap = ctx.getResourceMap();
- String resourceName = this.getAuthorityServicePath();
- AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
- //
- // If the authority item has references to it from other resources, we can't and won't
- // delete it.
- //
++ UriTemplateRegistry uriTemplateRegistry = ServiceMain.getInstance().getUriTemplateRegistry();
+ AuthorityRefDocList refObjs = authorityResource.getReferencingObjects(ctx, inAuthorityCsid, itemCsid,
+ uriTemplateRegistry, ctx.getUriInfo());
- if (refObjs.getTotalItems() != 0) {
- throw new DocumentException(String.format("Can not delete authority item '%s' because it still has records in the system that are referencing it.",
- itemCsid));
++
++ if (refObjs.getTotalItems() > 0) {
++ result = true;
++ logger.error(String.format("Cannot delete authority item '%s' because it still has %d records in the system that are referencing it.",
++ itemCsid, refObjs.getTotalItems()));
++ logReferencingObjects(docModel, refObjs);
+ }
++
++ return result;
++ }
++
++ private void logReferencingObjects(DocumentModel docModel, AuthorityRefDocList refObjs) {
++ List<AuthorityRefDocList.AuthorityRefDocItem> items = refObjs.getAuthorityRefDocItem();
++ int i = 0;
++ for (AuthorityRefDocList.AuthorityRefDocItem item : items) {
++ logger.debug(docModel.getName() + ": list-item[" + i + "] "
++ + item.getDocType() + "("
++ + item.getDocId() + ") Name:["
++ + item.getDocName() + "] Number:["
++ + item.getDocNumber() + "] in field:["
++ + item.getSourceField() + "]");
++ }
+ }
+
/*
* This method gets called after the primary update to an authority item has happened. If the authority item's refName
* has changed, then we need to updated all the records that use that refname with the new/updated version
AuthorityItemJAXBSchema.IN_AUTHORITY, inAuthority);
}
++ /**
++ * Returns a list of records that reference this authority item
++ *
++ * @param ctx
++ * @param uriTemplateRegistry
++ * @param serviceTypes
++ * @param propertyName
++ * @param itemcsid
++ * @return
++ * @throws Exception
++ */
public AuthorityRefDocList getReferencingObjects(
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
UriTemplateRegistry uriTemplateRegistry,
// First, create the Loanout
// We fetch the resource class by service name
-- NuxeoBasedResource resource = resourceMap.get( LoanoutClient.SERVICE_NAME);
++ NuxeoBasedResource resource = (NuxeoBasedResource) resourceMap.get( LoanoutClient.SERVICE_NAME);
Response response = resource.create(resourceMap, null, loanoutPayload);
if(response.getStatus() != CREATED_STATUS) {
completionStatus = STATUS_ERROR;
+ "<relationshipType>"+RELATION_TYPE+"</relationshipType>"
+ "<predicateDisplayName>"+RELATION_PREDICATE_DISP+"</predicateDisplayName>"
+ "</ns2:relations_common></document>";
-- NuxeoBasedResource resource = resourceMap.get(RelationClient.SERVICE_NAME);
++ NuxeoBasedResource resource = (NuxeoBasedResource) resourceMap.get(RelationClient.SERVICE_NAME);
Response response = resource.create(resourceMap, null, relationPayload);
if(response.getStatus() != CREATED_STATUS) {
completionStatus = STATUS_ERROR;
private InvocationResults updateComputedCurrentLocations(List<String> csids) {
ResourceMap resourcemap = getResourceMap();
-- NuxeoBasedResource collectionObjectResource = resourcemap.get(CollectionObjectClient.SERVICE_NAME);
-- NuxeoBasedResource movementResource = resourcemap.get(MovementClient.SERVICE_NAME);
++ NuxeoBasedResource collectionObjectResource = (NuxeoBasedResource) resourcemap.get(CollectionObjectClient.SERVICE_NAME);
++ NuxeoBasedResource movementResource = (NuxeoBasedResource) resourcemap.get(MovementClient.SERVICE_NAME);
String computedCurrentLocation;
int numUpdated = 0;
// UC Berkeley Botanical Garden v2.4 implementation.
// #################################################################
protected PoxPayloadOut findByCsid(String serviceName, String csid) throws URISyntaxException, DocumentException {
-- NuxeoBasedResource resource = getResourceMap().get(serviceName);
++ NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(serviceName);
return findByCsid(resource, csid);
}
private List<String> getMemberCsidsFromGroup(String serviceName, String groupCsid) throws URISyntaxException, DocumentException {
ResourceMap resourcemap = getResourceMap();
-- NuxeoBasedResource resource = resourcemap.get(serviceName);
++ NuxeoBasedResource resource = (NuxeoBasedResource) resourcemap.get(serviceName);
return getMemberCsidsFromGroup(resource, groupCsid);
}
private List<String> getNoContextCsids() throws URISyntaxException {
ResourceMap resourcemap = getResourceMap();
-- NuxeoBasedResource collectionObjectResource = resourcemap.get(CollectionObjectClient.SERVICE_NAME);
++ NuxeoBasedResource collectionObjectResource = (NuxeoBasedResource) resourcemap.get(CollectionObjectClient.SERVICE_NAME);
UriInfo uriInfo = createUriInfo();
uriInfo = addFilterToExcludeSoftDeletedRecords(uriInfo);
AbstractCommonList collectionObjects = collectionObjectResource.getList(uriInfo);
/** The xml text. */
private String xmlPayload;
-- private Document domDocument;
++ protected Document domDocument;
/** The payload name. */
private String payloadName;
return new PayloadOutputPart(label, element);
}
++ /**
++ * A synonym for the toXML() method.
++ * @return
++ */
++ public String asXML() {
++ return toXML();
++ }
++
/**
* Creates and returns an XML string representation of ourself.
*
*/
public String toXML() {
String result = null;
++ Document document = createDOMFromParts();
++
++ result = document.asXML();
++
++ if (logger.isTraceEnabled() == true) {
++ logger.trace("\n\n<<<< Payload Out : BEGIN <<<<\n" + result + "\n<<<< Payload Out : END <<<<\n");
++ }
++
++ return result;
++ }
++
++ private Document createDOMFromParts() {
++ Document result = null;
++
Document document = DocumentHelper.createDocument();
document.setXMLEncoding("UTF-8");
document.setName(getName());
//Add if (logger.isTraceEnabled() == true) logger.trace("Output part: " + outPart.getLabel() + " was empty.");
}
}
-- result = document.asXML();
++ result = document;
++
++ return result;
++ }
-- if (logger.isTraceEnabled() == true) {
-- logger.trace("\n\n<<<< Payload Out : BEGIN <<<<\n" +
-- result +
-- "\n<<<< Payload Out : END <<<<\n");
++ /**
++ * Gets the DOM object that we created at init time. This should never be null;
++ *
++ * @return the dOM document
++ */
++ @Override
++ public Document getDOMDocument() {
++ if (domDocument == null) {
++ domDocument = createDOMFromParts();
}
-- return result;
++ return this.domDocument;
}
--
++
/**
* Adds the part.
*
package org.collectionspace.services.common;
import java.lang.reflect.Method;
++import java.util.HashMap;
import java.util.List;
++import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.api.Tools;
++import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.context.ServiceContextProperties;
import org.collectionspace.services.common.document.BadRequestException;
import org.collectionspace.services.common.security.UnauthorizedException;
import org.collectionspace.services.common.storage.StorageClient;
import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
++import org.collectionspace.services.config.service.ServiceBindingType;
import org.jboss.resteasy.core.ResourceMethodInvoker;
//import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.spi.HttpRequest;
public boolean allowAnonymousAccess(HttpRequest request,
Class<?> resourceClass) {
return false;
-- }
++ }
++
++ /**
++ * Returns a UriRegistry entry: a map of tenant-qualified URI templates
++ * for the current resource, for all tenants
++ *
++ * @return a map of URI templates for the current resource, for all tenants
++ */
++ public Map<UriTemplateRegistryKey,StoredValuesUriTemplate> getUriRegistryEntries() {
++ Map<UriTemplateRegistryKey,StoredValuesUriTemplate> uriRegistryEntriesMap =
++ new HashMap<UriTemplateRegistryKey,StoredValuesUriTemplate>();
++ List<String> tenantIds = getTenantBindingsReader().getTenantIds();
++ for (String tenantId : tenantIds) {
++ uriRegistryEntriesMap.putAll(getUriRegistryEntries(tenantId, getDocType(tenantId), UriTemplateFactory.RESOURCE));
++ }
++ return uriRegistryEntriesMap;
++ }
++
++ /**
++ * Returns a resource's document type.
++ *
++ * @param tenantId
++ * @return
++ */
++ @Override
++ public String getDocType(String tenantId) {
++ return getDocType(tenantId, getServiceName());
++ }
++
++ /**
++ * Returns the document type associated with a specified service, within a specified tenant.
++ *
++ * @param tenantId a tenant ID
++ * @param serviceName a service name
++ * @return the Nuxeo document type associated with that service and tenant.
++ */
++ // FIXME: This method may properly belong in a different services package or class.
++ // Also, we need to check for any existing methods that may duplicate this one.
++ protected String getDocType(String tenantId, String serviceName) {
++ String docType = "";
++ if (Tools.isBlank(tenantId)) {
++ return docType;
++ }
++ ServiceBindingType sb = getTenantBindingsReader().getServiceBinding(tenantId, serviceName);
++ if (sb == null) {
++ return docType;
++ }
++ docType = sb.getObject().getName(); // Reads the Document Type from tenant bindings configuration
++ return docType;
++ }
++
++ /**
++ * Returns a UriRegistry entry: a map of tenant-qualified URI templates
++ * for the current resource, for a specified tenants
++ *
++ * @return a map of URI templates for the current resource, for a specified tenant
++ */
++ @Override
++ public Map<UriTemplateRegistryKey,StoredValuesUriTemplate> getUriRegistryEntries(String tenantId,
++ String docType, UriTemplateFactory.UriTemplateType type) {
++ Map<UriTemplateRegistryKey,StoredValuesUriTemplate> uriRegistryEntriesMap =
++ new HashMap<UriTemplateRegistryKey,StoredValuesUriTemplate>();
++ UriTemplateRegistryKey key;
++ if (Tools.isBlank(tenantId) || Tools.isBlank(docType)) {
++ return uriRegistryEntriesMap;
++ }
++ key = new UriTemplateRegistryKey();
++ key.setTenantId(tenantId);
++ key.setDocType(docType);
++ uriRegistryEntriesMap.put(key, getUriTemplate(type));
++ return uriRegistryEntriesMap;
++ }
++
++ /**
++ * Returns a URI template of the appropriate type, populated with the
++ * current service name as one of its stored values.
++ * *
++ * @param type a URI template type
++ * @return a URI template of the appropriate type.
++ */
++ @Override
++ public StoredValuesUriTemplate getUriTemplate(UriTemplateFactory.UriTemplateType type) {
++ Map<String,String> storedValuesMap = new HashMap<String,String>();
++ storedValuesMap.put(UriTemplateFactory.SERVICENAME_VAR, getServiceName());
++ StoredValuesUriTemplate template =
++ UriTemplateFactory.getURITemplate(type, storedValuesMap);
++ return template;
++ }
++
++ /**
++ * Returns a reader for reading values from tenant bindings configuration
++ *
++ * @return a tenant bindings configuration reader
++ */
++ @Override
++ public TenantBindingConfigReaderImpl getTenantBindingsReader() {
++ return ServiceMain.getInstance().getTenantBindingConfigReader();
++ }
++
}
package org.collectionspace.services.common;
import java.lang.reflect.Method;
++import java.util.Map;
++import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.context.ServiceContextFactory;
import org.collectionspace.services.common.document.DocumentHandler;
// <sec:filter-chain pattern="/publicitems/*/*/content"
// filters="none"/>
public boolean allowAnonymousAccess(HttpRequest request, Class<?> resourceClass);
++
++ /**
++ * Returns a UriRegistry entry: a map of tenant-qualified URI templates
++ * for the current resource, for all tenants
++ *
++ * @return a map of URI templates for the current resource, for all tenants
++ */
++ public Map<UriTemplateRegistryKey,StoredValuesUriTemplate> getUriRegistryEntries();
++ /**
++ * Returns a UriRegistry entry: a map of tenant-qualified URI templates
++ * for the current resource, for a specified tenants
++ *
++ * @return a map of URI templates for the current resource, for a specified tenant
++ */
++ public Map<UriTemplateRegistryKey,StoredValuesUriTemplate> getUriRegistryEntries(String tenantId,
++ String docType, UriTemplateFactory.UriTemplateType type);
++
++ /**
++ * Returns a URI template of the appropriate type, populated with the
++ * current service name as one of its stored values.
++ * *
++ * @param type a URI template type
++ * @return a URI template of the appropriate type.
++ */
++ public StoredValuesUriTemplate getUriTemplate(UriTemplateFactory.UriTemplateType type);
++
++ /**
++ * Returns a reader for reading values from tenant bindings configuration
++ *
++ * @return a tenant bindings configuration reader
++ */
++ public TenantBindingConfigReaderImpl getTenantBindingsReader();
++
++ /**
++ * Returns the document type of the resource based on the tenant bindings.
++ *
++ * @param tenantId
++ * @return
++ */
++ public String getDocType(String tenantId);
}
throws Exception, DocumentNotFoundException {
return getDocModelForAuthorityItem(repoSession, RefName.AuthorityItem.parse(refName));
}
--
-- protected String getDocType(String tenantId) {
-- return getDocType(tenantId, getServiceName());
-- }
--
-- /**
-- * Returns the Nuxeo document type associated with a specified service, within a specified tenant.
-- *
-- * @param tenantId a tenant ID
-- * @param serviceName a service name
-- * @return the Nuxeo document type associated with that service and tenant.
-- */
-- // FIXME: This method may properly belong in a different services package or class.
-- // Also, we need to check for any existing methods that may duplicate this one.
-- protected String getDocType(String tenantId, String serviceName) {
-- String docType = "";
-- if (Tools.isBlank(tenantId)) {
-- return docType;
-- }
-- ServiceBindingType sb = getTenantBindingsReader().getServiceBinding(tenantId, serviceName);
-- if (sb == null) {
-- return docType;
-- }
-- docType = sb.getObject().getName(); // Reads the Nuxeo Document Type from tenant bindings configuration
-- return docType;
-- }
--
-- /**
-- * Returns a UriRegistry entry: a map of tenant-qualified URI templates
-- * for the current resource, for all tenants
-- *
-- * @return a map of URI templates for the current resource, for all tenants
-- */
-- public Map<UriTemplateRegistryKey,StoredValuesUriTemplate> getUriRegistryEntries() {
-- Map<UriTemplateRegistryKey,StoredValuesUriTemplate> uriRegistryEntriesMap =
-- new HashMap<UriTemplateRegistryKey,StoredValuesUriTemplate>();
-- List<String> tenantIds = getTenantBindingsReader().getTenantIds();
-- for (String tenantId : tenantIds) {
-- uriRegistryEntriesMap.putAll(getUriRegistryEntries(tenantId, getDocType(tenantId), UriTemplateFactory.RESOURCE));
-- }
-- return uriRegistryEntriesMap;
-- }
--
-- /**
-- * Returns a UriRegistry entry: a map of tenant-qualified URI templates
-- * for the current resource, for a specified tenants
-- *
-- * @return a map of URI templates for the current resource, for a specified tenant
-- */
-- protected Map<UriTemplateRegistryKey,StoredValuesUriTemplate> getUriRegistryEntries(String tenantId,
-- String docType, UriTemplateFactory.UriTemplateType type) {
-- Map<UriTemplateRegistryKey,StoredValuesUriTemplate> uriRegistryEntriesMap =
-- new HashMap<UriTemplateRegistryKey,StoredValuesUriTemplate>();
-- UriTemplateRegistryKey key;
-- if (Tools.isBlank(tenantId) || Tools.isBlank(docType)) {
-- return uriRegistryEntriesMap;
-- }
-- key = new UriTemplateRegistryKey();
-- key.setTenantId(tenantId);
-- key.setDocType(docType);
-- uriRegistryEntriesMap.put(key, getUriTemplate(type));
-- return uriRegistryEntriesMap;
-- }
--
-- /**
-- * Returns a URI template of the appropriate type, populated with the
-- * current service name as one of its stored values.
-- * *
-- * @param type a URI template type
-- * @return a URI template of the appropriate type.
-- */
-- protected StoredValuesUriTemplate getUriTemplate(UriTemplateFactory.UriTemplateType type) {
-- Map<String,String> storedValuesMap = new HashMap<String,String>();
-- storedValuesMap.put(UriTemplateFactory.SERVICENAME_VAR, getServiceName());
-- StoredValuesUriTemplate template =
-- UriTemplateFactory.getURITemplate(type, storedValuesMap);
-- return template;
-- }
--
-- /**
-- * Returns a reader for reading values from tenant bindings configuration
-- *
-- * @return a tenant bindings configuration reader
-- */
-- protected TenantBindingConfigReaderImpl getTenantBindingsReader() {
-- return ServiceMain.getInstance().getTenantBindingConfigReader();
-- }
--
}
/*
* Maps service names to Resource instances. Use the Service Client Class to get the service name.
*/
- public interface ResourceMap extends Map<String, CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut>> {
-public interface ResourceMap extends Map<String, CollectionSpaceResource> {
++public interface ResourceMap<IT, OT> extends Map<String, CollectionSpaceResource<IT, OT>> {
}
import java.util.HashMap;
--public class ResourceMapImpl extends HashMap<String, NuxeoBasedResource> implements ResourceMap {
++import org.collectionspace.services.client.PoxPayloadIn;
++import org.collectionspace.services.client.PoxPayloadOut;
++
++public class ResourceMapImpl extends HashMap<String, CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut>> implements ResourceMap<PoxPayloadIn, PoxPayloadOut> {
++
++ /**
++ *
++ */
++ private static final long serialVersionUID = 1L;
}
*/
private synchronized void populateUriTemplateRegistry() {
if (uriTemplateRegistry.isEmpty()) {
-- NuxeoBasedResource resource = null;
++ CollectionSpaceResource resource = null;
ResourceMap resourceMap = getJaxRSResourceMap();
-- for (Map.Entry<String, NuxeoBasedResource> entry : resourceMap.entrySet()) {
++ Set<Map.Entry<String, CollectionSpaceResource>> entrySet = resourceMap.entrySet();
++ for (Map.Entry<String, CollectionSpaceResource> entry : entrySet) {
resource = entry.getValue();
Map<UriTemplateRegistryKey, StoredValuesUriTemplate> entries =
resource.getUriRegistryEntries();
uriTemplateRegistry.putAll(entries);
}
--
// FIXME: Contacts itself should not have an entry in the URI template registry;
// there should be a Contacts entry in that registry only for use in
// building URIs for resources that have contacts as a sub-resource
}
}
+ @Override
+ public CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut> getResource() throws Exception {
+ CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut> result = null;
+
+ ResourceMap resourceMap = getResourceMap();
+ String resourceName = getClient().getServiceName();
+ result = (CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut>) resourceMap.get(resourceName);
+
+ return result;
+ }
++
++ @Override
++ public CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut> getResource(String serviceName) throws Exception {
++ CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut> result = null;
++
++ ResourceMap resourceMap = getResourceMap();
++ String resourceName = serviceName;
++ result = (CollectionSpaceResource<PoxPayloadIn, PoxPayloadOut>) resourceMap.get(resourceName);
++
++ return result;
++ }
+
/* (non-Javadoc)
* @see org.collectionspace.services.common.context.RemoteServiceContextImpl#getLocalContext(java.lang.String)
*/
ServiceContext ctx = (ServiceContext) ctor.newInstance(getServiceName());
return ctx;
}
+
+ @Override
+ public CollectionSpaceResource<IT, OT> getResource() throws Exception {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("Unimplemented method.");
+ }
++
++ @Override
++ public CollectionSpaceResource<IT, OT> getResource(String serviceName)
++ throws Exception {
++ // TODO Auto-generated method stub
++ throw new RuntimeException("Unimplemented method.");
++ }
}
import javax.ws.rs.core.UriInfo;
import org.collectionspace.services.client.CollectionSpaceClient;
++import org.collectionspace.services.client.PoxPayloadIn;
++import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.common.CollectionSpaceResource;
import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.document.DocumentHandler;
*/
public void setOutput(OT output);
-- /**
- * @return the JAX-RS resource of service for the current context.
- * @throws Exception
- *
-- */
- public CollectionSpaceResource<IT, OT> getResource() throws Exception;
-
- public CollectionSpaceResource getResource();
-
/**
* @return the map of service names to resource classes.
*/
public void setRepositoryDomain(RepositoryDomainType repositoryDomain);
public CollectionSpaceClient getClient() throws Exception;
++
++ /**
++ * @return the JAX-RS resource of service for the current context.
++ * @throws Exception
++ */
++ public CollectionSpaceResource<IT, OT> getResource() throws Exception;
++
++ /**
++ * @return the JAX-RS resource of service for the current context.
++ * @throws Exception
++ */
++ public CollectionSpaceResource<IT, OT> getResource(
++ String serviceName) throws Exception;
}
--- /dev/null
--- /dev/null
++package org.collectionspace.services.common.document;
++
++public class DocumentReferenceException extends DocumentException {
++ /**
++ *
++ */
++ private static final long serialVersionUID = 1L;
++ final public static int HTTP_CODE = 500;
++
++ /**
++ * Creates a new instance of <code>DocumentNotFoundException</code> without detail message.
++ */
++ public DocumentReferenceException() {
++ setErrorCode(HTTP_CODE);
++ }
++
++ /**
++ * Constructs an instance of <code>DocumentNotFoundException</code> with the specified detail message.
++ * @param msg the detail message.
++ */
++ public DocumentReferenceException(String msg) {
++ super(msg);
++ setErrorCode(HTTP_CODE);
++ }
++
++ /**
++ * Constructs a new exception with the specified detail message and
++ * cause. <p>Note that the detail message associated with
++ * <code>cause</code> is <i>not</i> automatically incorporated in
++ * this exception's detail message.
++ *
++ * @param message the detail message (which is saved for later retrieval
++ * by the {@link #getMessage()} method).
++ * @param cause the cause (which is saved for later retrieval by the
++ * {@link #getCause()} method). (A <tt>null</tt> value is
++ * permitted, and indicates that the cause is nonexistent or
++ * unknown.)
++ * @since 1.4
++ */
++ public DocumentReferenceException(String message, Throwable cause) {
++ super(message, cause);
++ setErrorCode(HTTP_CODE);
++ }
++
++ /**
++ * Constructs a new exception with the specified cause and a detail
++ * message of <tt>(cause==null ? null : cause.toString())</tt> (which
++ * typically contains the class and detail message of <tt>cause</tt>).
++ * This constructor is useful for exceptions that are little more than
++ * wrappers for other throwables (for example, {@link
++ * java.security.PrivilegedActionException}).
++ *
++ * @param cause the cause (which is saved for later retrieval by the
++ * {@link #getCause()} method). (A <tt>null</tt> value is
++ * permitted, and indicates that the cause is nonexistent or
++ * unknown.)
++ * @since 1.4
++ */
++ public DocumentReferenceException(Throwable cause) {
++ super(cause);
++ setErrorCode(HTTP_CODE);
++ }
++}
public class RefNameServiceUtils {
public static enum SpecifierForm {
-- CSID, URN_NAME
++ CSID, URN_NAME // Either a CSID or a short ID
};
public static class Specifier {
+ //
+ // URN statics for things like urn:cspace:name(grover)
+ //
+ final static String URN_PREFIX = "urn:cspace:";
+ final static int URN_PREFIX_LEN = URN_PREFIX.length();
+ final static String URN_PREFIX_NAME = "name(";
+ final static int URN_NAME_PREFIX_LEN = URN_PREFIX_LEN + URN_PREFIX_NAME.length();
+ final static String URN_PREFIX_ID = "id(";
+ final static int URN_ID_PREFIX_LEN = URN_PREFIX_LEN + URN_PREFIX_ID.length();
+
public SpecifierForm form;
public String value;
- public String urnValue;
public Specifier(SpecifierForm form, String value) {
this.form = form;