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; } }