/* * 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.sequencer.cnd; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.AUTO_CREATED; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.CHILD_NODE_DEFINITION; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.DEFAULT_PRIMARY_TYPE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.DEFAULT_VALUES; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.HAS_ORDERABLE_CHILD_NODES; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.IS_ABSTRACT; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.IS_FULL_TEXT_SEARCHABLE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.IS_MIXIN; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.IS_QUERYABLE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.IS_QUERY_ORDERABLE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.MANDATORY; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.MULTIPLE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.NAME; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.NODE_TYPE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.NODE_TYPE_NAME; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.ON_PARENT_VERSION; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.PROPERTY_DEFINITION; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.PROTECTED; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.REQUIRED_PRIMARY_TYPES; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.REQUIRED_TYPE; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.SAME_NAME_SIBLINGS; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.SUPERTYPES; import static org.modeshape.sequencer.cnd.CndSequencerLexicon.VALUE_CONSTRAINTS; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Value; import javax.jcr.version.OnParentVersionAction; import org.junit.Test; import org.modeshape.jcr.api.JcrConstants; import org.modeshape.jcr.sequencer.AbstractSequencerTest; import org.modeshape.schematic.internal.annotation.FixFor; /** * Unit test for {@link CndSequencer} * * @author Horia Chiorean */ public class CndSequencerTest extends AbstractSequencerTest { @Override protected InputStream getRepositoryConfigStream() { return resourceStream("sequencer/cnd/repo-config.json"); } @Test public void sequenceImages() throws Exception { Node imagesNode = createNodeWithContentFromFile("images.cnd", "sequencer/cnd/images.cnd"); verifyImageMetadataNode(imagesNode); verifyEmbeddedImageNode(imagesNode); } private void verifyEmbeddedImageNode( Node imagesNode ) throws Exception { Node embeddedImageNode = getOutputNode(imagesNode, "image:embeddedImage"); assertNotNull(embeddedImageNode); new NodeDefinitionVerifier().name("image:embeddedImage").nodeTypeName("image:embeddedImage").mixin(true).verifyNode(embeddedImageNode); NodeIterator nodesIterator = embeddedImageNode.getNodes(); Node propertyDefinition = nodesIterator.nextNode(); new PropertyDefinitionVerifier().name("image:width").mandatory(false).requiredType("long").verify(propertyDefinition); assertFalse(nodesIterator.hasNext()); } private void verifyImageMetadataNode( Node imagesNode ) throws Exception { Node imageMetadataNode = getOutputNode(imagesNode, "image:metadata"); assertNotNull(imageMetadataNode); new NodeDefinitionVerifier().name("image:metadata").superTypes("nt:unstructured", "mix:mimeType").nodeTypeName("image:metadata").verifyNode(imageMetadataNode); NodeIterator nodesIterator = imageMetadataNode.getNodes(); Node propertyDefinition = nodesIterator.nextNode(); new PropertyDefinitionVerifier().name("image:formatName").mandatory(true).requiredType("string").valueConstraints("JPEG", "GIF", "PNG", "BMP", "PCX", "IFF", "RAS", "PBM", "PGM", "PPM", "PSD").verify(propertyDefinition); propertyDefinition = nodesIterator.nextNode(); new PropertyDefinitionVerifier().name("image:width").mandatory(false).requiredType("long").verify(propertyDefinition); propertyDefinition = nodesIterator.nextNode(); new PropertyDefinitionVerifier().name("image:progressive").mandatory(false).requiredType("boolean").verify(propertyDefinition); Node childNodeDefinition = nodesIterator.nextNode(); new NodeDefinitionVerifier().name("image:subImage").sameNameSiblings(true).requiredPrimaryTypes("image:embeddedImage").defaultPrimaryType("image:embeddedImage").verifyChildNode(childNodeDefinition); assertFalse(nodesIterator.hasNext()); } @Test public void ignoreInvalidFiles() throws Exception { final Node invalidNode = createNodeWithContentFromFile("invalid.cnd", "sequencer/cnd/invalid.cnd"); Thread.sleep(TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS)); NodeIterator nodeIterator = invalidNode.getNodes(); assertEquals("/invalid.cnd/jcr:content", nodeIterator.nextNode().getPath()); assertFalse(nodeIterator.hasNext()); } @Test @FixFor("MODE-2658") public void shouldRemovePreviousOutputWhenSequencingSameInput() throws Exception { Node imagesNode = createNodeWithContentFromFile("images.cnd", "sequencer/cnd/images.cnd"); Node imageMetadataNode = getOutputNode("/sequenced/images.cnd"); assertNotNull(imageMetadataNode); imagesNode.remove(); session.save(); createNodeWithContentFromFile("images.cnd", "sequencer/cnd/images.cnd"); imageMetadataNode = getOutputNode("/sequenced/images.cnd"); assertNotNull(imageMetadataNode); Node sequencedRoot = session.getNode("/sequenced"); assertEquals("Previous output should've been removed",1, sequencedRoot.getNodes().getSize()); } protected List<String> sortedListToLowerCase( List<String> valuesList ) { List<String> result = new ArrayList<String>(); for (String value : valuesList) { result.add(value.toLowerCase()); } Collections.sort(result); return result; } protected List<String> sortedValuesToLowerCase( Value[] values ) throws Exception { List<String> result = new ArrayList<String>(); for (Value value : values) { result.add(value.getString().toLowerCase()); } Collections.sort(result); return result; } protected class NodeDefinitionVerifier { private String name; private boolean mixin = false; private boolean isAbstract = false; private boolean isQueryable = true; private String nodeTypeName; private boolean hasOrderableChildNodes = false; private List<String> superTypes = Collections.emptyList(); private boolean autoCreated = false; private boolean mandatory = false; private String onParentVersion = OnParentVersionAction.ACTIONNAME_COPY.toLowerCase(); private boolean isProtected = false; private String defaultPrimaryType; private List<String> requiredPrimaryTypes = Collections.emptyList(); private boolean sameNameSiblings = false; NodeDefinitionVerifier autoCreated( final boolean autoCreated ) { this.autoCreated = autoCreated; return this; } NodeDefinitionVerifier name( final String name ) { this.name = name.toLowerCase(); return this; } NodeDefinitionVerifier mixin( final boolean mixin ) { this.mixin = mixin; return this; } NodeDefinitionVerifier isAbstract( final boolean isAbstract ) { this.isAbstract = isAbstract; return this; } NodeDefinitionVerifier isQueryable( final boolean isQueryable ) { this.isQueryable = isQueryable; return this; } NodeDefinitionVerifier nodeTypeName( final String nodeTypeName ) { this.nodeTypeName = nodeTypeName.toLowerCase(); return this; } NodeDefinitionVerifier hasOrderableChildNodes( final boolean hasOrderableChildNodes ) { this.hasOrderableChildNodes = hasOrderableChildNodes; return this; } NodeDefinitionVerifier superTypes( final String... superTypes ) { this.superTypes = sortedListToLowerCase(Arrays.asList(superTypes)); return this; } NodeDefinitionVerifier mandatory( final boolean mandatory ) { this.mandatory = mandatory; return this; } NodeDefinitionVerifier onParentVersion( final String onParentVersion ) { this.onParentVersion = onParentVersion; return this; } NodeDefinitionVerifier isProtected( final boolean isProtected ) { this.isProtected = isProtected; return this; } NodeDefinitionVerifier requiredPrimaryTypes( final String... requiredPrimaryTypes ) { this.requiredPrimaryTypes = sortedListToLowerCase(Arrays.asList(requiredPrimaryTypes)); return this; } NodeDefinitionVerifier sameNameSiblings( boolean sameNameSiblings ) { this.sameNameSiblings = sameNameSiblings; return this; } NodeDefinitionVerifier defaultPrimaryType( final String defaultPrimaryType ) { this.defaultPrimaryType = defaultPrimaryType.toLowerCase(); return this; } void verifyNode( Node nodeDefinition ) throws Exception { assertEquals(NODE_TYPE.toLowerCase(), nodeDefinition.getProperty(JcrConstants.JCR_PRIMARY_TYPE).getString().toLowerCase()); assertEquals(mixin, nodeDefinition.getProperty(IS_MIXIN).getBoolean()); assertEquals(isAbstract, nodeDefinition.getProperty(IS_ABSTRACT).getBoolean()); assertEquals(isQueryable, nodeDefinition.getProperty(IS_QUERYABLE).getBoolean()); assertNotNull(nodeTypeName); assertEquals(nodeTypeName, nodeDefinition.getProperty(NODE_TYPE_NAME).getString().toLowerCase()); assertEquals(hasOrderableChildNodes, nodeDefinition.getProperty(HAS_ORDERABLE_CHILD_NODES).getBoolean()); assertEquals(superTypes, sortedValuesToLowerCase(nodeDefinition.getProperty(SUPERTYPES).getValues())); } void verifyChildNode( Node childNodeDefinition ) throws Exception { assertEquals(CHILD_NODE_DEFINITION.toLowerCase(), childNodeDefinition.getProperty(JcrConstants.JCR_PRIMARY_TYPE).getString().toLowerCase()); assertNotNull(name); assertEquals(name, childNodeDefinition.getProperty(NAME).getString().toLowerCase()); assertEquals(autoCreated, childNodeDefinition.getProperty(AUTO_CREATED).getBoolean()); assertEquals(mandatory, childNodeDefinition.getProperty(MANDATORY).getBoolean()); assertNotNull(onParentVersion); assertEquals(onParentVersion, childNodeDefinition.getProperty(ON_PARENT_VERSION).getString().toLowerCase()); assertEquals(isProtected, childNodeDefinition.getProperty(PROTECTED).getBoolean()); assertNotNull(defaultPrimaryType); assertEquals(defaultPrimaryType, childNodeDefinition.getProperty(DEFAULT_PRIMARY_TYPE).getString().toLowerCase()); assertEquals(requiredPrimaryTypes, sortedValuesToLowerCase(childNodeDefinition.getProperty(REQUIRED_PRIMARY_TYPES).getValues())); assertEquals(sameNameSiblings, childNodeDefinition.getProperty(SAME_NAME_SIBLINGS).getBoolean()); assertEquals(sameNameSiblings, childNodeDefinition.getProperty(SAME_NAME_SIBLINGS).getBoolean()); } } private class PropertyDefinitionVerifier { private String name; private boolean autoCreated = false; private boolean mandatory = false; private String onParentVersion = OnParentVersionAction.ACTIONNAME_COPY.toLowerCase(); private boolean isProtected = false; private String requiredType; private List<String> valueConstraints = Collections.emptyList(); private List<String> defaultValues = Collections.emptyList(); private boolean multiple = false; private boolean fullTextSearchable = true; private boolean queryOrderable = true; protected PropertyDefinitionVerifier() { } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier autoCreated( boolean autoCreated ) { this.autoCreated = autoCreated; return this; } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier defaultValues( String... defaultValues ) { this.defaultValues = sortedListToLowerCase(Arrays.asList(defaultValues)); return this; } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier fullTextSearchable( boolean fullTextSearchable ) { this.fullTextSearchable = fullTextSearchable; return this; } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier isProtected( boolean isProtected ) { this.isProtected = isProtected; return this; } PropertyDefinitionVerifier mandatory( boolean mandatory ) { this.mandatory = mandatory; return this; } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier multiple( boolean multiple ) { this.multiple = multiple; return this; } PropertyDefinitionVerifier name( String name ) { this.name = name.toLowerCase(); return this; } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier onParentVersion( String onParentVersion ) { this.onParentVersion = onParentVersion.toLowerCase(); return this; } @SuppressWarnings( "unused" ) PropertyDefinitionVerifier queryOrderable( boolean queryOrderable ) { this.queryOrderable = queryOrderable; return this; } PropertyDefinitionVerifier requiredType( String requiredType ) { this.requiredType = requiredType; return this; } PropertyDefinitionVerifier valueConstraints( String... valueConstraints ) { this.valueConstraints = sortedListToLowerCase(Arrays.asList(valueConstraints)); return this; } void verify( Node propertyDefinition ) throws Exception { assertEquals(PROPERTY_DEFINITION.toLowerCase(), propertyDefinition.getProperty(JcrConstants.JCR_PRIMARY_TYPE).getString().toLowerCase()); assertNotNull(name); assertEquals(name, propertyDefinition.getProperty(NAME).getString().toLowerCase()); assertEquals(autoCreated, propertyDefinition.getProperty(AUTO_CREATED).getBoolean()); assertEquals(mandatory, propertyDefinition.getProperty(MANDATORY).getBoolean()); assertEquals(multiple, propertyDefinition.getProperty(MULTIPLE).getBoolean()); assertEquals(fullTextSearchable, propertyDefinition.getProperty(IS_FULL_TEXT_SEARCHABLE).getBoolean()); assertEquals(queryOrderable, propertyDefinition.getProperty(IS_QUERY_ORDERABLE).getBoolean()); assertEquals(isProtected, propertyDefinition.getProperty(PROTECTED).getBoolean()); assertNotNull(onParentVersion); assertEquals(onParentVersion, propertyDefinition.getProperty(ON_PARENT_VERSION).getString().toLowerCase()); assertNotNull(requiredType); assertEquals(requiredType, propertyDefinition.getProperty(REQUIRED_TYPE).getString().toLowerCase()); assertEquals(valueConstraints, sortedValuesToLowerCase(propertyDefinition.getProperty(VALUE_CONSTRAINTS).getValues())); assertEquals(defaultValues, sortedValuesToLowerCase(propertyDefinition.getProperty(DEFAULT_VALUES).getValues())); } } }