Package org.activemq.filter

Source Code of org.activemq.filter.DestinationMap

/**
*
* Copyright 2004 Protique Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
package org.activemq.filter;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.activemq.message.ActiveMQDestination;
import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;

/**
* A Map-like data structure allowing values to be indexed by {@link ActiveMQDestination}
* and retrieved by destination - supporting both * and > style of wildcard
* as well as composite destinations.
* <br>
* This class assumes that the index changes rarely but that fast lookup into the index is required.
* So this class maintains a pre-calculated index for destination steps. So looking up the values
* for "TEST.*" or "*.TEST" will be pretty fast.
* <br>
* Looking up of a value could return a single value or a List of matching values if a wildcard or
* composite destination is used.
*
* @version $Revision: 1.1.1.1 $
*/
public class DestinationMap {
    private DestinationMapNode rootNode = new DestinationMapNode();
    private Map vanillaDestinations = new ConcurrentHashMap();
    private boolean containsWildCards = false;
    protected static final String ANY_DESCENDENT = DestinationFilter.ANY_DESCENDENT;
    protected static final String ANY_CHILD = DestinationFilter.ANY_CHILD;
    private Set nullAnswer = new HashSet();

    /**
     * Looks up the value(s) matching the given Destination key. For simple destinations
     * this is typically a List of one single value, for wildcards or composite destinations this will typically be
     * a List of matching values.
     *
     * @param key the destination to lookup
     * @return a List of matching values or an empty list if there are no matching values.
     */
    public synchronized Set get(ActiveMQDestination key) {
        if (key.isComposite()) {
            List childDestinations = key.getChildDestinations();
            Set answer = new HashSet(childDestinations.size());
            for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
                ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
                Object value = get(childDestination);
                if (value instanceof Set) {
                    answer.addAll((Set) value);
                }
                else if (value != null) {
                    answer.add(value);
                }
                return answer;
            }
        }
        return findWildcardMatches(key);
    }

    /**
     * add destination to the map
     * @param key
     * @param value
     */
    public synchronized void put(ActiveMQDestination key, Object value) {
        if (key.isComposite()) {
            List childDestinations = key.getChildDestinations();
            for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
                ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
                put(childDestination, value);
            }
            return;
        }
        String[] paths = key.getDestinationPaths();
        rootNode.add(paths, 0, value);
        if (key.isWildcard()){
            containsWildCards = true;
        }
        addToVanillaDestinations(key, value);
    }

    /**
     * Removes the value from the associated destination
     * @param key
     * @param value
     */
    public synchronized void remove(ActiveMQDestination key, Object value) {
        if (key.isComposite()) {
            List childDestinations = key.getChildDestinations();
            for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
                ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
                remove(childDestination, value);
            }
            return;
        }
        String[] paths = key.getDestinationPaths();
        rootNode.remove(paths, 0, value);
        removeFromVanillaDestinations(key,value);
       

    }

    // Implementation methods
    //-------------------------------------------------------------------------
    protected Set findWildcardMatches(ActiveMQDestination key) {
        Set answer = nullAnswer;
        if (!containsWildCards && !key.isWildcard()){
            answer = getFromVanillaDestinations(key);
        }else {
            answer = new HashSet();
            String[] paths = key.getDestinationPaths();
            rootNode.appendMatchingValues(answer, paths, 0);
        }
        return answer;
    }

    /**
     * remove all destinations associated with a key
     * @param key
     */
    public void removeAll(ActiveMQDestination key) {
        if (key.isComposite()) {
            List childDestinations = key.getChildDestinations();
            for (Iterator iter = childDestinations.iterator(); iter.hasNext();) {
                ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
                removeAll(childDestination);
            }
            return;
        }
        String[] paths = key.getDestinationPaths();
        rootNode.removeAll(paths, 0);
        removeAllFromVanillaDestinations(key);
    }
   
    synchronized private void addToVanillaDestinations(ActiveMQDestination key, Object value) {
        Set set = new HashSet();
        Set oldSet = (Set)vanillaDestinations.get(key);
        if (oldSet != null) {
            set.addAll(oldSet);
        }
        set.add(value);
        vanillaDestinations.put(key,set);
    }
   
    synchronized private void removeFromVanillaDestinations(ActiveMQDestination key,Object value){

        Set oldSet = (Set)vanillaDestinations.get(key);
        if (oldSet != null) {
            Set set = new HashSet(oldSet);
            set.remove(value);
            if (set.isEmpty()){
                vanillaDestinations.remove(key);
            }
            vanillaDestinations.put(key,set);
        }
       
        validateContainsWildCards(key);
    }
   
    private void removeAllFromVanillaDestinations(ActiveMQDestination key){
        vanillaDestinations.remove(key);
        validateContainsWildCards(key);
    }
   
    private Set getFromVanillaDestinations(ActiveMQDestination key){
        Set answer = (Set)vanillaDestinations.get(key);
        return answer != null ? answer : nullAnswer;
    }
   
    private void validateContainsWildCards(ActiveMQDestination key){
        if (containsWildCards && key.isWildcard()){
            containsWildCards = false;
            for (Iterator i = vanillaDestinations.keySet().iterator(); i.hasNext();){
                ActiveMQDestination dest = (ActiveMQDestination)i.next();
                if (dest.isWildcard()){
                    containsWildCards = true;
                    break;
                }
            }
        }
    }

}
TOP

Related Classes of org.activemq.filter.DestinationMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.