You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fg...@apache.org on 2009/07/20 14:49:46 UTC

svn commit: r795804 - in /incubator/chemistry/trunk/chemistry: chemistry-api/src/main/java/org/apache/chemistry/ chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/ chemistry-atompub-client/src/main/java/org/apache/chemistry/ato...

Author: fguillaume
Date: Mon Jul 20 12:49:46 2009
New Revision: 795804

URL: http://svn.apache.org/viewvc?rev=795804&view=rev
Log:
CMIS-34: Implement AtomPub document creation

Added:
    incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java   (contents, props changed)
      - copied, changed from r794736, incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ValueAdapter.java
Removed:
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ValueAdapter.java
Modified:
    incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/PropertyType.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObject.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntry.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPPropertyDefinition.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/XmlProperty.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/pom.xml
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/ObjectElement.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/PropertiesElement.java
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java
    incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestAtomPubClientServer.java
    incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestSimpleDirect.java

Modified: incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/PropertyType.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/PropertyType.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/PropertyType.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-api/src/main/java/org/apache/chemistry/PropertyType.java Mon Jul 20 12:49:46 2009
@@ -176,4 +176,24 @@
     public String toString() {
         return this.getClass().getSimpleName() + '(' + name + ')';
     }
+
+    @Override
+    public int hashCode() {
+        return 31 + ordinal;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof PropertyType) {
+            return ordinal == ((PropertyType) obj).ordinal;
+        }
+        return false;
+    }
+
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java Mon Jul 20 12:49:46 2009
@@ -121,7 +121,6 @@
         }
         APPObjectEntry entry = newObjectEntry(typeId);
         if (folder != null) {
-            entry.setValue(Property.PARENT_ID, folder.getId());
             entry.addLink(CMIS.LINK_PARENTS,
                     ((APPFolder) folder).entry.getEditLink());
         }

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObject.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObject.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObject.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObject.java Mon Jul 20 12:49:46 2009
@@ -149,18 +149,26 @@
      * ----- data access -----
      */
 
