1 /**
  2  * @fileoverview A class representing the tokens of a XML stream.
  3  */
  4 
  5 goog.provide('xrx.token');
  6 
  7 
  8 
  9 goog.require('xrx.label');
 10 
 11 
 12 
 13 /**
 14  * Base class to construct a new token.
 15  * This constructor should never be called directly, but
 16  * by one of the inherited token classes.
 17  *
 18  * @constructor
 19  * @param {!number} type The type of the token.
 20  * @param {?xrx.label} label The label attached to the token.
 21  * @param {?number} offset The offset relative to the start of 
 22  *     the XML stream.
 23  * @param {?number} length The number of characters occupied 
 24  *     in the XML stream.
 25  */
 26 xrx.token = function(type, opt_label, opt_offset, opt_length) {
 27 
 28 
 29 
 30   /**
 31    * @private
 32    */
 33   this.type_ = type;
 34 
 35 
 36 
 37   /**
 38    * @private
 39    */
 40   this.label_ = opt_label;
 41 
 42 
 43 
 44   /**
 45    * @private
 46    */
 47   this.offset_ = opt_offset;
 48 
 49 
 50 
 51   /**
 52    * @private
 53    */
 54   this.length_ = opt_length;
 55 };
 56 
 57 
 58 
 59 /**
 60  * Primary tokens
 61  */
 62 /** @const */ xrx.token.ROOT = 0;
 63 /** @const */ xrx.token.START_TAG = 1;
 64 /** @const */ xrx.token.END_TAG = 2;
 65 /** @const */ xrx.token.EMPTY_TAG = 3;
 66 
 67 
 68 
 69 /**
 70  * Secondary tokens (part of a tag)
 71  */
 72 /** @const */ xrx.token.TAG_NAME = 5;
 73 /** @const */ xrx.token.ATTRIBUTE = 6;
 74 /** @const */ xrx.token.ATTR_NAME = 7;
 75 /** @const */ xrx.token.ATTR_VALUE = 8;
 76 /** @const */ xrx.token.NAMESPACE = 9;
 77 /** @const */ xrx.token.NS_PREFIX = 10;
 78 /** @const */ xrx.token.NS_URI = 11;
 79 
 80 
 81 
 82 /**
 83  * Generic tokens
 84  */
 85 /** @const */ xrx.token.UNDEFINED = -1;
 86 /** @const */ xrx.token.NOT_TAG = 12;
 87 // either xrx.token.START_TAG or 
 88 // xrx.token.EMPTY_TAG
 89 /** @const */ xrx.token.START_EMPTY_TAG = 4;
 90 // either xrx.token.END_TAG or 
 91 // xrx.token.START_EMPTY_TAG
 92 /** @const */ xrx.token.TAG = 13;
 93 
 94 
 95 
 96 /**
 97  * Complex tokens
 98  */
 99 // A selection of sequenced tokens of 
