mapcomplete/Logic/Tags/RegexTag.ts
2021-04-19 18:17:26 +02:00

98 lines
3.1 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;
}
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"
}
asChange(properties: any): { k: string; v: string }[] {
if(this.invert){
return []
}
if (typeof this.key === "string") {
if( typeof this.value === "string"){
return [{k: this.key, v: this.value}]
}
if(this.value.toString() != "/^..*$/"){
console.warn("Regex value in tag; using wildcard:", this.key, this.value)
}
return [{k: this.key, v: undefined}]
}
console.error("Cannot export regex tag to asChange; ", this.key, this.value)
return []
}
}