blob: c9b6b5bf727dc6ed84c2c2b36ae7f29ab0f3aa62 [file] [log] [blame]
// Copyright 2009 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Error class for BiDi checks.
*/
goog.provide('bidichecker.Error');
goog.require('bidichecker.HighlightableArea');
goog.require('bidichecker.utils');
goog.require('goog.array');
goog.require('goog.json');
goog.require('goog.string.StringBuffer');
/**
* Class representing a BiDi error.
* <p>This constructor can be called in two ways: 1. To create a new object,
* pass it typed parameter values (string/number), and 2. To reconstitute an
* object from serialization, pass it a bare Javascript object with its fields
* already initialized. In the first case, a new 'id' value will be assigned;
* in the second case, it should already be present in the bare object.
* @param {string|Object} typeOrRawObject If a string, the error type
* description (human readable). If an object, should contain the error's
* required data fields - id, type, severity - and, optionally: atText,
* locationDescription, precededByText and followedByText.
* @param {number=} opt_severity Error severity level: 1 is highest, 4 is
* lowest. Required if {@code typeOrRawObject} is a string.
* @param {bidichecker.HighlightableArea=} opt_highlightableArea The
* highlightable area of the DOM at the error's location. Required if {@code
* typeOrRawObject} is a string, except for testing.
* @param {string=} opt_atText Text contents where the error manifests on the
* page. Optional.
* @constructor
*/
bidichecker.Error = function(typeOrRawObject, opt_severity,
opt_highlightableArea, opt_atText) {
if (typeof typeOrRawObject == 'object') {
// Reconstitute an error object from the fields of a deserialized raw
// object.
var object = typeOrRawObject;
/** @const */ var fields = ['id', 'type', 'severity', 'atText',
'locationDescription', 'precededByText',
'followedByText'];
/** @const */ var requiredFields = ['id', 'type', 'severity'];
for (var i = 0; i < fields.length; ++i) {
var field = fields[i];
this[field] = field in object ? object[field] : null;
if (this[field] == null &&
goog.array.indexOf(requiredFields, field) >= 0) {
throw "Required field '" + field + "' not found in bidichecker.Error.";
}
}
return;
}
// Create a new error object from scratch.
//
// Since bidichecker.Error objects are serialized for output to JSON, the
// object fields are always accessed via strings, not dot-fields, to keep
// the JSCompiler from obfuscating them. To ensure the uniformity of this
// access pattern and reduce the likelihood of bugs, getters and setters have
// been provided for all relevant fields.
if (opt_severity == undefined) {
throw "Required parameter 'opt_severity' not found in bidichecker.Error.";
}
/**
* ID number for this error, globally unique during this session.
* @type {number}
* @private
*/
this['id'] = bidichecker.Error.nextErrorId_++;
/**
* Textual description of the error type.
* @type {string}
* @private
*/
this['type'] = typeOrRawObject;
/**
* Severity level of the error.
* @type {number}
* @private
*/
this['severity'] = opt_severity;
this.setHighlightableArea(opt_highlightableArea || null);
/**
* Text where the error occurs on the page, if applicable.
* @type {?string}
* @private
*/
this['atText'] = opt_atText || null;
};
/**
* The text preceding the error's location in the DOM.
* @type {?string}
* @private
*/
bidichecker.Error.prototype['precededByText'] = null;
/**
* The text following the error's location in the DOM.
* @type {?string}
* @private
*/
bidichecker.Error.prototype['followedByText'] = null;
/**
* Textual description of the error's location in the DOM, if applicable.
* @type {?string}
* @private
*/
bidichecker.Error.prototype['locationDescription'] = null;
/**
* Human-readable description of the error message, used only for serialization
* to the JSON interface. This field is always null except during serialization.
* @type {?string}
* @private
*/
bidichecker.Error.prototype['asString'] = null;
/**
* Next unallocated error ID number.
* @type {number}
* @private
*/
bidichecker.Error.nextErrorId_ = 0;
/**
* Highlightable areas of the DOM for errors in the current session. Indexed by
* error ID numbers. These are not stored in the error objects themselves
* because 1) they are not easily serializable to/from JSON, and 2) they need
* to remain accessible between a call to {@code checkPage()} and a subsequent
* call to {@code runGui()}.
* @type {!Array.<bidichecker.HighlightableArea>}
* @private
*/
bidichecker.Error.highlightableAreas_ = [];
/** @return {string} The error type. */
bidichecker.Error.prototype.getType = function() {
return this['type'];
};
/** @return {number} The error severity level. */
bidichecker.Error.prototype.getSeverity = function() {
return this['severity'];
};
/** @return {?string} The text at the error's location in the DOM. */
bidichecker.Error.prototype.getAtText = function() {
return this['atText'];
};
/** @return {?string} The text preceding the error's location in the DOM. */
bidichecker.Error.prototype.getPrecededByText = function() {
return this['precededByText'];
};
/** @return {?string} The text following the error's location in the DOM. */
bidichecker.Error.prototype.getFollowedByText = function() {
return this['followedByText'];
};
/**
* @return {?string} Textual description of the error location in the DOM.
*/
bidichecker.Error.prototype.getLocationDescription = function() {
return this['locationDescription'];
};
/**
* Sets the error severity level.
* @param {number} value The severity level.
*/
bidichecker.Error.prototype.setSeverity = function(value) {
this['severity'] = value;
};
/**
* Sets the text preceding the error's location in the DOM.
* @param {string} text The preceding text.
*/
bidichecker.Error.prototype.setPrecededByText = function(text) {
this['precededByText'] = text;
};
/**
* Sets the text following the error's location in the DOM.
* @param {string} text The folowing text.
*/
bidichecker.Error.prototype.setFollowedByText = function(text) {
this['followedByText'] = text;
};
/**
* Sets the textual description of the error location in the DOM.
* @param {string} text The description.
*/
bidichecker.Error.prototype.setLocationDescription = function(text) {
this['locationDescription'] = text;
};
/**
* Sets the highlightable DOM area for the error.
* @param {bidichecker.HighlightableArea} highlightableArea The area.
*/
bidichecker.Error.prototype.setHighlightableArea = function(highlightableArea) {
bidichecker.Error.highlightableAreas_[this['id']] = highlightableArea;
};
/**
* @return {bidichecker.HighlightableArea} The highlightable DOM area.
*/
bidichecker.Error.prototype.getHighlightableArea = function() {
return bidichecker.Error.highlightableAreas_[this['id']] || null;
};
/**
* Empties the cache of highlightable error areas. After this is called, {@code
* getHighlightableArea()} will no longer work for previously-created error
* objects.
*/
bidichecker.Error.clearHighlightableAreas = function() {
bidichecker.Error.highlightableAreas_ = [];
bidichecker.Error.nextErrorId_ = 0;
};
/**
* @return {string} Human-readable error description.
* @override
*/
bidichecker.Error.prototype.toString = function() {
var buffer = new goog.string.StringBuffer(
'[', this.getSeverity().toString(), '] ', this.getType());
var value;
if ((value = this.getAtText())) {
buffer.append(': ', bidichecker.utils.singleQuoteString(value));
}
if ((value = this.getPrecededByText())) {
buffer.append(' preceded by ', bidichecker.utils.singleQuoteString(value));
}
if ((value = this.getFollowedByText())) {
buffer.append(' followed by ', bidichecker.utils.singleQuoteString(value));
}
if ((value = this.getLocationDescription())) {
buffer.append(' in ', value);
}
return buffer.toString();
};
/**
* Serialize an array of errors to JSON, adding an 'asString' field containing
* a human-readable error message.
* @param {!Array.<!bidichecker.Error>} errors Array of error objects.
* @return {string} JSON-format string representing the errors.
*/
bidichecker.Error.serialize = function(errors) {
for (var i = 0; i < errors.length; ++i) {
var error = errors[i];
error['asString'] = error.toString();
}
return goog.json.serialize(errors);
};