all files / es6/ scope-manager.js

100% Statements 47/47
100% Branches 22/22
100% Functions 8/8
100% Lines 46/46
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88        382× 382× 382×     66× 66×     121× 112×       66×     66× 66× 66×   59× 48× 104× 104×   48×   11×           333× 333× 333× 333× 333× 333× 333×                   332× 324×     112×         112× 112× 112× 112×       270× 270× 270× 270×      
"use strict";
const Errors = require("./errors");
 
// This class responsibility is to manage the scope
const ScopeManager = class ScopeManager {
	constructor(options) {
		this.scopePath = options.scopePath;
		this.scopeList = options.scopeList;
		this.parser = options.parser;
	}
	loopOver(tag, callback, inverted) {
		inverted = inverted || false;
		return this.loopOverValue(this.getValue(tag), callback, inverted);
	}
	functorIfInverted(inverted, functor, value) {
		if (inverted) {
			functor(value);
		}
	}
	isValueFalsy(value, type) {
		return (value == null || !value || (type === "[object Array]" && value.length === 0));
	}
	loopOverValue(value, functor, inverted) {
		const type = Object.prototype.toString.call(value);
		const currentValue = this.scopeList[this.num];
		if (this.isValueFalsy(value, type)) {
			return this.functorIfInverted(inverted, functor, currentValue);
		}
		if (type === "[object Array]") {
			for (let i = 0, scope; i < value.length; i++) {
				scope = value[i];
				this.functorIfInverted(!inverted, functor, scope);
			}
			return;
		}
		if (type === "[object Object]") {
			return this.functorIfInverted(!inverted, functor, value);
		}
		if (value === true) {
			return this.functorIfInverted(!inverted, functor, currentValue);
		}
	}
	getValue(tag, num) {
		// search in the scopes (in reverse order) and keep the first defined value
		this.num = num == null ? (this.scopeList.length - 1) : num;
		let err;
		let result;
		const scope = this.scopeList[this.num];
		const parser = this.parser(tag);
		try {
			result = parser.get(scope, {num: this.num, scopeList: this.scopeList});
		}
		catch (error) {
			err = new Errors.XTScopeParserError("Scope parser execution failed");
			err.properties = {
				id: "scopeparser_execution_failed",
				explanation: `The scope parser for the tag ${tag} failed to execute`,
				scope,
				tag,
				rootError: error,
			};
			throw err;
		}
		if (result == null && this.num > 0) { return this.getValue(tag, this.num - 1); }
		return result;
	}
	createSubScopeManager(scope, tag) {
		const options = {
			scopePath: this.scopePath.slice(0),
			scopeList: this.scopeList.slice(0),
		};
 
		options.parser = this.parser;
		options.scopeList = this.scopeList.concat(scope);
		options.scopePath = this.scopePath.concat(tag);
		return new ScopeManager(options);
	}
};
 
ScopeManager.createBaseScopeManager = function ({parser, tags}) {
	const options = {parser, tags};
	options.scopePath = [];
	options.scopeList = [tags];
	return new ScopeManager(options);
};
 
module.exports = ScopeManager;