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 org.codehaus.activemq.message.ActiveMQDestination;
21  
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Set;
26  
27  /***
28   * A Map-like data structure allowing values to be indexed by {@link ActiveMQDestination}
29   * and retrieved by destination - supporting both * and > style of wildcard
30   * as well as composite destinations.
31   * <br>
32   * This class assumes that the index changes rarely but that fast lookup into the index is required.
33   * So this class maintains a pre-calculated index for destination steps. So looking up the values
34   * for "TEST.*" or "*.TEST" will be pretty fast.
35   * <br>
36   * Looking up of a value could return a single value or a List of matching values if a wildcard or
37   * composite destination is used.
38   *
39   * @version $Revision: 1.5 $
40   */
41  public class DestinationMap {
42      private DestinationMapNode rootNode = new DestinationMapNode();
43      protected static final String ANY_DESCENDENT = DestinationFilter.ANY_DESCENDENT;
44      protected static final String ANY_CHILD = DestinationFilter.ANY_CHILD;
45  
46      /***
47       * Looks up the value(s) matching the given Destination key. For simple destinations
48       * this is typically a List of one single value, for wildcards or composite destinations this will typically be
49       * a List of matching values.
50       *
51       * @param key the destination to lookup
52       * @return a List of matching values or an empty list if there are no matching values.
53       */
54      public synchronized Set get(ActiveMQDestination key) {
55          if (key.isComposite()) {
56              List childDestinations = key.getChildDestinations();
57              Set answer = new HashSet(childDestinations.size());
58              for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
59                  ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
60                  Object value = get(childDestination);
61                  if (value instanceof Set) {
62                      answer.addAll((Set) value);
63                  }
64                  else if (value != null) {
65                      answer.add(value);
66                  }
67                  return answer;
68              }
69          }
70          return findWildcardMatches(key);
71      }
72  
73      public synchronized void put(ActiveMQDestination key, Object value) {
74          if (key.isComposite()) {
75              List childDestinations = key.getChildDestinations();
76              for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
77                  ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
78                  put(childDestination, value);
79              }
80              return;
81          }
82          String[] paths = key.getDestinationPaths();
83          rootNode.add(paths, 0, value);
84      }
85  
86      /***
87       * Removes the value from the associated destination
88       */
89      public synchronized void remove(ActiveMQDestination key, Object value) {
90          if (key.isComposite()) {
91              List childDestinations = key.getChildDestinations();
92              for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
93                  ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
94                  remove(childDestination, value);
95              }
96              return;
97          }
98          String[] paths = key.getDestinationPaths();
99          rootNode.remove(paths, 0, value);
100 
101     }
102 
103     // Implementation methods
104     //-------------------------------------------------------------------------
105     protected Set findWildcardMatches(ActiveMQDestination key) {
106         String[] paths = key.getDestinationPaths();
107         Set answer = new HashSet();
108         rootNode.appendMatchingValues(answer, paths, 0);
109         return answer;
110     }
111 
112 }