package org.exoplatform.services.jcr.impl.core.nodetype;
import org.exoplatform.services.jcr.core.nodetype.NodeDefinitionData;
import org.exoplatform.services.jcr.core.nodetype.NodeTypeData;
import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionData;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.LocationFactory;
import org.exoplatform.services.jcr.impl.core.NamespaceRegistryImpl;
import org.exoplatform.services.jcr.impl.core.nodetype.registration.CNDStreamReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.version.OnParentVersionAction;
/**
* Created by The eXo Platform SAS. This class provides set of test for CND
* grammar parser implementation
*
* @author <a href="mailto:nikolazius@gmail.com">Nikolay Zamosenchuk</a>
* @version $Id: $
*/
public class TestCNDParser extends AbstractNodeTypeTest
{
private final NamespaceRegistryImpl namespaceRegistry = new NamespaceRegistryImpl();
private final LocationFactory locationFactory = new LocationFactory(namespaceRegistry);
private InternalQName toName(String name) throws RepositoryException
{
return locationFactory.parseJCRName(name).getInternalName();
}
/**
* Runs {@link CNDStreamReader} with std.err and std.out redirecting to avoid
* parse errors output
*
* @param line
* String containing node types in compact node type format
* @return list of {@link NodeTypeData}
* @throws RepositoryException
*/
private List<NodeTypeData> parseString(String line) throws RepositoryException
{
/**
* Start of I/O Redirecting. gUnit test uses std.err and std.out to
* examine the result of running test. So in ordinary situation parse
* errors are printed in std.err. In this case std devices are replaced by
* stubs
*/
PrintStream console = System.out;
PrintStream consoleErr = System.err;
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(out);
PrintStream ps2 = new PrintStream(err);
System.setOut(ps);
System.setErr(ps2);
try
{
return new CNDStreamReader(namespaceRegistry).read(new ByteArrayInputStream(line.getBytes()));
}
finally
{
System.setOut(console); // Reset standard output
System.setErr(consoleErr); // Reset standard err
}
}
/**
* Testing whether correct default nodeType parameters are assigned
*/
public void testDefaultNodeTypeParameters()
{
try
{
String ntString = "<ns = 'http://namespace.com/ns'> [ns:NodeType]";
NodeTypeData ntdActual = parseString(ntString).get(0);
/** Correct names */
assertEquals(ntdActual.getName(), toName("ns:NodeType"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), null);
assertEquals(ntdActual.isMixin(), false);
assertEquals(ntdActual.hasOrderableChildNodes(), false);
//assertEquals(ntdActual.isAbstract(), false);
//assertEquals(ntdActual.isQueryable(), true);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{Constants.NT_BASE}));
/** Correct properties */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredPropertyDefinitions(), new PropertyDefinitionData[0]));
/** Correct children */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredChildNodeDefinitions(), new PropertyDefinitionData[0]));
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Testing registered words usage
*/
public void testRegisteredWordsUsage1()
{
try
{
String ntString = "<ns = 'http://namespace.com/ns'> [ns:COPY]";
NodeTypeData ntdActual = parseString(ntString).get(0);
/** Correct names */
assertEquals(ntdActual.getName(), toName("ns:COPY"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), null);
assertEquals(ntdActual.isMixin(), false);
assertEquals(ntdActual.hasOrderableChildNodes(), false);
//assertEquals(ntdActual.isAbstract(), false);
//assertEquals(ntdActual.isQueryable(), true);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{Constants.NT_BASE}));
/** Correct properties */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredPropertyDefinitions(), new PropertyDefinitionData[0]));
/** Correct children */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredChildNodeDefinitions(), new PropertyDefinitionData[0]));
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Testing registered words usage
*/
public void testRegisteredWordsUsage2()
{
try
{
String ntString =
"<opv = 'http://namespace.com/opv'> [opv:STRING] > opv:decimal, opv:URI abstract orderable mixin noquery";
NodeTypeData ntdActual = parseString(ntString).get(0);
/** Correct names */
assertEquals(ntdActual.getName(), toName("opv:STRING"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), null);
assertEquals(ntdActual.isMixin(), true);
assertEquals(ntdActual.hasOrderableChildNodes(), true);
//assertEquals(ntdActual.isAbstract(), true);
//assertEquals(ntdActual.isQueryable(), false);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{toName("opv:decimal"),
toName("opv:URI")}));
/** Correct properties */
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Testing registered words usage
*/
public void testRegisteredWordsUsage3()
{
try
{
String ntString =
"<opv = 'http://namespace.com/opv'> [opv:mixin] > opv:decimal, opv:URI abstract orderable mixin noquery";
NodeTypeData ntdActual = parseString(ntString).get(0);
/** Correct names */
assertEquals(ntdActual.getName(), toName("opv:mixin"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), null);
assertEquals(ntdActual.isMixin(), true);
assertEquals(ntdActual.hasOrderableChildNodes(), true);
//assertEquals(ntdActual.isAbstract(), true);
//assertEquals(ntdActual.isQueryable(), false);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{toName("opv:decimal"),
toName("opv:URI")}));
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Testing whether NT:BASE is assigned to nodeType.
*/
public void testBaseTypeAssign()
{
try
{
String ntString = "<ns = 'http://namespace.com/ns'> [ns:NodeType] abstract orderable mixin noquery";
NodeTypeData ntdActual = parseString(ntString).get(0);
/** Correct names */
assertEquals(ntdActual.getName(), toName("ns:NodeType"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), null);
assertEquals(ntdActual.isMixin(), true);
assertEquals(ntdActual.hasOrderableChildNodes(), true);
//assertEquals(ntdActual.isAbstract(), true);
//assertEquals(ntdActual.isQueryable(), false);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{Constants.NT_BASE}));
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* The simplest node type definition is provided to parser. Checking equality
* to expected result
*/
public void testSimpleNodeType()
{
try
{
String ntString =
"<ns = 'http://namespace.com/ns'> [ns:NodeType] > ns:ParentType1, ns:ParentType2 abstract orderable mixin noquery";
NodeTypeData ntdActual = parseString(ntString).get(0);
/** Correct names */
assertEquals(ntdActual.getName(), toName("ns:NodeType"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), null);
assertEquals(ntdActual.isMixin(), true);
assertEquals(ntdActual.hasOrderableChildNodes(), true);
//assertEquals(ntdActual.isAbstract(), true);
//assertEquals(ntdActual.isQueryable(), false);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{
toName("ns:ParentType1"), toName("ns:ParentType2")}));
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Checking if property's default parameters are assigned correctly
*/
public void testDefalultProprtyParameters()
{
try
{
String ntString =
"<ns = 'http://namespace.com/ns'> <ex = 'http://namespace.com/ex'> [ns:NodeType] > ns:ParentType1, ns:ParentType2 a o m nq ! ex:property "
+ "- ex:property";
NodeTypeData ntdActual = parseString(ntString).get(0);
PropertyDefinitionData ptdActual = ntdActual.getDeclaredPropertyDefinitions()[0];
assertEquals(ptdActual.getName(), toName("ex:property"));
assertEquals(ptdActual.isAutoCreated(), false);
assertEquals(ptdActual.isMandatory(), false);
assertEquals(ptdActual.getOnParentVersion(), OnParentVersionAction.COPY);
assertEquals(ptdActual.isProtected(), false);
assertEquals(ptdActual.getRequiredType(), PropertyType.STRING);
assertEquals(ptdActual.getValueConstraints(), null);
assertEquals(ptdActual.getDefaultValues(), null);
assertEquals(ptdActual.isMultiple(), false);
// assertEquals(ptdActual.isQueryOrderable(), true);
// String[] actual = ptdActual.getAvailableQueryOperators();
// String[] expected = Operator.getAllQueryOperators();
// Arrays.sort(actual);
// Arrays.sort(expected);
// assertTrue(Arrays.deepEquals(actual, expected));
// assertEquals(ptdActual.isFullTextSearchable(), true);
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Checking if child's default parameters are assigned correctly
*/
public void testDefaultChildParameters()
{
try
{
String ntString =
"<ns = 'http://namespace.com/ns'> <ex = 'http://namespace.com/ex'> [ns:NodeType] > ns:ParentType1, ns:ParentType2 a o m nq + ns:node";
NodeTypeData ntdActual = parseString(ntString).get(0);
NodeDefinitionData chdActual = ntdActual.getDeclaredChildNodeDefinitions()[0];
assertEquals(chdActual.getName(), toName("ns:node"));
assertEquals(chdActual.isAutoCreated(), false);
assertEquals(chdActual.isMandatory(), false);
assertEquals(chdActual.getOnParentVersion(), OnParentVersionAction.COPY);
assertEquals(chdActual.isProtected(), false);
assertEquals(chdActual.getDefaultPrimaryType(), null);
assertEquals(chdActual.isAllowsSameNameSiblings(), false);
assertTrue(Arrays.deepEquals(chdActual.getRequiredPrimaryTypes(), new InternalQName[]{Constants.NT_BASE}));
}
catch (RepositoryException e)
{
fail("Exception found " + e.getMessage());
}
}
/**
* Full nodetype definition is provided to parser. Checking equality to
* expected result
*/
public void testComplexNodeType()
{
try
{
String ntString =
"<ns = 'http://namespace.com/ns'> <ex = 'http://namespace.com/ex'> [ns:NodeType] > ns:ParentType1, ns:ParentType2 a o m nq ! ex:property "
+ "- ex:property (STRING) = 'default1', 'default2' mandatory aut protected * INITIALIZE "
+ "< 'constraint1', 'constraint2' queryops '=, <>, <, <=, >, >=, LIKE' nofulltext noqueryorder "
+ "+ ns:node (ns:reqType1, ns:reqType2) = ns:defaultType mandatory autocreated protected sns VERSION "
+ "+ ns:node2 (ns:reqType1, ns:reqType2, nt:subBase) man p * VERSION";
NodeTypeData ntdActual = parseString(ntString).get(0);
PropertyDefinitionData ptdActual = ntdActual.getDeclaredPropertyDefinitions()[0];
NodeDefinitionData chdActual1 = ntdActual.getDeclaredChildNodeDefinitions()[0];
NodeDefinitionData chdActual2 = ntdActual.getDeclaredChildNodeDefinitions()[1];
/** Correct names */
assertEquals(ntdActual.getName(), toName("ns:NodeType"));
/** Correct attributes */
assertEquals(ntdActual.getPrimaryItemName(), toName("ex:property"));
assertEquals(ntdActual.isMixin(), true);
assertEquals(ntdActual.hasOrderableChildNodes(), true);
// assertEquals(ntdActual.isAbstract(), true);
// assertEquals(ntdActual.isQueryable(), false);
/** Correct supertypes */
assertTrue(Arrays.deepEquals(ntdActual.getDeclaredSupertypeNames(), new InternalQName[]{
toName("ns:ParentType1"), toName("ns:ParentType2")}));
/** Correct properties */
assertEquals(ptdActual.getName(), toName("ex:property"));
assertEquals(ptdActual.isAutoCreated(), true);
assertEquals(ptdActual.isMandatory(), true);
assertEquals(ptdActual.getOnParentVersion(), OnParentVersionAction.INITIALIZE);
assertEquals(ptdActual.isProtected(), true);
assertEquals(ptdActual.getRequiredType(), PropertyType.STRING);
assertTrue(Arrays.deepEquals(ptdActual.getValueConstraints(), new String[]{"constraint1", "constraint2"}));
assertTrue(Arrays.deepEquals(ptdActual.getDefaultValues(), new String[]{"default1", "default2"}));
assertEquals(ptdActual.isMultiple(), true);
// assertEquals(ptdActual.isQueryOrderable(), false);
// String[] actual = ptdActual.getAvailableQueryOperators();
// String[] expected = new String[]{"=", "<>", "<", "<=", ">", ">=", "LIKE"};
// Arrays.sort(actual);
// Arrays.sort(expected);
// assertTrue(Arrays.deepEquals(actual, expected));
// assertEquals(ptdActual.isFullTextSearchable(), false);
/** Correct children */
// first child
assertEquals(chdActual1.getName(), toName("ns:node"));
assertEquals(chdActual1.isAutoCreated(), true);
assertEquals(chdActual1.isMandatory(), true);
assertEquals(chdActual1.getOnParentVersion(), OnParentVersionAction.VERSION);
assertEquals(chdActual1.isProtected(), true);
assertEquals(chdActual1.getDefaultPrimaryType(), toName("ns:defaultType"));
assertEquals(chdActual1.isAllowsSameNameSiblings(), true);
assertTrue(Arrays.deepEquals(chdActual1.getRequiredPrimaryTypes(), new InternalQName[]{toName("ns:reqType1"),
toName("ns:reqType2")}));
// second child
assertEquals(chdActual2.getName(), toName("ns:node2"));
assertEquals(chdActual2.isAutoCreated(), false);
assertEquals(chdActual2.isMandatory(), true);
assertEquals(chdActual2.getOnParentVersion(), OnParentVersionAction.VERSION);
assertEquals(chdActual2.isProtected(), true);
assertEquals(chdActual2.getDefaultPrimaryType(), null);
assertEquals(chdActual2.isAllowsSameNameSiblings(), true);
assertTrue(Arrays.deepEquals(chdActual2.getRequiredPrimaryTypes(), new InternalQName[]{toName("ns:reqType1"),
toName("ns:reqType2"), toName("nt:subBase")}));
}
catch (RepositoryException e)
{
fail("Exception found ");
}
}
/**
* Testing whether wrong operator is handled correctly.
*/
public void testWrongOperator()
{
try
{
String ntString =
"<ns = 'http://namespace.com/ns'> <ex = 'http://namespace.com/ex'> [ns:NodeType] > ns:ParentType1, ns:ParentType2 a o m nq ! ex:property - ex:property (STRING) "
+ "= 'default1', 'default2' mandatory autocreated protected multiple VERSION < 'constraint1', 'constraint2' "
+ "queryops '=, <>, <, =>, >, >=, LIKE' nofulltext noqueryorder";
parseString(ntString);
fail("Exception should be generated! Wrong operator.");
}
catch (RepositoryException e)
{
// it's ok!
}
}
/**
* Testing whether wrong name is handled correctly.
*/
public void testWrongName()
{
try
{
String ntString =
"<ns = 'http://namespace.com/ns'> [ns::::NodeType] > ns:ParentType1, ns:ParentType2 a o m nq ! ex:property - ex:property (STRING) "
+ "= 'default1', 'default2' mandatory autocreated protected multiple VERSION < 'constraint1', 'constraint2' "
+ "queryops '=, <>, <, =>, >, >=, LIKE' nofulltext noqueryorder";
parseString(ntString);
fail("Exception should be generated! Wrong name.");
}
catch (RepositoryException e)
{
// it's ok!
}
}
/**
* Testing whether wrong input sequence is handled correctly.
*/
public void testWrongInput1()
{
try
{
String ntString =
"]ns:NodeType[ >< ns:ParentType1, ns:ParentType2 a o m nq ! ex:property - ex:property (STRING) ";
parseString(ntString);
fail("Exception should be generated! Wrong input.");
}
catch (RepositoryException e)
{
// it's ok!
}
}
/**
* Testing whether wrong input sequence is handled correctly.
*/
public void testWrongInput2()
{
try
{
String ntString =
"[ns:NodeType] < ns:ParentType1, ns:ParentType2 >a o m nq ! ex:property - ex:property (STRING) ";
parseString(ntString);
fail("Exception should be generated! Wrong input.");
}
catch (RepositoryException e)
{
// it's ok!
}
}
/**
* Testing whether wrong input sequence is handled correctly.
*/
public void testWrongInput3()
{
try
{
String ntString =
"[ns:NodeType] > ns:ParentType1, ns:ParentType2 a o =m -nq ! ex:property - ex:property (STRING) ";
parseString(ntString);
fail("Exception should be generated! Wrong input.");
}
catch (RepositoryException e)
{
// it's ok!
}
}
}