UNPKG

k2hr3-api

Version:

K2HR3 REST API is K2hdkc based Resource and Roles and policy Rules

1,236 lines 317 kB
"use strict"; /* * K2HR3 REST API * * Copyright 2017 Yahoo Japan Corporation. * * K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers * common management information for the cloud. * K2HR3 can dynamically manage information as "who", "what", "operate". * These are stored as roles, resources, policies in K2hdkc, and the * client system can dynamically read and modify these information. * * For the full copyright and license information, please view * the license file that was distributed with this source code. * * AUTHOR: Takeshi Nakatani * CREATE: Wed Jul 11 2017 * REVISION: * */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isK2hr3TemplateResult = exports.isValTypeTemplateVariablesMap = exports.isReplicationStatementObject = exports.isNotEmptyStatementsArray = exports.isSafeStatementsArray = exports.isSafeStatementObject = exports.K2hr3TemplateResult = void 0; const k2hr3apiutil_1 = __importDefault(require("./k2hr3apiutil")); const dbglogging_1 = __importDefault(require("./dbglogging")); //--------------------------------------------------------- // Keywords for K2HR3 Template Engine //--------------------------------------------------------- // Engine type Keywords const TEMPL_ENGINE_TYPE_PTN = '^{{#!(.*?)[ \t]*}}[\r\n]*'; // Regex = /^\{\{#\!(.*)[ \t]+\}\}[\r\n]*/ const TEMPL_K2HR3_TEMPLENGINE_KW = 'k2hr3template'; // This k2hr3template.js keywords // Template area Keywords const TEMPL_START_KW = '{{'; const TEMPL_END_KW = '}}'; const TEMPL_ESCAPE_START_KW = '{{{'; const TEMPL_ESCAPE_END_KW = '}}}'; // Special Keywords const TEMPL_SEMICOLON_KW = ';'; // ";" for sentence or "for" const TEMPL_COMMENT_KW = '#'; // Comment const TEMPL_PRINT_KW = '='; // Print command, this keyword after '{{' // Control syntax const TEMPL_IF_KW = 'if'; // if const TEMPL_ELIF_KW = 'elif'; // elif const TEMPL_ELSE_KW = 'else'; // else const TEMPL_ENDIF_KW = 'endif'; // endif const TEMPL_WHILE_KW = 'while'; // while const TEMPL_DO_KW = 'do'; // do(while) const TEMPL_DONE_KW = 'done'; // done const TEMPL_FOR_KW = 'for'; // for const TEMPL_FOREACH_KW = 'foreach'; // foreach const TEMPL_IN_KW = 'in'; // "in" for "foreach" const TEMPL_BREAK_KW = 'break'; // break const TEMPL_CONTINUE_KW = 'continue'; // continue // Conditions const TEMPL_AND_KW = '&&'; // Condition: AND const TEMPL_OR_KW = '||'; // Condition: OR const TEMPL_LESS_KW = '<'; // Condition: LESS THAN const TEMPL_GREAT_KW = '>'; // Condition: GREATER THAN const TEMPL_LESSEQ_KW = '<='; // Condition: LESS EQUAL THAN const TEMPL_GREATEQ_KW = '>='; // Condition: GREATER EQUAL THAN const TEMPL_EQUAL_KW = '=='; // Condition: EQUAL const TEMPL_NOTEQ_KW = '!='; // Condition: NOT EQUAL // One term operator const TEMPL_NOT_KW = '!'; // One term operator const TEMPL_INC_KW = '++'; // One term operator const TEMPL_DEC_KW = '--'; // One term operator // Binary operator const TEMPL_SET_KW = '='; // Binary operator const TEMPL_ADD_KW = '+'; // Binary operator const TEMPL_SUB_KW = '-'; // Binary operator const TEMPL_DIV_KW = '/'; // Binary operator const TEMPL_MUL_KW = '*'; // Binary operator const TEMPL_REM_KW = '%'; // Binary operator const TEMPL_AMP_KW = '&'; // Binary operator const TEMPL_VARTBAR_KW = '|'; // Binary operator const TEMPL_LSHIFT_KW = '<<'; // Binary operator const TEMPL_RSHIFT_KW = '>>'; // Binary operator // Array operator const TEMPL_SQUARE_START_KW = '['; // keywords for accessing to array member const TEMPL_SQUARE_END_KW = ']'; // const TEMPL_CURLY_START_KW = '{'; // keywords for accessing to object member const TEMPL_CURLY_END_KW = '}'; // // String area and escape for it const TEMPL_SINGLE_QUOTE_KW = '\''; // Separator for string value const TEMPL_DOUBLE_QUOTE_KW = '"'; // Separator for string value const TEMPL_ESCAPE_KW = '\\'; // escape // Variable area for K2hr3 template const TEMPL_VALUESEP_KW = '%'; // Separator for Variable // Length(size) property const TEMPL_LENGTH_KW = '.length'; // length property for array or object variable const TEMPL_SIZE_KW = '.size'; // const TEMPL_COUNT_KW = '.count'; // // Static values const TEMPL_NULL_KW = 'null'; // constant null const TEMPL_TRUE_KW = 'true'; // constant true const TEMPL_FALSE_KW = 'false'; // constant false // Radix for static number values const TEMPL_HEX_PREFIX_KW = '0x'; // hex(16) radix const TEMPL_HEX2_PREFIX_KW = 'x'; // hex(16) radix const TEMPL_OCT_PREFIX_KW = '0o'; // octal(8) radix const TEMPL_BIN_PREFIX_KW = '0b'; // binary(2) radix // // Calculation type using in Calculate Formula Class // const FORMULA_CALC_TYPE_UNKNOWN = -1; const FORMULA_CALC_TYPE_NOT = 0; const FORMULA_CALC_TYPE_INC = 1; const FORMULA_CALC_TYPE_DEC = 2; const FORMULA_CALC_TYPE_SET = 3; const FORMULA_CALC_TYPE_ADD = 4; const FORMULA_CALC_TYPE_SUB = 5; const FORMULA_CALC_TYPE_DIV = 6; const FORMULA_CALC_TYPE_MUL = 7; const FORMULA_CALC_TYPE_REM = 8; const FORMULA_CALC_TYPE_AMP = 9; const FORMULA_CALC_TYPE_VARTBAR = 10; const FORMULA_CALC_TYPE_LSHIFT = 11; const FORMULA_CALC_TYPE_RSHIFT = 12; // // Condition type using in Condition Formula Class // const FORMULA_COND_TYPE_UNKNOWN = -1; const FORMULA_COND_TYPE_AND = 100; const FORMULA_COND_TYPE_OR = 101; const FORMULA_COND_TYPE_LESS = 102; const FORMULA_COND_TYPE_GREAT = 103; const FORMULA_COND_TYPE_LESSEQ = 104; const FORMULA_COND_TYPE_GREATEQ = 105; const FORMULA_COND_TYPE_EQUAL = 106; const FORMULA_COND_TYPE_NOTEQ = 107; // // Utility for map // const TEMPL_BIN_OP_MAP = { [TEMPL_SUB_KW]: FORMULA_CALC_TYPE_SUB, [TEMPL_DIV_KW]: FORMULA_CALC_TYPE_DIV, [TEMPL_MUL_KW]: FORMULA_CALC_TYPE_MUL, [TEMPL_REM_KW]: FORMULA_CALC_TYPE_REM, [TEMPL_LSHIFT_KW]: FORMULA_CALC_TYPE_LSHIFT, [TEMPL_RSHIFT_KW]: FORMULA_CALC_TYPE_RSHIFT }; const FORMULA_CALAC_TYPE_STR_MAP = { [FORMULA_CALC_TYPE_SUB]: 'SUB(-)', [FORMULA_CALC_TYPE_DIV]: 'DIV(/)', [FORMULA_CALC_TYPE_MUL]: 'MUL(*)', [FORMULA_CALC_TYPE_REM]: 'REM(%)', [FORMULA_CALC_TYPE_LSHIFT]: 'LSHIFT(<<)', [FORMULA_CALC_TYPE_RSHIFT]: 'RSHIFT(>>)' }; const TEMPL_COND_TYPE_MAP = { [TEMPL_AND_KW]: FORMULA_COND_TYPE_AND, [TEMPL_OR_KW]: FORMULA_COND_TYPE_OR, [TEMPL_LESS_KW]: FORMULA_COND_TYPE_LESS, [TEMPL_GREAT_KW]: FORMULA_COND_TYPE_GREAT, [TEMPL_LESSEQ_KW]: FORMULA_COND_TYPE_LESSEQ, [TEMPL_GREATEQ_KW]: FORMULA_COND_TYPE_GREATEQ, [TEMPL_EQUAL_KW]: FORMULA_COND_TYPE_EQUAL, [TEMPL_NOTEQ_KW]: FORMULA_COND_TYPE_NOTEQ }; const FORMULA_COND_TYPE_STR_MAP = { [FORMULA_COND_TYPE_AND]: 'AND(&&)', [FORMULA_COND_TYPE_OR]: 'OR(||)', [FORMULA_COND_TYPE_LESS]: 'LESS(<)', [FORMULA_COND_TYPE_GREAT]: 'GREAT(>)', [FORMULA_COND_TYPE_LESSEQ]: 'LESSEQ(<=)', [FORMULA_COND_TYPE_GREATEQ]: 'GREATEQ(<=)', [FORMULA_COND_TYPE_EQUAL]: 'EQUAL(==)', [FORMULA_COND_TYPE_NOTEQ]: 'NOTEQ(!=)' }; //--------------------------------------------------------- // K2HR3 Template Engine Utility : Type chekcer //--------------------------------------------------------- const isSafeStatementObject = (val, is_check_units) => { if (!k2hr3apiutil_1.default.isPlainObject(val)) { return false; } if (!k2hr3apiutil_1.default.isBoolean(val.isStatement) || !k2hr3apiutil_1.default.isString(val.origString) || !k2hr3apiutil_1.default.isString(val.cvtString) || !k2hr3apiutil_1.default.isBoolean(val.isReplication)) { return false; } if (!k2hr3apiutil_1.default.isBoolean(is_check_units)) { is_check_units = true; } if (is_check_units && !k2hr3apiutil_1.default.isString2DArray(val.formUnits)) { return false; } return true; }; exports.isSafeStatementObject = isSafeStatementObject; const isSafeStatementsArray = (arr, is_check_units) => { if (!k2hr3apiutil_1.default.isBoolean(is_check_units)) { is_check_units = true; } return k2hr3apiutil_1.default.isArray(arr) && arr.every((element) => isSafeStatementObject(element, is_check_units)); }; exports.isSafeStatementsArray = isSafeStatementsArray; const isNotEmptyStatementsArray = (arr) => { return (isSafeStatementsArray(arr) && 0 !== arr.length); }; exports.isNotEmptyStatementsArray = isNotEmptyStatementsArray; const isReplicationStatementObject = (statementObj) => { if (!isSafeStatementObject(statementObj, false) || !statementObj.isReplication) { return false; } return true; }; exports.isReplicationStatementObject = isReplicationStatementObject; const isValTypeTemplateVariablesMap = (val) => { if (!k2hr3apiutil_1.default.isPlainObject(val)) { return false; } for (const [, value] of Object.entries(val)) { if (undefined === value) { return false; } } return true; }; exports.isValTypeTemplateVariablesMap = isValTypeTemplateVariablesMap; const isK2hr3TemplateResult = (val) => { return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof K2hr3TemplateResult); }; exports.isK2hr3TemplateResult = isK2hr3TemplateResult; const isBaseTemplateObject = (val) => { return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof BaseTemplateObject); }; const getSafeBaseTemplateObject = (val) => { return (isBaseTemplateObject(val) ? val : null); }; const isBaseFormulaObject = (val) => { return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof BaseFormulaObject); }; const isSyntaxFormulaObject = (val) => { return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof SyntaxFormulaObject); }; const isCalculateFormulaObject = (val) => { return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof CalculateFormulaObject); }; const isConditionFormulaObject = (val) => { return (k2hr3apiutil_1.default.isPlainObject(val) && val instanceof ConditionFormulaObject); }; //--------------------------------------------------------- // K2HR3 Template Engine Utility : Create K2HR3 Template Objects //--------------------------------------------------------- // Create one statement object tree and return top of tree object. // // return : following object // { // result: true/false // message: null or <error message string> // templObj: null or BaseTemplateObject object // } // // [NOTE] // If object tree is rechained(the parent was included into new object), // this returns result=true and templObj=null. // const createK2hr3TemplateObject = (statementsArray, parentObject) => { const resobj = { result: false, message: null, templObj: null }; if (!isSafeStatementsArray(statementsArray) || !isNotEmptyStatementsArray(statementsArray)) { resobj.result = true; resobj.templObj = null; dbglogging_1.default.elog('templateArray is empty or wrong : ' + JSON.stringify(statementsArray)); return resobj; } if (null !== parentObject && !isBaseTemplateObject(parentObject)) { resobj.result = false; resobj.message = 'parentObject is not BaseTemplateObject class or subclass : ' + JSON.stringify(parentObject); dbglogging_1.default.elog(resobj.message); return resobj; } let lastErrorString = ''; for (let cnt = 0; cnt < k2hr3StatementObjectList.length; ++cnt) { // create object const assembleObject = new k2hr3StatementObjectList[cnt](); // test assembling if (assembleObject.testAssemble(statementsArray)) { // try assemble if (null !== assembleObject.assemble(statementsArray, parentObject)) { let foundObject; for (foundObject = assembleObject; foundObject; foundObject = foundObject.getParentTemplObject()) { if (parentObject === foundObject.getParentTemplObject()) { // [NOTE] allow parentObject is null break; } } if (foundObject) { // found parent object in assembleObject's parent inheritance tree. // resobj.result = true; resobj.templObj = foundObject; return resobj; } else { // not found parent object in assembleObject's parent inheritance tree. // // This means that the parent of assembleObject points to parent object // rather than parentObject as analysis result, and assembleObject does // not exist in descendant tree of parentObject. // On this case, this function returns resobj.templObj = null, then // stop analyzing the statementArray for parentObject's child. // resobj.result = true; resobj.templObj = null; return resobj; } } else { // could not assemble or something error occurred. // then any error message is stocked. // if (k2hr3apiutil_1.default.isSafeString(lastErrorString.length)) { lastErrorString += ', '; } lastErrorString += '('; lastErrorString += assembleObject.getError() + ')'; } } else { // statement object is not a target } } // not matched resobj.result = false; resobj.message = 'any template class is not matched for templateArray : ' + lastErrorString; dbglogging_1.default.elog(resobj.message); return resobj; }; //--------------------------------------------------------- // K2HR3 Template Engine Utility : Check K2HR3 Template left //--------------------------------------------------------- // Check the first template statement's unit requires left // statements. // const REQUIRED_LEFT_NO = 0; const REQUIRED_LEFT_VARIABLE = 1; const REQUIRED_LEFT_CALCULATE = 2; const REQUIRED_LEFT_CONDITION = 4; const REQUIRED_LEFT_ALL = (REQUIRED_LEFT_VARIABLE | REQUIRED_LEFT_CALCULATE | REQUIRED_LEFT_CONDITION); const isRequireLeftTemplate = (statementsArray, arg_type) => { if (!k2hr3apiutil_1.default.isSafeNumber(arg_type)) { dbglogging_1.default.elog('arg_type parameter is wrong : ' + JSON.stringify(arg_type)); return false; } if (!isNotEmptyStatementsArray(statementsArray)) { // empty return false; } // first unit(string) const unit = statementsArray[0].formUnits[0][0]; let unit_type = REQUIRED_LEFT_NO; switch (unit) { case TEMPL_INC_KW: case TEMPL_DEC_KW: unit_type = REQUIRED_LEFT_VARIABLE; break; case TEMPL_AND_KW: case TEMPL_OR_KW: case TEMPL_LESS_KW: case TEMPL_GREAT_KW: case TEMPL_LESSEQ_KW: case TEMPL_GREATEQ_KW: case TEMPL_EQUAL_KW: case TEMPL_NOTEQ_KW: unit_type = REQUIRED_LEFT_ALL; break; case TEMPL_SET_KW: unit_type = REQUIRED_LEFT_VARIABLE; break; case TEMPL_ADD_KW: case TEMPL_SUB_KW: case TEMPL_DIV_KW: case TEMPL_MUL_KW: case TEMPL_REM_KW: unit_type = REQUIRED_LEFT_VARIABLE | REQUIRED_LEFT_CALCULATE; break; case TEMPL_AMP_KW: case TEMPL_VARTBAR_KW: unit_type = REQUIRED_LEFT_ALL; break; case TEMPL_LSHIFT_KW: case TEMPL_RSHIFT_KW: unit_type = REQUIRED_LEFT_VARIABLE; break; default: break; } return (0 !== (arg_type & unit_type)); }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Create/Modify Template Statement Objects //--------------------------------------------------------- const createEmptyK2hr3TemplateStatement = (isStatement, isReplication) => { const areaobj = { isStatement: (k2hr3apiutil_1.default.isBoolean(isStatement) ? isStatement : true), // default true origString: '', cvtString: '', isReplication: (k2hr3apiutil_1.default.isBoolean(isReplication) ? isReplication : true), // default true formUnits: [] // empty array[] }; return areaobj; }; const replicateK2hr3TemplateStatement = (statementObj) => { if (!isSafeStatementObject(statementObj, false)) { // not check units return createEmptyK2hr3TemplateStatement(); } const areaobj = createEmptyK2hr3TemplateStatement(statementObj.isStatement, true); if (k2hr3apiutil_1.default.isString2DArray(statementObj.formUnits)) { areaobj.formUnits = statementObj.formUnits; // reference } return areaobj; }; const createReplicatedK2hr3TemplateStatement = (isStatement, formUnits) => { const areaobj = createEmptyK2hr3TemplateStatement(isStatement, true); if (k2hr3apiutil_1.default.isNotEmptyArray(formUnits)) { areaobj.formUnits = formUnits; } return areaobj; }; const replaceK2hr3TemplateStatementFormUnits = (statementObj, formUnits) => { // Allowed empty formUnits and not check strict statementObj if (!isSafeStatementObject(statementObj) || !k2hr3apiutil_1.default.isString2DArray(formUnits)) { // check units return false; } statementObj.formUnits = formUnits; return true; }; const compressStatementsArray = (statementsArray) => { if (!k2hr3apiutil_1.default.isArray(statementsArray)) { return; } for (let cnt1 = 0; cnt1 < statementsArray.length;) { if (!isSafeStatementObject(statementsArray[cnt1], false)) { // something is wrong, then remove this statement object statementsArray.splice(cnt1, 1); } else { for (let cnt2 = 0; cnt2 < statementsArray[cnt1].formUnits.length;) { if (!k2hr3apiutil_1.default.isNotEmptyArray(statementsArray[cnt1].formUnits[cnt2])) { // units is empty, then remove this units statementsArray[cnt1].formUnits.splice(cnt2, 1); } else { for (let cnt3 = 0; cnt3 < statementsArray[cnt1].formUnits[cnt2].length;) { if (!k2hr3apiutil_1.default.isSafeString(statementsArray[cnt1].formUnits[cnt2][cnt3]) && '' !== statementsArray[cnt1].formUnits[cnt2][cnt3]) { // one unit is wrong, then remove this unit statementsArray[cnt1].formUnits[cnt2].splice(cnt3, 1); } else { ++cnt3; } } if (!k2hr3apiutil_1.default.isNotEmptyArray(statementsArray[cnt1].formUnits[cnt2])) { // finally units is empty, then remove this units statementsArray[cnt1].formUnits.splice(cnt2, 1); } else { ++cnt2; } } } if (!k2hr3apiutil_1.default.isNotEmptyArray(statementsArray[cnt1].formUnits)) { // finally units is empty, then remove this units statementsArray.splice(cnt1, 1); } else { ++cnt1; } } } }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Rollback Template Statement Objects //--------------------------------------------------------- // // rollback(insert) statement object to statements array // // is_add_first_pos : if true, insert statement object at first position in statementsArray. // if false, push bach units array data to statementsArray. // // return : returns statementsArray object // if input statementsArray is wrong, returned statementsArray is created in this function. // please take care for wrong input. // // [NOTE] // If statementObj is replication object, this rollbacks only formUnits in statementObj. // const rollbackStatementObjectToArray = (statementsArray, statementObj, is_add_first_pos) => { if (!k2hr3apiutil_1.default.isBoolean(is_add_first_pos)) { is_add_first_pos = true; } if (!isSafeStatementObject(statementObj, false)) { // not check units // statement object is something wrong // ---> nothing to do return statementsArray; } if (!isSafeStatementsArray(statementsArray, false)) { // not check units // statementsArray is something wrong // ---> overwrite it by statement object. statementsArray = [statementObj]; } else if (0 === statementsArray.length) { // statementsArray is empty // ---> push statement object. statementsArray.push(statementObj); } else { const pos = (is_add_first_pos ? 0 : (statementsArray.length - 1)); if (!isReplicationStatementObject(statementObj)) { // statement object is not replication if (isReplicationStatementObject(statementsArray[pos])) { // statementsArray[pos] is not replication if (is_add_first_pos) { // ---> insert statement object to top of statement array statementsArray.unshift(statementObj); } else { // ---> push back statement object to last of statement array statementsArray.push(statementObj); } } else { // statementsArray[pos] is replication, if (is_add_first_pos) { // ---> insert the statement object' formUnits to top of statementsArray[pos]'s one. // and replace statementsArray[pos] other member with statement object's one. for (let cnt = 0; cnt < statementsArray[pos].formUnits.length; ++cnt) { statementObj.formUnits.push(statementsArray[pos].formUnits[cnt]); } statementsArray.shift(); statementsArray.unshift(statementObj); } else { // ---> push back the statement object' formUnits to last of statementsArray[pos]'s one. // and replace statementsArray[pos] other member with statement object's one. for (let cnt = 0; cnt < statementsArray[pos].formUnits.length; ++cnt) { statementObj.formUnits.unshift(statementsArray[pos].formUnits[statementsArray[pos].formUnits.length - cnt - 1]); } statementsArray.splice(statementsArray.length - 1, 1); statementsArray.push(statementObj); } } } else { // statement object is replication if (isReplicationStatementObject(statementsArray[pos])) { // statementsArray[pos] is not replication if (is_add_first_pos) { // ---> insert statement object to top of statement array statementsArray.unshift(statementObj); } else { // ---> push back statement object to last of statement array statementsArray.push(statementObj); } } else { // statementsArray[pos] is replication if (is_add_first_pos) { // ---> insert the statement object' formUnits to top of statementsArray[pos]'s one. for (let cnt = 0; cnt < statementObj.formUnits.length; ++cnt) { statementsArray[pos].formUnits.unshift(statementObj.formUnits[statementObj.formUnits.length - cnt - 1]); } } else { // ---> push back the statement object' formUnits to last of statementsArray[pos]'s one. for (let cnt = 0; cnt < statementObj.formUnits.length; ++cnt) { statementsArray[pos].formUnits.push(statementObj.formUnits[cnt]); } } } } } return statementsArray; }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Parse Template Statement Objects //--------------------------------------------------------- // // Parse k2hr3 template to statement areas and minimum formula units. // // templString : The string is all of template string // result : Statement object Array // const parseK2hr3Template = (templString) => { // parse template to statement areas const resobj = parseK2hr3TemplateToStatements(templString); if (!isSafeStatementsArray(resobj)) { dbglogging_1.default.dlog('parsed template string result is null.'); return null; } const objarr = resobj; // parse each statement area to formula units for (let cnt = 0; k2hr3apiutil_1.default.isNotEmptyArray(objarr) && cnt < objarr.length; ++cnt) { if (!k2hr3apiutil_1.default.isSafeEntity(objarr[cnt])) { // why? objarr.splice(cnt, 1); if (0 === cnt) { cnt = -1; } else { --cnt; } continue; } let formUnits; if (objarr[cnt].isStatement) { // in statement area formUnits = parseK2hr3TemplateForStatements(objarr[cnt].cvtString); if (null === formUnits || !k2hr3apiutil_1.default.isString2DArray(formUnits)) { // empty sentence, so remove this element. objarr.splice(cnt, 1); if (0 === cnt) { cnt = -1; } else { --cnt; } continue; } } else { // not statement area formUnits = [[objarr[cnt].cvtString]]; } objarr[cnt].formUnits = formUnits; } if (!k2hr3apiutil_1.default.isNotEmptyArray(objarr)) { dbglogging_1.default.dlog('parsed template string result is null.'); return null; } //r3logger.dlog('parsed template string result is : ' + r3logger.dump(objarr)); return objarr; }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Parse Template String to Template Statement Objects //--------------------------------------------------------- // // Parse input string which is k2hr3 template to statement areas array. // Each area is statement or not statement area. // // templString : The string is all of template string // result : Following object array, return empty array when error. // [ // { : Each template area(statement area / not statement area) // "isStatement": true/false : This is true when the template area is statement({{...}}). // "origString": <string> : original string // "cvtString": <string> : converted string(escaped keyword and trimmed when statement area includes formula) // }, // ... // ] // const parseK2hr3TemplateToStatements = (templString) => { if (!k2hr3apiutil_1.default.isSafeString(templString)) { return null; } let inputString = templString; // parse const resobj = []; let tmpl_cvtstr = ''; let tmpl_origin = ''; let keyword = TEMPL_START_KW; let escword = TEMPL_ESCAPE_START_KW; let oescword = TEMPL_ESCAPE_END_KW; // not keyword's escape let templ_area = false; while (k2hr3apiutil_1.default.isSafeString(inputString) && 0 < inputString.length) { // each const key_pos = inputString.indexOf(keyword); // '{{' or '}}' const esc_pos = inputString.indexOf(escword); // '{{{' or '}}}' const oesc_pos = inputString.indexOf(oescword); // '}}}' or '{{{' if (-1 !== oesc_pos && (-1 === key_pos || oesc_pos < key_pos)) { // found not keyword's escaped words before keyword tmpl_origin += inputString.substr(0, oesc_pos + 3); tmpl_cvtstr += inputString.substr(0, oesc_pos + 2); // converts '{{{'('}}}') to '{{'('}}') and appends it to end of tmpl_cvtstr. inputString = inputString.substr(oesc_pos + 3); // after key words('{{{' or '}}}') } else { if (-1 != esc_pos && esc_pos === key_pos) { // found escaped key words tmpl_origin += inputString.substr(0, esc_pos + 3); tmpl_cvtstr += inputString.substr(0, esc_pos + 2); // converts '{{{'('}}}') to '{{'('}}') and appends it to end of tmpl_cvtstr. inputString = inputString.substr(esc_pos + 3); // after key words('{{{' or '}}}') } else if (-1 != key_pos) { // found key words if (templ_area) { tmpl_origin += inputString.substr(0, key_pos + 2); // original string with '}}' tmpl_cvtstr += inputString.substr(0, key_pos); // converted string without '}}' // make object const oneobj = { isStatement: true, origString: tmpl_origin, cvtString: tmpl_cvtstr.trim(), // trimmed string isReplication: false, formUnits: [] }; // add if (k2hr3apiutil_1.default.isSafeString(oneobj.origString)) { resobj.push(oneobj); } // set next templ_area = false; keyword = TEMPL_START_KW; escword = TEMPL_ESCAPE_START_KW; oescword = TEMPL_ESCAPE_END_KW; tmpl_origin = ''; tmpl_cvtstr = ''; inputString = inputString.substr(key_pos + 2); // after key words('{{') } else { tmpl_origin += inputString.substr(0, key_pos); // original string without '{{' tmpl_cvtstr += inputString.substr(0, key_pos); // converted string without '{{' // make object const oneobj = { isStatement: false, origString: tmpl_origin, cvtString: tmpl_cvtstr, // not trimmed string isReplication: false, formUnits: [] }; // add if (k2hr3apiutil_1.default.isSafeString(oneobj.origString)) { resobj.push(oneobj); } // set next templ_area = true; keyword = TEMPL_END_KW; escword = TEMPL_ESCAPE_END_KW; oescword = TEMPL_ESCAPE_START_KW; tmpl_origin = TEMPL_START_KW; // start original string with '{{' tmpl_cvtstr = ''; inputString = inputString.substr(key_pos + 2); // after key words('}}') } } else { // not found keywords tmpl_origin += inputString; // add rest string to original string tmpl_cvtstr += inputString; // add rest string to converted string const oneobj = { isStatement: (templ_area ? true : false), origString: tmpl_origin, cvtString: (templ_area ? tmpl_cvtstr.trim() : tmpl_cvtstr), isReplication: false, formUnits: [] }; // add if (k2hr3apiutil_1.default.isSafeString(oneobj.origString)) { resobj.push(oneobj); } break; } } } return resobj; }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Parse Template String to Minimum Template Statement Objects //--------------------------------------------------------- // // Parse input string which is rough cutting statement area to minimum statement array. // Each minimum statement has formula units array which elements are minimum formula string. // Formula unit string is separated by keywords. // // target : the string in template area which is from '{{' to '}}'. // result : The array has formula units array which is separated by ':'. // The one sentence array member is array which member is // minimum opcode/operand unit. // [ // [ : One sentence(separated by ';') // "unit string", : One unit(separated by keywords...) // "unit string", // ... // ], // ... // ] // // [NOTE] // About comment and print statement which are special. // If target starts comment keyword('{{#'), this returns [ ["#", "...."] ] array. // If target starts print keyword('{{='), this returns [ ["=", "...."], ... ] array. // const parseK2hr3TemplateForStatements = (target, is_print_statement) => { if (!k2hr3apiutil_1.default.isSafeString(target)) { return null; } const inputTarget = target; const is_print = (!k2hr3apiutil_1.default.isBoolean(is_print_statement) ? false : is_print_statement); let mainres = []; let subres = []; let one_part = ''; // check comment/print line at first if (0 === inputTarget.indexOf(TEMPL_COMMENT_KW)) { // found comment keyword at first character position one_part = inputTarget.substr(1).trim(); subres.push(TEMPL_COMMENT_KW); if (k2hr3apiutil_1.default.isSafeString(one_part)) { subres.push(one_part); } mainres.push(subres); return mainres; } else if (!is_print && 0 === inputTarget.indexOf(TEMPL_PRINT_KW)) { // found print keyword at first character position one_part = inputTarget.substr(1).trim(); // reentrant for analyzing after statement string const tmpres = parseK2hr3TemplateForStatements(one_part, true); if (null === tmpres || !k2hr3apiutil_1.default.isNotEmptyArray(tmpres)) { // mainres array is empty, then make static for print(maybe this is error at assembling or executing) subres.push(TEMPL_PRINT_KW); mainres = []; mainres.push(subres); } else if (!k2hr3apiutil_1.default.isNotEmptyArray(tmpres[0])) { // first array in mainres is empty, then make static for print(maybe this is error at assembling or executing) subres.push(TEMPL_PRINT_KW); mainres[0] = subres; } else { // insert print keyword into first of array mainres = tmpres; mainres[0].unshift(TEMPL_PRINT_KW); } return mainres; } // parse to statement string let is_squate = false; let is_dquate = false; let is_escape = false; for (let cnt = 0; cnt < inputTarget.length; ++cnt) { // check ';', '\'', '\"', '\\', '\s' if (TEMPL_SEMICOLON_KW === inputTarget[cnt]) { // ';' if (is_escape) { one_part += TEMPL_ESCAPE_KW; } is_squate = false; is_dquate = false; is_escape = false; if (0 < one_part.length) { subres.push(one_part); // finish one word one_part = ''; } if (0 < subres.length) { mainres.push(subres); // finish statement subres = []; } } else if (TEMPL_SINGLE_QUOTE_KW === inputTarget[cnt]) { // '\'' if (is_escape) { is_escape = false; one_part += TEMPL_ESCAPE_KW; one_part += inputTarget[cnt]; } else if (is_squate) { is_squate = false; one_part += inputTarget[cnt]; subres.push(one_part); // finish one word one_part = ''; } else if (is_dquate) { // nothing to do... one_part += inputTarget[cnt]; } else { is_squate = true; if (0 < one_part.length) { subres.push(one_part); // finish one word } one_part = inputTarget[cnt]; } } else if (TEMPL_DOUBLE_QUOTE_KW === inputTarget[cnt]) { // '\"' if (is_escape) { is_escape = false; one_part += TEMPL_ESCAPE_KW; one_part += inputTarget[cnt]; } else if (is_dquate) { is_dquate = false; one_part += inputTarget[cnt]; subres.push(one_part); // finish one word one_part = ''; } else if (is_squate) { // nothing to do... one_part += inputTarget[cnt]; } else { is_dquate = true; if (0 < one_part.length) { subres.push(one_part); // finish one word } one_part = inputTarget[cnt]; } } else if (TEMPL_ESCAPE_KW === inputTarget[cnt]) { // '\\' if (is_escape) { is_escape = false; one_part += TEMPL_ESCAPE_KW; one_part += inputTarget[cnt]; } else { is_escape = true; } } else if (' ' === inputTarget[cnt] || '\t' === inputTarget[cnt] || '\r' === inputTarget[cnt] || '\n' === inputTarget[cnt]) { // === \s if (is_escape) { is_escape = false; one_part += TEMPL_ESCAPE_KW; subres.push(one_part); // finish one word one_part = ''; } else if (is_dquate || is_squate) { one_part += inputTarget[cnt]; } else if (0 === one_part.length) { // nothing to do } else { subres.push(one_part); // finish one word one_part = ''; } } else { // another char if (is_escape) { is_escape = false; one_part += TEMPL_ESCAPE_KW; } one_part += inputTarget[cnt]; } } // rest if (is_escape) { one_part += TEMPL_ESCAPE_KW; } if (0 < one_part.length) { subres.push(one_part); // finish one word } if (0 < subres.length) { mainres.push(subres); // finish statement } // next parse units(minimum formula units) const tmpres = parseK2hr3TemplateStatementToFomulaUnits(mainres); return tmpres; }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Parsing Template Formula String to Minimum Template Statement Units //--------------------------------------------------------- // // This parses double array which is parsed by parseK2hr3TemplateForStatements // to minimum formula units. // After this parsing, the result double array is separated minimum formula units // array divided into instruction units. // // mainres : input array which elements are each statement area. // [ // [ : array for statement separated by ';' // "unit string", : unit statement string separated by ';' or "string"(which is statement area by '\'' or '\"') // ... // ] // ] // // result : parse input unit array by keywords // [ // [ : array for statement separated by ';' // "unit string", : One unit formula string separated by ';' or "string" or any keywords // ... // ] // ] // const parseK2hr3TemplateStatementToFomulaUnits = (mainres) => { if (!k2hr3apiutil_1.default.isString2DArray(mainres) || !k2hr3apiutil_1.default.isNotEmptyArray(mainres)) { return mainres; } const tmpres = mainres; for (let cnt = 0; cnt < tmpres.length; ++cnt) { if (!k2hr3apiutil_1.default.isNotEmptyArray(tmpres[cnt])) { // why? tmpres.splice(cnt, 1); if (0 === cnt) { cnt = -1; } else { --cnt; } continue; } // parse subres to some units const subres = tmpres[cnt]; for (let cnt2 = 0; cnt2 < subres.length; ++cnt2) { // parse string to minimum unit array const subres_array = parseK2hr3TemplateStatementToMinimumUnits(subres[cnt2]); if (!k2hr3apiutil_1.default.isNotEmptyArray(subres_array)) { // why? subres.splice(cnt2, 1); if (0 === cnt2) { cnt2 = -1; } else { --cnt2; } } else if (1 < subres_array.length) { // replace pos to array subres.splice(cnt2, 1); for (let cnt3 = 0; cnt3 < subres_array.length; ++cnt3) { subres.splice(cnt2, 0, subres_array[subres_array.length - cnt3 - 1]); } cnt2 += subres_array.length - 1; } else { // nothing to do } } // check empty subres if (!k2hr3apiutil_1.default.isStringArray(subres) || !k2hr3apiutil_1.default.isNotEmptyArray(subres)) { // tmpres[cnt] has empty subres array, then remove cnt position array. tmpres.splice(cnt, 1); if (0 === cnt) { cnt = -1; } else { --cnt; } } } // [NOTE] // if units array(subres) is empty, it is removed from tmpres. // if there is no units in tmpres, tmpres is empty array. // return tmpres; }; //--------------------------------------------------------- // K2HR3 Template Engine Utility // : Parsing Template String Including Some Formula to Minimum Template Statement Units //--------------------------------------------------------- // // If it starts '\'' or '\"', it means "string" area which maybe include ';' and '\s'. // Then this method does not check when the target is "string" and '\' character, // because it effects only "string". // The input string must not include basically ';' and '\s'. // // result : null or following array // [ // "unit string", : One unit in formula(separate keywords...) // ... // ] // const parseK2hr3TemplateStatementToMinimumUnits = (target) => { if (!k2hr3apiutil_1.default.isSafeString(target)) { return []; } const inputTarget = target; const resarr = []; if (TEMPL_SINGLE_QUOTE_KW === inputTarget[0] || TEMPL_DOUBLE_QUOTE_KW === inputTarget[0]) { // inputTarget is '...' or "..." string, then this can not parse. resarr.push(inputTarget); return resarr; } let one_part = ''; for (let cnt = 0; cnt < inputTarget.length; ++cnt) { if (TEMPL_VALUESEP_KW === inputTarget[cnt]) { // '%' (== TEMPL_REM_KW) // [NOTE] // Space characters are already parsed before calling this function. // if (inputTarget.length <= (cnt + 1)) { // inputTarget[cnt + 1] === \s or null, then inputTarget[cnt] is TEMPL_REM_KW if (0 !== one_part.length) { resarr.push(one_part); // set stocked string before percent } one_part = TEMPL_REM_KW; resarr.push(one_part); // set percent one_part = ''; } else { const end_percent_pos = inputTarget.substr(cnt + 1).indexOf(TEMPL_VALUESEP_KW); if (-1 === end_percent_pos) { // not found end(2'nd) percent/or \r(\n) found before percent, then inputTarget[cnt] is TEMPL_REM_KW if (0 !== one_part.length) { resarr.push(one_part); // set stocked string before percent } one_part = TEMPL_REM_KW; resarr.push(one_part); // set percent one_part = ''; } else { // found end(2'nd) percent, then these are TEMPL_VALUESEP_KW if (0 !== one_part.length) { resarr.push(one_part); // set stocked string before percent } one_part = TEMPL_REM_KW; one_part += inputTarget.substr(cnt + 1).substr(0, end_percent_pos); one_part += TEMPL_REM_KW; resarr.push(one_part); // set %...%(TEMPL_VALUESEP_KW area) one_part = ''; cnt += end_percent_pos + 1; // cnt is set end of TEMPL_VALUESEP_KW } } } else if (TEMPL_SQUARE_START_KW === inputTarget[cnt]) { // '[' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } resarr.push(TEMPL_SQUARE_START_KW); } else if (TEMPL_SQUARE_END_KW === inputTarget[cnt]) { // ']' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } resarr.push(TEMPL_SQUARE_END_KW); } else if (TEMPL_CURLY_START_KW === inputTarget[cnt]) { // '{' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } resarr.push(TEMPL_CURLY_START_KW); } else if (TEMPL_CURLY_END_KW === inputTarget[cnt]) { // '}' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } resarr.push(TEMPL_CURLY_END_KW); } else if (TEMPL_MUL_KW === inputTarget[cnt]) { // '*' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } resarr.push(TEMPL_MUL_KW); } else if (TEMPL_DIV_KW === inputTarget[cnt]) { // '/' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } resarr.push(TEMPL_DIV_KW); } else if (TEMPL_NOT_KW === inputTarget[cnt]) { // '!' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_SET_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_NOTEQ_KW); // '!=' } else { resarr.push(TEMPL_NOT_KW); // '!' } } else if (TEMPL_SET_KW === inputTarget[cnt]) { // '=' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_SET_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_EQUAL_KW); // '==' } else { resarr.push(TEMPL_SET_KW); // '=' } } else if (TEMPL_ADD_KW === inputTarget[cnt]) { // '+' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_ADD_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_INC_KW); // '++' } else { resarr.push(TEMPL_ADD_KW); // '+' } } else if (TEMPL_SUB_KW === inputTarget[cnt]) { // '-' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_SUB_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_DEC_KW); // '--' } else { resarr.push(TEMPL_SUB_KW); // '-' } } else if (TEMPL_AMP_KW === inputTarget[cnt]) { // '&' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_AMP_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_AND_KW); // '&&' } else { resarr.push(TEMPL_AMP_KW); // '&' } } else if (TEMPL_VARTBAR_KW === inputTarget[cnt]) { // '|' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_VARTBAR_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_OR_KW); // '||' } else { resarr.push(TEMPL_VARTBAR_KW); // '|' } } else if (TEMPL_LESS_KW === inputTarget[cnt]) { // '<' if (0 !== one_part.length) { resarr.push(one_part); one_part = ''; } if ((cnt + 1) < inputTarget.length && TEMPL_SET_KW === inputTarget[cnt + 1]) { ++cnt; resarr.push(TEMPL_LESS