Author: suat
Date: Thu Aug 25 15:10:51 2011
New Revision: 1161598
URL: http://svn.apache.org/viewvc?rev=1161598&view=rev
Log:
STANBOL 306:
jcr:
-Implemented methods defined in RDFMapper interface
-Reverted the extended JCRRepositoryAccess interface as the additional method
is not used
cmis:
-Updated implementation of the method to map a given RDF into the repository.
As a short explanation, for each object represented in the RDF, one folder and
two documents are created in the repository. One document contains the RDF
metadata of the object, other document represents the object itself and the
folder contains those documents. Some detailed information can be found in the
Javadocs CMISRDFMapper class.
-Next step for CMIS module is to code default implementation of the method that
generates RDF data from content repository.
Added:
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccess.java
- copied, changed from r1156602,
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccessImpl.java
Removed:
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccessImpl.java
Modified:
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRDFMapper.java
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRepositoryAccess.java
incubator/stanbol/trunk/cmsadapter/jcr/pom.xml
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRDFMapper.java
Modified:
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRDFMapper.java
URL:
http://svn.apache.org/viewvc/incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRDFMapper.java?rev=1161598&r1=1161597&r2=1161598&view=diff
==============================================================================
---
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRDFMapper.java
(original)
+++
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRDFMapper.java
Thu Aug 25 15:10:51 2011
@@ -38,56 +38,75 @@ import org.apache.chemistry.opencmis.com
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.Triple;
-import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
import org.apache.clerezza.rdf.core.serializedform.Serializer;
import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
+import org.apache.stanbol.cmsadapter.core.mapping.BaseRDFMapper;
import org.apache.stanbol.cmsadapter.core.mapping.RDFBridgeHelper;
import org.apache.stanbol.cmsadapter.servicesapi.helper.CMSAdapterVocabulary;
-import org.apache.stanbol.cmsadapter.servicesapi.mapping.RDFBridgeException;
+import org.apache.stanbol.cmsadapter.servicesapi.mapping.RDFBridge;
import org.apache.stanbol.cmsadapter.servicesapi.mapping.RDFMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Implementation of {@link RDFMapper} for CMIS repositories. While
transforming annotated RDF data to
- * repository, this class first takes root objects, i.e object having no
- * {@link CMSAdapterVocabulary#CMS_OBJECT_PARENT_REF} annotations. All
children of root objects are created as
- * documents in the same folder with the top root object as CMIS allows
setting a hierarchy with Folders only.<br>
- * <br>
- * For example, if an object has path /a/b/c/object path and has child objects
as cobject1 and cobject2. First
- * a, b, c folders are tried to be created and then all three object are
created in c folder. <br>
- * <br>
- * Custom properties to be mapped, child and parent annotations for a document
are selected from the annotated
- * graph collected in a separate graph, serialized as RDF/XML and serialized
RDF is set as
- * {@link ContentStream} of document.
+ * Implementation of {@link RDFMapper} for CMIS repositories.
+ * <p>
+ * As CMIS specification does not allow hierarchy in the documents and custom
properties for documents and
+ * folders, a folder-document mix workaround is applied to represent
hierarchical structures. See the
+ * explanations in {@link #storeRDFinRepository(Object, MGraph)} and
+ * {@link #generateRDFFromRepository(Object, String)}.
*
* @author suat
*
*/
@Component(immediate = true)
@Service
-public class CMISRDFMapper implements RDFMapper {
+public class CMISRDFMapper extends BaseRDFMapper implements RDFMapper {
private static final Logger log =
LoggerFactory.getLogger(CMISRDFMapper.class);
- private static final String DOCUMENT_RDF = "document_RDF";
+ private static final String DOCUMENT_RDF = "_metadata";
private static final String DOCUMENT_RDF_MIME_TYPE = "text/plain";
@Reference
Serializer serializer;
+ /**
+ * This implementation of {@link RDFMapper#storeRDFinRepository(Object,
MGraph)} realizes a workaround to
+ * come up with the restriction of not being able to create hierarchical
documents and set custom
+ * properties to documents.
+ * <p>
+ * The workaround is to create 3 object in the content repository for each
object that will normally be
+ * created from the RDF data. For example if a single object named
<b>MyObject</b> is expected to be
+ * created from the annotated RDF data in the content repository, first of
all a {@link Folder} named
+ * <b>MyObject</b> will be created. In this folder a {@link Document}
named <b>MyObject</b> representing
+ * the actual object and another document named <b>MyObject_metadata</b>
will be created.
+ * <p>
+ * Child relations between is set through the folder hierarchy and
<b>MyObject_metadata</b> contains an
+ * RDF data formed by the {@link RDFBridge}.
+ *
+ * @param session
+ * {@link Session} object to access the repository
+ * @param annotatedGraph
+ * annotated {@link MGraph} with CMS vocabulary annotations.
For details see
+ * {@link RDFMapper#storeRDFinRepository(Object, MGraph)}
+ */
@Override
- public void storeRDFinRepository(Object session, String rootPath, MGraph
annotatedGraph) throws RDFBridgeException {
- List<NonLiteral> rootObjects =
RDFBridgeHelper.getRootObjetsOfGraph(annotatedGraph);
+ public void storeRDFinRepository(Object session, MGraph annotatedGraph) {
+ List<NonLiteral> rootObjects =
RDFBridgeHelper.getRootObjectsOfGraph(annotatedGraph);
for (NonLiteral root : rootObjects) {
- String documentName = RDFBridgeHelper.getResourceStringValue(root,
- CMSAdapterVocabulary.CMS_OBJECT_NAME, annotatedGraph);
- Folder rootFolder = checkCreateParentNodes(rootPath, (Session)
session);
- createDocument(rootFolder, root, documentName, annotatedGraph,
(Session) session);
+ String documentName = getObjectName(root, annotatedGraph);
+ String documentPath = getObjectPath(root, documentName,
annotatedGraph);
+ Folder rootFolder = checkCreateParentFolders(documentPath,
(Session) session);
+ if (rootFolder != null) {
+ createDocument(rootFolder, root, documentName, annotatedGraph,
(Session) session);
+ } else {
+ log.warn("Failed to get Folder for path: {}", documentPath);
+ }
}
}
@@ -95,84 +114,59 @@ public class CMISRDFMapper implements RD
NonLiteral documentURI,
String documentName,
MGraph graph,
- Session session) throws RDFBridgeException {
+ Session session) {
+
+ Folder containerFolder = createStructureForDocument(documentName,
documentURI, parent, session, graph);
+
+ Iterator<Triple> it = graph.filter(null,
CMSAdapterVocabulary.CMS_OBJECT_PARENT_REF, documentURI);
+ while (it.hasNext()) {
+ NonLiteral childSubject = it.next().getSubject();
+ String childName =
RDFBridgeHelper.getResourceStringValue(childSubject,
+ CMSAdapterVocabulary.CMS_OBJECT_NAME, graph);
+ createDocument(containerFolder, childSubject, childName, graph,
session);
+ }
+ }
+
+ private Folder createStructureForDocument(String documentName,
+ NonLiteral documentURI,
+ Folder parentFolder,
+ Session session,
+ MGraph graph) {
String documentPath;
- String parentPath = parent.getPath();
+ String parentPath = parentFolder.getPath();
if (parentPath.endsWith("/")) {
documentPath = parentPath + documentName;
} else {
documentPath = parentPath + "/" + documentName;
}
- Document d = null;
- CmisObject o = null;
- try {
- o = session.getObjectByPath(documentPath);
- if (hasType(o, BaseTypeId.CMIS_DOCUMENT)) {
- d = (Document) o;
- d.setContentStream(getDocumentContentStream(documentURI,
graph), true);
- } else {
- log.warn(
- "Object having path: {} does not have Folder base type. It
should have Folder base type to allow create documents in it",
- documentPath);
- throw new RDFBridgeException("Existing object having path: " +
documentPath
- + " which does not have Folder
base type");
- }
- } catch (CmisObjectNotFoundException e) {
- log.debug("Object having path: {} does not exists, a new one will
be created", documentPath);
- d =
parent.createDocument(getProperties(BaseTypeId.CMIS_DOCUMENT.value(),
documentName),
- getDocumentContentStream(documentURI, graph),
VersioningState.NONE);
- }
- // create child objects of root object in the same folder with parent
- Iterator<Triple> it = graph.filter(null,
CMSAdapterVocabulary.CMS_OBJECT_PARENT_REF, documentURI);
- while (it.hasNext()) {
- NonLiteral childSubject = it.next().getSubject();
- String childName =
RDFBridgeHelper.getResourceStringValue(childSubject,
- CMSAdapterVocabulary.CMS_OBJECT_NAME, graph);
- createDocument(parent, childSubject, childName, graph, session);
+ Folder containerFolder = createFolderByPath(parentFolder,
documentName, documentPath, session);
+ if (containerFolder != null) {
+ String rdfDocumentName = documentName + DOCUMENT_RDF;
+ createDocumentByPath(containerFolder, rdfDocumentName,
documentPath + "/" + rdfDocumentName,
+ getDocumentContentStream(rdfDocumentName, documentURI, graph),
session);
+ createDocumentByPath(containerFolder, documentName, documentPath +
"/" + documentName, null,
+ session);
}
+ return containerFolder;
}
- private ContentStream getDocumentContentStream(NonLiteral documentURI,
MGraph graph) {
+ private ContentStream getDocumentContentStream(String documentName,
NonLiteral documentURI, MGraph graph) {
MGraph documentMGraph = collectedDocumentResources(documentURI, graph);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.serialize(baos, documentMGraph, SupportedFormat.RDF_XML);
byte[] serializedGraph = baos.toByteArray();
InputStream stream = new ByteArrayInputStream(baos.toByteArray());
BigInteger length = new BigInteger(serializedGraph.length + "");
- ContentStream contentStream = new ContentStreamImpl(DOCUMENT_RDF,
length, DOCUMENT_RDF_MIME_TYPE,
+ ContentStream contentStream = new ContentStreamImpl(documentName,
length, DOCUMENT_RDF_MIME_TYPE,
stream);
return contentStream;
}
private MGraph collectedDocumentResources(NonLiteral subject, MGraph
graph) {
MGraph documentMGraph = new SimpleMGraph();
- // put selected properties to the graph
- Iterator<Triple> it = graph.filter(subject,
CMSAdapterVocabulary.CMS_OBJECT_HAS_PROPERTY, null);
- while (it.hasNext()) {
- UriRef tempPropURI = new
UriRef(RDFBridgeHelper.removeEndCharacters(it.next().getObject()
- .toString()));
- UriRef propURI = RDFBridgeHelper.getResourceURIValue(tempPropURI,
- CMSAdapterVocabulary.CMS_OBJECT_PROPERTY_URI, graph);
- Iterator<Triple> propTriples = graph.filter(subject, propURI,
null);
- while (propTriples.hasNext()) {
- documentMGraph.add(propTriples.next());
- }
- }
- // put selected children annotations to the graph
- // The process below may be improved by changing RDF annotation
mechanism.
- it = graph.filter(null, CMSAdapterVocabulary.CMS_OBJECT_PARENT_REF,
subject);
- while (it.hasNext()) {
- NonLiteral childSubject = it.next().getSubject();
- Iterator<Triple> itt = graph.filter(subject, null, childSubject);
- if (itt.hasNext()) {
- documentMGraph.add(itt.next());
- }
- }
-
- // put parent annotations to the graph
- it = graph.filter(subject, CMSAdapterVocabulary.CMS_OBJECT_PARENT_REF,
null);
+ Iterator<Triple> it = graph.filter(subject, null, null);
while (it.hasNext()) {
documentMGraph.add(it.next());
}
@@ -180,45 +174,75 @@ public class CMISRDFMapper implements RD
}
/**
- * Takes a path and tries to check nodes that forms that path. If nodes do
not exist, they are created.
+ * Takes a document path and checks folders in which document will be
created/updated. If folders do not
+ * exist, they are created.
*
- * @param rootPath
+ * @param documentPath
* path in which root objects will be created or existing one
will be searched
* @param session
* session to access repository
- * @return
- * @throws RDFBridgeException
- * when another object which is not a folder in the specified
path
+ * @return {@link Folder} one level up from the document
*/
- private Folder checkCreateParentNodes(String rootPath, Session session)
throws RDFBridgeException {
+ private Folder checkCreateParentFolders(String documentPath, Session
session) {
Folder f = session.getRootFolder();
- String[] pathSections = rootPath.split("/");
+ String[] pathSections = documentPath.split("/");
String currentPath = "/";
- for (int i = 1; i < pathSections.length; i++) {
+ for (int i = 1; i < pathSections.length - 1; i++) {
String folderName = pathSections[i];
currentPath += folderName;
- CmisObject o;
- try {
- o = session.getObjectByPath(currentPath);
- if (hasType(o, BaseTypeId.CMIS_FOLDER)) {
- f = (Folder) o;
- currentPath += "/";
- } else {
- log.warn(
- "Object having path: {} does not have Folder base
type. It should have Folder base type to allow create documents in it",
- currentPath);
- throw new RDFBridgeException("Existing object having path:
" + currentPath
- + " which does not have
Folder base type");
- }
- } catch (CmisObjectNotFoundException e) {
- log.debug("Object having path: {} does not exists, a new one
will be created", currentPath);
- f =
f.createFolder(getProperties(BaseTypeId.CMIS_FOLDER.value(), folderName));
+ f = createFolderByPath(f, folderName, currentPath, session);
+ if (f != null) {
+ currentPath += "/";
+ } else {
+ return null;
}
}
+ return f;
+ }
+ private Folder createFolderByPath(Folder root, String name, String path,
Session session) {
+ Folder f;
+ try {
+ CmisObject o = session.getObjectByPath(path);
+ if (hasType(o, BaseTypeId.CMIS_FOLDER)) {
+ f = (Folder) o;
+ } else {
+ log.warn(
+ "Object having path: {} does not have Folder base type. It
should have Folder base type to allow create documents in it",
+ path);
+ return null;
+ }
+ } catch (CmisObjectNotFoundException e) {
+ log.debug("Object having path: {} does not exists, a new one will
be created", path);
+ f =
root.createFolder(getProperties(BaseTypeId.CMIS_FOLDER.value(), name));
+ }
return f;
}
+ private Document createDocumentByPath(Folder parent,
+ String name,
+ String path,
+ ContentStream contentStream,
+ Session session) {
+ Document d;
+ try {
+ CmisObject o = session.getObjectByPath(path);
+ if (hasType(o, BaseTypeId.CMIS_DOCUMENT)) {
+ d = (Document) o;
+ } else {
+ log.warn(
+ "Object having path: {} does not have Folder base type. It
should have Folder base type to allow create documents in it",
+ path);
+ return null;
+ }
+ } catch (CmisObjectNotFoundException e) {
+ log.debug("Object having path: {} does not exists, a new one will
be created", path);
+ d =
parent.createDocument(getProperties(BaseTypeId.CMIS_DOCUMENT.value(), name),
contentStream,
+ VersioningState.NONE);
+ }
+ return d;
+ }
+
private Map<String,Object> getProperties(String... properties) {
Map<String,Object> propMap = new HashMap<String,Object>();
propMap.put(PropertyIds.OBJECT_TYPE_ID, properties[0]);
@@ -229,4 +253,14 @@ public class CMISRDFMapper implements RD
private boolean hasType(CmisObject o, BaseTypeId type) {
return o.getBaseTypeId().equals(type);
}
+
+ @Override
+ public MGraph generateRDFFromRepository(Object session, String rootPath) {
+ throw new UnsupportedOperationException("This method is not
implemented yet");
+ }
+
+ @Override
+ public boolean canMap(String connectionType) {
+ return connectionType.contentEquals("CMIS");
+ }
}
Modified:
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRepositoryAccess.java
URL:
http://svn.apache.org/viewvc/incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRepositoryAccess.java?rev=1161598&r1=1161597&r2=1161598&view=diff
==============================================================================
---
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRepositoryAccess.java
(original)
+++
incubator/stanbol/trunk/cmsadapter/cmis/src/main/java/org/apache/stanbol/cmsadapter/cmis/repository/CMISRepositoryAccess.java
Thu Aug 25 15:10:51 2011
@@ -390,7 +390,7 @@ public class CMISRepositoryAccess implem
getSession(connectionInfo);
return true;
} catch (Exception e) {
- logger.debug("Error at trying to get session from connection
info", e);
+ logger.warn("Error at trying to get session from connection info",
e);
return false;
}
}
Modified: incubator/stanbol/trunk/cmsadapter/jcr/pom.xml
URL:
http://svn.apache.org/viewvc/incubator/stanbol/trunk/cmsadapter/jcr/pom.xml?rev=1161598&r1=1161597&r2=1161598&view=diff
==============================================================================
--- incubator/stanbol/trunk/cmsadapter/jcr/pom.xml (original)
+++ incubator/stanbol/trunk/cmsadapter/jcr/pom.xml Thu Aug 25 15:10:51 2011
@@ -51,12 +51,6 @@
<artifactId>org.apache.stanbol.cmsadapter.core</artifactId>
</dependency>
- <!-- Need only for NamespaceEnum -->
- <dependency>
- <groupId>org.apache.stanbol</groupId>
-
<artifactId>org.apache.stanbol.entityhub.servicesapi</artifactId>
- </dependency>
-
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
Modified:
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRDFMapper.java
URL:
http://svn.apache.org/viewvc/incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRDFMapper.java?rev=1161598&r1=1161597&r2=1161598&view=diff
==============================================================================
---
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRDFMapper.java
(original)
+++
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRDFMapper.java
Thu Aug 25 15:10:51 2011
@@ -1,23 +1,38 @@
package org.apache.stanbol.cmsadapter.jcr.repository;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import javax.jcr.NamespaceException;
import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import org.apache.clerezza.rdf.core.Literal;
+import org.apache.clerezza.rdf.core.LiteralFactory;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.Resource;
import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.TypedLiteral;
import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
+import org.apache.stanbol.cmsadapter.core.mapping.BaseRDFMapper;
import org.apache.stanbol.cmsadapter.core.mapping.RDFBridgeHelper;
import org.apache.stanbol.cmsadapter.servicesapi.helper.CMSAdapterVocabulary;
+import org.apache.stanbol.cmsadapter.servicesapi.helper.NamespaceEnum;
+import org.apache.stanbol.cmsadapter.servicesapi.mapping.RDFBridgeException;
import org.apache.stanbol.cmsadapter.servicesapi.mapping.RDFMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,17 +45,30 @@ import org.slf4j.LoggerFactory;
*/
@Component(immediate = true)
@Service
-public class JCRRDFMapper implements RDFMapper {
+public class JCRRDFMapper extends BaseRDFMapper implements RDFMapper {
private static final Logger log =
LoggerFactory.getLogger(JCRRDFMapper.class);
+ /**
+ * This list contains properties that will not be included in the RDF
which is generated from content
+ * repository
+ */
+ private static final List<UriRef> excludedProperties;
+
+ static {
+ excludedProperties = new ArrayList<UriRef>();
+ excludedProperties.add(CMSAdapterVocabulary.CMS_OBJECT_HAS_URI);
+ }
+
@Override
- public void storeRDFinRepository(Object session, String rootPath, MGraph
annotatedGraph) {
- List<NonLiteral> rootObjects =
RDFBridgeHelper.getRootObjetsOfGraph(annotatedGraph);
+ public void storeRDFinRepository(Object session, MGraph annotatedGraph) {
+ List<NonLiteral> rootObjects =
RDFBridgeHelper.getRootObjectsOfGraph(annotatedGraph);
for (NonLiteral root : rootObjects) {
- String nodeName = RDFBridgeHelper.getResourceStringValue(root,
- CMSAdapterVocabulary.CMS_OBJECT_NAME, annotatedGraph);
- Node parent = checkCreateParentNodes(rootPath, (Session) session);
- createNode(parent, root, nodeName, annotatedGraph, (Session)
session);
+ String nodeName = getObjectName(root, annotatedGraph);
+ String nodePath = getObjectPath(root, nodeName, annotatedGraph);
+ Node parent = checkCreateParentNodes(nodePath, (Session) session);
+ if (parent != null) {
+ createNode(parent, root, nodeName, annotatedGraph, (Session)
session);
+ }
}
try {
((Session) session).save();
@@ -73,17 +101,14 @@ public class JCRRDFMapper implements RDF
String parentPath = "";
try {
parentPath = parent.getPath();
- if (parent.hasNode(nodeName)) {
- n = parent.getNode(nodeName);
- } else {
- n = parent.addNode(nodeName);
- }
+ n = createActualNode(parent, nodeSubject, nodeName, graph);
} catch (RepositoryException e) {
- log.warn("Failed to create node {} for parent {}. ", new Object[]
{parentPath, nodeName}, e);
+ log.warn(String.format("Failed to create node %s for parent %s. ",
nodeName, parentPath), e);
+ return;
}
// create properties
- createNodeProperties(n, nodeSubject, graph);
+ createNodeProperties(n, nodeSubject, graph, session);
// create children
Iterator<Triple> it = graph.filter(null,
CMSAdapterVocabulary.CMS_OBJECT_PARENT_REF, nodeSubject);
@@ -96,52 +121,148 @@ public class JCRRDFMapper implements RDF
}
/**
- * This function creates specified properties for the node given as
parameter. If a property already
- * exists, it first is nullified then new value is assigned. Properties
are accessed through
- * {@code CMSAdapterVocabulary#CMS_OBJECT_HAS_PROPERTY} property.
+ * This method creates a node by using the specified parameters. It first
check RDF primary type and tries
+ * to create the node with the type specified it the type is set. In the
next step it checks mixin types
+ * and tries to set if there is any.
+ *
+ * @param parent
+ * @param nodeSubject
+ * @param nodeName
+ * @param graph
+ * @return
+ * @throws RepositoryException
+ */
+ private Node createActualNode(Node parent, NonLiteral nodeSubject, String
nodeName, MGraph graph) throws RepositoryException {
+ Node n;
+ if (parent.hasNode(nodeName)) {
+ n = parent.getNode(nodeName);
+ } else {
+ String nodeType =
RDFBridgeHelper.getResourceStringValue(nodeSubject,
+ getUriRefFromJCRConstant(Property.JCR_PRIMARY_TYPE), graph);
+
+ if (nodeType.contentEquals("")) {
+ n = parent.addNode(nodeName);
+ } else {
+ try {
+ n = parent.addNode(nodeName, nodeType);
+ } catch (RepositoryException e) {
+ log.warn(String.format("Failed to create node %s with the
type %s", nodeName, nodeType),
+ e);
+ n = parent.addNode(nodeName);
+ }
+ }
+
+ // check mixin types
+ Iterator<Triple> mixins = graph.filter(nodeSubject,
+ getUriRefFromJCRConstant(Property.JCR_MIXIN_TYPES), null);
+ String mixinType = "";
+ while (mixins.hasNext()) {
+ Resource r = mixins.next().getObject();
+ try {
+ mixinType = RDFBridgeHelper.getShortURIFromResource(r);
+ if (!mixinType.contentEquals("")) {
+ n.addMixin(mixinType);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to set mixin type: {}", mixinType);
+ }
+ }
+ }
+ return n;
+ }
+
+ /**
+ * Transforms the assertions belonging to a resource in the RDF data as
properties in the content
+ * repository.
*
* @param n
- * {@link Node} of which properties will be updated/created
* @param subject
- * corresponding URI of the node
* @param graph
- * annotated {@link MGraph}
+ * @param session
*/
- private void createNodeProperties(Node n, NonLiteral subject, MGraph
graph) {
- Iterator<Triple> it = graph.filter(subject,
CMSAdapterVocabulary.CMS_OBJECT_HAS_PROPERTY, null);
- while (it.hasNext()) {
- UriRef tempPropURI = new
UriRef(RDFBridgeHelper.removeEndCharacters(it.next().getObject()
- .toString()));
- String propName =
RDFBridgeHelper.getResourceStringValue(tempPropURI,
- CMSAdapterVocabulary.CMS_OBJECT_PROPERTY_NAME, graph);
- UriRef propURI = RDFBridgeHelper.getResourceURIValue(tempPropURI,
- CMSAdapterVocabulary.CMS_OBJECT_PROPERTY_URI, graph);
- Resource resource = RDFBridgeHelper.getResource(subject, propURI,
graph);
+ private void createNodeProperties(Node n, NonLiteral subject, MGraph
graph, Session session) {
+ Iterator<Triple> it = graph.filter(subject, null, null);
+ Map<String,PropertyInfo> propVals = new HashMap<String,PropertyInfo>();
- if (resource == null) {
- continue;
- }
+ createDefaultPropertiesForCMS(n, subject);
+
+ while (it.hasNext()) {
+ Triple t = it.next();
+ String propURI =
RDFBridgeHelper.removeEndCharacters(t.getPredicate().toString());
+ Resource resource = t.getObject();
String propValue = "";
if (resource instanceof Literal) {
- propValue = RDFBridgeHelper.getResourceStringValue(subject,
propURI, graph);
+ propValue = RDFBridgeHelper.getResourceStringValue(subject,
t.getPredicate(), graph);
} else if (resource instanceof UriRef) {
propValue =
RDFBridgeHelper.removeEndCharacters(resource.toString());
} else {
propValue = resource.toString();
}
- int propType = RDFBridgeHelper.getPropertyType(resource);
+ if (propVals.containsKey(propURI)) {
+ PropertyInfo pInfo = propVals.get(propURI);
+ pInfo.addPropertyValue(propValue);
+ } else {
+ PropertyInfo pInfo = new PropertyInfo();
+ pInfo.setPropertyType(resource);
+ pInfo.addPropertyValue(propValue);
+ propVals.put(propURI, pInfo);
+ }
+ }
+ for (String propURI : propVals.keySet()) {
+ PropertyInfo pInfo = propVals.get(propURI);
+ List<String> singlePropValList = pInfo.getPropertyValues();
+ String[] singlePropVals = new String[singlePropValList.size()];
+ singlePropValList.toArray(singlePropVals);
+ String propName =
NamespaceEnum.getShortName(RDFBridgeHelper.removeEndCharacters(propURI
+ .toString()));
+ // check whether the namespace prefix is registered in the JCR
+ // repository
+ try {
+ checkNamespaceForShortURI(session, propName);
+ } catch (Exception e) {
+ log.warn("Failed to check namespace for property: {}",
propURI, e);
+ continue;
+ }
+
try {
- n.setProperty(propName, (Value) null);
- n.setProperty(propName, propValue, propType);
- log.debug("{} property of updated/created with {}", propName,
propValue);
+ boolean isMultiple = false;
+ try {
+ Property p = n.getProperty(propName);
+ isMultiple = p.isMultiple();
+ if (isMultiple) {
+ n.setProperty(propName, (Value[]) null);
+ } else {
+ n.setProperty(propName, (Value) null);
+ }
+ } catch (Exception e) {
+ // assume property not found
+ n.setProperty(propName, (Value) null);
+ }
+
+ if (singlePropVals.length == 1) {
+ n.setProperty(propName, singlePropVals[0],
pInfo.getPropertyType());
+ } else {
+ n.setProperty(propName, singlePropVals,
pInfo.getPropertyType());
+ }
+ log.debug("{} property of updated/created with {}", propName);
} catch (Exception e) {
log.warn("Failed to update property: {} for node {}: ",
propName, e);
}
}
}
+ private void createDefaultPropertiesForCMS(Node n, NonLiteral subject) {
+ String uriPropShortURI = NamespaceEnum.getShortName(RDFBridgeHelper
+
.removeEndCharacters(CMSAdapterVocabulary.CMS_OBJECT_HAS_URI.toString()));
+ try {
+ n.setProperty(uriPropShortURI,
RDFBridgeHelper.removeEndCharacters(subject.toString()));
+ } catch (RepositoryException e) {
+ log.warn("Failed to set URI property of node", e);
+ }
+ }
+
/**
* Takes a path and tries to check nodes that forms that path. If nodes do
not exist, they are created.
*
@@ -159,12 +280,12 @@ public class JCRRDFMapper implements RDF
n = session.getRootNode();
currentPath = n.getPath();
} catch (RepositoryException e) {
- log.warn("Failed to get root node while trying to get Node for
path: {}", rootPath, e);
+ log.warn("Failed to get Node for path: {}", rootPath, e);
return null;
}
String[] pathSections = rootPath.split("/");
- for (int i = 1; i < pathSections.length; i++) {
+ for (int i = 1; i < pathSections.length - 1; i++) {
try {
if (!n.hasNode(pathSections[i])) {
n = n.addNode(pathSections[i]);
@@ -181,4 +302,323 @@ public class JCRRDFMapper implements RDF
return n;
}
-}
+
+ @Override
+ public MGraph generateRDFFromRepository(Object session, String rootPath)
throws RDFBridgeException {
+ MGraph cmsGraph = new SimpleMGraph();
+ Session jcrSession = (Session) session;
+
+ List<Node> targetNodes = new ArrayList<Node>();
+ try {
+ Node rootNode = jcrSession.getNode(rootPath);
+ NodeIterator it = rootNode.getNodes();
+ while (it.hasNext()) {
+ targetNodes.add(it.nextNode());
+ }
+ } catch (RepositoryException e) {
+ log.warn("Failed to retrieve node having path: {} or its
children", rootPath);
+ throw new RDFBridgeException("Failed to node having path: " +
rootPath + " or its children", e);
+ }
+
+ for (Node n : targetNodes) {
+ // get name to show in debug info
+ String name = "";
+ try {
+ name = n.getName();
+ cmsGraph.addAll(getGraphForNode(n));
+ } catch (RepositoryException e) {
+ log.warn("Repository exception while processing node having
name: {}", name, e);
+ }
+ }
+ return cmsGraph;
+ }
+
+ /**
+ * Generates an RDF from the specified {@link Node}. It annotates the
resource representing the Node with
+ * {@link CMSAdapterVocabulary#CMS_OBJECT}. In the next step, it
transforms the properties of the Node to
+ * the RDF. In the last step, it checks the child Nodes of the processed
Node and executes same operations
+ * for the child.
+ *
+ * @param n
+ * @return
+ */
+ MGraph getGraphForNode(Node n) {
+ MGraph graph = new SimpleMGraph();
+
+ // create CMS Object annotation
+ NonLiteral subject = getNodeURI(n);
+ if (subject == null) {
+ return graph;
+ }
+ graph.add(new TripleImpl(subject, RDFBridgeHelper.RDF_TYPE,
CMSAdapterVocabulary.CMS_OBJECT));
+
+ String nodeName = "";
+ try {
+ nodeName = n.getName();
+ } catch (RepositoryException e) {
+ log.warn("Failed to retrieve name of node", e);
+ }
+
+ // properties
+ try {
+ createPropertiesAsRDF(n, subject, graph);
+ } catch (RepositoryException e) {
+ log.warn("Failed to retrieve properties of node: {}", nodeName, e);
+ }
+
+ // children
+ NodeIterator nit;
+ try {
+ nit = n.getNodes();
+ while (nit.hasNext()) {
+ Node child = nit.nextNode();
+ NonLiteral childURI = getNodeURI(child);
+ if (childURI == null) {
+ continue;
+ }
+ graph.add(new TripleImpl(childURI,
CMSAdapterVocabulary.CMS_OBJECT_PARENT_REF, subject));
+ graph.addAll(getGraphForNode(child));
+ }
+ } catch (RepositoryException e) {
+ log.warn("Error while processing children of node: {}", nodeName,
e);
+ }
+ return graph;
+ }
+
+ private void createPropertiesAsRDF(Node n, NonLiteral subject, MGraph
graph) throws RepositoryException {
+ LiteralFactory literalFactory = LiteralFactory.getInstance();
+ PropertyIterator pit = n.getProperties();
+ while (pit.hasNext()) {
+ try {
+ Property p = pit.nextProperty();
+ UriRef pURI = getPropertyURI(p);
+ if (pURI == null || excludedProperties.contains(pURI)) {
+ continue;
+ }
+ List<Object> values = new ArrayList<Object>();
+ if (p.isMultiple()) {
+ values.addAll(getTypedPropertyValues(p.getType(),
p.getValues()));
+ } else {
+ values.add(getTypedPropertyValue(p.getType(),
p.getValue()));
+ }
+ for (Object val : values) {
+ /*
+ * As JCR does not support retrieval of values of URI
typed properties, object properties
+ * are reflected as String properties in JCR. So, when
creating RDF from JCR repository,
+ * currently just look at the value of property starts
with "http" prefix.
+ *
+ * TODO: Other dirty workaround may be including some
prefixes to the object properties to
+ * identify them
+ *
+ * TODO: Fix this when JCR supports retrieval of URI typed
property values
+ */
+ try {
+ String valStr = (String) val;
+ if (valStr.startsWith("http")) {
+ graph.add(new TripleImpl(subject, pURI, new
UriRef(valStr)));
+ continue;
+ }
+ } catch (Exception e) {
+ // ignore the exception
+ }
+ graph.add(new TripleImpl(subject, pURI,
literalFactory.createTypedLiteral(val)));
+ }
+ } catch (RepositoryException e) {
+ log.warn("Failed to process property of node", e);
+ }
+ }
+ createDefaultPropertiesForRDF(n, subject, graph);
+ }
+
+ private void createDefaultPropertiesForRDF(Node n, NonLiteral subject,
MGraph graph) {
+ try {
+ checkDefaultPropertyInitialization(subject,
CMSAdapterVocabulary.CMS_OBJECT_PATH, n.getPath(),
+ graph);
+ } catch (RepositoryException e) {
+ log.warn("Failed to initialize path property", e);
+ }
+ try {
+ checkDefaultPropertyInitialization(subject,
CMSAdapterVocabulary.CMS_OBJECT_NAME, n.getName(),
+ graph);
+ } catch (RepositoryException e) {
+ log.warn("Failed to initialize name property", e);
+ }
+ }
+
+ private void checkDefaultPropertyInitialization(NonLiteral subject,
+ UriRef property,
+ String value,
+ MGraph graph) {
+ LiteralFactory literalFactory = LiteralFactory.getInstance();
+ String oldValue = RDFBridgeHelper.getResourceStringValue(subject,
property, graph);
+ if (oldValue.contentEquals("")) {
+ graph.add(new TripleImpl(subject, property,
literalFactory.createTypedLiteral(value)));
+ }
+ }
+
+ private UriRef getNodeURI(Node n) {
+ String uriPropShortURI = NamespaceEnum.getShortName(RDFBridgeHelper
+
.removeEndCharacters(CMSAdapterVocabulary.CMS_OBJECT_HAS_URI.toString()));
+ String nodeName = "";
+ String nodeURI = null;
+ try {
+ nodeName = n.getName();
+ Property p = n.getProperty(uriPropShortURI);
+ nodeURI = p.getString();
+ return new UriRef(RDFBridgeHelper.removeEndCharacters(nodeURI));
+ } catch (Exception e) {
+ log.warn("Failed to retrieve URI from property for node {}",
nodeName);
+ }
+
+ try {
+ String baseURI = CMSAdapterVocabulary.CMS_ADAPTER_VOCABULARY_URI;
+ nodeURI = RDFBridgeHelper.appendLocalName(baseURI,
n.getIdentifier());
+ return new UriRef(nodeURI);
+ } catch (RepositoryException e) {
+ log.warn("Failed to retrieve identifer to be used as URI for node
{}", nodeName, e);
+ }
+ return null;
+ }
+
+ private static UriRef getPropertyURI(Property p) throws
RepositoryException {
+ String name = p.getName();
+ if (!name.contains(":")) {
+ name = NamespaceEnum.cms.getPrefix() + ":" + name;
+ }
+ if (RDFBridgeHelper.isShortNameResolvable(name)) {
+ return new UriRef(NamespaceEnum.getFullName(name));
+ } else {
+ log.warn("Failed to resolve property: {}", name);
+ return null;
+ }
+ }
+
+ private static List<Object> getTypedPropertyValues(int propertyType,
Value[] values) throws RepositoryException {
+ List<Object> typedValues = new ArrayList<Object>();
+ for (Value val : values) {
+ typedValues.add(getTypedPropertyValue(propertyType, val));
+ }
+ return typedValues;
+ }
+
+ private static Object getTypedPropertyValue(int propertyType, Value value)
throws RepositoryException {
+ switch (propertyType) {
+ case PropertyType.STRING:
+ return value.getString();
+ case PropertyType.BINARY:
+ return value.getString();
+ case PropertyType.BOOLEAN:
+ return value.getBoolean();
+ case PropertyType.DATE:
+ return value.getDate().getTime();
+ case PropertyType.URI:
+ return value.getString();
+ case PropertyType.DOUBLE:
+ return value.getDouble();
+ case PropertyType.DECIMAL:
+ return value.getDecimal().toBigInteger();
+ case PropertyType.LONG:
+ return value.getLong();
+ case PropertyType.PATH:
+ return value.getString();
+ default:
+ return value.getString();
+ }
+ }
+
+ /**
+ * Return related {@link PropertyType} according to data type of a {@link
Resource} if it is an instance
+ * of {@link TypedLiteral} ot {@link UriRef}, otherwise it return {@code
PropertyType#STRING} as default
+ * type.
+ *
+ * @param r
+ * @link {@link Resource} instance of which property type is demanded
+ * @return related {@link PropertyType}
+ */
+ public static int getPropertyTypeByResource(Resource r) {
+ if (r instanceof TypedLiteral) {
+ UriRef type = ((TypedLiteral) r).getDataType();
+ if (type.equals(RDFBridgeHelper.stringUri)) {
+ return PropertyType.STRING;
+ } else if (type.equals(RDFBridgeHelper.base64Uri)) {
+ return PropertyType.BINARY;
+ } else if (type.equals(RDFBridgeHelper.booleanUri)) {
+ return PropertyType.BOOLEAN;
+ } else if (type.equals(RDFBridgeHelper.dateTimeUri)) {
+ return PropertyType.DATE;
+ } else if (type.equals(RDFBridgeHelper.xsdAnyURI)) {
+ /*
+ * Normally this case should return PropertyType.URI, but JCR
API seems to fail when
+ * retrieving values of URI typed properties.
+ */
+ return PropertyType.STRING;
+ } else if (type.equals(RDFBridgeHelper.xsdDouble)) {
+ return PropertyType.DOUBLE;
+ } else if (type.equals(RDFBridgeHelper.xsdInt)) {
+ return PropertyType.DECIMAL;
+ } else if (type.equals(RDFBridgeHelper.xsdInteger)) {
+ return PropertyType.DECIMAL;
+ } else if (type.equals(RDFBridgeHelper.xsdLong)) {
+ return PropertyType.LONG;
+ } else if (type.equals(RDFBridgeHelper.xsdShort)) {
+ return PropertyType.DECIMAL;
+ } else {
+ return PropertyType.STRING;
+ }
+ } else if (r instanceof UriRef) {
+ /*
+ * Normally this case should return PropertyType.URI, but JCR API
seems to fail when retrieving
+ * values of URI typed properties.
+ */
+ return PropertyType.STRING;
+ } else {
+ return PropertyType.STRING;
+ }
+ }
+
+ private void checkNamespaceForShortURI(Session session, String shortURI)
throws NamespaceException,
+
RepositoryException {
+ String prefix = shortURI.split(":")[0];
+ try {
+ session.getNamespaceURI(prefix);
+ } catch (Exception e) {
+ String namespaceURI =
NamespaceEnum.forPrefix(prefix).getNamespace();
+
session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix,
namespaceURI);
+ }
+ }
+
+ private UriRef getUriRefFromJCRConstant(String jcrConstant) {
+ int end = jcrConstant.indexOf('}');
+ String uri = jcrConstant.substring(1, end) + "/" +
jcrConstant.substring(end + 1);
+ return new UriRef(uri);
+ }
+
+ @Override
+ public boolean canMap(String connectionType) {
+ return connectionType.contentEquals("JCR");
+ }
+
+ private class PropertyInfo {
+ private int type;
+ private List<String> propVals;
+
+ public void addPropertyValue(String value) {
+ if (propVals == null) {
+ propVals = new ArrayList<String>();
+ }
+ propVals.add(value);
+ }
+
+ public List<String> getPropertyValues() {
+ return propVals;
+ }
+
+ public void setPropertyType(Resource r) {
+ type = getPropertyTypeByResource(r);
+ }
+
+ public int getPropertyType() {
+ return type;
+ }
+ }
+}
\ No newline at end of file
Copied:
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccess.java
(from r1156602,
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccessImpl.java)
URL:
http://svn.apache.org/viewvc/incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccess.java?p2=incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccess.java&p1=incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccessImpl.java&r1=1156602&r2=1161598&rev=1161598&view=diff
==============================================================================
---
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccessImpl.java
(original)
+++
incubator/stanbol/trunk/cmsadapter/jcr/src/main/java/org/apache/stanbol/cmsadapter/jcr/repository/JCRRepositoryAccess.java
Thu Aug 25 15:10:51 2011
@@ -44,6 +44,7 @@ import org.apache.stanbol.cmsadapter.ser
import
org.apache.stanbol.cmsadapter.servicesapi.model.web.ObjectTypeDefinition;
import org.apache.stanbol.cmsadapter.servicesapi.model.web.Property;
import org.apache.stanbol.cmsadapter.servicesapi.model.web.PropertyDefinition;
+import org.apache.stanbol.cmsadapter.servicesapi.repository.RepositoryAccess;
import
org.apache.stanbol.cmsadapter.servicesapi.repository.RepositoryAccessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,9 +52,9 @@ import org.slf4j.LoggerFactory;
//TODO Implement session management. Currently for each operation a new
Session is retrieved.
@Component(immediate = true)
@Service
-public class JCRRepositoryAccessImpl implements JCRRepositoryAccess {
+public class JCRRepositoryAccess implements RepositoryAccess {
- private static final Logger log =
LoggerFactory.getLogger(JCRRepositoryAccessImpl.class);
+ private static final Logger log =
LoggerFactory.getLogger(JCRRepositoryAccess.class);
/**
* Tries to get a {@link Session} first through a {@link
RMIRemoteRepository}. If the attempt is
@@ -71,7 +72,7 @@ public class JCRRepositoryAccessImpl imp
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
-
Thread.currentThread().setContextClassLoader(JCRRepositoryAccessImpl.class.getClassLoader());
+
Thread.currentThread().setContextClassLoader(JCRRepositoryAccess.class.getClassLoader());
session = getSessionByRMI(connectionInfo);
if (session == null) {
session = getSessionByURL(connectionInfo);
@@ -437,21 +438,4 @@ public class JCRRepositoryAccessImpl imp
throw new RepositoryAccessException("Error at accessing parent",
e);
}
}
-
- @Override
- public Node getNodeByPath(String path, Session session) throws
RepositoryAccessException {
- JCRQueryRepresentation query =
QueryHelper.getJCRItemByPathQuery(path).get(0);
- QueryResult queryResult = executeQuery(query, session);
- NodeIterator nodes;
- try {
- nodes = queryResult.getNodes();
- if (nodes.hasNext()) {
- return nodes.nextNode();
- } else {
- return null;
- }
- } catch (RepositoryException e) {
- throw new RepositoryAccessException("Failed to execute query
results.", e);
- }
- }
}