private final static String OBJECT_DOCTYPE_PROPERTY = "objectDocumentType"; // FIXME: Get from external constant
protected final static String COLLECTIONOBJECTS_COMMON_SCHEMA = "collectionobjects_common"; // FIXME: Get from external constant
protected final static String COMPUTED_CURRENT_LOCATION_PROPERTY = "computedCurrentLocation"; // FIXME: Create and then get from external constant
- private final static String CURRENT_LOCATION_ELEMENT_NAME = "currentLocation"; // From movement_commons schema. FIXME: Get from external constant that already exists
+ protected final static String CURRENT_LOCATION_ELEMENT_NAME = "currentLocation"; // From movement_commons schema. FIXME: Get from external constant that already exists
protected final static String MOVEMENTS_COMMON_SCHEMA = "movements_common"; // FIXME: Get from external constant
private final static String LOCATION_DATE_PROPERTY = "locationDate"; // FIXME: Get from external constant
protected final static String CURRENT_LOCATION_PROPERTY = "currentLocation"; // FIXME: Get from external constant
collectionObjectDocModel = getCurrentDocModelFromCsid(session, collectionObjectCsid);
if (isActiveDocument(collectionObjectDocModel) == true) {
DocumentModel movementDocModel = getCurrentDocModelFromCsid(session, eventMovementCsid);
- //
- // Get the CollectionObject's most recent, valid related Movement to use for computing the
- // object's current location.
- //
- String mostRecentLocation = getMostRecentLocation(event, session, collectionObjectCsid,
- isAboutToBeRemovedEvent, eventMovementCsid);
- //
- // Update the CollectionObject's Computed Current Location field with the Movement record's location
- //
- boolean didLocationChange = updateCollectionObjectLocation(collectionObjectDocModel, movementDocModel, mostRecentLocation);
+ //
+ // Get the CollectionObject's most recent, valid related Movement to use for computing the
+ // object's current location.
+ //
+ DocumentModel mostRecentMovementDocumentModel = getMostRecentMovement(event, session,
+ collectionObjectCsid, isAboutToBeRemovedEvent, eventMovementCsid);
+ //
+ // Update the CollectionObject's Computed Current Location field with the Movement record's location
+ //
+ boolean didLocationChange = updateCollectionObjectLocation(collectionObjectDocModel,
+ movementDocModel, mostRecentMovementDocumentModel);
//
// If the location changed, save/persist the change to the repository and log the change.
* This method currently returns the related Movement record with the latest
* (i.e. most recent in time) Location Date field value.
*
+ * @param event a nuxeo event
* @param session a repository session.
* @param collectionObjectCsid a CollectionObject identifier (CSID)
* @param isAboutToBeRemovedEvent whether the current event involves a
* record that is slated for removal (hard deletion)
- * @param movementCsidToFilter the CSID of a Movement record slated for
+ * @param eventMovementCsid the CSID of a Movement record slated for
* deletion, or of a Movement record referenced by a Relation record slated
* for deletion. This record should be filtered out, prior to returning the
* most recent Movement record.
* identified by the supplied CSID.
* @throws DocumentException
*/
- protected String getMostRecentLocation(Event event,
- CoreSessionInterface session, String collectionObjectCsid,
- boolean isAboutToBeRemovedEvent, String eventMovementCsid) throws ClientException {
- //
- // Assume we can determine the most recent location by creating an indeterminate result
- //
- String result = INDETERMINATE_LOCATION;
+ protected DocumentModel getMostRecentMovement(Event event,
+ CoreSessionInterface session, String collectionObjectCsid,
+ boolean isAboutToBeRemovedEvent, String eventMovementCsid) throws ClientException {
+ DocumentModel result = null;
//
// Get active Relation records involving Movement records related to this CollectionObject.
String location = (String) movementDocModel.getProperty(MOVEMENTS_COMMON_SCHEMA, CURRENT_LOCATION_ELEMENT_NAME);
if (Tools.isBlank(location) == false) {
- result = location;
+ result = movementDocModel;
} else { // currentLocation must be set
getLogger().error(String.format("Movement record=%s is missing its required location value and so is excluded from the computation of cataloging record=%s's current location.",
NuxeoUtils.getCsid(movementDocModel), collectionObjectCsid));
if (locationDate.after(mostRecentLocationDate)) {
mostRecentLocationDate = locationDate;
mostRecentUpdatedDate = updatedDate;
- result = location;
+ result = movementDocModel;
} else if (locationDate.compareTo(mostRecentLocationDate) == 0) {
// If the current Movement record's location date is identical
// to that of the (at this time) most recent Movement record, then
// The most recent location date value doesn't need to be
// updated here, as the two records' values are identical
mostRecentUpdatedDate = updatedDate;
- result = location;
+ result = movementDocModel;
}
}
}
* @throws ClientException
*/
protected abstract boolean updateCollectionObjectLocation(DocumentModel collectionObjectDocModel,
- DocumentModel movmentDocModel,
- String movementRecordsLocation);
+ DocumentModel movementDocModel,
+ DocumentModel mostRecentMovementDocumentModel);
}
\ No newline at end of file
@Override
protected boolean updateCollectionObjectLocation(DocumentModel collectionObjectDocModel,
DocumentModel movementDocModel,
- String mostRecentLocation) throws ClientException {
- boolean flag = super.updateCollectionObjectLocation(collectionObjectDocModel, movementDocModel, mostRecentLocation);
- collectionObjectDocModel = updateComputedCrateValue(collectionObjectDocModel, movementDocModel);
+ DocumentModel mostRecentMovementDocumentModel) throws ClientException {
+ boolean locationChanged = super.updateCollectionObjectLocation(collectionObjectDocModel, movementDocModel,
+ mostRecentMovementDocumentModel);
+ boolean crateChanged = updateComputedCrateValue(collectionObjectDocModel, mostRecentMovementDocumentModel);
- return flag;
+ return locationChanged || crateChanged;
}
- private DocumentModel updateComputedCrateValue(DocumentModel collectionObjectDocModel,
- DocumentModel movementDocModel)
- throws ClientException {
+ private boolean updateComputedCrateValue(DocumentModel collectionObjectDocModel,
+ DocumentModel movementDocModel) throws ClientException {
+ boolean result = false;
- // Get the current crate value from the Movement (the "new" value)
- String crateRefName = (String) movementDocModel.getProperty(getParamValue(TENANT_MOVEMENTS_SCHEMANAME_KEY),
- CRATE_PROPERTY);
+ String crateRefName = null;
+ if (movementDocModel != null) {
+ // Get the current crate value from the Movement (the "new" value)
+ crateRefName = (String) movementDocModel.getProperty(getParamValue(TENANT_MOVEMENTS_SCHEMANAME_KEY),
+ CRATE_PROPERTY);
+ }
// Check that the value returned, which is expected to be a
// reference (refName) to an authority term:
if (Tools.notBlank(crateRefName)
&& RefNameUtils.parseAuthorityTermInfo(crateRefName) == null) {
logger.warn("Could not parse crate refName '" + crateRefName + "'");
- return collectionObjectDocModel;
+ return false;
} else {
if (logger.isTraceEnabled()) {
logger.trace("crate refName passes basic validation tests.");
// If the new value is blank, any non-blank existing value should always
// be overwritten ('nulled out') with a blank value.
if (Tools.isBlank(crateRefName) && Tools.notBlank(existingCrateRefName)) {
- collectionObjectDocModel.setProperty(TENANT_COLLECTIONOBJECTS_SCHEMANAME_KEY,
+ collectionObjectDocModel.setProperty(getParamValue(TENANT_COLLECTIONOBJECTS_SCHEMANAME_KEY),
COMPUTED_CRATE_PROPERTY, (Serializable) null);
+ result = true;
// Otherwise, if the new value is not blank, and
// * the existing value is blank, or
// * the new value is different than the existing value ...
} else if (Tools.notBlank(crateRefName) &&
- (Tools.isBlank(existingCrateRefName)
- || !crateRefName.equals(existingCrateRefName))) {
+ (Tools.isBlank(existingCrateRefName) || !crateRefName.equals(existingCrateRefName))) {
if (logger.isTraceEnabled()) {
logger.trace("crate refName requires updating.");
}
// ... update the existing value in the CollectionObject with the
// new value from the Movement.
- collectionObjectDocModel.setProperty(TENANT_COLLECTIONOBJECTS_SCHEMANAME_KEY,
+ collectionObjectDocModel.setProperty(getParamValue(TENANT_COLLECTIONOBJECTS_SCHEMANAME_KEY),
COMPUTED_CRATE_PROPERTY, crateRefName);
+ result = true;
} else {
if (logger.isTraceEnabled()) {
logger.trace("crate refName does NOT require updating.");
}
}
- return collectionObjectDocModel;
+ return result;
}
}
\ No newline at end of file
@Override
protected boolean updateCollectionObjectLocation(DocumentModel collectionObjectDocModel,
- DocumentModel movementDocModel,
- String movementRecordsLocation) throws ClientException {
- boolean result = false;
+ DocumentModel movementDocModel, //FIXME: Not needed?
+ DocumentModel mostRecentMovementDocumentModel) throws ClientException {
+ boolean result = false;
+
+ //
+ // The the most recent movement record is null, that means the CollectionObject has
+ // been unrelated to all movement records. Therefore, we need to clear the 'computedCurrentLocation' field.
+ //
+ if (mostRecentMovementDocumentModel == null) {
+ collectionObjectDocModel.setProperty(COLLECTIONOBJECTS_COMMON_SCHEMA,
+ COMPUTED_CURRENT_LOCATION_PROPERTY, null);
+ return true;
+ }
// Check that the location value returned, which is expected to be a reference (refName) to an authority term (such as a storage
// location or organization term):
// * Ensure it is not blank.
// * Ensure it is successfully parsed by the authority item parser.
//
+ String movementRecordsLocation = (String) mostRecentMovementDocumentModel.getProperty(
+ MOVEMENTS_COMMON_SCHEMA, CURRENT_LOCATION_ELEMENT_NAME);
if (Tools.isBlank(movementRecordsLocation)) {
return result;
} else if (RefNameUtils.parseAuthorityTermInfo(movementRecordsLocation) == null) {
<artifactId>org.collectionspace.services.batch.client</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.media.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.collectionspace.services</groupId>
+ <artifactId>org.collectionspace.services.media.service</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.collectionspace.services</groupId>
<artifactId>org.collectionspace.services.batch.jaxb</artifactId>
}
@Override
+ @Deprecated
public abstract void run();
/**
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
-import org.collectionspace.services.batch.BatchCommon;
import org.collectionspace.services.batch.AbstractBatchInvocable;
import org.collectionspace.services.client.CollectionObjectClient;
import org.collectionspace.services.client.CollectionSpaceClient;
import org.collectionspace.services.client.TaxonomyAuthorityClient;
import org.collectionspace.services.client.workflow.WorkflowClient;
import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants;
-import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.CollectionSpaceResource;
import org.collectionspace.services.common.NuxeoBasedResource;
-import org.collectionspace.services.common.ServiceMain;
-import org.collectionspace.services.common.UriTemplateRegistry;
import org.collectionspace.services.common.api.RefName;
import org.collectionspace.services.common.authorityref.AuthorityRefDocList;
import org.collectionspace.services.common.context.ServiceBindingUtils;
import org.collectionspace.services.common.relation.RelationResource;
import org.collectionspace.services.common.vocabulary.AuthorityResource;
import org.collectionspace.services.jaxb.AbstractCommonList;
+import org.collectionspace.services.media.nuxeo.MediaConstants;
import org.collectionspace.services.movement.nuxeo.MovementConstants;
import org.collectionspace.services.relation.RelationsCommonList;
import org.collectionspace.services.relation.RelationsCommonList.RelationListItem;
public abstract class AbstractBatchJob extends AbstractBatchInvocable {
- final Logger logger = LoggerFactory.getLogger(AbstractBatchJob.class);
+ protected final Logger logger = LoggerFactory.getLogger(AbstractBatchJob.class);
private Map<String, String> authorityServiceNamesByDocType;
- @SuppressWarnings("unchecked")
- protected static <T> Set<T> convertListToSet(List<T> list)
- {
+ @SuppressWarnings("unchecked")
+ protected static <T> Set<T> convertListToSet(List<T> list) {
// create a set from the List
return (Set<T>) list.stream().collect(Collectors.toSet());
}
return findRelatedObjects(subjectCsid, null, "affects", null, MovementConstants.NUXEO_DOCTYPE);
}
+ protected List<String> findRelatedMedia(String subjectCsid) throws URISyntaxException {
+ return findRelatedObjects(subjectCsid, null, "affects", null, MediaConstants.NUXEO_DOCTYPE);
+ }
+
protected String findBroader(String subjectCsid) throws URISyntaxException {
List<String> relatedObjects = findRelatedObjects(subjectCsid, null, "hasBroader", null, null);
return getFieldValue(payload, CollectionSpaceClient.COLLECTIONSPACE_CORE_SCHEMA, CollectionSpaceClient.COLLECTIONSPACE_CORE_REFNAME);
}
- protected class ResourceException extends Exception {
+ public class ResourceException extends Exception {
private static final long serialVersionUID = 1L;
private Response response;
--- /dev/null
+package org.collectionspace.services.batch.nuxeo;
+
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.collectionspace.services.client.MediaClient;
+import org.collectionspace.services.common.NuxeoBasedResource;
+import org.collectionspace.services.common.invocable.InvocationResults;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author RJ Li
+ */
+public class SetPrimaryDisplayBatchJob extends AbstractBatchJob {
+ final Logger log = LoggerFactory.getLogger(SetPrimaryDisplayBatchJob.class);
+
+ public SetPrimaryDisplayBatchJob() {
+ setSupportedInvocationModes(Collections.singletonList(INVOCATION_MODE_SINGLE));
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (requestIsForInvocationModeSingle()) {
+ String docType = getInvocationContext().getDocType();
+
+ if (!docType.equals("Media")) {
+ throw new Exception("Unsupported document type");
+ }
+
+ String mediaCsid = getInvocationContext().getSingleCSID();
+
+ if (mediaCsid == null) {
+ throw new Exception("Missing context csid");
+ }
+
+ int numAffected = makePrimary(mediaCsid);
+
+ InvocationResults results = new InvocationResults();
+ results.setNumAffected(numAffected);
+ results.setUserNote(numAffected + " media records updated");
+ results.setPrimaryURICreated("media.html?csid=" + mediaCsid);
+
+ setResults(results);
+ }
+ } catch (Exception e) {
+ setErrorResult(e.getMessage());
+ }
+ }
+
+ /**
+ * Makes the current media record the primary by setting primaryDisplay to true,
+ * and setting primaryDisplay of other media records related to the same
+ * collectionobject to false.
+ *
+ * @param mediaCsid the csid of the media record to make primary
+ */
+ private int makePrimary(String mediaCsid) throws URISyntaxException {
+ int affectedCount = 0;
+
+ // Set the given media record to be primary.
+
+ log.debug("Setting media to be primary: {}", mediaCsid);
+
+ setPrimaryDisplay(mediaCsid, true);
+ affectedCount++;
+
+ // Find all media records related to the same collectionobject(s)
+ // as the given media record.
+
+ Set<String> nonPrimaryMediaCsids = new HashSet<String>();
+
+ for (String collectionObjectCsid : findRelatedCollectionObjects(mediaCsid)) {
+ nonPrimaryMediaCsids.addAll(findRelatedMedia(collectionObjectCsid));
+ }
+
+ // Remove the record we're making primary.
+
+ nonPrimaryMediaCsids.remove(mediaCsid);
+
+ // Set the remaining media to be non-primary.
+
+ for (String nonPrimaryMediaCsid : nonPrimaryMediaCsids) {
+ log.debug("Setting media to be non-primary: {}", nonPrimaryMediaCsid);
+
+ setPrimaryDisplay(nonPrimaryMediaCsid, false);
+ affectedCount++;
+ }
+
+ return affectedCount;
+ }
+
+ private void setPrimaryDisplay(String mediaCsid, boolean primaryDisplay) throws URISyntaxException {
+ String updatePayload =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+ "<document name=\"media\">" +
+ "<ns2:media_pahma xmlns:ns2=\"http://collectionspace.org/services/media/local/pahma\" " +
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+ "<primaryDisplay>" + primaryDisplay + "</primaryDisplay>" +
+ "</ns2:media_pahma>" +
+ "</document>";
+
+ NuxeoBasedResource resource = (NuxeoBasedResource) getResourceMap().get(MediaClient.SERVICE_NAME);
+ resource.update(this.getServiceContext(), getResourceMap(), createUriInfo(), mediaCsid, updatePayload);
+ }
+}
import org.collectionspace.services.common.query.UriInfoImpl;
import org.collectionspace.services.jaxb.AbstractCommonList;
import org.dom4j.DocumentException;
-//import org.jboss.resteasy.specimpl.UriInfoImpl;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
}
@Override
+ @Deprecated
public void run() {
run(null);
}
*/
@Override
public void run(BatchCommon batchCommon) {
-
setCompletionStatus(STATUS_MIN_PROGRESS);
try {
String errMsg = "Error encountered in " + CLASSNAME + ": " + e.getLocalizedMessage();
setErrorResult(errMsg);
}
-
}
private InvocationResults updateComputedCurrentLocations(List<String> csids) {
--- /dev/null
+/**
+ * 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 University of California at Berkeley
+ *
+ * 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.group.nuxeo;
+
+/**
+ * GroupConstant processes Group document
+ *
+ */
+public class GroupConstants {
+
+ public final static String NUXEO_DOCTYPE = "Group";
+
+}
--- /dev/null
+/**
+ * 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 University of California at Berkeley
+ *
+ * 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.media.nuxeo;
+
+/**
+ * MediaConstants specifies constants for the Media service
+ */
+public class MediaConstants {
+
+ public final static String NUXEO_DOCTYPE = "Media";
+ public final static String NUXEO_SCHEMA_NAME = "media";
+ public final static String NUXEO_DC_TITLE = "CollectionSpace-Media";
+
+}