100 // different type forming a peace of 
101 // well-formed XML. Corresponds to what 
102 // a DOM element is.
103 /** @const */ xrx.token.FRAGMENT = 14; 
104 // xrx.token.START_TAG plus 
105 // xrx.token.END_TAG
106 /** @const */ xrx.token.START_END = 15;
107 // same as xrx.token.FRAGMENT, but may 
108 // start and end with xrx.token.NOT_TAG 
109 // or even may end or start with a part 
110 // of xrx.token.NOT_TAG
111 /** @const */ xrx.token.MIXED = 16;
112 
113 // numbering of tokens is important to 
114 // compute document order!
115 
116 
117 
118 /**
119  * Converts a generic token into its native form.
120  *
121  * @param {!xrx.token} token The token to convert.
122  * @return {?}
123  */
124 xrx.token.native = function(token) {
125   var newToken;
126   var label = token.label().clone();
127   var offset = token.offset();
128   var length = token.length();
129   
130   var convert = function(constr) {
131     var tmp = new constr();
132     tmp.label(label);
133     tmp.offset(offset);
134     tmp.length(length);
135     return tmp;
136   };
137   
138   switch(token.type()) {
139   case xrx.token.START_TAG:
140     newToken = convert(xrx.token.StartTag);
141     break;
142   case xrx.token.END_TAG:
143     newToken = convert(xrx.token.EndTag);
144     break;
145   case xrx.token.EMPTY_TAG:
146     newToken = convert(xrx.token.EmptyTag);
147     break;
148   case xrx.token.NOT_TAG:
149     newToken = convert(xrx.token.NotTag);
150     break;
151   case xrx.token.TAG_NAME:
152     newToken = convert(xrx.token.TagName);
153     break;
154   case xrx.token.ATTRIBUE:
155     newToken = convert(xrx.token.Attribute);
156     break;
157   case xrx.token.ATTR_NAME:
158     newToken = convert(xrx.token.AttrName);
159     break;
160   case xrx.token.ATTR_VALUE:
161     newToken = convert(xrx.token.AttrValue);
162     break;
163   default:
164     throw Error('Token is generic or unknown.');
165     break;  
166   };
167   
168   return newToken;
169 };
170 
171 
172 
173 /**
174  * Compares the generic type of two tokens.
175  *
176  * @param {!number} type The type to check against.
177  * @return {!boolean}
178  */
179 xrx.token.prototype.typeOf = function(type) {
180   return this.type_ === type;
181 };
182 
183 
184 
185 /**
186  * Checks if two tokens are the same. 
187  * Note that two tokens are considered as 'the same' 
188  * if the types and the labels of the two tokens are 
189  * identical. Offset and length do not play any role 
190  * for 'sameness'. 
191  *
192  * @param {!xrx.token} token The token to check against.
193  * @return {!boolean}
194  */
195 xrx.token.prototype.sameAs = function(token) {
196   return this.typeOf(token.type()) && this.label_.sameAs(token.label());
197 };
198 
199 
200 
201 /**
202  * See function xrx.token.sameAs(token), but overloading 
203  * the type and the label separately.
204  *
205  * @param {!type} type The type to check against.
206  * @param {!label} label The label to check against.
207  * @return {!boolean}
208  */
209 xrx.token.prototype.compare = function(type, label) {
210   return this.typeOf(type) && this.label_.sameAs(label);
211 };
212 
213 
214 
215 /**
216  * Indicates whether the token appears before the overloaded
217  * token in document-order.
218  * 
219  * @param {!xrx.token} token The token to compare.
220  * @return {!boolean} 
221  */
222 xrx.token.prototype.isBefore = function(token) {
223   return this.label_.isBefore(token.label()) || 
224       (this.label_.sameAs(token.label()) && this.type_ < token.type());
225 };
226 
227 
228 
229 /**
230  * Indicates whether the token appears after the overloaded
231  * token in document-order.
232  * 
233  * @param {!xrx.token} token The token to compare.
234  * @return {!boolean} 
235  */
236 xrx.token.prototype.isAfter = function(token) {
237   return this.label_.isAfter(token.label()) || 
238       (this.label_.sameAs(token.label()) && this.type_ > token.type());
239 };
240 
241 
242 
243 /**
244  * A cumulative setter function for all private members.
245  *
246  * @param {!number} type The type of the token.
247  * @param {!xrx.label} label The label attached to the token.
248  * @param {?number} offset The offset relative to the start of the XML stream.
249  * @param {?number} length The number of characters in the XML stream.
250  */
251 xrx.token.prototype.set = function(type, label, offset, length) {
252 
253   this.type_ = type;
254   this.label_ = label;
255   this.offset_ = offset;
256   this.length_ = length;
257 };
258 
259 
260 
261 /**
262  * A combined setter and getter function. Optionally sets the
263  * type. Returns the type or the new type.
264  * 
265  * @param {?number} opt_type The value to be set (optional).
266  * @return {!number}
267  */
268 xrx.token.prototype.type = function(opt_type) {
269   opt_type !== undefined ? this.type_ = opt_type : null;
270   return this.type_;
271 };
272 
273 
274 
275 /**
276  * A combined setter and getter function. Optionally sets the
277  * label. Returns the label or the new label.
278  * 
279  * @param {?number} opt_label The value to be set (optional).
280  * @return {!number}
281  */
282 xrx.token.prototype.label = function(opt_label) {
283   opt_label !== undefined ? this.label_ = opt_label : null;
284   return this.label_;
285 };
286 
287 
288 
289 /**
290  * A combined setter and getter function. Optionally sets the
291  * offset. Returns the offset or the new offset.
292  * 
293  * @param {?number} opt_offset The value to be set (optional).
294  * @return {!number}
295  */
296 xrx.token.prototype.offset = function(opt_offset) {
297   opt_offset !== undefined ? this.offset_ = opt_offset : null;
298   return this.offset_;
299 };
300 
301 
302 
303 /**
304  * A combined setter and getter function. Optionally sets the
305  * length. Returns the length or the new length.
306  * 
307  * @param {?number} opt_length The value to be set (optional).
308  * @return {!number}
309  */
310 xrx.token.prototype.length = function(opt_length) {
311   opt_length !== undefined ? this.length_ = opt_length : null;
312   return this.length_;
313 };
314 
315 
316 
317 /**
318  * Returns the XML string of a token in a XML stream.
319  * 
320  * @param {!string} stream A XML stream.
321  * @return {!string} The token string.
322  */
323 xrx.token.prototype.xml = function(stream) {
324   return stream.substr(this.offset_, this.length_);
325 };
326