/*
* Copyright 2015-2017 WorldWind Contributors
*
* 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.
*/
define([
'./WktElements',
'./geom/WktObject',
'./WktType'
], function (WktElements,
WktObject,
WktType) {
/**
* Tokenizer, which parses the source texts into the meaningful tokens and then transforms them to the objects.
* Intended for the internal use only.
* @private
* @constructor
* @alias WktTokens
*/
var WktTokens = function (sourceText) {
this.sourceText = sourceText;
};
/**
* It returns correctly initialized objects. It is possible to retrieve relevant shapes from all WKT Objects.
* @return {WKTObject[]}
*/
WktTokens.prototype.objects = function () {
var currentObject;
var objects = [];
this.tokenize(this.sourceText).forEach(function (token) {
if(currentObject && currentObject.isFinished() || !currentObject) {
// It represents new object.
var value = token.value;
var founded = value.match('[M]?[Z]?$');
if(founded && founded.length > 0 && founded[0] != '') {
value = value.substring(0, value.length - founded.length);
}
currentObject = WktElements[value] && new WktElements[value]();
if(!currentObject) {
currentObject = new WktObject();
}
if(founded && founded.length > 0 && founded[0] != '') {
currentObject.setOptions(founded[0], currentObject);
}
objects.push(currentObject);
} else {
currentObject.handleToken(token);
}
});
return objects;
};
/**
* It continues character by character through the string. The empty spaces works always as delimiter.
* It begins with the information about the type. It is one of the WKT types with potential ending with M or Z
* I have the complete tokens containing the basic information we need.
* @private
* @return {String[]}
*/
WktTokens.prototype.tokenize = function (textToParse) {
this.currentPosition = 0;
var tokens = [];
for (; this.currentPosition < textToParse.length; this.currentPosition++) {
var c = textToParse.charAt(this.currentPosition);
if (c == '(') {
tokens.push({
type: WktType.TokenType.LEFT_PARENTHESIS
});
} else if (c == ',') {
tokens.push({
type: WktType.TokenType.COMMA
});
} else if (c == ')') {
tokens.push({
type: WktType.TokenType.RIGHT_PARENTHESIS
});
} else if (this.isAlpha(c)) {
var text = this.readText(textToParse);
tokens.push({
type: WktType.TokenType.TEXT,
value: text
});
} else if (this.isNumeric(c)) {
var numeric = this.readNumeric(textToParse);
tokens.push({
type: WktType.TokenType.NUMBER,
value: numeric
});
} else if (this.isWhiteSpace(c)) {
continue;
} else {
throw new Error('Invalid character: {{', c, '}}');
}
}
return tokens;
};
/**
* It returns true if the character is letter, regardless of whether uppercase or lowercase.
* @private
* @param c {String} character to test
* @return {boolean} True if it is lowercase or uppercase
*/
WktTokens.prototype.isAlpha = function (c) {
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
};
/**
* It returns true if the character is part of the number. It has certain limitations such as -1- is considered as
* a number
* @private
* @param c {String} character to test
* @return {boolean} True if it is either Number or - or .
*/
WktTokens.prototype.isNumeric = function (c) {
return c >= '0' && c <= '9' || c == '.' || c == '-';
};
/**
* It returns true if the character represents whitespace. It is mainly relevant as whitespaces are one of the
* delimiters
* @private
* @param c {String} character to test
* @return {boolean} True if it is any type of white space.
*/
WktTokens.prototype.isWhiteSpace = function (c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
};
/**
* It returns the next chunk of the String, which represents the text. Non alpha characters end the text.
* @private
* @param textToParse {String} The text to use in parsing.
* @return {string} The full chunk of text
*/
WktTokens.prototype.readText = function (textToParse) {
var text = '';
while (this.isAlpha(textToParse.charAt(this.currentPosition))) {
text += textToParse.charAt(this.currentPosition);
this.currentPosition++;
}
this.currentPosition--;
return text;
};
/**
* It returns the next chunk of the String, which represents the number. Non numeric characters end the text.
* @private
* @param textToParse {String} The text to use in parsing.
* @return {Number} The full chunk of number
*/
WktTokens.prototype.readNumeric = function (textToParse) {
var numeric = '';
while (this.isNumeric(textToParse.charAt(this.currentPosition))) {
numeric += textToParse.charAt(this.currentPosition);
this.currentPosition++;
}
this.currentPosition--;
return Number(numeric);
};
return WktTokens;
});