+    @Override
+    public String getId() {
+        return entry.getId();
+    }
+
+    @Override
+    public String getTypeId() {
+        return entry.getTypeId();
+    }
+
     public Type getType() {
         return type;
     }
 
     public Property getProperty(String name) {
-        PropertyDefinition propertyDefinition = getType().getPropertyDefinition(
-                name);
-        if (propertyDefinition == null) {
+        PropertyDefinition pd = getType().getPropertyDefinition(name);
+        if (pd == null) {
             throw new IllegalArgumentException(name);
         }
-        // TODO deal with unfetched properties
-        return entry.getProperty(name);
+        return entry.getProperty(pd);
     }
 
     public Serializable getValue(String name) {
@@ -178,7 +186,7 @@
 
     public void save() {
         try {
-            if (getId() == null) {
+            if (entry.isCreation()) {
                 create();
             } else {
                 update();
@@ -194,6 +202,9 @@
             throw new IllegalArgumentException(
                     "Cannot create entry: no 'cmis-parents' link is present");
         }
+        // TODO in 0.5 the parents link (entry or feed) wasn't defined clearly
+        // TODO hardcoded Chemistry URL pattern here...
+        href = href.replaceAll("/object/([0-9a-f-]{36}$)", "/children/$1");
         Request req = new Request(href);
         req.setHeader("Content-Type", "application/atom+xml;type=entry");
         Response resp = entry.connection.getConnector().postObject(req, entry);

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntry.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntry.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntry.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPObjectEntry.java Mon Jul 20 12:49:46 2009
@@ -32,7 +32,7 @@
 import org.apache.chemistry.Property;
 import org.apache.chemistry.PropertyDefinition;
 import org.apache.chemistry.atompub.CMIS;
-import org.apache.chemistry.atompub.client.stax.ValueAdapter;
+import org.apache.chemistry.atompub.ValueAdapter;
 import org.apache.chemistry.atompub.client.stax.XmlProperty;
 import org.apache.chemistry.xml.stax.XMLWriter;
 
@@ -95,6 +95,10 @@
         return connection;
     }
 
+    protected boolean isCreation() {
+        return getId() == null;
+    }
+
     public String getId() {
         return (String) getValue(Property.ID);
     }
@@ -109,8 +113,18 @@
     }
 
     // not in API
-    public XmlProperty getProperty(String name) {
-        return properties.get(name);
+    public XmlProperty getProperty(PropertyDefinition pd) {
+        XmlProperty p = properties.get(pd.getName());
+        if (p != null) {
+            return p;
+        }
+        if (isCreation()) {
+            p = new XmlProperty(pd);
+            properties.put(pd.getName(), p);
+        } else {
+            // TODO not fetched...
+        }
+        return p;
     }
 
     public Map<String, Serializable> getValues() {
@@ -178,7 +192,7 @@
         xw.start();
         for (XmlProperty p : properties.values()) {
             ValueAdapter va = p.getAdapter();
-            xw.element(va.getPropertyName()).attr(CMIS.NAME, p.getName());
+            xw.element(va.getPropertyQName()).attr(CMIS.NAME, p.getName());
             xw.start();
             if (p.isValueLoaded()) {
                 Serializable v = p.getValue();

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPPropertyDefinition.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPPropertyDefinition.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPPropertyDefinition.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPPropertyDefinition.java Mon Jul 20 12:49:46 2009
@@ -33,7 +33,7 @@
 import org.apache.chemistry.PropertyType;
 import org.apache.chemistry.Updatability;
 import org.apache.chemistry.atompub.CMIS;
-import org.apache.chemistry.atompub.client.stax.ValueAdapter;
+import org.apache.chemistry.atompub.ValueAdapter;
 import org.apache.chemistry.xml.stax.ChildrenNavigator;
 import org.apache.chemistry.xml.stax.StaxReader;
 import org.apache.commons.logging.Log;

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/XmlProperty.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/XmlProperty.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/XmlProperty.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/XmlProperty.java Mon Jul 20 12:49:46 2009
@@ -23,6 +23,7 @@
 import org.apache.chemistry.Property;
 import org.apache.chemistry.PropertyDefinition;
 import org.apache.chemistry.PropertyType;
+import org.apache.chemistry.atompub.ValueAdapter;
 
 /**
  * Implementation of a CMIS property to be used when reading data from XML.

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/pom.xml
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/pom.xml?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/pom.xml (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/pom.xml Mon Jul 20 12:49:46 2009
@@ -36,6 +36,10 @@
     </dependency>
     <dependency>
       <groupId>org.apache.chemistry</groupId>
+      <artifactId>chemistry-commons</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.chemistry</groupId>
       <artifactId>chemistry-atompub</artifactId>
     </dependency>
 
@@ -53,12 +57,6 @@
     </dependency>
 
     <dependency>
-      <groupId>org.apache.chemistry</groupId>
-      <artifactId>chemistry-commons</artifactId>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java Mon Jul 20 12:49:46 2009
@@ -18,16 +18,19 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.abdera.factory.Factory;
 import org.apache.abdera.i18n.iri.IRI;
 import org.apache.abdera.model.AtomDate;
 import org.apache.abdera.model.Content;
 import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Element;
 import org.apache.abdera.model.Entry;
 import org.apache.abdera.model.Feed;
 import org.apache.abdera.model.Person;
@@ -37,17 +40,22 @@
 import org.apache.abdera.protocol.server.ResponseContext;
 import org.apache.abdera.protocol.server.context.AbstractResponseContext;
 import org.apache.abdera.protocol.server.context.BaseResponseContext;
+import org.apache.abdera.protocol.server.context.EmptyResponseContext;
 import org.apache.abdera.protocol.server.context.ResponseContextException;
 import org.apache.abdera.util.EntityTag;
 import org.apache.chemistry.BaseType;
+import org.apache.chemistry.ContentStream;
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.ObjectId;
 import org.apache.chemistry.Property;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.ReturnVersion;
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.Type;
+import org.apache.chemistry.VersioningState;
 import org.apache.chemistry.atompub.CMIS;
 import org.apache.chemistry.atompub.abdera.ObjectElement;
+import org.apache.chemistry.impl.simple.SimpleObjectId;
 
 /**
  * CMIS Collection for object entries.
@@ -170,6 +178,46 @@
     // getEntries is abstract, must be implemented
 
     @Override
+    public ResponseContext postEntry(RequestContext request) {
+        // TODO parameter sourceFolderId
+        // TODO parameter versioningState
+        Entry entry;
+        try {
+            entry = getEntryFromRequest(request);
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+        if (entry == null || !ProviderHelper.isValidEntry(entry)) {
+            return new EmptyResponseContext(400);
+        }
+        Element obb = entry.getFirstChild(CMIS.OBJECT);
+        ObjectElement objectElement = new ObjectElement(obb, repository);
+        Map<String, Serializable> properties;
+        try {
+            properties = objectElement.getProperties();
+        } catch (Exception e) { // TODO proper exception
+            return createErrorResponse(new ResponseContextException(500, e));
+        }
+        ContentStream contentStream = null;
+        VersioningState versioningState = null;
+        String typeId = (String) properties.get(Property.TYPE_ID);
+        // not null, already checked in getProperties
+
+        SPI spi = repository.getSPI(); // TODO XXX connection leak
+        ObjectId objectId = spi.createDocument(typeId, properties,
+                new SimpleObjectId(id), contentStream, versioningState);
+        ObjectEntry object = spi.getProperties(objectId, null, null, false,
+                false);
+
+        entry.setUpdated(new Date());
+        entry.getIdElement().setValue(getId(object));
+        String link = getObjectLink(object.getId(), request);
+        entry.addLink(link, "edit");
+        return buildCreateEntryResponse(link, entry);
+    }
+
+    // unused but abstract in parent...
+    @Override
     public ObjectEntry postEntry(String title, IRI id, String summary,
             Date updated, List<Person> authors, Content content,
             RequestContext request) throws ResponseContextException {

Copied: incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java (from r794736, incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ValueAdapter.java)
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java?p2=incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java&p1=incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ValueAdapter.java&r1=794736&r2=795804&rev=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ValueAdapter.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java Mon Jul 20 12:49:46 2009
@@ -15,11 +15,12 @@
  *     Bogdan Stefanescu, Nuxeo
  *     Florent Guillaume, Nuxeo
  */
-package org.apache.chemistry.atompub.client.stax;
+package org.apache.chemistry.atompub;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.net.URI;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
@@ -29,7 +30,6 @@
 
 import org.apache.abdera.model.AtomDate;
 import org.apache.chemistry.PropertyType;
-import org.apache.chemistry.atompub.CMIS;
 
 /**
  * Adapter between a Java value and a XML String representation.
@@ -42,7 +42,9 @@
 
     public abstract Serializable[] createArray(int size);
 
-    public abstract QName getPropertyName();
+    public abstract QName getPropertyQName();
+
+    public abstract PropertyType getPropertyType();
 
     protected static final class StringValueAdapter extends ValueAdapter {
         @Override
@@ -61,9 +63,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_STRING;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.STRING;
+        }
     }
 
     protected static final class DecimalValueAdapter extends ValueAdapter {
@@ -83,9 +90,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_DECIMAL;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.DECIMAL;
+        }
     }
 
     protected static final class IntegerValueAdapter extends ValueAdapter {
@@ -105,9 +117,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_INTEGER;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.INTEGER;
+        }
     }
 
     protected static final class BooleanValueAdapter extends ValueAdapter {
@@ -127,9 +144,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_BOOLEAN;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.BOOLEAN;
+        }
     }
 
     protected static final class DateTimeValueAdapter extends ValueAdapter {
@@ -151,9 +173,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_DATETIME;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.DATETIME;
+        }
     }
 
     protected static final class UriValueAdapter extends ValueAdapter {
@@ -177,9 +204,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_URI;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.URI;
+        }
     }
 
     protected static final class IdValueAdapter extends ValueAdapter {
@@ -199,9 +231,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_ID;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.ID;
+        }
     }
 
     protected static final class XmlValueAdapter extends ValueAdapter {
@@ -221,9 +258,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_XML;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.XML;
+        }
     }
 
     protected static final class HtmlValueAdapter extends ValueAdapter {
@@ -243,9 +285,14 @@
         }
 
         @Override
-        public QName getPropertyName() {
+        public QName getPropertyQName() {
             return CMIS.PROPERTY_HTML;
         }
+
+        @Override
+        public PropertyType getPropertyType() {
+            return PropertyType.HTML;
+        }
     }
 
     public static final ValueAdapter STRING = new StringValueAdapter();
@@ -266,21 +313,33 @@
 
     public static final ValueAdapter HTML = new HtmlValueAdapter();
 
-    private static final Map<Integer, ValueAdapter> adapters = new HashMap<Integer, ValueAdapter>();
+    protected static final Map<PropertyType, ValueAdapter> byPropertyType = new HashMap<PropertyType, ValueAdapter>();
+
+    protected static final Map<QName, ValueAdapter> byQName = new HashMap<QName, ValueAdapter>();
+
     static {
-        adapters.put(Integer.valueOf(PropertyType.STRING_ORD), STRING);
-        adapters.put(Integer.valueOf(PropertyType.DECIMAL_ORD), DECIMAL);
-        adapters.put(Integer.valueOf(PropertyType.INTEGER_ORD), INTEGER);
-        adapters.put(Integer.valueOf(PropertyType.BOOLEAN_ORD), BOOLEAN);
-        adapters.put(Integer.valueOf(PropertyType.DATETIME_ORD), DATETIME);
-        adapters.put(Integer.valueOf(PropertyType.URI_ORD), URI);
-        adapters.put(Integer.valueOf(PropertyType.ID_ORD), ID);
-        adapters.put(Integer.valueOf(PropertyType.XML_ORD), XML);
-        adapters.put(Integer.valueOf(PropertyType.HTML_ORD), HTML);
+        for (ValueAdapter va : Arrays.asList( //
+                STRING, //
+                DECIMAL, //
+                INTEGER, //
+                BOOLEAN, //
+                DATETIME, //
+                URI, //
+                ID, //
+                XML, //
+                HTML //
+        )) {
+            byPropertyType.put(va.getPropertyType(), va);
+            byQName.put(va.getPropertyQName(), va);
+        }
     }
 
     public static ValueAdapter getAdapter(PropertyType type) {
-        return adapters.get(Integer.valueOf(type.ordinal()));
+        return byPropertyType.get(type);
+    }
+
+    public static ValueAdapter getAdapter(QName qname) {
+        return byQName.get(qname);
     }
 
 }

Propchange: incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/ValueAdapter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/ObjectElement.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/ObjectElement.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/ObjectElement.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/ObjectElement.java Mon Jul 20 12:49:46 2009
@@ -17,11 +17,14 @@
 package org.apache.chemistry.atompub.abdera;
 
 import java.io.Serializable;
+import java.util.Collections;
 import java.util.Map;
 
 import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Element;
 import org.apache.abdera.model.ExtensibleElementWrapper;
 import org.apache.chemistry.ObjectEntry;
+import org.apache.chemistry.Repository;
 import org.apache.chemistry.Type;
 import org.apache.chemistry.atompub.CMIS;
 
@@ -30,18 +33,38 @@
  */
 public class ObjectElement extends ExtensibleElementWrapper {
 
+    protected final PropertiesElement properties;
+
+    /**
+     * Constructor used when parsing XML.
+     * @param repository
+     */
+    public ObjectElement(Element internal, Repository repository) {
+        super(internal);
+        Element propsel = getFirstChild(CMIS.PROPERTIES);
+        properties = propsel == null ? null : new PropertiesElement(propsel, repository);
+    }
+
+    /**
+     * Constructor used when generating XML.
+     */
     public ObjectElement(Factory factory, ObjectEntry object, Type type,
             String contentStreamURI) {
         super(factory, CMIS.OBJECT);
-        setProperties(object.getValues(), type, contentStreamURI);
+        properties = new PropertiesElement(getFactory(), contentStreamURI);
+        addExtension(properties);
+        setProperties(object.getValues(), type);
     }
 
-    public void setProperties(Map<String, Serializable> values, Type type,
-            String contentStreamURI) {
-        PropertiesElement el = new PropertiesElement(getFactory(),
-                contentStreamURI);
-        addExtension(el);
-        el.setProperties(values, type);
+    public Map<String, Serializable> getProperties() {
+        if (properties == null) {
+            return Collections.emptyMap();
+        }
+        return properties.getProperties();
+    }
+
+    public void setProperties(Map<String, Serializable> values, Type type) {
+        properties.setProperties(values, type);
     }
 
     // TODO allowable actions

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/PropertiesElement.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/PropertiesElement.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/PropertiesElement.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub/src/main/java/org/apache/chemistry/atompub/abdera/PropertiesElement.java Mon Jul 20 12:49:46 2009
@@ -20,11 +20,14 @@
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Arrays;
+import java.util.Map.Entry;
 
 import javax.xml.namespace.QName;
 
@@ -35,20 +38,35 @@
 import org.apache.chemistry.Property;
 import org.apache.chemistry.PropertyDefinition;
 import org.apache.chemistry.PropertyType;
+import org.apache.chemistry.Repository;
 import org.apache.chemistry.Type;
 import org.apache.chemistry.atompub.CMIS;
+import org.apache.chemistry.atompub.ValueAdapter;
 
 /**
  * Abdera ElementWrapper for an AtomPub cmis:properties element.
  */
 public class PropertiesElement extends ExtensibleElementWrapper {
 
+    protected final Repository repository;
+
+    /**
+     * Constructor used when parsing XML.
+     */
+    public PropertiesElement(Element internal, Repository repository) {
+        super(internal);
+        this.repository = repository;
+    }
+
     /**
-     * Constructor. ContentStreamUri is special-cased as it depends on the
-     * server context (base URL).
+     * Constructor used when generating XML.
+     * <p>
+     * ContentStreamUri is special-cased as it depends on the server context
+     * (base URL).
      */
     public PropertiesElement(Factory factory, String contentStreamURI) {
         super(factory, CMIS.PROPERTIES);
+        repository = null;
         if (contentStreamURI != null) {
             ExtensibleElement el = addExtension(CMIS.PROPERTY_URI);
             el.setAttributeValue(CMIS.NAME, Property.CONTENT_STREAM_URI);
@@ -65,6 +83,76 @@
         }
     }
 
+    public Map<String, Serializable> getProperties() {
+        // collector raw values
+        Map<String, List<Serializable>> raw = new HashMap<String, List<Serializable>>();
+        Map<String, ValueAdapter> adapters = new HashMap<String, ValueAdapter>();
+        String typeId = null;
+        for (Element element : getElements()) {
+            ValueAdapter va = ValueAdapter.getAdapter(element.getQName());
+            if (va == null) {
+                continue;
+            }
+            String name = element.getAttributeValue(CMIS.NAME);
+            adapters.put(name, va);
+            List<Serializable> list = new LinkedList<Serializable>();
+            for (Element el : element.getElements()) {
+                if (!el.getQName().equals(CMIS.VALUE)) {
+                    continue;
+                }
+                Serializable value = va.readValue(el.getText());
+                list.add(value);
+                if (name.equals(Property.TYPE_ID)) {
+                    typeId = (String) value;
+                }
+            }
+            raw.put(name, list);
+        }
+        if (typeId == null) {
+            // TODO proper exception
+            throw new RuntimeException("Invalid object with no "
+                    + Property.TYPE_ID);
+        }
+        Type type = repository.getType(typeId);
+        if (type == null) {
+            // TODO proper exception
+            throw new RuntimeException("Unknown type: " + typeId);
+        }
+        // now we have the type, build actual values
+        Map<String, Serializable> properties = new HashMap<String, Serializable>();
+        for (Entry<String, List<Serializable>> e : raw.entrySet()) {
+            String name = e.getKey();
+            PropertyDefinition pd = type.getPropertyDefinition(name);
+            if (pd == null) {
+                // TODO proper exception
+                throw new RuntimeException("Illegal property: " + name
+                        + " for type: " + typeId);
+            }
+            // check type matches qname
+            ValueAdapter va = adapters.get(name);
+            if (va.getPropertyType() != pd.getType()) {
+                throw new RuntimeException("Property: " + name + " has type: "
+                        + typeId + " but used element: "
+                        + va.getPropertyQName());
+            }
+            // put multi-value in array
+            List<Serializable> list = e.getValue();
+            Serializable value;
+            if (pd.isMultiValued()) {
+                value = list.toArray(va.createArray(list.size()));
+            } else {
+                if (list.size() != 1) {
+                    throw new RuntimeException("Property: " + name
+                            + " for type: " + typeId
+                            + " cannot have multi-values: " + list);
+                }
+                value = list.get(0);
+            }
+            properties.put(name, value);
+        }
+        return properties;
+    }
+
     public void setProperties(Map<String, Serializable> values, Type type) {
         for (PropertyDefinition propertyDefinition : type.getPropertyDefinitions()) {
             String name = propertyDefinition.getName();

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java Mon Jul 20 12:49:46 2009
@@ -151,97 +151,6 @@
     }
 
     /*
-     * Called by save() for new objects.
-     */
-    protected void saveObject(SimpleObject object) {
-        SimpleData data = object.entry.data;
-        Map<String, Serializable> update = new HashMap<String, Serializable>();
-
-        // generate an ID
-        String id = repository.generateId();
-        update.put(Property.ID, id);
-
-        // check mandatory properties
-        Type type = object.getType();
-        for (PropertyDefinition pd : type.getPropertyDefinitions()) {
-            String name = pd.getName();
-            if (Property.ID.equals(name)) {
-                // ignore, set later
-                continue;
-            }
-            if (pd.isRequired() && !data.containsKey(name)) {
-                if (Property.NAME.equals(name)) {
-                    update.put(Property.NAME, id);
-                } else if (Property.CREATED_BY.equals(name)) {
-                    update.put(Property.CREATED_BY, "system"); // TODO
-                } else if (Property.CREATION_DATE.equals(name)) {
-                    update.put(Property.CREATION_DATE,
-                            GregorianCalendar.getInstance());
-                } else if (Property.LAST_MODIFIED_BY.equals(name)) {
-                    update.put(Property.LAST_MODIFIED_BY, "system"); // TODO
-                } else if (Property.LAST_MODIFICATION_DATE.equals(name)) {
-                    update.put(Property.LAST_MODIFICATION_DATE,
-                            GregorianCalendar.getInstance());
-                } else if (Property.IS_LATEST_VERSION.equals(name)) {
-                    update.put(Property.IS_LATEST_VERSION, Boolean.TRUE);
-                } else if (Property.IS_LATEST_MAJOR_VERSION.equals(name)) {
-                    update.put(Property.IS_LATEST_MAJOR_VERSION, Boolean.TRUE);
-                } else if (Property.IS_VERSION_SERIES_CHECKED_OUT.equals(name)) {
-                    update.put(Property.IS_VERSION_SERIES_CHECKED_OUT,
-                            Boolean.FALSE);
-                } else if (Property.VERSION_SERIES_ID.equals(name)) {
-                    update.put(Property.VERSION_SERIES_ID, id);
-                } else if (Property.VERSION_LABEL.equals(name)) {
-                    update.put(Property.VERSION_LABEL, "1.0");
-                } else {
-                    throw new RuntimeException("Missing property: " + name); // TODO
-                }
-            }
-        }
-
-        // content stream
-        byte[] bytes = (byte[]) data.get(SimpleProperty.CONTENT_BYTES_KEY);
-        if (type.getContentStreamAllowed() == ContentStreamPresence.REQUIRED
-                && bytes == null) {
-            throw new RuntimeException("Content stream required"); // TODO
-        }
-        update.put(Property.CONTENT_STREAM_LENGTH, bytes == null ? null
-                : Integer.valueOf(bytes.length)); // TODO Long
-
-        // update data once we know there's no error
-        for (String key : update.keySet()) {
-            Serializable value = update.get(key);
-            if (value == null) {
-                data.remove(key);
-            } else {
-                data.put(key, value);
-            }
-        }
-
-        // properties
-        repository.datas.put(id, data); // TODO clone data?
-
-        // parents/children
-        String parentId = (String) data.get(Property.PARENT_ID);
-        if (type.getBaseType() == BaseType.FOLDER) {
-            // new folder, empty set of children
-            repository.children.put(id, repository.newSet());
-        } else {
-            // only folders have this property
-            data.remove(Property.PARENT_ID);
-        }
-        if (parentId != null) {
-            // this object is filed
-            // pointer to parent
-            Set<String> parents = repository.newSet();
-            parents.add(parentId);
-            repository.parents.put(id, parents);
-            // new pointer to child
-            repository.children.get(parentId).add(id);
-        }
-    }
-
-    /*
      * ----- Navigation Services -----
      */
 
@@ -375,11 +284,112 @@
      * ----- Object Services -----
      */
 
+    // Called by SimpleObject.save() for new objects.
+    protected void saveObject(SimpleObject object) {
+        saveData(object.entry.data, object.getTypeId());
+    }
+
+    protected void saveData(SimpleData data, String typeId) {
+        Map<String, Serializable> update = new HashMap<String, Serializable>();
+
+        // generate an ID
+        String id = repository.generateId();
+        update.put(Property.ID, id);
+
+        // check mandatory properties
+        Type type = repository.getType(typeId);
+        for (PropertyDefinition pd : type.getPropertyDefinitions()) {
+            String name = pd.getName();
+            if (Property.ID.equals(name)) {
+                // ignore, set later
+                continue;
+            }
+            if (pd.isRequired() && !data.containsKey(name)) {
+                if (Property.NAME.equals(name)) {
+                    update.put(Property.NAME, id);
+                } else if (Property.CREATED_BY.equals(name)) {
+                    update.put(Property.CREATED_BY, "system"); // TODO
+                } else if (Property.CREATION_DATE.equals(name)) {
+                    update.put(Property.CREATION_DATE,
+                            GregorianCalendar.getInstance());
+                } else if (Property.LAST_MODIFIED_BY.equals(name)) {
+                    update.put(Property.LAST_MODIFIED_BY, "system"); // TODO
+                } else if (Property.LAST_MODIFICATION_DATE.equals(name)) {
+                    update.put(Property.LAST_MODIFICATION_DATE,
+                            GregorianCalendar.getInstance());
+                } else if (Property.IS_LATEST_VERSION.equals(name)) {
+                    update.put(Property.IS_LATEST_VERSION, Boolean.TRUE);
+                } else if (Property.IS_LATEST_MAJOR_VERSION.equals(name)) {
+                    update.put(Property.IS_LATEST_MAJOR_VERSION, Boolean.TRUE);
+                } else if (Property.IS_VERSION_SERIES_CHECKED_OUT.equals(name)) {
+                    update.put(Property.IS_VERSION_SERIES_CHECKED_OUT,
+                            Boolean.FALSE);
+                } else if (Property.VERSION_SERIES_ID.equals(name)) {
+                    update.put(Property.VERSION_SERIES_ID, id);
+                } else if (Property.VERSION_LABEL.equals(name)) {
+                    update.put(Property.VERSION_LABEL, "1.0");
+                } else {
+                    throw new RuntimeException("Missing property: " + name); // TODO
+                }
+            }
+        }
+
+        // content stream
+        byte[] bytes = (byte[]) data.get(SimpleProperty.CONTENT_BYTES_KEY);
+        if (type.getContentStreamAllowed() == ContentStreamPresence.REQUIRED
+                && bytes == null) {
+            throw new RuntimeException("Content stream required"); // TODO
+        }
+        update.put(Property.CONTENT_STREAM_LENGTH, bytes == null ? null
+                : Integer.valueOf(bytes.length)); // TODO Long
+
+        // update data once we know there's no error
+        for (String key : update.keySet()) {
+            Serializable value = update.get(key);
+            if (value == null) {
+                data.remove(key);
+            } else {
+                data.put(key, value);
+            }
+        }
+
+        // properties
+        repository.datas.put(id, data); // TODO clone data?
+
+        // parents/children
+        String parentId = (String) data.get(Property.PARENT_ID);
+        if (type.getBaseType() == BaseType.FOLDER) {
+            // new folder, empty set of children
+            repository.children.put(id, repository.newSet());
+        } else {
+            // only folders have this property
+            data.remove(Property.PARENT_ID);
+        }
+        if (parentId != null) {
+            // this object is filed
+            // pointer to parent
+            Set<String> parents = repository.newSet();
+            parents.add(parentId);
+            repository.parents.put(id, parents);
+            // new pointer to child
+            repository.children.get(parentId).add(id);
+        }
+    }
+
     public ObjectId createDocument(String typeId,
             Map<String, Serializable> properties, ObjectId folder,
             ContentStream contentStream, VersioningState versioningState) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        Type type = repository.getType(typeId);
+        if (type == null || type.getBaseType() != BaseType.DOCUMENT) {
+            throw new IllegalArgumentException(typeId);
+        }
+        SimpleData data = new SimpleData(typeId);
+        data.putAll(properties);
+        if (folder != null) {
+            data.put(Property.PARENT_ID, folder.getId());
+        }
+        saveData(data, typeId);
+        return new SimpleObjectId((String) data.get(Property.ID));
     }
 
     public ObjectId createFolder(String typeId,

Modified: incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java Mon Jul 20 12:49:46 2009
@@ -54,12 +54,31 @@
 
     public SPI spi;
 
+    public abstract void makeRepository() throws Exception;
+
+    @Override
+    public void setUp() throws Exception {
+        makeRepository();
+        openConn();
+    }
+
     @Override
     public void tearDown() throws Exception {
-        conn.close();
+        closeConn();
         super.tearDown();
     }
 
+    protected void openConn() {
+        conn = repository.getConnection(null);
+        spi = conn.getSPI();
+    }
+
+    protected void closeConn() {
+        conn.close();
+        conn = null;
+        spi = null;
+    }
+
     public void testBasic() {
         assertNotNull(repository);
         assertNotNull(conn);
@@ -88,9 +107,9 @@
         // check default values
         for (CMISObject child : children) {
             String name = child.getName();
-            String title = (String) child.getValue("title");
-            String descr = (String) child.getValue("description");
-            Calendar date = (Calendar) child.getValue("date");
+            String title = child.getString("title");
+            String descr = child.getString("description");
+            Calendar date = child.getDateTime("date");
             if (name.equals("doc 3")) {
                 assertEquals("(no title)", title); // uses defaultValue
                 assertEquals("", descr); // emptry string defaultValue
@@ -201,4 +220,22 @@
         assertEquals(array.length, cs.getLength());
     }
 
+    public void testNewDocument() {
+        Folder root = conn.getRootFolder();
+        assertEquals(0, root.getChildren(BaseType.DOCUMENT).size());
+        Document doc = root.newDocument("doc");
+        doc.setName("mydoc");
+        doc.setValue("title", "mytitle");
+        doc.save();
+        // new connection
+        closeConn();
+        openConn();
+        root = conn.getRootFolder();
+        List<CMISObject> children = root.getChildren(BaseType.DOCUMENT);
+        assertEquals(1, children.size());
+        doc = (Document) children.get(0);
+        assertEquals("mydoc", doc.getName());
+        assertEquals("mytitle", doc.getString("title"));
+    }
+
 }

Modified: incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestAtomPubClientServer.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestAtomPubClientServer.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestAtomPubClientServer.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestAtomPubClientServer.java Mon Jul 20 12:49:46 2009
@@ -72,12 +72,10 @@
     }
 
     @Override
-    public void setUp() throws Exception {
+    public void makeRepository() throws Exception {
         String serverUrl = startServer();
         ContentManager cm = new APPContentManager(serverUrl);
         repository = cm.getDefaultRepository();
-        conn = repository.getConnection(null);
-        spi = conn.getSPI();
     }
 
     @Override

Modified: incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestSimpleDirect.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestSimpleDirect.java?rev=795804&r1=795803&r2=795804&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestSimpleDirect.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tests/src/test/java/org/apache/chemistry/test/TestSimpleDirect.java Mon Jul 20 12:49:46 2009
@@ -22,10 +22,8 @@
 public class TestSimpleDirect extends BasicTestCase {
 
     @Override
-    public void setUp() throws Exception {
+    public void makeRepository() throws Exception {
         repository = BasicHelper.makeRepository(null);
-        conn = repository.getConnection(null);
-        spi = conn.getSPI();
     }
 
 }