/*
* 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");
}
}