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 || [0];
 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([0]) : 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_.length === 1 ? this.label_[0] = 0 : 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_[0] === 0 ? this.label_[0] = 1 : 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.label_.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.label_.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.label_.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.label_.length; i++) {
180     if (this.label_[i] > label.value(i)) return true;
181   }
182   if (this.label_.length > label.length()) return true;
183   return false;
184 };
185 
186 
187 
188 xrx.label.prototype.isChildOf = function(label) {
189 
190   if (this.label_[0] === 1 && label.value(0) === 0) return true;
191   if (this.length() - 1 !== label.length()) return false;
192   var len = label.length();
193   for (var i = 0; i < len; i++) {
194     if (this.label_[i] === 0 && label.value(i) === 1) continue;
195     if (this.label_[i] !== label.value(i)) return false;
196   }
197   return true;
198 };
199 
200 
201 
202 xrx.label.prototype.isAncestorOf = function(label) {
203 
204   if (this.label_[0] === 0 && label.value(0) === 1) return true;
205   if (this.length() >= label.length()) return false;
206   var len = this.length();
207   for (var i = 0; i < len; i++) {
208     if (this.label_[i] === 0 && label.value(i) === 1) continue;
209     if (this.label_[i] !== label.value(i)) return false;
210   }
211   return true;
212 };
213 
214 
215 
216 xrx.label.prototype.isDescendantOf = function(label) {
217 
218   if (this.label_[0] === 1 && label.value(0) === 0) return true;
219   if (this.length() <= label.length()) return false;
220   var len = label.length();
221   for (var i = 0; i < len; i++) {
222     if (this.label_[i] === 1 && label.value(i) === 0) continue;
223     if (this.label_[i] !== label.value(i)) return false;
224   }
225   return true;
226 };
227 
228 
229 xrx.label.prototype.isParentOf = function(label) {
230 
231   if (this.label_[0] === 0 && label.value(0) === 1) return true;
232   if (this.length() !== label.length() - 1) return false;
233   var len = this.length();
234   for (var i = 0; i < len; i++) {
235     if (this.label_[i] === 0 && label.value(i) === 1) continue;
236     if (this.label_[i] !== label.value(i)) return false;
237   }
238   return true;
239 };
240 
241 xrx.label.prototype.isPrecedingSiblingOf = function(label) {
242 
243   if (this.length() !== label.length()) return false;
244   var len = this.length();
245   for (var i = 0; i < len - 1; i++) {
246     if (this.label_[i] !== label.value(i)) return false;
247   }
248   if (this.label_[len - 1] >= label.value(len - 1)) return false;
249   return true;
250 };
251 
252 
253 
254 xrx.label.prototype.toString = function() {
255   var string = '';
256 
257   for (var i = 0; i < this.label_.length; i++) {
258     string += this.label_[i].toString() + '.';
259   }
260   return string;
261 };
262 
263