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