00001 /* 00002 * LikeFilter.hpp 00003 * 00004 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_LIKE_FILTER_HPP 00017 #define COH_LIKE_FILTER_HPP 00018 00019 #include "coherence/lang.ns" 00020 00021 #include "coherence/io/pof/PofReader.hpp" 00022 #include "coherence/io/pof/PofWriter.hpp" 00023 #include "coherence/util/HashSet.hpp" 00024 #include "coherence/util/ValueExtractor.hpp" 00025 #include "coherence/util/filter/ComparisonFilter.hpp" 00026 #include "coherence/util/filter/IndexAwareFilter.hpp" 00027 00028 COH_OPEN_NAMESPACE3(coherence,util,filter) 00029 00030 using coherence::io::pof::PofReader; 00031 using coherence::io::pof::PofWriter; 00032 00033 00034 /** 00035 * Filter which compares the result of a method invocation with a value for 00036 * pattern match. A pattern can include regular characters and wildcard 00037 * characters '_' and '%'. 00038 * 00039 * During pattern matching, regular characters must exactly match the 00040 * characters in an evaluated string. Wildcard character '_' (underscore) can 00041 * be matched with any single character, and wildcard character '%' can be 00042 * matched with any string fragment of zero or more characters. 00043 * 00044 * @author djl 2008.07.24 00045 */ 00046 class COH_EXPORT LikeFilter 00047 : public class_spec<LikeFilter, 00048 extends<ComparisonFilter>, 00049 implements<IndexAwareFilter> > 00050 { 00051 friend class factory<LikeFilter>; 00052 00053 // ----- constructors --------------------------------------------------- 00054 00055 protected: 00056 /** 00057 * Default constructor (necessary for the PortableObject interface). 00058 */ 00059 LikeFilter(); 00060 00061 /** 00062 * Construct a LikeFilter for pattern match. 00063 * 00064 * @param vExtractor the ValueExtractor to use by this filter 00065 * @param vsPattern the string pattern to compare the result with 00066 * @param chEscape the escape character for escaping '%' and '_' 00067 * @param fIgnoreCase true to be case-insensitive 00068 */ 00069 LikeFilter(ValueExtractor::View vExtractor, String::View vsPattern, 00070 wchar16_t chEscape = (wchar16_t) 0, bool fIgnoreCase = false); 00071 00072 private: 00073 /** 00074 * Initialize this filter. 00075 * 00076 * @param chEscape the escape character for escaping '%' and '_' 00077 * @param fIgnoreCase true to be case-insensitive 00078 */ 00079 void init(wchar16_t chEscape, bool fIgnoreCase); 00080 00081 00082 // ----- ExtractorFilter interface -------------------------------------- 00083 00084 protected: 00085 /** 00086 * {@inheritDoc} 00087 */ 00088 virtual bool evaluateExtracted(Object::View vExtracted) const; 00089 00090 00091 // ----- IndexAwareFilter interface ------------------------------------- 00092 00093 public: 00094 /** 00095 * {@inheritDoc} 00096 */ 00097 virtual size32_t calculateEffectiveness(Map::View vMapIndexes, 00098 Set::View vSetKeys) const; 00099 00100 /** 00101 * {@inheritDoc} 00102 */ 00103 virtual Filter::View applyIndex(Map::View vMapIndexes, 00104 Set::Handle hSetKeys) const; 00105 00106 00107 // ----- PortableObject interface --------------------------------------- 00108 00109 public: 00110 /** 00111 * {@inheritDoc} 00112 */ 00113 virtual void readExternal(PofReader::Handle hIn); 00114 00115 /** 00116 * {@inheritDoc} 00117 */ 00118 virtual void writeExternal(PofWriter::Handle hOut) const; 00119 00120 00121 // ----- accessors ------------------------------------------------------ 00122 00123 public: 00124 /** 00125 * Obtain the filter's pattern string. 00126 * 00127 * @return the pattern string 00128 */ 00129 virtual String::View getPattern() const; 00130 00131 /** 00132 * Check whether or not the filter is case incensitive. 00133 * 00134 * @return true iff case insensitivity is specifically enabled 00135 */ 00136 virtual bool isIgnoreCase() const; 00137 00138 /** 00139 * Obtain the escape character that is used for escaping '%' and '_' 00140 * in the pattern or zero if there is no escape. 00141 * 00142 * @return the escape character 00143 */ 00144 virtual wchar16_t getEscapeChar() const; 00145 00146 /** 00147 * Display the execution plan that the LikeFilter has selected. 00148 * 00149 * @param out the ostream to display the plan on 00150 */ 00151 COH_INLINE void showPlan(std::ostream &out) const 00152 { 00153 out << formatPlan(); 00154 } 00155 00156 /** 00157 * Return the execution plan that the LikeFilter has selected. 00158 * 00159 * @return the plan 00160 */ 00161 virtual String::View formatPlan() const; 00162 00163 00164 // ----- internal methods ----------------------------------------------- 00165 00166 protected: 00167 /** 00168 * Build a plan for processing the LIKE functionality. 00169 */ 00170 virtual void buildPlan(); 00171 00172 /** 00173 * Check the passed String value to see if it matches the pattern that 00174 * this filter was constructed with. 00175 * 00176 * @param vsValue the String value to match against this filter's 00177 * pattern 00178 * 00179 * @return true iff the passed String value is LIKE this filter's 00180 * pattern 00181 */ 00182 virtual bool isMatch(String::View vsValue) const; 00183 00184 00185 // ----- nested class: MatchStep ---------------------------------------- 00186 00187 private: 00188 /** 00189 * Handles one matching step for a literal or a 00190 * character-by-character (literal and/or '_' matching). 00191 */ 00192 class MatchStep 00193 : public class_spec<MatchStep> 00194 { 00195 friend class factory<MatchStep>; 00196 00197 // ----- constructor ---------------------------------------- 00198 00199 protected: 00200 /** 00201 * Construct a MatchStep object. 00202 * 00203 * @param vsMatch the string of characters to match 00204 * in this step 00205 * @param vBitset corresponding to each character, true 00206 * if any character is allowed ('_') 00207 * @param fIsIgnoreCase true if ignoring case 00208 */ 00209 MatchStep(String::View vsMatch, HashSet::View vBitset, 00210 bool fIsIgnoreCase); 00211 00212 // ----- matching methods ----------------------------------- 00213 00214 public: 00215 /** 00216 * Find the first index of this match step in the passed 00217 * character array starting at the passed offset and 00218 * within the specified number of characters. 00219 * 00220 * @param vach the array of characters within which 00221 * to find a match 00222 * @param ofBegin the starting offset in character 00223 * array<tt>ach</tt> to start looking 00224 * for a match 00225 * @param ofEnd the first offset in the character 00226 * array <tt>ach</tt> which is beyond 00227 * the region that this operation is 00228 * allowed to search through to find a 00229 * match 00230 * 00231 * @return the first index at which the match is made, 00232 * or Array<char>::npos if the match cannot be made in the 00233 * designated range of offsets 00234 */ 00235 virtual size32_t indexOf(Array<char>::View vach, 00236 size32_t ofBegin, size32_t ofEnd) const; 00237 00238 // ----- accessors ------------------------------------------ 00239 00240 public: 00241 /** 00242 * @return the match pattern as a String 00243 */ 00244 virtual String::View getString() const; 00245 00246 /** 00247 * @return the length of the match pattern 00248 */ 00249 virtual size32_t getLength() const; 00250 00251 /** 00252 * @return true if there are no wildcards ('_') in the match 00253 * pattern 00254 */ 00255 virtual bool isLiteral() const; 00256 00257 // ----- Object methods ------------------------------------- 00258 00259 public: 00260 TypedHandle<const String> toString() const; 00261 00262 // ----- data members --------------------------------------- 00263 00264 private: 00265 /** 00266 * The match pattern, as a String. 00267 */ 00268 FinalView<String> f_vsMatch; 00269 00270 /** 00271 * The match pattern, as an array of char values. If the 00272 * filter is case insensitive, then this is the uppercase form 00273 * of the char values. 00274 */ 00275 MemberView<Array<char> > m_vachMatch; 00276 /** 00277 * The match pattern for a case insensitive like filter, as an 00278 * array of lowercase char values. For case sensitive filters, 00279 * this is null. 00280 */ 00281 MemberView<Array<char> > m_vachLower; 00282 00283 /** 00284 * For each character, true if the character is a wildcard 00285 * ('_'), or null if there are no wildcards. 00286 */ 00287 MemberView<Array<bool> > m_vafAny; 00288 00289 /** 00290 * Number of leading wildcards. 00291 */ 00292 size32_t m_cchSkipFront; 00293 00294 /** 00295 * Number of trailing wildcards. 00296 */ 00297 size32_t m_cchSkipBack; 00298 00299 /** 00300 * True if there are any wildcards in the middle. 00301 */ 00302 bool m_fMiddleWilds; 00303 00304 /** 00305 * True if there we are ignoring case. 00306 */ 00307 bool m_fIsIgnoreCase; 00308 00309 // ----- friends ---------------------------------------- 00310 00311 friend class LikeFilter; 00312 }; 00313 00314 00315 // ----- data members --------------------------------------------------- 00316 00317 private: 00318 /** 00319 * The escape character for escaping '_' and '%' in the pattern. 00320 * The valu zero is reserved to mean "no escape". 00321 */ 00322 wchar16_t m_chEscape; 00323 00324 /** 00325 * The option to ignore case sensitivity. True means that the filter 00326 * will match ignoring case. 00327 */ 00328 bool m_fIgnoreCase; 00329 00330 /** 00331 * Optimization plan number. Zero means default iterative evalution is 00332 * necessary. 00333 */ 00334 int32_t m_nPlan; 00335 00336 /** 00337 * Used by single-character matching optimization plans. 00338 */ 00339 char m_chPart; 00340 00341 /** 00342 * Used by string-character matching optimization plans. 00343 */ 00344 MemberView<String> m_vsPart; 00345 00346 /** 00347 * The "front" matching step used by the iterative processing; null if 00348 * the pattern starts with '%'. 00349 */ 00350 MemberView<MatchStep> m_vStepFront; 00351 00352 /** 00353 * The "back" matching step used by the iterative processing; null if 00354 * the pattern ends with '%'. 00355 */ 00356 MemberView<MatchStep> m_vStepBack; 00357 00358 /** 00359 * For iterative plans with a NULL "back" matching step, is trailing 00360 * data permitted. 00361 */ 00362 bool m_fTrailingTextAllowed; 00363 00364 /** 00365 * The array of "middle" matching steps used by the iterative 00366 * processing; may be NULL if none. 00367 */ 00368 MemberView<ObjectArray> m_vaStepMiddle; 00369 00370 /** 00371 * The flag that indicates whether the pattern is ascii. This allows 00372 * the match to execute locally. 00373 */ 00374 bool m_fPatternIsASCII; 00375 }; 00376 00377 COH_CLOSE_NAMESPACE3 00378 00379 #endif // COH_LIKE_FILTER_HPP