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