/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florent Guillaume
*/
package org.eclipse.ecr.opencmis.impl.client;
import java.util.ArrayList;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.chemistry.opencmis.client.api.ObjectId;
import org.apache.chemistry.opencmis.client.api.ObjectType;
import org.apache.chemistry.opencmis.client.api.Policy;
import org.apache.chemistry.opencmis.client.api.Property;
import org.apache.chemistry.opencmis.client.api.Relationship;
import org.apache.chemistry.opencmis.client.api.Rendition;
import org.apache.chemistry.opencmis.client.api.TransientCmisObject;
import org.apache.chemistry.opencmis.client.runtime.PropertyImpl;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.ExtensionLevel;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
import org.eclipse.ecr.opencmis.impl.server.NuxeoPropertyData;
/**
* A transient CMIS object for Nuxeo. Stores transient data until a save() is
* done.
*/
public class NuxeoTransientObject implements TransientCmisObject {
protected final NuxeoObject object;
/** Updated properties. */
protected Map<String, Object> properties;
protected Boolean markedForDeleteAllVersions;
public NuxeoTransientObject(NuxeoObject object) {
this.object = object;
properties = new HashMap<String, Object>();
}
@Override
public NuxeoObject getCmisObject() {
return object;
}
@Override
public String getId() {
return object.getId();
}
@Override
public ObjectType getType() {
return object.getType();
}
@Override
public BaseTypeId getBaseTypeId() {
return object.getBaseTypeId();
}
@Override
public ObjectType getBaseType() {
return object.getBaseType();
}
@Override
public String getName() {
return getPropertyValue(PropertyIds.NAME);
}
@Override
public String getChangeToken() {
return getPropertyValue(PropertyIds.CHANGE_TOKEN);
}
@Override
public String getCreatedBy() {
return getPropertyValue(PropertyIds.CREATED_BY);
}
@Override
public GregorianCalendar getCreationDate() {
return getPropertyValue(PropertyIds.CREATION_DATE);
}
@Override
public GregorianCalendar getLastModificationDate() {
return getPropertyValue(PropertyIds.LAST_MODIFICATION_DATE);
}
@Override
public String getLastModifiedBy() {
return getPropertyValue(PropertyIds.LAST_MODIFIED_BY);
}
@Override
public AllowableActions getAllowableActions() {
return object.getAllowableActions();
}
@Override
public List<Policy> getPolicies() {
return object.getPolicies();
}
@Override
public List<Relationship> getRelationships() {
return object.getRelationships();
}
@Override
public List<Rendition> getRenditions() {
return object.getRenditions();
}
@Override
public void addAce(String principalId, List<String> permissions,
AclPropagation aclPropagation) {
throw new CmisNotSupportedException();
}
@Override
public void removeAce(String principalId, List<String> permissions,
AclPropagation aclPropagation) {
throw new CmisNotSupportedException();
}
@Override
public Acl getOriginalAcl() {
throw new CmisNotSupportedException();
}
@Override
public void applyPolicy(Policy... policyIds) {
throw new CmisNotSupportedException();
}
@Override
public void removePolicy(Policy... policyIds) {
throw new CmisNotSupportedException();
}
@Override
public List<CmisExtensionElement> getInputExtensions(ExtensionLevel level) {
return Collections.emptyList();
}
@Override
public List<CmisExtensionElement> getOutputExtensions(ExtensionLevel level) {
return Collections.emptyList();
}
@Override
public void setOutputExtensions(ExtensionLevel level,
List<CmisExtensionElement> extensions) {
throw new CmisNotSupportedException();
}
@Override
public void delete(boolean allVersions) {
markedForDeleteAllVersions = Boolean.valueOf(allVersions);
}
@Override
public void setName(String name) {
setPropertyValue(PropertyIds.NAME, name);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getPropertyValue(String id) {
if (properties.containsKey(id)) {
return (T) properties.get(id);
}
// following cast needed by Sun javac
return (T) object.getPropertyValue(id);
}
@SuppressWarnings("unchecked")
@Override
public <T> Property<T> getProperty(String id) {
// TODO cache Property objects?
if (properties.containsKey(id)) {
T value = (T) properties.get(id);
PropertyDefinition<T> pd = (PropertyDefinition<T>) getType().getPropertyDefinitions().get(
id);
List<T> values;
if (value == null) {
values = Collections.emptyList();
} else if (value instanceof List<?>) {
values = (List<T>) value;
} else {
values = Collections.singletonList((T) value);
}
return new PropertyImpl<T>(pd, values);
}
return object.getProperty(id);
}
@Override
public List<Property<?>> getProperties() {
List<Property<?>> list = new ArrayList<Property<?>>();
Set<String> todo = new HashSet<String>(properties.keySet());
for (Property<?> p : object.getProperties()) {
String id = p.getId();
// updated properties take precedence
if (properties.containsKey(id)) {
p = getProperty(id);
todo.remove(id);
}
list.add(p);
}
// other updated properties not already on the object
for (String id : todo) {
list.add(getProperty(id));
}
return list;
}
@Override
public void setPropertyValue(String id, Object value) {
PropertyDefinition<?> pd = getType().getPropertyDefinitions().get(id);
if (pd == null) {
throw new CmisInvalidArgumentException("Unknown property: " + id);
}
if (pd.getUpdatability() == Updatability.READONLY) {
throw new CmisInvalidArgumentException("Property is read-only: "
+ id);
}
NuxeoPropertyData.validateCMISValue(value, pd);
properties.put(id, value);
}
@Override
public boolean isMarkedForDelete() {
return markedForDeleteAllVersions != null;
}
@Override
public boolean isModified() {
return markedForDeleteAllVersions != null || !properties.isEmpty();
}
protected boolean saveDeletes() {
if (markedForDeleteAllVersions != null) {
object.service.deleteObject(object.getRepositoryId(), getId(),
markedForDeleteAllVersions, null);
return true;
} else {
return false;
}
}
@Override
public ObjectId save() {
if (saveDeletes()) {
reset();
return null;
}
object.updateProperties(properties);
reset();
return this;
}
@Override
public void reset() {
properties.clear();
markedForDeleteAllVersions = null;
}
@Override
public void refreshAndReset() {
object.refresh();
reset();
}
}