001: /*
002: * Copyright © 2002-2005tagtraum industries
003: */
004: package com.tagtraum.jo.util;
005:
006: import com.tagtraum.framework.util.MultiValueMap;
007:
008: import java.util.ArrayList;
009: import java.util.Collections;
010: import java.util.List;
011: import java.util.Iterator;
012:
013: /**
014: *
015: * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
016: * @version 1.1beta1 ($Revision: 1.4 $)
017: */
018: public class URIFilterMapper {
019:
020: private List defaultList;
021: //private MultiValueMap patternMap;
022: private MultiValueMap prefixMatchRules;
023: private MultiValueMap suffixMatchRules;
024: private MultiValueMap exactMatchRules;
025: private List entries;
026:
027: public URIFilterMapper() {
028: // TODO: check concurrency!
029: this .defaultList = new ArrayList();
030: //this.patternMap = new MultiValueMap();
031: this .prefixMatchRules = new MultiValueMap();
032: this .suffixMatchRules = new MultiValueMap();
033: this .exactMatchRules = new MultiValueMap();
034: this .entries = new ArrayList();
035: }
036:
037: private void addDefault(Entry entry) {
038: defaultList.add(entry);
039: }
040:
041: public int rules() {
042: return entries.size();
043: }
044:
045: /**
046: * Returns an iterator over all {@link Entry}s in this mapper.
047: *
048: * @return Iterator over entries
049: */
050: public Iterator iterator() {
051: return entries.iterator();
052: }
053:
054: public Entry get(int index) {
055: return (Entry) entries.get(index);
056: }
057:
058: public void add(String pattern, Object object) {
059: if (pattern == null) {
060: throw new NullPointerException("Pattern cannot be 'null'.");
061: }
062: if (object == null) {
063: throw new NullPointerException("Object cannot be 'null'.");
064: }
065: Entry entry = new Entry(pattern, object);
066: // what is this for?
067: //patternMap.put(pattern, object);
068: entries.add(entry);
069: if (pattern.equals("/")) {
070: addDefault(entry);
071: } else {
072: if (pattern.endsWith("/*")) {
073: prefixMatchRules.put(pattern.substring(0, pattern
074: .length() - 2), entry);
075: } else if (pattern.startsWith("*.")) {
076: suffixMatchRules.put(pattern.substring(2), entry);
077: } else {
078: exactMatchRules.put(pattern, entry);
079: }
080: }
081: }
082:
083: /**
084: * Returns an array of matching objects. The objects are ordered in
085: * the order they were added with their patterns.
086: *
087: * @param uri pattern
088: * @return ordered list of matches.
089: */
090: public List get(String uri) {
091: // first node: Exact match!
092: List matchingEntryList = new ArrayList(exactMatchRules.get(uri));
093: // second node: prefix match!
094: int idx;
095: String uriPart = uri;
096: matchingEntryList.addAll(prefixMatchRules.get(uriPart));
097: // step through it
098: while ((idx = uriPart.lastIndexOf('/')) != -1) {
099: uriPart = uriPart.substring(0, idx);
100: matchingEntryList.addAll(prefixMatchRules.get(uriPart));
101: }
102: // third node: suffix match!
103: idx = uri.lastIndexOf('.');
104: if (idx != -1 && uri.length() > (idx + 1)) {
105: String theSuffix = uri.substring(idx + 1);
106: matchingEntryList.addAll(suffixMatchRules.get(theSuffix));
107: }
108: // fourth node: default match!
109: matchingEntryList.addAll(defaultList);
110: Collections.sort(matchingEntryList);
111: List matchingObjects = new ArrayList(matchingEntryList.size());
112: for (int i = 0, max = matchingEntryList.size(); i < max; i++) {
113: matchingObjects.add(((Entry) matchingEntryList.get(i))
114: .getObject());
115: }
116: return matchingObjects;
117: }
118:
119: public static class Entry implements Comparable {
120: private static int count;
121: private String pattern;
122: private int ord = count++;
123: private Object object;
124:
125: public Entry(String pattern, Object object) {
126: this .object = object;
127: this .pattern = pattern;
128: }
129:
130: public String getPattern() {
131: return pattern;
132: }
133:
134: public Object getObject() {
135: return object;
136: }
137:
138: public int compareTo(Object o) {
139: // TODO: test this!
140: return ord - ((Entry) o).ord;
141: }
142: }
143:
144: }
|