forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			121 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | import {Tag} from "./Tag"; | ||
|  | import {TagsFilter} from "./TagsFilter"; | ||
|  | import {And} from "./And"; | ||
|  | import {Utils} from "../Utils"; | ||
|  | 
 | ||
|  | export class TagUtils { | ||
|  |     static ApplyTemplate(template: string, tags: any): string { | ||
|  |         for (const k in tags) { | ||
|  |             while (template.indexOf("{" + k + "}") >= 0) { | ||
|  |                 const escaped = tags[k].replace(/</g, '<').replace(/>/g, '>'); | ||
|  |                 template = template.replace("{" + k + "}", escaped); | ||
|  |             } | ||
|  |         } | ||
|  |         return template; | ||
|  |     } | ||
|  | 
 | ||
|  |     static KVtoProperties(tags: Tag[]): any { | ||
|  |         const properties = {}; | ||
|  |         for (const tag of tags) { | ||
|  |             properties[tag.key] = tag.value | ||
|  |         } | ||
|  |         return properties; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Given two hashes of {key --> values[]}, makes sure that every neededTag is present in availableTags | ||
|  |      */ | ||
|  |     static AllKeysAreContained(availableTags: any, neededTags: any) { | ||
|  |         for (const neededKey in neededTags) { | ||
|  |             const availableValues: string[] = availableTags[neededKey] | ||
|  |             if (availableValues === undefined) { | ||
|  |                 return false; | ||
|  |             } | ||
|  |             const neededValues: string[] = neededTags[neededKey]; | ||
|  |             for (const neededValue of neededValues) { | ||
|  |                 if (availableValues.indexOf(neededValue) < 0) { | ||
|  |                     return false; | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |         return true; | ||
|  |     } | ||
|  | 
 | ||
|  |     /*** | ||
|  |      * Creates a hash {key --> [values]}, with all the values present in the tagsfilter | ||
|  |      * | ||
|  |      * @param tagsFilters | ||
|  |      * @constructor | ||
|  |      */ | ||
|  |     static SplitKeys(tagsFilters: TagsFilter[]) { | ||
|  |         const keyValues = {} // Map string -> string[]
 | ||
|  |         tagsFilters = [...tagsFilters] // copy all
 | ||
|  |         while (tagsFilters.length > 0) { | ||
|  |             // Queue
 | ||
|  |             const tagsFilter = tagsFilters.shift(); | ||
|  | 
 | ||
|  |             if (tagsFilter === undefined) { | ||
|  |                 continue; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (tagsFilter instanceof And) { | ||
|  |                 tagsFilters.push(...tagsFilter.and); | ||
|  |                 continue; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (tagsFilter instanceof Tag) { | ||
|  |                 if (keyValues[tagsFilter.key] === undefined) { | ||
|  |                     keyValues[tagsFilter.key] = []; | ||
|  |                 } | ||
|  |                 keyValues[tagsFilter.key].push(...tagsFilter.value.split(";")); | ||
|  |                 continue; | ||
|  |             } | ||
|  | 
 | ||
|  |             console.error("Invalid type to flatten the multiAnswer", tagsFilter); | ||
|  |             throw "Invalid type to FlattenMultiAnswer" | ||
|  |         } | ||
|  |         return keyValues; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Given multiple tagsfilters which can be used as answer, will take the tags with the same keys together as set. | ||
|  |      * E.g: | ||
|  |      * | ||
|  |      * FlattenMultiAnswer([and: [ "x=a", "y=0;1"], and: ["x=b", "y=2"], and: ["x=", "y=3"]]) | ||
|  |      * will result in | ||
|  |      * ["x=a;b", "y=0;1;2;3"] | ||
|  |      * | ||
|  |      * @param tagsFilters | ||
|  |      * @constructor | ||
|  |      */ | ||
|  |     static FlattenMultiAnswer(tagsFilters: TagsFilter[]): And { | ||
|  |         if (tagsFilters === undefined) { | ||
|  |             return new And([]); | ||
|  |         } | ||
|  | 
 | ||
|  |         let keyValues = TagUtils.SplitKeys(tagsFilters); | ||
|  |         const and: TagsFilter[] = [] | ||
|  |         for (const key in keyValues) { | ||
|  |             and.push(new Tag(key, Utils.Dedup(keyValues[key]).join(";"))); | ||
|  |         } | ||
|  |         return new And(and); | ||
|  |     } | ||
|  | 
 | ||
|  |     static MatchesMultiAnswer(tag: TagsFilter, tags: any): boolean { | ||
|  |         const splitted = TagUtils.SplitKeys([tag]); | ||
|  |         for (const splitKey in splitted) { | ||
|  |             const neededValues = splitted[splitKey]; | ||
|  |             if (tags[splitKey] === undefined) { | ||
|  |                 return false; | ||
|  |             } | ||
|  | 
 | ||
|  |             const actualValue = tags[splitKey].split(";"); | ||
|  |             for (const neededValue of neededValues) { | ||
|  |                 if (actualValue.indexOf(neededValue) < 0) { | ||
|  |                     return false; | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |         return true; | ||
|  |     } | ||
|  | } |