1 /** 2 * @fileoverview A class representing a numeric, array like 3 * XML labeling scheme. 4 */ 5 6 goog.provide('xrx.label'); 7 8 9 10 /** 11 * Constructs a new label. 12 * 13 * @constructor 14 * @param {?Array.<!number>} array The array of numbers. 15 */ 16 xrx.label = function(array) { 17 this.label_ = array || []; 18 }; 19 20 21 22 /** 23 * Returns the length of the label. The length corresponds 24 * to the nesting depth of a node or token in the XML tree. 25 * @return {!number} 26 */ 27 xrx.label.prototype.length = function() { 28 return this.label_.length; 29 }; 30 31 32 33 /** 34 * Returns a label item at position index. 35 * @param {!number} index The index. 36 * @return {!number} 37 */ 38 xrx.label.prototype.value = function(index) { 39 return this.label_[index]; 40 }; 41 42 43 44 /** 45 * Returns the first label item. 46 * @return {!number} 47 */ 48 xrx.label.prototype.first = function() { 49 return this.label_[0]; 50 }; 51 52 53 54 /** 55 * Returns the last label item. 56 * @return {!number} 57 */ 58 xrx.label.prototype.last = function() { 59 return this.label_[this.length() - 1]; 60 }; 61 62 63 64 /** 65 * Returns a copy of the label. 66 * @return {!xrx.label} 67 */ 68 xrx.label.prototype.clone = function() { 69 var length = this.length(); 70 var array = new Array(length); 71 72 for(var i = 0; i < length; i++) { 73 array[i] = this.label_[i]; 74 } 75 return new xrx.label(array); 76 }; 77 78 79 80 /** 81 * Returns the joint parent of two labels. 82 * @param {!xrx.label} label 83 * @return {!xrx.label} 84 */ 85 xrx.label.prototype.jointParent = function(label) { 86 var arr = []; 87 88 for(var i = 0; i < label.length(); i++) { 89 val = this.label_[i]; 90 val === label.value(i) ? arr.push(val) : null; 91 } 92 return arr.length === 0 ? new xrx.label() : new xrx.label(arr); 93 }; 94 95 96 97 /** 98 * Mutates the label into its parent label. 99 */ 100 xrx.label.prototype.parent = function() { 101 this.label_.pop(); 102 }; 103 104 105 106 /** 107 * Mutates the label into its child label. 108 */ 109 xrx.label.prototype.child = function() { 110 this.label_.push(1); 111 }; 112 113 114 115 /** 116 * Mutates the label into its preceding sibling label. 117 */ 118 xrx.label.prototype.precedingSibling = function() { 119 this.label_[this.length() - 1] -= 1; 120 }; 121 122 123 124 /** 125 * Mutates the label into its next sibling label. 126 */ 127 xrx.label.prototype.nextSibling = function() { 128 this.label_[this.length() - 1] += 1; 129 }; 130 131 132 133 /** 134 * Helper function for xrx.token.NOT_TAG. 135 * @deprecated 136 */ 137 xrx.label.prototype.push0 = function() { 138 this.label_.push(0); 139 }; 140 141 142 143 /** 144 * Indicates whether two labels are the same. 145 * @param {!xrx.label} 146 * @return {!boolean} 147 */ 148 xrx.label.prototype.sameAs = function(label) { 149 150 if (this.label_.length !== label.length()) { 151 return false; 152 } 153 for(var i = 0; i < label.length(); i++) { 154 if (this.label_[i] !== label.value(i)) { 155 return false; 156 } 157 } 158 return true; 159 }; 160 161 162 163 /** 164 * 165 */ 166 xrx.label.prototype.isBefore = function(label) { 167 168 for(var i = 0; i < this.length(); i++) { 169 if (this.label_[i] < label.value(i)) return true; 170 } 171 if (this.label_.length < label.length()) return true; 172 return false; 173 }; 174 175 176 177 xrx.label.prototype.isAfter = function(label) { 178 179 for(var i = 0; i < this.length(); i++) { 180 if (this.label_[i] > label.value(i)) return true; 181 } 182 if (this.length() > label.length()) return true; 183 return false; 184 }; 185 186 187 188 xrx.label.prototype.isChildOf = function(label) { 189 190 if (this.length() - 1 !== label.length()) return false; 191 192 for (var i = 0; i < label.length(); i++) { 193 if (this.label_[i] !== label.value(i)) return false; 194 } 195 return true; 196 }; 197 198 199 200 xrx.label.prototype.isAncestorOf = function(label) { 201 202 if (this.length() >= label.length()) return false; 203 204 for (var i = 0; i < this.length(); i++) { 205 if (this.label_[i] !== label.value(i)) return false; 206 } 207 return true; 208 }; 209 210 211 212 xrx.label.prototype.isDescendantOf = function(label) { 213 214 if (this.length() <= label.length()) return false; 215 216 for (var i = 0; i < label.length(); i++) { 217 if (this.label_[i] !== label.value(i)) return false; 218 } 219 return true; 220 }; 221 222 223 xrx.label.prototype.isParentOf = function(label) { 224 225 if (this.length() !== label.length() - 1) return false; 226 227 for (var i = 0; i < this.length(); i++) { 228 if (this.label_[i] !== label.value(i)) return false; 229 } 230 return true; 231 }; 232 233 xrx.label.prototype.isPrecedingSiblingOf = function(label) { 234 235 if (this.length() !== label.length()) return false; 236 var len = this.length(); 237 for (var i = 0; i < len - 1; i++) { 238 if (this.label_[i] !== label.value(i)) return false; 239 } 240 if (this.label_[len - 1] >= label.value(len - 1)) return false; 241 return true; 242 }; 243 244 245 246 xrx.label.prototype.toString = function() { 247 return this.label_.join('.'); 248 }; 249 250