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 */
017package org.apache.activemq.console.filter;
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Map;
024import java.util.regex.Pattern;
025
026public 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}