You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by dc...@apache.org on 2010/02/16 17:04:07 UTC

svn commit: r910572 [28/36] - in /incubator/chemistry/trunk/opencmis: ./ _dev/ opencmis-client/ opencmis-client/opencmis-client-api/ opencmis-client/opencmis-client-api/src/ opencmis-client/opencmis-client-api/src/main/ opencmis-client/opencmis-client-...

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/TypeValidator.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/TypeValidator.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/TypeValidator.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/TypeValidator.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,448 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.api.Choice;
+import org.apache.opencmis.commons.api.DocumentTypeDefinition;
+import org.apache.opencmis.commons.api.PropertyDecimalDefinition;
+import org.apache.opencmis.commons.api.PropertyDefinition;
+import org.apache.opencmis.commons.api.PropertyIntegerDefinition;
+import org.apache.opencmis.commons.api.PropertyStringDefinition;
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.enums.BaseObjectTypeIds;
+import org.apache.opencmis.commons.enums.Cardinality;
+import org.apache.opencmis.commons.enums.VersioningState;
+import org.apache.opencmis.commons.exceptions.CmisConstraintException;
+import org.apache.opencmis.commons.provider.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.commons.provider.PropertyDecimalData;
+import org.apache.opencmis.commons.provider.PropertyIntegerData;
+
+/**
+ * @author Jens
+ */
+public class TypeValidator {
+
+  static void validateRequiredSystemProperties(PropertiesData properties) {
+    if (properties == null || properties.getProperties() == null)
+      throw new RuntimeException("Cannot create object, no properties are given");
+
+    if (!properties.getProperties().containsKey(PropertyIds.CMIS_OBJECT_TYPE_ID))
+      throw new RuntimeException("Cannot create object, type id is missing");
+
+  }
+  
+  private static boolean isMandatorySystemProperty(String propertyId) {
+    // TODO Auto-generated method stub
+    return propertyId.equals(PropertyIds.CMIS_OBJECT_TYPE_ID);
+  }
+
+  @SuppressWarnings("unchecked")
+  static <T> PropertyValidator<T> createPropertyValidator(PropertyDefinition<?> propDef) {
+    PropertyValidator<T> result = null;
+    if (propDef instanceof PropertyIntegerDefinition) {
+      result = (PropertyValidator<T>) new PropertyValidatorInteger();
+    }
+    else if (propDef instanceof PropertyDecimalDefinition) {
+      result = (PropertyValidator<T>) new PropertyValidatorDecimal();
+    }
+    else if (propDef instanceof PropertyStringDefinition) {
+      result = (PropertyValidator<T>) new PropertyValidatorString();
+    }
+    else {
+      result = new PropertyValidator<T>();
+    }
+    return result;
+  }
+
+  /*
+   * property validations: not readonly, all required are given, all are known in type
+   * cardinality: no multi values for single value, def min max check for Integer and Decimal,
+   * choices and in list Strings, max length set default value for omitted properties
+   */
+  static class PropertyValidator<T> {
+
+    public void validate(PropertyDefinition<T> propDef, PropertyData<T> prop) {
+
+      // check general constraints for all property types
+      if (propDef.getCardinality() == Cardinality.SINGLE && prop.getValues().size() > 1)
+        throw new CmisConstraintException("The property with id " + propDef.getId()
+            + " is single valued, but multiple values are passed " + prop.getValues());
+
+      if (propDef.getChoices() != null && propDef.getChoices().size() > 0) {
+        validateChoices(propDef, prop);
+      }
+    }
+
+    private void validateChoices(PropertyDefinition<T> propDef, PropertyData<T> prop) {
+      boolean isAllowedValue = true;
+      boolean hasMultiValueChoiceLists = false;
+      for (Choice<?> allowedValue : propDef.getChoices()) {
+        if (allowedValue.getValue() != null && allowedValue.getValue().size() > 1)
+          hasMultiValueChoiceLists = true;
+      }
+
+      // check if value is in list
+      if (hasMultiValueChoiceLists) {
+        // do a complex check if this combination of actual values is allowed
+        // check if value is in list
+        isAllowedValue = false;
+        List<?> actualValues = prop.getValues();
+        for (Choice<?> allowedValue : propDef.getChoices()) {
+          if (allowedValue.getValue().size() == actualValues.size()) {
+            boolean listValuesAreEqual = true;
+            Iterator<?> it = allowedValue.getValue().iterator();
+            for (Object actualValue : actualValues) {
+              if (!actualValue.equals(it.next())) {
+                listValuesAreEqual = false;
+                break;
+              }
+            }
+            if (listValuesAreEqual) {
+              isAllowedValue = true;
+            }
+          }
+
+          if (isAllowedValue)
+            break;
+        }
+
+      }
+      else {
+        List<T> allowedValues = getAllowedValues(propDef.getChoices());
+        // do a simpler check if all values are choice elements
+
+        for (Object actualValue : prop.getValues()) {
+          if (!allowedValues.contains(actualValue)) {
+            isAllowedValue = false;
+            break;
+          }
+        }
+      }
+
+      if (!isAllowedValue)
+        throw new CmisConstraintException("The property with id " + propDef.getId()
+            + " has a fixed set of values. Value(s) " + prop.getValues() + " are not listed.");
+    }
+    
+    /**
+     * Calculate the list of allowed values for this property definition by recursively
+     * collecting all choice values from property definition
+     * 
+     * @param propDef
+     *          property definition
+     * @return
+     *    list of possible values in complete hierarchy
+     */
+    private List<T> getAllowedValues (List<Choice<T>> choices) {
+      List<T> allowedValues = new ArrayList<T>(choices.size());
+      for (Choice<T> choice : choices) {
+        if (choice.getValue() != null)
+          allowedValues.add(choice.getValue().get(0));
+        if (choice.getChoice() != null) {
+          List<Choice<T>> x = choice.getChoice();
+          allowedValues.addAll(getAllowedValues(x));
+        }
+      }  
+      return allowedValues;
+    }
+  }
+
+  static class PropertyValidatorInteger extends PropertyValidator<BigInteger> {
+
+    public void validate(PropertyDefinition<BigInteger> propDef, PropertyData<BigInteger> property) {
+
+      super.validate(propDef, property);
+
+      BigInteger propVal = ((PropertyIntegerData) property).getFirstValue();
+      BigInteger minVal = ((PropertyIntegerDefinition) propDef).getMinValue();
+      BigInteger maxVal = ((PropertyIntegerDefinition) propDef).getMaxValue();
+
+      // check min and max
+      if (minVal != null && propVal != null && propVal.compareTo(minVal) == -1) {
+        throw new CmisConstraintException("For property with id " + propDef.getId() + " the value "
+            + propVal + " is less than the minimum value " + minVal);
+      }
+      if (maxVal != null && propVal != null && propVal.compareTo(maxVal) == 1) {
+        throw new CmisConstraintException("For property with id " + propDef.getId() + " the value "
+            + propVal + " is bigger than the maximum value " + maxVal);
+      }
+    }
+  }
+
+  static class PropertyValidatorDecimal extends PropertyValidator<BigDecimal> {
+
+    public void validate(PropertyDefinition<BigDecimal> propDef, PropertyData<BigDecimal> property) {
+
+      super.validate(propDef, property);
+
+      BigDecimal propVal = ((PropertyDecimalData) property).getFirstValue();
+      BigDecimal minVal = ((PropertyDecimalDefinition) propDef).getMinValue();
+      BigDecimal maxVal = ((PropertyDecimalDefinition) propDef).getMaxValue();
+
+      // check min and max
+      if (minVal != null && propVal != null && propVal.compareTo(minVal) == -1) {
+        throw new CmisConstraintException("For property with id " + propDef.getId() + " the value "
+            + propVal + " is less than the minimum value " + minVal);
+      }
+      if (maxVal != null && propVal != null && propVal.compareTo(maxVal) == 1) {
+        throw new CmisConstraintException("For property with id " + propDef.getId() + " the value "
+            + propVal + " is bigger than the maximum value " + maxVal);
+      }
+    }
+  }
+
+  static class PropertyValidatorString extends PropertyValidator<String> {
+
+    public void validate(PropertyDefinition<String> propDef, PropertyData<String> property) {
+
+      super.validate(propDef, property);
+
+      long maxLen = ((PropertyStringDefinition) propDef).getMaxLength() == null ? -1
+          : ((PropertyStringDefinition) propDef).getMaxLength().longValue();
+      long len = ((PropertyData<String>) property).getFirstValue() == null ? -1
+          : ((PropertyData<String>) property).getFirstValue().length();
+
+      // check max length
+      if (maxLen >= 0 && len >= 0 && maxLen < len) {
+        throw new CmisConstraintException("For property with id " + propDef.getId()
+            + " the length of " + len + "is bigger than the maximum allowed length  " + maxLen);
+      }
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> void validateProperties(TypeDefinition typeDef, PropertiesData properties,
+      boolean checkMandatory) {
+
+    List<String> propDefsRequired = getMandatoryPropDefs(typeDef.getPropertyDefinitions());
+
+    for (PropertyData<?> prop : properties.getProperties().values()) {
+      String propertyId = prop.getId();
+      BaseObjectTypeIds baseTypeId = typeDef.getBaseId();
+
+      if (isSystemProperty(baseTypeId, propertyId))
+        continue; // ignore system properties for validation
+
+      // Check if all properties are known in the type
+      if (!typeContainsProperty(typeDef, propertyId)) {
+        throw new CmisConstraintException("Unknown property " + propertyId + " in type "
+            + typeDef.getId());
+      }
+
+      // check that all mandatory attributes are present
+      if (checkMandatory && propDefsRequired.contains(propertyId))
+        propDefsRequired.remove(propertyId);
+
+      // check all type specific constraints:
+      PropertyDefinition<T> propDef = getPropertyDefinition(typeDef, propertyId);
+      PropertyValidator<T> validator = createPropertyValidator(propDef);
+      validator.validate(propDef, (PropertyData<T>) prop);
+    }
+
+    if (checkMandatory && !propDefsRequired.isEmpty())
+      throw new CmisConstraintException("The following mandatory properties are missing: "
+          + propDefsRequired);
+  }
+  
+  public static void validateVersionStateForCreate(DocumentTypeDefinition typeDef, VersioningState verState) {
+    if (null==verState)
+      return;
+    if (typeDef.isVersionable() && verState.equals(VersioningState.NONE) || 
+        ! typeDef.isVersionable() && !verState.equals(VersioningState.NONE)) {
+      throw new CmisConstraintException("The versioning state flag is imcompatible to the type definition.");
+    }
+
+  }
+  public static void validateAllowedChildObjectTypes(TypeDefinition childTypeDef, List<String> allowedChildTypes) {
+    
+    if (null == allowedChildTypes)
+      return; // all types are allowed
+    
+    for (String allowedChildType : allowedChildTypes ) {
+      if (allowedChildType.equals(childTypeDef.getId()))
+        return;
+    }
+    throw new RuntimeException("The requested type " + childTypeDef.getId() + " is not allowed in this folder");    
+  }
+
+  private static List<String> getMandatoryPropDefs(Map<String, PropertyDefinition<?>> propDefs) {
+    List<String> res = new ArrayList<String>();
+    if (null != propDefs) {
+      for (PropertyDefinition<?> propDef : propDefs.values()) {
+        if (propDef.isRequired() && !isMandatorySystemProperty(propDef.getId()) )
+          res.add(propDef.getId());
+      }
+    }
+    return res;
+  }
+
+  public static boolean typeContainsProperty(TypeDefinition typeDef, String propertyId) {
+
+    Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
+    if (null == propDefs)
+      return false;
+    
+    PropertyDefinition<?> propDef = propDefs.get(propertyId);
+    
+    if (null == propDef)
+      return false; // unknown property id in this type
+    else
+      return true;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static<T> PropertyDefinition<T> getPropertyDefinition(TypeDefinition typeDef,
+      String propertyId) {
+
+    Map<String, PropertyDefinition<?>> propDefs = typeDef.getPropertyDefinitions();
+    if (null == propDefs)
+      return null;
+    
+    PropertyDefinition<?> propDef = propDefs.get(propertyId);
+    
+    if (null == propDef)
+      return null; // not found
+    else
+      return (PropertyDefinition<T>)propDef;
+  }
+
+  private static boolean isSystemProperty(BaseObjectTypeIds baseTypeId, String propertyId) {
+
+    if (propertyId.equals(PropertyIds.CMIS_NAME)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_OBJECT_ID)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_OBJECT_TYPE_ID)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_BASE_TYPE_ID)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_CREATED_BY)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_CREATION_DATE)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_LAST_MODIFIED_BY)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_LAST_MODIFICATION_DATE)) {
+      return true;
+    }
+    else if (propertyId.equals(PropertyIds.CMIS_CHANGE_TOKEN)) {
+      return true;
+    }
+
+    if (baseTypeId.equals(BaseObjectTypeIds.CMIS_DOCUMENT)) {
+      if (propertyId.equals(PropertyIds.CMIS_IS_IMMUTABLE)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_IS_LATEST_VERSION)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_IS_MAJOR_VERSION)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_VERSION_SERIES_ID)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_IS_LATEST_MAJOR_VERSION)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_VERSION_LABEL)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_VERSION_SERIES_ID)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_IS_VERSION_SERIES_CHECKED_OUT)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_VERSION_SERIES_CHECKED_OUT_BY)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_VERSION_SERIES_CHECKED_OUT_ID)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_CHECKIN_COMMENT)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_CONTENT_STREAM_LENGTH)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_CONTENT_STREAM_MIME_TYPE)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_CONTENT_STREAM_FILE_NAME)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_CONTENT_STREAM_ID)) {
+        return true;
+      }
+      else {
+        return false;
+      }
+    }
+    else if (baseTypeId.equals(BaseObjectTypeIds.CMIS_FOLDER)) {
+      if (propertyId.equals(PropertyIds.CMIS_PARENT_ID)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_ALLOWED_CHILD_OBJECT_TYPE_IDS)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_PATH)) {
+        return true;
+      }
+      else {
+        return false;
+      }
+    }
+    else if (baseTypeId.equals(BaseObjectTypeIds.CMIS_POLICY)) {
+      if (propertyId.equals(PropertyIds.CMIS_SOURCE_ID)) {
+        return true;
+      }
+      else if (propertyId.equals(PropertyIds.CMIS_TARGET_ID)) {
+        return true;
+      }
+      else {
+        return false;
+      }
+    }
+    else { // relationship
+      if (propertyId.equals(PropertyIds.CMIS_POLICY_TEXT)) {
+        return true;
+      }
+      else {
+        return false;
+      }
+    }
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/TypeValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/VersioningServiceImpl.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/VersioningServiceImpl.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/VersioningServiceImpl.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/VersioningServiceImpl.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.commons.api.DocumentTypeDefinition;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.enums.BaseObjectTypeIds;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.exceptions.CmisNotSupportedException;
+import org.apache.opencmis.commons.exceptions.CmisUpdateConflictException;
+import org.apache.opencmis.commons.provider.AccessControlList;
+import org.apache.opencmis.commons.provider.ContentStreamData;
+import org.apache.opencmis.commons.provider.Holder;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectService;
+import org.apache.opencmis.commons.provider.PropertiesData;
+import org.apache.opencmis.commons.provider.VersioningService;
+import org.apache.opencmis.inmemory.server.RuntimeContext;
+import org.apache.opencmis.inmemory.storedobj.api.Document;
+import org.apache.opencmis.inmemory.storedobj.api.DocumentVersion;
+import org.apache.opencmis.inmemory.storedobj.api.ObjectStore;
+import org.apache.opencmis.inmemory.storedobj.api.StoreManager;
+import org.apache.opencmis.inmemory.storedobj.api.StoredObject;
+import org.apache.opencmis.inmemory.storedobj.api.VersionedDocument;
+import org.apache.opencmis.inmemory.types.PropertyCreationHelper;
+
+public class VersioningServiceImpl extends AbstractServiceImpl implements VersioningService {
+  
+  private static Log LOG = LogFactory.getLog(VersioningServiceImpl.class);
+
+  private ObjectService fObjectService;
+
+  public VersioningServiceImpl(StoreManager storeManager, ObjectService objectService) {
+    super(storeManager);
+    fObjectService = objectService;
+  }
+
+  public void cancelCheckOut(String repositoryId, String objectId, ExtensionsData extension) {
+
+    checkStandardParameters(repositoryId, objectId);
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(objectId);
+    
+    String user = RuntimeContext.getRuntimeConfigValue(ConfigConstants.USERNAME);
+    VersionedDocument verDoc = testHasProperCheckedOutStatus(so, user);
+
+    verDoc.cancelCheckOut(user);
+  }
+  
+  public void checkIn(String repositoryId, Holder<String> objectId, Boolean major,
+      PropertiesData properties, ContentStreamData contentStream, String checkinComment,
+      List<String> policies, AccessControlList addAces, AccessControlList removeAces,
+      ExtensionsData extension) {
+    
+    checkStandardParameters(repositoryId, objectId.getValue());
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(objectId.getValue());
+
+    String user = RuntimeContext.getRuntimeConfigValue(ConfigConstants.USERNAME);
+    VersionedDocument verDoc = testHasProperCheckedOutStatus(so, user);
+
+    DocumentVersion  pwc = verDoc.getPwc();
+    
+    if (null != contentStream)
+      pwc.setContent(contentStream, false);
+    
+    if (null != properties && null != properties.getProperties())
+      pwc.setCustomProperties(properties.getProperties());
+    
+    verDoc.checkIn(major, checkinComment, user);    
+  }
+
+
+  public void checkOut(String repositoryId, Holder<String> objectId, ExtensionsData extension,
+      Holder<Boolean> contentCopied) {
+    
+    checkStandardParameters(repositoryId, objectId.getValue());
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(objectId.getValue());
+    TypeDefinition typeDef = getTypeDefinition(repositoryId, so);
+    if (!typeDef.getBaseId().equals(BaseObjectTypeIds.CMIS_DOCUMENT))
+      throw new CmisNotSupportedException("Only documents can be checked-out.");
+    else if (!((DocumentTypeDefinition) typeDef).isVersionable())  
+      throw new CmisNotSupportedException("Object can't be checked-out, type is not versionable.");
+    
+    checkIsVersionableObject(so);
+     
+    VersionedDocument verDoc = getVersionedDocumentOfObjectId(so);
+
+    ContentStreamData content = null;
+    
+    if (so instanceof DocumentVersion) {
+      // get document the version is contained in to c
+      content = ((DocumentVersion) so).getContent();
+    } else {
+      content = ((VersionedDocument) so).getLatestVersion(false).getContent();
+    }
+    
+    if (verDoc.isCheckedOut())
+      throw new CmisUpdateConflictException("Document " + objectId.getValue() + " is already checked out.");
+    
+    String user = RuntimeContext.getRuntimeConfigValue(ConfigConstants.USERNAME);
+    checkHasUser(user);    
+    
+    DocumentVersion pwc = verDoc.checkOut(content, user);
+    objectId.setValue(pwc.getId()); // return the id of the created pwc    
+  }
+
+  public List<ObjectData> getAllVersions(String repositoryId, String versionSeriesId,
+      String filter, Boolean includeAllowableActions, ExtensionsData extension) {
+    
+    checkStandardParameters(repositoryId, versionSeriesId);
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(versionSeriesId);
+    
+    if (! (so instanceof VersionedDocument))
+      throw new RuntimeException("Object is not instance of a VersionedDocument (version series)");    
+
+    VersionedDocument verDoc = (VersionedDocument)so;
+    List<ObjectData> res = new ArrayList<ObjectData> ();
+    List<DocumentVersion> versions = verDoc.getAllVersions(filter);
+    for (DocumentVersion version : versions) {
+      ObjectData objData = getObject(repositoryId, version.getId(), filter, includeAllowableActions, extension);
+      res.add(objData);
+    }
+
+    return res;
+  }
+
+  public ObjectData getObjectOfLatestVersion(String repositoryId, String versionSeriesId,
+      Boolean major, String filter, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
+      Boolean includeAcl, ExtensionsData extension) {
+
+    checkStandardParameters(repositoryId, versionSeriesId);
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(versionSeriesId);
+    ObjectData objData = null;
+    
+    if (so instanceof VersionedDocument) {
+      VersionedDocument verDoc = (VersionedDocument)so;
+      DocumentVersion latestVersion = verDoc.getLatestVersion(major);
+      objData = getObject(repositoryId, latestVersion.getId(), filter, includeAllowableActions, extension);
+    } else if (so instanceof Document) {
+      objData = getObject(repositoryId, so.getId(), filter, includeAllowableActions, extension);
+    } else
+      throw new RuntimeException("Object is not instance of a document (version series)");         
+
+    return objData;
+  }
+
+  public PropertiesData getPropertiesOfLatestVersion(String repositoryId, String versionSeriesId,
+      Boolean major, String filter, ExtensionsData extension) {
+       
+    checkStandardParameters(repositoryId, versionSeriesId);
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(versionSeriesId);
+    StoredObject latestVersionObject = null;
+    
+    if (so instanceof VersionedDocument) {
+      VersionedDocument verDoc = (VersionedDocument)so;
+      latestVersionObject = verDoc.getLatestVersion(major);
+    } else if (so instanceof Document) {
+      latestVersionObject = so;
+    } else
+      throw new RuntimeException("Object is not instance of a document (version series)");    
+
+    List<String> requestedIds = FilterParser.getRequestedIdsFromFilter(filter);
+    PropertiesData props = PropertyCreationHelper.getPropertiesFromObject(repositoryId, latestVersionObject,
+        fStoreManager, requestedIds);
+
+    return props;
+  }
+
+  private ObjectData getObject(String repositoryId, String objectId, String filter,
+      Boolean includeAllowableActions, ExtensionsData extension) {
+    return fObjectService.getObject(repositoryId, objectId, filter, includeAllowableActions, IncludeRelationships.NONE,
+        null, false, includeAllowableActions, extension);
+  }
+
+
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/VersioningServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpi.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpi.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpi.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpi.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory.clientprovider;
+
+import org.apache.opencmis.client.provider.spi.CmisSpi;
+import org.apache.opencmis.client.provider.spi.Session;
+import org.apache.opencmis.commons.provider.AclService;
+import org.apache.opencmis.commons.provider.DiscoveryService;
+import org.apache.opencmis.commons.provider.MultiFilingService;
+import org.apache.opencmis.commons.provider.NavigationService;
+import org.apache.opencmis.commons.provider.ObjectService;
+import org.apache.opencmis.commons.provider.PolicyService;
+import org.apache.opencmis.commons.provider.RelationshipService;
+import org.apache.opencmis.commons.provider.RepositoryInfoData;
+import org.apache.opencmis.commons.provider.RepositoryService;
+import org.apache.opencmis.commons.provider.VersioningService;
+import org.apache.opencmis.inmemory.ConfigConstants;
+import org.apache.opencmis.inmemory.NavigationServiceImpl;
+import org.apache.opencmis.inmemory.ObjectServiceImpl;
+import org.apache.opencmis.inmemory.RepositoryServiceImpl;
+import org.apache.opencmis.inmemory.VersioningServiceImpl;
+import org.apache.opencmis.inmemory.storedobj.api.StoreManager;
+import org.apache.opencmis.inmemory.storedobj.impl.SessionConfigReader;
+import org.apache.opencmis.inmemory.storedobj.impl.StoreManagerFactory;
+import org.apache.opencmis.inmemory.storedobj.impl.StoreManagerImpl;
+
+/**
+ * InMemory test SPI.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * @author Jens
+ * 
+ */
+public class CmisInMemorySpi implements CmisSpi {
+
+  // private static Log log = LogFactory.getLog(CmisInMemorySpi.class);
+  private Session fSession;
+  private RepositoryService fRepositoryService;
+  private NavigationService fNavigationService;
+  private ObjectService fObjectService;
+  private VersioningService fVersioningService;
+  private RepositoryInfoData fRepositoryInfo;
+  private StoreManager fStoreManager;
+  
+  CmisInMemorySpi(Session session) { // package visibility
+    fSession = session;
+    setup();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getRepositoryService()
+   */
+  public RepositoryService getRepositoryService() {
+    return fRepositoryService;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPIFactory#getSPIInstance(org.apache.opencmis.client.
+   * provider.spi.Session)
+   */
+  public CmisSpi getSpiInstance(Session session) {
+    fSession = session;
+    setup();
+    return this;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getACLService()
+   */
+  public AclService getAclService() {
+    // TODO to be completed if ACLs are implemented
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getDiscoveryService()
+   */
+  public DiscoveryService getDiscoveryService() {
+    // TODO to be completed if query is implemented
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getMultiFilingService()
+   */
+  public MultiFilingService getMultiFilingService() {
+    // TODO to be completed if multi-filing implemented
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getNavigationService()
+   */
+  public NavigationService getNavigationService() {
+    return fNavigationService;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getObjectService()
+   */
+  public ObjectService getObjectService() {
+    return fObjectService;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getPolicyService()
+   */
+  public PolicyService getPolicyService() {
+    // TODO to be completed if policies are implemented
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getRelationshipService()
+   */
+  public RelationshipService getRelationshipService() {
+    // TODO to be completed if relationships are implemented
+    return null;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#getVersioningService()
+   */
+  public VersioningService getVersioningService() {
+    return fVersioningService;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#clearAllCaches()
+   */
+  public void clearAllCaches() {
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.opencmis.client.provider.spi.CMISSPI#clearRepositoryCache(java.lang.String)
+   */
+  public void clearRepositoryCache(String repositoryId) {
+  }
+
+  
+  /**
+   * Returns the repository info.
+   */
+  public RepositoryInfoData getRepositoryInfo() {
+    return fRepositoryInfo;
+  }
+
+  public String getStoredObjectFactoryName() {
+    return StoreManagerImpl.class.getName();
+  }
+  
+  public StoreManager getStoreManager() {
+		return fStoreManager;
+	}
+
+  // ---- internal ----
+    
+  private void setup() {
+    String repositoryClassName = (String) fSession.get(ConfigConstants.REPOSITORY_CLASS);
+    if (null==repositoryClassName)
+      repositoryClassName = StoreManagerImpl.class.getName();
+    
+    fStoreManager = StoreManagerFactory.createInstance(repositoryClassName);
+    SessionConfigReader cfgReader = new SessionConfigReader(fSession);
+    fStoreManager.setConfigReader(cfgReader);
+    String repositoryId  = (String) fSession.get(ConfigConstants.REPOSITORY_ID);
+    
+    // first create repository
+    if (null != repositoryId ) {
+      fStoreManager.createRepository(repositoryId);
+    }
+    
+    // then create/initialize type system
+    String typeCreatorClassName = (String) fSession.get(ConfigConstants.TYPE_CREATOR_CLASS);
+    fStoreManager.initTypeSystem(repositoryId, typeCreatorClassName);
+
+    // then init repository (note: loads root folder which requires cmis:folder type available)
+    fStoreManager.initRepository(repositoryId, true);
+
+    String repoInfoCreatorClassName = (String) fSession.get(ConfigConstants.REPOSITORY_INFO_CREATOR_CLASS);
+    fStoreManager.initRepositoryInfo(repositoryId, repoInfoCreatorClassName);    
+
+    // initialize services
+    fRepositoryService = new RepositoryServiceImpl(fStoreManager);
+    fNavigationService = new NavigationServiceImpl(fStoreManager);
+    fObjectService = new ObjectServiceImpl(fStoreManager);
+    fVersioningService = new VersioningServiceImpl(fStoreManager, fObjectService);    
+  }
+
+  
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpi.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpiFactory.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpiFactory.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpiFactory.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpiFactory.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.opencmis.inmemory.clientprovider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.opencmis.client.provider.spi.CmisSpi;
+import org.apache.opencmis.client.provider.spi.CmisSpiFactory;
+import org.apache.opencmis.client.provider.spi.Session;
+
+/**
+ * Factory class for an in-memory SMIS SPI. For the in-memory implementation the 
+ * CMIS SPI creates one instance per session
+ * 
+ * @author Jens
+ *
+ */
+public class CmisInMemorySpiFactory implements CmisSpiFactory {
+
+  private static Map<Integer, CmisInMemorySpi> IN_MEM_SPIS = new HashMap<Integer, CmisInMemorySpi>();
+  public CmisSpi getSpiInstance(Session session) {
+    // we maintain one InMemory SPI for each session
+    
+    int sessionId = System.identityHashCode(session);
+    CmisInMemorySpi spi = IN_MEM_SPIS.get(sessionId);
+    if (null == spi) {
+      // does not yet exist, create one:
+      spi = new CmisInMemorySpi(session);
+      IN_MEM_SPIS.put(sessionId, spi);
+    }
+    return spi;
+  }
+
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/clientprovider/CmisInMemorySpiFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/AtomLinkInfoProvider.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/AtomLinkInfoProvider.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/AtomLinkInfoProvider.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/AtomLinkInfoProvider.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory.server;
+
+import java.util.List;
+
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectInFolderContainer;
+import org.apache.opencmis.commons.provider.ObjectInFolderData;
+import org.apache.opencmis.commons.provider.ObjectInFolderList;
+import org.apache.opencmis.commons.provider.ObjectList;
+import org.apache.opencmis.commons.provider.ObjectParentData;
+import org.apache.opencmis.inmemory.storedobj.api.Document;
+import org.apache.opencmis.inmemory.storedobj.api.ObjectStore;
+import org.apache.opencmis.inmemory.storedobj.api.StoreManager;
+import org.apache.opencmis.inmemory.storedobj.api.StoredObject;
+import org.apache.opencmis.inmemory.storedobj.api.Path;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+import org.apache.opencmis.server.spi.ObjectInfoImpl;
+
+/**
+ * For the Atom binding more information might be required than the result of a service call
+ * provides (mainly to fill all the links). This class fills the objectInfoHolder that was introduced
+ * for this purpose
+ *  
+ * @author Jens
+ *
+ */
+public class AtomLinkInfoProvider {
+  
+  private StoreManager fStoreManager;
+  
+  public AtomLinkInfoProvider(StoreManager storeManager) {
+    fStoreManager = storeManager;
+  }
+    
+  /**
+   * FillObjectInfoHolder object with required information needed for Atom binding for a single object
+   * 
+   * @param repositoryId
+   *          id of repository 
+   * @param objectId
+   *          object to retrieve information for
+   * @param objectInfos
+   *          Holder to fill with information
+   */
+  public void fillInformationForAtomLinks(String repositoryId, String objectId, ObjectInfoHolder objectInfos) {
+    if (null == objectInfos || null == objectId)
+      return;
+    
+    ObjectInfoImpl objInfo = new ObjectInfoImpl();
+    ObjectStore objectStore = fStoreManager.getObjectStore(repositoryId);
+    StoredObject so = objectStore.getObjectById(objectId);    
+    TypeDefinition typeDef = fStoreManager.getTypeById(repositoryId, so.getTypeId()).getTypeDefinition();
+    
+    // Fill all setters:
+    objInfo.setId(objectId);
+    objInfo.setName(so.getName());
+    objInfo.setCreatedBy(so.getCreatedBy()); //!
+    objInfo.setCreationDate(so.getCreatedAt()); //!
+    objInfo.setLastModificationDate(so.getModifiedAt());
+    objInfo.setTypeId(so.getTypeId());
+    objInfo.setBaseType(typeDef.getBaseId());
+    
+    // versioning information: currently only non-versioned documents supported by in-memory provider
+    objInfo.setIsCurrentVersion (true); 
+    objInfo.setHasVersionHistory(false);
+    objInfo.setWorkingCopyId(null);
+    objInfo.setWorkingCopyOriginalId(null);
+    
+    if (so instanceof Document) {
+      Document doc = ((Document)so);
+      objInfo.setHasContent(doc.getContent() != null);
+      objInfo.setContentType(doc.getContent() != null ? doc.getContent().getMimeType() : null);
+      objInfo.setFileName(doc.getContent() != null ? doc.getContent().getFilename() : null);
+    } else {
+      objInfo.setHasContent(false);
+      objInfo.setContentType(null);
+      objInfo.setFileName(null);
+    }
+    
+    // Filing
+    if (so instanceof Path) {
+      Path sop = ((Path)so);
+      objInfo.setHasParent(sop.getParent()!= null);
+    } else {
+      objInfo.setHasParent(false);      
+    }
+    
+    // Renditions, currently not supported by in-memory provider
+    objInfo.setRenditionInfos(null);
+    
+    // Relationships, currently not supported by in-memory provider
+    objInfo.setSupportsRelationships(false);
+    objInfo.setRelationshipSourceIds(null);
+    objInfo.setRelationshipTargetIds(null);
+    
+    // Policies, currently not supported by in-memory provider
+    objInfo.setSupportsPolicies(false);
+    
+    // ACLs, currently not supported by in-memory provider
+    objInfo.setHasAcl(false);
+    
+    objInfo.setSupportsDescendants(true);
+    objInfo.setSupportsFolderTree(true);
+    
+    objectInfos.addObjectInfo(objInfo);
+  }
+
+  /**
+   * FillObjectInfoHolder object with required information needed for Atom binding
+   * after a getChildren() call in navigation service 
+   * 
+   * @param repositoryId
+   *          id of repository 
+   * @param objectId
+   *          object to retrieve information for
+   * @param objectInfos
+   *          Holder to fill with information
+   * @param objList
+   *          result of getChildren call
+   */
+  public void fillInformationForAtomLinks(String repositoryId, String objectId,
+      ObjectInfoHolder objectInfos, ObjectInFolderList objList) {
+    
+    if (null == objectInfos || null == objList || null == objectId)
+      return;
+
+    // Fill object information for requested object
+    fillInformationForAtomLinks(repositoryId, objectId, objectInfos);
+    
+    // Fill object information for all children in result list
+    for (ObjectInFolderData object : objList.getObjects()) {
+      fillInformationForAtomLinks(repositoryId, object.getObject().getId(), objectInfos);
+    }
+  }
+  
+  /**
+   * FillObjectInfoHolder object with required information needed for Atom binding
+   * for an object list 
+   * 
+   * @param repositoryId
+   *          id of repository 
+   * @param objectId
+   *          object to retrieve information for
+   * @param objectInfos
+   *          Holder to fill with information
+   * @param objList
+   *          result of getChildren call
+   */
+  public void fillInformationForAtomLinks(String repositoryId, String objectId,
+      ObjectInfoHolder objectInfos, ObjectList objList) {
+   
+    if (null != objectId) {
+      // Fill object information for requested object
+      fillInformationForAtomLinks(repositoryId, objectId, objectInfos);
+    }
+    
+    if (null != objList && null != objList.getObjects()) {
+      // Fill object information for all children in result list
+      List<ObjectData> listObjects = objList.getObjects();
+      if (null != listObjects)
+        for (ObjectData object : listObjects) {
+          fillInformationForAtomLinks(repositoryId, object.getId(), objectInfos);
+        }    
+    }
+    
+  }
+
+  /**
+   * FillObjectInfoHolder object with required information needed for Atom binding
+   * for an ObjectInFolderContainer 
+   * 
+   * @param repositoryId
+   *          id of repository 
+   * @param objectId
+   *          object to retrieve information for
+   * @param objectInfos
+   *          Holder to fill with information
+   * @param objList
+   *          result of getChildren call
+   */
+  private void fillInformationForAtomLinks(String repositoryId, 
+      ObjectInfoHolder objectInfos, ObjectInFolderContainer oifc) {
+   
+    if (null == objectInfos || null == oifc)
+      return;
+
+    // Fill object information for all elements in result list
+    fillInformationForAtomLinks(repositoryId, objectInfos, oifc.getObject());
+    
+    if (null!=oifc.getChildren())
+      for (ObjectInFolderContainer object : oifc.getChildren()) {
+        // call recursively
+          fillInformationForAtomLinks(repositoryId, objectInfos, object);
+      }    
+  }
+
+  /**
+   * FillObjectInfoHolder object with required information needed for Atom binding
+   * for a list with ObjectInFolderContainers 
+   * 
+   * @param repositoryId
+   *          id of repository 
+   * @param objectId
+   *          object to retrieve information for
+   * @param objectInfos
+   *          Holder to fill with information
+   * @param oifcList
+   *          result of getDescendants call
+   */
+  public void fillInformationForAtomLinks(String repositoryId, String objectId,
+      ObjectInfoHolder objectInfos, List<ObjectInFolderContainer> oifcList) {
+   
+    if (null == objectInfos || null == oifcList || null == objectId)
+      return;
+
+    // Fill object information for requested object
+    fillInformationForAtomLinks(repositoryId, objectId, objectInfos);
+    
+    for (ObjectInFolderContainer object : oifcList) {
+      fillInformationForAtomLinks(repositoryId, objectInfos, object);
+    }    
+  }
+  
+  private void fillInformationForAtomLinks(String repositoryId,
+      ObjectInfoHolder objectInfos, ObjectInFolderData object) {
+    
+    fillInformationForAtomLinks(repositoryId, object.getObject().getId(), objectInfos);    
+  }
+
+  /**
+   * FillObjectInfoHolder object with required information needed for Atom binding
+   * for a list with ObjectParentData objects 
+   * 
+   * @param repositoryId
+   *          id of repository 
+   * @param objectId
+   *          object to retrieve information for
+   * @param objectInfos
+   *          Holder to fill with information
+   * @param objParents
+   *          result of getObjectParents call
+   */
+  public void fillInformationForAtomLinksGetParents(String repositoryId, String objectId,
+      ObjectInfoHolder objectInfos, List<ObjectParentData> objParents) {
+    
+    if (null == objectInfos || null == objParents || null == objectId)
+      return;
+
+    // Fill object information for requested object
+    fillInformationForAtomLinks(repositoryId, objectId, objectInfos);
+    
+    for (ObjectParentData object : objParents) {
+      fillInformationForAtomLinks(repositoryId, object.getObject().getId(), objectInfos);
+    }        
+  }
+  
+  
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/AtomLinkInfoProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/CallContextConfigReader.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/CallContextConfigReader.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/CallContextConfigReader.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/CallContextConfigReader.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.opencmis.inmemory.server;
+
+import org.apache.opencmis.inmemory.ConfigMap;
+import org.apache.opencmis.server.spi.CallContext;
+
+/**
+ * Implementation of interface Config map to read parameters from a request context 
+ * of a server session
+ * 
+ * @author jens
+ *
+ */
+public class CallContextConfigReader implements ConfigMap {
+
+  private CallContext fCallCtx;
+
+  CallContextConfigReader(CallContext callCtx) {
+    fCallCtx = callCtx;
+  }
+  
+  public String get(String paramName) {
+    return fCallCtx.get(paramName);
+  }
+
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/CallContextConfigReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryDiscoveryService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryDiscoveryService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryDiscoveryService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryDiscoveryService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory.server;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.enums.TypeOfChanges;
+import org.apache.opencmis.commons.impl.dataobjects.ChangeEventInfoDataImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectDataImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ObjectListImpl;
+import org.apache.opencmis.commons.provider.Holder;
+import org.apache.opencmis.commons.provider.NavigationService;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectInFolderContainer;
+import org.apache.opencmis.commons.provider.ObjectList;
+import org.apache.opencmis.commons.provider.RepositoryInfoData;
+import org.apache.opencmis.commons.provider.RepositoryService;
+import org.apache.opencmis.inmemory.storedobj.api.StoreManager;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisDiscoveryService;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+public class InMemoryDiscoveryService implements CmisDiscoveryService {
+
+  private StoreManager fStoreManager;
+  AtomLinkInfoProvider fAtomLinkProvider;
+  NavigationService fNavigationService; // real implementation of the service
+  RepositoryService fRepositoryService; 
+  
+  public InMemoryDiscoveryService(StoreManager storeManager, RepositoryService repSvc, NavigationService navSvc) {
+    fStoreManager = storeManager;
+    fAtomLinkProvider = new AtomLinkInfoProvider(fStoreManager);
+    fNavigationService  = navSvc;
+    fRepositoryService = repSvc;
+  }
+
+  public ObjectList getContentChanges(CallContext context, String repositoryId,
+      Holder<String> changeLogToken, Boolean includeProperties, String filter,
+      Boolean includePolicyIds, Boolean includeAcl, BigInteger maxItems, ExtensionsData extension,
+      ObjectInfoHolder objectInfos) {
+    // dummy implementation using hard coded values
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    RepositoryInfoData rep = fRepositoryService.getRepositoryInfo(repositoryId, null);
+    String rootFolderId = rep.getRootFolderId();
+
+    ObjectListImpl objList = new ObjectListImpl();
+    List<ObjectInFolderContainer> tempRes = fNavigationService.getDescendants(repositoryId,
+        rootFolderId, BigInteger.valueOf(3), filter, false, IncludeRelationships.NONE, null, false,
+        extension);
+    
+    // convert ObjectInFolderContainerList to objectList
+    List<ObjectData> lod = new ArrayList<ObjectData>();
+    for (ObjectInFolderContainer obj : tempRes) {
+      convertList(lod, obj);
+    }
+    objList.setObjects(lod);
+    objList.setNumItems(BigInteger.valueOf(lod.size()));
+    
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, null, objectInfos, objList);
+    return objList;
+  }
+  
+  private void convertList(List<ObjectData> lod, ObjectInFolderContainer obj) {
+    lod.add(obj.getObject().getObject());
+    // add dummy event info
+    ObjectData oif = obj.getObject().getObject();
+    ObjectDataImpl oifImpl = (ObjectDataImpl) oif;
+    ChangeEventInfoDataImpl changeEventInfo = new ChangeEventInfoDataImpl();
+    changeEventInfo.setTypeOfChanges(TypeOfChanges.UPDATED);
+    changeEventInfo.setChangeTime(new GregorianCalendar());
+    oifImpl.setChangeEventInfo(changeEventInfo );
+    if (null != obj.getChildren()) {
+      for (ObjectInFolderContainer oifc : obj.getChildren()) {
+        convertList(lod, oifc);
+      }
+    }
+  }
+
+  public ObjectList query(CallContext context, String repositoryId, String statement,
+      Boolean searchAllVersions, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter, BigInteger maxItems,
+      BigInteger skipCount, ExtensionsData extension) {
+    // dummy implementation using hard coded values
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    // use descendants of root folder as result
+    RepositoryInfoData rep = fRepositoryService.getRepositoryInfo(repositoryId, null);
+    String rootFolderId = rep.getRootFolderId();
+    ObjectListImpl objList = new ObjectListImpl();
+    List<ObjectInFolderContainer> tempRes = fNavigationService.getDescendants(repositoryId,
+        rootFolderId, BigInteger.valueOf(3), "*", includeAllowableActions, includeRelationships,
+        renditionFilter, false, extension);
+    
+    // convert ObjectInFolderContainerList to objectList
+    List<ObjectData> lod = new ArrayList<ObjectData>();
+    for (ObjectInFolderContainer obj : tempRes) {
+      convertList(lod, obj);
+    }
+    objList.setObjects(lod);
+    objList.setNumItems(BigInteger.valueOf(lod.size()));
+
+    return objList;
+  }
+
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryDiscoveryService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryNavigationService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryNavigationService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryNavigationService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryNavigationService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory.server;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.provider.NavigationService;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectInFolderContainer;
+import org.apache.opencmis.commons.provider.ObjectInFolderList;
+import org.apache.opencmis.commons.provider.ObjectList;
+import org.apache.opencmis.commons.provider.ObjectParentData;
+import org.apache.opencmis.inmemory.NavigationServiceImpl;
+import org.apache.opencmis.inmemory.storedobj.api.StoreManager;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisNavigationService;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+public class InMemoryNavigationService implements CmisNavigationService  {
+  StoreManager fStoreManager;
+  NavigationService fNavigationService; // real implementation of the service
+  CallContextConfigReader fCfgReader = null;
+  AtomLinkInfoProvider fAtomLinkProvider;
+  
+  InMemoryNavigationService(StoreManager storeManager) {
+    fStoreManager = storeManager;
+    fNavigationService = new NavigationServiceImpl(fStoreManager);
+    fAtomLinkProvider = new AtomLinkInfoProvider(fStoreManager);
+  }
+
+  public ObjectList getCheckedOutDocs(CallContext context, String repositoryId, String folderId,
+      String filter, String orderBy, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter, BigInteger maxItems,
+      BigInteger skipCount, ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+    
+    ObjectList res = fNavigationService.getCheckedOutDocs(repositoryId, folderId, filter, orderBy, includeAllowableActions, includeRelationships, renditionFilter, maxItems, skipCount, extension);
+    
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, folderId, objectInfos, res);
+
+    return res;
+  }
+
+  public ObjectInFolderList getChildren(CallContext context, String repositoryId, String folderId,
+      String filter, String orderBy, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter,
+      Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount,
+      ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+    
+    ObjectInFolderList res = fNavigationService.getChildren(repositoryId, folderId, filter, orderBy, includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, maxItems, skipCount, extension);
+    
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, folderId, objectInfos, res);
+    
+    return res;
+  }
+  
+
+  public List<ObjectInFolderContainer> getDescendants(CallContext context, String repositoryId,
+      String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter,
+      Boolean includePathSegment, ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    List<ObjectInFolderContainer> res = fNavigationService.getDescendants(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, extension);
+    
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, folderId, objectInfos, res);
+
+    return res;
+  }
+
+  public ObjectData getFolderParent(CallContext context, String repositoryId, String folderId,
+      String filter, ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    ObjectData res = fNavigationService.getFolderParent(repositoryId, folderId, filter, extension);
+
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, folderId, objectInfos);
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, res.getId(), objectInfos);
+
+    return res;
+  }
+
+  public List<ObjectInFolderContainer> getFolderTree(CallContext context, String repositoryId,
+      String folderId, BigInteger depth, String filter, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter,
+      Boolean includePathSegment, ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    List<ObjectInFolderContainer> res = fNavigationService.getFolderTree(repositoryId, folderId, depth, filter, includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, extension);
+    
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, folderId, objectInfos, res);
+    
+    return res;
+  }
+
+  public List<ObjectParentData> getObjectParents(CallContext context, String repositoryId,
+      String objectId, String filter, Boolean includeAllowableActions,
+      IncludeRelationships includeRelationships, String renditionFilter,
+      Boolean includeRelativePathSegment, ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    List<ObjectParentData> res = fNavigationService.getObjectParents(repositoryId, objectId, filter, includeAllowableActions, includeRelationships, renditionFilter, includeRelativePathSegment, extension);
+    
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinksGetParents(repositoryId, objectId, objectInfos, res);
+
+    return res;
+  }
+
+  public NavigationService getNavigationService() {
+    return fNavigationService;
+  }
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryNavigationService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryObjectService.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryObjectService.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryObjectService.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryObjectService.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,352 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.opencmis.inmemory.server;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.api.ExtensionsData;
+import org.apache.opencmis.commons.api.TypeDefinitionContainer;
+import org.apache.opencmis.commons.enums.BaseObjectTypeIds;
+import org.apache.opencmis.commons.enums.IncludeRelationships;
+import org.apache.opencmis.commons.enums.UnfileObjects;
+import org.apache.opencmis.commons.enums.VersioningState;
+import org.apache.opencmis.commons.provider.AccessControlList;
+import org.apache.opencmis.commons.provider.AllowableActionsData;
+import org.apache.opencmis.commons.provider.ContentStreamData;
+import org.apache.opencmis.commons.provider.FailedToDeleteData;
+import org.apache.opencmis.commons.provider.Holder;
+import org.apache.opencmis.commons.provider.ObjectData;
+import org.apache.opencmis.commons.provider.ObjectService;
+import org.apache.opencmis.commons.provider.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.commons.provider.RenditionData;
+import org.apache.opencmis.inmemory.ObjectServiceImpl;
+import org.apache.opencmis.inmemory.storedobj.api.StoreManager;
+import org.apache.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
+import org.apache.opencmis.inmemory.types.InMemoryFolderTypeDefinition;
+import org.apache.opencmis.inmemory.types.InMemoryPolicyTypeDefinition;
+import org.apache.opencmis.inmemory.types.InMemoryRelationshipTypeDefinition;
+import org.apache.opencmis.server.spi.CallContext;
+import org.apache.opencmis.server.spi.CmisObjectService;
+import org.apache.opencmis.server.spi.ObjectInfoHolder;
+
+public class InMemoryObjectService implements CmisObjectService {
+  private static final Log LOG = LogFactory.getLog(ServiceFactory.class.getName());
+
+  StoreManager fStoreManager;
+  ObjectService fObjectService; // real implementation of the service
+  CallContextConfigReader fCfgReader = null;
+  AtomLinkInfoProvider fAtomLinkProvider;
+
+  InMemoryObjectService(StoreManager storeManager) {
+    fStoreManager = storeManager;
+    fObjectService = new ObjectServiceImpl(fStoreManager);
+    fAtomLinkProvider = new AtomLinkInfoProvider(fStoreManager);
+  }
+  
+  ObjectService getObjectService() {
+    return fObjectService;
+  }
+  
+  public String createDocument(CallContext context, String repositoryId, PropertiesData properties,
+      String folderId, ContentStreamData contentStream, VersioningState versioningState,
+      List<String> policies, AccessControlList addAces, AccessControlList removeAces,
+      ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.createDocument(repositoryId, properties, folderId, contentStream,
+        versioningState, policies, addAces, removeAces, extension);
+  }
+
+  public String createDocumentFromSource(CallContext context, String repositoryId, String sourceId,
+      PropertiesData properties, String folderId, VersioningState versioningState,
+      List<String> policies, AccessControlList addAces, AccessControlList removeAces,
+      ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.createDocumentFromSource(repositoryId, sourceId, properties, folderId,
+        versioningState, policies, addAces, removeAces, extension);
+  }
+
+  public String createFolder(CallContext context, String repositoryId, PropertiesData properties,
+      String folderId, List<String> policies, AccessControlList addAces,
+      AccessControlList removeAces, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.createFolder(repositoryId, properties, folderId, policies, addAces,
+        removeAces, extension);
+  }
+
+  public String createPolicy(CallContext context, String repositoryId, PropertiesData properties,
+      String folderId, List<String> policies, AccessControlList addAces,
+      AccessControlList removeAces, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.createPolicy(repositoryId, properties, folderId, policies, addAces,
+        removeAces, extension);
+  }
+
+  public String createRelationship(CallContext context, String repositoryId,
+      PropertiesData properties, List<String> policies, AccessControlList addAces,
+      AccessControlList removeAces, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.createRelationship(repositoryId, properties, policies, addAces,
+        removeAces, extension);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.opencmis.server.spi.CmisObjectService#create(org.apache.opencmis.server.spi.CallContext, java.lang.String, org.apache.opencmis.client.provider.PropertiesData, java.lang.String, org.apache.opencmis.client.provider.ContentStreamData, org.apache.opencmis.commons.enums.VersioningState, org.apache.opencmis.client.provider.ExtensionsData, org.apache.opencmis.server.spi.ObjectInfoHolder)
+   * 
+   * An additional create call compared to the ObjectService from the CMIS spec.
+   * This one is needed because the Atom binding in the server implementation does 
+   * not know what kind of object needs to be created. Also the ObjectInfoHolder needs
+   * to be filled.
+   * 
+   */
+  public ObjectData create(CallContext context, String repositoryId, PropertiesData properties,
+      String folderId, ContentStreamData contentStream, VersioningState versioningState, List<String> policies,
+      ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+    
+    if (null==properties || null==properties.getProperties())
+        throw new RuntimeException("Cannot create object, without properties.");
+
+    // Find out what kind of object needs to be created
+    PropertyData<String> pd = (PropertyData<String>) properties.getProperties().get(PropertyIds.CMIS_OBJECT_TYPE_ID);
+    String typeId = pd==null ? null : pd.getFirstValue(); 
+    if (null==typeId)
+      throw new RuntimeException("Cannot create object, without a type (no property with id CMIS_OBJECT_TYPE_ID).");
+    
+    TypeDefinitionContainer typeDefC = fStoreManager.getTypeById(repositoryId, typeId);
+    if (typeDefC == null)
+      throw new RuntimeException("Cannot create object, a type with id " + typeId + " is unknown");
+
+    // check if the given type is a document type
+    BaseObjectTypeIds typeBaseId = typeDefC.getTypeDefinition().getBaseId();
+    String resId = null;
+    if (typeBaseId.equals(InMemoryDocumentTypeDefinition.getRootDocumentType().getBaseId())) {
+      resId = createDocument(context, repositoryId, properties, folderId, contentStream, versioningState, 
+          null, null, null, null);
+    } else if (typeBaseId.equals(InMemoryFolderTypeDefinition.getRootFolderType().getBaseId())) {
+      resId = createFolder(context, repositoryId, properties, folderId, null, null, null, null);
+    } else if (typeBaseId.equals(InMemoryPolicyTypeDefinition.getRootPolicyType().getBaseId())) {
+      resId = createPolicy(context, repositoryId, properties, folderId, null, null, null, null);
+    } else if (typeBaseId.equals(InMemoryRelationshipTypeDefinition.getRootRelationshipType().getBaseId())) {
+      resId = createRelationship(context, repositoryId, properties,  null, null, null, null);
+    } else
+      LOG.error("The type contains an unknown base object id, object can't be created");
+
+    // Make a call to getObject to convert the resulting id into an ObjectData
+    ObjectData res = null;
+    if (null!=resId) {
+      res = getObject(context, repositoryId, resId, "*", false, IncludeRelationships.NONE,
+          null, false, false, extension, objectInfos);
+    }
+    
+    return res;
+  }
+  
+  public void deleteContentStream(CallContext context, String repositoryId,
+      Holder<String> objectId, Holder<String> changeToken, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    fObjectService.deleteContentStream(repositoryId, objectId, changeToken, extension);
+  }
+
+  public void deleteObjectOrCancelCheckOut(CallContext context, String repositoryId, String objectId,
+      Boolean allVersions, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    fObjectService.deleteObject(repositoryId, objectId, allVersions, extension);
+  }
+
+  public FailedToDeleteData deleteTree(CallContext context, String repositoryId, String folderId,
+      Boolean allVersions, UnfileObjects unfileObjects, Boolean continueOnFailure,
+      ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.deleteTree(repositoryId, folderId, allVersions, unfileObjects,
+        continueOnFailure, extension);
+  }
+
+  public AllowableActionsData getAllowableActions(CallContext context, String repositoryId,
+      String objectId, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.getAllowableActions(repositoryId, objectId, extension);
+  }
+
+  public ContentStreamData getContentStream(CallContext context, String repositoryId,
+      String objectId, String streamId, BigInteger offset, BigInteger length,
+      ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.getContentStream(repositoryId, objectId, streamId, offset, length,
+        extension);
+  }
+
+  public ObjectData getObject(CallContext context, String repositoryId, String objectId,
+      String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includePolicyIds, Boolean includeAcl,
+      ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    ObjectData res = fObjectService.getObject(repositoryId, objectId, filter,
+        includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds,
+        includeAcl, extension);
+
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, objectId, objectInfos);
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, res == null ? null : res.getId(),
+        objectInfos);
+
+    return res;
+  }
+
+  public ObjectData getObjectByPath(CallContext context, String repositoryId, String path,
+      String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships,
+      String renditionFilter, Boolean includePolicyIds, Boolean includeAcl,
+      ExtensionsData extension, ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    ObjectData res = fObjectService.getObjectByPath(repositoryId, path, filter,
+        includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds,
+        includeAcl, extension);
+
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, res == null ? null : res.getId(),
+        objectInfos);
+
+    return res;
+  }
+
+  public PropertiesData getProperties(CallContext context, String repositoryId, String objectId,
+      String filter, ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    PropertiesData res = fObjectService.getProperties(repositoryId, objectId, filter, extension);
+
+    return res;
+  }
+
+  public List<RenditionData> getRenditions(CallContext context, String repositoryId,
+      String objectId, String renditionFilter, BigInteger maxItems, BigInteger skipCount,
+      ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    return fObjectService.getRenditions(repositoryId, objectId, renditionFilter, maxItems,
+        skipCount, extension);
+  }
+
+  public ObjectData moveObject(CallContext context, String repositoryId, Holder<String> objectId,
+      String targetFolderId, String sourceFolderId, ExtensionsData extension,
+      ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    fObjectService.moveObject(repositoryId, objectId, targetFolderId, sourceFolderId, extension);
+
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, objectId.getValue(), objectInfos);
+  
+    // Make a call to getObject afterwards to be able to provide all the required information
+    ObjectData res = null;
+    if (null != objectId.getValue()) {
+      res = getObject(context, repositoryId, objectId.getValue(), "*", false, IncludeRelationships.NONE,
+          null, false, false, extension, objectInfos);
+    }
+    return res;
+  }
+
+  public void setContentStream(CallContext context, String repositoryId, Holder<String> objectId,
+      Boolean overwriteFlag, Holder<String> changeToken, ContentStreamData contentStream,
+      ExtensionsData extension) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    fObjectService.setContentStream(repositoryId, objectId, overwriteFlag, changeToken,
+        contentStream, extension);
+  }
+
+  public ObjectData updateProperties(CallContext context, String repositoryId, Holder<String> objectId,
+      Holder<String> changeToken, PropertiesData properties, AccessControlList acl, ExtensionsData extension,
+      ObjectInfoHolder objectInfos) {
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    RuntimeContext.getRuntimeConfig().attachCfg(new CallContextConfigReader(context));
+
+    if (null!=properties)
+      fObjectService.updateProperties(repositoryId, objectId, changeToken, properties, extension);
+    
+    if (null != acl) {
+      LOG.warn("Setting ACLs is currently not supported by this implementation, acl is ignored");
+      // if implemented add this call:
+      // fAclService.appyAcl(context, repositoryId, acl, null, AclPropagation.OBJECTONLY, extension);
+    }
+
+    // To be able to provide all Atom links in the response we need additional information:
+    fAtomLinkProvider.fillInformationForAtomLinks(repositoryId, objectId.getValue(), objectInfos);
+
+    // Make a call to getObject afterwards to be able to provide all the required information
+    ObjectData res = null;
+    if (null != objectId.getValue()) {
+      res = getObject(context, repositoryId, objectId.getValue(), "*", false, IncludeRelationships.NONE,
+          null, false, false, extension, objectInfos);
+    }
+    return res;
+  }
+
+}

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/main/java/org/apache/opencmis/inmemory/server/InMemoryObjectService.java
------------------------------------------------------------------------------
    svn:eol-style = native