/*
* StringMapper.js - ilib string mapper class definition
*
* Copyright © 2014-2015, 2018, JEDLSoft
*
* 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.
*/
var ilib = require("../index.js");
var Utils = require("./Utils.js");
var Locale = require("./Locale.js");
var IString = require("./IString.js");
/**
* @class
* Create a new string mapper instance. <p>
*
* The options may contain any of the following properties:
*
* <ul>
* <li><i>locale</i> - locale to use when loading the mapper. Some maps are
* locale-dependent, and this locale selects the right one. Default if this is
* not specified is the current locale.
*
* <li><i>name</i> - the name of the map to load
*
* <li><i>mapFunction</i> - specify an algorithmic mapping function to use if
* the mapper does not have an explicit mapping for a character. The idea is
* to save disk and memory when algorithmic mapping can be done for some of
* the characters, but not others. The exceptions can go into the json file,
* and the characters that conform to the rule can be mapped algorithmically.
* The map function should take a string containing 1 character as a parameter
* and should return a string containing one or more characters. If the
* character is outside of the range that can be mapped, it should be returned
* unchanged.
*
* <li><i>onLoad</i> - a callback function to call when this object is fully
* loaded. When the onLoad option is given, this object will attempt to
* load any missing locale data using the ilib loader callback.
* When the constructor is done (even if the data is already preassembled), the
* onLoad function is called with the current instance as a parameter, so this
* callback can be used with preassembled or dynamic loading or a mix of the two.
*
* <li><i>sync</i> - tell whether to load any missing locale data synchronously or
* asynchronously. If this option is given as "false", then the "onLoad"
* callback must be given, as the instance returned from this constructor will
* not be usable for a while.
*
* <li><i>loadParams</i> - an object containing parameters to pass to the
* loader callback function when locale data is missing. The parameters are not
* interpretted or modified in any way. They are simply passed along. The object
* may contain any property/value pairs as long as the calling code is in
* agreement with the loader callback function as to what those parameters mean.
* </ul>
*
*
* @constructor
* @param {Object=} options options to initialize this string mapper
*/
var StringMapper = function (options) {
var sync = true,
loadParams = undefined;
this.locale = new Locale();
this.mapData = {};
this.mapFunction = undefined;
if (options) {
if (typeof(options.locale) !== 'undefined') {
this.locale = (typeof(options.locale) === 'string') ? new Locale(options.locale) : options.locale;
}
if (typeof(options.name) !== 'undefined') {
this.name = options.name;
}
if (typeof(options.mapFunction) === 'function') {
this.mapFunction = options.mapFunction;
}
if (typeof(options.sync) !== 'undefined') {
sync = (options.sync === true);
}
if (typeof(options.loadParams) !== 'undefined') {
loadParams = options.loadParams;
}
}
Utils.loadData({
object: "StringMapper",
locale: this.locale,
name: this.name + ".json",
sync: sync,
loadParams: loadParams,
callback: ilib.bind(this, function (map) {
this.mapData = map || {};
if (options && typeof(options.onLoad) === 'function') {
options.onLoad(this);
}
})
});
};
StringMapper.prototype = {
/**
* Return the locale that this mapper was constructed.
* @return {Locale} the locale instance
*/
getLocale: function () {
return this.locale;
},
getName: function () {
return this.name;
},
/**
* Map a string using the mapping defined in the constructor. This method
* iterates through all characters in the string and maps them one-by-one.
* If a particular character has a mapping, the mapping result will be
* added to the output. If there is no mapping, but there is a mapFunction
* defined, the mapFunction results will be added to the result. Otherwise,
* the original character from the input string will be added to the result.
*
* @param {string|IString|undefined} string
* @return {string|IString|undefined}
*/
map: function (string) {
var input;
if (!string) {
return string;
}
if (typeof(string) === 'string') {
input = new IString(string);
} else {
input = string.toString();
}
var ret = "";
var it = input.charIterator();
var c;
while (it.hasNext()) {
c = it.next();
if (this.mapData && this.mapData[c]) {
ret += this.mapData[c];
} else if (this.mapFunction) {
ret += this.mapFunction(c);
} else {
ret += c;
}
}
return ret;
}
};
module.exports = StringMapper;
Source