/**
* This file Copyright (c) 2012 Magnolia International
* Ltd. (http://www.magnolia-cms.com). All rights reserved.
*
*
* This file is dual-licensed under both the Magnolia
* Network Agreement and the GNU General Public License.
* You may elect to use one or the other of these licenses.
*
* This file is distributed in the hope that it will be
* useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
* Redistribution, except as permitted by whichever of the GPL
* or MNA you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or
* modify this file under the terms of the GNU General
* Public License, Version 3, as published by the Free Software
* Foundation. You should have received a copy of the GNU
* General Public License, Version 3 along with this program;
* if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 2. For the Magnolia Network Agreement (MNA), this file
* and the accompanying materials are made available under the
* terms of the MNA which accompanies this distribution, and
* is available at http://www.magnolia-cms.com/mna.html
*
* Any modifications to this file must keep this entire header
* intact.
*
*/
package info.magnolia.jcr.wrapper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import info.magnolia.jcr.util.NodeUtil;
import info.magnolia.test.mock.jcr.MockNode;
import info.magnolia.test.mock.jcr.SessionTestUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.junit.Test;
/**
* @version $Id$
*/
public class ExtendingNodeWrapperTest {
private Session session;
@Test
public void testExtendsPropertyIsHidden() throws RepositoryException, IOException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/bla/bla.prop2=world\n" +
"/impl/node.prop1=hello\n" +
"/impl/node.extends=../../bla/bla\n"
);
Node plainNode = session.getNode("impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertFalse(extendedNode.hasProperty(ExtendingNodeWrapper.EXTENDING_NODE_PROPERTY));
// WHEN
try {
extendedNode.getProperty(ExtendingNodeWrapper.EXTENDING_NODE_PROPERTY);
fail("Should not get there.");
// THEN
} catch (PathNotFoundException e) {
assertEquals("Cannont access property [/impl/node.extends]", e.getMessage());
}
// WHEN
PropertyIterator it = extendedNode.getProperties();
// THEN
while(it.hasNext()) {
Property prop = (Property) it.next();
if(prop.getName().equals(ExtendingNodeWrapper.EXTENDING_NODE_PROPERTY)) {
fail("Found extends property that is supposed to be hidden.");
}
}
}
@Test
public void testNodePropertiesAreMerged() throws RepositoryException, IOException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/bla/bla.prop2=world\n" +
"/impl/node.prop1=hello\n" +
"/impl/node.extends=../../bla/bla\n"
);
Node plainNode = session.getNode("impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertTrue(extendedNode.hasProperty("prop1"));
assertTrue(extendedNode.hasProperty("prop2"));
assertFalse(extendedNode.hasProperty("nonexistingProperty"));
assertEquals("hello", extendedNode.getProperty("prop1").getString());
assertEquals("world", extendedNode.getProperty("prop2").getString());
assertEquals(2, extendedNode.getProperties().getSize());
}
@Test
public void testPropertiesCanBeOverriden() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/bla/bla.prop1=default\n" +
"/impl/node.prop1=new\n" +
"/impl/node.extends=../../bla/bla\n"
);
Node plainNode = session.getNode("impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertEquals("new", extendedNode.getProperty("prop1").getString());
assertEquals(1, extendedNode.getProperties().getSize());
}
@Test
public void testThatSubNodesAreMerged() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/bla/bla/subnode1\n" +
"/impl/node/subnode2\n" +
"/impl/node.extends=../../bla/bla\n"
);
Node plainNode = session.getNode("impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertTrue(extendedNode.hasNode("subnode1"));
assertTrue(extendedNode.hasNode("subnode2"));
assertNotNull(extendedNode.getNode("subnode1"));
assertNotNull(extendedNode.getNode("subnode2"));
assertEquals(2, extendedNode.getNodes().getSize());
}
@Test
public void testThatSubNodesCanBeOverwritten() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/bla/bla/subnode.@uuid=1\n" +
"/impl/node/subnode.@uuid=2\n" +
"/impl/node.extends=../../bla/bla\n"
);
Node plainNode = session.getNode("impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertTrue(extendedNode.hasNode("subnode"));
assertEquals("2", extendedNode.getNode("subnode").getIdentifier());
assertEquals(1, extendedNode.getNodes().getSize());
}
@Test
public void testDeepMerge() throws IOException, RepositoryException{
// GIVEN
String [][] expected = new String[][]{
{"nodeData1","org1"}, // inherited
{"nodeData2","org2.2"}, // overwritten
{"nodeData3","org3"}, // added
};
session = SessionTestUtil.createSession("test",
"/base/node/subnode.nodeData1=org1\n" +
"/base/node/subnode.nodeData2=org2.1\n" +
"/impl/node.extends=../../base/node\n" +
"/impl/node/subnode.nodeData2=org2.2\n" +
"/impl/node/subnode.nodeData3=org3"
);
Node plainNode = session.getNode("/impl/node");
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// WHEN
Node subnode = extendedNode.getNode("subnode");
// THEN
for (String[] pair : expected) {
String name = pair[0];
String value = pair[1];
assertTrue(subnode.hasProperty(name));
assertEquals(value, subnode.getProperty(name).getString());
}
// WHEN
PropertyIterator it = subnode.getProperties();
// THEN
assertEquals(3, it.getSize());
int pos = 0;
while(it.hasNext()) {
Property prop = (Property) it.next();
assertEquals(expected[pos][1], prop.getString());
pos++;
}
}
@Test
public void testOrderIsKeptWhileMergingSubNodes() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/base/node/subnode1.@uuid=1\n" +
"/base/node/subnode2.@uuid=2.1\n" +
"/base/node/subnode3.@uuid=3\n" +
"/impl/node.extends=../../base/node\n" +
"/impl/node/subnode2.@uuid=2.2\n" +
"/impl/node/subnode4.@uuid=4"
);
Node plainNode = session.getNode("/impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertTrue(extendedNode.hasNode("subnode1"));
assertTrue(extendedNode.hasNode("subnode2"));
assertTrue(extendedNode.hasNode("subnode3"));
assertTrue(extendedNode.hasNode("subnode4"));
assertEquals("1", extendedNode.getNode("subnode1").getIdentifier());
assertEquals("2.2", extendedNode.getNode("subnode2").getIdentifier());
assertEquals("3", extendedNode.getNode("subnode3").getIdentifier());
assertEquals("4", extendedNode.getNode("subnode4").getIdentifier());
// WHEN
NodeIterator it = extendedNode.getNodes();
// THEN
assertEquals(4, it.getSize());
int i = 1;
while (it.hasNext()) {
Node child = (Node) it.next();
assertEquals("subnode" + i, child.getName());
i++;
}
}
@Test
public void testBasicMultipleInheritance() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/superbase/node.nodeData1=org1\n" +
"/base/node.extends=../../superbase/node\n" +
"/base/node.nodeData2=org2\n" +
"/impl/node.extends=../../base/node\n" +
"/impl/node.nodeData3=org3"
);
Node plainNode = session.getNode("/impl/node");
// WHEN
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertTrue(extendedNode.hasProperty("nodeData1"));
assertTrue(extendedNode.hasProperty("nodeData2"));
assertTrue(extendedNode.hasProperty("nodeData3"));
assertEquals("org1", extendedNode.getProperty("nodeData1").getString());
assertEquals("org2", extendedNode.getProperty("nodeData2").getString());
assertEquals("org3", extendedNode.getProperty("nodeData3").getString());
assertEquals(3, extendedNode.getProperties().getSize());
}
@Test
public void testComplextMultipleInheritance1() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/superbase.nodeData1=org1\n" +
"/base/node/subnode.nodeData2=org2\n" +
"/base/node/subnode.extends=/superbase\n" +
"/impl/node.extends=/base/node\n" +
"/impl/node/subnode.nodeData3=org3"
);
Node plainNode = session.getNode("/impl/node");
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// WHEN
Node subnode = extendedNode.getNode("subnode");
// THEN
assertTrue(subnode.hasProperty("nodeData1"));
assertTrue(subnode.hasProperty("nodeData2"));
assertTrue(subnode.hasProperty("nodeData3"));
assertEquals("org1", subnode.getProperty("nodeData1").getString());
assertEquals("org2", subnode.getProperty("nodeData2").getString());
assertEquals("org3", subnode.getProperty("nodeData3").getString());
assertEquals(3, subnode.getProperties().getSize());
}
@Test
public void testComplextMultipleInheritance2() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/superbase.nodeData1=org1\n" +
"/base/node/subnode.nodeData2=org2\n" +
"/impl/node.extends=/base/node\n" +
"/impl/node/subnode.extends=/superbase\n" +
"/impl/node/subnode.nodeData3=org3\n"
);
Node plainNode = session.getNode("/impl/node");
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// WHEN
Node subnode = extendedNode.getNode("subnode");
// THEN
assertTrue(subnode.hasProperty("nodeData1"));
assertTrue(subnode.hasProperty("nodeData2"));
assertTrue(subnode.hasProperty("nodeData3"));
assertEquals("org1", subnode.getProperty("nodeData1").getString());
assertEquals("org2", subnode.getProperty("nodeData2").getString());
assertEquals("org3", subnode.getProperty("nodeData3").getString());
assertEquals(3, subnode.getProperties().getSize());
}
@Test
public void testComplextMultipleInheritanceWithOverride() throws IOException, RepositoryException{
// GIVEN
session = SessionTestUtil.createSession("test",
"/superbase.nodeData1=org1\n" +
"/superbase/uglyChild/withSubChild.nodeDataX=over1\n" +
"/base/node/subnode.nodeData2=org2\n" +
"/impl/node.extends=/base/node\n" +
"/impl/node/subnode.extends=/superbase\n" +
"/impl/node/subnode/uglyChild.extends=override\n" +
"/impl/node/subnode.nodeData3=org3"
);
Node plainNode = session.getNode("/impl/node");
Node extendedNode = new ExtendingNodeWrapper(plainNode);
// WHEN
Node subnode = extendedNode.getNode("subnode");
// THEN
// inherited from superbase:
assertTrue(subnode.hasProperty("nodeData1"));
// inherited from base/node:/subnode
assertTrue(subnode.hasProperty("nodeData2"));
// subnode's own Node
assertTrue(subnode.hasProperty("nodeData3"));
// WHEN
// override defining node
Node disinheritedNode = subnode.getNode("uglyChild");
// THEN
// we hide extends now
assertFalse(disinheritedNode.hasProperty(ExtendingNodeWrapper.EXTENDING_NODE_PROPERTY));
// superbase child node should not be inherited because of override
assertFalse(disinheritedNode.hasNode("withSubChild"));
assertEquals("org2", subnode.getProperty("nodeData2").getString());
assertEquals("org3", subnode.getProperty("nodeData3").getString());
assertEquals(3, subnode.getProperties().getSize());
}
@Test
public void testExtendsNonAbsolutelyAndNodeIsNotExisting() throws IOException, RepositoryException {
// GIVEN
session = SessionTestUtil.createSession("test",
"/superbase.nodeData1=org1\n" +
"/superbase/uglyChild.nodeDataX=over1\n" +
"/impl/node.extends=/superbase\n" +
"/impl/node2.extends=../../superbase/uglyChild\n" +
"/impl/node3.extends=../../superbase/wrongNode"
);
try {
Node plainNode = session.getNode("/impl/node3");
// WHEN
new ExtendingNodeWrapper(plainNode, true);
fail("Must never get here!");
// THEN
} catch (RuntimeException e) {
assertEquals("Can't find referenced node for value: MockNode [primaryType=mgnl:contentNode, name=node3]", e.getMessage());
}
}
@Test
public void testExtendsWithEmptyValue() throws Exception {
// GIVEN
session = SessionTestUtil.createSession("test", "/impl/node\n");
Node plainNode = session.getNode("/impl/node");
plainNode.setProperty(ExtendingNodeWrapper.EXTENDING_NODE_PROPERTY, " ");
// WHEN
ExtendingNodeWrapper extendedNode = new ExtendingNodeWrapper(plainNode);
// THEN
assertFalse(extendedNode.isExtending());
}
@Test
public void testExtendsAbsolutelyAndNodeIsNotExisting() throws IOException, RepositoryException {
// GIVEN
session = SessionTestUtil.createSession("test",
"/impl/node.extends=/base/node\n" +
"/impl/node.nodeData2=org2"
);
Node plainNode = session.getNode("/impl/node");
// WHEN
try {
new ExtendingNodeWrapper(plainNode, true);
fail("should never get here...");
// THEN
} catch (RuntimeException e) {
assertEquals("Can't find referenced node for value: MockNode [primaryType=mgnl:contentNode, name=node]", e.getMessage());
}
}
@Test
public void testGetPath() throws RepositoryException {
// GIVEN
MockNode plainNode = new MockNode("impl");
Node subNode = plainNode.addNode("node");
Node extendedNode = new ExtendingNodeWrapper(subNode);
// WHEN
final String result = extendedNode.getPath();
// THEN
assertEquals("/impl/node", result);
}
@Test
public void testGetPropertiesByNamePattern() throws IOException, RepositoryException {
// GIVEN
session = SessionTestUtil.createSession("test",
"/superbase/node.nodeData1=org1\n" +
"/base/node.extends=../../superbase/node\n" +
"/base/node.nodeData2=org2\n" +
"/impl/node.extends=../../base/node\n" +
"/impl/node.nodeData3=org3"
);
Node plainNode = session.getNode("/impl/node");
Node extendedNode = new ExtendingNodeWrapper(plainNode);
List<String> propertyNames = new ArrayList<String>();
propertyNames.add("nodeData1");
propertyNames.add("nodeData2");
propertyNames.add("nodeData3");
// WHEN
PropertyIterator it = extendedNode.getProperties("node*");
// THEN
assertEquals(3, it.getSize());
while (it.hasNext()) {
Property prop = (Property) it.next();
assertTrue(propertyNames.contains(prop.getName()));
}
// again but pass array instead of string
// WHEN
it = extendedNode.getProperties(new String[] {"node*"});
// THEN
assertEquals(3, it.getSize());
while (it.hasNext()) {
Property prop = (Property) it.next();
assertTrue(propertyNames.contains(prop.getName()));
}
}
@Test
public void testGetNodesByNamePattern() throws IOException, RepositoryException {
// GIVEN
session = SessionTestUtil.createSession("test",
"/base/node/subnode1\n" +
"/base/node/subnode2\n" +
"/impl/node.extends=/base/node\n" +
"/impl/node/subnode2\n" +
"/impl/node/newnode"
);
Node plainNode = session.getNode("/impl/node");
Node extendedNode = new ExtendingNodeWrapper(plainNode);
List<String> nodeNames = new ArrayList<String>();
nodeNames.add("subnode1");
nodeNames.add("subnode2");
nodeNames.add("newnode");
// WHEN
NodeIterator it = extendedNode.getNodes("sub* | newnode");
// THEN
assertEquals(3, it.getSize());
int i = 0;
while (it.hasNext()) {
Node node = (Node) it.next();
assertEquals(nodeNames.get(i), node.getName());
i++;
}
// again but pass array instead of string
// WHEN
it = extendedNode.getNodes(new String[] {"sub*", "newnode"});
// THEN
assertEquals(3, it.getSize());
i = 0;
while (it.hasNext()) {
Node node = (Node) it.next();
assertEquals(nodeNames.get(i), node.getName());
i++;
}
}
@Test
public void testSubNodesAreWrapped() throws RepositoryException, IOException {
// GIVEN
session = SessionTestUtil.createSession("test",
"/parent.string=Hello\n" +
"/parent.integer=10\n" +
"/parent/beans/sub1.string=foo\n" +
"/parent/beans/sub2.string=bar\n" +
"/parent/beans/sub3.string=baz\n" +
"/sub/bean.string=World\n" +
"/sub/bean.integer=999\n" +
"/sub/bean.extends=/parent\n" +
"/another/sub/bean.extends=../../../sub/bean\n" +
"/another/sub/bean/beans/sub3.string=bla\n" +
"/another/sub/bean/beans/sub4.string=blah\n"
);
ExtendingNodeWrapper node = new ExtendingNodeWrapper(session.getNode("/another/sub/bean"));
// WHEN
List<Node> nodes = (List<Node>) NodeUtil.getSortedCollectionFromNodeIterator(node.getNode("beans").getNodes());
// THEN
assertEquals(4, nodes.size());
for (Node n : nodes) {
assertTrue(n instanceof ExtendingNodeWrapper);
}
assertEquals("foo", nodes.get(0).getProperty("string").getString());
assertEquals("bar", nodes.get(1).getProperty("string").getString());
assertEquals("bla", nodes.get(2).getProperty("string").getString());
assertEquals("blah", nodes.get(3).getProperty("string").getString());
}
@Test
public void testNodeCannotSelfExtend() throws IOException, RepositoryException {
// GIVEN
session = SessionTestUtil.createSession("test",
"/parent.extends=../parent\n"
);
// WHEN
ExtendingNodeWrapper node = new ExtendingNodeWrapper(session.getNode("/parent"));
// THEN
assertFalse(node.isExtending());
}
}