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}