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 public List query(List queries) throws Exception {
049 Map regex = new HashMap();
050 List newQueries = new ArrayList();
051
052 // Lets parse for regular expression queries
053 for (Iterator i = queries.iterator(); i.hasNext();) {
054 // Get key-value pair
055 String token = (String)i.next();
056 String key = "";
057 String val = "";
058 int pos = token.indexOf("=");
059 if (pos >= 0) {
060 val = token.substring(pos + 1);
061 key = token.substring(0, pos);
062 }
063
064 // Add the regex query to list and make it a non-factor in the
065 // succeeding queries
066 if (isRegularExpression(val)) {
067 regex.put(key, compileQuery(val));
068
069 // Add the normal query to the query list
070 } else {
071 newQueries.add(token);
072 }
073 }
074
075 // Filter the result using the regular expressions specified
076 return filterCollectionUsingRegEx(regex, next.query(newQueries));
077 }
078
079 /**
080 * Checks if a given string is a regular expression query. Currently, a
081 * pattern is a regex query, if it starts with the
082 * RegExQueryFilter.REGEX_PREFIX.
083 *
084 * @param query
085 * @return
086 */
087 protected boolean isRegularExpression(String query) {
088 return query.startsWith(REGEX_PREFIX);
089 }
090
091 /**
092 * Compiles the regex query to a pattern.
093 *
094 * @param query - query string to compile
095 * @return regex pattern
096 */
097 protected Pattern compileQuery(String query) {
098 return Pattern.compile(query.substring(REGEX_PREFIX.length()));
099 }
100
101 /**
102 * Filter the specified colleciton using the regex patterns extracted.
103 *
104 * @param regex - regex map
105 * @param data - list of objects to filter
106 * @return filtered list of objects that matches the regex map
107 * @throws Exception
108 */
109 protected List filterCollectionUsingRegEx(Map regex, List data) throws Exception {
110 // No regular expressions filtering needed
111 if (regex == null || regex.isEmpty()) {
112 return data;
113 }
114
115 List filteredElems = new ArrayList();
116
117 // Get each data object to filter
118 for (Iterator i = data.iterator(); i.hasNext();) {
119 Object dataElem = i.next();
120 // If properties of data matches all the regex pattern, add it
121 if (matches(dataElem, regex)) {
122 filteredElems.add(dataElem);
123 }
124 }
125
126 return filteredElems;
127 }
128
129 /**
130 * Determines how the object is to be matched to the regex map.
131 *
132 * @param data - object to match
133 * @param regex - regex map
134 * @return true, if the object matches the regex map, false otherwise
135 * @throws Exception
136 */
137 protected abstract boolean matches(Object data, Map regex) throws Exception;
138 }