forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			85 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			85 lines
		
	
	
	
		
			2.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | import {Tag} from "./Tag"; | ||
|  | import {TagsFilter} from "./TagsFilter"; | ||
|  | 
 | ||
|  | export class RegexTag extends TagsFilter { | ||
|  |     private readonly key: RegExp | string; | ||
|  |     private readonly value: RegExp | string; | ||
|  |     private readonly invert: boolean; | ||
|  |     private readonly matchesEmpty: boolean | ||
|  | 
 | ||
|  |     constructor(key: string | RegExp, value: RegExp | string, invert: boolean = false) { | ||
|  |         super(); | ||
|  |         this.key = key; | ||
|  |         this.value = value; | ||
|  |         this.invert = invert; | ||
|  |         this.matchesEmpty = RegexTag.doesMatch("", this.value); | ||
|  |     } | ||
|  | 
 | ||
|  |     private static doesMatch(fromTag: string, possibleRegex: string | RegExp): boolean { | ||
|  |         if (typeof possibleRegex === "string") { | ||
|  |             return fromTag === possibleRegex; | ||
|  |         } | ||
|  |         return fromTag.match(possibleRegex) !== null; | ||
|  |     } | ||
|  | 
 | ||
|  |     private static source(r: string | RegExp) { | ||
|  |         if (typeof (r) === "string") { | ||
|  |             return r; | ||
|  |         } | ||
|  |         return r.source; | ||
|  |     } | ||
|  | 
 | ||
|  |     asOverpass(): string[] { | ||
|  |         if (typeof this.key === "string") { | ||
|  |             return [`['${this.key}'${this.invert ? "!" : ""}~'${RegexTag.source(this.value)}']`]; | ||
|  |         } | ||
|  |         return [`[~'${this.key.source}'${this.invert ? "!" : ""}~'${RegexTag.source(this.value)}']`]; | ||
|  |     } | ||
|  | 
 | ||
|  |     isUsableAsAnswer(): boolean { | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     matchesProperties(tags: any): boolean { | ||
|  |         for (const key in tags) { | ||
|  |             if (RegexTag.doesMatch(key, this.key)) { | ||
|  |                 const value = tags[key] | ||
|  |                 return RegexTag.doesMatch(value, this.value) != this.invert; | ||
|  |             } | ||
|  |         } | ||
|  |         if (this.matchesEmpty) { | ||
|  |             // The value is 'empty'
 | ||
|  |             return !this.invert; | ||
|  |         } | ||
|  |         // The matching key was not found
 | ||
|  |         return this.invert; | ||
|  |     } | ||
|  | 
 | ||
|  |     substituteValues(tags: any): TagsFilter { | ||
|  |         return this; | ||
|  |     } | ||
|  | 
 | ||
|  |     asHumanString() { | ||
|  |         if (typeof this.key === "string") { | ||
|  |             return `${this.key}${this.invert ? "!" : ""}~${RegexTag.source(this.value)}`; | ||
|  |         } | ||
|  |         return `${this.key.source}${this.invert ? "!" : ""}~~${RegexTag.source(this.value)}` | ||
|  |     } | ||
|  | 
 | ||
|  |     isEquivalent(other: TagsFilter): boolean { | ||
|  |         if (other instanceof RegexTag) { | ||
|  |             return other.asHumanString() == this.asHumanString(); | ||
|  |         } | ||
|  |         if (other instanceof Tag) { | ||
|  |             return RegexTag.doesMatch(other.key, this.key) && RegexTag.doesMatch(other.value, this.value); | ||
|  |         } | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     usedKeys(): string[] { | ||
|  |         if (typeof this.key === "string") { | ||
|  |             return [this.key]; | ||
|  |         } | ||
|  |         throw "Key cannot be determined as it is a regex" | ||
|  |     } | ||
|  | } |