1 /** 2 * Copyright: 3 * (C) 2016 Martin Brzenska 4 * 5 * License: 6 * Distributed under the terms of the MIT license. 7 * Consult the provided LICENSE.md file for details 8 */ 9 module libdominator.Attribute; 10 11 import std.regex : regex , matchFirst ; 12 import std.array : split; 13 14 import libdominator; 15 16 ///Struct for Node Attributes 17 struct Attribute 18 { 19 string key; 20 string[] values; 21 22 /** 23 * Params: 24 * key = the Name of the Attribute (can be prefixed with '(regex)') 25 * values = a whitespace serparated List of Attribute Values (each Value can be prefixed with '(regex)') 26 */ 27 this(string key, string values) 28 { 29 import std.string : toLower; 30 this.key = toLower(key); 31 this.values = split(values); 32 } 33 /** 34 * Params: 35 * key = The name of the attribute (can be prefixed with '(regex)') 36 * values = Array of attribute values (each value can be prefixed with '(regex)') 37 */ 38 this(string key, string[] values) 39 { 40 this.key = key; 41 this.values = values; 42 } 43 44 ///Checks if the given node matches the attributes given key 45 bool matchesKey(Node node) 46 { 47 if (key.length > 6 && key[0..7] == "(regex)") 48 { 49 auto regx = regex(key[7..$]); 50 foreach (Attribute attrib; node.getAttributes()) 51 { 52 auto capture = matchFirst(attrib.key, regx); 53 if (!capture.empty) 54 { 55 return true; 56 } 57 } 58 } 59 else 60 { 61 foreach (Attribute attrib; node.getAttributes()) 62 { 63 if (attrib.key == key) 64 { 65 return true; 66 } 67 } 68 } 69 return false; 70 } 71 ///Checks if at least one of the attribute values of the given node matches the given attribute values 72 bool matchesValue(Node node) 73 { 74 if (values.length == 0) 75 { 76 return true; 77 } 78 ubyte hitCount; 79 foreach (string value; values) 80 { 81 bool isRegex; 82 if (value.length > 6 && value[0 .. 7] == "(regex)") 83 { 84 isRegex =true; 85 } 86 foreach (Attribute attrib; node.getAttributes()) 87 { 88 foreach (string nodeValue; attrib.values) 89 { 90 if(isRegex) 91 { 92 auto capture = matchFirst(nodeValue, regex(value[7..$])); 93 if (!capture.empty) { hitCount++; } 94 } 95 else { 96 if (nodeValue == value) { hitCount++; } 97 } 98 if(hitCount == values.length) { return true; } 99 } 100 } 101 } 102 return false; 103 } 104 105 /** 106 * Checks if the given node matches key and values of this attribute. 107 * Note that all atribute values from this attribute must match the given nodes attribute values - not the other way round 108 */ 109 bool matches(Node node) 110 { 111 return this.matchesKey(node) && this.matchesValue(node); 112 } 113 114 }