forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			121 lines
		
	
	
		
			No EOL
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			No EOL
		
	
	
		
			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;
 | |
|     }
 | |
| } |