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 }