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 &gt; 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 }