import org.collectionspace.services.common.publicitem.PublicItemResource;
import org.collectionspace.services.common.relation.RelationResource;
import org.collectionspace.services.common.security.SecurityInterceptor;
-import org.collectionspace.services.advancedsearch.AdvancedSearch;
/**
* CollectionSpaceJaxRsApplication, the root application
<dependency>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.jaxb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.common-api</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.collectionspace.services</groupId>
- <artifactId>org.collectionspace.services.advancedsearch.client</artifactId>
- <version>${project.version}</version>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.advancedsearch.client</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
</exclusion>
</exclusions>
</dependency>
- <dependency>
- <groupId>org.collectionspace.services</groupId>
- <artifactId>
- org.collectionspace.services.collectionobject.client
- </artifactId>
- <version>8.2.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.collectionspace.services</groupId>
- <artifactId>
- org.collectionspace.services.media.service
- </artifactId>
- <version>8.3.0-SNAPSHOT</version>
- </dependency>
</dependencies>
<build>
package org.collectionspace.services.advancedsearch;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.stream.Collectors;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Request;
-import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import org.collectionspace.collectionspace_core.CollectionSpaceCore;
+import org.collectionspace.services.MediaJAXBSchema;
import org.collectionspace.services.advancedsearch.AdvancedsearchCommonList.AdvancedsearchListItem;
import org.collectionspace.services.advancedsearch.model.BriefDescriptionListModel;
import org.collectionspace.services.advancedsearch.model.ContentConceptListModel;
import org.collectionspace.services.advancedsearch.model.ObjectNameListModel;
import org.collectionspace.services.advancedsearch.model.ResponsibleDepartmentsListModel;
import org.collectionspace.services.advancedsearch.model.TitleGroupListModel;
-import org.collectionspace.services.client.AdvancedSearchClient;
import org.collectionspace.services.client.CollectionObjectClient;
import org.collectionspace.services.client.CollectionSpaceClient;
import org.collectionspace.services.client.IQueryManager;
-import org.collectionspace.services.client.PayloadInputPart;
-import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PayloadOutputPart;
+import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.collectionobject.CollectionObjectResource;
import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
-import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.UriInfoWrapper;
import org.collectionspace.services.common.context.RemoteServiceContextFactory;
import org.collectionspace.services.common.context.ServiceContextFactory;
import org.collectionspace.services.jaxb.AbstractCommonList;
import org.collectionspace.services.jaxb.AbstractCommonList.ListItem;
+import org.collectionspace.services.jaxb.BlobJAXBSchema;
import org.collectionspace.services.media.MediaResource;
-import org.dom4j.DocumentException;
-import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.collectionspace.services.nuxeo.client.handler.CSDocumentModelList;
+import org.collectionspace.services.nuxeo.client.handler.CSDocumentModelList.CSDocumentModelResponse;
+import org.collectionspace.services.nuxeo.client.handler.UnfilteredDocumentModelHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
-// FIXME: The *Client pattern should be deprecated; it's only really used in unit tests, and trying to use it in services creates authorization challenges. It's repeated here only to maintain parity with existing services.
/**
* This class defines the advanced search endpoints.
*/
-@Path(AdvancedSearchClient.SERVICE_PATH)
+@Path(AdvancedSearchConstants.SERVICE_PATH)
@Consumes("application/xml")
@Produces("application/xml")
public class AdvancedSearch
extends AbstractCollectionSpaceResourceImpl<AdvancedsearchListItem, AdvancedsearchListItem> {
private static final String FIELDS_RETURNED = "uri|csid|refName|blobCsid|updatedAt|objectId|objectNumber|objectName|title|computedCurrentLocation|responsibleDepartments|responsibleDepartment|contentConcepts|briefDescription";
- private static final String COMMON_PART_NAME = CollectionObjectClient.SERVICE_NAME + CollectionSpaceClient.PART_LABEL_SEPARATOR + CollectionSpaceClient.PART_COMMON_LABEL; // FIXME: it's not great to hardcode this here
+ // FIXME: it's not great to hardcode this here
+ private static final String COMMON_PART_NAME = CollectionObjectClient.SERVICE_NAME
+ + CollectionSpaceClient.PART_LABEL_SEPARATOR
+ + CollectionSpaceClient.PART_COMMON_LABEL;
private final Logger logger = LoggerFactory.getLogger(AdvancedSearch.class);
private final CollectionObjectResource cor = new CollectionObjectResource();
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters(true);
logger.info("advancedsearch called with query params: {}", queryParams);
- // the list to return
+ cor.setDocumentHandlerClass(UnfilteredDocumentModelHandler.class);
ObjectFactory objectFactory = new ObjectFactory();
+ // the list to return
AdvancedsearchCommonList resultsList = objectFactory.createAdvancedsearchCommonList();
// FIXME: this shouldn't be necessary?
- resultsList.advancedsearchListItem = new ArrayList<AdvancedsearchListItem>();
+ resultsList.advancedsearchListItem = new ArrayList<>();
+
+ AbstractCommonList abstractCommonList = cor.getList(uriInfo);
+ if (!(abstractCommonList instanceof CSDocumentModelList)) {
+ return resultsList;
+ }
+
+ Unmarshaller unmarshaller;
+ CSDocumentModelList collectionObjectList = (CSDocumentModelList) abstractCommonList;
+ try {
+ unmarshaller = AdvancedSearchJAXBContext.getJaxbContext().createUnmarshaller();
+ } catch (JAXBException e) {
+ // this should result in a 500, need to verify from bigReThrow to see what exception it should be
+ throw new RuntimeException("Unable to create unmarshaller for AdvancedSearch", e);
+ }
- // the logic here is to use CollectionObjectResource to perform the search, then
- // loop over the results retrieving corresponding CollectionobjectsCommon objects,
- // which have more fields
- AbstractCommonList collectionObjectList = cor.getList(uriInfo);
- List<ListItem> collectionObjectListItems = collectionObjectList.getListItem();
+ for (CSDocumentModelResponse response : collectionObjectList.getResponseList()) {
+ PoxPayloadOut outputPayload = response.getPayload();
+ PayloadOutputPart corePart = outputPayload.getPart(CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA);
+ PayloadOutputPart commonPart = outputPayload.getPart(COMMON_PART_NAME);
+ CollectionSpaceCore core;
+ CollectionobjectsCommon collectionObject;
- HashMap<String, String> collectionObjectValuesMap = new HashMap<String, String>();
- for (ListItem item : collectionObjectListItems) {
- // FIXME: is there no better way to do this? We should at least abstract this logic out of here
- List<Element> els = item.getAny();
- for (Element el : els) {
- String elementName = el.getTagName();
- String elementText = el.getTextContent();
- collectionObjectValuesMap.put(elementName, elementText);
+ try {
+ core = (CollectionSpaceCore) unmarshaller.unmarshal((Document) corePart.getBody());
+ collectionObject = (CollectionobjectsCommon) unmarshaller.unmarshal((Document) commonPart.getBody());
+ } catch (JAXBException e) {
+ throw new RuntimeException(e);
}
- String csid = collectionObjectValuesMap.get("csid");
+
+ String csid = response.getCsid();
UriInfoWrapper wrappedUriInfo = new UriInfoWrapper(uriInfo);
List<String> blobCsids = findBlobCsids(csid, wrappedUriInfo);
- /*
- * NOTE: code below is partly based on
- * CollectionObjectServiceTest.readCollectionObjectCommonPart and
- * AbstractPoxServiceTestImpl
- */
- ResourceMap resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class);
- Response res = cor.get(request, resourceMap, uriInfo, csid);
- int statusCode = res.getStatus();
- logger.warn("advancedsearch: call to CollectionObjectResource for csid {} returned status {}", csid, statusCode);
- CollectionobjectsCommon collectionObject = null;
- // FIXME: is there no better way to do this? We should at least abstract this logic out of here
- PoxPayloadIn input = null;
- try {
- String responseXml = new String((byte[]) res.getEntity(),StandardCharsets.UTF_8);
- input = new PoxPayloadIn(responseXml);
- } catch (DocumentException e) {
- // TODO: need better error handling
- logger.error("advancedsearch: could not create PoxPayloadIn", e);
- continue;
- }
- if (null != input) {
- PayloadInputPart payloadInputPart = input.getPart(COMMON_PART_NAME);
- if (null != payloadInputPart) {
- collectionObject = (CollectionobjectsCommon) payloadInputPart.getBody();
- }
+ AdvancedsearchListItem listItem = objectFactory.createAdvancedsearchCommonListAdvancedsearchListItem();
+ if (core != null) {
+ listItem.setCsid(csid);
+ listItem.setRefName(core.getRefName());
+ listItem.setUri(core.getUri());
+ listItem.setUpdatedAt(core.getUpdatedAt());
+ } else {
+ logger.warn("advancedsearch: could not find collectionspace_core associated with csid {}", csid);
}
- // build up a listitem for the result list using the additional fields in CollectionObjectsCommon
- if (null != collectionObject) {
- AdvancedsearchListItem listItem = objectFactory.createAdvancedsearchCommonListAdvancedsearchListItem();
+
+ if (collectionObject != null) {
+ listItem.setObjectNumber(collectionObject.getObjectNumber());
listItem.setBriefDescription(BriefDescriptionListModel
- .briefDescriptionListToDisplayString(collectionObject.getBriefDescriptions()));
- // TODO: collectionObject.getComputedCurrentLocation() is (can be?) a refname.
- // code below extracts display name. there's probably something in RefName or
- // similar to do this kind of thing see also
- // ContentConceptListModel.displayNameFromRefName
- String currLoc = collectionObject.getComputedCurrentLocation();
- String currLocDisplayName = currLoc;
- if (null != currLoc && currLoc.indexOf("'") < currLoc.lastIndexOf("'")) {
- currLocDisplayName = currLoc.substring(currLoc.indexOf("'") + 1, currLoc.lastIndexOf("'"));
- }
- listItem.setComputedCurrentLocation(currLocDisplayName); // "Computed Current
- // Location: Display
- // full string" from
- // https://docs.google.com/spreadsheets/d/103jyxa2oCtt8U0IQ25xsOyIxqwKvPNXlcCtcjGlT5tQ/edit?gid=0#gid=0
+ .briefDescriptionListToDisplayString(collectionObject.getBriefDescriptions()));
+ listItem.setComputedCurrentLocation(collectionObject.getComputedCurrentLocation());
listItem.setObjectName(
- ObjectNameListModel.objectNameListToDisplayString(collectionObject.getObjectNameList()));
+ ObjectNameListModel.objectNameListToDisplayString(collectionObject.getObjectNameList()));
listItem.setTitle(
- TitleGroupListModel.titleGroupListToDisplayString(collectionObject.getTitleGroupList()));
+ TitleGroupListModel.titleGroupListToDisplayString(collectionObject.getTitleGroupList()));
ResponsibleDepartmentsList rdl = ResponsibleDepartmentsListModel
- .responsibleDepartmentListToResponsibleDepartmentsList(
- collectionObject.getResponsibleDepartments());
+ .responsibleDepartmentListToResponsibleDepartmentsList(
+ collectionObject.getResponsibleDepartments());
listItem.setResponsibleDepartments(rdl);
listItem.setResponsibleDepartment(
- ResponsibleDepartmentsListModel.responsibleDepartmentsListDisplayString(rdl));
+ ResponsibleDepartmentsListModel.responsibleDepartmentsListDisplayString(rdl));
listItem.setContentConcepts(
- ContentConceptListModel.contentConceptListDisplayString(collectionObject.getContentConcepts()));
+ ContentConceptListModel.contentConceptListDisplayString(collectionObject.getContentConcepts()));
// from media resource
if (blobCsids.size() > 0) {
listItem.setBlobCsid(blobCsids.get(0));
}
-
- // from collectionobject itself
- listItem.setCsid(collectionObjectValuesMap.get("csid"));
- listItem.setObjectId(collectionObjectValuesMap.get("objectId")); // "Identification Number: Display full
- // string" from
- // https://docs.google.com/spreadsheets/d/103jyxa2oCtt8U0IQ25xsOyIxqwKvPNXlcCtcjGlT5tQ/edit?gid=0#gid=0
- listItem.setObjectNumber(collectionObjectValuesMap.get("objectNumber"));
- listItem.setRefName(collectionObjectValuesMap.get("refName"));
- listItem.setUri(collectionObjectValuesMap.get("uri"));
- try {
- XMLGregorianCalendar date = DatatypeFactory.newInstance()
- .newXMLGregorianCalendar(collectionObjectValuesMap.get("updatedAt"));
- listItem.setUpdatedAt(date); // "Last Updated Date: Display Date, if updated same day can we display
- // x number of hours ago" from
- // https://docs.google.com/spreadsheets/d/103jyxa2oCtt8U0IQ25xsOyIxqwKvPNXlcCtcjGlT5tQ/edit?gid=0#gid=0
- } catch (DatatypeConfigurationException e) {
- // FIXME need better error handling
- logger.error("advancedsearch: could not create XMLGregorianCalendar for updatedAt ", e);
- logger.error("advancedsearch: updatedAt: {}", collectionObjectValuesMap.get("updatedAt"));
- }
-
// add the populated item to the results
resultsList.getAdvancedsearchListItem().add(listItem);
} else {
logger.warn("advancedsearch: could not find CollectionobjectsCommon associated with csid {}", csid);
}
- res.close();
+
}
// NOTE: I think this is necessary for the front end to know what to do with
wrappedQueryParams.add("pgNum", "0");
wrappedQueryParams.add("sortBy", "media_common:title");
AbstractCommonList associatedMedia = mr.getList(wrappedUriInfo);
- HashMap<String, String> mediaResourceValuesMap = new HashMap<String, String>();
- ArrayList<String> blobCsids = new ArrayList<String>();
- for (ListItem item : associatedMedia.getListItem()) {
- // FIXME: is there no better way to do this? we should at least abstract out this logic
- List<Element> els = item.getAny();
- for (Element el : els) {
- String elementName = el.getTagName();
- String elementText = el.getTextContent();
- mediaResourceValuesMap.put(elementName, elementText);
- }
- String blobCsid = mediaResourceValuesMap.get("blobCsid");
- if (null != blobCsid) {
- blobCsids.add(blobCsid);
- }
+ if (associatedMedia == null || associatedMedia.getListItem() == null) {
+ return Collections.emptyList();
}
- return blobCsids;
+
+ return associatedMedia.getListItem().stream()
+ .filter(item -> item != null && item.getAny() != null)
+ .flatMap(li -> li.getAny().stream())
+ .filter(element -> MediaJAXBSchema.blobCsid.equals(element.getTagName()))
+ .map(Element::getTextContent)
+ .filter(blobCsid -> blobCsid != null && !blobCsid.isEmpty())
+ .collect(Collectors.toList());
}
@Override
@Override
public String getServiceName() {
- return AdvancedSearchClient.SERVICE_NAME;
+ return AdvancedSearchConstants.SERVICE_NAME;
}
@Override
--- /dev/null
+package org.collectionspace.services.advancedsearch;
+
+/**
+ * Maybe better as an enum type?
+ */
+public interface AdvancedSearchConstants {
+
+ String SERVICE_NAME = "advancedsearch";
+ String SERVICE_PATH_COMPONENT = SERVICE_NAME;
+ String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
+
+}
--- /dev/null
+package org.collectionspace.services.advancedsearch;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.collectionspace.collectionspace_core.CollectionSpaceCore;
+import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
+
+/**
+ * Singleton for the {@link JAXBContext} which the AdvancedSearch will use
+ * Eventually this should just be a bean which can be injected
+ * @since 8.3.0
+ */
+public final class AdvancedSearchJAXBContext {
+ private static final AdvancedSearchJAXBContext INSTANCE = new AdvancedSearchJAXBContext();
+
+ private final JAXBContext jaxbContext;
+
+ private AdvancedSearchJAXBContext() {
+ try {
+ jaxbContext = JAXBContext.newInstance(CollectionSpaceCore.class, CollectionobjectsCommon.class);
+ } catch (JAXBException e) {
+ throw new RuntimeException("Unable to create JAXBContext for AdvancedSearch");
+ }
+ }
+
+ public static JAXBContext getJaxbContext() {
+ return INSTANCE.jaxbContext;
+ }
+}
package org.collectionspace.services.client;
-//import java.io.ByteArrayInputStream; //FIXME: REM - Remove these unneeded import statements
-//import java.io.InputStream;
-//import java.io.Reader;
-//import java.io.StringReader;
-//import java.util.Iterator;
-//import java.util.List;
-
-//import javax.xml.transform.Source;
-//import javax.xml.transform.stream.StreamSource;
-
-//import org.dom4j.Attribute;
-//import org.dom4j.Document;
import java.io.File;
import java.io.IOException;
import org.dom4j.DocumentException;
import org.dom4j.Element;
-//import org.dom4j.Namespace;
-//import org.dom4j.io.SAXReader;
-//import org.xml.sax.InputSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.collectionspace.services.authorization.PermissionException;
import org.collectionspace.services.client.CollectionSpaceClient;
-import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.config.ServiceConfigUtils;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
/** The storage client. */
private StorageClient storageClient;
-
+
+ /**
+ * A DocumentHandler provided for use instead of the default from the ServiceContext
+ * Note: considering a provider or something here, not entirely sure yet
+ */
+ private Class<? extends DocumentHandler> documentHandlerClass;
+
/**
* Extract id.
*
*
* @throws Exception the exception
*/
- public DocumentHandler createDocumentHandler(ServiceContext<IT, OT> ctx,
- Object commonPart) throws Exception {
- DocumentHandler docHandler = ctx.getDocumentHandler();
+ public DocumentHandler createDocumentHandler(ServiceContext<IT, OT> ctx, Object commonPart) throws Exception {
+ DocumentHandler docHandler;
+ if (documentHandlerClass != null) {
+ docHandler = documentHandlerClass.newInstance();
+ docHandler.setServiceContext(ctx);
+ } else {
+ docHandler = ctx.getDocumentHandler();
+ }
+
+ // common part is the jaxb class?
docHandler.setCommonPart(commonPart);
return docHandler;
}
}
return responseBuilder;
- }
+ }
+
+ public void setDocumentHandlerClass(Class<? extends DocumentHandler> dhClass) {
+ this.documentHandlerClass = dhClass;
+ }
}
*/
package org.collectionspace.services.common;
-import java.util.Iterator;
-import java.util.List;
-
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
import org.dom4j.Element;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
-import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
-import org.dom4j.Document;
/**
* RemoteServiceContext is used to encapsulate the service context of a
this.properties = properties;
}
-// public void initializeDocumentFilter(ServiceContext ctx) {
-// DocumentFilter docFilter = this.createDocumentFilter(ctx);
-// this.setDocumentFilter(docFilter);
-// }
- /* (non-Javadoc)
- * @see org.collectionspace.services.common.document.DocumentHandler#createDocumentFilter()
- */
-@Override
+ /**
+ * @see org.collectionspace.services.common.document.DocumentHandler#createDocumentFilter()
+ */
+ @Override
public abstract DocumentFilter createDocumentFilter();
/**
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.text.DecimalFormat;
-import java.text.FieldPosition;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import org.dom4j.io.DOMReader;
import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
-//import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
import org.nuxeo.ecm.core.io.ExportConstants;
import org.nuxeo.common.collections.PrimitiveArrays;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-
-//import org.dom4j.Document;
-//import org.dom4j.Element;
-//import org.dom4j.Node;
-//import org.dom4j.NodeList;
-//import org.dom4j.Text;
/**
* DocumentUtils is a collection of utilities related to document management
Schema schema = getSchemaFromName(partMeta.getLabel());
buildDocument(document, root, objectProps, schema);
- String w3cDocumentStr = xmlToString(document);
+ // String w3cDocumentStr = xmlToString(document);
DOMReader reader = new DOMReader();
org.dom4j.Document dom4jDoc = reader.read(document);
result.detach(); // return just the root element detached from the DOM
// document
- return result;// FIXME: REM - Add if (logger.isTraceEnabled() == true)
- // logger.trace(document.asXML());
+ return result;
}
/**
* @throws IOException
* Signals that an I/O exception has occurred.
*/
- private static void buildProperty(Document document, Element parent,
- Field field, Object value) throws IOException {
+ public static void buildProperty(Document document, Element parent, Field field, Object value) throws IOException {
Type type = field.getType();
// no need to qualify each element name as namespace is already added
String propName = field.getName().getLocalName();
--- /dev/null
+package org.collectionspace.services.nuxeo.client.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+
+/**
+ * A CollectionSpace version of the {@link org.nuxeo.ecm.core.api.DocumentModelList}. Primarily used in order to
+ * response with a full dataset rather than the simpler list views previously done in CollectionSpace.
+ *
+ * @since 8.3.0
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+@XmlRootElement(name = "abstract-common-list")
+public class CSDocumentModelList extends AbstractCommonList {
+
+ public static class CSDocumentModelResponse {
+ private final String csid;
+ private final PoxPayloadOut payload;
+
+ public CSDocumentModelResponse(final String csid, final PoxPayloadOut out) {
+ this.csid = csid;
+ this.payload = out;
+ }
+
+ public String getCsid() {
+ return csid;
+ }
+
+ public PoxPayloadOut getPayload() {
+ return payload;
+ }
+ }
+
+ private final List<CSDocumentModelResponse> responseList = new ArrayList<>();
+
+ public List<CSDocumentModelResponse> getResponseList() {
+ return responseList;
+ }
+
+ public void addResponsePayload(final String csid, final PoxPayloadOut out) {
+ responseList.add(new CSDocumentModelResponse(csid, out));
+ }
+}
--- /dev/null
+package org.collectionspace.services.nuxeo.client.handler;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.collectionspace.services.client.IQueryManager;
+import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.PoxPayloadOut;
+import org.collectionspace.services.client.workflow.WorkflowClient;
+import org.collectionspace.services.common.authorityref.AuthorityRefList;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.DocumentException;
+import org.collectionspace.services.common.document.DocumentFilter;
+import org.collectionspace.services.common.document.DocumentUtils;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
+import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.lifecycle.TransitionDef;
+import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
+import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentFilter;
+import org.dom4j.io.DOMReader;
+import org.nuxeo.ecm.core.api.DocumentModel;
+import org.nuxeo.ecm.core.api.DocumentModelList;
+import org.nuxeo.ecm.core.api.model.Property;
+import org.nuxeo.ecm.core.schema.types.Field;
+import org.nuxeo.ecm.core.schema.types.Schema;
+
+/**
+ * A DocumentModelHandler which does not restrict the view to a single xml part (e.g. collectionobjects_common)
+ *
+ * Note: currently the only use for this is the AdvancedSearch API which requires a full view of the Document being
+ * returned to us by Nuxeo.
+ *
+ * @since 8.3.0
+ */
+public class UnfilteredDocumentModelHandler extends DocumentModelHandler<DocumentModel, AbstractCommonList> {
+
+ private static final String NAME = "unfiltered-search-result";
+
+ private AbstractCommonList commonList;
+ private DocumentModel document;
+ private DocumentFilter filter;
+
+ @Override
+ public DocumentFilter getDocumentFilter() {
+ if (filter == null) {
+ ServiceContext<PoxPayloadIn, PoxPayloadOut> context = getServiceContext();
+ if (context == null) {
+ throw new RuntimeException("DocumentModelHandler is missing its ServiceContext and cannot complete the "
+ + "current request");
+ }
+
+ filter = new NuxeoDocumentFilter(context);
+
+ // Initialize the sort, paging, and workflow params
+ MultivaluedMap<String, String> queryParameters = context.getQueryParams();
+ if (queryParameters != null && !queryParameters.isEmpty()) {
+ filter.setSortOrder(queryParameters);
+ filter.setPagination(queryParameters);
+ String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
+ if (workflowWhereClause != null) {
+ filter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
+ }
+ }
+ }
+
+ return filter;
+ }
+
+ /**
+ * yoinked from AbstractServiceContextImpl. Might move into a common class since it's only returning a string.
+ */
+ private String buildWorkflowWhereClause(MultivaluedMap<String, String> queryParams) {
+ String result = null;
+
+ String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_DELETED_QP);
+ // if set to true, it doesn't matter what the value is for 'includeDeleted'
+ String includeOnlyDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED_QP);
+
+ if (includeOnlyDeleted != null) {
+ if (Boolean.parseBoolean(includeOnlyDeleted)) {
+ // A value of 'true' for 'includeOnlyDeleted' means we're looking *only* for soft-deleted records/documents.
+ result = String.format("(ecm:currentLifeCycleState = '%s' OR ecm:currentLifeCycleState = '%s' OR ecm:currentLifeCycleState = '%s')",
+ WorkflowClient.WORKFLOWSTATE_DELETED,
+ WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED,
+ WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
+ }
+ } else if (includeDeleted != null && !Boolean.parseBoolean(includeDeleted)) {
+ // We can only get here if the 'includeOnlyDeleted' query param is missing altogether.
+ // Ensure we don't return soft-deleted records
+ result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
+ WorkflowClient.WORKFLOWSTATE_DELETED,
+ WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED,
+ WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
+ }
+
+ return result;
+ }
+
+
+ /**
+ * This is similar to the implementation in
+ * {@link org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler#extractAllParts(DocumentWrapper)}
+ * except for a list result
+ *
+ * @param wrapDoc The document model list from nuxeo
+ * @return A {@link CSDocumentModelList} with the {@link org.collectionspace.services.client.PayloadOutputPart}s
+ * for each document
+ * @throws Exception if there are any errors handling the XML
+ */
+ @Override
+ public AbstractCommonList extractCommonPartList(DocumentWrapper<DocumentModelList> wrapDoc) throws Exception {
+ final String xmlNs = "ns2";
+ final DocumentModelList documentModelList = wrapDoc.getWrappedObject();
+
+ final CSDocumentModelList cspaceDocModelList = new CSDocumentModelList();
+ final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+
+ final DocumentFilter docFilter = getDocumentFilter();
+ long pageSize = docFilter.getPageSize();
+ long pageNum = pageSize != 0 ? docFilter.getOffset() / pageSize : pageSize;
+ // set the page size and page number
+ cspaceDocModelList.setPageNum(pageNum);
+ cspaceDocModelList.setPageSize(pageSize);
+ DocumentModelList docList = wrapDoc.getWrappedObject();
+ // Set num of items in list. this is useful to our testing framework.
+ cspaceDocModelList.setItemsInPage(docList.size());
+ // set the total result size
+ cspaceDocModelList.setTotalItems(docList.totalSize());
+
+ for (DocumentModel documentModel : documentModelList) {
+ final PoxPayloadOut out = new PoxPayloadOut(NAME);
+
+ // todo: only work on schemas we support
+ for (Schema schema : documentModel.getDocumentType().getSchemas()) {
+ final String schemaName = schema.getName();
+ org.w3c.dom.Document document = documentBuilder.newDocument();
+ final String namespaceUri = schema.getNamespace().uri;
+ final String qualifiedName = xmlNs + ":" + schemaName;
+
+ org.w3c.dom.Element root = document.createElementNS(namespaceUri, qualifiedName);
+ root.setAttribute("xmlns:" + xmlNs, namespaceUri);
+ document.appendChild(root);
+
+ final Collection<Property> properties = documentModel.getPropertyObjects(schemaName);
+ for (Property property : properties) {
+ final Field field = property.getField();
+ final Object value = property.getValue();
+
+ if (value != null) {
+ DocumentUtils.buildProperty(document, root, field, value);
+ }
+ }
+
+ out.addPart(schemaName, document);
+ }
+
+ cspaceDocModelList.addResponsePayload(documentModel.getName(), out);
+ }
+
+ return cspaceDocModelList;
+ }
+
+ @Override
+ public DocumentModel extractCommonPart(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
+ return wrapDoc.getWrappedObject();
+ }
+
+ @Override
+ public DocumentModel getCommonPart() {
+ return document;
+ }
+
+ @Override
+ public void setCommonPart(DocumentModel document) {
+ this.document = document;
+ }
+
+ @Override
+ public AbstractCommonList getCommonPartList() {
+ return commonList;
+ }
+
+ @Override
+ public void setCommonPartList(AbstractCommonList obj) {
+ commonList = obj;
+ }
+
+ @Override
+ public String getQProperty(String prop) throws DocumentException {
+ return "";
+ }
+
+ @Override
+ public boolean supportsWorkflowStates() {
+ return false;
+ }
+
+ // unsupported (for now)
+
+ @Override
+ protected String getRefnameDisplayName(DocumentWrapper<DocumentModel> docWrapper) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void handleWorkflowTransition(ServiceContext ctx, DocumentWrapper<DocumentModel> wrapDoc,
+ TransitionDef transitionDef) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void completeUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
+
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void fillCommonPart(DocumentModel obj, DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AbstractCommonList extractPagingInfo(AbstractCommonList theCommonList,
+ DocumentWrapper<DocumentModelList> wrapDoc) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AuthorityRefList getAuthorityRefs(String csid,
+ List<RefNameServiceUtils.AuthRefConfigInfo> authRefConfigInfoList)
+ throws Exception {
+ throw new UnsupportedOperationException();
+ }
+}
*/
package org.collectionspace.services.nuxeo.client.java;
-import java.util.Collection;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.commons.lang.StringUtils;
import org.collectionspace.services.client.Profiler;
import org.collectionspace.services.client.CollectionSpaceClient;
-import org.collectionspace.services.client.IClientQueryParams;
import org.collectionspace.services.client.IQueryManager;
import org.collectionspace.services.client.IRelationsManager;
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.common.document.AbstractMultipartDocumentHandlerImpl;
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.DocumentWrapper;
import org.collectionspace.services.common.document.DocumentWrapperImpl;
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
import org.collectionspace.services.lifecycle.Lifecycle;
-import org.collectionspace.services.lifecycle.State;
-import org.collectionspace.services.lifecycle.StateList;
-import org.collectionspace.services.lifecycle.TransitionDef;
-import org.collectionspace.services.lifecycle.TransitionDefList;
-import org.collectionspace.services.lifecycle.TransitionList;
-import org.nuxeo.ecm.core.NXCore;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.model.PropertyException;
-import org.nuxeo.ecm.core.lifecycle.LifeCycle;
-import org.nuxeo.ecm.core.lifecycle.LifeCycleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @see org.collectionspace.services.common.document.AbstractDocumentHandlerImpl#isCMISQuery()
*/
public boolean isCMISQuery() {
- boolean result = false;
-
- MultivaluedMap<String, String> queryParams = getServiceContext().getQueryParams();
- //
- // Look the query params to see if we need to make a CMSIS query.
- //
- String asSubjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_SUBJECT);
- String asOjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_OBJECT);
- String asEither = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_EITHER);
- if (asSubjectCsid != null || asOjectCsid != null || asEither != null) {
- result = true;
- }
-
- return result;
+ boolean result = false;
+
+ MultivaluedMap<String, String> queryParams = getServiceContext().getQueryParams();
+ String asSubjectCsid = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_SUBJECT);
+ String asObjectCsid = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_OBJECT);
+ String asEither = queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_AS_EITHER);
+ if (asSubjectCsid != null || asObjectCsid != null || asEither != null) {
+ result = true;
+ }
+
+ return result;
}
-
+
@Override
public String getDocumentsToIndexQuery(String indexId, String csid) throws DocumentException, Exception {
String result = null;
*
* $LastChangedRevision: $
* $LastChangedDate: $
- * @param <T>
+ * @param <T>
* @param <TL>
*/
-public abstract class RemoteDocumentModelHandlerImpl<T, TL>
+public abstract class RemoteDocumentModelHandlerImpl<T, TL>
extends DocumentModelHandler<T, TL> {
/** The logger. */
* @throws Exception
*/
@Deprecated
- protected Map<String, Object> extractPart(
- DocumentModel docModel, String schema, ObjectPartType partMeta,
- Map<String, Object> addToMap)
+ protected Map<String, Object> extractPart(DocumentModel docModel,
+ String schema,
+ ObjectPartType partMeta,
+ Map<String, Object> addToMap)
throws Exception {
Map<String, Object> result = null;
return result;
}
- /*
- public String getStringPropertyFromDoc(
- ServiceContext ctx,
- String csid,
- String propertyXPath ) throws DocumentNotFoundException, DocumentException {
- RepositoryInstance repoSession = null;
- boolean releaseRepoSession = false;
- String returnValue = null;
-
- try{
- RepositoryClientImpl repoClient = (RepositoryClientImpl)this.getRepositoryClient(ctx);
- repoSession = this.getRepositorySession();
- if (repoSession == null) {
- repoSession = repoClient.getRepositorySession();
- releaseRepoSession = true;
- }
-
- try {
- DocumentWrapper<DocumentModel> wrapper = repoClient.getDoc(repoSession, ctx, csid);
- DocumentModel docModel = wrapper.getWrappedObject();
- returnValue = (String) docModel.getPropertyValue(propertyXPath);
- } catch (PropertyException pe) {
- throw pe;
- } catch (DocumentException de) {
- throw de;
- } catch (Exception e) {
- if (logger.isDebugEnabled()) {
- logger.debug("Caught exception ", e);
- }
- throw new DocumentException(e);
- } finally {
- if (releaseRepoSession && repoSession != null) {
- repoClient.releaseRepositorySession(repoSession);
- }
- }
- } catch (Exception e) {
- if (logger.isDebugEnabled()) {
- logger.debug("Caught exception ", e);
- }
- throw new DocumentException(e);
- }
-
-
- if (logger.isWarnEnabled() == true) {
- logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
- }
- return returnValue;
- }
- */
-
-
-
/* (non-Javadoc)
* @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#getAuthorityRefs(org.collectionspace.services.common.document.DocumentWrapper, java.util.List)
*/
*/
package org.collectionspace.services.export.nuxeo;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.InputStream;
-import java.nio.file.Files;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-
-import javax.ws.rs.core.MediaType;
-import javax.naming.NamingException;
-import javax.ws.rs.core.Response;
-
-import org.apache.commons.lang.StringUtils;
-import org.collectionspace.authentication.AuthN;
-import org.collectionspace.services.ExportJAXBSchema;
-import org.collectionspace.services.account.AccountResource;
-import org.collectionspace.services.authorization.AuthZ;
-import org.collectionspace.services.authorization.CSpaceResource;
-import org.collectionspace.services.authorization.PermissionException;
-import org.collectionspace.services.authorization.URIResourceImpl;
-import org.collectionspace.services.authorization.perms.ActionType;
+
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
-import org.collectionspace.services.client.ExportClient;
-import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.NuxeoBasedResource;
import org.collectionspace.services.common.ResourceMap;
-import org.collectionspace.services.common.ServiceMain;
-import org.collectionspace.services.common.api.JEEServerDeployment;
-import org.collectionspace.services.common.api.FileTools;
-import org.collectionspace.services.common.api.Tools;
-import org.collectionspace.services.common.authorization_mgt.ActionGroup;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
-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.DocumentWrapper;
import org.collectionspace.services.common.invocable.Invocable;
import org.collectionspace.services.common.invocable.InvocationContext;
-import org.collectionspace.services.common.invocable.InvocationContext.ListCSIDs;
-import org.collectionspace.services.common.storage.JDBCTools;
import org.collectionspace.services.config.service.ServiceBindingType;
-import org.collectionspace.services.config.types.PropertyItemType;
import org.collectionspace.services.export.ExportsCommon;
-import org.collectionspace.services.jaxb.InvocableJAXBSchema;
import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl;
-import org.collectionspace.services.nuxeo.util.NuxeoUtils;
-import org.nuxeo.ecm.core.api.model.PropertyException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.slf4j.Logger;
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ jaxb:version="1.0"
+ targetNamespace="http://collectionspace.org/collectionspace_core/"
+ version="4.0">
+ <xs:element name="collectionspace_core">
+ <xs:annotation>
+ <xs:appinfo>
+ <jaxb:class name="CollectionSpaceCore" />
+ <jaxb:package name="org.collectionspace.services.core" />
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="uri" type="xs:string"/>
+ <xs:element name="updatedAt" type="xs:date"/>
+ <xs:element name="refName" type="xs:string"/>
+ <xs:element name="updatedBy" type="xs:string"/>
+ <xs:element name="tenantId" type="xs:string"/>
+ <xs:element name="createdAt" type="xs:date"/>
+ <xs:element name="createdBy" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>