From 341f695f2a5083650bc3f2a0a1bc18c385d5f9d8 Mon Sep 17 00:00:00 2001 From: Patrick Schmitz Date: Wed, 21 Apr 2010 06:15:30 +0000 Subject: [PATCH] CSPACE-1079 Search for documents that refer to a given Person item. Added support for describing which services are objects and which are procedures. Added support to describe which fields hold refnames. Added support to describe which fields should be used to provide summary values in the results. Only supported for PersonAuthority. Still need to add this for OrgAuthority as well. --- .../resources/OSGI-INF/core-types-contrib.xml | 2 +- .../resources/OSGI-INF/layouts-contrib.xml | 206 ++++++------ .../acquisition/AcquisitionResource.java | 5 +- .../CollectionObjectResource.java | 5 +- .../main/config/services/tenant-bindings.xml | 27 +- .../common/config/PropertyItemUtils.java | 53 ++- .../config/TenantBindingConfigReaderImpl.java | 15 +- .../common/config/TenantBindingUtils.java | 2 +- .../context/AbstractServiceContextImpl.java | 54 +-- .../common/context/ServiceBindingUtils.java | 58 +++- .../common/document/DocumentHandler.java | 1 - .../vocabulary/RefNameServiceUtils.java | 120 ++++++- .../java/RemoteDocumentModelHandlerImpl.java | 6 + .../client/java/RepositoryJavaClientImpl.java | 5 +- services/intake/client/pom.xml | 6 + .../client/test/PersonAuthRefDocsTest.java | 317 ++++++++++++++++++ .../services/intake/IntakeResource.java | 5 +- .../src/main/resources/authorityrefdocs.xsd | 44 +++ .../services/loanin/LoaninResource.java | 5 +- .../services/loanout/LoanoutResource.java | 5 +- services/person/client/pom.xml | 11 + .../client/PersonAuthorityClient.java | 11 + .../services/client/PersonAuthorityProxy.java | 13 + .../person/PersonAuthorityResource.java | 120 +++++-- 24 files changed, 905 insertions(+), 191 deletions(-) create mode 100644 services/intake/client/src/test/java/org/collectionspace/services/client/test/PersonAuthRefDocsTest.java create mode 100644 services/jaxb/src/main/resources/authorityrefdocs.xsd diff --git a/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/core-types-contrib.xml b/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/core-types-contrib.xml index e3b2a71d9..e2b0c7c73 100644 --- a/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/core-types-contrib.xml +++ b/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/core-types-contrib.xml @@ -1,7 +1,7 @@ - + diff --git a/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/layouts-contrib.xml b/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/layouts-contrib.xml index 1e0da7c20..54a1f0c5f 100644 --- a/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/layouts-contrib.xml +++ b/services/acquisition/3rdparty/nuxeo-platform-cs-acquisition/src/main/resources/OSGI-INF/layouts-contrib.xml @@ -12,28 +12,29 @@ accessionDate acquisitionAuthorizer - AcquisitionAuthorizerDate - AcquisitionDate - AcquisitionFundingDenomination - AcquisitionFundingSource - AcquisitionFundingSourceProvisos - AcquisitionMethod - AcquisitionNote - AcquisitionProvisos - AcquisitionReason - AcquisitionReferenceNumber - AcquisitionSource - GroupPurchasePriceDenomination - GroupPurchasePriceValue - ObjectOfferPriceDenomination - ObjectOfferPriceValue - ObjectPurchaseOfferPriceDenomination - ObjectPurchaseOfferPriceValue - ObjectPurchasePriceDenomination - ObjectPurchasePriceValue - OriginalObjectPurchasePriceDenomination - OriginalObjectPurchasePriceValue - TransferOfTitleNumber + acquisitionAuthorizerDate + acquisitionDate + acquisitionFundingDenomination + acquisitionFundingValue + acquisitionFundingSource + acquisitionFundingSourceProvisos + acquisitionMethod + acquisitionNote + acquisitionProvisos + acquisitionReason + acquisitionReferenceNumber + acquisitionSource + groupPurchasePriceDenomination + groupPurchasePriceValue + objectOfferPriceDenomination + objectOfferPriceValue + objectPurchaseOfferPriceDenomination + objectPurchaseOfferPriceValue + objectPurchasePriceDenomination + objectPurchasePriceValue + originalObjectPurchasePriceDenomination + originalObjectPurchasePriceValue + transferOfTitleNumber fieldCollectionDate fieldCollectionEventName fieldCollectionNumber @@ -46,7 +47,7 @@ true - acq:accessionDate + acquisitions_common:accessionDate dataInputText @@ -59,319 +60,306 @@ true - acq:acquisitionAuthorizer + acquisitions_common:acquisitionAuthorizer dataInputText - + - + true - acq:acquisitionAuthorizerDate + acquisitions_common:acquisitionAuthorizerDate dataInputText - + - + true - acq:acquisitionDate + acquisitions_common:acquisitionDate dataInputText - + - + true - acq:acquisitionFunding + acquisitions_common:acquisitionFundingDenomination dataInputText - + - + true - acq:acquisitionFundingDenomination + acquisitions_common:acquisitionFundingValue dataInputText - + - + true - acq:acquisitionFundingValue - - - dataInputText - - - - - - - - true - - acq:acquisitionFundingSource + acquisitions_common:acquisitionFundingSource dataInputText - + - + true - acq:AcquisitionFundingSourceProvisos + acquisitions_common:acquisitionFundingSourceProvisos dataInputText - + - + true - acq:AcquisitionMethod + acquisitions_common:acquisitionMethod dataInputText - + - + true - acq:AcquisitionNote + acquisitions_common:acquisitionNote dataInputText - + - + true - acq:AcquisitionProvisos + acquisitions_common:acquisitionProvisos dataInputText - + - + true - acq:AcquisitionReason + acquisitions_common:acquisitionReason dataInputText - + - + true - acq:AcquisitionReferenceNumber + acquisitions_common:acquisitionReferenceNumber dataInputText - + - + true - acq:AcquisitionSource + acquisitions_common:acquisitionSources dataInputText - + - + true - acq:groupPurchasePriceDenomination + acquisitions_common:groupPurchasePriceDenomination dataInputText - + - + true - acq:groupPurchasePriceValue + acquisitions_common:groupPurchasePriceValue dataInputText - + - + true - acq:objectOfferPriceDenomination + acquisitions_common:objectOfferPriceDenomination dataInputText - + true - acq:objectOfferPriceValue + acquisitions_common:objectOfferPriceValue dataInputText - + - + true - acq:objectPurchaseOfferPriceDenomination + acquisitions_common:objectPurchaseOfferPriceDenomination dataInputText - + - + true - acq:objectPurchaseOfferPriceValue + acquisitions_common:objectPurchaseOfferPriceValue dataInputText - + - + true - acq:objectPurchasePriceDenomination + acquisitions_common:objectPurchasePriceDenomination dataInputText - + - + true - acq:objectPurchasePriceValue + acquisitions_common:objectPurchasePriceValue dataInputText - + - + true - acq:OriginalObjectPurchasePriceDenomination + acquisitions_common:originalObjectPurchasePriceDenomination dataInputText - + - + true - acq:originalObjectPurchasePriceValue + acquisitions_common:originalObjectPurchasePriceValue dataInputText - + - + true - acq:transferOfTitleNumber + acquisitions_common:transferOfTitleNumber dataInputText @@ -384,7 +372,7 @@ true - acq:fieldCollectionDate + acquisitions_common:fieldCollectionDate dataInputText @@ -397,7 +385,7 @@ true - acq:fieldCollectionEventName + acquisitions_common:fieldCollectionEventName dataInputText @@ -410,7 +398,7 @@ true - acq:fieldCollectionNumber + acquisitions_common:fieldCollectionNumber dataInputText @@ -423,7 +411,7 @@ true - acq:fieldCollector + acquisitions_common:fieldCollector dataInputText diff --git a/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java b/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java index ab6a8c5d7..5065ddb78 100644 --- a/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java +++ b/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java @@ -43,6 +43,7 @@ import javax.ws.rs.core.UriInfo; import org.collectionspace.services.common.AbstractMultiPartCollectionSpaceResourceImpl; import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentNotFoundException; @@ -433,7 +434,9 @@ public class AcquisitionResource getRepositoryClient(ctx).getDoc(ctx, csid); RemoteDocumentModelHandlerImpl handler = (RemoteDocumentModelHandlerImpl)createDocumentHandler(ctx); - List authRefFields = ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(RefNameServiceUtils.AUTH_REF_PROP); + List authRefFields = + ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues( + ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); authRefList = handler.getAuthorityRefs(docWrapper, authRefFields); } catch (UnauthorizedException ue) { Response response = Response.status( diff --git a/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java b/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java index 643a29481..df2b554b9 100644 --- a/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java +++ b/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java @@ -49,6 +49,7 @@ import org.collectionspace.services.common.context.ServiceContextFactory; //import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.MultipartServiceContextFactory; import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.BadRequestException; import org.collectionspace.services.common.document.DocumentFilter; @@ -439,7 +440,9 @@ public class CollectionObjectResource getRepositoryClient(ctx).getDoc(ctx, csid); RemoteDocumentModelHandlerImpl handler = (RemoteDocumentModelHandlerImpl)createDocumentHandler(ctx); - List authRefFields = ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(RefNameServiceUtils.AUTH_REF_PROP); + List authRefFields = + ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues( + ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); authRefList = handler.getAuthorityRefs(docWrapper, authRefFields); } catch (UnauthorizedException ue) { Response response = Response.status( diff --git a/services/common/src/main/config/services/tenant-bindings.xml b/services/common/src/main/config/services/tenant-bindings.xml index a9cd3d2de..f77ae2107 100644 --- a/services/common/src/main/config/services/tenant-bindings.xml +++ b/services/common/src/main/config/services/tenant-bindings.xml @@ -24,7 +24,11 @@ org.collectionspace.services.collectionobject.nuxeo.CollectionObjectValidatorHandler - + objectNamePropertyobjectName + objectNumberPropertyobjectNumber + + org.collectionspace.services.intake.nuxeo.IntakeValidatorHandler + + + objectNumberPropertyentryNumber + org.collectionspace.services.loanin.nuxeo.LoaninValidatorHandler + + + objectNumberPropertyloanInNumber + authRefborrowersContact authReflendersAuthorizer authReflendersContact - + + + authRefcontactName + + org.collectionspace.services.acquisition.nuxeo.AcquisitionValidatorHandler + + + objectNumberPropertyacquisitionReferenceNumber + propNodeList, + public static String getPropertyValueByNameFromNodeList(List propNodeList, String propName) { if(propNodeList.isEmpty()) { return null; } - return getPropertyValue(propNodeList.get(0).getItem(), propName); + return getPropertyValueByName(propNodeList.get(0).getItem(), propName); } @@ -27,7 +27,7 @@ public class PropertyItemUtils { * @param propName the property to fetch * @return the String value of the named property */ - public static String getPropertyValue(List propList, + public static String getPropertyValueByName(List propList, String propName) { if(propName==null) { throw new IllegalArgumentException("PropertyItemUtils.getPropertyValues: null property name!"); @@ -40,27 +40,56 @@ public class PropertyItemUtils { return null; } + /** + * @param propNodeList the JAXB wrapping node of for the list to search for the named property + * @param propName the name of the property of interest + * @param qualPrefix a namespace qualifier prefix (with ':') to prepend, or null + * @return a List of string values found for the named property + */ public static List getPropertyValuesByNameInNodeList( - List propNodeList, String propName) { - return getPropertyValuesByNameInNodeList(propNodeList, propName, null); + List propNodeList, String propName, String qualPrefix) { + return getPropertyValuesByNameInNodeList(propNodeList, propName, qualPrefix, null); } + /** + * @param propNodeList the JAXB wrapping node of for the list to search for the named property + * @param propName the name of the property of interest + * @param qualPrefix a namespace qualifier prefix (with ':') to prepend, or null + * @param values and existing list to append values to. If null, a new one will be created. + * @return values, or that is null, a new List of string values found for the named property + */ public static List getPropertyValuesByNameInNodeList( - List propNodeList, String propName, List values) { + List propNodeList, String propName, String qualPrefix, + List values) { if(propNodeList.isEmpty()) { if(values==null) - return new ArrayList(); + values = new ArrayList(); + return values; } - return getPropertyValuesByName(propNodeList.get(0).getItem(), propName, null); + return getPropertyValuesByName(propNodeList.get(0).getItem(), + propName, qualPrefix, values); } + /** + * @param propNodeList the Item list to search for the named property + * @param propName the name of the property of interest + * @param qualPrefix a namespace qualifier prefix (with ':') to prepend, or null + * @return a List of string values found for the named property + */ public static List getPropertyValuesByName( - List propItems, String propName) { - return getPropertyValuesByName(propItems, propName, null); + List propItems, String propName, String qualPrefix) { + return getPropertyValuesByName(propItems, propName, qualPrefix, null); } + /** + * @param propNodeList the Item list to search for the named property + * @param propName the name of the property of interest + * @param qualPrefix a namespace qualifier prefix (with ':') to prepend, or null + * @param values and existing list to append values to. If null, a new one will be created. + * @return values, or that is null, a new List of string values found for the named property + */ public static List getPropertyValuesByName( - List propItems, String propName, + List propItems, String propName, String qualPrefix, List values ) { if(values==null) values = new ArrayList(); @@ -68,7 +97,7 @@ public class PropertyItemUtils { if(propName.equals(propItem.getKey())) { String value = propItem.getValue(); if(value!=null) { - values.add(value); + values.add((qualPrefix!=null)?(qualPrefix+value):value); } } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingConfigReaderImpl.java b/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingConfigReaderImpl.java index b92cbe270..c30b1fbe8 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingConfigReaderImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingConfigReaderImpl.java @@ -241,7 +241,7 @@ public class TenantBindingConfigReaderImpl TenantBindingType tenant = tenantBindings.get(tenantId); if (tenant != null) { for (ServiceBindingType sb : tenant.getServiceBindings()) { - if (sb.getType().equals(serviceType)) { + if (serviceType.equals(sb.getType())) { if (list == null) { list = new ArrayList(); } @@ -263,6 +263,11 @@ public class TenantBindingConfigReaderImpl return serviceWorkspaces.get(tenantService); } + /** + * @param tenantId + * @param serviceName + * @return the properly qualified service name + */ public static String getTenantQualifiedServiceName( String tenantId, String serviceName) { return tenantId + "." + serviceName.toLowerCase(); @@ -272,6 +277,14 @@ public class TenantBindingConfigReaderImpl return RepositoryClientFactory.getInstance().getClient(clientName); } + /** + * Sets properties in the passed list on the local properties for this TenantBinding. + * Note: will only set properties not already set on the TenantBinding. + * + * @param propList + * @param propagateToServices If true, recurses to set set properties + * on the associated services. + */ public void setDefaultPropertiesOnTenants(List propList, boolean propagateToServices) { // For each tenant, set properties in list that are not already set diff --git a/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingUtils.java b/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingUtils.java index 3aa85947e..de64c3e37 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/config/TenantBindingUtils.java @@ -25,7 +25,7 @@ public class TenantBindingUtils { throw new IllegalArgumentException("TenantBindingUtils.getPropertyValues: null property name!"); } List tenantPropList = tenantBinding.getProperties(); - return PropertyItemUtils.getPropertyValueFromNodeList(tenantPropList, propName ); + return PropertyItemUtils.getPropertyValueByNameFromNodeList(tenantPropList, propName ); } /** diff --git a/services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java b/services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java index b30bf5a0d..00ea2611e 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContextImpl.java @@ -61,6 +61,18 @@ import org.slf4j.LoggerFactory; * $LastChangedRevision: $ * $LastChangedDate: $ */ +/** + * @author pschmitz + * + * @param + * @param + */ +/** + * @author pschmitz + * + * @param + * @param + */ public abstract class AbstractServiceContextImpl implements ServiceContext { @@ -178,27 +190,26 @@ public abstract class AbstractServiceContextImpl } /** - * Gets the property values for part. - * - * @param partLabel the part label - * @param propName the prop name - * - * @return the property values for part + * @param partLabel The name of the scehma part to search in + * @param propName The name of the property (or properties) to find + * @param qualified Whether the returned values should be qualified with the + * partLabel. This is when the property values are schema field references. + * @return List of property values for the matched property on the named schema part. */ - public List getPropertyValuesForPart(String partLabel, String propName) { + public List getPropertyValuesForPart(String partLabel, String propName, boolean qualified) { List allProps = getPropertiesForPart(partLabel); - return PropertyItemUtils.getPropertyValuesByName(allProps, propName); + return PropertyItemUtils.getPropertyValuesByName(allProps, propName, + (qualified?(partLabel+":"):null)); } /** - * Gets the all parts property values. - * - * @param propName the prop name - * - * @return the all parts property values + * @param propName The name of the property (or properties) to find + * @param qualified Whether the returned values should be qualified with the + * partLabel. This is when the property values are schema field references. + * @return List of property values for the matched property on any schema part. */ - public List getAllPartsPropertyValues(String propName) { - return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName); + public List getAllPartsPropertyValues(String propName, boolean qualified) { + return ServiceBindingUtils.getAllPartsPropertyValues(getServiceBinding(), propName, qualified); } /* (non-Javadoc) @@ -218,14 +229,13 @@ public abstract class AbstractServiceContextImpl } /** - * Gets the common part property values. - * - * @param propName the prop name - * - * @return the common part property values + * @param propName The name of the property (or properties) to find + * @param qualified Whether the returned values should be qualified with the + * partLabel. This is when the property values are schema field references. + * @return List of property values for the matched property on the common schema part. */ - public List getCommonPartPropertyValues(String propName) { - return getPropertyValuesForPart(getCommonPartLabel(), propName); + public List getCommonPartPropertyValues(String propName, boolean qualified) { + return getPropertyValuesForPart(getCommonPartLabel(), propName, qualified); } /* (non-Javadoc) diff --git a/services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java b/services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java index 31e2f4db5..8edfecbd0 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/context/ServiceBindingUtils.java @@ -11,8 +11,23 @@ import org.collectionspace.services.common.service.ServiceObjectType; import org.collectionspace.services.common.tenant.TenantBindingType; import org.collectionspace.services.common.types.PropertyItemType; import org.collectionspace.services.common.types.PropertyType; +import org.nuxeo.ecm.core.api.ClientException; +import org.nuxeo.ecm.core.api.DocumentModel; public class ServiceBindingUtils { + public static final boolean QUALIFIED_PROP_NAMES = true; + public static final boolean UNQUALIFIED_PROP_NAMES = false; + public static final String AUTH_REF_PROP = "authRef"; + public static final String OBJ_NUMBER_PROP = "objectNumberProperty"; + public static final String OBJ_NAME_PROP = "objectNameProperty"; + public static final String SERVICE_TYPE_PROP = "type"; + public static final String SERVICE_TYPE_OBJECT = "object"; + public static final String SERVICE_TYPE_PROCEDURE = "procedure"; + + // TODO consider building up a hashTable of the properties for each + // service binding. There will be generic properties, as well as + // properties on each part. Could build up a key from tenant id, + // servicename, (partname for those props), propName public static void getPartsMetadata(ServiceBindingType serviceBinding, Map objectPartMap) { @@ -23,7 +38,7 @@ public class ServiceBindingUtils { } } - public static List getPropertiesForPart(ServiceBindingType serviceBinding, + private static List getPropertiesForPart(ServiceBindingType serviceBinding, String partLabel) { ServiceObjectType objectType = serviceBinding.getObject(); List objectPartTypes = objectType.getPart(); @@ -37,19 +52,27 @@ public class ServiceBindingUtils { } public static List getPropertyValuesForPart(ServiceBindingType serviceBinding, - String partLabel, String propName) { + String partLabel, String propName, boolean qualify) { List partProps = getPropertiesForPart(serviceBinding, partLabel); - return PropertyItemUtils.getPropertyValuesByName(partProps, propName); + return PropertyItemUtils.getPropertyValuesByName(partProps, propName, + (qualify?(partLabel+":"):null)); } + /** + * @param serviceBinding the service to work from + * @param propName the name of the property of interest + * @param qualify if QUALIFIED_PROP_NAMES, will prefix all values with the part label + * @return a list of (qualified) + */ public static List getAllPartsPropertyValues(ServiceBindingType serviceBinding, - String propName) { + String propName, boolean qualify) { List values = new ArrayList(); ServiceObjectType objectType = serviceBinding.getObject(); List objectPartTypes = objectType.getPart(); for (ObjectPartType objectPartType : objectPartTypes) { List propNodeList = objectPartType.getProperties(); - PropertyItemUtils.getPropertyValuesByNameInNodeList(propNodeList, propName, values); + PropertyItemUtils.getPropertyValuesByNameInNodeList(propNodeList, + propName, (qualify?(objectPartType.getLabel()+":"):null), values); } return values; } @@ -65,7 +88,7 @@ public class ServiceBindingUtils { throw new IllegalArgumentException("ServiceBindingUtils.getPropertyValues: null property name!"); } List servicePropList = service.getProperties(); - return PropertyItemUtils.getPropertyValueFromNodeList(servicePropList, propName ); + return PropertyItemUtils.getPropertyValueByNameFromNodeList(servicePropList, propName ); } /** @@ -103,4 +126,27 @@ public class ServiceBindingUtils { propName, value, onlyIfNotSet); } + public static String getMappedFieldInDoc( ServiceBindingType sb, + String logicalFieldName, DocumentModel docModel ) { + // Now we have to get the number, which is configured as some field + // on each docType + /* If we go to qualified field names, we'll need this + String[] strings = qPropName.split(":"); + if(strings.length!=2) { + throw new RuntimeException( + "getMappedFieldInDoc: Bad configuration of " + +logicalFieldName+" field for: "+docModel.getDocumentType().getName()); + } + */ + String propName = getPropertyValue(sb, logicalFieldName); + if(propName==null||propName.isEmpty()) + return null; + try { + return (String)docModel.getPropertyValue(propName); + } catch(ClientException ce) { + throw new RuntimeException( + "getMappedFieldInDoc: Problem fetching: "+propName, ce); + } + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java index 4a6467dd2..3e8874a9d 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java @@ -230,7 +230,6 @@ public interface DocumentHandler { * filter that is relevant to be used with this document handler * and corresponding storage client * - * @param ctx ServiceContext used to fetch default pagination, etc. * @return */ public DocumentFilter createDocumentFilter(); diff --git a/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java b/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java index 98aab7e38..98b0d1d7c 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/vocabulary/RefNameServiceUtils.java @@ -24,8 +24,12 @@ package org.collectionspace.services.common.vocabulary; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import org.nuxeo.ecm.core.api.ClientException; +import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,6 +43,7 @@ import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.common.repository.RepositoryClient; import org.collectionspace.services.common.service.ServiceBindingType; +import org.collectionspace.services.nuxeo.util.NuxeoUtils; /** * RefNameServiceUtils is a collection of services utilities related to refName usage. @@ -47,12 +52,10 @@ import org.collectionspace.services.common.service.ServiceBindingType; * $LastChangedDate: $ */ public class RefNameServiceUtils { - - public static final String AUTH_REF_PROP = "authRef"; private final Logger logger = LoggerFactory.getLogger(RefNameServiceUtils.class); - public AuthorityRefDocList getAuthorityRefDocs(RepositoryClient repoClient, + public static AuthorityRefDocList getAuthorityRefDocs(RepositoryClient repoClient, String tenantId, String serviceType, String refName, int pageSize, int pageNum, boolean computeTotal ) throws DocumentException, DocumentNotFoundException { @@ -62,26 +65,127 @@ public class RefNameServiceUtils { TenantBindingConfigReaderImpl tReader = ServiceMain.getInstance().getTenantBindingConfigReader(); List servicebindings = tReader.getServiceBindingsByType(tenantId, serviceType); - if(servicebindings==null || servicebindings.size()>0) + if(servicebindings==null || servicebindings.isEmpty()) return null; + // Need to escape the quotes in the refName + // TODO What if they are already escaped? + String escapedRefName = refName.replaceAll("'", "\\\\'"); String domain = tReader.getTenantBinding(tenantId).getRepositoryDomain(); ArrayList docTypes = new ArrayList(); + HashMap queriedServiceBindings = new HashMap(); + HashMap> authRefFieldsByService = new HashMap>(); StringBuilder whereClause = new StringBuilder(); + boolean fFirst = true; for(ServiceBindingType sb:servicebindings) { - List authRefFields = ServiceBindingUtils.getAllPartsPropertyValues(sb, AUTH_REF_PROP); + List authRefFields = + ServiceBindingUtils.getAllPartsPropertyValues(sb, + ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); + if(authRefFields.isEmpty()) + continue; String docType = sb.getObject().getName(); + queriedServiceBindings.put(docType, sb); + authRefFieldsByService.put(docType, authRefFields); docTypes.add(docType); + /* + // HACK - need to get qualified properties from the ServiceBinding + String prefix = ""; + if(docType.equalsIgnoreCase("Intake")) + prefix = "intakes_common:"; + else if(docType.equalsIgnoreCase("Loanin")) + prefix = "loansin_common:"; + else if(docType.equalsIgnoreCase("Acquisition")) + prefix = "acquisitions_common:"; + */ for(String field:authRefFields) { // Build up the where clause for each authRef field - throw new UnsupportedOperationException(); + if(fFirst) { + fFirst = false; + } else { + whereClause.append(" OR "); + } + //whereClause.append(prefix); + whereClause.append(field); + whereClause.append("='"); + whereClause.append(escapedRefName); + whereClause.append("'"); } } + if(fFirst) // found no authRef fields - nothing to query + return wrapperList; + String fullQuery = whereClause.toString(); // for debug // Now we have to issue the search DocumentWrapper docListWrapper = repoClient.findDocs( docTypes, whereClause.toString(), domain, pageSize, pageNum, computeTotal ); - return null; + // Now we gather the info for each document into the list and return + DocumentModelList docList = docListWrapper.getWrappedObject(); + Iterator iter = docList.iterator(); + while(iter.hasNext()){ + DocumentModel docModel = iter.next(); + AuthorityRefDocList.AuthorityRefDocItem ilistItem = new AuthorityRefDocList.AuthorityRefDocItem(); + String csid = NuxeoUtils.extractId(docModel.getPathAsString()); + String docType = docModel.getDocumentType().getName(); + ServiceBindingType sb = queriedServiceBindings.get(docType); + if(sb==null) { + throw new RuntimeException( + "getAuthorityRefDocs: No Service Binding for docType: "+docType); + } + String serviceContextPath = "/" + sb.getName().toLowerCase() + "/"; + // The id and URI are the same on all doctypes + ilistItem.setDocId(csid); + ilistItem.setUri(serviceContextPath+csid); + ilistItem.setDocType(docType); + ilistItem.setDocNumber( + ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NUMBER_PROP, docModel)); + ilistItem.setDocName( + ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NAME_PROP, docModel)); + // Now, we have to loop over the authRefFieldsByService to figure + // out which field matched this. Ignore multiple matches. + List authRefFields = authRefFieldsByService.get(docType); + if(authRefFields==null || authRefFields.isEmpty()){ + throw new RuntimeException( + "getAuthorityRefDocs: internal logic error: can't fetch authRefFields for DocType." ); + } + boolean fRefFound = false; + /* Use this if we go to qualified field names + for(String field:authRefFields){ + String[] strings = field.split(":"); + if(strings.length!=2) { + throw new RuntimeException( + "getAuthorityRefDocs: Bad configuration of authRefField."); + } + try { + if(refName.equals(docModel.getProperty(strings[0], strings[1]))) { + ilistItem.setSourceField(field); + fRefFound = true; + break; + } + } catch(ClientException ce) { + throw new RuntimeException( + "getAuthorityRefDocs: Problem fetching: "+field, ce); + } + } + */ + for(String field:authRefFields){ + try { + if(refName.equals(docModel.getPropertyValue(field))) { + ilistItem.setSourceField(field); + fRefFound = true; + break; + } + } catch(ClientException ce) { + throw new RuntimeException( + "getAuthorityRefDocs: Problem fetching: "+field, ce); + } + } + if(!fRefFound) { + throw new RuntimeException( + "getAuthorityRefDocs: Could not find refname in object:" + +docType+":"+csid); + } + list.add(ilistItem); + } + return wrapperList; } - } diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java index 4f660b263..6e29b3467 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java @@ -204,6 +204,12 @@ public abstract class RemoteDocumentModelHandlerImpl return result; } + /** + * @param docWrapper + * @param authRefFields list of schema-qualified field names + * @return + * @throws PropertyException + */ public AuthorityRefList getAuthorityRefs( DocumentWrapper docWrapper, List authRefFields) throws PropertyException { diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index 9ce6d6d77..cd371656a 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -409,8 +409,6 @@ public class RepositoryJavaClientImpl implements RepositoryClient { wrapDoc = new DocumentWrapperImpl(docList); } catch (IllegalArgumentException iae) { throw iae; - } catch (DocumentException de) { - throw de; } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception ", e); @@ -763,8 +761,9 @@ public class RepositoryJavaClientImpl implements RepositoryClient { boolean fFirst = true; for(String docType:docTypes) { if(fFirst) { - query.append(","); fFirst = false; + } else { + query.append(","); } query.append(docType); } diff --git a/services/intake/client/pom.xml b/services/intake/client/pom.xml index 26b89598e..499910fa2 100644 --- a/services/intake/client/pom.xml +++ b/services/intake/client/pom.xml @@ -31,6 +31,12 @@ org.collectionspace.services.jaxb ${project.version} + + org.collectionspace.services + org.collectionspace.services.common + true + ${project.version} + org.collectionspace.services org.collectionspace.services.intake.jaxb diff --git a/services/intake/client/src/test/java/org/collectionspace/services/client/test/PersonAuthRefDocsTest.java b/services/intake/client/src/test/java/org/collectionspace/services/client/test/PersonAuthRefDocsTest.java new file mode 100644 index 000000000..05d2d68d2 --- /dev/null +++ b/services/intake/client/src/test/java/org/collectionspace/services/client/test/PersonAuthRefDocsTest.java @@ -0,0 +1,317 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + * + * http://www.collectionspace.org + * http://wiki.collectionspace.org + * + * Copyright © 2009 Regents of the University of California + * + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + * + * You may obtain a copy of the ECL 2.0 License at + * https://source.collectionspace.org/collection-space/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.collectionspace.services.client.test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.collectionspace.services.PersonJAXBSchema; +import org.collectionspace.services.client.IntakeClient; +import org.collectionspace.services.client.PersonAuthorityClient; +import org.collectionspace.services.client.PersonAuthorityClientUtils; +import org.collectionspace.services.common.authorityref.AuthorityRefDocList; +import org.collectionspace.services.intake.IntakesCommon; +import org.collectionspace.services.intake.IntakesCommonList; + +import org.jboss.resteasy.client.ClientResponse; + +import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; +import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; +import org.jboss.resteasy.plugins.providers.multipart.OutputPart; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * PersonAuthRefDocsTest, carries out tests against a + * deployed and running Person Service. + * + * $LastChangedRevision: 1327 $ + * $LastChangedDate: 2010-02-12 10:35:11 -0800 (Fri, 12 Feb 2010) $ + */ +public class PersonAuthRefDocsTest extends BaseServiceTest { + + private final Logger logger = + LoggerFactory.getLogger(PersonAuthRefDocsTest.class); + + // Instance variables specific to this test. + private IntakeClient intakeClient = new IntakeClient(); + private PersonAuthorityClient personAuthClient = new PersonAuthorityClient(); + final String SERVICE_PATH_COMPONENT = "intakes"; + final String PERSON_AUTHORITY_NAME = "TestPersonAuth"; + private String knownIntakeId = null; + private List intakeIdsCreated = new ArrayList(); + private List personIdsCreated = new ArrayList(); + private int CREATED_STATUS = Response.Status.CREATED.getStatusCode(); + private int OK_STATUS = Response.Status.OK.getStatusCode(); + private String personAuthCSID = null; + private String currentOwnerPersonCSID = null; + private String currentOwnerRefName = null; + private String depositorRefName = null; + private String conditionCheckAssesorRefName = null; + private String insurerRefName = null; + private String fieldCollectorRefName = null; + private String valuerRefName = null; + private final int NUM_AUTH_REF_DOCS_EXPECTED = 1; + + // --------------------------------------------------------------- + // CRUD tests : CREATE tests + // --------------------------------------------------------------- + // Success outcomes + @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class) + public void createIntakeWithAuthRefs(String testName) throws Exception { + + testSetup(CREATED_STATUS, ServiceRequestType.CREATE,testName); + + // Submit the request to the service and store the response. + String identifier = createIdentifier(); + + // Create all the person refs and entities + createPersonRefs(); + + MultipartOutput multipart = createIntakeInstance( + "entryNumber-" + identifier, + "entryDate-" + identifier, + currentOwnerRefName, + depositorRefName, + conditionCheckAssesorRefName, + insurerRefName, + fieldCollectorRefName, + valuerRefName ); + + ClientResponse res = intakeClient.create(multipart); + + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + // + // Specifically: + // Does it fall within the set of valid status codes? + // Does it exactly match the expected status code? + if(logger.isDebugEnabled()){ + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + + // Store the ID returned from the first resource created + // for additional tests below. + if (knownIntakeId == null){ + knownIntakeId = extractId(res); + if (logger.isDebugEnabled()) { + logger.debug(testName + ": knownIntakeId=" + knownIntakeId); + } + } + + // Store the IDs from every resource created by tests, + // so they can be deleted after tests have been run. + intakeIdsCreated.add(extractId(res)); + } + + protected void createPersonRefs(){ + String authRefName = + PersonAuthorityClientUtils.createPersonAuthRefName(PERSON_AUTHORITY_NAME, false); + MultipartOutput multipart = PersonAuthorityClientUtils.createPersonAuthorityInstance( + PERSON_AUTHORITY_NAME, authRefName, personAuthClient.getCommonPartName()); + ClientResponse res = personAuthClient.create(multipart); + int statusCode = res.getStatus(); + + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, CREATED_STATUS); + personAuthCSID = extractId(res); + + currentOwnerRefName = PersonAuthorityClientUtils.createPersonRefName( + authRefName, "Olivier Owner", true); + currentOwnerPersonCSID = createPerson("Olivier", "Owner", currentOwnerRefName); + personIdsCreated.add(currentOwnerPersonCSID); + + depositorRefName = PersonAuthorityClientUtils.createPersonRefName( + authRefName, "Debbie Depositor", true); + personIdsCreated.add(createPerson("Debbie", "Depositor", depositorRefName)); + + conditionCheckAssesorRefName = PersonAuthorityClientUtils.createPersonRefName( + authRefName, "Andrew Assessor", true); + personIdsCreated.add(createPerson("Andrew", "Assessor", conditionCheckAssesorRefName)); + + insurerRefName = PersonAuthorityClientUtils.createPersonRefName( + authRefName, "Ingrid Insurer", true); + personIdsCreated.add(createPerson("Ingrid", "Insurer", insurerRefName)); + + fieldCollectorRefName = PersonAuthorityClientUtils.createPersonRefName( + authRefName, "Connie Collector", true); + personIdsCreated.add(createPerson("Connie", "Collector", fieldCollectorRefName)); + + valuerRefName = PersonAuthorityClientUtils.createPersonRefName( + authRefName, "Vince Valuer", true); + personIdsCreated.add(createPerson("Vince", "Valuer", valuerRefName)); + + + } + + protected String createPerson(String firstName, String surName, String refName ) { + Map personInfo = new HashMap(); + personInfo.put(PersonJAXBSchema.FORE_NAME, firstName); + personInfo.put(PersonJAXBSchema.SUR_NAME, surName); + MultipartOutput multipart = + PersonAuthorityClientUtils.createPersonInstance(personAuthCSID, + refName, personInfo, personAuthClient.getItemCommonPartName()); + ClientResponse res = personAuthClient.createItem(personAuthCSID, multipart); + int statusCode = res.getStatus(); + + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, CREATED_STATUS); + return extractId(res); + } + + // Success outcomes + @Test(dataProvider="testName", dataProviderClass=AbstractServiceTestImpl.class, + dependsOnMethods = {"createIntakeWithAuthRefs"}) + public void readAndCheckAuthRefDocs(String testName) throws Exception { + + // Perform setup. + testSetup(OK_STATUS, ServiceRequestType.READ,testName); + + // Get the auth ref docs and check them + ClientResponse refDocListResp = + personAuthClient.getReferencingObjects(personAuthCSID, currentOwnerPersonCSID); + + int statusCode = refDocListResp.getStatus(); + + if(logger.isDebugEnabled()){ + logger.debug(testName + ".getReferencingObjects: status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + AuthorityRefDocList list = refDocListResp.getEntity(); + + // Optionally output additional data about list members for debugging. + boolean iterateThroughList = true; + boolean fFoundIntake = false; + if(iterateThroughList && logger.isDebugEnabled()){ + List items = + list.getAuthorityRefDocItem(); + int i = 0; + logger.debug(testName + ": Docs that use: " + currentOwnerRefName); + for(AuthorityRefDocList.AuthorityRefDocItem item : items){ + logger.debug(testName + ": list-item[" + i + "] " + + item.getDocType() + "(" + + item.getDocId() + ") Name:[" + + item.getDocName() + "] Number:[" + + item.getDocNumber() + "] in field:[" + + item.getSourceField() + "]"); + if(!fFoundIntake && knownIntakeId.equalsIgnoreCase(item.getDocId())) { + fFoundIntake = true; + } + i++; + } + Assert.assertTrue(fFoundIntake, "Did not find Intake with authref!"); + } + } + + + // --------------------------------------------------------------- + // Cleanup of resources created during testing + // --------------------------------------------------------------- + + /** + * Deletes all resources created by tests, after all tests have been run. + * + * This cleanup method will always be run, even if one or more tests fail. + * For this reason, it attempts to remove all resources created + * at any point during testing, even if some of those resources + * may be expected to be deleted by certain tests. + */ + @AfterClass(alwaysRun=true) + public void cleanUp() { + String noTest = System.getProperty("noTestCleanup"); + if("true".equalsIgnoreCase(noTest)) { + if (logger.isDebugEnabled()) { + logger.debug("Skipping Cleanup phase"); + } + return; + } + if (logger.isDebugEnabled()) { + logger.debug("Cleaning up temporary resources created for testing ..."); + } + // Note: Any non-success responses are ignored and not reported. + for (String resourceId : intakeIdsCreated) { + ClientResponse res = intakeClient.delete(resourceId); + } + // Delete persons before PersonAuth + for (String resourceId : personIdsCreated) { + ClientResponse res = personAuthClient.deleteItem(personAuthCSID, resourceId); + } + ClientResponse res = personAuthClient.delete(personAuthCSID); + } + + // --------------------------------------------------------------- + // Utility methods used by tests above + // --------------------------------------------------------------- + @Override + public String getServicePathComponent() { + return SERVICE_PATH_COMPONENT; + } + + private MultipartOutput createIntakeInstance(String entryNumber, + String entryDate, + String currentOwner, + String depositor, + String conditionCheckAssesor, + String insurer, + String fieldCollector, + String Valuer ) { + IntakesCommon intake = new IntakesCommon(); + intake.setEntryNumber(entryNumber); + intake.setEntryDate(entryDate); + intake.setCurrentOwner(currentOwner); + intake.setDepositor(depositor); + intake.setConditionCheckAssesor(conditionCheckAssesor); + intake.setInsurer(insurer); + intake.setFieldCollector(fieldCollector); + intake.setValuer(Valuer); + MultipartOutput multipart = new MultipartOutput(); + OutputPart commonPart = + multipart.addPart(intake, MediaType.APPLICATION_XML_TYPE); + commonPart.getHeaders().add("label", intakeClient.getCommonPartName()); + + if(logger.isDebugEnabled()){ + logger.debug("to be created, intake common"); + logger.debug(objectAsXmlString(intake, IntakesCommon.class)); + } + + return multipart; + } +} diff --git a/services/intake/service/src/main/java/org/collectionspace/services/intake/IntakeResource.java b/services/intake/service/src/main/java/org/collectionspace/services/intake/IntakeResource.java index a7be7687c..08ca4bb92 100644 --- a/services/intake/service/src/main/java/org/collectionspace/services/intake/IntakeResource.java +++ b/services/intake/service/src/main/java/org/collectionspace/services/intake/IntakeResource.java @@ -49,6 +49,7 @@ import org.collectionspace.services.common.authorityref.AuthorityRefList; //import org.collectionspace.services.common.context.MultipartServiceContext; //import org.collectionspace.services.common.context.MultipartServiceContextFactory; import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; @@ -293,7 +294,9 @@ public class IntakeResource extends getRepositoryClient(ctx).getDoc(ctx, csid); RemoteDocumentModelHandlerImpl handler = (RemoteDocumentModelHandlerImpl)createDocumentHandler(ctx); - List authRefFields = ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(RefNameServiceUtils.AUTH_REF_PROP); + List authRefFields = + ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues( + ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); authRefList = handler.getAuthorityRefs(docWrapper, authRefFields); } catch (UnauthorizedException ue) { Response response = Response.status( diff --git a/services/jaxb/src/main/resources/authorityrefdocs.xsd b/services/jaxb/src/main/resources/authorityrefdocs.xsd new file mode 100644 index 000000000..906bace83 --- /dev/null +++ b/services/jaxb/src/main/resources/authorityrefdocs.xsd @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/loanin/service/src/main/java/org/collectionspace/services/loanin/LoaninResource.java b/services/loanin/service/src/main/java/org/collectionspace/services/loanin/LoaninResource.java index 79c302bda..de642b32c 100644 --- a/services/loanin/service/src/main/java/org/collectionspace/services/loanin/LoaninResource.java +++ b/services/loanin/service/src/main/java/org/collectionspace/services/loanin/LoaninResource.java @@ -48,6 +48,7 @@ import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.MultipartServiceContextFactory; import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; @@ -291,7 +292,9 @@ public class LoaninResource extends getRepositoryClient(ctx).getDoc(ctx, csid); RemoteDocumentModelHandlerImpl handler = (RemoteDocumentModelHandlerImpl)createDocumentHandler(ctx); - List authRefFields = ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(RefNameServiceUtils.AUTH_REF_PROP); + List authRefFields = + ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues( + ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); authRefList = handler.getAuthorityRefs(docWrapper, authRefFields); } catch (UnauthorizedException ue) { Response response = Response.status( diff --git a/services/loanout/service/src/main/java/org/collectionspace/services/loanout/LoanoutResource.java b/services/loanout/service/src/main/java/org/collectionspace/services/loanout/LoanoutResource.java index 6ea529f88..bf6ef7c56 100644 --- a/services/loanout/service/src/main/java/org/collectionspace/services/loanout/LoanoutResource.java +++ b/services/loanout/service/src/main/java/org/collectionspace/services/loanout/LoanoutResource.java @@ -48,6 +48,7 @@ import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.MultipartServiceContextFactory; import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; @@ -291,7 +292,9 @@ public class LoanoutResource extends getRepositoryClient(ctx).getDoc(ctx, csid); RemoteDocumentModelHandlerImpl handler = (RemoteDocumentModelHandlerImpl)createDocumentHandler(ctx); - List authRefFields = ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues(RefNameServiceUtils.AUTH_REF_PROP); + List authRefFields = + ((MultipartServiceContextImpl)ctx).getCommonPartPropertyValues( + ServiceBindingUtils.AUTH_REF_PROP, ServiceBindingUtils.QUALIFIED_PROP_NAMES); authRefList = handler.getAuthorityRefs(docWrapper, authRefFields); } catch (UnauthorizedException ue) { Response response = Response.status( diff --git a/services/person/client/pom.xml b/services/person/client/pom.xml index e12fe3816..7f9a83191 100644 --- a/services/person/client/pom.xml +++ b/services/person/client/pom.xml @@ -26,6 +26,17 @@ test + + org.collectionspace.services + org.collectionspace.services.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.common + true + ${project.version} + org.collectionspace.services org.collectionspace.services.person.jaxb diff --git a/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityClient.java b/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityClient.java index c17eeec0b..af2efcd16 100644 --- a/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityClient.java +++ b/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityClient.java @@ -3,6 +3,8 @@ package org.collectionspace.services.client; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; +import org.collectionspace.services.common.authorityref.AuthorityRefList; +import org.collectionspace.services.common.authorityref.AuthorityRefDocList; import org.collectionspace.services.contact.ContactsCommonList; import org.collectionspace.services.person.PersonauthoritiesCommonList; import org.collectionspace.services.person.PersonsCommonList; @@ -139,6 +141,15 @@ public class PersonAuthorityClient extends AbstractServiceClientImpl { return personAuthorityProxy.readItemList(vcsid); } + /** + * @param csid + * @return + * @see org.collectionspace.services.client.IntakeProxy#getAuthorityRefs(java.lang.String) + */ + public ClientResponse getReferencingObjects(String parentcsid, String csid) { + return personAuthorityProxy.getReferencingObjects(parentcsid, csid); + } + /** * @return * @see org.collectionspace.services.client.PersonAuthorityProxy#readItemListForNamedAuthority() diff --git a/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityProxy.java b/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityProxy.java index 10c27a001..ca8f4e688 100644 --- a/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityProxy.java +++ b/services/person/client/src/main/java/org/collectionspace/services/client/PersonAuthorityProxy.java @@ -10,6 +10,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; +import org.collectionspace.services.common.authorityref.AuthorityRefDocList; import org.collectionspace.services.contact.ContactsCommonList; import org.collectionspace.services.person.PersonauthoritiesCommonList; import org.collectionspace.services.person.PersonsCommonList; @@ -60,6 +61,18 @@ public interface PersonAuthorityProxy { @Path("/{vcsid}/items/") ClientResponse readItemList(@PathParam("vcsid") String vcsid); + /** + * @param csid + * @return + * @see org.collectionspace.services.client.IntakeProxy#getAuthorityRefs(java.lang.String) + */ + @GET + @Path("{csid}/items/{itemcsid}/refObjs") + @Produces("application/xml") + ClientResponse getReferencingObjects( + @PathParam("csid") String parentcsid, + @PathParam("itemcsid") String itemcsid); + // List Items for a named authority @GET @Produces({"application/xml"}) diff --git a/services/person/service/src/main/java/org/collectionspace/services/person/PersonAuthorityResource.java b/services/person/service/src/main/java/org/collectionspace/services/person/PersonAuthorityResource.java index 71a025cb3..1b6070ee2 100644 --- a/services/person/service/src/main/java/org/collectionspace/services/person/PersonAuthorityResource.java +++ b/services/person/service/src/main/java/org/collectionspace/services/person/PersonAuthorityResource.java @@ -23,7 +23,8 @@ */ package org.collectionspace.services.person; -//import java.net.URI; +import java.util.List; + import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -35,7 +36,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; -//import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; @@ -46,27 +46,35 @@ import org.collectionspace.services.PersonJAXBSchema; import org.collectionspace.services.common.AbstractMultiPartCollectionSpaceResourceImpl; import org.collectionspace.services.common.ClientType; import org.collectionspace.services.common.ServiceMain; -//import org.collectionspace.services.common.context.MultipartServiceContext; -//import org.collectionspace.services.common.context.MultipartServiceContextFactory; +import org.collectionspace.services.common.authorityref.AuthorityRefDocList; +import org.collectionspace.services.common.authorityref.AuthorityRefList; +import org.collectionspace.services.common.context.MultipartServiceContext; +import org.collectionspace.services.common.context.MultipartServiceContextFactory; +import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.BadRequestException; +import org.collectionspace.services.common.document.DocumentException; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; -//import org.collectionspace.services.common.document.DocumentWrapper; +import org.collectionspace.services.common.document.DocumentWrapper; +import org.collectionspace.services.common.repository.RepositoryClient; import org.collectionspace.services.common.security.UnauthorizedException; -//import org.collectionspace.services.common.vocabulary.RefNameUtils; +import org.collectionspace.services.common.vocabulary.RefNameServiceUtils; +import org.collectionspace.services.common.vocabulary.RefNameUtils; import org.collectionspace.services.common.query.IQueryManager; import org.collectionspace.services.contact.ContactResource; import org.collectionspace.services.contact.ContactsCommon; import org.collectionspace.services.contact.ContactsCommonList; import org.collectionspace.services.contact.ContactJAXBSchema; import org.collectionspace.services.contact.nuxeo.ContactDocumentModelHandler; +import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl; import org.collectionspace.services.person.nuxeo.PersonDocumentModelHandler; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.util.HttpResponseCodes; -//import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.DocumentModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -313,12 +321,88 @@ public class PersonAuthorityResource extends } /** - * Gets the person authority. + * Gets the entities referencing this Person instance. The service type + * can be passed as a query param "type", and must match a configured type + * for the service bindings. If not set, the type defaults to + * ServiceBindingUtils.SERVICE_TYPE_PROCEDURE. * - * @param csid the csid + * @param csid the parent csid + * @param itemcsid the person csid + * @param ui the ui * - * @return the person authority + * @return the info for the referencing objects */ + @GET + @Path("{csid}/items/{itemcsid}/refObjs") + @Produces("application/xml") + public AuthorityRefDocList getReferencingObjects( + @PathParam("csid") String parentcsid, + @PathParam("itemcsid") String itemcsid, + @Context UriInfo ui) { + AuthorityRefDocList authRefDocList = null; + if (logger.isDebugEnabled()) { + logger.debug("getReferencingObjects with parentcsid=" + + parentcsid + " and itemcsid=" + itemcsid); + } + if (parentcsid == null || "".equals(parentcsid) + || itemcsid == null || "".equals(itemcsid)) { + logger.error("getPerson: missing parentcsid or itemcsid!"); + Response response = Response.status(Response.Status.BAD_REQUEST).entity( + "get failed on Person with parentcsid=" + + parentcsid + " and itemcsid=" + itemcsid).type( + "text/plain").build(); + throw new WebApplicationException(response); + } + try { + // Note that we have to create the service context for the Items, not the main service + ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(getItemServiceName()); + DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid); + RepositoryClient repoClient = getRepositoryClient(ctx); + DocumentFilter myFilter = handler.createDocumentFilter(); + MultivaluedMap queryParams = ui.getQueryParameters(); + myFilter.setPagination(queryParams); + String serviceType = ServiceBindingUtils.SERVICE_TYPE_PROCEDURE; + List list = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP); + if (list != null) { + serviceType = list.get(0); + } + DocumentWrapper docWrapper = repoClient.getDoc(ctx, itemcsid); + DocumentModel docModel = docWrapper.getWrappedObject(); + String refName = (String)docModel.getPropertyValue(PersonJAXBSchema.REF_NAME); + + authRefDocList = RefNameServiceUtils.getAuthorityRefDocs(repoClient, + ctx.getTenantId(), serviceType, refName, + myFilter.getPageSize(), myFilter.getStartPage(), true ); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); + } catch (DocumentNotFoundException dnfe) { + if (logger.isDebugEnabled()) { + logger.debug("getReferencingObjects", dnfe); + } + Response response = Response.status(Response.Status.NOT_FOUND).entity( + "GetReferencingObjects failed with parentcsid=" + + parentcsid + " and itemcsid=" + itemcsid).type( + "text/plain").build(); + throw new WebApplicationException(response); + } catch (Exception e) { // Includes DocumentException + if (logger.isDebugEnabled()) { + logger.debug("GetReferencingObjects", e); + } + Response response = Response.status( + Response.Status.INTERNAL_SERVER_ERROR).entity("Get failed").type("text/plain").build(); + throw new WebApplicationException(response); + } + if (authRefDocList == null) { + Response response = Response.status(Response.Status.NOT_FOUND).entity( + "Get failed, the requested Person CSID:" + itemcsid + ": was not found.").type( + "text/plain").build(); + throw new WebApplicationException(response); + } + return authRefDocList; + } + @GET @Path("{csid}") public MultipartOutput getPersonAuthority(@PathParam("csid") String csid) { @@ -552,17 +636,12 @@ public class PersonAuthorityResource extends if (logger.isDebugEnabled()) { logger.debug("getPerson with parentcsid=" + parentcsid + " and itemcsid=" + itemcsid); } - if (parentcsid == null || "".equals(parentcsid)) { - logger.error("getPerson: missing csid!"); + if (parentcsid == null || "".equals(parentcsid) + || itemcsid == null || "".equals(itemcsid)) { + logger.error("getPerson: missing parentcsid or itemcsid!"); Response response = Response.status(Response.Status.BAD_REQUEST).entity( - "get failed on Person csid=" + parentcsid).type( - "text/plain").build(); - throw new WebApplicationException(response); - } - if (itemcsid == null || "".equals(itemcsid)) { - logger.error("getPerson: missing itemcsid!"); - Response response = Response.status(Response.Status.BAD_REQUEST).entity( - "get failed on Person itemcsid=" + itemcsid).type( + "get failed on Person with parentcsid=" + + parentcsid + " and itemcsid=" + itemcsid).type( "text/plain").build(); throw new WebApplicationException(response); } @@ -660,6 +739,7 @@ public class PersonAuthorityResource extends } return personObjectList; } + /** * Gets the person list by auth name. -- 2.47.3