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.
/*
* BSD 3-Clause License
*
* Copyright (c) 2017, David Tesler
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.github.protobufel.common.files.regex;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import java.util.*;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.github.protobufel.common.verifications.Verifications.*;
/**
* A container of the extended parentPattern support.
*
* @author [email protected] David Tesler
*/
public final class Patterns {
private Patterns() {
}
public static final class ExtendedPattern implements IPatternSupport {
private final List includes;
private final List excludes;
@SuppressWarnings("null")
public ExtendedPattern(final Collection includes, final Collection excludes,
final int flags) {
@NonNull Collection nonNullIncludes = verifyNonNullIterable(includes);
this.includes = Collections.unmodifiableList(new ArrayList(
verifyArgument(!nonNullIncludes.isEmpty(), nonNullIncludes, "includes must be non-empty")));
this.excludes = Collections.unmodifiableList(new ArrayList(verifyNonNullIterable(excludes)));
}
private ExtendedPattern(final Iterable includes, final Iterable excludes,
final int flags) {
this.includes = getCompiledPatterns(includes, flags);
this.excludes = getCompiledPatterns(excludes, flags);
}
private List getCompiledPatterns(final Iterable regexes, final int flags) {
final @NonNull ArrayList patterns = new ArrayList();
for (String regex : regexes) {
patterns.add(Pattern.compile(verifyNonNull(regex), flags));
}
@SuppressWarnings("null")
@NonNull List unmodifiableList = Collections.unmodifiableList(patterns);
return unmodifiableList;
}
public static ExtendedPattern compile(final Iterable includes,
final Iterable excludes) {
return new ExtendedPattern(includes, excludes, 0);
}
public static ExtendedPattern compile(final Iterable includes,
final Iterable excludes, final int flags) {
return new ExtendedPattern(includes, excludes, flags);
}
public static boolean matches(final String regex, final CharSequence input) {
return Pattern.matches(regex, input);
}
public static boolean matches(final Iterable includes,
final Iterable excludes, final CharSequence input) {
return ExtendedPattern.compile(includes, excludes).matcher(input).matches();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((excludes == null) ? 0 : excludes.hashCode());
result = prime * result + ((includes == null) ? 0 : includes.hashCode());
return result;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof ExtendedPattern)) {
return false;
}
ExtendedPattern other = (ExtendedPattern) obj;
if (!excludes.equals(other.excludes)) {
return false;
}
if (!includes.equals(other.includes)) {
return false;
}
return true;
}
@Override
public String toString() {
return "ExtendedPattern [includes=" + includes + ", excludes=" + excludes + "]";
}
public String pattern() {
return "[includes=" + includes + ", excludes=" + excludes + "]";
}
public int excludeFlags(final int index) {
return excludes.get(index).flags();
}
public int includeFlags(final int index) {
return includes.get(index).flags();
}
public int includeCount() {
return includes.size();
}
public int excludeCount() {
return excludes.size();
}
@Override
public ExtendedMatcher matcher(CharSequence input) {
return new ExtendedMatcher(this, input);
}
public String[] split(CharSequence input, int limit) {
return RegexSupport.split(this, input, limit);
}
public String[] split(CharSequence input) {
return RegexSupport.split(this, input, 0);
}
}
public static final class ExtendedMatcher implements MatchResult, IMatcherSupport {
private static final MatchResult EMPTY_MATCH_RESULT = new MatchResult() {
@Override
public int start(int group) {
throw new IllegalStateException("No match available");
}
@Override
public int start() {
throw new IllegalStateException("No match available");
}
@Override
public int groupCount() {
return -1;
}
@Override
public String group(int group) {
throw new IllegalStateException("No match found");
}
@Override
public String group() {
throw new IllegalStateException("No match found");
}
@Override
public int end(int group) {
throw new IllegalStateException("No match available");
}
@Override
public int end() {
throw new IllegalStateException("No match available");
}
};
private final Matcher delegate;
private ExtendedPattern parentPattern;
private CharSequence input;
private int lastAppendPosition = 0;
private int includeIndex;
private MatcherOp lastOp;
private int lastStart;
private ExtendedMatcher(final ExtendedPattern pattern, final CharSequence input) {
this.parentPattern = verifyNonNull(pattern);
this.input = verifyNonNull(input);
@SuppressWarnings("null")
@NonNull Matcher matcher = pattern.includes.get(0).matcher(input);
this.delegate = matcher;
this.includeIndex = -1;
this.lastOp = MatcherOp.NOOP;
lastStart = -1;
}
public int getLastAppendPosition() {
return lastAppendPosition;
}
protected List getIncludes() {
return parentPattern.includes;
}
protected List getExcludes() {
return parentPattern.excludes;
}
@Override
public ExtendedMatcher setLastAppendPosition(int lastAppendPosition) {
this.lastAppendPosition = lastAppendPosition;
return this;
}
@Override
public Matcher getDelegate() {
return delegate;
}
@Override
public CharSequence getInput() {
return input;
}
@Override
public ExtendedPattern pattern() {
return parentPattern;
}
public ExtendedMatcher region(int start, int end) {
delegate.region(start, end);
return this;
}
public int regionStart() {
return delegate.regionStart();
}
public int regionEnd() {
return delegate.regionEnd();
}
public ExtendedMatcher usePattern(final ExtendedPattern pattern) {
@NonNull ExtendedPattern nonNullPattern = verifyArgument(pattern != null, pattern,
"Pattern cannot be null");
this.parentPattern = nonNullPattern;
delegate.usePattern(nonNullPattern.includes.get(0));
return this;
}
@Override
public ExtendedMatcher reset() {
delegate.reset();
includeIndex = -1;
return this;
}
public ExtendedMatcher reset(CharSequence input) {
this.input = input;
includeIndex = -1;
return reset();
}
@SuppressWarnings("null")
public MatchResult toMatchResult() {
return (includeIndex == -1) ? EMPTY_MATCH_RESULT : delegate.toMatchResult();
}
@Override
public int start() {
return delegate.start();
}
@Override
public int start(int group) {
return delegate.start(group);
}
@Override
public int end() {
return delegate.end();
}
@Override
public int end(int group) {
return delegate.end(group);
}
@Override
@SuppressWarnings("null")
public String group() {
return delegate.group();
}
@Override
public @Nullable String group(int group) {
return delegate.group(group);
}
public @Nullable String group(String name) {
return delegate.group(name);
}
@Override
public int groupCount() {
return delegate.groupCount();
}
public boolean matches() {
lastOp = MatcherOp.MATCHES;
lastStart = -1;
int i = -1;
for (Pattern pattern : getExcludes()) {
i++;
if (delegate.usePattern(pattern).matches()) {
includeIndex = -1;
return false;
}
}
i= -1;
for (Pattern pattern : getIncludes()) {
i++;
if (delegate.usePattern(pattern).matches()) {
includeIndex = i;
return true;
}
}
includeIndex = -1;
return false;
}
@Override
public boolean find() {
lastOp = MatcherOp.FIND;
int start;
if (includeIndex == -1) {
start = 0;
} else {
start = (delegate.end() == delegate.start()) ? (delegate.end() + 1) : delegate.end();
}
final int regionStart = delegate.regionStart();
final int regionEnd = delegate.regionEnd();
if (start < regionStart) {
start = regionStart;
}
if (start > regionEnd) {
includeIndex = -1;
lastStart = -1;
return false;
}
lastStart = start;
final Set rejected = new HashSet();
int i = -1;
for (Pattern pattern : getIncludes()) {
i++;
if (delegate.usePattern(pattern).find(start)) {
final Interval matchedInterval = new Interval(delegate.start(), delegate.end());
if (rejected.contains(matchedInterval)) {
continue;
}
if (!matchesExcludes(delegate.start(), delegate.end())) {
includeIndex = i;
return true;
}
rejected.add(matchedInterval);
}
}
includeIndex = -1;
return false;
}
private boolean matchesExcludes(final int start, final int end) {
if (getExcludes().isEmpty()) {
return false;
}
Matcher matcher = null;
for (Pattern pattern : getExcludes()) {
@SuppressWarnings("null")
@NonNull Pattern nonNullPattern = pattern;
if (matcher == null) {
matcher = getNewMatcher(nonNullPattern, start, end);
} else {
matcher.usePattern(nonNullPattern);
}
if (matcher.matches()) {
return true;
}
}
return false;
}
@SuppressWarnings("null")
private Matcher getNewMatcher(final Pattern pattern, final int regionStart, final int regionEnd) {
return pattern.matcher(input)
.region(regionStart, regionEnd)
.useTransparentBounds(delegate.hasTransparentBounds())
.useAnchoringBounds(delegate.hasAnchoringBounds());
}
public boolean find(final int start) {
lastOp = MatcherOp.FIND_AT;
if ((start < 0) || (start > input.length())) {
lastStart = -1;
includeIndex = -1;
throw new IndexOutOfBoundsException("Illegal start index");
}
lastStart = start;
final Set rejected = new HashSet();
int i = -1;
for (Pattern pattern : getIncludes()) {
i++;
if (delegate.usePattern(pattern).find(start)) {
final Interval matchedInterval = new Interval(delegate.start(), delegate.end());
if (rejected.contains(matchedInterval)) {
continue;
}
if (!matchesExcludes(delegate.start(), delegate.end())) {
includeIndex = i;
return true;
}
rejected.add(matchedInterval);
}
}
includeIndex = -1;
return false;
}
public boolean lookingAt() {
lastOp = MatcherOp.LOOKING_AT;
lastStart = -1;
final Set rejected = new HashSet();
int i = -1;
for (Pattern pattern : getIncludes()) {
i++;
if (delegate.usePattern(pattern).lookingAt()) {
if (rejected.contains(delegate.end())) {
continue;
}
if (!matchesExcludes(delegate.start(), delegate.end())) {
includeIndex = i;
return true;
}
rejected.add(delegate.end());
}
}
includeIndex = -1;
return false;
}
public StringBuffer appendTail(StringBuffer sb) {
return RegexSupport.appendTail(input, lastAppendPosition, sb);
}
public ExtendedMatcher appendReplacement(StringBuffer sb, String replacement) {
return RegexSupport.appendReplacement(this, sb, replacement);
}
public String replaceAll(String replacement) {
return RegexSupport.replaceAll(this, replacement);
}
public String replaceFirst(String replacement) {
return RegexSupport.replaceFirst(this, replacement);
}
public boolean hasTransparentBounds() {
return delegate.hasTransparentBounds();
}
public ExtendedMatcher useTransparentBounds(boolean b) {
delegate.useTransparentBounds(b);
return this;
}
public boolean hasAnchoringBounds() {
return delegate.hasAnchoringBounds();
}
public ExtendedMatcher useAnchoringBounds(boolean b) {
delegate.useAnchoringBounds(b);
return this;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ExtendedMatcher [parentPattern=").append(pattern())
.append(", region=").append(regionStart()).append(", ").append(regionEnd())
.append(", lastmatch=").append(includeIndex == -1 ? null : group())
.append("]");
@SuppressWarnings("null")
@NonNull String string = builder.toString();
return string;
}
public boolean hitEnd() {
return delegate.hitEnd();
}
public boolean requireEnd() {
if (includeIndex == -1) {
// requireEnd has no meaning, return false
return false;
}
return delegate.requireEnd();
}
public boolean tryHitEnd() {
if (delegate.hitEnd()) {
return true;
}
Matcher matcher = null;
int skipIndex = (includeIndex == -1) ? (parentPattern.includeCount() - 1) : includeIndex;
int i = -1;
for (Pattern pattern : getIncludes()) {
i++;
if (i == skipIndex) {
continue;
}
@SuppressWarnings("null")
@NonNull Pattern nonNullPattern = pattern;
if (matcher == null) {
matcher = getNewMatcher(nonNullPattern, delegate.regionStart(), delegate.regionEnd());
} else {
matcher.usePattern(nonNullPattern).reset();
}
if (lastOp.apply(matcher, lastStart)) {
if (matcher.requireEnd()) {
return true;
}
}
}
return false;
}
public boolean tryRequireEnd() {
if (includeIndex == -1) {
// requireEnd has no meaning, return false
return false;
}
if (!delegate.requireEnd()) {
return false;
}
Matcher matcher = null;
for (Pattern pattern : getIncludes().subList(includeIndex + 1, getIncludes().size())) {
@SuppressWarnings("null")
@NonNull Pattern nonNullPattern = pattern;
if (matcher == null) {
matcher = getNewMatcher(nonNullPattern, delegate.regionStart(), delegate.regionEnd());
} else {
matcher.usePattern(nonNullPattern).reset();
}
if (lastOp.apply(matcher, lastStart)) {
if (!matchesExcludes(matcher.start(), matcher.end()) && !matcher.requireEnd()) {
return false;
}
}
}
return true;
}
private enum MatcherOp {
NOOP {
@Override
public boolean apply(Matcher matcher, int start) {
throw new UnsupportedOperationException();
}
},
FIND_AT() {
@Override
public boolean apply(final Matcher matcher, final int start) {
return matcher.find(start);
}
},
LOOKING_AT {
@Override
public boolean apply(final Matcher matcher, final int start) {
return matcher.lookingAt();
}
},
FIND { // internally, same as FIND_AT
@Override
public boolean apply(final Matcher matcher, final int start) {
return matcher.find(start);
}
},
MATCHES {
@Override
public boolean apply(final Matcher matcher, final int start) {
return matcher.matches();
}
};
public abstract boolean apply(final Matcher matcher, final int start);
}
}
private static final class Interval implements Comparable{
final int start;
final int end;
public Interval(int start, int end) {
this.start = start;
this.end = end;
}
@SuppressWarnings("unused")
public int getStart() {
return start;
}
@SuppressWarnings("unused")
public int getEnd() {
return end;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + end;
result = prime * result + start;
return result;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Interval)) {
return false;
}
Interval other = (Interval) obj;
if (end != other.end) {
return false;
}
if (start != other.start) {
return false;
}
return true;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Interval [start=").append(start).append(", end=").append(end).append("]");
@SuppressWarnings("null")
@NonNull String str = builder.toString();
return str;
}
@Override
public int compareTo(final @Nullable Interval other) {
if (other == null) {
return 1;
} else if (start < other.start) {
return -1;
} else if (start > other.start) {
return 1;
} else if (end < other.end) {
return -1;
} else if (end > other.end) {
return 1;
} else {
return 0;
}
}
}
}