001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.page.document.psml;
018:
019: import java.util.Comparator;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.Map;
023: import java.util.TreeMap;
024: import java.util.regex.Pattern;
025:
026: import org.apache.jetspeed.page.document.Node;
027: import org.apache.jetspeed.page.document.NodeSet;
028:
029: /**
030: * <p>
031: * PageSetImpl
032: * </p>
033: * <p>
034: *
035: * </p>
036: *
037: * @author <a href="mailto:weaver@apache.org">Scott T. Weaver </a>
038: * @version $Id: NodeSetImpl.java 568811 2007-08-23 03:00:37Z woonsan $
039: *
040: */
041: public class NodeSetImpl implements NodeSet {
042: private Map nodes;
043: private Map subsets;
044: private String resolveToPath;
045: private Comparator comparator;
046: protected static final Map patternCache = new HashMap();
047:
048: public NodeSetImpl(String resolveToPath) {
049: this .resolveToPath = resolveToPath;
050: nodes = new TreeMap();
051: subsets = new HashMap();
052: }
053:
054: /**
055: *
056: * @param resolveToPath
057: * @param comparator
058: */
059: public NodeSetImpl(String resolveToPath, Comparator comparator) {
060: this .resolveToPath = resolveToPath;
061: nodes = new TreeMap(comparator);
062: this .comparator = comparator;
063: subsets = new HashMap();
064: }
065:
066: /**
067: *
068: * <p>
069: * get
070: * </p>
071: *
072: * @see org.apache.jetspeed.page.document.NodeSet#get(java.lang.String)
073: * @param name
074: * @return
075: */
076: public Node get(String name) {
077:
078: if (nodes.containsKey(name)) {
079: return (Node) nodes.get(name);
080: } else if (resolveToPath != null) {
081: if (resolveToPath.endsWith(Node.PATH_SEPARATOR)) {
082: return (Node) nodes.get(resolveToPath + name);
083: } else {
084: return (Node) nodes.get(resolveToPath
085: + Node.PATH_SEPARATOR + name);
086: }
087: }
088:
089: return null;
090: }
091:
092: /**
093: *
094: * <p>
095: * add
096: * </p>
097: *
098: * @see org.apache.jetspeed.page.document.NodeSet#add(org.apache.jetspeed.page.document.Node)
099: * @param document
100: */
101: public void add(Node node) {
102: String path = node.getPath();
103: nodes.put(path, node);
104: if (subsets.containsKey(node.getType())) {
105: ((NodeSet) subsets.get(node.getType())).add(node);
106: }
107: }
108:
109: /**
110: * <p>
111: * size
112: * </p>
113: *
114: * @see org.apache.jetspeed.page.document.NodeSet#size()
115: * @return
116: */
117: public int size() {
118: return nodes.size();
119: }
120:
121: /**
122: *
123: * <p>
124: * iterator
125: * </p>
126: *
127: * @see org.apache.jetspeed.page.document.NodeSet#iterator()
128: * @return
129: */
130: public Iterator iterator() {
131: return nodes.values().iterator();
132: }
133:
134: /**
135: * <p>
136: * subset
137: * </p>
138: *
139: * @see org.apache.jetspeed.page.document.NodeSet#subset(java.lang.String)
140: * @param type
141: * @return
142: */
143: public NodeSet subset(String type) {
144: NodeSet subset = (NodeSet) subsets.get(type);
145: if (subset == null) {
146: subset = new NodeSetImpl(resolveToPath, comparator);
147:
148: Iterator nodeItr = nodes.values().iterator();
149: while (nodeItr.hasNext()) {
150: Node node = (Node) nodeItr.next();
151: if (node.getType().equals(type)) {
152: subset.add(node);
153: }
154: }
155:
156: synchronized (subsets) {
157: subsets.put(type, subset);
158: }
159: }
160:
161: return subset;
162: }
163:
164: /**
165: * <p>
166: * exclusiveSubset
167: * </p>
168: *
169: * @see org.apache.jetspeed.page.document.NodeSet#exclusiveSubset(java.lang.String)
170: * @param regex
171: * @return
172: */
173: public NodeSet exclusiveSubset(String regex) {
174: Iterator allNodes = nodes.entrySet().iterator();
175: NodeSetImpl subset = new NodeSetImpl(resolveToPath, comparator);
176: final Pattern pattern = getPattern(regex);
177: while (allNodes.hasNext()) {
178: Map.Entry entry = (Map.Entry) allNodes.next();
179: Node node = (Node) entry.getValue();
180: String key = (String) entry.getKey();
181: if (!matches(pattern, key)
182: && !matches(pattern, node.getName())) {
183: subset.add(node);
184: }
185: }
186:
187: return subset;
188: }
189:
190: /**
191: * <p>
192: * inclusiveSubset
193: * </p>
194: *
195: * @see org.apache.jetspeed.page.document.NodeSet#inclusiveSubset(java.lang.String)
196: * @param regex
197: * @return
198: */
199: public NodeSet inclusiveSubset(String regex) {
200: Iterator allNodes = nodes.entrySet().iterator();
201: NodeSetImpl subset = new NodeSetImpl(resolveToPath, comparator);
202: final Pattern pattern = getPattern(regex);
203: while (allNodes.hasNext()) {
204: Map.Entry entry = (Map.Entry) allNodes.next();
205: String key = (String) entry.getKey();
206: Node node = (Node) entry.getValue();
207: if (matches(pattern, key)
208: || matches(pattern, node.getName())) {
209: subset.add(node);
210: }
211: }
212:
213: return subset;
214: }
215:
216: /**
217: *
218: * <p>
219: * getComparator
220: * </p>
221: *
222: * @return comparator used to order nodes
223: */
224: public Comparator getComparator() {
225: return comparator;
226: }
227:
228: /**
229: *
230: * <p>
231: * matches
232: * </p>
233: *
234: * @param pattern
235: * @param value
236: * @return
237: */
238: protected final boolean matches(Pattern pattern, String value) {
239: return pattern.matcher(value).matches();
240: }
241:
242: /**
243: *
244: * <p>
245: * getPattern
246: * </p>
247: *
248: * @param regex
249: * @return
250: */
251: protected final Pattern getPattern(String regex) {
252: if (patternCache.containsKey(regex)) {
253: return (Pattern) patternCache.get(regex);
254: } else {
255: Pattern pattern = Pattern.compile(regex);
256: patternCache.put(regex, pattern);
257: return pattern;
258: }
259: }
260:
261: /**
262: * <p>
263: * contains
264: * </p>
265: *
266: * @see org.apache.jetspeed.page.document.NodeSet#contains()
267: * @return
268: */
269: public boolean contains(Node node) {
270: return nodes.values().contains(node);
271: }
272:
273: /**
274: * <p>
275: * isEmpty
276: * </p>
277: *
278: * @see org.apache.jetspeed.page.document.NodeSet#isEmpty()
279: * @return
280: */
281: public boolean isEmpty() {
282: return nodes.isEmpty();
283: }
284:
285: /**
286: * <p>
287: * remove
288: * </p>
289: *
290: * @param node to remove
291: * @return removed node
292: */
293: public Node remove(Node node) {
294: String path = node.getPath();
295: if (nodes.get(path) == node) {
296: nodes.remove(path);
297: if (subsets.containsKey(node.getType())) {
298: ((NodeSetImpl) subsets.get(node.getType()))
299: .remove(node);
300: }
301: }
302: return null;
303: }
304: }
|