/** * Get node number (level="multiple"). Return a vector giving the hierarchic position of this * node. See the XSLT spec for details. * * @exception XPathException * @param node The node to be numbered * @param count Pattern that identifies which nodes (ancestors and their previous siblings) should * be counted. Default (null) is the element name if the current node is an element, or * "node()" otherwise. * @param from Pattern that specifies where counting starts from. Default (null) is the root node. * Only nodes below the first (most recent) node that matches the 'from' pattern are counted. * @param controller The controller for the transformation * @return a vector containing for each ancestor-or-self that matches the count pattern and that * is below the nearest node that matches the from pattern, an Integer which is one greater * than the number of previous siblings that match the count pattern. */ public static List getNumberMulti( NodeInfo node, Pattern count, Pattern from, Controller controller) throws XPathException { // checkNumberable(node); ArrayList v = new ArrayList(); if (count == null) { if (node.getFingerprint() == -1) { // unnamed node count = NodeKindTest.makeNodeKindTest(node.getNodeKind()); } else { count = new NameTest(node); } } NodeInfo curr = node; while (true) { if (count.matches(curr, controller)) { int num = getNumberSingle(curr, count, null, controller); v.add(0, new Long(num)); } curr = curr.getParent(); if (curr == null) break; if (from != null && from.matches(curr, controller)) break; } return v; }
/** * Tests that both RE2's and JDK's pattern class act as we expect them. The regular expression * {@code regexp} matches the string {@code match} and doesn't match {@code nonMatch} */ public void testMatches(String regexp, String match, String nonMatch) { String errorString = "Pattern with regexp: " + regexp; assertTrue( "JDK " + errorString + " doesn't match: " + match, java.util.regex.Pattern.matches(regexp, match)); assertFalse( "JDK " + errorString + " matches: " + nonMatch, java.util.regex.Pattern.matches(regexp, nonMatch)); assertTrue( errorString + " doesn't match: " + match, Pattern.matches(regexp, utf8Slice(match), options)); assertFalse( errorString + " matches: " + nonMatch, Pattern.matches(regexp, utf8Slice(nonMatch), options)); }
private void scanDir(File dir, List<Pattern> includes) { if (!dir.canRead()) return; // See if patterns are specific enough to avoid scanning every file in the directory. boolean scanAll = false; for (Pattern include : includes) { if (include.value.indexOf('*') != -1 || include.value.indexOf('?') != -1) { scanAll = true; break; } } if (!scanAll) { // If not scanning all the files, we know exactly which ones to include. List matchingIncludes = new ArrayList(1); for (Pattern include : includes) { if (matchingIncludes.isEmpty()) matchingIncludes.add(include); else matchingIncludes.set(0, include); process(dir, include.value, matchingIncludes); } } else { // Scan every file. for (String fileName : dir.list()) { // Get all include patterns that match. List<Pattern> matchingIncludes = new ArrayList(includes.size()); for (Pattern include : includes) if (include.matches(fileName)) matchingIncludes.add(include); if (matchingIncludes.isEmpty()) continue; process(dir, fileName, matchingIncludes); } } }
/** * Matches. * * @param src the src * @return true, if successful */ public boolean matches(String src) { if (pattern == null) { pattern = new Pattern(url); } return pattern.matches(src); }
/** * Get node number (level="single"). If the current node matches the supplied pattern, the * returned number is one plus the number of previous siblings that match the pattern. Otherwise, * return the element number of the nearest ancestor that matches the supplied pattern. * * @param node the current node, the one whose node number is required * @param count Pattern that identifies which nodes should be counted. Default (null) is the * element name if the current node is an element, or "node()" otherwise. * @param from Pattern that specifies where counting starts from. Default (null) is the root node. * (This parameter does not seem useful but is included for the sake of XSLT conformance.) * @param controller the controller of the transformation, used if the patterns reference context * values (e.g. variables) * @exception XPathException when any error occurs in processing * @return the node number established as follows: go to the nearest ancestor-or-self that matches * the 'count' pattern and that is a descendant of the nearest ancestor that matches the * 'from' pattern. Return one plus the nunber of preceding siblings of that ancestor that * match the 'count' pattern. If there is no such ancestor, return 0. */ public static int getNumberSingle( NodeInfo node, Pattern count, Pattern from, Controller controller) throws XPathException { // checkNumberable(node); if (count == null && from == null) { return getNumberSimple(node, controller); } boolean knownToMatch = false; if (count == null) { if (node.getFingerprint() == -1) { // unnamed node count = NodeKindTest.makeNodeKindTest(node.getNodeKind()); } else { count = new NameTest(node); } knownToMatch = true; } NodeInfo target = node; while (!(knownToMatch || count.matches(target, controller))) { target = target.getParent(); if (target == null) { return 0; } if (from != null && from.matches(target, controller)) { return 0; } } // we've found the ancestor to count from SequenceIterator preceding = target.iterateAxis(Axis.PRECEDING_SIBLING, count.getNodeTest()); // pass the filter condition down to the axis enumeration where possible boolean alreadyChecked = (count instanceof NodeTest); int i = 1; while (true) { NodeInfo p = (NodeInfo) preceding.next(); if (p == null) { return i; } if (alreadyChecked || count.matches(p, controller)) { i++; } } }
public GlobScanner( File rootDir, List<String> includes, List<String> excludes, boolean ignoreCase) { if (rootDir == null) throw new IllegalArgumentException("rootDir cannot be null."); if (!rootDir.exists()) throw new IllegalArgumentException("Directory does not exist: " + rootDir); if (!rootDir.isDirectory()) throw new IllegalArgumentException("File must be a directory: " + rootDir); try { rootDir = rootDir.getCanonicalFile(); } catch (IOException ex) { throw new RuntimeException("OS error determining canonical path: " + rootDir, ex); } this.rootDir = rootDir; if (includes == null) throw new IllegalArgumentException("includes cannot be null."); if (excludes == null) throw new IllegalArgumentException("excludes cannot be null."); if (includes.isEmpty()) includes.add("**"); List<Pattern> includePatterns = new ArrayList(includes.size()); for (String include : includes) includePatterns.add(new Pattern(include, ignoreCase)); List<Pattern> allExcludePatterns = new ArrayList(excludes.size()); for (String exclude : excludes) allExcludePatterns.add(new Pattern(exclude, ignoreCase)); scanDir(rootDir, includePatterns); if (!allExcludePatterns.isEmpty()) { // For each file, see if any exclude patterns match. outerLoop: // for (Iterator matchIter = matches.iterator(); matchIter.hasNext(); ) { String filePath = (String) matchIter.next(); List<Pattern> excludePatterns = new ArrayList(allExcludePatterns); try { // Shortcut for excludes that are "**/XXX", just check file name. for (Iterator excludeIter = excludePatterns.iterator(); excludeIter.hasNext(); ) { Pattern exclude = (Pattern) excludeIter.next(); if (exclude.values.length == 2 && exclude.values[0].equals("**")) { exclude.incr(); String fileName = filePath.substring(filePath.lastIndexOf(File.separatorChar) + 1); if (exclude.matches(fileName)) { matchIter.remove(); continue outerLoop; } excludeIter.remove(); } } // Get the file names after the root dir. String[] fileNames = filePath.split("\\" + File.separator); for (String fileName : fileNames) { for (Iterator excludeIter = excludePatterns.iterator(); excludeIter.hasNext(); ) { Pattern exclude = (Pattern) excludeIter.next(); if (!exclude.matches(fileName)) { excludeIter.remove(); continue; } exclude.incr(fileName); if (exclude.wasFinalMatch()) { // Exclude pattern matched. matchIter.remove(); continue outerLoop; } } // Stop processing the file if none of the exclude patterns matched. if (excludePatterns.isEmpty()) continue outerLoop; } } finally { for (Pattern exclude : allExcludePatterns) exclude.reset(); } } } }
/** * This takes a regex and it's compile time flags, a string that is expected to match the regex * and a string that is not expected to match the regex. * * <p>We don't check for JDK compatibility here, since the flags are not in a 1-1 correspondence. */ public void testMatchesRE2(String regexp, int flags, String match, String nonMatch) { Pattern p = Pattern.compile(regexp, flags, options); String errorString = "Pattern with regexp: " + regexp + " and flags: " + flags; assertTrue(errorString + " doesn't match: " + match, p.matches(utf8Slice(match))); assertFalse(errorString + " matches: " + nonMatch, p.matches(utf8Slice(nonMatch))); }
/** * Get node number (level="any"). Return one plus the number of previous nodes in the document * that match the supplied pattern * * @exception XPathException * @param inst Identifies the xsl:number instruction; this is relevant when the function is * memoised to support repeated use of the same instruction to number modulple nodes * @param node Identifies the xsl:number instruction; this is relevant when the function is * memoised to support repeated use of the same instruction to number modulple nodes * @param count Pattern that identifies which nodes should be counted. Default (null) is the * element name if the current node is an element, or "node()" otherwise. * @param from Pattern that specifies where counting starts from. Default (null) is the root node. * Only nodes after the first (most recent) node that matches the 'from' pattern are counted. * @param controller The controller * @param hasVariablesInPatterns if the count or from patterns contain variables, then it's not * safe to get the answer by adding one to the number of the most recent node that matches * @return one plus the number of nodes that precede the current node, that match the count * pattern, and that follow the first node that matches the from pattern if specified. */ public static int getNumberAny( Instruction inst, NodeInfo node, Pattern count, Pattern from, Controller controller, boolean hasVariablesInPatterns) throws XPathException { NodeInfo memoNode = null; int memoNumber = 0; boolean memoise = (!hasVariablesInPatterns && count != null); if (memoise) { Object[] memo = (Object[]) controller.getUserData(inst, "xsl:number"); if (memo != null) { memoNode = (NodeInfo) memo[0]; memoNumber = ((Integer) memo[1]).intValue(); } } int num = 0; if (count == null) { if (node.getFingerprint() == -1) { // unnamed node count = NodeKindTest.makeNodeKindTest(node.getNodeKind()); } else { count = new NameTest(node); } num = 1; } else if (count.matches(node, controller)) { num = 1; } // We use a special axis invented for the purpose: the union of the preceding and // ancestor axes, but in reverse document order // Pass part of the filtering down to the axis iterator if possible NodeTest filter; if (from == null) { filter = count.getNodeTest(); } else if (from.getNodeKind() == Type.ELEMENT && count.getNodeKind() == Type.ELEMENT) { filter = NodeKindTest.ELEMENT; } else { filter = AnyNodeTest.getInstance(); } SequenceIterator preceding = node.iterateAxis(Axis.PRECEDING_OR_ANCESTOR, filter); while (true) { NodeInfo prev = (NodeInfo) preceding.next(); if (prev == null) { break; } if (from != null && from.matches(prev, controller)) { return num; } if (count.matches(prev, controller)) { if (num == 1 && memoNode != null && prev.isSameNode(memoNode)) { num = memoNumber + 1; break; } num++; } } if (memoise) { Object[] memo = new Object[2]; memo[0] = node; memo[1] = new Integer(num); controller.setUserData(inst, "xsl:number", memo); } return num; }
private static int evaluateForPattern(State state, int patternSize) { int size = State.BORAD_SIZE; int value = 0; int i, j; Pattern pattern1 = new Pattern(patternSize); Pattern pattern2 = new Pattern(patternSize); for (i = 0; i < size; i++) { pattern1.reset(); pattern2.reset(); for (j = 0; j < patternSize; j++) { pattern1.put(state.board[j][i]); pattern2.put(state.board[i][j]); } j--; do { // System.out.println("i:" + i + " j:" + j); value += pattern1.matches(); value += pattern2.matches(); j++; if (j == size) break; // pattern1 -= state.board[j - patternSize][i]; pattern1.put(state.board[j][i]); // pattern1 += state.board[j][i]; // pattern2 -= state.board[i][j - patternSize]; pattern2.put(state.board[i][j]); // pattern2 += state.board[i][j]; } while (true); } // (k1-k2: 45 degree, k1-k3 : 135 degree) int k1, k2, k3; for (i = -(size - patternSize); i <= size - patternSize; i++) { if (i < 0) { k1 = -i; k2 = 0; k3 = size - 1; } else { k1 = 0; k2 = i; k3 = size - i - 1; } pattern1.reset(); pattern2.reset(); for (j = 0; j < patternSize; j++) { pattern1.put(state.board[k1 + j][k2 + j]); pattern2.put(state.board[k1 + j][k3 - j]); } j--; do { value += pattern1.matches(); value += pattern2.matches(); j++; // 2 patterns are symmetric, so detection for 1 is enough if (k1 + j == size || k2 + j == size) break; // pattern1 -= state.board[k1 + j - patternSize][k2 + j - patternSize]; pattern1.put(state.board[k1 + j][k2 + j]); // pattern1 += state.board[k1 + j][k2 + j]; // pattern2 -= state.board[k1 + j - patternSize][k3 - j + patternSize]; pattern2.put(state.board[k1 + j][k3 - j]); // pattern2 += state.board[k1 + j][k3 - j]; } while (true); } return value; }