mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 09:03:21 +00:00 
			
		
		
		
	GUAC-1138: Add filter pattern tokenizer. Match any object property against all tokens.
This commit is contained in:
		| @@ -23,8 +23,14 @@ | |||||||
| /** | /** | ||||||
|  * A service for defining the FilterPattern class. |  * A service for defining the FilterPattern class. | ||||||
|  */ |  */ | ||||||
| angular.module('list').factory('FilterPattern', ['$parse', | angular.module('list').factory('FilterPattern', ['$injector', | ||||||
|     function defineFilterPattern($parse) { |     function defineFilterPattern($injector) { | ||||||
|  |  | ||||||
|  |     // Required types | ||||||
|  |     var FilterToken = $injector.get('FilterToken'); | ||||||
|  |  | ||||||
|  |     // Required services | ||||||
|  |     var $parse = $injector.get('$parse'); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Object which handles compilation of filtering predicates as used by |      * Object which handles compilation of filtering predicates as used by | ||||||
| @@ -69,6 +75,43 @@ angular.module('list').factory('FilterPattern', ['$parse', | |||||||
|             getters.push($parse(expression)); |             getters.push($parse(expression)); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Determines whether the given object matches the given filter pattern | ||||||
|  |          * token. | ||||||
|  |          * | ||||||
|  |          * @param {Object} object | ||||||
|  |          *     The object to match the token against. | ||||||
|  |          *  | ||||||
|  |          * @param {FilterToken} token | ||||||
|  |          *     The token from the tokenized filter pattern to match aginst the | ||||||
|  |          *     given object. | ||||||
|  |          * | ||||||
|  |          * @returns {Boolean} | ||||||
|  |          *     true if the object matches the token, false otherwise. | ||||||
|  |          */ | ||||||
|  |         var matchesToken = function matchToken(object, token) { | ||||||
|  |  | ||||||
|  |             // Only match against literals | ||||||
|  |             if (token.type !== 'LITERAL') | ||||||
|  |                 return false; | ||||||
|  |  | ||||||
|  |             // For each defined getter | ||||||
|  |             for (var i=0; i < getters.length; i++) { | ||||||
|  |  | ||||||
|  |                 // Retrieve value of current getter | ||||||
|  |                 var value = getters[i](object); | ||||||
|  |  | ||||||
|  |                 // If the value matches the pattern, the whole object matches | ||||||
|  |                 if (String(value).toLowerCase().indexOf(token.value) !== -1)  | ||||||
|  |                     return true; | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // No matches found | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |         }; | ||||||
|  |  | ||||||
|         /** |         /** | ||||||
|          * The current filtering predicate. |          * The current filtering predicate. | ||||||
|          * |          * | ||||||
| @@ -92,26 +135,20 @@ angular.module('list').factory('FilterPattern', ['$parse', | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|                  |                  | ||||||
|             // Convert to lower case for case insensitive matching             |             // Tokenize pattern, converting to lower case for case-insensitive matching | ||||||
|             pattern = pattern.toLowerCase(); |             var tokens = FilterToken.tokenize(pattern.toLowerCase()); | ||||||
|  |  | ||||||
|             // Return predicate which matches against the value of any getter in the getters array |             // Return predicate which matches against the value of any getter in the getters array | ||||||
|             filterPattern.predicate = function matchAny(object) { |             filterPattern.predicate = function matchesAllTokens(object) { | ||||||
|  |  | ||||||
|                 // For each defined getter |  | ||||||
|                 for (var i=0; i < getters.length; i++) { |  | ||||||
|  |  | ||||||
|                     // Retrieve value of current getter |  | ||||||
|                     var value = getters[i](object); |  | ||||||
|  |  | ||||||
|                     // If the value matches the pattern, the whole object matches |  | ||||||
|                     if (String(value).toLowerCase().indexOf(pattern) !== -1)  |  | ||||||
|                         return true; |  | ||||||
|  |  | ||||||
|  |                 // False if any token does not match | ||||||
|  |                 for (var i=0; i < tokens.length; i++) { | ||||||
|  |                     if (!matchesToken(object, tokens[i])) | ||||||
|  |                         return false; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // No matches found |                 // True if all tokens matched | ||||||
|                 return false; |                 return true; | ||||||
|  |  | ||||||
|             }; |             }; | ||||||
|              |              | ||||||
|   | |||||||
							
								
								
									
										153
									
								
								guacamole/src/main/webapp/app/list/types/FilterToken.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								guacamole/src/main/webapp/app/list/types/FilterToken.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (C) 2015 Glyptodon LLC | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in | ||||||
|  |  * all copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  |  * THE SOFTWARE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A service for defining the FilterToken class. | ||||||
|  |  */ | ||||||
|  | angular.module('list').factory('FilterToken', [ | ||||||
|  |     function defineFilterToken() { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * An arbitrary token having an associated type and string value. | ||||||
|  |      * | ||||||
|  |      * @constructor | ||||||
|  |      * @param {String} type | ||||||
|  |      *     The type of this token. Each legal type name is a property within | ||||||
|  |      *     FilterToken.Types. | ||||||
|  |      * | ||||||
|  |      * @param {String} value | ||||||
|  |      *     The string value of this token. | ||||||
|  |      */ | ||||||
|  |     var FilterToken = function FilterToken(type, value) { | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * The type of this token. Each legal type name is a property within | ||||||
|  |          * FilterToken.Types. | ||||||
|  |          * | ||||||
|  |          * @type String | ||||||
|  |          */ | ||||||
|  |         this.type = type; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * The string value of this token. | ||||||
|  |          * | ||||||
|  |          * @type String | ||||||
|  |          */ | ||||||
|  |         this.value = value; | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * All legal token types, and corresponding regular expressions which match | ||||||
|  |      * them. If the regular expression contains capturing groups, the last | ||||||
|  |      * matching group will be used as the value of the token. | ||||||
|  |      * | ||||||
|  |      * @type Object.<String, RegExp> | ||||||
|  |      */ | ||||||
|  |     FilterToken.Types = { | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * A string literal. | ||||||
|  |          */ | ||||||
|  |         LITERAL: /^"([^"]*)"|^\S+/, | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Arbitrary contiguous whitespace. | ||||||
|  |          */ | ||||||
|  |         WHITESPACE: /^\s+/ | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Tokenizes the given string, returning an array of tokens. Whitespace | ||||||
|  |      * tokens are dropped. | ||||||
|  |      * | ||||||
|  |      * @param {String} str | ||||||
|  |      *     The string to tokenize. | ||||||
|  |      * | ||||||
|  |      * @returns {FilterToken[]} | ||||||
|  |      *     All tokens identified within the given string, in order. | ||||||
|  |      */ | ||||||
|  |     FilterToken.tokenize = function tokenize(str) { | ||||||
|  |  | ||||||
|  |         var tokens = []; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * Returns the first token on the current string, removing the token | ||||||
|  |          * from that string. | ||||||
|  |          * | ||||||
|  |          * @returns FilterToken | ||||||
|  |          *     The first token on the string, or null if no tokens match. | ||||||
|  |          */ | ||||||
|  |         var popToken = function popToken() { | ||||||
|  |  | ||||||
|  |             // Attempt to find a matching token | ||||||
|  |             for (var type in FilterToken.Types) { | ||||||
|  |  | ||||||
|  |                 // Get regular expression for current type | ||||||
|  |                 var regex = FilterToken.Types[type]; | ||||||
|  |  | ||||||
|  |                 // If token matches, return the matching group | ||||||
|  |                 var match = regex.exec(str); | ||||||
|  |                 if (match) { | ||||||
|  |  | ||||||
|  |                     // Advance to next token | ||||||
|  |                     str = str.substring(match[0].length); | ||||||
|  |  | ||||||
|  |                     // Grab last matching group | ||||||
|  |                     var matchingGroup = match[0]; | ||||||
|  |                     for (var i=1; i < match.length; i++) | ||||||
|  |                         matchingGroup = match[i] || matchingGroup; | ||||||
|  |  | ||||||
|  |                     // Return new token | ||||||
|  |                     return new FilterToken(type, matchingGroup); | ||||||
|  |  | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // No match | ||||||
|  |             return null; | ||||||
|  |  | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         // Tokenize input until no input remains | ||||||
|  |         while (str) { | ||||||
|  |  | ||||||
|  |             // Remove first token | ||||||
|  |             var token = popToken(); | ||||||
|  |             if (!token) | ||||||
|  |                 break; | ||||||
|  |  | ||||||
|  |             // Add token to tokens array, if not whitespace | ||||||
|  |             if (token.type !== 'WHITESPACE') | ||||||
|  |                 tokens.push(token); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return tokens; | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     return FilterToken; | ||||||
|  |  | ||||||
|  | }]); | ||||||
		Reference in New Issue
	
	Block a user