/* * 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.sequencer; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; /** * @author Randall Hauch */ public class SequencerPathExpressionTest { private SequencerPathExpression expr; @Before public void beforeEach() throws Exception { expr = new SequencerPathExpression(new PathExpression(".*"), "/output"); } @Test( expected = IllegalArgumentException.class ) public void shouldNotCompileNullExpression() throws Exception { SequencerPathExpression.compile(null); } @Test( expected = InvalidSequencerPathExpression.class ) public void shouldNotCompileZeroLengthExpression() throws Exception { SequencerPathExpression.compile(""); } @Test( expected = InvalidSequencerPathExpression.class ) public void shouldNotCompileBlankExpression() throws Exception { SequencerPathExpression.compile(" "); } @Test public void shouldCompileExpressionWithOnlySelectionExpression() throws Exception { expr = SequencerPathExpression.compile("/a/b/c"); assertThat(expr, is(notNullValue())); assertThat(expr.getSelectExpression(), is("/a/b/c")); assertThat(expr.getOutputExpression(), is(SequencerPathExpression.DEFAULT_OUTPUT_EXPRESSION)); } @Test( expected = InvalidSequencerPathExpression.class ) public void shouldNotCompileExpressionWithSelectionExpressionAndDelimiterAndNoOutputExpression() throws Exception { SequencerPathExpression.compile("/a/b/c=>"); } @Test public void shouldCompileExpressionWithSelectionExpressionAndDelimiterAndOutputExpression() throws Exception { expr = SequencerPathExpression.compile("/a/b/c=>."); assertThat(expr, is(notNullValue())); assertThat(expr.getSelectExpression(), is("/a/b/c")); assertThat(expr.getOutputExpression(), is(".")); expr = SequencerPathExpression.compile("/a/b/c=>/x/y"); assertThat(expr, is(notNullValue())); assertThat(expr.getSelectExpression(), is("/a/b/c")); assertThat(expr.getOutputExpression(), is("/x/y")); } @Test public void shouldCompileExpressionWithExtraWhitespace() throws Exception { expr = SequencerPathExpression.compile(" /a/b/c => . "); assertThat(expr, is(notNullValue())); assertThat(expr.getSelectExpression(), is("/a/b/c")); assertThat(expr.getOutputExpression(), is(".")); expr = SequencerPathExpression.compile(" /a/b/c => /x/y "); assertThat(expr, is(notNullValue())); assertThat(expr.getSelectExpression(), is("/a/b/c")); assertThat(expr.getOutputExpression(), is("/x/y")); } @Test public void shouldCompileExpressionWithIndexes() throws Exception { assertThat(SequencerPathExpression.compile("/a/b[0]/c[1]/d/e"), is(notNullValue())); assertThat(SequencerPathExpression.compile("/a/b[0]/c[1]/d/e[2]"), is(notNullValue())); } protected void assertNotMatches( SequencerPathExpression.Matcher matcher ) { assertThat(matcher, is(notNullValue())); assertThat(matcher.getSelectedPath(), is(nullValue())); assertThat(matcher.getOutputPath(), is(nullValue())); assertThat(matcher.matches(), is(false)); } protected void assertMatches( SequencerPathExpression.Matcher matcher, String selectedPath, String outputPath ) { assertMatches(matcher, selectedPath, null, outputPath); } protected void assertMatches( SequencerPathExpression.Matcher matcher, String selectedPath, String outputWorkspace, String outputPath ) { assertThat(matcher, is(notNullValue())); assertThat(matcher.getSelectedPath(), is(selectedPath)); assertThat(matcher.getOutputPath(), is(outputPath)); assertThat(matcher.getOutputWorkspaceName(), is(outputWorkspace)); if (selectedPath == null) { assertThat(matcher.matches(), is(false)); } else { assertThat(matcher.matches(), is(true)); } } @Test public void shouldMatchExpressionsWithoutRegardToCase() throws Exception { expr = SequencerPathExpression.compile("/a/b/c/d/e[@something] => ."); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/a/b/c/d/e"); assertMatches(expr.matcher("/a/b/c/d/E/@something"), "/a/b/c/d/E", "/a/b/c/d/E"); } @Test public void shouldMatchExpressionsWithExactFullPath() throws Exception { expr = SequencerPathExpression.compile("/a/b/c/d/e[@something] => ."); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/a/b/c/d/e"); assertNotMatches(expr.matcher("/a/b/c/d/E/@something2")); assertNotMatches(expr.matcher("/a/b/c/d/ex/@something")); assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something")); } @Test public void shouldMatchExpressionsWithExactFullPathAndExtraPathInsideMatch() throws Exception { expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => ."); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c"); assertNotMatches(expr.matcher("/a/b/c/d/E/@something2")); assertNotMatches(expr.matcher("/a/b/c/d/ex/@something")); assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something")); } @Test public void shouldMatchExpressionsWithWildcardSelection() throws Exception { expr = SequencerPathExpression.compile("/a/*/c[d/e/@something] => ."); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c"); assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c", "/a/b[2]/c"); assertMatches(expr.matcher("/a/rt/c/d/e/@something"), "/a/rt/c", "/a/rt/c"); assertNotMatches(expr.matcher("/ac/d/e/@something")); } @Test public void shouldMatchExpressionsWithFilenameLikeWildcardSelection() throws Exception { expr = SequencerPathExpression.compile("/a/*.txt[@something] => ."); assertMatches(expr.matcher("/a/b.txt/@something"), "/a/b.txt", "/a/b.txt"); assertNotMatches(expr.matcher("/a/b.tx/@something")); expr = SequencerPathExpression.compile("/a/*.txt/c[@something] => ."); assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c"); assertNotMatches(expr.matcher("/a/b.tx/c/@something")); expr = SequencerPathExpression.compile("//*.txt[*]/c[@something] => ."); assertMatches(expr.matcher("/a/b.txt/c/@something"), "/a/b.txt/c", "/a/b.txt/c"); assertNotMatches(expr.matcher("/a/b.tx/c/@something")); } @Test public void shouldMatchExpressionsWithSegmentWildcardSelection() throws Exception { expr = SequencerPathExpression.compile("/a//c[d/e/@something] => ."); assertMatches(expr.matcher("/a/c/d/e/@something"), "/a/c", "/a/c"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/a/b/c"); assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c", "/a/b[2]/c"); assertMatches(expr.matcher("/a/rt/c/d/e/@something"), "/a/rt/c", "/a/rt/c"); assertMatches(expr.matcher("/a/r/s/t/c/d/e/@something"), "/a/r/s/t/c", "/a/r/s/t/c"); assertMatches(expr.matcher("/a/r[1]/s[2]/t[33]/c/d/e/@something"), "/a/r[1]/s[2]/t[33]/c", "/a/r[1]/s[2]/t[33]/c"); assertNotMatches(expr.matcher("/a[3]/c/d/e/@something")); } @Test public void shouldMatchExpressionsWithIndexesInSelectionPaths() throws Exception { expr = SequencerPathExpression.compile("/a/b[2,3,4,5]/c/d/e[@something] => /x/y"); assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y"); assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something")); assertNotMatches(expr.matcher("/a/b/c/d/e/@something")); assertNotMatches(expr.matcher("/a[1]/b/c/d/e/@something")); expr = SequencerPathExpression.compile("/a/b[0,2,3,4,5]/c/d/e[@something] => /x/y"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y"); assertNotMatches(expr.matcher("/a/b[1]/c/d/e/@something")); assertNotMatches(expr.matcher("/a[1]/b/c/d/e/@something")); } @Test public void shouldMatchExpressionsWithAnyIndexesInSelectionPaths() throws Exception { expr = SequencerPathExpression.compile("/a/b[*]/c[]/d/e[@something] => /x/y"); assertMatches(expr.matcher("/a/b[2]/c/d/e/@something"), "/a/b[2]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[3]/c/d/e/@something"), "/a/b[3]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[4]/c/d/e/@something"), "/a/b[4]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[5]/c/d/e/@something"), "/a/b[5]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[1]/c/d/e/@something"), "/a/b[1]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[6]/c/d/e/@something"), "/a/b[6]/c/d/e", "/x/y"); assertMatches(expr.matcher("/a/b[6]/c[1]/d/e/@something"), "/a/b[6]/c[1]/d/e", "/x/y"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c/d/e", "/x/y"); } @Test public void shouldMatchExpressionsWithFullOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/y"); } public void shouldMatchExpressionsWithRepositoryInSelectionPath() throws Exception { expr = SequencerPathExpression.compile("reposA::/a/b/c[d/e/@something] => /x/y"); assertMatches(expr.matcher(":/a/b/c/d/e/@something"), "/a/b/c", null, "/x/y"); } public void shouldMatchExpressionsWithRepositoryAndWorkspaceInSelectionPath() throws Exception { expr = SequencerPathExpression.compile("reposA::/a/b/c[d/e/@something] => /x/y"); assertMatches(expr.matcher("wsA:/a/b/c/d/e/@something"), "/a/b/c", "wsA", "/x/y"); } public void shouldMatchExpressionsWithRepositoryInFullOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => :/x/y"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", null, "/x/y"); } @Test public void shouldMatchExpressionsWithNamedGroupsInOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a(//c)[d/e/@something] => $1/y/z"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/b/c/y/z"); expr = SequencerPathExpression.compile("/a(/(b|c|d|)/e)[f/g/@something] => $1/y/z"); assertMatches(expr.matcher("/a/b/e/f/g/@something"), "/a/b/e", "/b/e/y/z"); assertMatches(expr.matcher("/a/c/e/f/g/@something"), "/a/c/e", "/c/e/y/z"); assertMatches(expr.matcher("/a/d/e/f/g/@something"), "/a/d/e", "/d/e/y/z"); assertMatches(expr.matcher("/a/e/f/g/@something"), "/a/e", "/e/y/z"); assertNotMatches(expr.matcher("/a/t/e/f/g/@something")); expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /u/$1/y/z/$2/$3"); assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/u/b/c/y/z/d/f"); assertMatches(expr.matcher("/a/b/c/e/f/@something"), "/a/b/c", "/u/b/c/y/z/e/f"); assertMatches(expr.matcher("/a/b/c/d/g/@something"), "/a/b/c", "/u/b/c/y/z/d/g"); assertMatches(expr.matcher("/a/b/c/e/g/@something"), "/a/b/c", "/u/b/c/y/z/e/g"); expr = SequencerPathExpression.compile("/a/(b/c)/(d|e)/(f|g)/@something => /u/$1/y/z/$2/$3"); assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c/d/f", "/u/b/c/y/z/d/f"); assertMatches(expr.matcher("/a/b/c/e/f/@something"), "/a/b/c/e/f", "/u/b/c/y/z/e/f"); assertMatches(expr.matcher("/a/b/c/d/g/@something"), "/a/b/c/d/g", "/u/b/c/y/z/d/g"); assertMatches(expr.matcher("/a/b/c/e/g/@something"), "/a/b/c/e/g", "/u/b/c/y/z/e/g"); } @Test public void shouldMatchExpressionWithReoccurringNamedGroupsDollarsInOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /u/$1/y/z/$2/$3/$1/$1"); assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/u/b/c/y/z/d/f/b/c/b/c"); } @Test public void shouldMatchExpressionWithNamedGroupsAndEscapedDollarsInOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a/(b/c)[(d|e)/(f|g)/@something] => /\\$2u/$1/y/z/$2/$3"); assertMatches(expr.matcher("/a/b/c/d/f/@something"), "/a/b/c", "/\\$2u/b/c/y/z/d/f"); } @Test public void shouldMatchExpressionWithParentReferencesInOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y/z/../.."); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x"); expr = SequencerPathExpression.compile("/a/(b/c)[d/e/@something] => /x/$1/z/../../v"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/v"); } @Test public void shouldMatchExpressionWithSelfReferencesInOutputPath() throws Exception { expr = SequencerPathExpression.compile("/a/b/c[d/e/@something] => /x/y/./z/."); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/y/z"); expr = SequencerPathExpression.compile("/a/(b/c)[d/e/@something] => /x/$1/./z"); assertMatches(expr.matcher("/a/b/c/d/e/@something"), "/a/b/c", "/x/b/c/z"); } @Test public void shouldMatchExpressionWithFilenamePatternAndChildProperty() throws Exception { expr = SequencerPathExpression.compile("//(*.(jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd))[*]/jcr:content[@jcr:data]=>/images/$1"); assertMatches(expr.matcher("/a/b/caution.png/jcr:content/@jcr:data"), "/a/b/caution.png/jcr:content", "/images/caution.png"); } @Test public void shouldMatchExpressionWithArbitraryDepthCaptured() throws Exception { expr = SequencerPathExpression.compile("/files(//)*.xsd[*]/jcr:content[/@jcr:data] => /x/xsd/$1"); assertMatches(expr.matcher("/files/a/b/c/d/e.xsd/jcr:content/@jcr:data"), "/files/a/b/c/d/e.xsd/jcr:content", "/x/xsd/a/b/c/d"); expr = SequencerPathExpression.compile("/files(//)*.xsd[*]/jcr:content[@jcr:data] => /x/xsd/$1"); assertMatches(expr.matcher("/files/a/b/c/d/e.xsd/jcr:content/@jcr:data"), "/files/a/b/c/d/e.xsd/jcr:content", "/x/xsd/a/b/c/d"); expr = SequencerPathExpression.compile("/files(//)*.xsd[*]/jcr:content/[@jcr:data] => /x/xsd/$1"); assertMatches(expr.matcher("/files/a/b/c/d/e.xsd/jcr:content/@jcr:data"), "/files/a/b/c/d/e.xsd/jcr:content", "/x/xsd/a/b/c/d"); expr = SequencerPathExpression.compile("/files(//)*.xsd[*]/jcr:content/[@jcr:data] => /x/xsd/$1"); assertMatches(expr.matcher("/files/e.xsd/jcr:content/@jcr:data"), "/files/e.xsd/jcr:content", "/x/xsd"); expr = SequencerPathExpression.compile("/files(//)(*.xsd[*])[/jcr:content/@jcr:data] => /x/xsd/$1"); assertMatches(expr.matcher("/files/a/b/c/d/e.xsd/jcr:content/@jcr:data"), "/files/a/b/c/d/e.xsd", "/x/xsd/a/b/c/d"); assertMatches(expr.matcher("/files/a/b/c/d/e.xsd/jcr:content/@jcr:data"), "/files/a/b/c/d/e.xsd", "/x/xsd/a/b/c/d"); expr = SequencerPathExpression.compile("/files(//)(*.xsd[*])/jcr:content[@jcr:data] => /x/xsd/$2"); assertMatches(expr.matcher("/files/a/b/c/d/e.xsd/jcr:content/@jcr:data"), "/files/a/b/c/d/e.xsd/jcr:content", "/x/xsd/e.xsd"); } }