Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jackrabbit.spi.commons.name;
import javax.jcr.RepositoryException;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.Path.Element;
/**
* Pattern to match normalized {@link Path}s.
* A pattern matches either a constant path, a name of a path element, a selection of
* either of two patterns or a sequence of two patterns. The matching process is greedy.
* That is, whenever a match is not unique only the longest match is considered.
* Matching consumes as many elements from the beginning of an input path as possible and
* returns what's left as an instance of {@link MatchResult}.
* Use the {@link Matcher} class for matching a whole path or finding matches inside a path.
*/
public abstract class Pattern {
/**
* Matches this pattern against the input.
* @param input path to match with this pattern
* @return result from the matching pattern against input
* @throws IllegalArgumentException if input is not normalized
*/
public MatchResult match(Path input) {
try {
return match(new Context(input)).getMatchResult();
}
catch (RepositoryException e) {
throw (IllegalArgumentException) new IllegalArgumentException("Path not normalized")
.initCause(e);
}
}
protected abstract Context match(Context input) throws RepositoryException;
/**
* Construct a new pattern which matches an exact path
* @param path
* @return A pattern which matches path and nothing else
* @throws IllegalArgumentException if path is null
*/
public static Pattern path(Path path) {
if (path == null) {
throw new IllegalArgumentException("path cannot be null");
}
return new PathPattern(path);
}
/**
* Construct a new pattern which matches a path element of a given name
* @param name
* @return A pattern which matches a path element with name name
* @throws IllegalArgumentException if name is null
*/
public static Pattern name(Name name) {
if (name == null) {
throw new IllegalArgumentException("name cannot be null");
}
return new NamePattern(name);
}
/**
* Constructs a pattern which matches a path elements against regular expressions.
* @param namespaceUri A regular expression used for matching the name space URI of
* a path element.
* @param localName A regular expression used for matching the local name of a path
* element
* @return A pattern which matches a path element if namespaceUri matches the
* name space URI of the path element and localName matches the local name of the
* path element.
* @throws IllegalArgumentException if either namespaceUri or
* localName is null
*
* @see java.util.regex.Pattern
*/
public static Pattern name(String namespaceUri, String localName) {
if (namespaceUri == null || localName == null) {
throw new IllegalArgumentException("neither namespaceUri nor localName can be null");
}
return new RegexPattern(namespaceUri, localName);
}
private static final Pattern ALL_PATTERN = new Pattern() {
protected Context match(Context input) {
return input.matchToEnd();
}
public String toString() {
return "[ALL]";
}
};
/**
* A pattern which matches all input.
* @return
*/
public static Pattern all() {
return ALL_PATTERN;
}
private static final Pattern NOTHING_PATTERN = new Pattern() {
protected Context match(Context input) {
return input.match(0);
}
public String toString() {
return "[NOTHING]";
}
};
/**
* A pattern which matches nothing.
* @return
*/
public static Pattern nothing() {
return NOTHING_PATTERN;
}
/**
* A pattern which matches pattern1 followed by pattern2 and
* returns the longer of the two matches.
* @param pattern1
* @param pattern2
* @return
* @throws IllegalArgumentException if either argument is null
*/
public static Pattern selection(Pattern pattern1, Pattern pattern2) {
if (pattern1 == null || pattern2 == null) {
throw new IllegalArgumentException("Neither pattern can be null");
}
return new SelectPattern(pattern1, pattern2);
}
/**
* A pattern which matches pattern1 followed by pattern2.
* @param pattern1
* @param pattern2
* @return
*/
public static Pattern sequence(Pattern pattern1, Pattern pattern2) {
if (pattern1 == null || pattern2 == null) {
throw new IllegalArgumentException("Neither pattern can be null");
}
return new SequencePattern(pattern1, pattern2);
}
/**
* A pattern which matches pattern as many times as possible
* @param pattern
* @return
*/
public static Pattern repeat(Pattern pattern) {
if (pattern == null) {
throw new IllegalArgumentException("Pattern can not be null");
}
return new RepeatPattern(pattern);
}
/**
* A pattern which matches pattern as many times as possible
* but at least min times and at most max times.
* @param pattern
* @param min
* @param max
* @return
*/
public static Pattern repeat(Pattern pattern, int min, int max) {
if (pattern == null) {
throw new IllegalArgumentException("Pattern can not be null");
}
return new RepeatPattern(pattern, min, max);
}
// -----------------------------------------------------< Context >---
private static class Context {
private final Path path;
private final int length;
private final int pos;
private final boolean isMatch;
public Context(Path path) {
super();
this.path = path;
length = path.getLength();
isMatch = false;
pos = 0;
}
public Context(Context context, int pos, boolean matched) {
path = context.path;
length = context.length;
this.pos = pos;
this.isMatch = matched;
if (pos > length) {
throw new IllegalArgumentException("Cannot match beyond end of input");
}
}
public Context matchToEnd() {
return new Context(this, length, true);
}
public Context match(int count) {
return new Context(this, pos + count, true);
}
public Context noMatch() {
return new Context(this, this.pos, false);
}
public boolean isMatch() {
return isMatch;
}
public Path getRemainder() throws RepositoryException {
if (pos >= length) {
return null;
}
else {
return path.subPath(pos, length);
}
}
public boolean isExhausted() {
return pos == length;
}
public MatchResult getMatchResult() {
return new MatchResult(path, isMatch? pos : 0);
}
public String toString() {
return pos + " @ " + path;
}
}
// -----------------------------------------------------< SelectPattern >---
private static class SelectPattern extends Pattern {
private final Pattern pattern1;
private final Pattern pattern2;
public SelectPattern(Pattern pattern1, Pattern pattern2) {
super();
this.pattern1 = pattern1;
this.pattern2 = pattern2;
}
protected Context match(Context input) throws RepositoryException {
Context remainder1 = pattern1.match(input);
Context remainder2 = pattern2.match(input);
return remainder1.pos > remainder2.pos ?
remainder1 : remainder2;
}
public String toString() {
return new StringBuffer()
.append("(")
.append(pattern1)
.append("|")
.append(pattern2)
.append(")")
.toString();
}
}
// -----------------------------------------------------< SequencePattern >---
private static class SequencePattern extends Pattern {
private final Pattern pattern1;
private final Pattern pattern2;
public SequencePattern(Pattern pattern1, Pattern pattern2) {
super();
this.pattern1 = pattern1;
this.pattern2 = pattern2;
}
protected Context match(Context input) throws RepositoryException {
Context context1 = pattern1.match(input);
if (context1.isMatch()) {
return pattern2.match(context1);
}
else {
return input.noMatch();
}
}
public String toString() {
return new StringBuffer()
.append("(")
.append(pattern1)
.append(", ")
.append(pattern2)
.append(")")
.toString();
}
}
// -----------------------------------------------------< RepeatPattern >---
private static class RepeatPattern extends Pattern {
private final Pattern pattern;
private final int min;
private final int max;
private boolean hasBounds;
public RepeatPattern(Pattern pattern) {
this(pattern, 0, 0);
this.hasBounds = false;
}
public RepeatPattern(Pattern pattern, int min, int max) {
super();
this.pattern = pattern;
this.min = min;
this.max = max;
this.hasBounds = true;
}
protected Context match(Context input) throws RepositoryException {
Context nextInput;
Context output = input.match(0);
int matchCount = -1;
do {
nextInput = output;
output = pattern.match(nextInput);
matchCount++;
} while (output.isMatch() && (output.pos > nextInput.pos));
if (!hasBounds() || (min <= matchCount && matchCount <= max)) {
return nextInput;
}
else {
return input.noMatch();
}
}
private boolean hasBounds() {
return hasBounds;
}
public String toString() {
return new StringBuffer()
.append("(")
.append(pattern)
.append(")*")
.toString();
}
}
// -----------------------------------------------------< PathPattern >---
private static class PathPattern extends Pattern {
private final Path path;
private final Element[] patternElements;
public PathPattern(Path path) {
super();
this.path = path;
patternElements = path.getElements();
}
protected Context match(Context input) throws RepositoryException {
if (input.isExhausted()) {
return input;
}
Path inputPath = input.getRemainder();
if (!inputPath.isNormalized()) {
throw new IllegalArgumentException("Not normalized");
}
Element[] inputElements = inputPath.getElements();
int inputLength = inputElements.length;
int patternLength = patternElements.length;
if (patternLength > inputLength) {
return input.noMatch();
}
for (int k = 0; k < patternLength; k++) {
if (!patternElements[k].equals(inputElements[k])) {
return input.noMatch();
}
}
return input.match(patternLength);
}
public String toString() {
return new StringBuffer()
.append("\"")
.append(path)
.append("\"")
.toString();
}
}
// -----------------------------------------------------< AbstractNamePattern >---
private static abstract class AbstractNamePattern extends Pattern {
protected abstract boolean matches(Element element);
protected Context match(Context input) throws RepositoryException {
if (input.isExhausted()) {
return input.noMatch();
}
Path inputPath = input.getRemainder();
if (!inputPath.isNormalized()) {
throw new IllegalArgumentException("Not normalized");
}
Element[] inputElements = inputPath.getElements();
if (inputElements.length < 1 || !matches(inputElements[0])) {
return input.noMatch();
}
return input.match(1);
}
}
// -----------------------------------------------------< NameNamePattern >---
private static class NamePattern extends AbstractNamePattern {
private final Name name;
public NamePattern(Name name) {
super();
this.name = name;
}
protected boolean matches(Element element) {
return name.equals(element.getName());
}
public String toString() {
return new StringBuffer()
.append("\"")
.append(name)
.append("\"")
.toString();
}
}
// -----------------------------------------------------< StringNamePattern >---
private static class RegexPattern extends AbstractNamePattern {
private final java.util.regex.Pattern namespaceUri;
private final java.util.regex.Pattern localName;
private final String localNameStr;
private final String namespaceUriStr;
public RegexPattern(String namespaceUri, String localName) {
super();
this.namespaceUri = java.util.regex.Pattern.compile(namespaceUri);
this.localName = java.util.regex.Pattern.compile(localName);
this.namespaceUriStr = namespaceUri;
this.localNameStr = localName;
}
protected boolean matches(Element element) {
Name name = element.getName();
boolean nsMatches = namespaceUri.matcher(name.getNamespaceURI()).matches();
boolean localMatches = localName.matcher(name.getLocalName()).matches();
return nsMatches && localMatches;
}
public String toString() {
return new StringBuffer()
.append("\"{")
.append(namespaceUriStr)
.append("}")
.append(localNameStr)
.append("\"")
.toString();
}
}
}