001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  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    package org.apache.activemq.console.filter;
018    
019    import java.util.ArrayList;
020    import java.util.HashMap;
021    import java.util.Iterator;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.regex.Pattern;
025    
026    public abstract class RegExQueryFilter extends AbstractQueryFilter {
027        public static final String REGEX_PREFIX = "REGEX:QUERY:";
028    
029        /**
030         * Creates a regular expression query that is able to match an object using
031         * key-value pattern regex filtering
032         *
033         * @param next
034         */
035        protected RegExQueryFilter(QueryFilter next) {
036            super(next);
037        }
038    
039        /**
040         * Separates the regular expressions queries from the usual queries. A query
041         * is a regex query, if it is key-value pair with the format <key>=<value>,
042         * and value is a pattern that satisfies the isRegularExpression method.
043         *
044         * @param queries - list of queries
045         * @return filtered objects that matches the regex query
046         * @throws Exception
047         */
048        @SuppressWarnings({ "rawtypes", "unchecked" })
049        public List query(List queries) throws Exception {
050            Map regex = new HashMap();
051            List newQueries = new ArrayList();
052    
053            // Lets parse for regular expression queries
054            for (Iterator i = queries.iterator(); i.hasNext();) {
055                // Get key-value pair
056                String token = (String)i.next();
057                String key = "";
058                String val = "";
059                int pos = token.indexOf("=");
060                if (pos >= 0) {
061                    val = token.substring(pos + 1);
062                    key = token.substring(0, pos);
063                }
064    
065                // Add the regex query to list and make it a non-factor in the
066                // succeeding queries
067                if (isRegularExpression(val)) {
068                    regex.put(key, compileQuery(val));
069    
070                    // Add the normal query to the query list
071                } else {
072                    newQueries.add(token);
073                }
074            }
075    
076            // Filter the result using the regular expressions specified
077            return filterCollectionUsingRegEx(regex, next.query(newQueries));
078        }
079    
080        /**
081         * Checks if a given string is a regular expression query. Currently, a
082         * pattern is a regex query, if it starts with the
083         * RegExQueryFilter.REGEX_PREFIX.
084         *
085         * @param query
086         * @return boolean result of query check
087         */
088        protected boolean isRegularExpression(String query) {
089            return query.startsWith(REGEX_PREFIX);
090        }
091    
092        /**
093         * Compiles the regex query to a pattern.
094         *
095         * @param query - query string to compile
096         * @return regex pattern
097         */
098        protected Pattern compileQuery(String query) {
099            return Pattern.compile(query.substring(REGEX_PREFIX.length()));
100        }
101    
102        /**
103         * Filter the specified colleciton using the regex patterns extracted.
104         *
105         * @param regex - regex map
106         * @param data - list of objects to filter
107         * @return filtered list of objects that matches the regex map
108         * @throws Exception
109         */
110        @SuppressWarnings({ "rawtypes", "unchecked" })
111        protected List filterCollectionUsingRegEx(Map regex, List data) throws Exception {
112            // No regular expressions filtering needed
113            if (regex == null || regex.isEmpty()) {
114                return data;
115            }
116    
117            List filteredElems = new ArrayList();
118    
119            // Get each data object to filter
120            for (Iterator i = data.iterator(); i.hasNext();) {
121                Object dataElem = i.next();
122                // If properties of data matches all the regex pattern, add it
123                if (matches(dataElem, regex)) {
124                    filteredElems.add(dataElem);
125                }
126            }
127    
128            return filteredElems;
129        }
130    
131        /**
132         * Determines how the object is to be matched to the regex map.
133         *
134         * @param data - object to match
135         * @param regex - regex map
136         * @return true, if the object matches the regex map, false otherwise
137         * @throws Exception
138         */
139        @SuppressWarnings("rawtypes")
140        protected abstract boolean matches(Object data, Map regex) throws Exception;
141    }