001 /**
002 *
003 * Copyright 2004 Protique Ltd
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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 **/
018 package org.activemq.filter;
019
020 import java.util.ArrayList;
021 import java.util.HashMap;
022 import java.util.HashSet;
023 import java.util.List;
024 import java.util.Map;
025 import java.util.Set;
026
027 /**
028 * An implementation class used to implement {@link DestinationMap}
029 *
030 * @version $Revision: 1.1.1.1 $
031 */
032 public class DestinationMapNode {
033 // we synchornize at the DestinationMap level
034 private List values = new ArrayList();
035 private Map childNodes = new HashMap();
036 private DestinationMapNode anyChild;
037 protected static final String ANY_CHILD = DestinationMap.ANY_CHILD;
038 protected static final String ANY_DESCENDENT = DestinationMap.ANY_DESCENDENT;
039
040
041 /**
042 * Returns the child node for the given named path or null if it does not exist
043 */
044 public DestinationMapNode getChild(String path) {
045 return (DestinationMapNode) childNodes.get(path);
046 }
047
048 /**
049 * Returns the child node for the given named path, lazily creating one if it does
050 * not yet exist
051 */
052 public DestinationMapNode getChildOrCreate(String path) {
053 DestinationMapNode answer = (DestinationMapNode) childNodes.get(path);
054 if (answer == null) {
055 answer = createChildNode();
056 childNodes.put(path, answer);
057 }
058 return answer;
059 }
060
061 /**
062 * Returns the node which represents all children (i.e. the * node)
063 */
064 public DestinationMapNode getAnyChildNode() {
065 if (anyChild == null) {
066 anyChild = createChildNode();
067 }
068 return anyChild;
069 }
070
071 /**
072 * Returns a mutable List of the values available at this node in the tree
073 */
074 public List getValues() {
075 return values;
076 }
077
078 /**
079 * Returns a list of all the values from this node down the tree
080 */
081 public Set getDesendentValues() {
082 Set answer = new HashSet();
083 appendDescendantValues(answer);
084 return answer;
085 }
086
087 public void add(String[] paths, int idx, Object value) {
088 if (idx >= paths.length) {
089 values.add(value);
090 }
091 else {
092 if (idx == paths.length - 1) {
093 getAnyChildNode().getValues().add(value);
094 }
095 else {
096 getAnyChildNode().add(paths, idx + 1, value);
097 }
098 getChildOrCreate(paths[idx]).add(paths, idx + 1, value);
099 }
100 }
101
102 public void remove(String[] paths, int idx, Object value) {
103 if (idx >= paths.length) {
104 values.remove(value);
105 }
106 else {
107 if (idx == paths.length - 1) {
108 getAnyChildNode().getValues().remove(value);
109 }
110 else {
111 getAnyChildNode().remove(paths, idx + 1, value);
112 }
113 getChildOrCreate(paths[idx]).remove(paths, ++idx, value);
114 }
115 }
116
117 public void removeAll(String[] paths, int idx) {
118 if (idx >= paths.length) {
119 values.clear();
120 }
121 else {
122 if (idx == paths.length - 1) {
123 getAnyChildNode().getValues().clear();
124 }
125 else {
126 getAnyChildNode().removeAll(paths, idx + 1);
127 }
128 getChildOrCreate(paths[idx]).removeAll(paths, ++idx);
129 }
130 }
131
132 protected void appendDescendantValues(Set answer) {
133 answer.addAll(values);
134 if (anyChild != null) {
135 anyChild.appendDescendantValues(answer);
136 }
137 }
138
139 /**
140 * Factory method to create a child node
141 */
142 protected DestinationMapNode createChildNode() {
143 return new DestinationMapNode();
144 }
145
146 public void appendMatchingWildcards(Set answer, String[] paths, int idx) {
147 DestinationMapNode wildCardNode = getChild(ANY_CHILD);
148 if (wildCardNode != null) {
149 wildCardNode.appendMatchingValues(answer, paths, idx + 1);
150 }
151 wildCardNode = getChild(ANY_DESCENDENT);
152 if (wildCardNode != null) {
153 answer.addAll(wildCardNode.getDesendentValues());
154 }
155 }
156
157 public void appendMatchingValues(Set answer, String[] paths, int startIndex) {
158 DestinationMapNode node = this;
159 for (int i = startIndex, size = paths.length; i < size && node != null; i++) {
160 String path = paths[i];
161 if (path.equals(ANY_DESCENDENT)) {
162 answer.addAll(node.getDesendentValues());
163 break;
164 }
165
166 node.appendMatchingWildcards(answer, paths, i);
167 if (path.equals(ANY_CHILD)) {
168 node = node.getAnyChildNode();
169 }
170 else {
171 node = node.getChild(path);
172 }
173 }
174 if (node != null) {
175 answer.addAll(node.getValues());
176 }
177 }
178
179 }