You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2010/01/26 18:56:55 UTC
svn commit: r903343 - in /jackrabbit/sandbox/jackrabbit-spi2cmis/src:
main/java/org/apache/jackrabbit/spi2cmis/
main/java/org/apache/jackrabbit/spi2cmis/util/ main/resources/
test/java/org/apache/jackrabbit/spi2cmis/
Author: mduerig
Date: Tue Jan 26 17:56:54 2010
New Revision: 903343
URL: http://svn.apache.org/viewvc?rev=903343&view=rev
Log:
- Exposing CMIS folder as JCR type nt:folder
- Exposing CMIS document as JCR type nt:file
- Exposing content streams via jcr:data property
Added:
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Arrays.java (with props)
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Functions.java (with props)
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Iterators.java (with props)
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Predicate.java (with props)
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Streams.java (with props)
Removed:
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/SuppressWarning.java
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/Util.java
Modified:
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java
jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd
jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/ReadTest.java
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/CmisRepositoryService.java Tue Jan 26 17:56:54 2010
@@ -17,8 +17,6 @@
package org.apache.jackrabbit.spi2cmis;
-import static org.apache.jackrabbit.spi2cmis.SuppressWarning.unchecked;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -26,6 +24,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import javax.jcr.Credentials;
@@ -38,22 +37,19 @@
import org.apache.chemistry.CMIS;
import org.apache.chemistry.CMISObject;
import org.apache.chemistry.Connection;
+import org.apache.chemistry.ContentStream;
import org.apache.chemistry.Folder;
import org.apache.chemistry.ListPage;
import org.apache.chemistry.ObjectEntry;
-import org.apache.chemistry.ObjectId;
import org.apache.chemistry.Property;
import org.apache.chemistry.Repository;
import org.apache.chemistry.RepositoryCapabilities;
import org.apache.chemistry.RepositoryInfo;
import org.apache.chemistry.Type;
-import org.apache.commons.collections.Transformer;
-import org.apache.commons.collections.iterators.EmptyIterator;
-import org.apache.commons.collections.iterators.SingletonIterator;
-import org.apache.commons.collections.iterators.TransformIterator;
import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
import org.apache.jackrabbit.commons.cnd.ParseException;
import org.apache.jackrabbit.spi.ChildInfo;
+import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.ItemId;
import org.apache.jackrabbit.spi.ItemInfo;
import org.apache.jackrabbit.spi.Name;
@@ -69,10 +65,17 @@
import org.apache.jackrabbit.spi.RepositoryService;
import org.apache.jackrabbit.spi.SessionInfo;
import org.apache.jackrabbit.spi.commons.AbstractRepositoryService;
+import org.apache.jackrabbit.spi.commons.ChildInfoImpl;
+import org.apache.jackrabbit.spi.commons.NodeInfoImpl;
+import org.apache.jackrabbit.spi.commons.PropertyInfoImpl;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
import org.apache.jackrabbit.spi.commons.nodetype.QDefinitionBuilderFactory;
-import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+import org.apache.jackrabbit.spi2cmis.util.Arrays;
+import org.apache.jackrabbit.spi2cmis.util.Iterators;
+import org.apache.jackrabbit.spi2cmis.util.Streams;
+import org.apache.jackrabbit.spi2cmis.util.Functions.Function;
+import org.apache.jackrabbit.spi2cmis.util.Functions.PartialFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
@@ -82,10 +85,6 @@
* Implements a direct mapping of CMIS types to JCR types and of the CMIS content structure
* to a JCR content structure.
* <ul>
- * <li>todo implement: expose cmis:folder as nt:folder and cmis:document as nt:file
- * </li>
- * <li>todo implement: expose content streams
- * </li>
* <li>todo implement: implement query support
* </li>
* <li>todo implement: access control
@@ -117,7 +116,7 @@
* @param cmisRepository the underlying CMIS repository
* @throws RepositoryException
*/
- protected CmisRepositoryService(Repository cmisRepository) throws RepositoryException {
+ protected CmisRepositoryService(final Repository cmisRepository) throws RepositoryException {
super();
this.cmisRepository = cmisRepository;
@@ -141,9 +140,8 @@
}
// Register JCR related node types
- for (QNodeTypeDefinition ntd : cndReader.getNodeTypeDefinitions()) {
- nodeTypeDefs.registerNodeTypes(new QNodeTypeDefinition[] { ntd }, true);
- }
+ List<QNodeTypeDefinition> jcrTypes = cndReader.getNodeTypeDefinitions();
+ nodeTypeDefs.registerNodeTypes(jcrTypes.toArray(new QNodeTypeDefinition[jcrTypes.size()]), true);
// Register JCR related name spaces
Map<String, String> prefix2Uri = cndReader.getNamespaceMapping().getPrefixToURIMapping();
@@ -153,58 +151,46 @@
// Register node types of the CMIS repository
Collection<Type> cmisTypes = cmisRepository.getTypes();
- QNodeTypeDefinition[] ntds = new QNodeTypeDefinition[cmisTypes.size()];
- int k = 0;
- for (Type cmisType : cmisTypes) {
- ntds[k++] = TypeTransformer.jcrNodeTypeDef(cmisRepository, cmisType, namespaces);
- }
- nodeTypeDefs.registerNodeTypes(ntds, true);
+ nodeTypeDefs.registerNodeTypes(Arrays.map(cmisTypes, new QNodeTypeDefinition[cmisTypes.size()],
+ new PartialFunction<Type, QNodeTypeDefinition, RepositoryException>() {
+ public QNodeTypeDefinition apply(Type cmisType) throws RepositoryException {
+ return TypeTransformer.jcrNodeTypeDef(cmisRepository, cmisType, namespaces);
+ }
+ }), true);
}
- private static void initRepositoryDescriptors(Map<String, QValue[]> descriptors, RepositoryInfo info)
+ private void initRepositoryDescriptors(Map<String, QValue[]> descriptors, RepositoryInfo info)
throws ValueFormatException, RepositoryException {
- QValueFactory qvf = QValueFactoryImpl.getInstance();
+ QValueFactory factory = getQValueFactory();
- descriptors.put(CMIS.DESCRIPTION.toString(), qValue(info.getDescription(), qvf));
- descriptors.put(CMIS.VENDOR_NAME.toString(), qValue(info.getVendorName(), qvf));
- descriptors.put(CMIS.PRODUCT_NAME.toString(), qValue(info.getProductName(), qvf));
- descriptors.put(CMIS.PRODUCT_VERSION.toString(), qValue(info.getProductVersion(), qvf));
- descriptors.put(CMIS.VERSION_SUPPORTED.toString(), qValue(info.getVersionSupported(), qvf));
+ descriptors.put(CMIS.DESCRIPTION.toString(), qValue(info.getDescription(), factory));
+ descriptors.put(CMIS.VENDOR_NAME.toString(), qValue(info.getVendorName(), factory));
+ descriptors.put(CMIS.PRODUCT_NAME.toString(), qValue(info.getProductName(), factory));
+ descriptors.put(CMIS.PRODUCT_VERSION.toString(), qValue(info.getProductVersion(), factory));
+ descriptors.put(CMIS.VERSION_SUPPORTED.toString(), qValue(info.getVersionSupported(), factory));
Document repoSpecific = info.getRepositorySpecificInformation();
if (repoSpecific != null) {
- descriptors.put(CMIS.REPOSITORY_SPECIFIC_INFORMATION.toString(), qValue(repoSpecific.toString(), qvf));
+ descriptors.put(CMIS.REPOSITORY_SPECIFIC_INFORMATION.toString(), qValue(repoSpecific.toString(), factory));
}
RepositoryCapabilities caps = info.getCapabilities();
- descriptors.put(CMIS.CAPABILITY_MULTIFILING.toString(), qValue(caps.hasMultifiling(), qvf));
- descriptors.put(CMIS.CAPABILITY_UNFILING.toString(), qValue(caps.hasUnfiling() , qvf));
- descriptors.put(CMIS.CAPABILITY_VERSION_SPECIFIC_FILING.toString(), qValue(caps.hasVersionSpecificFiling(), qvf));
- descriptors.put(CMIS.CAPABILITY_PWC_UPDATABLE.toString(), qValue(caps.isPWCUpdatable(), qvf));
- descriptors.put(CMIS.CAPABILITY_PWC_SEARCHABLE.toString(), qValue(caps.isPWCSearchable() , qvf));
- descriptors.put(CMIS.CAPABILITY_ALL_VERSIONS_SEARCHABLE.toString(), qValue(caps.isAllVersionsSearchable() , qvf));
- descriptors.put(CMIS.CAPABILITY_CAN_GET_DESCENDANTS.toString(), qValue(caps.hasGetDescendants() , qvf));
- descriptors.put(CMIS.CAPABILITY_CAN_GET_FOLDER_TREE.toString(), qValue(caps.hasGetFolderTree(), qvf));
- descriptors.put(CMIS.CAPABILITY_CONTENT_STREAM_UPDATABILITY.toString(), qValue(caps.isContentStreamUpdatableAnytime() , qvf));
-
- descriptors.put(CMIS.CAPABILITY_QUERY.toString(), qValue(caps.getQueryCapability(), qvf));
- descriptors.put(CMIS.CAPABILITY_JOIN.toString(), qValue(caps.getJoinCapability(), qvf));
- descriptors.put(CMIS.CAPABILITY_RENDITIONS.toString(), qValue(caps.getRenditionCapability(), qvf));
- descriptors.put(CMIS.CAPABILITY_CHANGES.toString(), qValue(caps.getChangeCapability(), qvf));
- descriptors.put(CMIS.CAPABILITY_ACL.toString(), qValue(caps.getACLCapability(), qvf));
- }
-
- private static QValue[] qValue(String value, QValueFactory factory) throws RepositoryException {
- return new QValue[] { factory.create(value, PropertyType.STRING) };
- }
-
- private static QValue[] qValue(boolean value, QValueFactory factory) throws RepositoryException {
- return new QValue[] { factory.create(value) };
- }
-
- private static QValue[] qValue(Enum<?> value, QValueFactory factory) throws RepositoryException {
- return qValue(value.toString(), factory);
+ descriptors.put(CMIS.CAPABILITY_MULTIFILING.toString(), qValue(caps.hasMultifiling(), factory));
+ descriptors.put(CMIS.CAPABILITY_UNFILING.toString(), qValue(caps.hasUnfiling() , factory));
+ descriptors.put(CMIS.CAPABILITY_VERSION_SPECIFIC_FILING.toString(), qValue(caps.hasVersionSpecificFiling(), factory));
+ descriptors.put(CMIS.CAPABILITY_PWC_UPDATABLE.toString(), qValue(caps.isPWCUpdatable(), factory));
+ descriptors.put(CMIS.CAPABILITY_PWC_SEARCHABLE.toString(), qValue(caps.isPWCSearchable() , factory));
+ descriptors.put(CMIS.CAPABILITY_ALL_VERSIONS_SEARCHABLE.toString(), qValue(caps.isAllVersionsSearchable() , factory));
+ descriptors.put(CMIS.CAPABILITY_CAN_GET_DESCENDANTS.toString(), qValue(caps.hasGetDescendants() , factory));
+ descriptors.put(CMIS.CAPABILITY_CAN_GET_FOLDER_TREE.toString(), qValue(caps.hasGetFolderTree(), factory));
+ descriptors.put(CMIS.CAPABILITY_CONTENT_STREAM_UPDATABILITY.toString(), qValue(caps.isContentStreamUpdatableAnytime() , factory));
+
+ descriptors.put(CMIS.CAPABILITY_QUERY.toString(), qValue(caps.getQueryCapability(), factory));
+ descriptors.put(CMIS.CAPABILITY_JOIN.toString(), qValue(caps.getJoinCapability(), factory));
+ descriptors.put(CMIS.CAPABILITY_RENDITIONS.toString(), qValue(caps.getRenditionCapability(), factory));
+ descriptors.put(CMIS.CAPABILITY_CHANGES.toString(), qValue(caps.getChangeCapability(), factory));
+ descriptors.put(CMIS.CAPABILITY_ACL.toString(), qValue(caps.getACLCapability(), factory));
}
private static void close(Reader sr) {
@@ -232,9 +218,10 @@
@Override
protected QNodeDefinition createRootNodeDefinition(SessionInfo sessionInfo) throws RepositoryException {
+ Name rootName = NameTransformer.jcrName(BaseType.FOLDER.getId(), namespaces);
Connection conn = getCmisConnection(sessionInfo);
Folder root = conn.getRootFolder();
- return TypeTransformer.jcrNodeDef(NameConstants.NT_BASE, root.getType(), namespaces);
+ return TypeTransformer.jcrNodeDef(rootName, root.getType(), namespaces);
}
// -----------------------------------------------------< Workspaces >---
@@ -259,36 +246,66 @@
public NodeInfo getNodeInfo(SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
Connection conn = cmisConnections.get(sessionInfo);
- CMISObject obj = getCMISObject(conn, nodeId);
- return ItemTransformer.jcrNode(obj, namespaces);
+
+ if (denotesJcrContent(nodeId)) {
+ // Create node info for synthetic node jcr:content
+ CMISObject parent = getCMISParentObject(conn, nodeId);
+ IdFactory factory = getIdFactory();
+
+ Path parentPath = PathTransformer.jcrPath(parent, namespaces);
+ Path path = getPathFactory().create(parentPath, NameConstants.JCR_CONTENT, false);
+ Iterator<PropertyId> propertyIds = Iterators.iterator (
+ factory.createPropertyId(nodeId, NameConstants.JCR_DATA),
+ factory.createPropertyId(nodeId, NameConstants.JCR_MIMETYPE),
+ factory.createPropertyId(nodeId, NameConstants.JCR_LASTMODIFIED),
+ factory.createPropertyId(nodeId, NameConstants.JCR_LASTMODIFIEDBY)
+ );
+
+ return new NodeInfoImpl(path, nodeId, Path.INDEX_DEFAULT, NameConstants.NT_RESOURCE,
+ Name.EMPTY_ARRAY, Iterators.<Object> empty(), propertyIds, null);
+ }
+ else {
+ CMISObject obj = getCMISObject(conn, nodeId);
+ return ItemTransformer.jcrNodeInfo(obj, namespaces);
+ }
}
public Iterator<? extends ItemInfo> getItemInfos(SessionInfo sessionInfo, NodeId nodeId)
throws RepositoryException {
- // todo implement: batch reading
- return unchecked(new SingletonIterator(getNodeInfo(sessionInfo, nodeId)));
+ return Iterators.<NodeInfo>singleton(getNodeInfo(sessionInfo, nodeId));
}
public Iterator<ChildInfo> getChildInfos(SessionInfo sessionInfo, NodeId parentId)
throws RepositoryException {
+ if (denotesJcrContent(parentId)) {
+ // jcr:content has no children
+ return Iterators.empty();
+ }
+
final Connection conn = cmisConnections.get(sessionInfo);
CMISObject parent = getCMISObject(conn, parentId);
- // If parentId refers to a folder...
+ // If parentId refers...
if (BaseType.FOLDER == parent.getBaseType()) {
- // ... retrieve children and transform them into ChildInfos
+ // ... to a folder, retrieve children and transform them into ChildInfos
ListPage<ObjectEntry> children = conn.getSPI().getChildren(parent, null, null, null); // todo fix: specify inclusions
- return unchecked(new TransformIterator(children.iterator(), new Transformer() {
- public Object transform(Object entry) {
- CMISObject obj = conn.getObject((ObjectId) entry);
- return ItemTransformer.jcrChildInfo(obj, namespaces);
- }
- }));
+
+ return Iterators.map(children.iterator(),
+ new Function<ObjectEntry, ChildInfo>() {
+ public ChildInfo apply(ObjectEntry entry) {
+ CMISObject obj = conn.getObject(entry);
+ return ItemTransformer.jcrChildInfo(obj, namespaces);
+ }});
+ }
+ else if (BaseType.DOCUMENT == parent.getBaseType()) {
+ // ... to a document, add jcr:content as single child node
+ return Iterators.<ChildInfo>singleton(new ChildInfoImpl(NameConstants.JCR_CONTENT, null, Path.INDEX_DEFAULT));
}
else {
- return unchecked(EmptyIterator.INSTANCE);
+ // ... otherwise there are no child nodes
+ return Iterators.empty();
}
}
@@ -296,17 +313,105 @@
boolean weakReferences) throws RepositoryException {
// todo implement: getReferences
- return unchecked(EmptyIterator.INSTANCE);
+ return Iterators.empty();
}
public PropertyInfo getPropertyInfo(SessionInfo sessionInfo, PropertyId propertyId)
throws RepositoryException {
- NodeId parentId = propertyId.getParentId();
- Connection conn = getCmisConnection(sessionInfo);
- CMISObject parent = getCMISObject(conn, parentId);
- Property prop = parent.getProperty(IdTransformer.cmisId(propertyId.getName(), namespaces));
- return ItemTransformer.jcrPropertyInfo(parent, prop, namespaces);
+ Name propertyName = propertyId.getName();
+ CMISObject parentCmisObject;
+ Path parentPath;
+ {
+ Connection conn = getCmisConnection(sessionInfo);
+ NodeId parentId = propertyId.getParentId();
+
+ if (denotesJcrContent(parentId)) {
+ parentCmisObject = getCMISParentObject(conn, parentId);
+ parentPath = PathTransformer.jcrPath(parentCmisObject, namespaces);
+ parentPath = getPathFactory().create(parentPath, NameConstants.JCR_CONTENT, false);
+ }
+ else {
+ parentCmisObject = getCMISObject(conn, parentId);
+ parentPath = PathTransformer.jcrPath(parentCmisObject, namespaces);
+ }
+ }
+
+ Path propertyPath = getPathFactory().create(parentPath, propertyId.getName(), false);
+ final QValueFactory factory = getQValueFactory();
+ try {
+ // Properties from nt:base
+ if (NameConstants.JCR_PRIMARYTYPE.equals(propertyName)) {
+ Name primaryType = TypeTransformer.jcrTypeName(parentCmisObject.getType(), namespaces);
+ QValue[] values = qValue(primaryType, factory);
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.NAME, false, values);
+ }
+ else if (NameConstants.JCR_MIXINTYPES.equals(propertyName)) {
+ Name[] mixinTypes = TypeTransformer.jcrMixinNames(parentCmisObject.getType(), namespaces);
+ QValue[] values = Arrays.map(mixinTypes, new QValue[mixinTypes.length],
+ new PartialFunction<Name, QValue, RepositoryException>() {
+ public QValue apply(Name name) throws RepositoryException {
+ return factory.create(name);
+ }
+ });
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.NAME, true, values);
+ }
+
+ // properties from mix:created
+ else if (NameConstants.JCR_CREATED.equals(propertyName)) {
+ Property prop = parentCmisObject.getProperty("cmis:creationDate");
+ QValue[] values = ValueTransformer.jcrValue(prop);
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.DATE, false, values);
+ }
+ else if (NameConstants.JCR_CREATEDBY.equals(propertyName)) {
+ Property prop = parentCmisObject.getProperty("cmis:createdBy");
+ QValue[] values = ValueTransformer.jcrValue(prop);
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.STRING, false, values);
+ }
+
+ // properties from nt:resource
+ else if (NameConstants.JCR_DATA.equals(propertyName)) {
+ QValue[] values;
+ try {
+ ContentStream content = parentCmisObject.getContentStream(null);
+ values = qValue(content.getStream(), factory);
+ }
+ catch (UnsupportedOperationException e) {
+ // todo fix: Remove when SimpleObject#getContentStream is implemented
+ values = qValue(Streams.emptyInStream(), factory);
+ }
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.BINARY, false, values);
+ }
+
+ // properties from mix:lastModified
+ else if (NameConstants.JCR_LASTMODIFIED.equals(propertyName)) {
+ Property prop = parentCmisObject.getProperty("cmis:lastModificationDate");
+ QValue[] values = ValueTransformer.jcrValue(prop);
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.DATE, false, values);
+ }
+ else if (NameConstants.JCR_LASTMODIFIEDBY.equals(propertyName)) {
+ Property prop = parentCmisObject.getProperty("cmis:lastModifiedBy");
+ QValue[] values = ValueTransformer.jcrValue(prop);
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.STRING, false, values);
+ }
+
+ // properties from mix:mimeType
+ else if (NameConstants.JCR_MIMETYPE.equals(propertyName)) {
+ Property prop = parentCmisObject.getProperty("cmis:contentStreamMimeType");
+ QValue[] values = ValueTransformer.jcrValue(prop);
+ return new PropertyInfoImpl(propertyPath, propertyId, PropertyType.STRING, false, values);
+ }
+ else {
+ Property prop = parentCmisObject.getProperty(IdTransformer.cmisId(propertyName, namespaces));
+ return ItemTransformer.jcrPropertyInfo(parentCmisObject, prop, namespaces);
+ }
+ }
+ catch (ValueFormatException e) {
+ throw new PathNotFoundException(e);
+ }
+ catch (IOException e) {
+ throw new PathNotFoundException(e);
+ }
}
// -----------------------------------------------------< private >---
@@ -329,7 +434,7 @@
/**
* Retrieve the CMIS object identified by the given nodeId from a CMIS connection.
*/
- private CMISObject getCMISObject(Connection conn, NodeId nodeId) throws RepositoryException {
+ private static CMISObject getCMISObject(Connection conn, NodeId nodeId) throws RepositoryException {
String uuid = nodeId.getUniqueID();
Path path = nodeId.getPath();
@@ -349,15 +454,59 @@
// Otherwise construct the full CMIS path from an absolute part and a relative part.
String abs = uuid == null
? ""
- : PathTransformer.cmisPath(o) + '/';
+ : PathTransformer.cmisPath(o);
String rel = PathTransformer.cmisPath(path);
- ObjectEntry entry = conn.getSPI().getObjectByPath(abs + rel, null); // todo fix: specify inclusions
+ ObjectEntry entry = conn.getSPI().getObjectByPath(concat(abs, rel), null); // todo fix: specify inclusions
if (entry == null) {
throw new PathNotFoundException();
}
return conn.getObject(entry);
}
+ private CMISObject getCMISParentObject(Connection conn, NodeId nodeId) throws RepositoryException {
+ String uuid = nodeId.getUniqueID();
+ Path parentPath = nodeId.getPath().getAncestor(1);
+ NodeId id = getIdFactory().createNodeId(uuid, parentPath);
+ return getCMISObject(conn, id);
+ }
+
+ private static String concat(String p1, String p2) {
+ if ("".equals(p1) || "".equals(p2)) {
+ return p1 + p2;
+ }
+ else {
+ return p1 + '/' + p2;
+ }
+ }
+
+ /**
+ * Determine whether a nodeId identifies a jcr:content node
+ */
+ private static boolean denotesJcrContent(NodeId nodeId) {
+ Path path = nodeId.getPath();
+ return path != null && NameConstants.JCR_CONTENT.equals(path.getNameElement().getName());
+ }
+
+ private static QValue[] qValue(String value, QValueFactory factory) throws RepositoryException {
+ return new QValue[] { factory.create(value, PropertyType.STRING) };
+ }
+
+ private static QValue[] qValue(boolean value, QValueFactory factory) throws RepositoryException {
+ return new QValue[] { factory.create(value) };
+ }
+
+ private static QValue[] qValue(Enum<?> value, QValueFactory factory) throws RepositoryException {
+ return qValue(value.toString(), factory);
+ }
+
+ private static QValue[] qValue(Name value, QValueFactory factory) throws RepositoryException {
+ return new QValue[] { factory.create(value) };
+ }
+
+ private static QValue[] qValue(InputStream value, QValueFactory factory) throws RepositoryException, IOException {
+ return new QValue[] { factory.create(value) };
+ }
+
}
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ItemTransformer.java Tue Jan 26 17:56:54 2010
@@ -16,9 +16,9 @@
*/
package org.apache.jackrabbit.spi2cmis;
-import static org.apache.jackrabbit.spi2cmis.SuppressWarning.unchecked;
-
+import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import javax.jcr.Item;
@@ -28,11 +28,6 @@
import org.apache.chemistry.Property;
import org.apache.chemistry.PropertyDefinition;
import org.apache.chemistry.Type;
-import org.apache.commons.collections.Predicate;
-import org.apache.commons.collections.Transformer;
-import org.apache.commons.collections.iterators.EmptyIterator;
-import org.apache.commons.collections.iterators.FilterIterator;
-import org.apache.commons.collections.iterators.TransformIterator;
import org.apache.jackrabbit.spi.ChildInfo;
import org.apache.jackrabbit.spi.IdFactory;
import org.apache.jackrabbit.spi.Name;
@@ -46,13 +41,16 @@
import org.apache.jackrabbit.spi.commons.NodeInfoImpl;
import org.apache.jackrabbit.spi.commons.PropertyInfoImpl;
import org.apache.jackrabbit.spi.commons.identifier.IdFactoryImpl;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+import org.apache.jackrabbit.spi2cmis.util.Iterators;
+import org.apache.jackrabbit.spi2cmis.util.Predicate;
+import org.apache.jackrabbit.spi2cmis.util.Functions.Function;
/**
* Utility class to transform {@link CMISObject}s to JCR {@link Item}s.
*/
public class ItemTransformer {
-
private static final IdFactory ID_FACTORY = IdFactoryImpl.getInstance();
private ItemTransformer() {
@@ -61,39 +59,58 @@
/**
* Transform a {@link CMISObject} into a {@link NodeInfo} with respect to a name space mapping.
- * @param cmidObject {@link CMISObject}
+ * @param cmisObject {@link CMISObject}
* @param namespaces name space mapping
* @return JCR {@link NodeInfo}
*/
- public static NodeInfo jcrNode(CMISObject cmidObject, final NamespaceMapping namespaces) {
- Path path = PathTransformer.jcrPath(cmidObject, namespaces);
- final NodeId nodeId = IdTransformer.jcrId(cmidObject);
-
- Type type = cmidObject.getType();
- Name primaryTypeName = NameTransformer.jcrName(type.getId(), namespaces);
-
- // todo implement: include references
- Iterator<PropertyId> references = unchecked(EmptyIterator.INSTANCE);
+ public static NodeInfo jcrNodeInfo(CMISObject cmisObject, final NamespaceMapping namespaces) {
+ Path path = PathTransformer.jcrPath(cmisObject, namespaces);
+ final NodeId nodeId = IdTransformer.jcrId(cmisObject);
+
+ Type cmisType = cmisObject.getType();
+ Name primaryTypeName = TypeTransformer.jcrTypeName(cmisType, namespaces);
+ Name[] mixins = TypeTransformer.jcrMixinNames(cmisType, namespaces);
+ Iterator<PropertyId> references = Iterators.empty(); // todo implement: include references
// From all properties...
- final Map<String, Property> properties = cmidObject.getProperties();
+ final Map<String, Property> properties = cmisObject.getProperties();
- // ... filter out the ones having null values
- FilterIterator nonNullProperties = new FilterIterator(properties.keySet().iterator(), new Predicate() {
- public boolean evaluate(Object id) {
- return properties.get(id).getValue() != null;
- }
- });
+ // ... retain the properties having its value set
+ Iterator<String> setProperties = Iterators
+ .filter(properties.keySet().iterator(), new Predicate<String>() {
+ public boolean evaluate(String id) {
+ return ValueTransformer.hasValue(properties.get(id));
+ }
+ });
// ... and transform them into valid JCR names
- Iterator<PropertyId> propertyIds = unchecked(new TransformIterator(nonNullProperties, new Transformer() {
- public Object transform(Object id) {
- Name propertyName = NameTransformer.jcrName((String) id, namespaces);
- return ID_FACTORY.createPropertyId(nodeId, propertyName);
+ Iterator<PropertyId> transformedPropertyIds = Iterators
+ .map(setProperties, new Function<String, PropertyId>(){
+ public PropertyId apply(String id) {
+ Name propertyName = NameTransformer.jcrName(id, namespaces);
+ return ID_FACTORY.createPropertyId(nodeId, propertyName);
+ }
+ });
+
+ // ... and add properties of nt:base
+ List<PropertyId> additionalPropertyIds = new ArrayList<PropertyId>();
+ additionalPropertyIds.add(ID_FACTORY.createPropertyId(nodeId, NameConstants.JCR_PRIMARYTYPE));
+ additionalPropertyIds.add(ID_FACTORY.createPropertyId(nodeId, NameConstants.JCR_MIXINTYPES));
+
+ // ... and if this is a hierarchy node from nt:hierarchy
+ if (TypeTransformer.isHierarchyNode(cmisType)) {
+ if (ValueTransformer.hasValue(properties.get("cmis:creationDate"))) {
+ additionalPropertyIds.add(ID_FACTORY.createPropertyId(nodeId, NameConstants.JCR_CREATED));
}
- }));
+ if (ValueTransformer.hasValue(properties.get("cmis:createdBy"))) {
+ additionalPropertyIds.add(ID_FACTORY.createPropertyId(nodeId, NameConstants.JCR_CREATEDBY));
+ }
+ }
+
+ Iterator<PropertyId> propertyIds = Iterators
+ .chain(transformedPropertyIds, additionalPropertyIds.iterator());
- return new NodeInfoImpl(path, nodeId, 0, primaryTypeName, new Name[0], references, propertyIds, null);
+ return new NodeInfoImpl(path, nodeId, 0, primaryTypeName, mixins, references, propertyIds, null);
}
/**
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/PathTransformer.java Tue Jan 26 17:56:54 2010
@@ -52,6 +52,11 @@
StringBuilder s = new StringBuilder();
boolean first = true;
for (Path.Element element : path.getNormalizedPath().getElements()) {
+ if (element.denotesCurrent()) {
+ continue;
+ }
+ assert !element.denotesParent();
+
if (element.denotesRoot()) {
s.append('/');
}
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/TypeTransformer.java Tue Jan 26 17:56:54 2010
@@ -32,6 +32,7 @@
import org.apache.chemistry.Repository;
import org.apache.chemistry.Type;
import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NameFactory;
import org.apache.jackrabbit.spi.QNodeDefinition;
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
import org.apache.jackrabbit.spi.QPropertyDefinition;
@@ -41,12 +42,14 @@
import org.apache.jackrabbit.spi.commons.QNodeTypeDefinitionImpl;
import org.apache.jackrabbit.spi.commons.QPropertyDefinitionImpl;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
/**
* Utility class to transform CMIS {@link Type}s to JCR {@link QNodeTypeDefinition}s.
*/
public class TypeTransformer {
+ private static final NameFactory nameFactory = NameFactoryImpl.getInstance();
private TypeTransformer() {
super();
@@ -67,12 +70,23 @@
Name name = NameTransformer.jcrName(cmisType.getId(), namespaces);
String parentId = cmisType.getParentId();
- Name[] supertypes = parentId == null
- ? Name.EMPTY_ARRAY
- : new Name[] { NameTransformer.jcrName(parentId, namespaces) };
- Name[] supportedMixins = Name.EMPTY_ARRAY;
- boolean isMixin = false;
+ Name[] supertypes;
+ if (isFolder(cmisType)) {
+ supertypes = new Name[] { NameConstants.NT_FOLDER };
+ }
+ else if (isDocument(cmisType)) {
+ supertypes = new Name[] { NameConstants.NT_FILE };
+ }
+ else if (parentId == null) {
+ supertypes = new Name[] { NameConstants.NT_BASE };
+ }
+ else {
+ supertypes = new Name[] { NameTransformer.jcrName(parentId, namespaces) };
+ }
+
+ Name[] supportedMixins = null;
+ boolean isMixin = isFolder(cmisType);
boolean isAbstract = false;
boolean isQueryable = cmisType.isQueryable();
boolean hasOrderableChildNodes = false;
@@ -90,16 +104,9 @@
QPropertyDefinition[] declaredPropDefs = dpd.toArray(new QPropertyDefinition[dpd.size()]);
- QNodeDefinition[] declaredNodeDefs;
- if (BaseType.FOLDER.getId().equals(cmisType.getId())) {
- declaredNodeDefs = new QNodeDefinition[] { createResidualNodeDef(name) };
- }
- else {
- declaredNodeDefs = QNodeDefinition.EMPTY_ARRAY;
- }
-
return new QNodeTypeDefinitionImpl(name, supertypes, supportedMixins, isMixin, isAbstract,
- isQueryable, hasOrderableChildNodes, primaryItemName, declaredPropDefs, declaredNodeDefs);
+ isQueryable, hasOrderableChildNodes, primaryItemName, declaredPropDefs,
+ QNodeDefinition.EMPTY_ARRAY);
}
/**
@@ -171,6 +178,78 @@
return ValueTransformer.getValueTransformer(cmisPropertyType).getJcrPropertyType();
}
+ /**
+ * Name of the JCR type for a CMIS type with respect to a name space mapping
+ * @param cmisType
+ * @param namespaces
+ * @return JCR type Name
+ */
+ public static Name jcrTypeName(Type cmisType, NamespaceMapping namespaces) {
+ if (isFolder(cmisType)) {
+ return NameConstants.NT_FOLDER;
+ }
+ else if (isDocument(cmisType)) {
+ return NameConstants.NT_FILE;
+ }
+ else {
+ return NameTransformer.jcrName(cmisType.getId(), namespaces);
+ }
+ }
+
+ /**
+ * Names of the JCR mixins for a CMIS type with respect to a name space mapping
+ * @param cmisType
+ * @param namespaces
+ * @return JCR mixin type names
+ */
+ public static Name[] jcrMixinNames(Type cmisType, NamespaceMapping namespaces) {
+ if (TypeTransformer.isFolder(cmisType)) {
+ return new Name[] { NameTransformer.jcrName(BaseType.FOLDER.getId(), namespaces) };
+ }
+ else if (TypeTransformer.isDocument(cmisType)) {
+ return new Name[] { NameTransformer.jcrName(BaseType.DOCUMENT.getId(), namespaces) };
+ }
+ else {
+ return Name.EMPTY_ARRAY;
+ }
+ }
+
+ /**
+ * Determines whether a type is a cmis:folder
+ * @param cmisType
+ * @return true iff <code>cmisType</code> is a cmis:folder and no other sub type
+ * of cmis:folder.
+ */
+ public static boolean isFolder(Type cmisType) {
+ return BaseType.FOLDER.getId().equals(cmisType.getId());
+ }
+
+ /**
+ * Determines whether a type is a cmis:document
+ * @param cmisType
+ * @return true iff <code>cmisType</code> is a cmis:document no other sub type
+ * of cmis:document.
+ */
+ public static boolean isDocument(Type cmisType) {
+ return BaseType.DOCUMENT.getId().equals(cmisType.getId());
+ }
+
+ /**
+ * Determines whether a type is a hierarchy type. A hierarchy type is a type whose
+ * base type is wither cmis:document or cmis:folder.
+ * @param cmisType
+ * @return true iff <code>cmisType</code> is a hierarchy type
+ */
+ public static boolean isHierarchyNode(Type cmisType) {
+ switch (cmisType.getBaseType()) {
+ case DOCUMENT:
+ case FOLDER:
+ return true;
+ default:
+ return false;
+ }
+ }
+
// -----------------------------------------------------< >---
private static Set<String> getSuperTypeProperties(Repository cmisRepository, Type cmisType) {
@@ -199,17 +278,4 @@
return ids;
}
- private static QNodeDefinitionImpl createResidualNodeDef(Name declaringNodeType) {
- Name name = NameConstants.ANY_NAME;
- boolean isAutoCreated = false;
- boolean isMandatory = false;
- int onParentVersion = OnParentVersionAction.IGNORE;
- boolean isProtected = false;
- Name defaultPrimaryType = NameConstants.NT_BASE;
- Name[] requiredPrimaryTypes = { NameConstants.NT_BASE };
- boolean allowsSameNameSiblings = false;
- return new QNodeDefinitionImpl(name, declaringNodeType, isAutoCreated, isMandatory, onParentVersion,
- isProtected, defaultPrimaryType, requiredPrimaryTypes, allowsSameNameSiblings);
- }
-
}
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/ValueTransformer.java Tue Jan 26 17:56:54 2010
@@ -20,7 +20,6 @@
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@@ -28,12 +27,15 @@
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
+import javax.jcr.ValueFormatException;
import org.apache.chemistry.Property;
import org.apache.chemistry.PropertyDefinition;
import org.apache.jackrabbit.spi.QValue;
import org.apache.jackrabbit.spi.QValueFactory;
import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
+import org.apache.jackrabbit.spi2cmis.util.Arrays;
+import org.apache.jackrabbit.spi2cmis.util.Functions.PartialFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -95,7 +97,7 @@
new HashMap<org.apache.chemistry.PropertyType, ValueTransformer>();
static {
- for (ValueTransformer t : Arrays.asList(
+ for (ValueTransformer t : java.util.Arrays.asList (
DECIMAL_VALUE_TRANSFORMER, INTEGER_VALUE_TRANSFORMER, BOOLEAN_VALUE_TRANSFORMER,
DATE_TIME_VALUE_TRANSFORMER, URI_VALUE_TRANSFORMER, ID_VALUE_TRANSFORMER,
STRING_VALUE_TRANSFORMER, HTML_VALUE_TRANSFORMER
@@ -117,29 +119,43 @@
* @throws RepositoryException
*/
public static QValue[] jcrValue(Property cmisProperty) throws RepositoryException {
- PropertyDefinition def = cmisProperty.getDefinition();
- Serializable val = cmisProperty.getValue();
- return jcrValue(val, def.getType());
+ if (hasValue(cmisProperty)) {
+ PropertyDefinition def = cmisProperty.getDefinition();
+ return jcrValue(cmisProperty.getValue(), def.getType());
+ }
+ else {
+ throw new ValueFormatException("Null value not allowed");
+ }
+ }
+
+ /**
+ * Determines if a property value is set
+ * @param cmisProperty
+ * @return true iff the value of <code>cmisProperty</code> is set.
+ */
+ public static boolean hasValue(Property cmisProperty) {
+ return cmisProperty.getValue() != null;
}
/**
* Transforms a CMIS value to a JCR {@link QValue}.
- * @param cmisValue CMIS value
- * @param cmisPropertyType CMIS {@link org.apache.chemistry.PropertyType}
- * @return JCR {@link QValue}
+ *
+ * @param cmisValue CMIS value
+ * @param cmisPropertyType CMIS {@link org.apache.chemistry.PropertyType}
+ * @return JCR {@link QValue}
* @throws RepositoryException
*/
- public static QValue[] jcrValue(Serializable cmisValue, org.apache.chemistry.PropertyType cmisPropertyType)
+ public static QValue[] jcrValue(Serializable cmisValue, final org.apache.chemistry.PropertyType cmisPropertyType)
throws RepositoryException {
if (cmisValue.getClass().isArray()) {
- Serializable[] values = (Serializable[]) cmisValue;
- QValue[] qValues = new QValue[values.length];
- int k = 0;
- for (Serializable v : values) {
- qValues[k++] = getValueTransformer(cmisPropertyType).getQValue(v);
- }
- return qValues;
+ return Arrays.map((Serializable[]) cmisValue, new QValue[((Serializable[]) cmisValue).length],
+ new PartialFunction<Serializable, QValue, RepositoryException>() {
+ public QValue apply(Serializable value) throws RepositoryException {
+ return getValueTransformer(cmisPropertyType).getQValue(value);
+ }
+ });
+
}
else {
return new QValue[] { getValueTransformer(cmisPropertyType).getQValue(cmisValue) };
Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Arrays.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Arrays.java?rev=903343&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Arrays.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Arrays.java Tue Jan 26 17:56:54 2010
@@ -0,0 +1,94 @@
+/*
+ * 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.jackrabbit.spi2cmis.util;
+
+import java.util.Iterator;
+
+import org.apache.jackrabbit.spi2cmis.util.Functions.PartialFunction;
+
+/**
+ * Utility classed providing methods for mapping functions over arrays
+ */
+public class Arrays {
+
+ private Arrays() {
+ super();
+ }
+
+ /**
+ * Map a {@link PartialFunction} over a <code>source</code> array and store the results into a
+ * <code>target</code> array.
+ * @param <S>
+ * @param <T>
+ * @param <E>
+ * @param source
+ * @param target
+ * @param f
+ * @return
+ * @throws E
+ */
+ public static <S, T, E extends Throwable> T[] map(S[] source, T[] target, PartialFunction<S, T, E> f) throws E {
+ int k = 0;
+ for (S s : source) {
+ target[k++] = f.apply(s);
+ }
+
+ return target;
+ }
+
+ /**
+ * Map a {@link PartialFunction} over an interable <code>source</code> and store the results into a
+ * <code>target</code> array.
+ * @param <S>
+ * @param <T>
+ * @param <E>
+ * @param source
+ * @param target
+ * @param f
+ * @return
+ * @throws E
+ */
+ public static <S, T, E extends Throwable> T[] map(Iterable<S> source, T[] target, PartialFunction<S, T, E> f) throws E {
+ int k = 0;
+ for (S s : source) {
+ target[k++] = f.apply(s);
+ }
+
+ return target;
+ }
+
+ /**
+ * Map a {@link PartialFunction} over a <code>source</code> iterator and store the results into a
+ * <code>target</code> array.
+ * @param <S>
+ * @param <T>
+ * @param <E>
+ * @param source
+ * @param target
+ * @param f
+ * @return
+ * @throws E
+ */
+ public static <S, T, E extends Throwable> T[] map(final Iterator<S> source, T[] target, PartialFunction<S, T, E> f) throws E {
+ return map(new Iterable<S>() {
+ public Iterator<S> iterator() {
+ return source;
+ }
+ }, target, f);
+ }
+
+}
Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Arrays.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Functions.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Functions.java?rev=903343&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Functions.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Functions.java Tue Jan 26 17:56:54 2010
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.spi2cmis.util;
+
+/**
+ * Helper class providing definitions for {@link Function} and {@link PartialFunction}.
+ */
+public class Functions {
+
+ private Functions() {
+ super();
+ }
+
+ /**
+ * A partial function taking an argument of type <code>S</code> to a value of
+ * type <code>T</code> or throwing an exception of type <code>E</code>.
+ * @param <S>
+ * @param <T>
+ * @param <E>
+ */
+ public interface PartialFunction<S, T, E extends Throwable> {
+ public T apply(S s) throws E;
+ }
+
+ /**
+ * A function taking an argument of type <code>S</code> to a value of
+ * type <code>T</code>. <code>Function</code> is a sub type of
+ * {@link PartialFunction} which never throws an exception.
+ * @param <S>
+ * @param <T>
+ */
+ public interface Function<S, T> extends PartialFunction<S, T, None>{
+ public T apply(S s);
+ }
+
+ class None extends Error{ /* empty */}
+
+}
\ No newline at end of file
Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Functions.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Iterators.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Iterators.java?rev=903343&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Iterators.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Iterators.java Tue Jan 26 17:56:54 2010
@@ -0,0 +1,117 @@
+/*
+ * 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.jackrabbit.spi2cmis.util;
+
+import java.util.Iterator;
+
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.collections.iterators.ArrayIterator;
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.FilterIterator;
+import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.commons.collections.iterators.SingletonIterator;
+import org.apache.commons.collections.iterators.TransformIterator;
+import org.apache.jackrabbit.spi2cmis.util.Functions.Function;
+
+/**
+ * Helper class providing type safe wrappers for the Iterators provided in Apache
+ * Commons Collection.
+ */
+public class Iterators {
+
+ private Iterators() {
+ super();
+ }
+
+ /**
+ * Iterator of a single value of type <code>T</code>.
+ * @param <T>
+ * @param value
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterator<T> singleton(T value) {
+ return new SingletonIterator(value);
+ }
+
+ /**
+ * Map a {@link Functions} of an iterator.
+ * @param <S>
+ * @param <T>
+ * @param source
+ * @param f
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <S, T> Iterator<T> map(Iterator<S> source, final Function<S, T> f) {
+ return new TransformIterator(source, new Transformer() {
+ public Object transform(Object o) {
+ return f.apply((S) o);
+ }
+ });
+ }
+
+ /**
+ * Filter an iterator according to a {@link Predicate}.
+ * @param <T>
+ * @param source
+ * @param predicate
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterator<T> filter(Iterator<T> source, final Predicate<T> predicate) {
+ return new FilterIterator(source, new org.apache.commons.collections.Predicate() {
+ public boolean evaluate(Object object) {
+ return predicate.evaluate((T) object);
+ }
+ });
+ }
+
+ /**
+ * Chain two iterators
+ * @param <T>
+ * @param first
+ * @param second
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterator<T> chain(Iterator<T> first, Iterator<T> second) {
+ return new IteratorChain(first, second);
+ }
+
+ /**
+ * Empty iterator
+ * @param <T>
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterator<T> empty() {
+ return EmptyIterator.INSTANCE;
+ }
+
+ /**
+ * Iterator over a set of values
+ * @param <T>
+ * @param values
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterator<T> iterator(T... values) {
+ return new ArrayIterator(values);
+ }
+
+}
Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Iterators.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Predicate.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Predicate.java?rev=903343&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Predicate.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Predicate.java Tue Jan 26 17:56:54 2010
@@ -0,0 +1,25 @@
+/*
+ * 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.jackrabbit.spi2cmis.util;
+
+/**
+ * Predicate
+ * @param <T>
+ */
+public interface Predicate<T> {
+ public boolean evaluate(T value);
+}
Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Predicate.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Streams.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Streams.java?rev=903343&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Streams.java (added)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Streams.java Tue Jan 26 17:56:54 2010
@@ -0,0 +1,48 @@
+/*
+ * 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.jackrabbit.spi2cmis.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Utility class for handling streams.
+ */
+public class Streams {
+ private final static InputStream EMPTY_IN_STREAM = new EmptyInputStream();
+
+ private Streams() {
+ super();
+ }
+
+ /**
+ * Empty input stream
+ * @return
+ */
+ public static InputStream emptyInStream() {
+ return EMPTY_IN_STREAM;
+ }
+
+ // -----------------------------------------------------< private >---
+
+ private static class EmptyInputStream extends InputStream {
+ @Override
+ public int read() throws IOException {
+ return -1;
+ }
+ }
+}
Propchange: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/java/org/apache/jackrabbit/spi2cmis/util/Streams.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/main/resources/nodetypes.cnd Tue Jan 26 17:56:54 2010
@@ -23,5 +23,29 @@
<xml='http://www.w3.org/XML/1998/namespace'>
[nt:base]
-- jcr:primaryType (NAME) autocreated mandatory protected COMPUTE
-- jcr:mixinTypes (NAME) autocreated mandatory protected multiple COMPUTE
\ No newline at end of file
+- jcr:primaryType (NAME) autocreated mandatory protected
+- jcr:mixinTypes (NAME) autocreated mandatory protected multiple
+
+[mix:created] mixin
+- jcr:created (DATE) autocreated protected
+- jcr:createdBy (STRING) autocreated protected
+
+[mix:lastModified] mixin
+- jcr:lastModified (DATE) autocreated protected
+- jcr:lastModifiedBy (STRING) autocreated protected
+
+[mix:mimeType] mixin
+- jcr:mimeType (STRING) protected
+- jcr:encoding (STRING) protected
+
+[nt:hierarchyNode] > nt:base, mix:created abstract
+
+[nt:file] > nt:hierarchyNode primaryitem jcr:content
++ jcr:content (nt:base) mandatory
+
+[nt:folder] > nt:hierarchyNode
++ * (nt:hierarchyNode)
+
+[nt:resource] > nt:base, mix:mimeType, mix:lastModified
+primaryitem jcr:data
+- jcr:data (BINARY) mandatory
Modified: jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/ReadTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/ReadTest.java?rev=903343&r1=903342&r2=903343&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/ReadTest.java (original)
+++ jackrabbit/sandbox/jackrabbit-spi2cmis/src/test/java/org/apache/jackrabbit/spi2cmis/ReadTest.java Tue Jan 26 17:56:54 2010
@@ -30,9 +30,11 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
+import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.PropertyDefinition;
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
import org.apache.jackrabbit.spi.commons.QNodeTypeDefinitionImpl;
@@ -130,6 +132,27 @@
}
}
+ public void testGetBinaryValue() throws RepositoryException {
+ String paths[] = {
+// "/Sites/Franki/d2.txt/jcr:content/jcr:data",
+// "/default-domain/workspaces/demo-workspace/testi/jcr:content/jcr:data",
+ "/folder 1/folder 2/doc 3/jcr:content/jcr:data",
+ };
+
+ Session session = repository.login();
+ try {
+ for (String path : paths) {
+ Property property = session.getProperty(path);
+ assertEquals(path, property.getPath());
+ dumpProperty(property);
+ System.out.println(property.getString());
+ }
+ }
+ finally {
+ session.logout();
+ }
+ }
+
public void testTraverse() throws RepositoryException {
String paths[] = { "/" };
@@ -149,7 +172,8 @@
private static void dumpNode(Node node, boolean recursive) throws RepositoryException {
NodeType nt = node.getPrimaryNodeType();
- System.out.println(node.getPath() + ": " + nt.getName());
+ NodeDefinition nd = node.getDefinition();
+ System.out.println(node.getPath() + ": " + nt.getName() + " (" + nd.getName() + ")");
dumpProperties(node);
@@ -168,19 +192,29 @@
private static void dumpProperty(Property property) throws RepositoryException {
String value;
+ PropertyDefinition pd = property.getDefinition();
+
if (property.isMultiple()) {
Value[] values = property.getValues();
value = "[";
for (Value v : values) {
- value += (v.getString() + ", ");
+ if (PropertyType.BINARY == v.getType()) {
+ value += "[[BINARY]], ";
+ }
+ else {
+ value += (v.getString() + ", ");
+ }
}
value += "]";
}
+ else if (PropertyType.BINARY == property.getType()) {
+ value = "[[BINARY]]";
+ }
else {
value = property.getString();
}
System.out.println(property.getPath() + ": " + PropertyType.nameFromValue(property.getType())
- + " = " + value);
+ + "(" + pd.getName() + ") = " + value);
}
}