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 }