View Javadoc

1   /***
2    * 
3    * Copyright 2004 Protique Ltd
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.codehaus.activemq.filter;
19  
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  import java.util.HashSet;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Set;
26  
27  /***
28   * An implementation class used to implement {@link DestinationMap}
29   *
30   * @version $Revision: 1.4 $
31   */
32  public class DestinationMapNode {
33      // we synchornize at the DestinationMap level
34      private List values = new ArrayList();
35      private Map childNodes = new HashMap();
36      private DestinationMapNode anyChild;
37      protected static final String ANY_CHILD = DestinationMap.ANY_CHILD;
38      protected static final String ANY_DESCENDENT = DestinationMap.ANY_DESCENDENT;
39  
40  
41      /***
42       * Returns the child node for the given named path or null if it does not exist
43       */
44      public DestinationMapNode getChild(String path) {
45          return (DestinationMapNode) childNodes.get(path);
46      }
47  
48      /***
49       * Returns the child node for the given named path, lazily creating one if it does
50       * not yet exist
51       */
52      public DestinationMapNode getChildOrCreate(String path) {
53          DestinationMapNode answer = (DestinationMapNode) childNodes.get(path);
54          if (answer == null) {
55              answer = createChildNode();
56              childNodes.put(path, answer);
57          }
58          return answer;
59      }
60  
61      /***
62       * Returns the node which represents all children (i.e. the * node)
63       */
64      public DestinationMapNode getAnyChildNode() {
65          if (anyChild == null) {
66              anyChild = createChildNode();
67          }
68          return anyChild;
69      }
70  
71      /***
72       * Returns a mutable List of the values available at this node in the tree
73       */
74      public List getValues() {
75          return values;
76      }
77  
78      /***
79       * Returns a list of all the values from this node down the tree
80       */
81      public Set getDesendentValues() {
82          Set answer = new HashSet();
83          appendDescendantValues(answer);
84          return answer;
85      }
86  
87      public void add(String[] paths, int idx, Object value) {
88          if (idx >= paths.length) {
89              values.add(value);
90          }
91          else {
92              if (idx == paths.length - 1) {
93                  getAnyChildNode().getValues().add(value);
94              }
95              else {
96                  getAnyChildNode().add(paths, idx + 1, value);
97              }
98              getChildOrCreate(paths[idx]).add(paths, idx + 1, value);
99          }
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     protected void appendDescendantValues(Set answer) {
118         answer.addAll(values);
119         if (anyChild != null) {
120             anyChild.appendDescendantValues(answer);
121         }
122     }
123 
124     /***
125      * Factory method to create a child node
126      */
127     protected DestinationMapNode createChildNode() {
128         return new DestinationMapNode();
129     }
130 
131     public void appendMatchingWildcards(Set answer, String[] paths, int idx) {
132         DestinationMapNode wildCardNode = getChild(ANY_CHILD);
133         if (wildCardNode != null) {
134             wildCardNode.appendMatchingValues(answer, paths, idx + 1);
135         }
136         wildCardNode = getChild(ANY_DESCENDENT);
137         if (wildCardNode != null) {
138             answer.addAll(wildCardNode.getDesendentValues());
139         }
140     }
141 
142     public void appendMatchingValues(Set answer, String[] paths, int startIndex) {
143         DestinationMapNode node = this;
144         for (int i = startIndex, size = paths.length; i < size && node != null; i++) {
145             String path = paths[i];
146             if (path.equals(ANY_DESCENDENT)) {
147                 answer.addAll(node.getDesendentValues());
148                 break;
149             }
150 
151             node.appendMatchingWildcards(answer, paths, i);
152             if (path.equals(ANY_CHILD)) {
153                 node = node.getAnyChildNode();
154             }
155             else {
156                 node = node.getChild(path);
157             }
158         }
159         if (node != null) {
160             answer.addAll(node.getValues());
161         }
162     }
163 }