package com.walker.web.agent.impl;
import com.walker.web.agent.Capabilities;
public class Rule {
// The properties of the matching pattern
private final Literal myPrefix;
private final Literal[] mySuffixes;
private final Literal myPostfix;
// The size of the pattern
private final int mySize;
// The browser properties
private final Capabilities myCapabilities;
/**
* Creates a new rule.
* @param prefix The prefix of the matching pattern, potentially null
* @param suffixes The required substrings separated by wildcards, potentially null
to indicate no
* wildcards
* @param postfix The postfix of the matching pattern, potentially null
* @param pattern The original string representation of the matching pattern
* @param capabilities The browser properties for this rule
*/
Rule(final Literal prefix, final Literal[] suffixes, final Literal postfix, final String pattern,
final Capabilities capabilities) {
myPrefix = prefix;
mySuffixes = suffixes;
myPostfix = postfix;
myCapabilities = capabilities;
mySize = pattern.length();
}
/**
* Return the prefix.
* @return the prefix, possibly null
*/
Literal getPrefix() {
return myPrefix;
}
/**
* The required substrings separated by wildcards, potentially null
to indicate no wildcards
* @return The required substrings.
*/
Literal[] getSuffixes() {
return mySuffixes;
}
/**
* Return the postfix.
* @return the postfix, possibly null
*/
Literal getPostfix() {
return myPostfix;
}
/**
* Tests whether this rule needs a specific string in the useragent to match.
* @return true
if this rule can't match without the specific substring, false otherwise.
*/
boolean requires(final String value) {
if (requires(myPrefix, value) || requires(myPostfix, value)) {
return true;
}
if (mySuffixes == null) {
return false;
}
for (final Literal suffix : mySuffixes) {
if (requires(suffix, value)) {
return true;
}
}
return false;
}
private static boolean requires(final Literal literal, final String value) {
return literal != null && literal.requires(value);
}
Capabilities getCapabilities() {
return myCapabilities;
}
int getSize() {
return mySize;
}
final boolean matches(final SearchableString value) {
// Inclusive
final int start;
if (myPrefix == null) {
start = 0;
} else if (value.startsWith(myPrefix)) {
start = myPrefix.getLength();
} else {
return false;
}
// Inclusive
final int end;
if (myPostfix == null) {
end = value.getSize() - 1;
} else if (value.endsWith(myPostfix)) {
end = value.getSize() - 1 - myPostfix.getLength();
} else {
return false;
}
return checkWildCards(value, mySuffixes, start, end);
}
// Static for inline (2x)
static boolean checkWildCards(final SearchableString value, final Literal[] suffixes, final int start,
final int end) {
if (suffixes == null) {
// No wildcards
return start == end + 1;
}
// One wildcard
if (suffixes.length == 0) {
return start <= end + 1;
}
int from = start;
for (final Literal suffix : suffixes) {
final int match = checkWildCard(value, suffix, from);
if (match == -1) {
return false;
}
from = suffix.getLength() + match;
if (from > end + 1) {
return false;
}
}
return true;
}
// Return found index or -1
private static int checkWildCard(final SearchableString value, final Literal suffix, final int start) {
for (final int index : value.getIndices(suffix)) {
if (index >= start) {
return index;
}
}
return -1;
}
/**
* Returns the reconstructed original pattern.
* @return the reconstructed original pattern
*/
String getPattern() {
final StringBuilder result = new StringBuilder();
if (myPrefix != null) {
result.append(myPrefix);
}
if (mySuffixes != null) {
result.append("*");
for (final Literal sub : mySuffixes) {
result.append(sub);
result.append("*");
}
}
if (myPostfix != null) {
result.append(myPostfix);
}
return result.toString();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return getPattern() + " : " + myCapabilities;
}
}