001: /*
002: * @(#)DefaultRuleSet.java 1.2 04/12/06
003: *
004: * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.xml;
010:
011: import java.util.*;
012:
013: class DefaultRuleSet implements RuleSet {
014: private static Comparator patternNodeComparator = new PatternNodeComparator();
015:
016: private PatternNode rootNode = new PatternNode();
017: private PatternNode reverseNodes = new PatternNode();
018: private int count = 0;
019:
020: /*
021: * Registers a rule that does not start with "//"
022: */
023: private void addForwardPattern(String pattern, RuleTarget value) {
024: PatternNode node = rootNode;
025: int pos = 1;
026: while (true) {
027: int idx = pattern.indexOf('/', pos);
028: if (idx < 0) {
029: break;
030: }
031: String s = pattern.substring(pos, idx);
032: if (s.equals("*")) {
033: node.wildcardNode = new PatternNode();
034: } else if (!node.containsKey(s)) {
035: node.put(s, node = new PatternNode());
036: } else {
037: node = (PatternNode) node.get(s);
038: }
039: pos = idx + 1;
040: }
041: String s = pattern.substring(pos);
042: if (s.equals("*")) {
043: node.wildcardNode = node = new PatternNode();
044: } else if (!node.containsKey(s)) {
045: node.put(s, node = new PatternNode());
046: } else {
047: node = (PatternNode) node.get(s);
048: }
049: node.value = value;
050: node.id = ++count;
051: }
052:
053: /*
054: * Registers a rule that starts with "//"
055: */
056: private void addReversePattern(String pattern, RuleTarget value) {
057: ArrayList list = new ArrayList();
058: int pos = 2;
059: while (true) {
060: int idx = pattern.indexOf('/', pos);
061: if (idx < 0) {
062: break;
063: }
064: list.add(pattern.substring(pos, idx));
065: pos = idx + 1;
066: }
067: list.add(pattern.substring(pos));
068: Collections.reverse(list);
069:
070: PatternNode node = reverseNodes;
071: for (Iterator it = list.iterator(); it.hasNext();) {
072: String s = (String) it.next();
073: if (s.equals("*")) {
074: node.wildcardNode = node = new PatternNode();
075: } else if (!node.containsKey(s)) {
076: node.put(s, node = new PatternNode());
077: } else {
078: node = (PatternNode) node.get(s);
079: }
080: }
081: if (node != null) {
082: node.value = value;
083: node.id = ++count;
084: }
085: }
086:
087: /**
088: * Adds a rule
089: *
090: * @param pattern a pattern of a path
091: * @param value the target value
092: */
093: public void add(String pattern, DigestAction action, String keyword) {
094: RuleTarget value = new RuleTarget(action, keyword);
095: if (pattern.startsWith("//")) {
096: addReversePattern(pattern, value);
097: } else {
098: addForwardPattern(pattern, value);
099: }
100: }
101:
102: private void searchPattern(PatternNode nodes, List paths, int idx,
103: int endIndex, boolean forward, Set list) {
104: PatternNode n = (PatternNode) nodes.get(paths.get(idx));
105: int last = paths.size();
106: if (n != null) {
107: if (n.id != 0) {
108: list.add(n);
109: }
110: if (idx != endIndex) {
111: searchPattern(n, paths, forward ? idx + 1 : idx - 1,
112: endIndex, forward, list);
113: }
114: }
115: n = nodes.wildcardNode;
116: if (n != null) {
117: if (n.id != 0) {
118: list.add(n);
119: }
120: if (idx != endIndex) {
121: searchPattern(n, paths, forward ? idx + 1 : idx - 1,
122: endIndex, forward, list);
123: }
124: }
125: }
126:
127: /**
128: * Searches an actual path
129: *
130: * @param path the actual path
131: * @return A list of target objects
132: */
133: public void scan(String path, List paths, TargetHandler handler)
134: throws Exception {
135: Set nodeSet = new TreeSet(patternNodeComparator);
136: int pathSize = paths.size();
137: searchPattern(rootNode, paths, 0, pathSize - 1, true, nodeSet);
138: searchPattern(reverseNodes, paths, pathSize - 1, 0, false,
139: nodeSet);
140: for (Iterator it = nodeSet.iterator(); it.hasNext();) {
141: PatternNode node = (PatternNode) it.next();
142: if (node.id > 0) {
143: RuleTarget rule = node.value;
144: handler.handle(rule.action, rule.keyword);
145: }
146: }
147: }
148:
149: static class PatternNode extends HashMap {
150: RuleTarget value;
151: int id;
152: PatternNode wildcardNode;
153: }
154:
155: static class PatternNodeComparator implements Comparator {
156: public int compare(Object o1, Object o2) {
157: PatternNode p1 = (PatternNode) o1;
158: PatternNode p2 = (PatternNode) o2;
159: return p1.id - p2.id;
160: }
161: }
162: }
|