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 [33/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/test/java/org/apache/opencmis/inmemory/TypeValidationTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/TypeValidationTest.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/TypeValidationTest.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/TypeValidationTest.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,722 @@
+/*
+ * 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.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.api.Choice;
+import org.apache.opencmis.commons.api.PropertyDefinition;
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.enums.Cardinality;
+import org.apache.opencmis.commons.exceptions.CmisConstraintException;
+import org.apache.opencmis.commons.impl.dataobjects.ChoiceImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyBooleanDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyHtmlDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyIdDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.ProviderObjectFactoryImpl;
+import org.apache.opencmis.commons.provider.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.commons.provider.ProviderObjectFactory;
+import org.apache.opencmis.inmemory.TypeManager;
+import org.apache.opencmis.inmemory.TypeValidator;
+import org.apache.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
+import org.apache.opencmis.inmemory.types.PropertyCreationHelper;
+
+/**
+ * @author Jens
+ */
+public class TypeValidationTest extends TestCase {
+  private static final String MY_DOC_TYPE = "MyDocType1";
+  private static final String STRING_DOC_TYPE = "StringDocType";
+  private static final String STRING_PROP_TYPE = "StringProp";
+  private static final String INT_DOC_TYPE = "IntegerDocType";
+  private static final String INT_PROP_TYPE = "IntegerProp";
+  private static final String DECIMAL_DOC_TYPE = "DecimalDocType";
+  private static final String DECIMAL_PROP_TYPE = "DecimalProp";
+  private static final String PICK_LIST_DOC_TYPE = "PickListDocType";
+  private static final String PICK_LIST_PROP_DEF = "PickListProp";
+  private static final String DOC_TYPE_SUPER = "SuperDocType";
+  private static final String DOC_TYPE_SUB = "SubDocType";
+  private static final String STRING_PROP_TYPE_SUPER = "StringPropSuper";
+  private static final String STRING_PROP_TYPE_SUB = "StringPropSub";
+  private static final ProviderObjectFactory FACTORY = new ProviderObjectFactoryImpl();
+  
+  protected void setUp() throws Exception {
+    super.setUp();
+  }
+
+  protected void tearDown() throws Exception {
+    super.tearDown();
+  }
+  
+  private List<PropertyData<?>> createPropertiesWithNameAndTypeId(String typeId) {
+    List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+    properties.add(FACTORY.createPropertyIdData(PropertyIds.CMIS_NAME, "Document_1"));
+    properties.add(FACTORY.createPropertyIdData(PropertyIds.CMIS_OBJECT_TYPE_ID, typeId));
+    return properties;
+  }
+
+  public void testMandatoryPropertyValidation() {
+    // create properties in the same way as we would pass them to a createDocument call
+    // of the ObjectService
+
+    List<PropertyData<?>> properties =  createPropertiesWithNameAndTypeId(MY_DOC_TYPE);
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+    
+    // validate properties according to type
+    TypeDefinition typeDef = buildMyType();
+
+    // try missing mandatory Boolean property
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if mandatory property is missing.");
+    }
+    catch (CmisConstraintException e) {
+      assertTrue(e.getMessage().contains("mandatory properties are missing"));
+    }
+
+    // add missing mandatory Boolean property and try again
+    properties.add(FACTORY.createPropertyBooleanData("BooleanProp", true));
+    props = FACTORY.createPropertiesData(properties);
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (CmisConstraintException e) {
+      fail("TypeValidator should not throw CMISConstraintException if mandatory property is present.");
+    }
+  }
+
+  public void testStringPropertyValidation() {
+    TypeDefinition typeDef = buildTypeWithStringProp(); // we only have one
+
+    List<PropertyData<?>> properties =  createPropertiesWithNameAndTypeId(STRING_DOC_TYPE);
+    properties.add(FACTORY.createPropertyStringData(STRING_PROP_TYPE,
+        "A String property with quite a long value exceeding the max. length."));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try exceeding string length
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if max string length is exceeded");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties =  createPropertiesWithNameAndTypeId(STRING_DOC_TYPE);    
+    properties.add(FACTORY.createPropertyStringData(STRING_PROP_TYPE,"short val"));
+    props = FACTORY.createPropertiesData(properties);
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw exception if string length is valid" + e);
+    }
+  }
+
+  public void testIntegerPropertyValidation() {
+
+    TypeDefinition typeDef = buildTypeWithIntegerProp();
+    
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(INT_DOC_TYPE);
+    properties.add(FACTORY.createPropertyIntegerData(INT_PROP_TYPE, BigInteger.valueOf(-100))); // try wrong value
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try exceeding string length
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if integer value is out of range");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(INT_DOC_TYPE);    
+    properties.add(FACTORY.createPropertyIntegerData(INT_PROP_TYPE, BigInteger.valueOf(1))); // try correct value
+    props = FACTORY.createPropertiesData(properties);
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw exception if integer value is valid. " + e);
+    }
+
+  }
+
+  public void testDecimalPropertyValidation() {
+    TypeDefinition typeDef = buildTypeWithDecimalProp();
+
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(DECIMAL_DOC_TYPE);
+    properties.add(FACTORY.createPropertyDecimalData(DECIMAL_PROP_TYPE, BigDecimal.valueOf(-11.11)));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try exceeding string length
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if decimal value is out of range");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(DECIMAL_DOC_TYPE);
+    properties.add(FACTORY.createPropertyDecimalData(DECIMAL_PROP_TYPE, BigDecimal.valueOf(1.23)));
+    props = FACTORY.createPropertiesData(properties);
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw exception if decimal value is valid. " + e);
+    }
+  }
+
+  public void testPickListValidationSingleValue() {
+    TypeDefinition typeDef =buildTypeWithPickList(Cardinality.SINGLE);
+
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, "pink"));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try wrong value
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if choice value is not in list of valid values");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, "blue"));
+    props = FACTORY.createPropertiesData(properties);
+
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw CMISConstraintException if choice value is in list of valid values"
+          + e);
+    }
+  }
+
+  public void testPickListValidationMultiValue() {
+    TypeDefinition typeDef =buildTypeWithPickList(Cardinality.MULTI);
+
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    List<String> propValues = new ArrayList<String>();
+    propValues.add("red");
+    propValues.add("pink");    
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, propValues));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try wrong value
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if choice value is not in list of valid values");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    propValues = new ArrayList<String>();
+    propValues.add("red");
+    propValues.add("green");
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, propValues));
+    props = FACTORY.createPropertiesData(properties);
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw CMISConstraintException if choice value is in list of valid values"
+          + e);
+    }
+  }
+
+  public void testPickListValidationMultiUsingMultipleValueLists() {
+    TypeDefinition typeDef = buildTypeWithMultiPickList();
+
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    List<String> propValues = new ArrayList<String>();
+    propValues.add("red");
+    propValues.add("green");
+    propValues.add("pink");    
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, propValues));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try wrong value
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if choice value is not in list of valid values");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    propValues = new ArrayList<String>();
+    propValues.add("red");
+    propValues.add("green");
+    propValues.add("blue");
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, propValues));
+    props = FACTORY.createPropertiesData(properties);
+
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw CMISConstraintException if choice value is in list of valid values"
+          + e);
+    }
+  }
+
+  public void testHierachicalPickListValidationSingleValue() {
+    TypeDefinition typeDef = buildTypeWithHierachicalPickList(Cardinality.SINGLE);
+
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, "frankfurt"));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try wrong value
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if choice value is not in list of valid values");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, "munich"));
+    props = FACTORY.createPropertiesData(properties);
+
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw CMISConstraintException if choice value is in list of valid values"
+          + e);
+    }
+  }
+
+  public void testHierachicalPickListValidationMultiValue() {
+    TypeDefinition typeDef = buildTypeWithHierachicalPickList(Cardinality.MULTI);
+
+    List<PropertyData<?>> properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    List<String> propValues = new ArrayList<String>();
+    propValues.add("stuttgart");
+    propValues.add("hintertupfingen");
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, propValues));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try wrong value
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+      fail("TypeValidator should throw CMISConstraintException if choice value is not in list of valid values");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties = createPropertiesWithNameAndTypeId(PICK_LIST_DOC_TYPE);
+    propValues = new ArrayList<String>();
+    propValues.add("munich");
+    propValues.add("walldorf");
+    properties.add(FACTORY.createPropertyStringData(PICK_LIST_PROP_DEF, propValues));
+    props = FACTORY.createPropertiesData(properties);
+
+    try {
+      TypeValidator.validateProperties(typeDef, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw CMISConstraintException if choice value is in list of valid values"
+          + e);
+    }
+  }
+
+  public void testInheritedPropertyValidation() {
+    TypeManager tm = buildInheritedTypes();
+    TypeDefinition superType = tm.getTypeById(DOC_TYPE_SUPER).getTypeDefinition();
+    TypeDefinition subType = tm.getTypeById(DOC_TYPE_SUB).getTypeDefinition();;
+    
+    List<PropertyData<?>> properties =  createPropertiesWithNameAndTypeId(DOC_TYPE_SUB);
+    properties.add(FACTORY.createPropertyStringData(STRING_PROP_TYPE_SUB,
+        "A String property with quite a long value exceeding the max. length."));
+    PropertiesData props = FACTORY.createPropertiesData(properties);
+
+    // try exceeding string length on org property
+    try {
+      TypeValidator.validateProperties(superType, props, true);
+      fail("TypeValidator should throw CMISConstraintException if max string length is exceeded");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    // try exceeding string length on inherited property
+    properties =  createPropertiesWithNameAndTypeId(DOC_TYPE_SUB);
+    properties.add(FACTORY.createPropertyStringData(STRING_PROP_TYPE_SUPER,
+        "A String property with quite a long value exceeding the max. length."));
+    props = FACTORY.createPropertiesData(properties);
+
+    // try exceeding string length
+    try {
+      TypeValidator.validateProperties(subType, props, true);
+      fail("TypeValidator should throw CMISConstraintException if max string length is exceeded");
+    }
+    catch (Exception e) {
+      assertTrue(e instanceof CmisConstraintException);
+    }
+
+    properties =  createPropertiesWithNameAndTypeId(DOC_TYPE_SUB);    
+    properties.add(FACTORY.createPropertyStringData(STRING_PROP_TYPE_SUPER, "super val"));
+    properties.add(FACTORY.createPropertyStringData(STRING_PROP_TYPE_SUB, "sub val"));
+    props = FACTORY.createPropertiesData(properties);
+    try {
+      TypeValidator.validateProperties(subType, props, true);
+    }
+    catch (Exception e) {
+      fail("TypeValidator should not throw exception if string length is valid" + e);
+    }
+  }
+
+  /**
+   * create sample type
+   * 
+   * @return type definition of sample type
+   */
+  private static InMemoryDocumentTypeDefinition buildMyType() {
+    // always add CMIS default types
+
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(MY_DOC_TYPE,
+        "Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    // create a boolean property definition
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+
+    PropertyDefinition<Boolean> prop = PropertyCreationHelper.createBooleanDefinition(
+        "BooleanProp", "Sample Boolean Property");
+    ((PropertyBooleanDefinitionImpl) prop).setIsRequired(true);
+    propertyDefinitions.put(prop.getId(), prop);
+
+    prop = PropertyCreationHelper.createBooleanMultiDefinition("BooleanPropMV",
+        "Sample Boolean multi-value Property");
+    propertyDefinitions.put(prop.getId(), prop);
+
+    PropertyDateTimeDefinitionImpl prop2 = PropertyCreationHelper.createDateTimeDefinition(
+        "DateTimeProp", "Sample DateTime Property");
+    propertyDefinitions.put(prop2.getId(), prop2);
+
+    prop2 = PropertyCreationHelper.createDateTimeMultiDefinition("DateTimePropMV",
+        "Sample DateTime multi-value Property");
+    propertyDefinitions.put(prop2.getId(), prop2);
+
+    PropertyDecimalDefinitionImpl prop3 = PropertyCreationHelper.createDecimalDefinition(
+        "DecimalProp", "Sample Decimal Property");
+    propertyDefinitions.put(prop3.getId(), prop3);
+
+    prop3 = PropertyCreationHelper.createDecimalDefinition("DecimalPropMV",
+        "Sample Decimal multi-value Property");
+    propertyDefinitions.put(prop3.getId(), prop3);
+
+    PropertyHtmlDefinitionImpl prop4 = PropertyCreationHelper.createHtmlDefinition("HtmlProp",
+        "Sample Html Property");
+    propertyDefinitions.put(prop4.getId(), prop4);
+
+    prop4 = PropertyCreationHelper.createHtmlDefinition("HtmlPropMV",
+        "Sample Html multi-value Property");
+    propertyDefinitions.put(prop4.getId(), prop4);
+
+    PropertyIdDefinitionImpl prop5 = PropertyCreationHelper.createIdDefinition("IdProp",
+        "Sample Id Property");
+    propertyDefinitions.put(prop5.getId(), prop5);
+
+    prop5 = PropertyCreationHelper.createIdDefinition("IdPropMV",
+        "Sample Id Html multi-value Property");
+    propertyDefinitions.put(prop5.getId(), prop5);
+
+    PropertyIntegerDefinitionImpl prop6 = PropertyCreationHelper.createIntegerDefinition(
+        "IntProp", "Sample Int Property");
+    propertyDefinitions.put(prop6.getId(), prop6);
+
+    prop6 = PropertyCreationHelper.createIntegerDefinition("IntPropMV",
+        "Sample Int multi-value Property");
+    propertyDefinitions.put(prop6.getId(), prop6);
+
+    PropertyStringDefinitionImpl prop7 = PropertyCreationHelper.createStringDefinition(
+        "StringProp", "Sample String Property");
+    propertyDefinitions.put(prop7.getId(), prop7);
+
+    PropertyUriDefinitionImpl prop8 = PropertyCreationHelper.createUriDefinition("UriProp",
+        "Sample Uri Property");
+    propertyDefinitions.put(prop8.getId(), prop8);
+
+    prop8 = PropertyCreationHelper.createUriDefinition("UriPropMV",
+        "Sample Uri multi-value Property");
+    propertyDefinitions.put(prop8.getId(), prop8);
+
+    PropertyStringDefinitionImpl prop9 = PropertyCreationHelper.createStringDefinition(
+        PICK_LIST_PROP_DEF, "Sample Pick List Property");
+
+    PropertyCreationHelper.addElemToPicklist(prop9, "red");
+    PropertyCreationHelper.addElemToPicklist(prop9, "green");
+    PropertyCreationHelper.addElemToPicklist(prop9, "blue");
+    PropertyCreationHelper.addElemToPicklist(prop9, "black");
+    PropertyCreationHelper.setDefaultValue(prop9, "blue");
+
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static InMemoryDocumentTypeDefinition buildTypeWithStringProp() {
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(STRING_DOC_TYPE,
+        "String Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+
+    PropertyStringDefinitionImpl propDef = PropertyCreationHelper.createStringDefinition(
+        STRING_PROP_TYPE, "Sample String Property");
+    propDef.setMaxLength(BigInteger.valueOf(10));
+    propertyDefinitions.put(propDef.getId(), propDef);
+
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static InMemoryDocumentTypeDefinition buildTypeWithIntegerProp() {
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(INT_DOC_TYPE,
+        "Int Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+
+    PropertyIntegerDefinitionImpl propDef = PropertyCreationHelper.createIntegerDefinition(
+        INT_PROP_TYPE, "Sample Integer Property");
+    propDef.setMinValue(BigInteger.valueOf(-1));
+    propDef.setMaxValue(BigInteger.valueOf(1));
+    propertyDefinitions.put(propDef.getId(), propDef);
+
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static InMemoryDocumentTypeDefinition buildTypeWithDecimalProp() {
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(DECIMAL_DOC_TYPE,
+        "Decimal Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+
+    PropertyDecimalDefinitionImpl propDef = PropertyCreationHelper.createDecimalDefinition(
+        DECIMAL_PROP_TYPE, "Sample Decimal Property");
+    propDef.setMinValue(BigDecimal.valueOf(-1.5));
+    propDef.setMaxValue(BigDecimal.valueOf(1.5));
+    propertyDefinitions.put(propDef.getId(), propDef);
+
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static InMemoryDocumentTypeDefinition buildTypeWithPickList(Cardinality cardinality) {
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(PICK_LIST_DOC_TYPE,
+        "PickList Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+
+    PropertyStringDefinitionImpl propDef = PropertyCreationHelper.createStringDefinition(
+        PICK_LIST_PROP_DEF, "Sample PickList (choice) Property");
+    List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
+    ChoiceImpl<String> elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("red"));
+    elem.setDisplayName("Red");
+    choiceList.add(elem);
+    elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("green"));
+    elem.setDisplayName("Green");
+    choiceList.add(elem);
+    elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("blue"));
+    elem.setDisplayName("Blue");
+    choiceList.add(elem);
+    elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("black"));
+    elem.setDisplayName("Black");
+    choiceList.add(elem);
+    propDef.setChoices(choiceList);
+    propDef.setDefaultValue(Collections.singletonList("blue"));
+    propDef.setCardinality(cardinality);
+    propertyDefinitions.put(propDef.getId(), propDef);
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static InMemoryDocumentTypeDefinition buildTypeWithMultiPickList() {
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(PICK_LIST_DOC_TYPE,
+        "PickList Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+
+    PropertyStringDefinitionImpl propDef = PropertyCreationHelper.createStringDefinition(
+        PICK_LIST_PROP_DEF, "Sample PickList (choice) Property");
+    List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
+    ChoiceImpl<String> elem = new ChoiceImpl<String>();
+    List<String> valueList = new ArrayList<String>();
+    valueList.add("red");
+    valueList.add("green");
+    valueList.add("blue");
+    elem.setValue(valueList);
+    elem.setDisplayName("RGB");
+    choiceList.add(elem);
+
+    elem = new ChoiceImpl<String>();
+    valueList = new ArrayList<String>();
+    valueList.add("cyan");
+    valueList.add("magenta");
+    valueList.add("yellow");
+    valueList.add("black");
+    elem.setValue(valueList);
+    elem.setDisplayName("CMYK");
+    choiceList.add(elem);
+
+    propDef.setChoices(choiceList);
+    // propDef.setDefaultValue(...);
+    propDef.setCardinality(Cardinality.MULTI);
+    propertyDefinitions.put(propDef.getId(), propDef);
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static InMemoryDocumentTypeDefinition buildTypeWithHierachicalPickList(
+      Cardinality cardinality) {
+    InMemoryDocumentTypeDefinition cmisType = new InMemoryDocumentTypeDefinition(PICK_LIST_DOC_TYPE,
+        "PickList Document Type for Validation", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+
+    // Create a two-level pick list with an outer property list state and an inner
+    // list of city
+    PropertyStringDefinitionImpl propDef = PropertyCreationHelper.createStringDefinition(
+        PICK_LIST_PROP_DEF, "Sample PickList (choice) Property");
+    List<Choice<String>> choiceListOuter = new ArrayList<Choice<String>>();
+
+    ChoiceImpl<String> elemOuter = new ChoiceImpl<String>();
+    elemOuter.setDisplayName("Bavaria");
+    List<Choice<String>> choiceListInner = new ArrayList<Choice<String>>();
+    ChoiceImpl<String> elemInner = new ChoiceImpl<String>();
+    elemInner.setDisplayName("Munich");
+    elemInner.setValue(Collections.singletonList("munich"));
+    choiceListInner.add(elemInner);
+    elemInner = new ChoiceImpl<String>();
+    elemInner.setDisplayName("Ingolstadt");
+    elemInner.setValue(Collections.singletonList("ingolstadt"));
+    choiceListInner.add(elemInner);
+    elemInner = new ChoiceImpl<String>();
+    elemInner.setDisplayName("Passau");
+    elemInner.setValue(Collections.singletonList("passau"));
+    choiceListInner.add(elemInner);
+    elemOuter.setChoice(choiceListInner);
+    choiceListOuter.add(elemOuter);
+
+    elemOuter = new ChoiceImpl<String>();
+    elemOuter.setDisplayName("Baden Wurtemberg");
+    choiceListInner = new ArrayList<Choice<String>>();
+    elemInner = new ChoiceImpl<String>();
+    elemInner.setDisplayName("Stuttgart");
+    elemInner.setValue(Collections.singletonList("stuttgart"));
+    choiceListInner.add(elemInner);
+    elemInner = new ChoiceImpl<String>();
+    elemInner.setDisplayName("Karlsruhe");
+    elemInner.setValue(Collections.singletonList("karlsruhe"));
+    choiceListInner.add(elemInner);
+    elemInner = new ChoiceImpl<String>();
+    elemInner.setDisplayName("Walldorf");
+    elemInner.setValue(Collections.singletonList("walldorf"));
+    choiceListInner.add(elemInner);
+    elemOuter.setChoice(choiceListInner);
+    choiceListOuter.add(elemOuter);
+
+    propDef.setChoices(choiceListOuter);
+    propDef.setCardinality(cardinality);
+    propertyDefinitions.put(propDef.getId(), propDef);
+    cmisType.setPropertyDefinitions(propertyDefinitions);
+
+    return cmisType;
+  }
+
+  private static TypeManager buildInheritedTypes() {
+
+    TypeManager tm = new TypeManager();
+    tm.initTypeSystem(null);  // create CMIS default types
+    
+    // create super type
+    InMemoryDocumentTypeDefinition cmisSuperType = new InMemoryDocumentTypeDefinition(DOC_TYPE_SUPER,
+        "Document Type With a child", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+    PropertyStringDefinitionImpl propDef = PropertyCreationHelper.createStringDefinition(
+        STRING_PROP_TYPE_SUPER, "Sample String Property SuperType");
+    propDef.setMaxLength(BigInteger.valueOf(10));
+    propertyDefinitions.put(propDef.getId(), propDef);
+    cmisSuperType.setPropertyDefinitions(propertyDefinitions);
+
+    // create sub type
+    InMemoryDocumentTypeDefinition cmisSubType = new InMemoryDocumentTypeDefinition(DOC_TYPE_SUB,
+        "Document Type With a parent", cmisSuperType);
+
+    propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    // create a String property definition
+    propDef = PropertyCreationHelper.createStringDefinition(
+        STRING_PROP_TYPE_SUB, "Sample String Property Subtype");
+    propDef.setMaxLength(BigInteger.valueOf(20));
+    propertyDefinitions.put(propDef.getId(), propDef);
+    cmisSubType.setPropertyDefinitions(propertyDefinitions);
+    
+    tm.addTypeDefinition(cmisSuperType);
+    tm.addTypeDefinition(cmisSubType);
+
+    return tm;
+  }
+
+}

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/UnitTestTypeSystemCreator.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/UnitTestTypeSystemCreator.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/UnitTestTypeSystemCreator.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/UnitTestTypeSystemCreator.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,256 @@
+/*
+ * 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;
+
+/**
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * @author Jens
+ * 
+ */
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.opencmis.commons.api.Choice;
+import org.apache.opencmis.commons.api.PropertyDefinition;
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.impl.dataobjects.ChoiceImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyDateTimeDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyDecimalDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyHtmlDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyIdDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyIntegerDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyUriDefinitionImpl;
+import org.apache.opencmis.inmemory.TypeCreator;
+import org.apache.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
+import org.apache.opencmis.inmemory.types.PropertyCreationHelper;
+
+public class UnitTestTypeSystemCreator implements TypeCreator {
+  static public List<TypeDefinition> singletonTypes = buildTypesList();
+  public static final String COMPLEX_TYPE = "ComplexType";
+  public static final String TOPLEVEL_TYPE = "DocumentTopLevel";
+  public static final String LEVEL1_TYPE = "DocumentLevel1";;
+  public static final String LEVEL2_TYPE = "DocumentLevel2";
+
+  /**
+   * in the public interface of this class we return the singleton containing the required types
+   * for testing
+   */
+  public List<TypeDefinition> createTypesList() {
+    return singletonTypes;
+  }
+
+  public static List<TypeDefinition> getTypesList() {
+    return singletonTypes;
+  }
+  
+  static public TypeDefinition getTypeById(String typeId) {
+    for (TypeDefinition typeDef : singletonTypes)
+      if (typeDef.getId().equals(typeId))
+        return typeDef;
+    return null;
+  }
+
+  /**
+   * create root types and a collection of sample types
+   * 
+   * @return typesMap map filled with created types
+   */
+  private static List<TypeDefinition> buildTypesList() {
+    // always add CMIS default types
+    List<TypeDefinition> typesList = new LinkedList<TypeDefinition>();
+
+    InMemoryDocumentTypeDefinition cmisType1 = new InMemoryDocumentTypeDefinition("MyDocType1",
+        "My Type 1 Level 1", InMemoryDocumentTypeDefinition.getRootDocumentType());
+    typesList.add(cmisType1);
+    
+
+    InMemoryDocumentTypeDefinition cmisType2 = new InMemoryDocumentTypeDefinition("MyDocType2",
+        "My Type 2 Level 1", InMemoryDocumentTypeDefinition.getRootDocumentType());
+    typesList.add(cmisType2);
+
+    InMemoryDocumentTypeDefinition cmisType11 = new InMemoryDocumentTypeDefinition("MyDocType1.1",
+        "My Type 3 Level 2", cmisType1);
+    typesList.add(cmisType11);
+
+    InMemoryDocumentTypeDefinition cmisType111 = new InMemoryDocumentTypeDefinition("MyDocType1.1.1",
+        "My Type 4 Level 3", cmisType11);
+    typesList.add(cmisType111);
+
+    InMemoryDocumentTypeDefinition cmisType112 = new InMemoryDocumentTypeDefinition("MyDocType1.1.2",
+        "My Type 5 Level 3", cmisType11);
+    typesList.add(cmisType112);
+
+    InMemoryDocumentTypeDefinition cmisType12 = new InMemoryDocumentTypeDefinition("MyDocType1.2",
+        "My Type 6 Level 2", cmisType1);
+    typesList.add(cmisType12);
+
+    InMemoryDocumentTypeDefinition cmisType21 = new InMemoryDocumentTypeDefinition("MyDocType2.1",
+        "My Type 7 Level 2", cmisType2);
+    typesList.add(cmisType21);
+
+    InMemoryDocumentTypeDefinition cmisType22 = new InMemoryDocumentTypeDefinition("MyDocType2.2",
+        "My Type 8 Level 2", cmisType2);
+    typesList.add(cmisType22);
+    InMemoryDocumentTypeDefinition cmisType23 = new InMemoryDocumentTypeDefinition("MyDocType2.3",
+        "My Type 9 Level 2", cmisType2);
+    typesList.add(cmisType23);
+    InMemoryDocumentTypeDefinition cmisType24 = new InMemoryDocumentTypeDefinition("MyDocType2.4",
+        "My Type 10 Level 2", cmisType2);
+    typesList.add(cmisType24);
+    InMemoryDocumentTypeDefinition cmisType25 = new InMemoryDocumentTypeDefinition("MyDocType2.5",
+        "My Type 11 Level 2", cmisType2);
+    typesList.add(cmisType25);
+
+    InMemoryDocumentTypeDefinition cmisType26 = new InMemoryDocumentTypeDefinition("MyDocType2.6",
+        "My Type 12 Level 2", cmisType2);
+    typesList.add(cmisType26);
+    InMemoryDocumentTypeDefinition cmisType27 = new InMemoryDocumentTypeDefinition("MyDocType2.7",
+        "My Type 13 Level 2", cmisType2);
+    typesList.add(cmisType27);
+    InMemoryDocumentTypeDefinition cmisType28 = new InMemoryDocumentTypeDefinition("MyDocType2.8",
+        "My Type 14 Level 2", cmisType2);
+    typesList.add(cmisType28);
+    InMemoryDocumentTypeDefinition cmisType29 = new InMemoryDocumentTypeDefinition("MyDocType2.9",
+        "My Type 15 Level 2", cmisType2);
+    typesList.add(cmisType29);
+
+    // create a complex type with properties
+    InMemoryDocumentTypeDefinition cmisComplexType = new InMemoryDocumentTypeDefinition(COMPLEX_TYPE,
+        "Complex type with properties, Level 1", InMemoryDocumentTypeDefinition.getRootDocumentType());
+    
+    // create a boolean property definition
+    
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    
+    PropertyDefinition<Boolean> prop = PropertyCreationHelper.createBooleanDefinition("BooleanProp", "Sample Boolean Property");
+    propertyDefinitions.put(prop.getId(), prop);
+    
+    prop = PropertyCreationHelper.createBooleanMultiDefinition("BooleanPropMV", "Sample Boolean multi-value Property");
+    propertyDefinitions.put(prop.getId(), prop);
+
+    PropertyDateTimeDefinitionImpl prop2 = PropertyCreationHelper.createDateTimeDefinition("DateTimeProp", "Sample DateTime Property");
+    propertyDefinitions.put(prop2.getId(), prop2);
+    
+    prop2 = PropertyCreationHelper.createDateTimeMultiDefinition("DateTimePropMV", "Sample DateTime multi-value Property");
+    propertyDefinitions.put(prop2.getId(), prop2);
+
+    PropertyDecimalDefinitionImpl prop3 = PropertyCreationHelper.createDecimalDefinition("DecimalProp", "Sample Decimal Property");
+    propertyDefinitions.put(prop3.getId(), prop3);
+    
+    prop3 = PropertyCreationHelper.createDecimalDefinition("DecimalPropMV", "Sample Decimal multi-value Property");
+    propertyDefinitions.put(prop3.getId(), prop3);
+
+    PropertyHtmlDefinitionImpl prop4 = PropertyCreationHelper.createHtmlDefinition("HtmlProp", "Sample Html Property");
+    propertyDefinitions.put(prop4.getId(), prop4);
+    
+    prop4 = PropertyCreationHelper.createHtmlDefinition("HtmlPropMV", "Sample Html multi-value Property");
+    propertyDefinitions.put(prop4.getId(), prop4);
+
+    PropertyIdDefinitionImpl prop5 = PropertyCreationHelper.createIdDefinition("IdProp", "Sample Id Property");
+    propertyDefinitions.put(prop5.getId(), prop5);
+    
+    prop5 = PropertyCreationHelper.createIdDefinition("IdPropMV", "Sample Id Html multi-value Property");
+    propertyDefinitions.put(prop5.getId(), prop5);
+
+    PropertyIntegerDefinitionImpl prop6 = PropertyCreationHelper.createIntegerDefinition("IntProp", "Sample Int Property");
+    propertyDefinitions.put(prop6.getId(), prop6);
+    
+    prop6 = PropertyCreationHelper.createIntegerDefinition("IntPropMV", "Sample Int multi-value Property");
+    propertyDefinitions.put(prop6.getId(), prop6);
+
+    PropertyStringDefinitionImpl prop7 = PropertyCreationHelper.createStringDefinition("StringProp", "Sample String Property");
+    propertyDefinitions.put(prop7.getId(), prop7);
+    
+    PropertyUriDefinitionImpl prop8 = PropertyCreationHelper.createUriDefinition("UriProp", "Sample Uri Property");
+    propertyDefinitions.put(prop8.getId(), prop8);
+    
+    prop8 = PropertyCreationHelper.createUriDefinition("UriPropMV", "Sample Uri multi-value Property");
+    propertyDefinitions.put(prop8.getId(), prop8);
+
+    PropertyStringDefinitionImpl prop9 = PropertyCreationHelper.createStringDefinition("PickListProp", "Sample Pick List Property");
+    List<Choice<String>> choiceList = new ArrayList<Choice<String>>();
+    ChoiceImpl<String> elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("red"));
+    choiceList.add(elem);
+    elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("green"));
+    choiceList.add(elem);
+    elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("blue"));
+    choiceList.add(elem);
+    elem = new ChoiceImpl<String>();
+    elem.setValue(Collections.singletonList("black"));
+    choiceList.add(elem);   
+    prop9.setChoices(choiceList);
+    prop9.setDefaultValue(Collections.singletonList("blue"));
+    
+    /* try short form: * /
+    PropertyCreationHelper.addElemToPicklist(prop9, "red");    
+    PropertyCreationHelper.addElemToPicklist(prop9, "green");    
+    PropertyCreationHelper.addElemToPicklist(prop9, "blue");    
+    PropertyCreationHelper.addElemToPicklist(prop9, "black");
+    PropertyCreationHelper.setDefaultValue(prop9, "blue");    
+    /* */
+    
+    cmisComplexType.addCustomPropertyDefinitions(propertyDefinitions);    
+    
+    // add type to types collection
+    typesList.add(cmisComplexType);
+
+    // create a type hierarchy with inherited properties
+    InMemoryDocumentTypeDefinition cmisDocTypeTopLevel = new InMemoryDocumentTypeDefinition(TOPLEVEL_TYPE,
+        "Document type with properties, Level 1", InMemoryDocumentTypeDefinition.getRootDocumentType());
+
+    InMemoryDocumentTypeDefinition cmisDocTypeLevel1 = new InMemoryDocumentTypeDefinition(LEVEL1_TYPE,
+        "Document type with inherited properties, Level 2", cmisDocTypeTopLevel);
+    
+    InMemoryDocumentTypeDefinition cmisDocTypeLevel2 = new InMemoryDocumentTypeDefinition(LEVEL2_TYPE,
+        "Document type with inherited properties, Level 3", cmisDocTypeLevel1);
+    
+    propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    PropertyStringDefinitionImpl propTop = PropertyCreationHelper.createStringDefinition("StringPropTopLevel", "Sample String Property");
+    propertyDefinitions.put(propTop.getId(), propTop);
+    cmisDocTypeTopLevel.addCustomPropertyDefinitions(propertyDefinitions);    
+    
+    propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    PropertyStringDefinitionImpl propLevel1 = PropertyCreationHelper.createStringDefinition("StringPropLevel1", "String Property Level 1");
+    propertyDefinitions.put(propLevel1.getId(), propLevel1);
+    cmisDocTypeLevel1.addCustomPropertyDefinitions(propertyDefinitions);    
+
+    propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    PropertyStringDefinitionImpl propLevel2 = PropertyCreationHelper.createStringDefinition("StringPropLevel2", "String Property Level 2");
+    propertyDefinitions.put(propLevel2.getId(), propLevel2);
+    cmisDocTypeLevel2.addCustomPropertyDefinitions(propertyDefinitions);    
+
+    // add type to types collection
+    typesList.add(cmisDocTypeTopLevel);
+    typesList.add(cmisDocTypeLevel1);
+    typesList.add(cmisDocTypeLevel2);
+    
+    return typesList;
+  }
+
+}
+
+

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersionTestTypeSystemCreator.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersionTestTypeSystemCreator.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersionTestTypeSystemCreator.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersionTestTypeSystemCreator.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,89 @@
+/*
+ * 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.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.opencmis.commons.api.PropertyDefinition;
+import org.apache.opencmis.commons.api.TypeDefinition;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
+import org.apache.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
+import org.apache.opencmis.inmemory.types.PropertyCreationHelper;
+
+public class VersionTestTypeSystemCreator implements TypeCreator {
+  static public String VERSION_TEST_DOCUMENT_TYPE_ID = "MyVersionedType";
+  static public String PROPERTY_ID = "StringProp";
+  static public List<TypeDefinition> singletonTypes = buildTypesList();
+
+
+  /**
+   * in the public interface of this class we return the singleton containing the required types
+   * for testing
+   */
+  public List<TypeDefinition> createTypesList() {
+    return singletonTypes;
+  }
+
+  public static List<TypeDefinition> getTypesList() {
+    return singletonTypes;
+  }
+  
+  static public TypeDefinition getTypeById(String typeId) {
+    for (TypeDefinition typeDef : singletonTypes)
+      if (typeDef.getId().equals(typeId))
+        return typeDef;
+    return null;
+  }
+
+  /**
+   * create root types and a collection of sample types
+   * 
+   * @return typesMap map filled with created types
+   */
+  private static List<TypeDefinition> buildTypesList() {
+    // always add CMIS default types
+    List<TypeDefinition> typesList = new LinkedList<TypeDefinition>();
+
+    // create a complex type with properties
+    InMemoryDocumentTypeDefinition cmisComplexType = new InMemoryDocumentTypeDefinition(VERSION_TEST_DOCUMENT_TYPE_ID,
+        "VersionedType", InMemoryDocumentTypeDefinition.getRootDocumentType());
+    
+    // create a boolean property definition
+    
+    Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+    
+    PropertyStringDefinitionImpl prop1 = PropertyCreationHelper.createStringDefinition(PROPERTY_ID, "Sample String Property");
+    propertyDefinitions.put(prop1.getId(), prop1);
+    
+    cmisComplexType.addCustomPropertyDefinitions(propertyDefinitions);    
+    cmisComplexType.setIsVersionable(true); // make it a versionable type;
+    
+    // add type to types collection
+    typesList.add(cmisComplexType);
+
+    
+    return typesList;
+  }
+
+}
+
+

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersioningTest.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersioningTest.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersioningTest.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/java/org/apache/opencmis/inmemory/VersioningTest.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,625 @@
+/*
+ * 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.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.apache.opencmis.client.provider.factory.CmisProviderFactory;
+import org.apache.opencmis.commons.PropertyIds;
+import org.apache.opencmis.commons.SessionParameter;
+import org.apache.opencmis.commons.api.DocumentTypeDefinition;
+import org.apache.opencmis.commons.api.PropertyDefinition;
+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.enums.VersioningState;
+import org.apache.opencmis.commons.exceptions.CmisConstraintException;
+import org.apache.opencmis.commons.exceptions.CmisUpdateConflictException;
+import org.apache.opencmis.commons.impl.dataobjects.PropertyStringDefinitionImpl;
+import org.apache.opencmis.commons.provider.CmisProvider;
+import org.apache.opencmis.commons.provider.ContentStreamData;
+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.ObjectList;
+import org.apache.opencmis.commons.provider.ObjectService;
+import org.apache.opencmis.commons.provider.PropertiesData;
+import org.apache.opencmis.commons.provider.PropertyBooleanData;
+import org.apache.opencmis.commons.provider.PropertyData;
+import org.apache.opencmis.commons.provider.PropertyIdData;
+import org.apache.opencmis.commons.provider.PropertyStringData;
+import org.apache.opencmis.commons.provider.ProviderObjectFactory;
+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.RepositoryServiceTest.UnitTestRepositoryInfo;
+import org.apache.opencmis.inmemory.server.RuntimeContext;
+import org.apache.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
+import org.apache.opencmis.inmemory.types.InMemoryFolderTypeDefinition;
+import org.apache.opencmis.inmemory.types.PropertyCreationHelper;
+
+public class VersioningTest extends TestCase {
+  private static Log log = LogFactory.getLog(ObjectServiceTest.class);
+  private static final String REPOSITORY_ID = "UnitTestRepository";
+  private static final String PROP_VALUE = "Mickey Mouse";
+  private static final String PROP_VALUE_NEW = "Donald Duck";
+  private static final String PROP_NAME = "My Versioned Document";
+  private static final String TEST_USER = "TestUser";
+  private static final String TEST_USER_2 = "OtherUser";
+  
+  private ProviderObjectFactory fFactory;
+  private CmisProvider fProvider;
+  ObjectService fObjSvc;
+  VersioningService fVerSvc;
+  RepositoryService fRepSvc;
+  NavigationService fNavSvc;
+  String fRepositoryId;
+  String fRootFolderId;
+  ObjectCreator fCreator;
+  
+  @Before
+  public void setUp() throws Exception {
+    Map<String, String> parameters = new HashMap<String, String>();
+    parameters.put(SessionParameter.BINDING_SPI_CLASS, CmisProviderFactory.BINDING_SPI_INMEMORY);
+    // attach repository info to the session:
+    parameters
+        .put(ConfigConstants.REPOSITORY_INFO_CREATOR_CLASS, UnitTestRepositoryInfo.class.getName());
+
+    parameters.put(ConfigConstants.TYPE_CREATOR_CLASS, VersionTestTypeSystemCreator.class.getName());
+    parameters.put(ConfigConstants.REPOSITORY_ID, REPOSITORY_ID);
+  
+    // get factory and create provider
+    CmisProviderFactory factory = CmisProviderFactory.newInstance();
+    fProvider = factory.createCmisProvider(parameters);
+    assertNotNull(fProvider);
+    fFactory = fProvider.getObjectFactory();
+    fRepSvc = fProvider.getRepositoryService();
+    RepositoryInfoData rep = fRepSvc.getRepositoryInfo(REPOSITORY_ID, null);
+    fObjSvc = fProvider.getObjectService();
+    fVerSvc = fProvider.getVersioningService();
+    fNavSvc = fProvider.getNavigationService();
+    fRepositoryId = rep.getRepositoryId();
+    fRootFolderId = rep.getRootFolderId();
+    fCreator = new ObjectCreator(fFactory, fObjSvc, fRepositoryId);
+    setRuntimeContext(TEST_USER);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  private void setRuntimeContext(String user) {
+    Map<String, String> parameters = new HashMap<String, String>();
+    parameters.put(ConfigConstants.USERNAME, user);
+
+    // Attach the CallContext to a thread local context that can be accessed from everywhere
+    ConfigMap cfgReader = new MapConfigReader(parameters);  
+    RuntimeContext.getRuntimeConfig().attachCfg(cfgReader); 
+  }
+    
+  public void testCreateVersionedDocumentMinor() {
+    testCreateVersionedDocument(VersioningState.MINOR);
+  }
+  
+  public void testCreateVersionedDocumentCheckedOut() {
+    testCreateVersionedDocument(VersioningState.CHECKEDOUT);
+  }
+  
+  public void testCreateVersionedDocumentNone() {
+    try {
+      testCreateVersionedDocument(VersioningState.NONE);
+      fail("creating a document of a versionable type with state VersioningState.NONE should fail.");
+    } catch (Exception e) {     
+      assertEquals(CmisConstraintException.class, e.getClass());
+    }
+  }
+
+  public void testCheckOutBasic() {
+    String verId = createDocument(PROP_NAME, fRootFolderId, VersioningState.MAJOR);
+
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+
+    assertFalse(isCheckedOut(docId));
+
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verId); // or should this be version series?
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    String pwcId = idHolder.getValue();
+    // test that object is checked out and that all properties are set correctly
+    PropertiesData props = fObjSvc.getProperties(fRepositoryId, pwcId, "*", null);
+    String changeToken = (String) props.getProperties().get(PropertyIds.CMIS_CHANGE_TOKEN).getFirstValue();
+    checkVersionProperties(pwcId, VersioningState.CHECKEDOUT, props.getProperties());
+    
+    // Test that a second checkout is not possible
+    try {
+      fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+      fail("Checking out a document that is already checked-out should fail.");
+    } catch (Exception e) {
+      assertTrue(e instanceof CmisUpdateConflictException);
+    }
+    // version and version series should be checked out now
+    assertTrue(isCheckedOut(docId));
+    assertTrue(isCheckedOut(pwcId));
+
+    // Set a new content and modify property
+    ContentStreamData altContent = fCreator.createAlternateContent();
+    idHolder = new Holder<String>(pwcId);
+    Holder<String> tokenHolder = new Holder<String>(changeToken);
+    fObjSvc.setContentStream(fRepositoryId, idHolder, true, tokenHolder, altContent, null);
+    fCreator.updateProperty(idHolder.getValue(), VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW);
+
+    // Test that a check-in as same user is possible
+    String checkinComment = "Checkin without content and properties.";
+    fVerSvc.checkIn(fRepositoryId, idHolder, true, null, null, checkinComment, null, null, null,
+        null);
+    // Neither the version nor the version series should be checked out any longer:
+    assertFalse(isCheckedOut(idHolder.getValue()));
+    assertFalse(isCheckedOut(docId));
+    ContentStreamData retrievedContent = fObjSvc.getContentStream(fRepositoryId, idHolder
+        .getValue(), null, BigInteger.valueOf(-1) /* offset */,
+        BigInteger.valueOf(-1) /* length */, null);
+    assertTrue(fCreator.verifyContent(fCreator.createAlternateContent(), retrievedContent));
+    assertTrue(fCreator.verifyProperty(idHolder.getValue(), VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW));
+
+    List<ObjectData> allVersions = fVerSvc.getAllVersions(fRepositoryId, docId, "*", false, null);
+    assertEquals(2, allVersions.size());
+  }
+  
+  public void testCheckInWithContent() {
+    String verId = createDocument(PROP_NAME, fRootFolderId, VersioningState.MAJOR);
+
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+
+    assertFalse(isCheckedOut(docId));
+
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verId); // or should this be version series?
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    String pwcId = idHolder.getValue();
+    
+    ContentStreamData altContent = fCreator.createAlternateContent();
+    PropertiesData newProps = fCreator.getUpdatePropertyList(VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW);
+    idHolder = new Holder<String>(pwcId);
+    assertTrue(isCheckedOut(docId));
+    assertTrue(isCheckedOut(pwcId));
+
+    // Test check-in and pass content and properties
+    String checkinComment = "Checkin with content and properties.";
+    fVerSvc.checkIn(fRepositoryId, idHolder, true, newProps, altContent, checkinComment, null, null, null,
+        null);
+    // Neither the version nor the version series should be checked out any longer:
+    assertFalse(isCheckedOut(idHolder.getValue()));
+    assertFalse(isCheckedOut(docId));
+    ContentStreamData retrievedContent = fObjSvc.getContentStream(fRepositoryId, idHolder
+        .getValue(), null, BigInteger.valueOf(-1) /* offset */,
+        BigInteger.valueOf(-1) /* length */, null);
+
+    // New content and property should be set
+    assertTrue(fCreator.verifyContent(fCreator.createAlternateContent(), retrievedContent));    
+    assertTrue(fCreator.verifyProperty(idHolder.getValue(), VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW));
+  }
+  
+  public void testCheckOutAndOtherUser() {
+    String verId = createDocument(PROP_NAME, fRootFolderId, VersioningState.MAJOR);
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+    assertFalse(isCheckedOut(docId));
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verId); // or should this be version series?
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    String pwcId = idHolder.getValue();
+    
+    // Test that a checkin as another user is not possible
+    setRuntimeContext(TEST_USER_2);
+    try {      
+      fVerSvc.checkIn(fRepositoryId, idHolder, true, null, null, "My Comment", null, null, null, null);
+      fail("Checking in a document as another user should fail.");
+    } catch (Exception e) {
+      assertTrue(e instanceof CmisUpdateConflictException);
+    }
+
+    // Test that a cancel checkout as another user is not possible
+    try {      
+      fVerSvc.cancelCheckOut(fRepositoryId, pwcId, null);
+      fail("Checking in a document as another user should fail.");
+    } catch (Exception e) {
+      assertTrue(e instanceof CmisUpdateConflictException);
+    }
+    
+    // Test that an updateProperties as another user is not possible
+    try {      
+      fCreator.updateProperty(pwcId, VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW);
+      fail("updateProperty in a document as another user should fail.");
+    } catch (Exception e) {
+      assertTrue(e instanceof CmisUpdateConflictException);
+    }
+
+    ContentStreamData altContent = fCreator.createAlternateContent();
+    Holder<String> pwcHolder = new Holder<String>(pwcId);
+    try {      
+      fObjSvc.setContentStream(fRepositoryId, pwcHolder, true, null, altContent, null);
+      fail("setContentStream in a document as another user should fail.");
+    } catch (Exception e) {
+      assertTrue(e instanceof CmisUpdateConflictException);
+    }
+
+    setRuntimeContext(TEST_USER);
+    // Test that a check-in as same user is possible
+    fVerSvc.checkIn(fRepositoryId, pwcHolder, true, null, null, "testCheckOutAndOtherUser", null, null, null,null);
+    
+    // Because nothing was changed we should have a new version with identical content
+    ContentStreamData retrievedContent = fObjSvc.getContentStream(fRepositoryId, pwcHolder.getValue(),
+        null, BigInteger.valueOf(-1) /* offset */, BigInteger.valueOf(-1) /* length */, null);
+    assertTrue(fCreator.verifyContent(retrievedContent, fCreator.createContent()));    
+    assertTrue(fCreator.verifyProperty(idHolder.getValue(), VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE));  
+  }
+  
+  public void testCancelCheckout() {
+    String verId = createDocument(PROP_NAME, fRootFolderId, VersioningState.MAJOR);
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String idOfLastVersion = version.getId();
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+    assertFalse(isCheckedOut(docId));
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verId); // or should this be version series?
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    String pwcId = idHolder.getValue();
+    
+    // Set a new content and modify property
+    PropertiesData props = fObjSvc.getProperties(fRepositoryId, pwcId, "*", null);
+    String changeToken = (String) props.getProperties().get(PropertyIds.CMIS_CHANGE_TOKEN).getFirstValue();
+    ContentStreamData altContent = fCreator.createAlternateContent();
+    idHolder = new Holder<String>(pwcId);
+    Holder<String> tokenHolder = new Holder<String>(changeToken);
+    fObjSvc.setContentStream(fRepositoryId, idHolder, true, tokenHolder, altContent, null);
+    fCreator.updateProperty(idHolder.getValue(), VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW);
+    
+    // cancel checkout 
+    fVerSvc.cancelCheckOut(fRepositoryId, pwcId, null);
+    try {
+      // Verify that pwc no longer exists
+      fObjSvc.getObject(fRepositoryId, pwcId, "*", false, IncludeRelationships.NONE,
+          null, false, false, null);
+      fail("Getting pwc after cancel checkout should fail.");
+    } catch (Exception e1) {
+    }
+    
+    // verify that the old content and properties are still valid
+    assertTrue(fCreator.verifyProperty(docId, VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE));      
+    ContentStreamData retrievedContent = fObjSvc.getContentStream(fRepositoryId, idOfLastVersion,
+        null, BigInteger.valueOf(-1) /* offset */, BigInteger.valueOf(-1) /* length */, null);
+    assertTrue(fCreator.verifyContent(retrievedContent, fCreator.createContent()));    
+  }
+  
+  public void testGetPropertiesOfLatestVersion() {
+    VersioningState versioningState = VersioningState.MAJOR;
+    String verId = createDocument(PROP_NAME, fRootFolderId, versioningState);
+    getDocument(verId);
+    
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+    
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verId); // or should this be version series?
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    String pwcId = idHolder.getValue();
+    
+    ContentStreamData altContent = fCreator.createAlternateContent();
+    PropertiesData newProps = fCreator.getUpdatePropertyList(VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW);
+    idHolder = new Holder<String>(pwcId);
+    assertTrue(isCheckedOut(docId));
+    assertTrue(isCheckedOut(pwcId));
+
+    // Test check-in and pass content and properties
+    String checkinComment = "Checkin with content and properties.";
+    fVerSvc.checkIn(fRepositoryId, idHolder, true, newProps, altContent, checkinComment, null, null, null,
+        null);
+    
+    PropertiesData latest = fVerSvc.getPropertiesOfLatestVersion(fRepositoryId, docId, true, "*", null);
+    assertNotNull(latest);
+    
+    checkVersionProperties(verId, versioningState, latest.getProperties());        
+  }
+  
+  public void testGetLatestVersion() {
+    VersioningState versioningState = VersioningState.MINOR;
+    String verId = createDocument(PROP_NAME, fRootFolderId, versioningState);
+    getDocument(verId);
+    
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+    
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verId); // or should this be version series?
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    String pwcId = idHolder.getValue();
+    
+    ContentStreamData altContent = fCreator.createAlternateContent();
+    PropertiesData newProps = fCreator.getUpdatePropertyList(VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE_NEW);
+    idHolder = new Holder<String>(pwcId);
+    assertTrue(isCheckedOut(docId));
+    assertTrue(isCheckedOut(pwcId));
+
+    // Test check-in and pass content and properties
+    String checkinComment = "Checkin with content and properties.";
+    fVerSvc.checkIn(fRepositoryId, idHolder, true, newProps, altContent, checkinComment, null, null, null,
+        null);
+    
+    // get latest major version
+    versioningState = VersioningState.MAJOR;
+    boolean isMajor = true;
+    ObjectData objData = fVerSvc.getObjectOfLatestVersion(fRepositoryId, docId, isMajor, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    checkVersionProperties(verId, versioningState, objData.getProperties().getProperties());        
+    ContentStreamData retrievedContent = fObjSvc.getContentStream(fRepositoryId, objData.getId(),
+        null, BigInteger.valueOf(-1) /* offset */, BigInteger.valueOf(-1) /* length */, null);
+    assertTrue(fCreator.verifyContent(retrievedContent, fCreator.createAlternateContent()));    
+
+    // get latest non-major version, must be the same as before
+    versioningState = VersioningState.MAJOR;
+    isMajor = false;
+    objData = fVerSvc.getObjectOfLatestVersion(fRepositoryId, docId, isMajor, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    checkVersionProperties(verId, versioningState, objData.getProperties().getProperties());        
+    retrievedContent = fObjSvc.getContentStream(fRepositoryId, objData.getId(),
+        null, BigInteger.valueOf(-1) /* offset */, BigInteger.valueOf(-1) /* length */, null);
+    assertTrue(fCreator.verifyContent(retrievedContent, fCreator.createAlternateContent()));        
+   }
+  
+  public void testGetCheckedOutDocuments() {
+    // create two folders with each having two documents, one of them being checked out
+    final int count = 2;
+    String[] folderIds = createLevel1Folders();
+    String[] verSeriesIds = new String[folderIds.length * count];
+    for (int i=0; i<folderIds.length; i++) {
+      for (int j=0; j<count; j++) {
+        String verId = createDocument("MyDoc"+j, folderIds[i], VersioningState.MAJOR);
+        ObjectData od = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+        verSeriesIds[i*folderIds.length + j] = getVersionSeriesId(verId, od.getProperties().getProperties());
+      }
+    }
+    // checkout first in each folder
+    Holder<Boolean> contentCopied = new Holder<Boolean>();
+    Holder<String> idHolder = new Holder<String>(verSeriesIds[0]);
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    idHolder = new Holder<String>(verSeriesIds[2]);
+    fVerSvc.checkOut(fRepositoryId, idHolder, null, contentCopied);
+    
+    // must be one in first folder
+    ObjectList checkedOutDocuments = fNavSvc.getCheckedOutDocs(fRepositoryId, folderIds[0], "*",
+        null, false, IncludeRelationships.NONE, null, BigInteger.valueOf(-1), BigInteger
+            .valueOf(-1), null);
+    assertEquals(1, checkedOutDocuments.getNumItems().longValue());
+    assertEquals(1, checkedOutDocuments.getObjects().size());
+    
+    // must be one in second folder
+    checkedOutDocuments = fNavSvc.getCheckedOutDocs(fRepositoryId, folderIds[1], "*",
+        null, false, IncludeRelationships.NONE, null, BigInteger.valueOf(-1), BigInteger
+            .valueOf(-1), null);
+    assertEquals(1, checkedOutDocuments.getNumItems().longValue());
+    assertEquals(1, checkedOutDocuments.getObjects().size());
+    
+    // must be two in repository
+    checkedOutDocuments = fNavSvc.getCheckedOutDocs(fRepositoryId, null, "*",
+        null, false, IncludeRelationships.NONE, null, BigInteger.valueOf(-1), BigInteger
+            .valueOf(-1), null);
+    assertEquals(2, checkedOutDocuments.getNumItems().longValue());    
+    assertEquals(2, checkedOutDocuments.getObjects().size());
+  }
+  
+  private String[] createLevel1Folders() {
+    ObjectService objSvc = fProvider.getObjectService();
+    final int num = 2;
+    String[] res = new String[num];
+    
+    for (int i = 0; i < num; i++) {
+      List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+      properties.add(fFactory.createPropertyIdData(PropertyIds.CMIS_NAME, "Folder " + i));
+      properties.add(fFactory.createPropertyIdData(PropertyIds.CMIS_OBJECT_TYPE_ID,
+          BaseObjectTypeIds.CMIS_FOLDER.value()));
+      PropertiesData props = fFactory.createPropertiesData(properties);      
+      String id = objSvc.createFolder(fRepositoryId, props, fRootFolderId, null, null, null, null);
+      res[i] = id;
+    }
+    return res;
+  }
+
+  private void testCreateVersionedDocument(VersioningState versioningState) {
+    // type id is: VersionTestTypeSystemCreator.VERSION_TEST_DOCUMENT_TYPE_ID    
+    String verId = createDocument(PROP_NAME, fRootFolderId, versioningState);
+    getDocument(verId);
+    
+    ObjectData version = fObjSvc.getObject(fRepositoryId, verId, "*", false, IncludeRelationships.NONE, null, false, false, null);
+    String docId = getVersionSeriesId(verId, version.getProperties().getProperties());
+    assertTrue(null != docId && docId.length() > 0 );
+    
+    List<ObjectData> allVersions = fVerSvc.getAllVersions(fRepositoryId, docId, "*", false, null);
+    assertEquals(1, allVersions.size());
+    
+    checkVersionProperties(verId, versioningState, allVersions.get(0).getProperties().getProperties());    
+  }
+  
+  private String getVersionSeriesId(String docId, Map<String, PropertyData<?>> props) {
+    PropertyIdData pdid = (PropertyIdData) props.get(PropertyIds.CMIS_VERSION_SERIES_ID);
+    assertNotNull(pdid);
+    String sVal = pdid.getFirstValue();
+    assertNotNull(sVal);
+    return sVal;
+  }
+  
+  private boolean isCheckedOut(String objectId) {
+    PropertiesData props = fObjSvc.getProperties(fRepositoryId, objectId, "*", null);
+    return isCheckedOut(props.getProperties());
+  }
+  
+  private boolean isCheckedOut( Map<String, PropertyData<?>> props) {
+    PropertyBooleanData pdb = (PropertyBooleanData) props.get(PropertyIds.CMIS_IS_VERSION_SERIES_CHECKED_OUT);
+    assertNotNull(pdb);
+    boolean bVal = pdb.getFirstValue();
+    return bVal;
+ 
+  }
+  
+  private void checkVersionProperties(String docId, VersioningState versioningState, Map<String, PropertyData<?>> props) {
+    for (PropertyData<?> pd : props.values()) {
+      log.info("return property id: " + pd.getId() + ", value: " + pd.getValues());
+    }
+    
+    DocumentTypeDefinition typeDef = (DocumentTypeDefinition) fRepSvc.getTypeDefinition(fRepositoryId, VersionTestTypeSystemCreator.VERSION_TEST_DOCUMENT_TYPE_ID, null);
+    PropertyBooleanData pdb = (PropertyBooleanData) props.get(PropertyIds.CMIS_IS_LATEST_VERSION);
+    assertNotNull(pdb);
+    boolean bVal = pdb.getFirstValue();
+    assertEquals(versioningState != VersioningState.CHECKEDOUT, bVal); // if checked out it isn't the latest version
+
+    pdb = (PropertyBooleanData) props.get(PropertyIds.CMIS_IS_MAJOR_VERSION);
+    assertNotNull(pdb);
+    bVal = pdb.getFirstValue();
+    assertEquals(versioningState == VersioningState.MAJOR, bVal);
+    
+    pdb = (PropertyBooleanData) props.get(PropertyIds.CMIS_IS_LATEST_MAJOR_VERSION);
+    assertNotNull(pdb);
+    bVal = pdb.getFirstValue();
+    assertEquals(versioningState == VersioningState.MAJOR, bVal);
+    
+    PropertyIdData pdid = (PropertyIdData) props.get(PropertyIds.CMIS_VERSION_SERIES_ID);
+    assertNotNull(pdb);
+    String sVal = pdid.getFirstValue();
+    if (typeDef.isVersionable())
+      assertFalse(docId.equals(sVal));
+    else
+      assertEquals(docId, sVal);
+
+    pdb = (PropertyBooleanData) props.get(PropertyIds.CMIS_IS_VERSION_SERIES_CHECKED_OUT);
+    assertNotNull(pdb);
+    bVal = pdb.getFirstValue();
+    assertEquals(versioningState == VersioningState.CHECKEDOUT, bVal);
+    
+    PropertyStringData pds = (PropertyStringData) props.get(PropertyIds.CMIS_VERSION_SERIES_CHECKED_OUT_BY);
+    assertNotNull(pdb);
+    sVal = pds.getFirstValue();
+    if (versioningState == VersioningState.CHECKEDOUT)
+      assertTrue(sVal != null && sVal.length() > 0);
+    else
+      assertTrue(null == sVal || sVal.equals(""));
+
+    pdid = (PropertyIdData) props.get(PropertyIds.CMIS_VERSION_SERIES_CHECKED_OUT_ID);
+    assertNotNull(pdid);
+    sVal = pdid.getFirstValue();
+    if (versioningState == VersioningState.CHECKEDOUT)
+      assertTrue(sVal != null && sVal.length() > 0);
+    else
+      assertTrue(null == sVal || sVal.equals(""));
+    
+    pds = (PropertyStringData) props.get(PropertyIds.CMIS_CHECKIN_COMMENT);
+    assertNotNull(pdb);
+    sVal = pds.getFirstValue();
+    assertTrue(null == sVal || sVal.equals(""));
+    
+  }
+
+  private String getDocument(String id) {
+    String returnedId=null;
+    try {
+      ObjectData res = fObjSvc.getObject(fRepositoryId, id, "*", false, IncludeRelationships.NONE,
+          null, false, false, null);
+      assertNotNull(res);
+      testReturnedProperties(res.getProperties().getProperties());
+      returnedId = res.getId();
+      assertEquals(id, returnedId);    
+    } catch (Exception e) {
+      fail("getObject() failed with exception: " + e);
+    }    
+    return returnedId;
+  }
+  
+  private void testReturnedProperties(Map<String, PropertyData<?>> props) {
+    for (PropertyData<?> pd : props.values()) {
+      log.info("return property id: " + pd.getId() + ", value: " + pd.getValues());
+    }
+    
+    PropertyData<?> pd = props.get(PropertyIds.CMIS_NAME);
+    assertNotNull(pd);
+    assertEquals(PROP_NAME, pd.getFirstValue());
+    pd = props.get(PropertyIds.CMIS_OBJECT_TYPE_ID);
+    assertEquals(VersionTestTypeSystemCreator.VERSION_TEST_DOCUMENT_TYPE_ID, pd.getFirstValue());
+    pd = props.get(VersionTestTypeSystemCreator.PROPERTY_ID);
+    assertEquals(PROP_VALUE, pd.getFirstValue());
+  }
+ 
+  private String createDocument(String name, String folderId, VersioningState versioningState) {
+
+    String id = null;
+    Map<String, String> properties = new HashMap<String, String>();
+    properties.put(VersionTestTypeSystemCreator.PROPERTY_ID, PROP_VALUE);
+    id = fCreator.createDocument(name, VersionTestTypeSystemCreator.VERSION_TEST_DOCUMENT_TYPE_ID, folderId, 
+        versioningState, properties);
+    
+    return id;
+  }
+    
+  public static class VersionTestTypeSystemCreator implements TypeCreator {
+    static public String VERSION_TEST_DOCUMENT_TYPE_ID = "MyVersionedType";
+    static public String PROPERTY_ID = "StringProp";
+
+    public List<TypeDefinition> createTypesList() {
+      // always add CMIS default types
+      List<TypeDefinition> typesList = new LinkedList<TypeDefinition>();
+
+      // create a complex type with properties
+      InMemoryDocumentTypeDefinition cmisComplexType = new InMemoryDocumentTypeDefinition(VERSION_TEST_DOCUMENT_TYPE_ID,
+          "VersionedType", InMemoryDocumentTypeDefinition.getRootDocumentType());
+      
+      // create a single String property definition
+      
+      Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+      
+      PropertyStringDefinitionImpl prop1 = PropertyCreationHelper.createStringDefinition(PROPERTY_ID, "Sample String Property");
+      propertyDefinitions.put(prop1.getId(), prop1);
+      
+      cmisComplexType.addCustomPropertyDefinitions(propertyDefinitions);    
+      cmisComplexType.setIsVersionable(true); // make it a versionable type;
+      
+      // add type to types collection
+      typesList.add(cmisComplexType);
+
+      
+      return typesList;
+   }
+    
+  } // ObjectTestTypeSystemCreator
+  
+}
\ No newline at end of file

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

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/resources/log4j.properties?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/resources/log4j.properties (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/resources/log4j.properties Tue Feb 16 16:03:38 2010
@@ -0,0 +1,22 @@
+#sample log4j.properties
+
+log4j.rootCategory=DEBUG, R, O
+
+# Stdout
+log4j.appender.O=org.apache.log4j.ConsoleAppender
+
+# File
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=log4j.log
+
+# Control the maximum log file size
+log4j.appender.R.MaxFileSize=100KB
+
+# Archive log files (one backup file here)
+log4j.appender.R.MaxBackupIndex=1
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.O.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n
+log4j.appender.O.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c: %m%n
+
+log4j.logger.org.apache.opencmis.client.provider.spi=O
\ No newline at end of file

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-inmemory/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Tue Feb 16 16:03:38 2010
@@ -0,0 +1,6 @@
+bin
+target
+*.iws
+*.ipr
+*.iml
+.*

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/pom.xml
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/pom.xml?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/pom.xml (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/pom.xml Tue Feb 16 16:03:38 2010
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                             http://maven.apache.org/maven-v4_0_0.xsd">
+                             
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opencmis</groupId>
+    <artifactId>opencmis</artifactId>
+    <version>0.1-SNAPSHOT</version>
+	<relativePath>../../pom.xml</relativePath>		
+  </parent>
+  
+  <artifactId>opencmis-server-spi</artifactId>
+  <name>OpenCMIS Server SPI</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opencmis</groupId>
+      <artifactId>opencmis-commons-api</artifactId>
+      <version>${version}</version>
+    </dependency>
+  </dependencies>
+
+</project>

Propchange: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/src/main/java/org/apache/opencmis/server/spi/AbstractServicesFactory.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/src/main/java/org/apache/opencmis/server/spi/AbstractServicesFactory.java?rev=910572&view=auto
==============================================================================
--- incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/src/main/java/org/apache/opencmis/server/spi/AbstractServicesFactory.java (added)
+++ incubator/chemistry/trunk/opencmis/opencmis-server/opencmis-server-spi/src/main/java/org/apache/opencmis/server/spi/AbstractServicesFactory.java Tue Feb 16 16:03:38 2010
@@ -0,0 +1,107 @@
+/*
+ * 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.server.spi;
+
+import java.util.Map;
+
+import org.apache.opencmis.commons.exceptions.CmisNotSupportedException;
+
+/**
+ * The aim of this class is provide CMIS service instances.
+ * 
+ * @author <a href="mailto:fmueller@opentext.com">Florian M&uuml;ller</a>
+ * 
+ */
+public abstract class AbstractServicesFactory {
+
+  /**
+   * Initializes the factory instance.
+   */
+  public void init(Map<String, String> parameters) {
+  }
+
+  /**
+   * Cleans up the the factory instance.
+   */
+  public void destroy() {
+  }
+
+  /**
+   * Returns the CMIS Repository Service object.
+   */
+  public CmisRepositoryService getRepositoryService() {
+    throw new CmisNotSupportedException("Repository Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS Navigation Service object.
+   */
+  public CmisNavigationService getNavigationService() {
+    throw new CmisNotSupportedException("Navigation Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS Object Service object.
+   */
+  public CmisObjectService getObjectService() {
+    throw new CmisNotSupportedException("Object Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS Versioning Service object.
+   */
+  public CmisVersioningService getVersioningService() {
+    throw new CmisNotSupportedException("Versioning Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS Relationship Service object.
+   */
+  public CmisRelationshipService getRelationshipService() {
+    throw new CmisNotSupportedException("Releationship Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS Discovery Service object.
+   */
+  public CmisDiscoveryService getDiscoveryService() {
+    throw new CmisNotSupportedException("Discovery Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS MultiFiling Service object.
+   */
+  public CmisMultiFilingService getMultiFilingService() {
+    throw new CmisNotSupportedException("MultiFiling Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS ACL Service object.
+   */
+  public CmisAclService getAclService() {
+    throw new CmisNotSupportedException("ACL Service not supported!");
+  }
+
+  /**
+   * Returns the CMIS Policy Service object.
+   */
+  public CmisPolicyService getPolicyService() {
+    throw new CmisNotSupportedException("Policy Service not supported!");
+  }
+}

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