/* * ModeShape (http://www.modeshape.org) * * Licensed 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.modeshape.jcr; import java.util.HashSet; import java.util.Set; import java.util.UUID; import javax.jcr.NamespaceRegistry; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Value; import javax.jcr.query.QueryResult; import org.junit.Assert; import org.junit.Test; import org.modeshape.common.FixFor; import org.modeshape.jcr.api.JcrTools; public class SrampIntegrationTest extends SingleUseAbstractTest { public static class JCRConstants { public static final String JCR_MIME_TYPE = "jcr:mimeType"; public static final String JCR_CONTENT = "jcr:content"; public static final String JCR_SQL2 = "JCR-SQL2"; public static final String SRAMP = "sramp"; public static final String SRAMP_NS = "http://s-ramp.org/xmlns/2010/s-ramp"; public static final String SRAMP_PROPERTIES = "sramp-properties"; public static final String SRAMP_PROPERTIES_NS = "http://s-ramp.org/xmlns/2010/s-ramp#properties"; public static final String SRAMP_RELATIONSHIPS = "sramp-relationships"; public static final String SRAMP_RELATIONSHIPS_NS = "http://s-ramp.org/xmlns/2010/s-ramp#relationships"; public static final String SRAMP_ = SRAMP + ":"; public static final String SRAMP_BASE_ARTIFACT_TYPE = SRAMP_ + "baseArtifactType"; public static final String SRAMP_CONTENT_TYPE = SRAMP_ + "contentType"; public static final String SRAMP_CONTENT_SIZE = SRAMP_ + "contentSize"; public static final String SRAMP_CONTENT_ENCODING = SRAMP_ + "contentEncoding"; public static final String SRAMP_UUID = SRAMP_ + "uuid"; public static final String SRAMP_NAME = SRAMP_ + "name"; public static final String SRAMP_ARTIFACT_MODEL = SRAMP_ + "artifactModel"; public static final String SRAMP_ARTIFACT_TYPE = SRAMP_ + "artifactType"; public static final String SRAMP_EXTENDED_TYPE = SRAMP_ + "extendedType"; } @Override public void beforeEach() throws Exception { super.beforeEach(); } @Test public void shouldAddArtifactsAndRelationshipsUsingNotionalNodeTypes() throws Exception { // Register some namespaces ... NamespaceRegistry namespaceRegistry = session.getWorkspace().getNamespaceRegistry(); namespaceRegistry.registerNamespace(JCRConstants.SRAMP, JCRConstants.SRAMP_NS); namespaceRegistry.registerNamespace(JCRConstants.SRAMP_PROPERTIES, JCRConstants.SRAMP_PROPERTIES_NS); namespaceRegistry.registerNamespace(JCRConstants.SRAMP_RELATIONSHIPS, JCRConstants.SRAMP_RELATIONSHIPS_NS); // and node types ... registerNodeTypes("cnd/sramp-notional.cnd"); // Add some artifact nodes. session = repository.login(); Node rootNode = session.getRootNode(); String jcrNodeType = JCRConstants.SRAMP_ + "artifact"; // Node - Artifact A Node artifactA = rootNode.addNode("artifact-a", jcrNodeType); artifactA.setProperty("sramp:uuid", "1"); artifactA.setProperty("sramp:name", "A"); artifactA.setProperty("sramp:model", "core"); artifactA.setProperty("sramp:type", "Document"); // Node - Artifact B Node artifactB = rootNode.addNode("artifact-b", jcrNodeType); artifactB.setProperty("sramp:uuid", "2"); artifactB.setProperty("sramp:name", "B"); artifactB.setProperty("sramp:model", "core"); artifactB.setProperty("sramp:type", "Document"); // Node - Artifact C Node artifactC = rootNode.addNode("artifact-c", jcrNodeType); artifactC.setProperty("sramp:uuid", "3"); artifactC.setProperty("sramp:name", "C"); artifactC.setProperty("sramp:model", "core"); artifactC.setProperty("sramp:type", "Document"); session.save(); // //////////////////////////////////////////////////////////////////// // Add the relationship nodes. Here's what // I'm going for here: // A has relationships to both B and C of type 'relatesTo' // A has a relationship to C of type 'isDocumentedBy' // B has a single relationship to C of type 'covets' // C has no relationships // //////////////////////////////////////////////////////////////////// Node relA_relatesTo = artifactA.addNode("relatesTo", "sramp:relationship"); relA_relatesTo.setProperty("sramp:type", "relatesTo"); Value[] targets = new Value[2]; targets[0] = session.getValueFactory().createValue(artifactB, false); targets[1] = session.getValueFactory().createValue(artifactC, false); relA_relatesTo.setProperty("sramp:target", targets); Node relA_isDocumentedBy = artifactA.addNode("isDocumentedBy", "sramp:relationship"); relA_isDocumentedBy.setProperty("sramp:type", "isDocumentedBy"); relA_isDocumentedBy.setProperty("sramp:target", session.getValueFactory().createValue(artifactC, false)); Node relB_covets = artifactB.addNode("relationship-b-1", "sramp:relationship"); relB_covets.setProperty("sramp:type", "covets"); relB_covets.setProperty("sramp:target", session.getValueFactory().createValue(artifactC, false)); session.save(); // print = true; if (print) { tools.printSubgraph(artifactA); tools.printSubgraph(artifactB); tools.printSubgraph(artifactC); } session.logout(); String query = null; QueryResult jcrQueryResult = null; NodeIterator jcrNodes = null; Set<String> jcr_uuids = new HashSet<String>(); // Now it's time to do some querying. session = repository.login(); // Show that we have the 'relatesTo' relationship set up for Artifact A (with two targets) query = "SELECT relationship.[sramp:target] AS target_jcr_uuid FROM [sramp:artifact] AS artifact" + " JOIN [sramp:relationship] AS relationship ON ISCHILDNODE(relationship, artifact)" + " WHERE artifact.[sramp:name] = 'A' AND relationship.[sramp:type] = 'relatesTo'"; jcrQueryResult = assertJcrSql2Query(query, 1); jcrNodes = jcrQueryResult.getNodes(); Node n = jcrNodes.nextNode(); String setCriteria = ""; for (Value value : n.getProperty("sramp:target").getValues()) { printMessage(" Found JCR UUID: " + value.getString()); if (!jcr_uuids.isEmpty()) setCriteria = setCriteria + ", "; jcr_uuids.add(value.getString()); setCriteria = setCriteria + "'" + value.getString() + "'"; } // Now show that the UUIDs found above match the jcr:uuid for Artifact B and Artifact C query = "SELECT artifact.[jcr:uuid] FROM [sramp:artifact] AS artifact" + " WHERE artifact.[sramp:name] = 'B' OR artifact.[sramp:name] = 'C'"; jcrQueryResult = assertJcrSql2Query(query, 2); jcrNodes = jcrQueryResult.getNodes(); Node n1 = jcrNodes.nextNode(); Node n2 = jcrNodes.nextNode(); Assert.assertTrue("Expected to find the JCR UUID in jcr_uuids", jcr_uuids.contains(n1.getProperty("jcr:uuid").getString())); Assert.assertTrue("Expected to find the JCR UUID in jcr_uuids", jcr_uuids.contains(n2.getProperty("jcr:uuid").getString())); printMessage("Confirmed: the [jcr:uuid] for both Artifact B and Artifact C were found!"); // // Next step ... // query = "SELECT relationship.[sramp:target] FROM [sramp:relationship] AS relationship" // + " WHERE relationship.[jcr:path] LIKE '/artifact-a/%' AND relationship.[sramp:type] = 'relatesTo'"; // jcrQueryResult = assertJcrSql2Query(query, 1); // // query = "SELECT artifact.[jcr:uuid], artifact.[jcr:path] FROM [sramp:artifact] AS artifact"; // jcrQueryResult = assertJcrSql2Query(query, 3); // // query = // "SELECT artifact.[jcr:uuid], artifact.[jcr:path] FROM [sramp:artifact] AS artifact WHERE artifact.[jcr.uuid] LIKE '%" // + jcr_uuids.iterator().next() + "'"; // jcrQueryResult = assertJcrSql2Query(query, 1); // // query = "SELECT artifact.[jcr:path] FROM [sramp:artifact] AS artifact WHERE artifact.[jcr.uuid] IN (" + setCriteria + // ")"; // jcrQueryResult = assertJcrSql2Query(query, 2); // // query = "SELECT artifact.* FROM [sramp:artifact] AS artifact WHERE artifact.[jcr.uuid] IN (" + setCriteria + ")"; // jcrQueryResult = assertJcrSql2Query(query, 2); // // query = "SELECT artifact.* FROM [sramp:artifact] AS artifact WHERE artifact.[jcr.uuid] IN (" + query + ")"; // jcrQueryResult = assertJcrSql2Query(query, 2); // OK - so far so good. Now put it all together in a single query! Here // we are trying to select Artifact B and Artifact C by selecting all Artifacts // that Artifatc A has a 'relatesTo' relationship on query = "SELECT artifact2.* FROM [sramp:artifact] AS artifact1" + " JOIN [sramp:relationship] AS relationship1 ON ISCHILDNODE(relationship1, artifact1)" + " JOIN [sramp:artifact] AS artifact2 ON artifact2.[jcr:uuid] = relationship1.[sramp:target]" + " WHERE artifact1.[sramp:name] = 'A' AND relationship1.[sramp:type] = 'relatesTo')"; jcrQueryResult = assertJcrSql2Query(query, 2); jcrNodes = jcrQueryResult.getNodes(); Assert.assertEquals("Expected two (2) nodes (Artifact B and Artifact C) to come back!", 2, jcrNodes.getSize()); } @Test @FixFor( "MODE-1978" ) public void shouldAllowRemovingArtifact() throws Exception { // Register the node types ... registerNodeTypes("cnd/sramp.cnd"); UUID uuid = UUID.randomUUID(); Node sramp = session.getRootNode().addNode("sramp"); Node artifacts = sramp.addNode("artifacts"); Node trash = sramp.addNode("trash"); session.save(); Node artifact = artifacts.addNode(uuid.toString()); artifact.addMixin("sramp:xsdDocument"); artifact.setProperty("sramp:uuid", uuid.toString()); Node artifactChild = artifact.addNode("child"); artifactChild.addMixin("sramp:elementDeclaration"); artifactChild.setProperty("sramp:uuid", UUID.randomUUID().toString()); session.save(); // Now "remove" it by removing the doc type mixins, adding the "deleted" mixin, and moving it to a different area ... artifact.removeMixin("sramp:xsdDocument"); artifact.addMixin("sramp:deletedArtifact"); artifactChild.removeMixin("sramp:elementDeclaration"); artifactChild.addMixin("sramp:deletedArtifact"); session.move(artifact.getPath(), trash.getPath()); session.save(); } @Test @FixFor( "MODE-1978" ) public void shouldAllowRemovingArtifactWithNoExistingTrash() throws Exception { JcrTools tools = new JcrTools(); // print = true; // Register the node types ... registerNodeTypes("cnd/sramp.cnd"); UUID uuid = UUID.randomUUID(); Node artifacts = tools.findOrCreateNode(session, "/sramp/artifacts", "nt:folder"); session.save(); Node artifact = artifacts.addNode(uuid.toString(), "sramp:nonDocumentArtifactType"); printMessage("Added artifact node: " + artifact); artifact.addMixin("sramp:xsdDocument"); artifact.setProperty("sramp:uuid", uuid.toString()); Node artifactChild = artifact.addNode("child", "sramp:derivedArtifactPrimaryType"); printMessage("Added child node: " + artifactChild); artifactChild.addMixin("sramp:elementDeclaration"); artifactChild.setProperty("sramp:uuid", UUID.randomUUID().toString()); session.save(); // Now "remove" it by removing the doc type mixins, adding the "deleted" mixin, and moving it to a different area ... artifact.addMixin("sramp:deletedArtifact"); artifact.removeMixin("sramp:xsdDocument"); artifactChild.addMixin("sramp:deletedArtifact"); artifactChild.removeMixin("sramp:elementDeclaration"); String srcPath = artifact.getPath(); String trashPath = srcPath.replace("sramp", "sramp-trash"); String parentSrcPath = artifacts.getPath(); String parentTrashPath = parentSrcPath.replace("sramp", "sramp-trash"); Node artifactTrash = tools.findOrCreateNode(session, parentTrashPath, "nt:folder"); print(artifactTrash); session.move(srcPath, trashPath); session.save(); } }