/*
* 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.test.api;
import org.apache.jackrabbit.test.AbstractJCRTest;
import org.apache.jackrabbit.test.NotExecutableException;
import javax.jcr.Session;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Value;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import java.util.NoSuchElementException;
/**
* All test cases in this class rely on content in the repository. That is the
* default workspace must at least contain one child node under {@link #testRoot}
* otherwise a {@link NotExecutableException} is thrown.
*
*/
public class NodeDiscoveringNodeTypesTest extends AbstractJCRTest {
/**
* The session we use for the tests
*/
private Session session;
/**
* A child node of the root node in the default workspace.
*/
private Node childNode;
/**
* Sets up the fixture for the test cases.
*/
protected void setUp() throws Exception {
isReadOnly = true;
super.setUp();
session = getHelper().getReadOnlySession();
testRootNode = session.getRootNode().getNode(testPath);
NodeIterator nodes = testRootNode.getNodes();
try {
childNode = nodes.nextNode();
} catch (NoSuchElementException e) {
}
}
/**
* Releases the session acquired in {@link #setUp()}.
*/
protected void tearDown() throws Exception {
if (session != null) {
session.logout();
session = null;
}
childNode = null;
super.tearDown();
}
/**
* Test if getPrimaryNodeType() returns the node type according to the
* property "jcr:primaryType"
*/
public void testGetPrimaryNodeType()
throws NotExecutableException, RepositoryException {
if (childNode == null) {
throw new NotExecutableException("Workspace does not have sufficient content for this test. " +
"Root node must have at least one child node.");
}
NodeType type = childNode.getPrimaryNodeType();
String name = childNode.getProperty(jcrPrimaryType).getString();
assertEquals("getPrimaryNodeType() must return the node type stored " +
"as property \"jcr:primaryType\"",
name, type.getName());
assertFalse("getPrimaryNodeType() must return a primary node type",
type.isMixin());
}
/**
* Test if getMixinNodeType returns the node types according to the property
* "jcr:mixinTypes". Therefore a node with mixin types is located recursively
* in the entire repository. A NotExecutableException is thrown when no such
* node is found.
*/
public void testGetMixinNodeTypes()
throws NotExecutableException, RepositoryException {
if (childNode == null) {
throw new NotExecutableException("Workspace does not have sufficient content for this test. " +
"Root node must have at least one child node.");
}
Node node = locateNodeWithMixinNodeTypes(testRootNode);
if (node == null) {
throw new NotExecutableException("Workspace does not contain a node with mixin node types defined");
}
Value names[] = node.getProperty(jcrMixinTypes).getValues();
NodeType types[] = node.getMixinNodeTypes();
assertEquals("getMixinNodeTypes() does not return the same number of " +
"node types as " +
"getProperty(\"jcr:mixinTypes\").getValues()",
types.length,
names.length);
StringBuffer namesString = new StringBuffer();
for (int i = 0; i < names.length; i++) {
namesString.append("|" + names[i].getString() + "|");
}
for (int i = 0; i < types.length; i++) {
String pattern = "|" + types[i].getName() + "|";
assertTrue("getMixinNodeTypes() does not return the same node" +
"types as getProperty(\"jcr:mixinTypes\").getValues()",
namesString.indexOf(pattern) != -1);
assertTrue("All nodes returned by getMixinNodeTypes() must be" +
"mixin",
types[i].isMixin());
}
}
/**
* Test if isNodeTye(String nodeTypeName) returns true if nodeTypeName is the
* name of the primary node type, the name of a mixin node type and the name
* of a supertype.
*/
public void testIsNodeType()
throws NotExecutableException, RepositoryException {
String nodeTypeName;
// test with primary node's name
nodeTypeName = testRootNode.getPrimaryNodeType().getName();
assertTrue("isNodeType(String nodeTypeName) must return true if " +
"nodeTypeName is the name of the primary node type",
testRootNode.isNodeType(nodeTypeName));
String expNodeTypeName = getQualifiedName(testRootNode.getSession(), nodeTypeName);
assertTrue("isNodeType(String expNodeTypeName) must return true if "
+ "expNodeTypeName is the name of the primary node type", testRootNode.isNodeType(expNodeTypeName));
// test with mixin node's name
// (if such a node is available)
Node nodeWithMixin = locateNodeWithMixinNodeTypes(testRootNode);
if (nodeWithMixin != null) {
NodeType types[] = nodeWithMixin.getMixinNodeTypes();
nodeTypeName = types[0].getName();
expNodeTypeName = getQualifiedName(testRootNode.getSession(), nodeTypeName);
assertTrue("isNodeType(String nodeTypeName) must return true if " + "nodeTypeName is the name of one of the "
+ "mixin node types", nodeWithMixin.isNodeType(nodeTypeName));
assertTrue("isNodeType(String expNodeTypeName) must return true if " + "expNodeTypeName is the name of one of the "
+ "mixin node types", nodeWithMixin.isNodeType(expNodeTypeName));
}
// test with the name of predefined supertype "nt:base"
assertTrue("isNodeType(String nodeTypeName) must return true if " +
"nodeTypeName is the name of a node type of a supertype",
testRootNode.isNodeType(ntBase));
assertTrue("isNodeType(String nodeTypeName) must return true if "
+ "nodeTypeName is the name of a node type of a supertype", testRootNode.isNodeType(NodeType.NT_BASE));
}
//-----------------------< internal >---------------------------------------
/**
* Returns the first descendant of <code>node</code> which defines mixin
* node type(s).
*
* @param node <code>Node</code> to start traversal.
* @return first node with mixin node type(s)
*/
private Node locateNodeWithMixinNodeTypes(Node node)
throws RepositoryException {
if (node.getMixinNodeTypes().length != 0) {
return node;
}
NodeIterator nodes = node.getNodes();
while (nodes.hasNext()) {
Node returnedNode = this.locateNodeWithMixinNodeTypes(nodes.nextNode());
if (returnedNode != null) {
return returnedNode;
}
}
return null;
}
}