You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by sk...@apache.org on 2010/04/23 12:38:11 UTC

svn commit: r937238 [1/2] - in /incubator/chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/ chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/j...

Author: sklevenz
Date: Fri Apr 23 10:38:11 2010
New Revision: 937238

URL: http://svn.apache.org/viewvc?rev=937238&view=rev
Log:
fix code format issue

Modified:
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractPersistentCmisObject.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/PersistentFolderImpl.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/PersistentSessionImpl.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/java/org/apache/chemistry/opencmis/client/runtime/PagingListTest.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/WriteObjectRelationIT.java
    incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/WriteObjectVersionIT.java

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractPersistentCmisObject.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractPersistentCmisObject.java?rev=937238&r1=937237&r2=937238&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractPersistentCmisObject.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractPersistentCmisObject.java Fri Apr 23 10:38:11 2010
@@ -63,868 +63,868 @@ import org.apache.chemistry.opencmis.com
  */
 public abstract class AbstractPersistentCmisObject implements CmisObject {
 
-	private PersistentSessionImpl session;
-	private ObjectType objectType;
-	private Map<String, Property<?>> properties;
-	private AllowableActions allowableActions;
-	private List<Rendition> renditions;
-	private Acl acl;
-	private List<Policy> policies;
-	private List<Relationship> relationships;
-	private OperationContext creationContext;
-	private boolean isChanged = false;
-	private long refreshTimestamp;
-
-	private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock();
-
-	/**
-	 * Initializes the object.
-	 */
-	protected void initialize(PersistentSessionImpl session, ObjectType objectType, ObjectData objectData,
-			OperationContext context) {
-		if (session == null) {
-			throw new IllegalArgumentException("Session must be set!");
-		}
-
-		if (objectType == null) {
-			throw new IllegalArgumentException("Object type must be set!");
-		}
-
-		if (objectType.getPropertyDefinitions().size() < 9) {
-			// there must be at least the 9 standard properties that all objects
-			// have
-			throw new IllegalArgumentException("Object type must have property defintions!");
-		}
-
-		this.session = session;
-		this.objectType = objectType;
-		this.creationContext = new OperationContextImpl(context);
-		this.refreshTimestamp = System.currentTimeMillis();
-
-		ObjectFactory of = getObjectFactory();
-
-		if (objectData != null) {
-			// handle properties
-			if (objectData.getProperties() != null) {
-				this.properties = of.convertProperties(objectType, objectData.getProperties());
-			}
-
-			// handle allowable actions
-			if (objectData.getAllowableActions() != null) {
-				this.allowableActions = objectData.getAllowableActions();
-			}
-
-			// handle renditions
-			if (objectData.getRenditions() != null) {
-				this.renditions = new ArrayList<Rendition>();
-				for (RenditionData rd : objectData.getRenditions()) {
-					this.renditions.add(of.convertRendition(getId(), rd));
-				}
-			}
-
-			// handle ACL
-			if (objectData.getAcl() != null) {
-				acl = objectData.getAcl();
-			}
-
-			// handle policies
-			if ((objectData.getPolicyIds() != null) && (objectData.getPolicyIds().getPolicyIds() != null)) {
-				policies = new ArrayList<Policy>();
-				for (String pid : objectData.getPolicyIds().getPolicyIds()) {
-					CmisObject policy = session.getObject(getSession().createObjectId(pid));
-					if (policy instanceof Policy) {
-						policies.add((Policy) policy);
-					}
-				}
-			}
-
-			// handle relationships
-			if (objectData.getRelationships() != null) {
-				relationships = new ArrayList<Relationship>();
-				for (ObjectData rod : objectData.getRelationships()) {
-					CmisObject relationship = of.convertObject(rod, this.creationContext);
-					if (relationship instanceof Relationship) {
-						relationships.add((Relationship) relationship);
-					}
-				}
-			}
-		}
-
-		isChanged = false;
-	}
-
-	/**
-	 * Acquires a write lock.
-	 */
-	protected void writeLock() {
-		fLock.writeLock().lock();
-	}
-
-	/**
-	 * Releases a write lock.
-	 */
-	protected void writeUnlock() {
-		fLock.writeLock().unlock();
-	}
-
-	/**
-	 * Acquires a read lock.
-	 */
-	protected void readLock() {
-		fLock.readLock().lock();
-	}
-
-	/**
-	 * Releases a read lock.
-	 */
-	protected void readUnlock() {
-		fLock.readLock().unlock();
-	}
-
-	/**
-	 * Returns the session object.
-	 */
-	protected PersistentSessionImpl getSession() {
-		return this.session;
-	}
-
-	/**
-	 * Returns the repository id.
-	 */
-	protected String getRepositoryId() {
-		return getSession().getRepositoryId();
-	}
-
-	/**
-	 * Returns the object type.
-	 */
-	protected ObjectType getObjectType() {
-		readLock();
-		try {
-			return this.objectType;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/**
-	 * Returns the binding object.
-	 */
-	protected CmisBinding getBinding() {
-		return getSession().getBinding();
-	}
-
-	/**
-	 * Returns the object factory.
-	 */
-	protected ObjectFactory getObjectFactory() {
-		return getSession().getObjectFactory();
-	}
-
-	/**
-	 * Returns the id of this object or throws an exception if the id is
-	 * unknown.
-	 */
-	protected String getObjectId() {
-		String objectId = getId();
-		if (objectId == null) {
-			throw new IllegalStateException("Object Id is unknown!");
-		}
-
-		return objectId;
-	}
-
-	// --- operations ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#delete(boolean)
-	 */
-	public void delete(boolean allVersions) {
-		String objectId = getObjectId();
-		getBinding().getObjectService().deleteObject(getRepositoryId(), objectId, allVersions, null);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#updateProperties()
-	 */
-	public ObjectId updateProperties() {
-		readLock();
-		try {
-			String objectId = getObjectId();
-			Holder<String> objectIdHolder = new Holder<String>(objectId);
-
-			String changeToken = getChangeToken();
-			Holder<String> changeTokenHolder = new Holder<String>(changeToken);
-
-			Set<Updatability> updatebility = new HashSet<Updatability>();
-			updatebility.add(Updatability.READWRITE);
-
-			// check if checked out
-			Boolean isCheckedOut = getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
-			if ((isCheckedOut != null) && isCheckedOut.booleanValue()) {
-				updatebility.add(Updatability.WHENCHECKEDOUT);
-			}
-
-			// it's time to update
-			getBinding().getObjectService().updateProperties(getRepositoryId(), objectIdHolder, changeTokenHolder,
-					getObjectFactory().convertProperties(this.properties, this.objectType, updatebility), null);
-
-			if (objectIdHolder.getValue() == null) {
-				return null;
-			}
-
-			return getSession().createObjectId(objectIdHolder.getValue());
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#updateProperties(java.util.Map)
-	 */
-	public ObjectId updateProperties(Map<String, ?> properties) {
-		if ((properties == null) || (properties.isEmpty())) {
-			throw new IllegalArgumentException("Properties must not be empty!");
-		}
-
-		readLock();
-		try {
-			String objectId = getObjectId();
-			Holder<String> objectIdHolder = new Holder<String>(objectId);
-
-			String changeToken = getChangeToken();
-			Holder<String> changeTokenHolder = new Holder<String>(changeToken);
-
-			Set<Updatability> updatebility = new HashSet<Updatability>();
-			updatebility.add(Updatability.READWRITE);
-
-			// check if checked out
-			Boolean isCheckedOut = getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
-			if ((isCheckedOut != null) && isCheckedOut.booleanValue()) {
-				updatebility.add(Updatability.WHENCHECKEDOUT);
-			}
-
-			// it's time to update
-			getBinding().getObjectService().updateProperties(getRepositoryId(), objectIdHolder, changeTokenHolder,
-					getObjectFactory().convertProperties(properties, this.objectType, updatebility), null);
-
-			if (objectIdHolder.getValue() == null) {
-				return null;
-			}
-
-			return getSession().createObjectId(objectIdHolder.getValue());
-		} finally {
-			readUnlock();
-		}
-	}
-
-	// --- properties ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getBaseType()
-	 */
-	public ObjectType getBaseType() {
-		BaseTypeId baseTypeId = getBaseTypeId();
-		if (baseTypeId == null) {
-			return null;
-		}
-
-		return getSession().getTypeDefinition(baseTypeId.value());
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getBaseTypeId()
-	 */
-	public BaseTypeId getBaseTypeId() {
-		String baseType = getPropertyValue(PropertyIds.BASE_TYPE_ID);
-		if (baseType == null) {
-			return null;
-		}
-
-		return BaseTypeId.fromValue(baseType);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getChangeToken()
-	 */
-	public String getChangeToken() {
-		return getPropertyValue(PropertyIds.CHANGE_TOKEN);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getCreatedBy()
-	 */
-	public String getCreatedBy() {
-		return getPropertyValue(PropertyIds.CREATED_BY);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getCreationDate()
-	 */
-	public GregorianCalendar getCreationDate() {
-		return getPropertyValue(PropertyIds.CREATION_DATE);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getId()
-	 */
-	public String getId() {
-		return getPropertyValue(PropertyIds.OBJECT_ID);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getLastModificationDate()
-	 */
-	public GregorianCalendar getLastModificationDate() {
-		return getPropertyValue(PropertyIds.LAST_MODIFICATION_DATE);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getLastModifiedBy()
-	 */
-	public String getLastModifiedBy() {
-		return getPropertyValue(PropertyIds.LAST_MODIFIED_BY);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getName()
-	 */
-	public String getName() {
-		return getPropertyValue(PropertyIds.NAME);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getProperties()
-	 */
-	public List<Property<?>> getProperties() {
-		readLock();
-		try {
-			return new ArrayList<Property<?>>(this.properties.values());
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#getProperty(java.lang.String)
-	 */
-	@SuppressWarnings("unchecked")
-	public <T> Property<T> getProperty(String id) {
-		readLock();
-		try {
-			return (Property<T>) this.properties.get(id);
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#getPropertyMultivalue(java.
-	 * lang.String)
-	 */
-	public <T> List<T> getPropertyMultivalue(String id) {
-		Property<T> property = getProperty(id);
-		if (property == null) {
-			return null;
-		}
-
-		return property.getValues();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#getPropertyValue(java.lang.
-	 * String)
-	 */
-	public <T> T getPropertyValue(String id) {
-		Property<T> property = getProperty(id);
-		if (property == null) {
-			return null;
-		}
-
-		return property.getFirstValue();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#setName(java.lang.String)
-	 */
-	public void setName(String name) {
-		setProperty(PropertyIds.NAME, name);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#setProperty(java.lang.String,
-	 * java.lang.Object)
-	 */
-	@SuppressWarnings("unchecked")
-	public <T> void setProperty(String id, T value) {
-		PropertyDefinition<?> propertyDefinition = checkProperty(id, value);
-
-		// check updatability
-		if (propertyDefinition.getUpdatability() == Updatability.READONLY) {
-			throw new IllegalArgumentException("Property is read-only!");
-		}
-
-		// create property
-		Property<T> newProperty = (Property<T>) getObjectFactory().createProperty(
-				(PropertyDefinition<T>) propertyDefinition, value);
-
-		writeLock();
-		try {
-			setChanged();
-			this.properties.put(id, newProperty);
-		} finally {
-			writeUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#setPropertyMultivalue(java.
-	 * lang.String, java.util.List)
-	 */
-	@SuppressWarnings("unchecked")
-	public <T> void setPropertyMultivalue(String id, List<T> value) {
-		PropertyDefinition<?> propertyDefinition = checkProperty(id, value);
-
-		// check updatability
-		if (propertyDefinition.getUpdatability() == Updatability.READONLY) {
-			throw new IllegalArgumentException("Property is read-only!");
-		}
-
-		// create property
-		Property<T> newProperty = (Property<T>) getObjectFactory().createPropertyMultivalue(
-				(PropertyDefinition<T>) propertyDefinition, value);
-
-		writeLock();
-		try {
-			setChanged();
-			this.properties.put(id, newProperty);
-		} finally {
-			writeUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getType()
-	 */
-	public ObjectType getType() {
-		readLock();
-		try {
-			return this.objectType;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	// --- allowable actions ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getAllowableActions()
-	 */
-	public AllowableActions getAllowableActions() {
-		readLock();
-		try {
-			return this.allowableActions;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	// --- renditions ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getRenditions()
-	 */
-	public List<Rendition> getRenditions() {
-		readLock();
-		try {
-			return this.renditions;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	// --- ACL ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getAcl(boolean)
-	 */
-	public Acl getAcl(boolean onlyBasicPermissions) {
-		String objectId = getObjectId();
-		return getBinding().getAclService().getAcl(getRepositoryId(), objectId, onlyBasicPermissions, null);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#applyAcl(java.util.List,
-	 * java.util.List, org.apache.opencmis.commons.enums.AclPropagation)
-	 */
-	public Acl applyAcl(List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation) {
-		String objectId = getObjectId();
-
-		ObjectFactory of = getObjectFactory();
-
-		return getBinding().getAclService().applyAcl(getRepositoryId(), objectId, of.convertAces(addAces),
-				of.convertAces(removeAces), aclPropagation, null);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#addAcl(java.util.List,
-	 * org.apache.opencmis.commons.enums.AclPropagation)
-	 */
-	public void addAcl(List<Ace> addAces, AclPropagation aclPropagation) {
-		applyAcl(addAces, null, aclPropagation);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#removeAcl(java.util.List,
-	 * org.apache.opencmis.commons.enums.AclPropagation)
-	 */
-	public void removeAcl(List<Ace> removeAces, AclPropagation aclPropagation) {
-		applyAcl(null, removeAces, aclPropagation);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getAcl()
-	 */
-	public Acl getAcl() {
-		readLock();
-		try {
-			return this.acl;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	// --- policies ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#applyPolicy(org.apache.opencmis
-	 * .client.api.ObjectId)
-	 */
-	public void applyPolicy(ObjectId policyId) {
-		if ((policyId == null) || (policyId.getId() == null)) {
-			throw new IllegalArgumentException("Policy Id is not set!");
-		}
-
-		String objectId = getObjectId();
-		getBinding().getPolicyService().applyPolicy(getRepositoryId(), policyId.getId(), objectId, null);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#removePolicy(org.apache.opencmis
-	 * .client.api.ObjectId)
-	 */
-	public void removePolicy(ObjectId policyId) {
-		if ((policyId == null) || (policyId.getId() == null)) {
-			throw new IllegalArgumentException("Policy Id is not set!");
-		}
-
-		String objectId = getObjectId();
-		getBinding().getPolicyService().removePolicy(getRepositoryId(), policyId.getId(), objectId, null);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getPolicies()
-	 */
-	public List<Policy> getPolicies() {
-		readLock();
-		try {
-			return this.policies;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	// --- relationships ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getRelationships()
-	 */
-	public List<Relationship> getRelationships() {
-		readLock();
-		try {
-			return this.relationships;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getRelationships(boolean,
-	 * org.apache.opencmis.commons.enums.RelationshipDirection,
-	 * org.apache.opencmis.client.api.objecttype.ObjectType,
-	 * org.apache.opencmis.client.api.OperationContext, int)
-	 */
-	public PagingIterable<Relationship> getRelationships(final boolean includeSubRelationshipTypes,
-			final RelationshipDirection relationshipDirection, ObjectType type, OperationContext context,
-			final int itemsPerPage) {
-		if (itemsPerPage < 1) {
-			throw new IllegalArgumentException("itemsPerPage must be > 0!");
-		}
-
-		final String objectId = getObjectId();
-		final String typeId = (type == null ? null : type.getId());
-		final RelationshipService relationshipService = getBinding().getRelationshipService();
-		final OperationContext ctxt = new OperationContextImpl(context);
-
-		return new DefaultPagingIterable<Relationship>(new AbstractPageFetch<Relationship>() {
-
-			@Override
-			protected AbstractPageFetch.PageFetchResult<Relationship> fetchPage(long skipCount) {
-
-				// fetch the relationships
-				ObjectList relList = relationshipService.getObjectRelationships(getRepositoryId(), objectId,
-						includeSubRelationshipTypes, relationshipDirection, typeId, ctxt.getFilterString(), ctxt
-								.isIncludeAllowableActions(), BigInteger.valueOf(itemsPerPage), BigInteger
-								.valueOf(skipCount), null);
-
-				// convert relationship objects
-				List<Relationship> page = new ArrayList<Relationship>();
-				if (relList.getObjects() != null) {
-					for (ObjectData rod : relList.getObjects()) {
-						Relationship relationship = new PersistentRelationshipImpl(getSession(), getObjectFactory()
-								.getTypeFromObjectData(rod), rod, ctxt);
-
-						page.add(relationship);
-					}
-				}
-
-				return new AbstractPageFetch.PageFetchResult<Relationship>(page, relList.getNumItems(), relList
-						.hasMoreItems()) {
-				};
-			}
-		});
-	}
-
-	// --- other ---
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#isChanged()
-	 */
-	public boolean isChanged() {
-		readLock();
-		try {
-			return isChanged;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/**
-	 * Sets the isChanged flag to <code>true</code>
-	 */
-	protected void setChanged() {
-		writeLock();
-		try {
-			isChanged = true;
-		} finally {
-			writeUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#getRefreshTimestamp()
-	 */
-	public long getRefreshTimestamp() {
-		readLock();
-		try {
-			return this.refreshTimestamp;
-		} finally {
-			readUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.CmisObject#refresh(org.apache.opencmis
-	 * .client.api.OperationContext )
-	 */
-	public void refresh() {
-		writeLock();
-		try {
-			String objectId = getObjectId();
-
-			// get the latest data from the repository
-			ObjectData objectData = getSession().getBinding().getObjectService().getObject(getRepositoryId(), objectId,
-					creationContext.getFilterString(), creationContext.isIncludeAllowableActions(),
-					creationContext.getIncludeRelationships(), creationContext.getRenditionFilterString(),
-					creationContext.isIncludePolicies(), creationContext.isIncludeAcls(), null);
-
-			// reset this object
-			initialize(getSession(), getObjectType(), objectData, this.creationContext);
-		} finally {
-			writeUnlock();
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.CmisObject#refreshIfOld(long)
-	 */
-	public void refreshIfOld(long durationInMillis) {
-		writeLock();
-		try {
-			if (this.refreshTimestamp < System.currentTimeMillis() - durationInMillis) {
-				refresh();
-			}
-		} finally {
-			writeUnlock();
-		}
-	}
-
-	// --- internal ---
-
-	/**
-	 * Checks if a value matches a property definition.
-	 */
-	private PropertyDefinition<?> checkProperty(String id, Object value) {
-		PropertyDefinition<?> propertyDefinition = getObjectType().getPropertyDefinitions().get(id);
-		if (propertyDefinition == null) {
-			throw new IllegalArgumentException("Unknown property '" + id + "'!");
-		}
-
-		// null values are ok for updates
-		if (value == null) {
-			return propertyDefinition;
-		}
-
-		// single and multi value check
-		List<?> values = null;
-		if (value instanceof List<?>) {
-			if (propertyDefinition.getCardinality() != Cardinality.MULTI) {
-				throw new IllegalArgumentException("Property '" + propertyDefinition.getId()
-						+ "' is not a multi value property!");
-			}
-
-			values = (List<?>) value;
-			if (values.isEmpty()) {
-				return propertyDefinition;
-			}
-		} else {
-			if (propertyDefinition.getCardinality() != Cardinality.SINGLE) {
-				throw new IllegalArgumentException("Property '" + propertyDefinition.getId()
-						+ "' is not a single value property!");
-			}
-
-			values = Collections.singletonList(value);
-		}
-
-		// check if list contains null values
-		for (Object o : values) {
-			if (o == null) {
-				throw new IllegalArgumentException("Property '" + propertyDefinition.getId()
-						+ "' contains null values!");
-			}
-		}
-
-		// take a sample and test the data type
-		boolean typeMatch = false;
-		Object firstValue = values.get(0);
-
-		switch (propertyDefinition.getPropertyType()) {
-		case STRING:
-		case ID:
-		case URI:
-		case HTML:
-			typeMatch = (firstValue instanceof String);
-			break;
-		case INTEGER:
-			typeMatch = (firstValue instanceof BigInteger);
-			break;
-		case DECIMAL:
-			typeMatch = (firstValue instanceof BigDecimal);
-			break;
-		case BOOLEAN:
-			typeMatch = (firstValue instanceof Boolean);
-			break;
-		case DATETIME:
-			typeMatch = (firstValue instanceof GregorianCalendar);
-			break;
-		}
-
-		if (!typeMatch) {
-			throw new IllegalArgumentException("Value of property '" + propertyDefinition.getId()
-					+ "' does not match property type!");
-		}
+    private PersistentSessionImpl session;
+    private ObjectType objectType;
+    private Map<String, Property<?>> properties;
+    private AllowableActions allowableActions;
+    private List<Rendition> renditions;
+    private Acl acl;
+    private List<Policy> policies;
+    private List<Relationship> relationships;
+    private OperationContext creationContext;
+    private boolean isChanged = false;
+    private long refreshTimestamp;
+
+    private final ReentrantReadWriteLock fLock = new ReentrantReadWriteLock();
+
+    /**
+     * Initializes the object.
+     */
+    protected void initialize(PersistentSessionImpl session, ObjectType objectType, ObjectData objectData,
+            OperationContext context) {
+        if (session == null) {
+            throw new IllegalArgumentException("Session must be set!");
+        }
+
+        if (objectType == null) {
+            throw new IllegalArgumentException("Object type must be set!");
+        }
+
+        if (objectType.getPropertyDefinitions().size() < 9) {
+            // there must be at least the 9 standard properties that all objects
+            // have
+            throw new IllegalArgumentException("Object type must have property defintions!");
+        }
+
+        this.session = session;
+        this.objectType = objectType;
+        this.creationContext = new OperationContextImpl(context);
+        this.refreshTimestamp = System.currentTimeMillis();
+
+        ObjectFactory of = getObjectFactory();
+
+        if (objectData != null) {
+            // handle properties
+            if (objectData.getProperties() != null) {
+                this.properties = of.convertProperties(objectType, objectData.getProperties());
+            }
+
+            // handle allowable actions
+            if (objectData.getAllowableActions() != null) {
+                this.allowableActions = objectData.getAllowableActions();
+            }
+
+            // handle renditions
+            if (objectData.getRenditions() != null) {
+                this.renditions = new ArrayList<Rendition>();
+                for (RenditionData rd : objectData.getRenditions()) {
+                    this.renditions.add(of.convertRendition(getId(), rd));
+                }
+            }
+
+            // handle ACL
+            if (objectData.getAcl() != null) {
+                acl = objectData.getAcl();
+            }
+
+            // handle policies
+            if ((objectData.getPolicyIds() != null) && (objectData.getPolicyIds().getPolicyIds() != null)) {
+                policies = new ArrayList<Policy>();
+                for (String pid : objectData.getPolicyIds().getPolicyIds()) {
+                    CmisObject policy = session.getObject(getSession().createObjectId(pid));
+                    if (policy instanceof Policy) {
+                        policies.add((Policy) policy);
+                    }
+                }
+            }
+
+            // handle relationships
+            if (objectData.getRelationships() != null) {
+                relationships = new ArrayList<Relationship>();
+                for (ObjectData rod : objectData.getRelationships()) {
+                    CmisObject relationship = of.convertObject(rod, this.creationContext);
+                    if (relationship instanceof Relationship) {
+                        relationships.add((Relationship) relationship);
+                    }
+                }
+            }
+        }
+
+        isChanged = false;
+    }
+
+    /**
+     * Acquires a write lock.
+     */
+    protected void writeLock() {
+        fLock.writeLock().lock();
+    }
+
+    /**
+     * Releases a write lock.
+     */
+    protected void writeUnlock() {
+        fLock.writeLock().unlock();
+    }
+
+    /**
+     * Acquires a read lock.
+     */
+    protected void readLock() {
+        fLock.readLock().lock();
+    }
+
+    /**
+     * Releases a read lock.
+     */
+    protected void readUnlock() {
+        fLock.readLock().unlock();
+    }
+
+    /**
+     * Returns the session object.
+     */
+    protected PersistentSessionImpl getSession() {
+        return this.session;
+    }
+
+    /**
+     * Returns the repository id.
+     */
+    protected String getRepositoryId() {
+        return getSession().getRepositoryId();
+    }
+
+    /**
+     * Returns the object type.
+     */
+    protected ObjectType getObjectType() {
+        readLock();
+        try {
+            return this.objectType;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /**
+     * Returns the binding object.
+     */
+    protected CmisBinding getBinding() {
+        return getSession().getBinding();
+    }
+
+    /**
+     * Returns the object factory.
+     */
+    protected ObjectFactory getObjectFactory() {
+        return getSession().getObjectFactory();
+    }
+
+    /**
+     * Returns the id of this object or throws an exception if the id is
+     * unknown.
+     */
+    protected String getObjectId() {
+        String objectId = getId();
+        if (objectId == null) {
+            throw new IllegalStateException("Object Id is unknown!");
+        }
+
+        return objectId;
+    }
+
+    // --- operations ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#delete(boolean)
+     */
+    public void delete(boolean allVersions) {
+        String objectId = getObjectId();
+        getBinding().getObjectService().deleteObject(getRepositoryId(), objectId, allVersions, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#updateProperties()
+     */
+    public ObjectId updateProperties() {
+        readLock();
+        try {
+            String objectId = getObjectId();
+            Holder<String> objectIdHolder = new Holder<String>(objectId);
+
+            String changeToken = getChangeToken();
+            Holder<String> changeTokenHolder = new Holder<String>(changeToken);
+
+            Set<Updatability> updatebility = new HashSet<Updatability>();
+            updatebility.add(Updatability.READWRITE);
+
+            // check if checked out
+            Boolean isCheckedOut = getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
+            if ((isCheckedOut != null) && isCheckedOut.booleanValue()) {
+                updatebility.add(Updatability.WHENCHECKEDOUT);
+            }
+
+            // it's time to update
+            getBinding().getObjectService().updateProperties(getRepositoryId(), objectIdHolder, changeTokenHolder,
+                    getObjectFactory().convertProperties(this.properties, this.objectType, updatebility), null);
+
+            if (objectIdHolder.getValue() == null) {
+                return null;
+            }
+
+            return getSession().createObjectId(objectIdHolder.getValue());
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#updateProperties(java.util.Map)
+     */
+    public ObjectId updateProperties(Map<String, ?> properties) {
+        if ((properties == null) || (properties.isEmpty())) {
+            throw new IllegalArgumentException("Properties must not be empty!");
+        }
+
+        readLock();
+        try {
+            String objectId = getObjectId();
+            Holder<String> objectIdHolder = new Holder<String>(objectId);
+
+            String changeToken = getChangeToken();
+            Holder<String> changeTokenHolder = new Holder<String>(changeToken);
+
+            Set<Updatability> updatebility = new HashSet<Updatability>();
+            updatebility.add(Updatability.READWRITE);
+
+            // check if checked out
+            Boolean isCheckedOut = getPropertyValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT);
+            if ((isCheckedOut != null) && isCheckedOut.booleanValue()) {
+                updatebility.add(Updatability.WHENCHECKEDOUT);
+            }
+
+            // it's time to update
+            getBinding().getObjectService().updateProperties(getRepositoryId(), objectIdHolder, changeTokenHolder,
+                    getObjectFactory().convertProperties(properties, this.objectType, updatebility), null);
+
+            if (objectIdHolder.getValue() == null) {
+                return null;
+            }
+
+            return getSession().createObjectId(objectIdHolder.getValue());
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // --- properties ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getBaseType()
+     */
+    public ObjectType getBaseType() {
+        BaseTypeId baseTypeId = getBaseTypeId();
+        if (baseTypeId == null) {
+            return null;
+        }
+
+        return getSession().getTypeDefinition(baseTypeId.value());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getBaseTypeId()
+     */
+    public BaseTypeId getBaseTypeId() {
+        String baseType = getPropertyValue(PropertyIds.BASE_TYPE_ID);
+        if (baseType == null) {
+            return null;
+        }
+
+        return BaseTypeId.fromValue(baseType);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getChangeToken()
+     */
+    public String getChangeToken() {
+        return getPropertyValue(PropertyIds.CHANGE_TOKEN);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getCreatedBy()
+     */
+    public String getCreatedBy() {
+        return getPropertyValue(PropertyIds.CREATED_BY);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getCreationDate()
+     */
+    public GregorianCalendar getCreationDate() {
+        return getPropertyValue(PropertyIds.CREATION_DATE);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getId()
+     */
+    public String getId() {
+        return getPropertyValue(PropertyIds.OBJECT_ID);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getLastModificationDate()
+     */
+    public GregorianCalendar getLastModificationDate() {
+        return getPropertyValue(PropertyIds.LAST_MODIFICATION_DATE);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getLastModifiedBy()
+     */
+    public String getLastModifiedBy() {
+        return getPropertyValue(PropertyIds.LAST_MODIFIED_BY);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getName()
+     */
+    public String getName() {
+        return getPropertyValue(PropertyIds.NAME);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getProperties()
+     */
+    public List<Property<?>> getProperties() {
+        readLock();
+        try {
+            return new ArrayList<Property<?>>(this.properties.values());
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#getProperty(java.lang.String)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> Property<T> getProperty(String id) {
+        readLock();
+        try {
+            return (Property<T>) this.properties.get(id);
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#getPropertyMultivalue(java.
+     * lang.String)
+     */
+    public <T> List<T> getPropertyMultivalue(String id) {
+        Property<T> property = getProperty(id);
+        if (property == null) {
+            return null;
+        }
+
+        return property.getValues();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#getPropertyValue(java.lang.
+     * String)
+     */
+    public <T> T getPropertyValue(String id) {
+        Property<T> property = getProperty(id);
+        if (property == null) {
+            return null;
+        }
+
+        return property.getFirstValue();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#setName(java.lang.String)
+     */
+    public void setName(String name) {
+        setProperty(PropertyIds.NAME, name);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#setProperty(java.lang.String,
+     * java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> void setProperty(String id, T value) {
+        PropertyDefinition<?> propertyDefinition = checkProperty(id, value);
+
+        // check updatability
+        if (propertyDefinition.getUpdatability() == Updatability.READONLY) {
+            throw new IllegalArgumentException("Property is read-only!");
+        }
+
+        // create property
+        Property<T> newProperty = (Property<T>) getObjectFactory().createProperty(
+                (PropertyDefinition<T>) propertyDefinition, value);
+
+        writeLock();
+        try {
+            setChanged();
+            this.properties.put(id, newProperty);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#setPropertyMultivalue(java.
+     * lang.String, java.util.List)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> void setPropertyMultivalue(String id, List<T> value) {
+        PropertyDefinition<?> propertyDefinition = checkProperty(id, value);
+
+        // check updatability
+        if (propertyDefinition.getUpdatability() == Updatability.READONLY) {
+            throw new IllegalArgumentException("Property is read-only!");
+        }
+
+        // create property
+        Property<T> newProperty = (Property<T>) getObjectFactory().createPropertyMultivalue(
+                (PropertyDefinition<T>) propertyDefinition, value);
+
+        writeLock();
+        try {
+            setChanged();
+            this.properties.put(id, newProperty);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getType()
+     */
+    public ObjectType getType() {
+        readLock();
+        try {
+            return this.objectType;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // --- allowable actions ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getAllowableActions()
+     */
+    public AllowableActions getAllowableActions() {
+        readLock();
+        try {
+            return this.allowableActions;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // --- renditions ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getRenditions()
+     */
+    public List<Rendition> getRenditions() {
+        readLock();
+        try {
+            return this.renditions;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // --- ACL ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getAcl(boolean)
+     */
+    public Acl getAcl(boolean onlyBasicPermissions) {
+        String objectId = getObjectId();
+        return getBinding().getAclService().getAcl(getRepositoryId(), objectId, onlyBasicPermissions, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#applyAcl(java.util.List,
+     * java.util.List, org.apache.opencmis.commons.enums.AclPropagation)
+     */
+    public Acl applyAcl(List<Ace> addAces, List<Ace> removeAces, AclPropagation aclPropagation) {
+        String objectId = getObjectId();
+
+        ObjectFactory of = getObjectFactory();
+
+        return getBinding().getAclService().applyAcl(getRepositoryId(), objectId, of.convertAces(addAces),
+                of.convertAces(removeAces), aclPropagation, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#addAcl(java.util.List,
+     * org.apache.opencmis.commons.enums.AclPropagation)
+     */
+    public void addAcl(List<Ace> addAces, AclPropagation aclPropagation) {
+        applyAcl(addAces, null, aclPropagation);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#removeAcl(java.util.List,
+     * org.apache.opencmis.commons.enums.AclPropagation)
+     */
+    public void removeAcl(List<Ace> removeAces, AclPropagation aclPropagation) {
+        applyAcl(null, removeAces, aclPropagation);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getAcl()
+     */
+    public Acl getAcl() {
+        readLock();
+        try {
+            return this.acl;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // --- policies ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#applyPolicy(org.apache.opencmis
+     * .client.api.ObjectId)
+     */
+    public void applyPolicy(ObjectId policyId) {
+        if ((policyId == null) || (policyId.getId() == null)) {
+            throw new IllegalArgumentException("Policy Id is not set!");
+        }
+
+        String objectId = getObjectId();
+        getBinding().getPolicyService().applyPolicy(getRepositoryId(), policyId.getId(), objectId, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#removePolicy(org.apache.opencmis
+     * .client.api.ObjectId)
+     */
+    public void removePolicy(ObjectId policyId) {
+        if ((policyId == null) || (policyId.getId() == null)) {
+            throw new IllegalArgumentException("Policy Id is not set!");
+        }
+
+        String objectId = getObjectId();
+        getBinding().getPolicyService().removePolicy(getRepositoryId(), policyId.getId(), objectId, null);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getPolicies()
+     */
+    public List<Policy> getPolicies() {
+        readLock();
+        try {
+            return this.policies;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    // --- relationships ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getRelationships()
+     */
+    public List<Relationship> getRelationships() {
+        readLock();
+        try {
+            return this.relationships;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getRelationships(boolean,
+     * org.apache.opencmis.commons.enums.RelationshipDirection,
+     * org.apache.opencmis.client.api.objecttype.ObjectType,
+     * org.apache.opencmis.client.api.OperationContext, int)
+     */
+    public PagingIterable<Relationship> getRelationships(final boolean includeSubRelationshipTypes,
+            final RelationshipDirection relationshipDirection, ObjectType type, OperationContext context,
+            final int itemsPerPage) {
+        if (itemsPerPage < 1) {
+            throw new IllegalArgumentException("itemsPerPage must be > 0!");
+        }
+
+        final String objectId = getObjectId();
+        final String typeId = (type == null ? null : type.getId());
+        final RelationshipService relationshipService = getBinding().getRelationshipService();
+        final OperationContext ctxt = new OperationContextImpl(context);
+
+        return new DefaultPagingIterable<Relationship>(new AbstractPageFetch<Relationship>() {
+
+            @Override
+            protected AbstractPageFetch.PageFetchResult<Relationship> fetchPage(long skipCount) {
+
+                // fetch the relationships
+                ObjectList relList = relationshipService.getObjectRelationships(getRepositoryId(), objectId,
+                        includeSubRelationshipTypes, relationshipDirection, typeId, ctxt.getFilterString(), ctxt
+                                .isIncludeAllowableActions(), BigInteger.valueOf(itemsPerPage), BigInteger
+                                .valueOf(skipCount), null);
+
+                // convert relationship objects
+                List<Relationship> page = new ArrayList<Relationship>();
+                if (relList.getObjects() != null) {
+                    for (ObjectData rod : relList.getObjects()) {
+                        Relationship relationship = new PersistentRelationshipImpl(getSession(), getObjectFactory()
+                                .getTypeFromObjectData(rod), rod, ctxt);
+
+                        page.add(relationship);
+                    }
+                }
+
+                return new AbstractPageFetch.PageFetchResult<Relationship>(page, relList.getNumItems(), relList
+                        .hasMoreItems()) {
+                };
+            }
+        });
+    }
+
+    // --- other ---
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#isChanged()
+     */
+    public boolean isChanged() {
+        readLock();
+        try {
+            return isChanged;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /**
+     * Sets the isChanged flag to <code>true</code>
+     */
+    protected void setChanged() {
+        writeLock();
+        try {
+            isChanged = true;
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#getRefreshTimestamp()
+     */
+    public long getRefreshTimestamp() {
+        readLock();
+        try {
+            return this.refreshTimestamp;
+        } finally {
+            readUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.CmisObject#refresh(org.apache.opencmis
+     * .client.api.OperationContext )
+     */
+    public void refresh() {
+        writeLock();
+        try {
+            String objectId = getObjectId();
+
+            // get the latest data from the repository
+            ObjectData objectData = getSession().getBinding().getObjectService().getObject(getRepositoryId(), objectId,
+                    creationContext.getFilterString(), creationContext.isIncludeAllowableActions(),
+                    creationContext.getIncludeRelationships(), creationContext.getRenditionFilterString(),
+                    creationContext.isIncludePolicies(), creationContext.isIncludeAcls(), null);
+
+            // reset this object
+            initialize(getSession(), getObjectType(), objectData, this.creationContext);
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.CmisObject#refreshIfOld(long)
+     */
+    public void refreshIfOld(long durationInMillis) {
+        writeLock();
+        try {
+            if (this.refreshTimestamp < System.currentTimeMillis() - durationInMillis) {
+                refresh();
+            }
+        } finally {
+            writeUnlock();
+        }
+    }
+
+    // --- internal ---
+
+    /**
+     * Checks if a value matches a property definition.
+     */
+    private PropertyDefinition<?> checkProperty(String id, Object value) {
+        PropertyDefinition<?> propertyDefinition = getObjectType().getPropertyDefinitions().get(id);
+        if (propertyDefinition == null) {
+            throw new IllegalArgumentException("Unknown property '" + id + "'!");
+        }
+
+        // null values are ok for updates
+        if (value == null) {
+            return propertyDefinition;
+        }
+
+        // single and multi value check
+        List<?> values = null;
+        if (value instanceof List<?>) {
+            if (propertyDefinition.getCardinality() != Cardinality.MULTI) {
+                throw new IllegalArgumentException("Property '" + propertyDefinition.getId()
+                        + "' is not a multi value property!");
+            }
+
+            values = (List<?>) value;
+            if (values.isEmpty()) {
+                return propertyDefinition;
+            }
+        } else {
+            if (propertyDefinition.getCardinality() != Cardinality.SINGLE) {
+                throw new IllegalArgumentException("Property '" + propertyDefinition.getId()
+                        + "' is not a single value property!");
+            }
+
+            values = Collections.singletonList(value);
+        }
+
+        // check if list contains null values
+        for (Object o : values) {
+            if (o == null) {
+                throw new IllegalArgumentException("Property '" + propertyDefinition.getId()
+                        + "' contains null values!");
+            }
+        }
+
+        // take a sample and test the data type
+        boolean typeMatch = false;
+        Object firstValue = values.get(0);
+
+        switch (propertyDefinition.getPropertyType()) {
+        case STRING:
+        case ID:
+        case URI:
+        case HTML:
+            typeMatch = (firstValue instanceof String);
+            break;
+        case INTEGER:
+            typeMatch = (firstValue instanceof BigInteger);
+            break;
+        case DECIMAL:
+            typeMatch = (firstValue instanceof BigDecimal);
+            break;
+        case BOOLEAN:
+            typeMatch = (firstValue instanceof Boolean);
+            break;
+        case DATETIME:
+            typeMatch = (firstValue instanceof GregorianCalendar);
+            break;
+        }
+
+        if (!typeMatch) {
+            throw new IllegalArgumentException("Value of property '" + propertyDefinition.getId()
+                    + "' does not match property type!");
+        }
 
-		return propertyDefinition;
-	}
+        return propertyDefinition;
+    }
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/PersistentFolderImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/PersistentFolderImpl.java?rev=937238&r1=937237&r2=937238&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/PersistentFolderImpl.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/PersistentFolderImpl.java Fri Apr 23 10:38:11 2010
@@ -61,494 +61,494 @@ import org.apache.chemistry.opencmis.com
 
 public class PersistentFolderImpl extends AbstractPersistentFilableCmisObject implements Folder {
 
-	private static final Set<Updatability> CREATE_UPDATABILITY = new HashSet<Updatability>();
-	static {
-		CREATE_UPDATABILITY.add(Updatability.ONCREATE);
-		CREATE_UPDATABILITY.add(Updatability.READWRITE);
-	}
-
-	/**
-	 * Constructor.
-	 */
-	public PersistentFolderImpl(PersistentSessionImpl session, ObjectType objectType, ObjectData objectData,
-			OperationContext context) {
-		initialize(session, objectType, objectData, context);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#createDocument(java.util.Map,
-	 * org.apache.opencmis.client.api.ContentStream,
-	 * org.apache.opencmis.commons.enums.VersioningState, java.util.List,
-	 * java.util.List, java.util.List,
-	 * org.apache.opencmis.client.api.OperationContext)
-	 */
-	public Document createDocument(Map<String, ?> properties, ContentStream contentStream,
-			VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
-			OperationContext context) {
-		String objectId = getObjectId();
-
-		ObjectFactory of = getObjectFactory();
-
-		String newId = getBinding().getObjectService().createDocument(getRepositoryId(),
-				of.convertProperties(properties, null, CREATE_UPDATABILITY), objectId,
-				of.convertContentStream(contentStream), versioningState, of.convertPolicies(policies),
-				of.convertAces(addAces), of.convertAces(removeAces), null);
-
-		// if no context is provided the object will not be fetched
-		if ((context == null) || (newId == null)) {
-			return null;
-		}
-
-		// get the new object
-		CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
-		if (!(object instanceof Document)) {
-			throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
-		}
-
-		return (Document) object;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.Folder#createDocumentFromSource(org.apache
-	 * .opencmis.client.api .ObjectId, java.util.Map,
-	 * org.apache.opencmis.commons.enums.VersioningState, java.util.List,
-	 * java.util.List, java.util.List,
-	 * org.apache.opencmis.client.api.OperationContext)
-	 */
-	public Document createDocumentFromSource(ObjectId source, Map<String, ?> properties,
-			VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
-			OperationContext context) {
-		if ((source == null) || (source.getId() == null)) {
-			throw new IllegalArgumentException("Source must be set!");
-		}
-
-		String objectId = getObjectId();
-
-		// get the type of the source document
-		ObjectType type = null;
-		if (source instanceof CmisObject) {
-			type = ((CmisObject) source).getBaseType();
-		} else {
-			CmisObject sourceObj = getSession().getObject(source);
-			type = sourceObj.getType();
-		}
-
-		if (type.getBaseTypeId() != BaseTypeId.CMIS_DOCUMENT) {
-			throw new IllegalArgumentException("Source object must be a document!");
-		}
-
-		ObjectFactory of = getObjectFactory();
-
-		Set<Updatability> updatebility = new HashSet<Updatability>();
-		updatebility.add(Updatability.READWRITE);
-
-		String newId = getBinding().getObjectService().createDocumentFromSource(getRepositoryId(), source.getId(),
-				of.convertProperties(properties, type, updatebility), objectId, versioningState,
-				of.convertPolicies(policies), of.convertAces(addAces), of.convertAces(removeAces), null);
-
-		// if no context is provided the object will not be fetched
-		if ((context == null) || (newId == null)) {
-			return null;
-		}
-
-		// get the new object
-		CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
-		if (!(object instanceof Document)) {
-			throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
-		}
-
-		return (Document) object;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#createFolder(java.util.Map,
-	 * java.util.List, java.util.List, java.util.List,
-	 * org.apache.opencmis.client.api.OperationContext)
-	 */
-	public Folder createFolder(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
-			List<Ace> removeAces, OperationContext context) {
-		String objectId = getObjectId();
-
-		ObjectFactory of = getObjectFactory();
-
-		String newId = getBinding().getObjectService().createFolder(getRepositoryId(),
-				of.convertProperties(properties, null, CREATE_UPDATABILITY), objectId, of.convertPolicies(policies),
-				of.convertAces(addAces), of.convertAces(removeAces), null);
-
-		// if no context is provided the object will not be fetched
-		if ((context == null) || (newId == null)) {
-			return null;
-		}
-
-		// get the new object
-		CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
-		if (!(object instanceof Folder)) {
-			throw new CmisRuntimeException("Newly created object is not a folder! New id: " + newId);
-		}
-
-		return (Folder) object;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#createPolicy(java.util.Map,
-	 * java.util.List, java.util.List, java.util.List,
-	 * org.apache.opencmis.client.api.OperationContext)
-	 */
-	public Policy createPolicy(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
-			List<Ace> removeAces, OperationContext context) {
-		String objectId = getObjectId();
-
-		ObjectFactory of = getObjectFactory();
-
-		String newId = getBinding().getObjectService().createPolicy(getRepositoryId(),
-				of.convertProperties(properties, null, CREATE_UPDATABILITY), objectId, of.convertPolicies(policies),
-				of.convertAces(addAces), of.convertAces(removeAces), null);
-
-		// if no context is provided the object will not be fetched
-		if ((context == null) || (newId == null)) {
-			return null;
-		}
-
-		// get the new object
-		CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
-		if (!(object instanceof Policy)) {
-			throw new CmisRuntimeException("Newly created object is not a policy! New id: " + newId);
-		}
-
-		return (Policy) object;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#deleteTree(boolean,
-	 * org.apache.opencmis.commons.enums.UnfileObjects, boolean)
-	 */
-	public List<String> deleteTree(boolean allVersions, UnfileObject unfile, boolean continueOnFailure) {
-		String repositoryId = getRepositoryId();
-		String objectId = getObjectId();
-
-		FailedToDeleteData failed = getBinding().getObjectService().deleteTree(repositoryId, objectId, allVersions,
-				unfile, continueOnFailure, null);
-
-		return failed.getIds();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getAllowedChildObjectTypes()
-	 */
-	public List<ObjectType> getAllowedChildObjectTypes() {
-		List<ObjectType> result = new ArrayList<ObjectType>();
-
-		readLock();
-		try {
-			List<String> otids = getPropertyMultivalue(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS);
-			if (otids == null) {
-				return result;
-			}
-
-			for (String otid : otids) {
-				result.add(getSession().getTypeDefinition(otid));
-			}
-		} finally {
-			readUnlock();
-		}
-
-		return result;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getCheckedOutDocs(int)
-	 */
-	public PagingIterable<Document> getCheckedOutDocs(int itemsPerPage) {
-		return getCheckedOutDocs(getSession().getDefaultContext(), itemsPerPage);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @seeorg.apache.opencmis.client.api.Folder#getCheckedOutDocs(org.apache.
-	 * opencmis.client.api. OperationContext, int)
-	 */
-	public PagingIterable<Document> getCheckedOutDocs(OperationContext context, final int itemsPerPage) {
-		if (itemsPerPage < 1) {
-			throw new IllegalArgumentException("itemsPerPage must be > 0!");
-		}
-
-		final String objectId = getObjectId();
-		final NavigationService navigationService = getBinding().getNavigationService();
-		final ObjectFactory objectFactory = getSession().getObjectFactory();
-		final OperationContext ctxt = new OperationContextImpl(context);
-
-		return new DefaultPagingIterable<Document>(new AbstractPageFetch<Document>() {
-
-			@Override
-			protected AbstractPageFetch.PageFetchResult<Document> fetchPage(long skipCount) {
-
-				// get checked out documents for this folder
-				ObjectList checkedOutDocs = navigationService.getCheckedOutDocs(getRepositoryId(), objectId, ctxt
-						.getFilterString(), ctxt.getOrderBy(), ctxt.isIncludeAllowableActions(), ctxt
-						.getIncludeRelationships(), ctxt.getRenditionFilterString(), BigInteger.valueOf(itemsPerPage),
-						BigInteger.valueOf(skipCount), null);
-
-				// convert objects
-				List<Document> page = new ArrayList<Document>();
-				if (checkedOutDocs.getObjects() != null) {
-					for (ObjectData objectData : checkedOutDocs.getObjects()) {
-						CmisObject doc = objectFactory.convertObject(objectData, ctxt);
-						if (!(doc instanceof Document)) {
-							// should not happen...
-							continue;
-						}
-
-						page.add((Document) doc);
-					}
-				}
-
-				return new AbstractPageFetch.PageFetchResult<Document>(page, checkedOutDocs.getNumItems(),
-						checkedOutDocs.hasMoreItems()) {
-				};
-			}
-		});
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getChildren(int)
-	 */
-	public PagingIterable<CmisObject> getChildren(int itemsPerPage) {
-		return getChildren(getSession().getDefaultContext(), itemsPerPage);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.api.Folder#getChildren(org.apache.opencmis
-	 * .client.api.OperationContext , int)
-	 */
-	public PagingIterable<CmisObject> getChildren(OperationContext context, final int itemsPerPage) {
-
-		if (itemsPerPage < 1) {
-			throw new IllegalArgumentException("itemsPerPage must be > 0!");
-		}
-
-		final String objectId = getObjectId();
-		final NavigationService navigationService = getBinding().getNavigationService();
-		final ObjectFactory objectFactory = getSession().getObjectFactory();
-		final OperationContext ctxt = new OperationContextImpl(context);
-
-		return new DefaultPagingIterable<CmisObject>(new AbstractPageFetch<CmisObject>() {
-
-			@Override
-			protected AbstractPageFetch.PageFetchResult<CmisObject> fetchPage(long skipCount) {
-
-				// get the children
-				ObjectInFolderList children = navigationService.getChildren(getRepositoryId(), objectId, ctxt
-						.getFilterString(), ctxt.getOrderBy(), ctxt.isIncludeAllowableActions(), ctxt
-						.getIncludeRelationships(), ctxt.getRenditionFilterString(), ctxt.isIncludePathSegments(),
-						BigInteger.valueOf(itemsPerPage), BigInteger.valueOf(skipCount), null);
-
-				// convert objects
-				List<CmisObject> page = new ArrayList<CmisObject>();
-				List<ObjectInFolderData> childObjects = children.getObjects();
-				if (childObjects != null) {
-					for (ObjectInFolderData objectData : childObjects) {
-						if (objectData.getObject() != null) {
-							page.add(objectFactory.convertObject(objectData.getObject(), ctxt));
-						}
-					}
-				}
-
-				return new AbstractPageFetch.PageFetchResult<CmisObject>(page, children.getNumItems(), children
-						.hasMoreItems()) {
-				};
-			}
-		});
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getDescendants(int)
-	 */
-	public List<Tree<FileableCmisObject>> getDescendants(int depth) {
-		return getDescendants(depth, getSession().getDefaultContext());
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getDescendants(int,
-	 * org.apache.opencmis.client.api.OperationContext)
-	 */
-	public List<Tree<FileableCmisObject>> getDescendants(int depth, OperationContext context) {
-		String objectId = getObjectId();
-
-		// get the descendants
-		List<ObjectInFolderContainer> providerContainerList = getBinding().getNavigationService().getDescendants(
-				getRepositoryId(), objectId, BigInteger.valueOf(depth), context.getFilterString(),
-				context.isIncludeAllowableActions(), context.getIncludeRelationships(),
-				context.getRenditionFilterString(), context.isIncludePathSegments(), null);
-
-		return convertProviderContainer(providerContainerList, context);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getFolderTree(int)
-	 */
-	public List<Tree<FileableCmisObject>> getFolderTree(int depth) {
-		return getFolderTree(depth, getSession().getDefaultContext());
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getFolderTree(int,
-	 * org.apache.opencmis.client.api.OperationContext)
-	 */
-	public List<Tree<FileableCmisObject>> getFolderTree(int depth, OperationContext context) {
-		String objectId = getObjectId();
-
-		// get the folder tree
-		List<ObjectInFolderContainer> providerContainerList = getBinding().getNavigationService().getFolderTree(
-				getRepositoryId(), objectId, BigInteger.valueOf(depth), context.getFilterString(),
-				context.isIncludeAllowableActions(), context.getIncludeRelationships(),
-				context.getRenditionFilterString(), context.isIncludePathSegments(), null);
-
-		return convertProviderContainer(providerContainerList, context);
-	}
-
-	/**
-	 * Converts a provider container into an API container.
-	 */
-	private List<Tree<FileableCmisObject>> convertProviderContainer(
-			List<ObjectInFolderContainer> providerContainerList, OperationContext context) {
-		if (providerContainerList == null) {
-			return null;
-		}
-
-		ObjectFactory of = getSession().getObjectFactory();
-
-		List<Tree<FileableCmisObject>> result = new ArrayList<Tree<FileableCmisObject>>();
-		for (ObjectInFolderContainer oifc : providerContainerList) {
-			if ((oifc.getObject() == null) || (oifc.getObject().getObject() == null)) {
-				// shouldn't happen ...
-				continue;
-			}
-
-			// convert the object
-			CmisObject object = of.convertObject(oifc.getObject().getObject(), context);
-			if (!(object instanceof FileableCmisObject)) {
-				// the repository must not return objects that are not fileable,
-				// but you never know...
-				continue;
-			}
-
-			// convert the children
-			List<Tree<FileableCmisObject>> children = convertProviderContainer(oifc.getChildren(), context);
-
-			// add both to current container
-			result.add(new ContainerImpl<FileableCmisObject>((FileableCmisObject) object, children));
-		}
-
-		return result;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#isRootFolder()
-	 */
-	public boolean isRootFolder() {
-		String objectId = getObjectId();
-		String rootFolderId = getSession().getRepositoryInfo().getRootFolderId();
-
-		return objectId.equals(rootFolderId);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getFolderParent()
-	 */
-	public Folder getFolderParent() {
-		if (isRootFolder()) {
-			return null;
-		}
-
-		List<Folder> parents = super.getParents();
-		if ((parents == null) || (parents.isEmpty())) {
-			return null;
-		}
-
-		return parents.get(0);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.opencmis.client.api.Folder#getPath()
-	 */
-	public String getPath() {
-		String path;
-
-		readLock();
-		try {
-			// get the path property
-			path = getPropertyValue(PropertyIds.PATH);
-
-			// if the path property isn't set, get it
-			if (path == null) {
-				String objectId = getObjectId();
-				ObjectData objectData = getBinding().getObjectService().getObject(getRepositoryId(), objectId,
-						PropertyIds.PATH, false, IncludeRelationships.NONE, "cmis:none", false, false, null);
-
-				if ((objectData.getProperties() != null) && (objectData.getProperties().getProperties() != null)) {
-					PropertyData<?> pathProperty = objectData.getProperties().getProperties().get(PropertyIds.PATH);
-
-					if (pathProperty instanceof PropertyString) {
-						path = ((PropertyString) pathProperty).getFirstValue();
-					}
-				}
-			}
-		} finally {
-			readUnlock();
-		}
-
-		// we still don't know the path ... it's not a CMIS compliant repository
-		if (path == null) {
-			throw new CmisRuntimeException("Repository didn't return " + PropertyIds.PATH + "!");
-		}
-
-		return path;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.apache.opencmis.client.runtime.AbstractPersistentFilableCmisObject
-	 * #getPaths()
-	 */
-	@Override
-	public List<String> getPaths() {
-		return Collections.singletonList(getPath());
-	}
+    private static final Set<Updatability> CREATE_UPDATABILITY = new HashSet<Updatability>();
+    static {
+        CREATE_UPDATABILITY.add(Updatability.ONCREATE);
+        CREATE_UPDATABILITY.add(Updatability.READWRITE);
+    }
+
+    /**
+     * Constructor.
+     */
+    public PersistentFolderImpl(PersistentSessionImpl session, ObjectType objectType, ObjectData objectData,
+            OperationContext context) {
+        initialize(session, objectType, objectData, context);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#createDocument(java.util.Map,
+     * org.apache.opencmis.client.api.ContentStream,
+     * org.apache.opencmis.commons.enums.VersioningState, java.util.List,
+     * java.util.List, java.util.List,
+     * org.apache.opencmis.client.api.OperationContext)
+     */
+    public Document createDocument(Map<String, ?> properties, ContentStream contentStream,
+            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
+            OperationContext context) {
+        String objectId = getObjectId();
+
+        ObjectFactory of = getObjectFactory();
+
+        String newId = getBinding().getObjectService().createDocument(getRepositoryId(),
+                of.convertProperties(properties, null, CREATE_UPDATABILITY), objectId,
+                of.convertContentStream(contentStream), versioningState, of.convertPolicies(policies),
+                of.convertAces(addAces), of.convertAces(removeAces), null);
+
+        // if no context is provided the object will not be fetched
+        if ((context == null) || (newId == null)) {
+            return null;
+        }
+
+        // get the new object
+        CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
+        if (!(object instanceof Document)) {
+            throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
+        }
+
+        return (Document) object;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.Folder#createDocumentFromSource(org.apache
+     * .opencmis.client.api .ObjectId, java.util.Map,
+     * org.apache.opencmis.commons.enums.VersioningState, java.util.List,
+     * java.util.List, java.util.List,
+     * org.apache.opencmis.client.api.OperationContext)
+     */
+    public Document createDocumentFromSource(ObjectId source, Map<String, ?> properties,
+            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
+            OperationContext context) {
+        if ((source == null) || (source.getId() == null)) {
+            throw new IllegalArgumentException("Source must be set!");
+        }
+
+        String objectId = getObjectId();
+
+        // get the type of the source document
+        ObjectType type = null;
+        if (source instanceof CmisObject) {
+            type = ((CmisObject) source).getBaseType();
+        } else {
+            CmisObject sourceObj = getSession().getObject(source);
+            type = sourceObj.getType();
+        }
+
+        if (type.getBaseTypeId() != BaseTypeId.CMIS_DOCUMENT) {
+            throw new IllegalArgumentException("Source object must be a document!");
+        }
+
+        ObjectFactory of = getObjectFactory();
+
+        Set<Updatability> updatebility = new HashSet<Updatability>();
+        updatebility.add(Updatability.READWRITE);
+
+        String newId = getBinding().getObjectService().createDocumentFromSource(getRepositoryId(), source.getId(),
+                of.convertProperties(properties, type, updatebility), objectId, versioningState,
+                of.convertPolicies(policies), of.convertAces(addAces), of.convertAces(removeAces), null);
+
+        // if no context is provided the object will not be fetched
+        if ((context == null) || (newId == null)) {
+            return null;
+        }
+
+        // get the new object
+        CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
+        if (!(object instanceof Document)) {
+            throw new CmisRuntimeException("Newly created object is not a document! New id: " + newId);
+        }
+
+        return (Document) object;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#createFolder(java.util.Map,
+     * java.util.List, java.util.List, java.util.List,
+     * org.apache.opencmis.client.api.OperationContext)
+     */
+    public Folder createFolder(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
+            List<Ace> removeAces, OperationContext context) {
+        String objectId = getObjectId();
+
+        ObjectFactory of = getObjectFactory();
+
+        String newId = getBinding().getObjectService().createFolder(getRepositoryId(),
+                of.convertProperties(properties, null, CREATE_UPDATABILITY), objectId, of.convertPolicies(policies),
+                of.convertAces(addAces), of.convertAces(removeAces), null);
+
+        // if no context is provided the object will not be fetched
+        if ((context == null) || (newId == null)) {
+            return null;
+        }
+
+        // get the new object
+        CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
+        if (!(object instanceof Folder)) {
+            throw new CmisRuntimeException("Newly created object is not a folder! New id: " + newId);
+        }
+
+        return (Folder) object;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#createPolicy(java.util.Map,
+     * java.util.List, java.util.List, java.util.List,
+     * org.apache.opencmis.client.api.OperationContext)
+     */
+    public Policy createPolicy(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
+            List<Ace> removeAces, OperationContext context) {
+        String objectId = getObjectId();
+
+        ObjectFactory of = getObjectFactory();
+
+        String newId = getBinding().getObjectService().createPolicy(getRepositoryId(),
+                of.convertProperties(properties, null, CREATE_UPDATABILITY), objectId, of.convertPolicies(policies),
+                of.convertAces(addAces), of.convertAces(removeAces), null);
+
+        // if no context is provided the object will not be fetched
+        if ((context == null) || (newId == null)) {
+            return null;
+        }
+
+        // get the new object
+        CmisObject object = getSession().getObject(getSession().createObjectId(newId), context);
+        if (!(object instanceof Policy)) {
+            throw new CmisRuntimeException("Newly created object is not a policy! New id: " + newId);
+        }
+
+        return (Policy) object;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#deleteTree(boolean,
+     * org.apache.opencmis.commons.enums.UnfileObjects, boolean)
+     */
+    public List<String> deleteTree(boolean allVersions, UnfileObject unfile, boolean continueOnFailure) {
+        String repositoryId = getRepositoryId();
+        String objectId = getObjectId();
+
+        FailedToDeleteData failed = getBinding().getObjectService().deleteTree(repositoryId, objectId, allVersions,
+                unfile, continueOnFailure, null);
+
+        return failed.getIds();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getAllowedChildObjectTypes()
+     */
+    public List<ObjectType> getAllowedChildObjectTypes() {
+        List<ObjectType> result = new ArrayList<ObjectType>();
+
+        readLock();
+        try {
+            List<String> otids = getPropertyMultivalue(PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS);
+            if (otids == null) {
+                return result;
+            }
+
+            for (String otid : otids) {
+                result.add(getSession().getTypeDefinition(otid));
+            }
+        } finally {
+            readUnlock();
+        }
+
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getCheckedOutDocs(int)
+     */
+    public PagingIterable<Document> getCheckedOutDocs(int itemsPerPage) {
+        return getCheckedOutDocs(getSession().getDefaultContext(), itemsPerPage);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @seeorg.apache.opencmis.client.api.Folder#getCheckedOutDocs(org.apache.
+     * opencmis.client.api. OperationContext, int)
+     */
+    public PagingIterable<Document> getCheckedOutDocs(OperationContext context, final int itemsPerPage) {
+        if (itemsPerPage < 1) {
+            throw new IllegalArgumentException("itemsPerPage must be > 0!");
+        }
+
+        final String objectId = getObjectId();
+        final NavigationService navigationService = getBinding().getNavigationService();
+        final ObjectFactory objectFactory = getSession().getObjectFactory();
+        final OperationContext ctxt = new OperationContextImpl(context);
+
+        return new DefaultPagingIterable<Document>(new AbstractPageFetch<Document>() {
+
+            @Override
+            protected AbstractPageFetch.PageFetchResult<Document> fetchPage(long skipCount) {
+
+                // get checked out documents for this folder
+                ObjectList checkedOutDocs = navigationService.getCheckedOutDocs(getRepositoryId(), objectId, ctxt
+                        .getFilterString(), ctxt.getOrderBy(), ctxt.isIncludeAllowableActions(), ctxt
+                        .getIncludeRelationships(), ctxt.getRenditionFilterString(), BigInteger.valueOf(itemsPerPage),
+                        BigInteger.valueOf(skipCount), null);
+
+                // convert objects
+                List<Document> page = new ArrayList<Document>();
+                if (checkedOutDocs.getObjects() != null) {
+                    for (ObjectData objectData : checkedOutDocs.getObjects()) {
+                        CmisObject doc = objectFactory.convertObject(objectData, ctxt);
+                        if (!(doc instanceof Document)) {
+                            // should not happen...
+                            continue;
+                        }
+
+                        page.add((Document) doc);
+                    }
+                }
+
+                return new AbstractPageFetch.PageFetchResult<Document>(page, checkedOutDocs.getNumItems(),
+                        checkedOutDocs.hasMoreItems()) {
+                };
+            }
+        });
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getChildren(int)
+     */
+    public PagingIterable<CmisObject> getChildren(int itemsPerPage) {
+        return getChildren(getSession().getDefaultContext(), itemsPerPage);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.api.Folder#getChildren(org.apache.opencmis
+     * .client.api.OperationContext , int)
+     */
+    public PagingIterable<CmisObject> getChildren(OperationContext context, final int itemsPerPage) {
+
+        if (itemsPerPage < 1) {
+            throw new IllegalArgumentException("itemsPerPage must be > 0!");
+        }
+
+        final String objectId = getObjectId();
+        final NavigationService navigationService = getBinding().getNavigationService();
+        final ObjectFactory objectFactory = getSession().getObjectFactory();
+        final OperationContext ctxt = new OperationContextImpl(context);
+
+        return new DefaultPagingIterable<CmisObject>(new AbstractPageFetch<CmisObject>() {
+
+            @Override
+            protected AbstractPageFetch.PageFetchResult<CmisObject> fetchPage(long skipCount) {
+
+                // get the children
+                ObjectInFolderList children = navigationService.getChildren(getRepositoryId(), objectId, ctxt
+                        .getFilterString(), ctxt.getOrderBy(), ctxt.isIncludeAllowableActions(), ctxt
+                        .getIncludeRelationships(), ctxt.getRenditionFilterString(), ctxt.isIncludePathSegments(),
+                        BigInteger.valueOf(itemsPerPage), BigInteger.valueOf(skipCount), null);
+
+                // convert objects
+                List<CmisObject> page = new ArrayList<CmisObject>();
+                List<ObjectInFolderData> childObjects = children.getObjects();
+                if (childObjects != null) {
+                    for (ObjectInFolderData objectData : childObjects) {
+                        if (objectData.getObject() != null) {
+                            page.add(objectFactory.convertObject(objectData.getObject(), ctxt));
+                        }
+                    }
+                }
+
+                return new AbstractPageFetch.PageFetchResult<CmisObject>(page, children.getNumItems(), children
+                        .hasMoreItems()) {
+                };
+            }
+        });
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getDescendants(int)
+     */
+    public List<Tree<FileableCmisObject>> getDescendants(int depth) {
+        return getDescendants(depth, getSession().getDefaultContext());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getDescendants(int,
+     * org.apache.opencmis.client.api.OperationContext)
+     */
+    public List<Tree<FileableCmisObject>> getDescendants(int depth, OperationContext context) {
+        String objectId = getObjectId();
+
+        // get the descendants
+        List<ObjectInFolderContainer> providerContainerList = getBinding().getNavigationService().getDescendants(
+                getRepositoryId(), objectId, BigInteger.valueOf(depth), context.getFilterString(),
+                context.isIncludeAllowableActions(), context.getIncludeRelationships(),
+                context.getRenditionFilterString(), context.isIncludePathSegments(), null);
+
+        return convertProviderContainer(providerContainerList, context);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getFolderTree(int)
+     */
+    public List<Tree<FileableCmisObject>> getFolderTree(int depth) {
+        return getFolderTree(depth, getSession().getDefaultContext());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getFolderTree(int,
+     * org.apache.opencmis.client.api.OperationContext)
+     */
+    public List<Tree<FileableCmisObject>> getFolderTree(int depth, OperationContext context) {
+        String objectId = getObjectId();
+
+        // get the folder tree
+        List<ObjectInFolderContainer> providerContainerList = getBinding().getNavigationService().getFolderTree(
+                getRepositoryId(), objectId, BigInteger.valueOf(depth), context.getFilterString(),
+                context.isIncludeAllowableActions(), context.getIncludeRelationships(),
+                context.getRenditionFilterString(), context.isIncludePathSegments(), null);
+
+        return convertProviderContainer(providerContainerList, context);
+    }
+
+    /**
+     * Converts a provider container into an API container.
+     */
+    private List<Tree<FileableCmisObject>> convertProviderContainer(
+            List<ObjectInFolderContainer> providerContainerList, OperationContext context) {
+        if (providerContainerList == null) {
+            return null;
+        }
+
+        ObjectFactory of = getSession().getObjectFactory();
+
+        List<Tree<FileableCmisObject>> result = new ArrayList<Tree<FileableCmisObject>>();
+        for (ObjectInFolderContainer oifc : providerContainerList) {
+            if ((oifc.getObject() == null) || (oifc.getObject().getObject() == null)) {
+                // shouldn't happen ...
+                continue;
+            }
+
+            // convert the object
+            CmisObject object = of.convertObject(oifc.getObject().getObject(), context);
+            if (!(object instanceof FileableCmisObject)) {
+                // the repository must not return objects that are not fileable,
+                // but you never know...
+                continue;
+            }
+
+            // convert the children
+            List<Tree<FileableCmisObject>> children = convertProviderContainer(oifc.getChildren(), context);
+
+            // add both to current container
+            result.add(new ContainerImpl<FileableCmisObject>((FileableCmisObject) object, children));
+        }
+
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#isRootFolder()
+     */
+    public boolean isRootFolder() {
+        String objectId = getObjectId();
+        String rootFolderId = getSession().getRepositoryInfo().getRootFolderId();
+
+        return objectId.equals(rootFolderId);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getFolderParent()
+     */
+    public Folder getFolderParent() {
+        if (isRootFolder()) {
+            return null;
+        }
+
+        List<Folder> parents = super.getParents();
+        if ((parents == null) || (parents.isEmpty())) {
+            return null;
+        }
+
+        return parents.get(0);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.opencmis.client.api.Folder#getPath()
+     */
+    public String getPath() {
+        String path;
+
+        readLock();
+        try {
+            // get the path property
+            path = getPropertyValue(PropertyIds.PATH);
+
+            // if the path property isn't set, get it
+            if (path == null) {
+                String objectId = getObjectId();
+                ObjectData objectData = getBinding().getObjectService().getObject(getRepositoryId(), objectId,
+                        PropertyIds.PATH, false, IncludeRelationships.NONE, "cmis:none", false, false, null);
+
+                if ((objectData.getProperties() != null) && (objectData.getProperties().getProperties() != null)) {
+                    PropertyData<?> pathProperty = objectData.getProperties().getProperties().get(PropertyIds.PATH);
+
+                    if (pathProperty instanceof PropertyString) {
+                        path = ((PropertyString) pathProperty).getFirstValue();
+                    }
+                }
+            }
+        } finally {
+            readUnlock();
+        }
+
+        // we still don't know the path ... it's not a CMIS compliant repository
+        if (path == null) {
+            throw new CmisRuntimeException("Repository didn't return " + PropertyIds.PATH + "!");
+        }
+
+        return path;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.opencmis.client.runtime.AbstractPersistentFilableCmisObject
+     * #getPaths()
+     */
+    @Override
+    public List<String> getPaths() {
+        return Collections.singletonList(getPath());
+    }
 }