manyfest 1.0.41 → 1.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["node_modules/browser-pack/_prelude.js","node_modules/fable-serviceproviderbase/package.json","manyfest.compatible.js","node_modules/fable-serviceproviderbase/source/Fable-ServiceProviderBase.js","source/Manyfest-CleanWrapCharacters.js","source/Manyfest-HashTranslation.js","source/Manyfest-LogToConsole.js","source/Manyfest-ObjectAddress-CheckAddressExists.js","source/Manyfest-ObjectAddress-DeleteValue.js","source/Manyfest-ObjectAddress-GetValue.js","source/Manyfest-ObjectAddress-Parser.js","source/Manyfest-ObjectAddress-SetValue.js","source/Manyfest-ObjectAddressGeneration.js","source/Manyfest-ParseConditionals.js","source/Manyfest-SchemaManipulation.js","source/Manyfest.js"],"names":["f","exports","_typeof","module","define","amd","g","window","global","self","Manyfest","r","e","n","t","o","i","c","require","u","a","Error","code","p","call","length","libPackage","FableServiceProviderBase","pFable","pOptions","pServiceHash","_classCallCheck","isFable","connectFable","fable","_PackageFableServiceProvider","UUID","getUUID","options","concat","Math","floor","random","serviceType","Hash","_createClass","key","value","tmpErrorMessage","console","log","Logging","services","servicesMap","_defineProperty","CoreServiceProviderBase","cleanWrapCharacters","pCharacter","pString","startsWith","endsWith","substring","libSimpleLog","ManyfestHashTranslation","pInfoLog","pErrorLog","logInfo","logError","translationTable","translationCount","Object","keys","addTranslation","pTranslation","_this","tmpTranslationSources","forEach","pTranslationSource","removeTranslationHash","pTranslationHash","removeTranslation","_this2","clearTranslations","translate","logToConsole","pLogLine","pLogObject","tmpLogLine","JSON","stringify","libGetObjectValue","_MockFable","DataFormat","ManyfestObjectAddressResolverCheckAddressExists","getObjectValueClass","checkAddressExists","pObject","pAddress","pRootObject","tmpRootObject","tmpAddressPartBeginning","stringGetFirstSegment","tmpBracketStartIndex","indexOf","tmpBracketStopIndex","tmpFunctionStartIndex","stringCountEnclosures","tmpFunctionAddress","trim","tmpBoxedPropertyName","tmpBoxedPropertyReference","tmpBoxedPropertyNumber","parseInt","Array","isArray","isNaN","tmpSubObjectName","tmpNewAddress","tmpFunctionArguments","stringGetSegments","stringGetEnclosureValueByIndex","apply","pError","message","tmpArgumentValues","push","getValueAtAddress","fCleanWrapCharacters","fParseConditionals","ManyfestObjectAddressResolverDeleteValue","checkRecordFilters","pRecord","deleteValueAtAddress","pParentAddress","undefined","tmpParentAddress","tmpSeparatorIndex","tmpObjectTypeMarkerIndex","tmpInputArray","tmpKeepRecord","splice","tmpObjectPropertyName","tmpArrayProperty","tmpContainerObject","tmpPropertyParentAddress","tmpValue","tmpObjectProperty","tmpObjectPropertyKeys","ManyfestObjectAddressResolverGetValue","tmpParentAddressParts","tmpBackNavigationCount","charAt","tmpParentAddressLength","tmpRecurseAddress","slice","join","tmpOutputArray","stringCountSegments","pSeparator","pEnclosureStartSymbolMap","pEnclosureEndSymbolMap","tmpString","tmpSeparator","tmpEnclosureStartSymbolMap","pEnclosureStart","tmpEnclosureEndSymbolMap","pEnclosureEnd","tmpSegmentCount","tmpEnclosureStack","pop","tmpCurrentSegmentStart","tmpSegmentList","tmpEnclosureStart","tmpEnclosureEnd","tmpEnclosureCount","tmpEnclosureDepth","pEnclosureIndexToGet","tmpEnclosureIndexToGet","tmpMatchedEnclosureIndex","tmpEnclosedValueStartIndex","tmpEnclosedValueEndIndex","ManyfestObjectAddressSetValue","setValueAtAddress","pValue","tmpIndexIsNumeric","ManyfestObjectAddressGeneration","generateAddressses","pBaseAddress","pSchema","tmpBaseAddress","tmpSchema","tmpObjectType","tmpSchemaObjectEntry","Address","Name","InSchema","DataType","Default","tmpObjectProperties","_ConditionalStanzaStart","_ConditionalStanzaStartLength","_ConditionalStanzaEnd","_ConditionalStanzaEndLength","testCondition","pManyfest","pSearchAddress","pSearchComparator","parseConditionals","tmpStartIndex","tmpStopIndex","tmpMagicComparisonPatternSet","split","tmpSearchAddress","tmpSearchComparator","tmpSearchValue","ManyfestSchemaManipulation","resolveAddressMappings","pManyfestSchemaDescriptors","pAddressMapping","tmpManyfestAddresses","tmpHashMapping","tmpAddressMappingSet","pInputAddress","tmpNewDescriptorAddress","tmpOldDescriptorAddress","tmpDescriptor","safeResolveAddressMappings","tmpManyfestSchemaDescriptors","parse","mergeAddressMappings","pManyfestSchemaDescriptorsDestination","pManyfestSchemaDescriptorsSource","tmpSource","tmpNewManyfestSchemaDescriptors","tmpDescriptorAddresses","pDescriptorAddress","libFableServiceProviderBase","libHashTranslation","libObjectAddressCheckAddressExists","libObjectAddressGetValue","libObjectAddressSetValue","libObjectAddressDeleteValue","libObjectAddressGeneration","libSchemaManipulation","_DefaultConfiguration","Scope","Descriptors","_libFableServiceProvi","pManifest","_this3","_callSuper","objectAddressCheckAddressExists","objectAddressGetValue","objectAddressSetValue","objectAddressDeleteValue","defaultValues","strict","scope","elementAddresses","elementHashes","elementDescriptors","reset","loadManifest","schemaManipulations","objectAddressGeneration","hashTranslations","numberRegex","_assertThisInitialized","_inherits","clone","tmpNewOptions","tmpNewManyfest","getManifest","deserialize","pManifestString","tmpManifest","tmpDescriptorKeys","tmpDescriptionAddresses","addDescriptor","HashTranslations","serialize","pDescriptor","getDescriptorByHash","pHash","getDescriptor","resolveHashAddress","eachDescriptor","fAction","checkAddressExistsByHash","tmpAddress","tmpInElementHashTable","tmpInTranslationTable","getValueByHash","getDefaultValue","lintAddress","tmpLintedAddress","setValueByHash","deleteValueByHash","validate","tmpValidationData","Errors","MissingElements","addValidationError","pErrorMessage","tmpValueExists","Required","tmpElementType","toString","toLowerCase","test","tmpValueString","tmpValueDate","Date","tmpDataType","populateDefaults","pOverwriteProperties","populateObject","fFilter","_this4","tmpObject","tmpOverwriteProperties","tmpFilterFunction"],"mappings":"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","file":"manyfest.compatible.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()","module.exports={\n \"name\": \"fable-serviceproviderbase\",\n \"version\": \"3.0.15\",\n \"description\": \"Simple base classes for fable services.\",\n \"main\": \"source/Fable-ServiceProviderBase.js\",\n \"scripts\": {\n \"start\": \"node source/Fable-ServiceProviderBase.js\",\n \"test\": \"npx mocha -u tdd -R spec\",\n \"tests\": \"npx mocha -u tdd --exit -R spec --grep\",\n \"coverage\": \"npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec\",\n \"build\": \"npx quack build\"\n },\n \"mocha\": {\n \"diff\": true,\n \"extension\": [\n \"js\"\n ],\n \"package\": \"./package.json\",\n \"reporter\": \"spec\",\n \"slow\": \"75\",\n \"timeout\": \"5000\",\n \"ui\": \"tdd\",\n \"watch-files\": [\n \"source/**/*.js\",\n \"test/**/*.js\"\n ],\n \"watch-ignore\": [\n \"lib/vendor\"\n ]\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/stevenvelozo/fable-serviceproviderbase.git\"\n },\n \"keywords\": [\n \"entity\",\n \"behavior\"\n ],\n \"author\": \"Steven Velozo <steven@velozo.com> (http://velozo.com/)\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/stevenvelozo/fable-serviceproviderbase/issues\"\n },\n \"homepage\": \"https://github.com/stevenvelozo/fable-serviceproviderbase\",\n \"devDependencies\": {\n \"fable\": \"^3.0.143\",\n \"quackage\": \"^1.0.33\"\n }\n}","(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.Manyfest = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\nmodule.exports={\n \"name\": \"fable-serviceproviderbase\",\n \"version\": \"3.0.15\",\n \"description\": \"Simple base classes for fable services.\",\n \"main\": \"source/Fable-ServiceProviderBase.js\",\n \"scripts\": {\n \"start\": \"node source/Fable-ServiceProviderBase.js\",\n \"test\": \"npx mocha -u tdd -R spec\",\n \"tests\": \"npx mocha -u tdd --exit -R spec --grep\",\n \"coverage\": \"npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec\",\n \"build\": \"npx quack build\"\n },\n \"mocha\": {\n \"diff\": true,\n \"extension\": [\n \"js\"\n ],\n \"package\": \"./package.json\",\n \"reporter\": \"spec\",\n \"slow\": \"75\",\n \"timeout\": \"5000\",\n \"ui\": \"tdd\",\n \"watch-files\": [\n \"source/**/*.js\",\n \"test/**/*.js\"\n ],\n \"watch-ignore\": [\n \"lib/vendor\"\n ]\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/stevenvelozo/fable-serviceproviderbase.git\"\n },\n \"keywords\": [\n \"entity\",\n \"behavior\"\n ],\n \"author\": \"Steven Velozo <steven@velozo.com> (http://velozo.com/)\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/stevenvelozo/fable-serviceproviderbase/issues\"\n },\n \"homepage\": \"https://github.com/stevenvelozo/fable-serviceproviderbase\",\n \"devDependencies\": {\n \"fable\": \"^3.0.143\",\n \"quackage\": \"^1.0.33\"\n }\n}\n},{}],2:[function(require,module,exports){\n/**\n* Fable Service Base\n* @author <steven@velozo.com>\n*/\n\nconst libPackage = require('../package.json');\n\nclass FableServiceProviderBase\n{\n\t// The constructor can be used in two ways:\n\t// 1) With a fable, options object and service hash (the options object and service hash are optional)\n\t// 2) With an object or nothing as the first parameter, where it will be treated as the options object\n\tconstructor(pFable, pOptions, pServiceHash)\n\t{\n\t\t// Check if a fable was passed in; connect it if so\n\t\tif ((typeof(pFable) === 'object') && pFable.isFable)\n\t\t{\n\t\t\tthis.connectFable(pFable);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.fable = false;\n\t\t}\n\n\t\t// Initialize the services map if it wasn't passed in\n\t\t/** @type {Object} */\n\t\tthis._PackageFableServiceProvider = libPackage;\n\n\t\t// initialize options and UUID based on whether the fable was passed in or not.\n\t\tif (this.fable)\n\t\t{\n\t\t\tthis.UUID = pFable.getUUID();\n\t\t\tthis.options = (typeof(pOptions) === 'object') ? pOptions\n\t\t\t\t\t\t\t: {};\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// With no fable, check to see if there was an object passed into either of the first two\n\t\t\t// Parameters, and if so, treat it as the options object\n\t\t\tthis.options = ((typeof(pFable) === 'object') && !pFable.isFable) ? pFable\n\t\t\t\t\t\t\t: (typeof(pOptions) === 'object') ? pOptions\n\t\t\t\t\t\t\t: {};\n\t\t\tthis.UUID = `CORE-SVC-${Math.floor((Math.random() * (99999 - 10000)) + 10000)}`\n\t\t}\n\n\t\t// It's expected that the deriving class will set this\n\t\tthis.serviceType = `Unknown-${this.UUID}`;\n\n\t\t// The service hash is used to identify the specific instantiation of the service in the services map\n\t\tthis.Hash = (typeof(pServiceHash) === 'string') ? pServiceHash \n\t\t\t\t\t: (!this.fable && (typeof(pOptions) === 'string')) ? pOptions\n\t\t\t\t\t: `${this.UUID}`;\n\t}\n\n\tconnectFable(pFable)\n\t{\n\t\tif ((typeof(pFable) !== 'object') || (!pFable.isFable))\n\t\t{\n\t\t\tlet tmpErrorMessage = `Fable Service Provider Base: Cannot connect to Fable, invalid Fable object passed in. The pFable parameter was a [${typeof(pFable)}].}`;\n\t\t\tconsole.log(tmpErrorMessage);\n\t\t\treturn new Error(tmpErrorMessage);\n\t\t}\n\n\t\tif (!this.fable)\n\t\t{\n\t\t\tthis.fable = pFable;\n\t\t}\n\n\t\tif (!this.log)\n\t\t{\n\t\t\tthis.log = this.fable.Logging;\n\t\t}\n\t\tif (!this.services)\n\t\t{\n\t\t\tthis.services = this.fable.services;\n\t\t}\n\n\t\tif (!this.servicesMap)\n\t\t{\n\t\t\tthis.servicesMap = this.fable.servicesMap;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tstatic isFableService = true;\n}\n\nmodule.exports = FableServiceProviderBase;\n\n// This is left here in case we want to go back to having different code/base class for \"core\" services\nmodule.exports.CoreServiceProviderBase = FableServiceProviderBase;\n},{\"../package.json\":1}],3:[function(require,module,exports){\n// When a boxed property is passed in, it should have quotes of some\n// kind around it.\n//\n// For instance:\n// \t\tMyValues['Name']\n// \t\tMyValues[\"Age\"]\n// \t\tMyValues[`Cost`]\n//\n// This function removes the wrapping quotes.\n//\n// Please note it *DOES NOT PARSE* template literals, so backticks just\n// end up doing the same thing as other quote types.\n//\n// TODO: Should template literals be processed? If so what state do they have access to? That should happen here if so.\n// TODO: Make a simple class include library with these\nconst cleanWrapCharacters = (pCharacter, pString) =>\n{\n\tif (pString.startsWith(pCharacter) && pString.endsWith(pCharacter))\n\t{\n\t\treturn pString.substring(1, pString.length - 1);\n\t}\n\telse\n\t{\n\t\treturn pString;\n\t}\n};\n\nmodule.exports = cleanWrapCharacters;\n},{}],4:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\n/**\n* Hash Translation\n*\n* This is a very simple translation table for hashes, which allows the same schema to resolve\n* differently based on a loaded translation table.\n*\n* This is to prevent the requirement for mutating schemas over and over again when we want to\n* reuse the structure but look up data elements by different addresses.\n*\n* One side-effect of this is that a translation table can \"override\" the built-in hashes, since\n* this is always used to resolve hashes before any of the functionCallByHash(pHash, ...) perform\n* their lookups by hash.\n*\n* @class ManyfestHashTranslation\n*/\nclass ManyfestHashTranslation\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) === 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) === 'function') ? pErrorLog : libSimpleLog;\n\n this.translationTable = {};\n\t}\n\n translationCount()\n {\n return Object.keys(this.translationTable).length;\n }\n\n addTranslation(pTranslation)\n {\n // This adds a translation in the form of:\n // { \"SourceHash\": \"DestinationHash\", \"SecondSourceHash\":\"SecondDestinationHash\" }\n if (typeof(pTranslation) != 'object')\n {\n this.logError(`Hash translation addTranslation expected a translation be type object but was passed in ${typeof(pTranslation)}`);\n return false;\n }\n\n let tmpTranslationSources = Object.keys(pTranslation)\n\n tmpTranslationSources.forEach(\n (pTranslationSource) =>\n {\n if (typeof(pTranslation[pTranslationSource]) != 'string')\n {\n this.logError(`Hash translation addTranslation expected a translation destination hash for [${pTranslationSource}] to be a string but the referrant was a ${typeof(pTranslation[pTranslationSource])}`);\n }\n else\n {\n this.translationTable[pTranslationSource] = pTranslation[pTranslationSource];\n }\n });\n }\n\n removeTranslationHash(pTranslationHash)\n {\n if (pTranslationHash in this.translationTable)\n {\n delete this.translationTable[pTranslationHash];\n }\n }\n\n // This removes translations.\n // If passed a string, just removes the single one.\n // If passed an object, it does all the source keys.\n removeTranslation(pTranslation)\n {\n if (typeof(pTranslation) == 'string')\n {\n this.removeTranslationHash(pTranslation);\n return true;\n }\n else if (typeof(pTranslation) == 'object')\n {\n let tmpTranslationSources = Object.keys(pTranslation)\n\n tmpTranslationSources.forEach(\n (pTranslationSource) =>\n {\n this.removeTranslation(pTranslationSource);\n });\n return true;\n }\n else\n {\n this.logError(`Hash translation removeTranslation expected either a string or an object but the passed-in translation was type ${typeof(pTranslation)}`);\n return false;\n }\n }\n\n clearTranslations()\n {\n this.translationTable = {};\n }\n\n translate(pTranslation)\n {\n if (pTranslation in this.translationTable)\n {\n return this.translationTable[pTranslation];\n }\n else\n {\n return pTranslation;\n }\n }\n}\n\nmodule.exports = ManyfestHashTranslation;\n},{\"./Manyfest-LogToConsole.js\":5}],5:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\n\n/**\n* Manyfest simple logging shim (for browser and dependency-free running)\n*/\n\nconst logToConsole = (pLogLine, pLogObject) =>\n{\n let tmpLogLine = (typeof(pLogLine) === 'string') ? pLogLine : '';\n\n console.log(`[Manyfest] ${tmpLogLine}`);\n\n if (pLogObject) console.log(JSON.stringify(pLogObject));\n};\n\nmodule.exports = logToConsole;\n},{}],6:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nconst libSimpleLog = require('./Manyfest-LogToConsole.js');\n// This is for resolving functions mid-address\nconst libGetObjectValue = require('./Manyfest-ObjectAddress-GetValue.js');\n\n// TODO: Just until this is a fable service.\nlet _MockFable = { DataFormat: require('./Manyfest-ObjectAddress-Parser.js') };\n\n/**\n* Object Address Resolver\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n*\n* @class ManyfestObjectAddressResolverCheckAddressExists\n*/\nclass ManyfestObjectAddressResolverCheckAddressExists\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.getObjectValueClass = new libGetObjectValue(this.logInfo, this.logError);\n\t}\n\n\t// Check if an address exists.\n\t//\n\t// This is necessary because the getValueAtAddress function is ambiguous on\n\t// whether the element/property is actually there or not (it returns\n\t// undefined whether the property exists or not). This function checks for\n\t// existance and returns true or false dependent.\n\tcheckAddressExists (pObject, pAddress, pRootObject)\n\t{\n\t\t// TODO: Should these throw an error?\n\t\t// Make sure pObject is an object\n\t\tif (typeof(pObject) != 'object') return false;\n\t\t// Make sure pAddress is a string\n\t\tif (typeof(pAddress) != 'string') return false;\n\n\t\t// Set the root object to the passed-in object if it isn't set yet. This is expected to be the root object.\n\t\t// NOTE: This was added to support functions mid-stream\n\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t// DONE: Make this work for things like SomeRootObject.Metadata[\"Some.People.Use.Bad.Object.Property.Names\"]\n\t\tlet tmpAddressPartBeginning = _MockFable.DataFormat.stringGetFirstSegment(pAddress);\n\n\t\t// This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)\n\t\tif (tmpAddressPartBeginning.length == pAddress.length)\n\t\t{\n\t\t\t// Check if the address refers to a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = pAddress.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(pAddress) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = pAddress.substring(0, tmpFunctionStartIndex).trim();\n\n\t\t\t\tif (((tmpFunctionAddress in pObject)) && (typeof(pObject[tmpFunctionAddress]) == 'function'))\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Check if the property exists.\n\t\t\t\t\treturn (tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Use the new in operator to see if the element is in the array\n\t\t\t\t\treturn (tmpBoxedPropertyNumber in pObject[tmpBoxedPropertyName]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Check if the property exists\n\t\t\t\treturn (pAddress in pObject);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet tmpSubObjectName = tmpAddressPartBeginning;\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpAddressPartBeginning.length+1);\n\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = tmpSubObjectName.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(tmpSubObjectName) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = tmpSubObjectName.substring(0, tmpFunctionStartIndex).trim();\n\t\t\t\t//tmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\n\t\t\t\tif (!typeof(pObject[tmpFunctionAddress]) == 'function')\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Now see if the function has arguments.\n\t\t\t\t// Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *\n\t\t\t\tlet tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(tmpSubObjectName.substring(tmpFunctionAddress.length), 0), ',');\n\t\t\t\tif ((tmpFunctionArguments.length == 0) || (tmpFunctionArguments[0] == ''))\n\t\t\t\t{\n\t\t\t\t\t// No arguments... just call the function (bound to the scope of the object it is contained withing)\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject), tmpNewAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tlibSimpleLog.log(`Error calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tlibSimpleLog.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlet tmpArgumentValues = [];\n\n\t\t\t\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t\t\t\t// Now get the value for each argument\n\t\t\t\t\tfor (let i = 0; i < tmpFunctionArguments.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Resolve the values for each subsequent entry\n\t\t\t\t\t\t// NOTE: This is where the resolves get really tricky. Recursion within recursion. Programming gom jabbar, yo.\n\t\t\t\t\t\ttmpArgumentValues.push(this.getObjectValueClass.getValueAtAddress(tmpRootObject, tmpFunctionArguments[i]));\n\t\t\t\t\t}\n\n\t\t\t\t\t//return this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpRootObject);\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tlibSimpleLog.log(`Error calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tlibSimpleLog.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// Because this is an impossible address, the property doesn't exist\n\t\t\t\t\t// TODO: Should we throw an error in this condition?\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.checkAddressExists(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.checkAddressExists(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\treturn this.checkAddressExists(pObject[tmpSubObjectName], tmpNewAddress, tmpRootObject);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.checkAddressExists(pObject[tmpSubObjectName], tmpNewAddress, tmpRootObject);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressResolverCheckAddressExists;\n\n},{\"./Manyfest-LogToConsole.js\":5,\"./Manyfest-ObjectAddress-GetValue.js\":8,\"./Manyfest-ObjectAddress-Parser.js\":9}],7:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\nlet fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');\nlet fParseConditionals = require(`../source/Manyfest-ParseConditionals.js`)\n\n/**\n* Object Address Resolver - DeleteValue\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n* TODO: Once we validate this pattern is good to go, break these out into\n* three separate modules.\n*\n* @class ManyfestObjectAddressResolverDeleteValue\n*/\nclass ManyfestObjectAddressResolverDeleteValue\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.cleanWrapCharacters = fCleanWrapCharacters;\n\t}\n\n\t// TODO: Dry me\n\tcheckRecordFilters(pAddress, pRecord)\n\t{\n\t\treturn fParseConditionals(this, pAddress, pRecord);\n\t}\n\n\t// Delete the value of an element at an address\n\tdeleteValueAtAddress (pObject, pAddress, pParentAddress)\n\t{\n\t\t// Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object)\n\t\tif (typeof(pObject) != 'object') return undefined;\n\t\t// Make sure pAddress (the address we are resolving) is a string\n\t\tif (typeof(pAddress) != 'string') return undefined;\n\t\t// Stash the parent address for later resolution\n\t\tlet tmpParentAddress = \"\";\n\t\tif (typeof(pParentAddress) == 'string')\n\t\t{\n\t\t\ttmpParentAddress = pParentAddress;\n\t\t}\n\n\t\t// TODO: Make this work for things like SomeRootObject.Metadata[\"Some.People.Use.Bad.Object.Property.Names\"]\n\t\tlet tmpSeparatorIndex = pAddress.indexOf('.');\n\n\t\t// This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)\n\t\tif (tmpSeparatorIndex == -1)\n\t\t{\n\t\t\t// Check if the address refers to a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\n\t\t\t// Check for the Object Set Type marker.\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Return the value in the property\n\t\t\t\t\tdelete pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference];\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdelete pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber];\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlet tmpInputArray = pObject[tmpBoxedPropertyName];\n\t\t\t\t// Count from the end to the beginning so splice doesn't %&%#$ up the array\n\t\t\t\tfor (let i = tmpInputArray.length - 1; i >= 0; i--)\n\t\t\t\t{\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpInputArray[i]);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Delete elements end to beginning\n\t\t\t\t\t\ttmpInputArray.splice(i, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t// The object has been flagged as an object set, so treat it as such\n\t\t\telse if (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tdelete pObject[tmpObjectPropertyName];\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Now is the point in recursion to return the value in the address\n\t\t\t\tdelete pObject[pAddress];\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);\n\n\t\t\t// BOXED ELEMENTS\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// Check if the boxed property is an object.\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, tmpParentAddress);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, tmpParentAddress);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the array and grab the addresses from there.\n\t\t\t\tlet tmpArrayProperty = pObject[tmpBoxedPropertyName];\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpBoxedPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpArrayProperty.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}[${i}]`;\n\t\t\t\t\tlet tmpValue = this.deleteValueAtAddress(pObject[tmpBoxedPropertyName][i], tmpNewAddress, tmpPropertyParentAddress);\n\n\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// OBJECT SET\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\t\t\tif (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the Object and grab the addresses from there.\n\t\t\t\tlet tmpObjectProperty = pObject[tmpObjectPropertyName];\n\t\t\t\tlet tmpObjectPropertyKeys = Object.keys(tmpObjectProperty);\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpObjectPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpObjectPropertyKeys.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}.${tmpObjectPropertyKeys[i]}`;\n\t\t\t\t\tlet tmpValue = this.deleteValueAtAddress(pObject[tmpObjectPropertyName][tmpObjectPropertyKeys[i]], tmpNewAddress, tmpPropertyParentAddress);\n\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpValue);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressResolverDeleteValue;\n},{\"../source/Manyfest-ParseConditionals.js\":12,\"./Manyfest-CleanWrapCharacters.js\":3,\"./Manyfest-LogToConsole.js\":5}],8:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\nlet fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');\nlet fParseConditionals = require(`../source/Manyfest-ParseConditionals.js`);\n\nlet _MockFable = { DataFormat: require('./Manyfest-ObjectAddress-Parser.js') };\n\n/**\n* Object Address Resolver - GetValue\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n* TODO: Once we validate this pattern is good to go, break these out into\n* three separate modules.\n*\n* @class ManyfestObjectAddressResolverGetValue\n*/\nclass ManyfestObjectAddressResolverGetValue\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.cleanWrapCharacters = fCleanWrapCharacters;\n\t}\n\n\tcheckRecordFilters(pAddress, pRecord)\n\t{\n\t\treturn fParseConditionals(this, pAddress, pRecord);\n\t}\n\n\t// Get the value of an element at an address\n\tgetValueAtAddress (pObject, pAddress, pParentAddress, pRootObject)\n\t{\n\t\t// Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object)\n\t\tif (typeof(pObject) != 'object')\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\t\tif (pObject === null)\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\t\t// Make sure pAddress (the address we are resolving) is a string\n\t\tif (typeof(pAddress) != 'string')\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\t\t// Stash the parent address for later resolution\n\t\tlet tmpParentAddress = \"\";\n\t\tif (typeof(pParentAddress) == 'string')\n\t\t{\n\t\t\ttmpParentAddress = pParentAddress;\n\t\t}\n\n\t\t// Set the root object to the passed-in object if it isn't set yet. This is expected to be the root object.\n\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t// DONE: Make this work for things like SomeRootObject.Metadata[\"Some.People.Use.Bad.Object.Property.Names\"]\n\t\tlet tmpAddressPartBeginning = _MockFable.DataFormat.stringGetFirstSegment(pAddress);\n\n\t\t// Adding simple back-navigation in objects\n\t\tif (tmpAddressPartBeginning == '')\n\t\t{\n\t\t\t// Given an address of \"Bundle.Contract.IDContract...Project.IDProject\" the ... would be interpreted as two back-navigations from IDContract.\n\t\t\t// When the address is passed in, though, the first . is already eliminated. So we can count the dots.\n\t\t\tlet tmpParentAddressParts = _MockFable.DataFormat.stringGetSegments(tmpParentAddress);\n\n\t\t\tlet tmpBackNavigationCount = 0;\n\n\t\t\t// Count the number of dots\n\t\t\tfor (let i = 0; i < pAddress.length; i++)\n\t\t\t{\n\t\t\t\tif (pAddress.charAt(i) != '.')\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttmpBackNavigationCount++;\n\t\t\t}\n\n\t\t\tlet tmpParentAddressLength = tmpParentAddressParts.length - tmpBackNavigationCount;\n\n\t\t\tif (tmpParentAddressLength < 0)\n\t\t\t{\n\t\t\t\t// We are trying to back navigate more than we can.\n\t\t\t\t// TODO: Should this be undefined or should we bank out at the bottom and try to go forward?\n\t\t\t\t// This seems safest for now.\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// We are trying to back navigate to a parent object.\n\t\t\t\t// Recurse with the back-propagated parent address, and, the new address without the back-navigation dots.\n\t\t\t\tlet tmpRecurseAddress = pAddress.slice(tmpBackNavigationCount);\n\t\t\t\tif (tmpParentAddressLength > 0)\n\t\t\t\t{\n\t\t\t\t\ttmpRecurseAddress = `${tmpParentAddressParts.slice(0, tmpParentAddressLength).join('.')}.${tmpRecurseAddress}`;\n\t\t\t\t}\n\t\t\t\tthis.logInfo(`Back-navigation detected. Recursing back to address [${tmpRecurseAddress}]`);\n\t\t\t\treturn this.getValueAtAddress(tmpRootObject, tmpRecurseAddress);\n\t\t\t}\n\t\t}\n\n\t\t// This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)\n\t\tif (tmpAddressPartBeginning.length == pAddress.length)\n\t\t{\n\t\t\t// TODO: Optimize this by having these calls only happen when the previous fails.\n\t\t\t// TODO: Alternatively look for all markers in one pass?\n\t\t\t// Check if the address refers to a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\n\t\t\t// Check for the Object Set Type marker.\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = pAddress.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(pAddress) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = pAddress.substring(0, tmpFunctionStartIndex).trim();\n\n\t\t\t\tif (!typeof(pObject[tmpFunctionAddress]) == 'function')\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Now see if the function has arguments.\n\t\t\t\t// Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *\n\t\t\t\tlet tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(pAddress.substring(tmpFunctionAddress.length), 0), ',');\n\t\t\t\tif ((tmpFunctionArguments.length == 0) || (tmpFunctionArguments[0] == ''))\n\t\t\t\t{\n\t\t\t\t\t// No arguments... just call the function (bound to the scope of the object it is contained withing)\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn pObject[tmpFunctionAddress].apply(pObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlet tmpArgumentValues = [];\n\n\t\t\t\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t\t\t\t// Now get the value for each argument\n\t\t\t\t\tfor (let i = 0; i < tmpFunctionArguments.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Resolve the values for each subsequent entry\n\t\t\t\t\t\t// Check if the argument value is a string literal or a reference to an address\n\t\t\t\t\t\tif ((tmpFunctionArguments[i].length >= 2)\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(0) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"`\"))\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"`\")))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a string literal\n\t\t\t\t\t\t\ttmpArgumentValues.push(tmpFunctionArguments[i].substring(1, tmpFunctionArguments[i].length-1));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a hash address\n\t\t\t\t\t\t\ttmpArgumentValues.push(this.getValueAtAddress(tmpRootObject, tmpFunctionArguments[i]));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Return the value in the property\n\t\t\t\t\treturn pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber];\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlet tmpInputArray = pObject[tmpBoxedPropertyName];\n\t\t\t\tlet tmpOutputArray = [];\n\t\t\t\tfor (let i = 0; i < tmpInputArray.length; i++)\n\t\t\t\t{\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpInputArray[i]);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpOutputArray.push(tmpInputArray[i]);\n\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmpOutputArray;\n\t\t\t}\n\t\t\t// The object has been flagged as an object set, so treat it as such\n\t\t\telse if (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn pObject[tmpObjectPropertyName];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Now is the point in recursion to return the value in the address\n\t\t\t\tif (typeof(pObject[pAddress]) != null)\n\t\t\t\t{\n\t\t\t\t\treturn pObject[pAddress];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//let tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);\n\t\t\t//let tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);\n\t\t\tlet tmpSubObjectName = tmpAddressPartBeginning;\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpAddressPartBeginning.length+1);\n\n\t\t\t// BOXED ELEMENTS\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = tmpSubObjectName.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(tmpSubObjectName) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = tmpSubObjectName.substring(0, tmpFunctionStartIndex).trim();\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\n\t\t\t\tif (!typeof(pObject[tmpFunctionAddress]) == 'function')\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Now see if the function has arguments.\n\t\t\t\t// Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *\n\t\t\t\tlet tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(tmpSubObjectName.substring(tmpFunctionAddress.length), 0), ',');\n\t\t\t\tif ((tmpFunctionArguments.length == 0) || (tmpFunctionArguments[0] == ''))\n\t\t\t\t{\n\t\t\t\t\t// No arguments... just call the function (bound to the scope of the object it is contained withing)\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpFunctionAddress].apply(pObject), tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlet tmpArgumentValues = [];\n\n\t\t\t\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t\t\t\t// Now get the value for each argument\n\t\t\t\t\tfor (let i = 0; i < tmpFunctionArguments.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Resolve the values for each subsequent entry\n\t\t\t\t\t\t// Check if the argument value is a string literal or a reference to an address\n\t\t\t\t\t\tif ((tmpFunctionArguments[i].length >= 2)\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(0) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"`\"))\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"`\")))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a string literal\n\t\t\t\t\t\t\ttmpArgumentValues.push(tmpFunctionArguments[i].substring(1, tmpFunctionArguments[i].length-1));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a hash address\n\t\t\t\t\t\t\ttmpArgumentValues.push(this.getValueAtAddress(tmpRootObject, tmpFunctionArguments[i]));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\t// Check if the boxed property is an object.\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the array and grab the addresses from there.\n\t\t\t\tlet tmpArrayProperty = pObject[tmpBoxedPropertyName];\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpBoxedPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpArrayProperty.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}[${i}]`;\n\t\t\t\t\tlet tmpValue = this.getValueAtAddress(pObject[tmpBoxedPropertyName][i], tmpNewAddress, tmpPropertyParentAddress, tmpRootObject);\n\n\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// OBJECT SET\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\t\t\tif (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the Object and grab the addresses from there.\n\t\t\t\tlet tmpObjectProperty = pObject[tmpObjectPropertyName];\n\t\t\t\tlet tmpObjectPropertyKeys = Object.keys(tmpObjectProperty);\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpObjectPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpObjectPropertyKeys.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}.${tmpObjectPropertyKeys[i]}`;\n\t\t\t\t\tlet tmpValue = this.getValueAtAddress(pObject[tmpObjectPropertyName][tmpObjectPropertyKeys[i]], tmpNewAddress, tmpPropertyParentAddress, tmpRootObject);\n\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpValue);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\treturn this.getValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.getValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressResolverGetValue;\n},{\"../source/Manyfest-ParseConditionals.js\":12,\"./Manyfest-CleanWrapCharacters.js\":3,\"./Manyfest-LogToConsole.js\":5,\"./Manyfest-ObjectAddress-Parser.js\":9}],9:[function(require,module,exports){\n// TODO: This is an inelegant solution to delay the rewrite of Manyfest.\n\n// Fable 3.0 has a service for data formatting that deals well with nested enclosures.\n\n// The Manyfest library predates fable 3.0 and the services structure of it, so the functions\n// are more or less pure javascript and as functional as they can be made to be.\n\n// Until we shift Manyfest to be a fable service, these three functions were pulled out of\n// fable to aid in parsing functions with nested enclosures.\n\nmodule.exports = {\n\t/**\n\t * Count the number of segments in a string, respecting enclosures\n\t * \n\t * @param {string} pString \n\t * @param {string} pSeparator \n\t * @param {object} pEnclosureStartSymbolMap \n\t * @param {object} pEnclosureEndSymbolMap \n\t * @returns the count of segments in the string as a number\n\t */\n\tstringCountSegments: (pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\n\t\tlet tmpSeparator = (typeof(pSeparator) == 'string') ? pSeparator : '.';\n\n\t\tlet tmpEnclosureStartSymbolMap = (typeof(pEnclosureStartSymbolMap) == 'object') ? pEnclosureStart : { '{': 0, '[': 1, '(': 2 };\n\t\tlet tmpEnclosureEndSymbolMap = (typeof(pEnclosureEndSymbolMap) == 'object') ? pEnclosureEnd : { '}': 0, ']': 1, ')': 2 };\n\n\t\tif (pString.length < 1)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet tmpSegmentCount = 1;\n\t\tlet tmpEnclosureStack = [];\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// IF This is the start of a segment\n\t\t\tif ((tmpString[i] == tmpSeparator)\n\t\t\t\t// AND we are not in a nested portion of the string\n\t\t\t\t&& (tmpEnclosureStack.length == 0))\n\t\t\t{\n\t\t\t\t// Increment the segment count\n\t\t\t\ttmpSegmentCount++;\n\t\t\t}\n\t\t\t// IF This is the start of an enclosure\n\t\t\telse if (tmpString[i] in tmpEnclosureStartSymbolMap)\n\t\t\t{\n\t\t\t\t// Add it to the stack!\n\t\t\t\ttmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);\n\t\t\t}\n\t\t\t// IF This is the end of an enclosure\n\t\t\telse if ((tmpString[i] in tmpEnclosureEndSymbolMap)\n\t\t\t\t// AND it matches the current nest level symbol\n\t\t\t\t&& tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1])\n\t\t\t{\n\t\t\t\t// Pop it off the stack!\n\t\t\t\ttmpEnclosureStack.pop();\n\t\t\t}\n\t\t}\n\n\t\treturn tmpSegmentCount;\n\t},\n\n\t/**\n\t * Get the first segment in a string, respecting enclosures\n\t * \n\t * @param {string} pString \n\t * @param {string} pSeparator \n\t * @param {object} pEnclosureStartSymbolMap \n\t * @param {object} pEnclosureEndSymbolMap \n\t * @returns the first segment in the string as a string\n\t */\n\tstringGetFirstSegment: (pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\n\t\tlet tmpSeparator = (typeof(pSeparator) == 'string') ? pSeparator : '.';\n\n\t\tlet tmpEnclosureStartSymbolMap = (typeof(pEnclosureStartSymbolMap) == 'object') ? pEnclosureStart : { '{': 0, '[': 1, '(': 2 };\n\t\tlet tmpEnclosureEndSymbolMap = (typeof(pEnclosureEndSymbolMap) == 'object') ? pEnclosureEnd : { '}': 0, ']': 1, ')': 2 };\n\n\t\tif (pString.length < 1)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet tmpEnclosureStack = [];\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// IF This is the start of a segment\n\t\t\tif ((tmpString[i] == tmpSeparator)\n\t\t\t\t// AND we are not in a nested portion of the string\n\t\t\t\t&& (tmpEnclosureStack.length == 0))\n\t\t\t{\n\t\t\t\t// Return the segment\n\t\t\t\treturn tmpString.substring(0, i);\n\t\t\t}\n\t\t\t// IF This is the start of an enclosure\n\t\t\telse if (tmpString[i] in tmpEnclosureStartSymbolMap)\n\t\t\t{\n\t\t\t\t// Add it to the stack!\n\t\t\t\ttmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);\n\t\t\t}\n\t\t\t// IF This is the end of an enclosure\n\t\t\telse if ((tmpString[i] in tmpEnclosureEndSymbolMap)\n\t\t\t\t// AND it matches the current nest level symbol\n\t\t\t\t&& tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1])\n\t\t\t{\n\t\t\t\t// Pop it off the stack!\n\t\t\t\ttmpEnclosureStack.pop();\n\t\t\t}\n\t\t}\n\n\t\treturn tmpString;\n\t},\n\n\t/**\n\t * Get all segments in a string, respecting enclosures\n\t * \n\t * @param {string} pString \n\t * @param {string} pSeparator \n\t * @param {object} pEnclosureStartSymbolMap \n\t * @param {object} pEnclosureEndSymbolMap \n\t * @returns the first segment in the string as a string\n\t */\n\tstringGetSegments: (pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap)=>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\n\t\tlet tmpSeparator = (typeof(pSeparator) == 'string') ? pSeparator : '.';\n\n\t\tlet tmpEnclosureStartSymbolMap = (typeof(pEnclosureStartSymbolMap) == 'object') ? pEnclosureStart : { '{': 0, '[': 1, '(': 2 };\n\t\tlet tmpEnclosureEndSymbolMap = (typeof(pEnclosureEndSymbolMap) == 'object') ? pEnclosureEnd : { '}': 0, ']': 1, ')': 2 };\n\n\t\tlet tmpCurrentSegmentStart = 0;\n\t\tlet tmpSegmentList = [];\n\n\t\tif (pString.length < 1)\n\t\t{\n\t\t\treturn tmpSegmentList;\n\t\t}\n\n\t\tlet tmpEnclosureStack = [];\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// IF This is the start of a segment\n\t\t\tif ((tmpString[i] == tmpSeparator)\n\t\t\t\t// AND we are not in a nested portion of the string\n\t\t\t\t&& (tmpEnclosureStack.length == 0))\n\t\t\t{\n\t\t\t\t// Return the segment\n\t\t\t\ttmpSegmentList.push(tmpString.substring(tmpCurrentSegmentStart, i));\n\t\t\t\ttmpCurrentSegmentStart = i+1;\n\t\t\t}\n\t\t\t// IF This is the start of an enclosure\n\t\t\telse if (tmpString[i] in tmpEnclosureStartSymbolMap)\n\t\t\t{\n\t\t\t\t// Add it to the stack!\n\t\t\t\ttmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);\n\t\t\t}\n\t\t\t// IF This is the end of an enclosure\n\t\t\telse if ((tmpString[i] in tmpEnclosureEndSymbolMap)\n\t\t\t\t// AND it matches the current nest level symbol\n\t\t\t\t&& tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1])\n\t\t\t{\n\t\t\t\t// Pop it off the stack!\n\t\t\t\ttmpEnclosureStack.pop();\n\t\t\t}\n\t\t}\n\n\t\tif (tmpCurrentSegmentStart < tmpString.length)\n\t\t{\n\t\t\ttmpSegmentList.push(tmpString.substring(tmpCurrentSegmentStart));\n\t\t}\n\n\t\treturn tmpSegmentList;\n\t},\n\n\t/**\n\t * Count the number of enclosures in a string based on the start and end characters.\n\t *\n\t * If no start or end characters are specified, it will default to parentheses. If the string is not a string, it will return 0.\n\t *\n\t * @param {string} pString\n\t * @param {string} pEnclosureStart\n\t * @param {string} pEnclosureEnd\n\t * @returns the count of full in the string\n\t */\n\tstringCountEnclosures: (pString, pEnclosureStart, pEnclosureEnd) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\t\tlet tmpEnclosureStart = (typeof(pEnclosureStart) == 'string') ? pEnclosureStart : '(';\n\t\tlet tmpEnclosureEnd = (typeof(pEnclosureEnd) == 'string') ? pEnclosureEnd : ')';\n\n\t\tlet tmpEnclosureCount = 0;\n\t\tlet tmpEnclosureDepth = 0;\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// This is the start of an enclosure\n\t\t\tif (tmpString[i] == tmpEnclosureStart)\n\t\t\t{\n\t\t\t\tif (tmpEnclosureDepth == 0)\n\t\t\t\t{\n\t\t\t\t\ttmpEnclosureCount++;\n\t\t\t\t}\n\t\t\t\ttmpEnclosureDepth++;\n\t\t\t}\n\t\t\telse if (tmpString[i] == tmpEnclosureEnd)\n\t\t\t{\n\t\t\t\ttmpEnclosureDepth--;\n\t\t\t}\n\t\t}\n\n\t\treturn tmpEnclosureCount;\n\t},\n\n\n\t/**\n\t * Get the value of the enclosure at the specified index.\n\t *\n\t * If the index is not a number, it will default to 0. If the string is not a string, it will return an empty string. If the enclosure is not found, it will return an empty string. If the enclosure\n\t *\n\t * @param {string} pString\n\t * @param {number} pEnclosureIndexToGet\n\t * @param {string} pEnclosureStart\n\t * @param {string}} pEnclosureEnd\n\t * @returns {string}\n\t */\n\tstringGetEnclosureValueByIndex: (pString, pEnclosureIndexToGet, pEnclosureStart, pEnclosureEnd) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\t\tlet tmpEnclosureIndexToGet = (typeof(pEnclosureIndexToGet) == 'number') ? pEnclosureIndexToGet : 0;\n\t\tlet tmpEnclosureStart = (typeof(pEnclosureStart) == 'string') ? pEnclosureStart : '(';\n\t\tlet tmpEnclosureEnd = (typeof(pEnclosureEnd) == 'string') ? pEnclosureEnd : ')';\n\n\t\tlet tmpEnclosureCount = 0;\n\t\tlet tmpEnclosureDepth = 0;\n\n\t\tlet tmpMatchedEnclosureIndex = false;\n\t\tlet tmpEnclosedValueStartIndex = 0;\n\t\tlet tmpEnclosedValueEndIndex = 0;\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// This is the start of an enclosure\n\t\t\tif (tmpString[i] == tmpEnclosureStart)\n\t\t\t{\n\t\t\t\ttmpEnclosureDepth++;\n\n\t\t\t\t// Only count enclosures at depth 1, but still this parses both pairs of all of them.\n\t\t\t\tif (tmpEnclosureDepth == 1)\n\t\t\t\t{\n\t\t\t\t\ttmpEnclosureCount++;\n\t\t\t\t\tif (tmpEnclosureIndexToGet == (tmpEnclosureCount - 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t// This is the start of *the* enclosure\n\t\t\t\t\t\ttmpMatchedEnclosureIndex = true;\n\t\t\t\t\t\ttmpEnclosedValueStartIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// This is the end of an enclosure\n\t\t\telse if (tmpString[i] == tmpEnclosureEnd)\n\t\t\t{\n\t\t\t\ttmpEnclosureDepth--;\n\n\t\t\t\t// Again, only count enclosures at depth 1, but still this parses both pairs of all of them.\n\t\t\t\tif ((tmpEnclosureDepth == 0) &&\n\t\t\t\t\ttmpMatchedEnclosureIndex &&\n\t\t\t\t\t(tmpEnclosedValueEndIndex <= tmpEnclosedValueStartIndex))\n\t\t\t\t{\n\t\t\t\t\ttmpEnclosedValueEndIndex = i;\n\t\t\t\t\ttmpMatchedEnclosureIndex = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (tmpEnclosureCount <= tmpEnclosureIndexToGet)\n\t\t{\n\t\t\t// Return an empty string if the enclosure is not found\n\t\t\treturn '';\n\t\t}\n\n\t\tif ((tmpEnclosedValueEndIndex > 0) && (tmpEnclosedValueEndIndex > tmpEnclosedValueStartIndex))\n\t\t{\n\t\t\treturn tmpString.substring(tmpEnclosedValueStartIndex+1, tmpEnclosedValueEndIndex);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn tmpString.substring(tmpEnclosedValueStartIndex+1);\n\t\t}\n\t}\n}\n},{}],10:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\nlet fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');\n\n/**\n* Object Address Resolver - SetValue\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n*\n* @class ManyfestObjectAddressSetValue\n*/\nclass ManyfestObjectAddressSetValue\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.cleanWrapCharacters = fCleanWrapCharacters;\n\t}\n\n\t// Set the value of an element at an address\n\tsetValueAtAddress (pObject, pAddress, pValue)\n\t{\n\t\t// Make sure pObject is an object\n\t\tif (typeof(pObject) != 'object') return false;\n\t\t// Make sure pAddress is a string\n\t\tif (typeof(pAddress) != 'string') return false;\n\n\t\tlet tmpSeparatorIndex = pAddress.indexOf('.');\n\n\t\tif (tmpSeparatorIndex == -1)\n\t\t{\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\t\t\t\tlet tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);\n\n\t\t\t\tif (pObject[tmpBoxedPropertyName] == null)\n\t\t\t\t{\n\t\t\t\t\tif (tmpIndexIsNumeric)\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = [];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\tif (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return the value in the property\n\t\t\t\t\t//TODO: For cases where we have chained [][] properties, this needs to recurse somehow\n\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = pValue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twhile(pObject[tmpBoxedPropertyName].length < (tmpBoxedPropertyNumber + 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName].push({});\n\t\t\t\t\t}\n\n\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber] = pValue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Now is the time in recursion to set the value in the object\n\t\t\t\tpObject[pAddress] = pValue;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);\n\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\t\t\t\tlet tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);\n\n\t\t\t\t//if (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\tif (pObject[tmpBoxedPropertyName] == null)\n\t\t\t\t{\n\t\t\t\t\tif (tmpIndexIsNumeric)\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = [];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) != tmpIndexIsNumeric)\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\tif (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.setValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, pValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twhile(pObject[tmpBoxedPropertyName].length < (tmpBoxedPropertyNumber + 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName].push({});\n\t\t\t\t\t}\n\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.setValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, pValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\tif (!('__ERROR' in pObject))\n\t\t\t\t\tpObject['__ERROR'] = {};\n\t\t\t\t// Put it in an error object so data isn't lost\n\t\t\t\tpObject['__ERROR'][pAddress] = pValue;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\treturn this.setValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, pValue);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.setValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, pValue);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressSetValue;\n},{\"./Manyfest-CleanWrapCharacters.js\":3,\"./Manyfest-LogToConsole.js\":5}],11:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\n/**\n* Object Address Generation\n*\n* Automagically generate addresses and properties based on a passed-in object,\n* to be used for easy creation of schemas. Meant to simplify the lives of\n* developers wanting to create schemas without typing a bunch of stuff.\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n*\n* @class ManyfestObjectAddressGeneration\n*/\nclass ManyfestObjectAddressGeneration\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\t}\n\n\t// generateAddressses\n\t//\n\t// This flattens an object into a set of key:value pairs for *EVERY SINGLE\n\t// POSSIBLE ADDRESS* in the object. It can get ... really insane really\n\t// quickly. This is not meant to be used directly to generate schemas, but\n\t// instead as a starting point for scripts or UIs.\n\t//\n\t// This will return a mega set of key:value pairs with all possible schema\n\t// permutations and default values (when not an object) and everything else.\n\tgenerateAddressses (pObject, pBaseAddress, pSchema)\n\t{\n\t\tlet tmpBaseAddress = (typeof(pBaseAddress) == 'string') ? pBaseAddress : '';\n\t\tlet tmpSchema = (typeof(pSchema) == 'object') ? pSchema : {};\n\n\t\tlet tmpObjectType = typeof(pObject);\n\n\t\tlet tmpSchemaObjectEntry = (\n\t\t\t{\n\t\t\t\tAddress: tmpBaseAddress,\n\t\t\t\tHash: tmpBaseAddress,\n\t\t\t\tName: tmpBaseAddress,\n\t\t\t\t// This is so scripts and UI controls can force a developer to opt-in.\n\t\t\t\tInSchema: false\n\t\t\t}\n\t\t)\n\n\t\tif ((tmpObjectType == 'object') && (pObject == null))\n\t\t{\n\t\t\ttmpObjectType = 'null';\n\t\t}\n\n\t\tswitch(tmpObjectType)\n\t\t{\n\t\t\tcase 'string':\n\t\t\t\ttmpSchemaObjectEntry.DataType = 'String';\n\t\t\t\ttmpSchemaObjectEntry.Default = pObject;\n\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\tbreak;\n\t\t\tcase 'number':\n\t\t\tcase 'bigint':\n\t\t\t\ttmpSchemaObjectEntry.DataType = 'Number';\n\t\t\t\ttmpSchemaObjectEntry.Default = pObject;\n\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\tbreak;\n\t\t\tcase 'undefined':\n\t\t\tcase 'null':\n\t\t\t\ttmpSchemaObjectEntry.DataType = 'Any';\n\t\t\t\ttmpSchemaObjectEntry.Default = pObject;\n\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\tbreak;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(pObject))\n\t\t\t\t{\n\t\t\t\t\ttmpSchemaObjectEntry.DataType = 'Array';\n\t\t\t\t\tif (tmpBaseAddress != '')\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (let i = 0; i < pObject.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.generateAddressses(pObject[i], `${tmpBaseAddress}[${i}]`, tmpSchema);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttmpSchemaObjectEntry.DataType = 'Object';\n\t\t\t\t\tif (tmpBaseAddress != '')\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\t\t\ttmpBaseAddress += '.';\n\t\t\t\t\t}\n\n\t\t\t\t\tlet tmpObjectProperties = Object.keys(pObject);\n\n\t\t\t\t\tfor (let i = 0; i < tmpObjectProperties.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.generateAddressses(pObject[tmpObjectProperties[i]], `${tmpBaseAddress}${tmpObjectProperties[i]}`, tmpSchema);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'symbol':\n\t\t\tcase 'function':\n\t\t\t\t// Symbols and functions neither recurse nor get added to the schema\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn tmpSchema;\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressGeneration;\n},{\"./Manyfest-LogToConsole.js\":5}],12:[function(require,module,exports){\n// Given a string, parse out any conditional expressions and set whether or not to keep the record.\n//\n// For instance:\n// \t\t'files[]<<~?format,==,Thumbnail?~>>'\n// 'files[]<<~?format,==,Metadata?~>>'\n// 'files[]<<~?size,>,4000?~>>'\n//\n// The wrapping parts are the <<~? and ?~>> megabrackets.\n//\n// The function does not need to alter the string -- just check the conditionals within.\n\n// TODO: Consider making this an es6 class\n\n// Let's use indexOf since it is apparently the fastest.\nconst _ConditionalStanzaStart = '<<~?';\nconst _ConditionalStanzaStartLength = _ConditionalStanzaStart.length;\nconst _ConditionalStanzaEnd = '?~>>';\nconst _ConditionalStanzaEndLength = _ConditionalStanzaEnd.length;\n\n// Ugh dependency injection. Can't wait to make these all fable services.\n//let libObjectAddressCheckAddressExists = new (require('./Manyfest-ObjectAddress-CheckAddressExists.js'))();\n\n// Test the condition of a value in a record\nconst testCondition = (pManyfest, pRecord, pSearchAddress, pSearchComparator, pValue) =>\n{\n\tswitch(pSearchComparator)\n\t{\n\t\tcase 'TRUE':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) === true);\n\t\t\tbreak;\n\t\tcase 'FALSE':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) === false);\n\t\t\tbreak;\n\t\tcase 'LNGT':\n\t\tcase 'LENGTH_GREATER_THAN':\n\t\t\tswitch(typeof(pManyfest.getValueAtAddress(pRecord, pSearchAddress)))\n\t\t\t{\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length > pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'object':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length > pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'LNLT':\n\t\tcase 'LENGTH_LESS_THAN':\n\t\t\tswitch(typeof(pManyfest.getValueAtAddress(pRecord, pSearchAddress)))\n\t\t\t{\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length < pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'object':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length < pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\t// TODO: Welcome to dependency hell. This fixes itself when we move to fable services.\n\t\t// case 'EX':\n\t\t// case 'EXISTS':\n\t\t// \treturn libObjectAddressCheckAddressExists.checkAddressExists(pRecord, pSearchAddress);\n\t\t// \tbreak;\n\t\t// case 'DNEX':\n\t\t// case 'DOES_NOT_EXIST':\n\t\t// \treturn !libObjectAddressCheckAddressExists.checkAddressExists(pRecord, pSearchAddress);\n\t\t// \tbreak;\n\t\tcase '!=':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) != pValue);\n\t\t\tbreak;\n\t\tcase '<':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) < pValue);\n\t\t\tbreak;\n\t\tcase '>':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) > pValue);\n\t\t\tbreak;\n\t\tcase '<=':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) <= pValue);\n\t\t\tbreak;\n\t\tcase '>=':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) >= pValue);\n\t\t\tbreak;\n\t\tcase '===':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) === pValue);\n\t\t\tbreak;\n\t\tcase '==':\n\t\tdefault:\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) == pValue);\n\t\t\tbreak;\n\t}\n};\n\nconst parseConditionals = (pManyfest, pAddress, pRecord) =>\n{\n\tlet tmpKeepRecord = true;\n\n\t/*\n\t\tAlgorithm is simple:\n\n\t\t1. Enuerate start points\n\t\t2. Find stop points within each start point\n\t\t3. Check the conditional\n\t*/\n\tlet tmpStartIndex = pAddress.indexOf(_ConditionalStanzaStart);\n\n\twhile (tmpStartIndex != -1)\n\t{\n\t\tlet tmpStopIndex = pAddress.indexOf(_ConditionalStanzaEnd, tmpStartIndex+_ConditionalStanzaStartLength);\n\n\t\tif (tmpStopIndex != -1)\n\t\t{\n\t\t\tlet tmpMagicComparisonPatternSet = pAddress.substring(tmpStartIndex+_ConditionalStanzaStartLength, tmpStopIndex).split(',');\n\n\t\t\t// The address to search for\n\t\t\tlet tmpSearchAddress = tmpMagicComparisonPatternSet[0];\n\n\t\t\t// The copmparison expression (EXISTS as default)\n\t\t\tlet tmpSearchComparator = 'EXISTS';\n\t\t\tif (tmpMagicComparisonPatternSet.length > 1)\n\t\t\t{\n\t\t\t\ttmpSearchComparator = tmpMagicComparisonPatternSet[1];\t\t\t\t\n\t\t\t}\n\n\t\t\t// The value to search for\n\t\t\tlet tmpSearchValue = false;\n\t\t\tif (tmpMagicComparisonPatternSet.length > 2)\n\t\t\t{\n\t\t\t\ttmpSearchValue = tmpMagicComparisonPatternSet[2];\n\t\t\t}\n\n\t\t\t// Process the piece\n\t\t\ttmpKeepRecord = tmpKeepRecord && testCondition(pManyfest, pRecord, tmpSearchAddress, tmpSearchComparator, tmpSearchValue);\n\t\t\ttmpStartIndex = pAddress.indexOf(_ConditionalStanzaStart, tmpStopIndex+_ConditionalStanzaEndLength);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttmpStartIndex = -1;\n\t\t}\n\t\t\n\t}\n\n\treturn tmpKeepRecord;\n}\n\nmodule.exports = parseConditionals;\n},{}],13:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\n/**\n* Schema Manipulation Functions\n*\n* @class ManyfestSchemaManipulation\n*/\nclass ManyfestSchemaManipulation\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) === 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) === 'function') ? pErrorLog : libSimpleLog;\n\t}\n\n // This translates the default address mappings to something different.\n //\n // For instance you can pass in manyfest schema descriptor object:\n // \t{\n\t//\t \"Address.Of.a\": { \"Hash\": \"a\", \"Type\": \"Number\" },\n\t//\t \"Address.Of.b\": { \"Hash\": \"b\", \"Type\": \"Number\" }\n\t// }\n //\n //\n // And then an address mapping (basically a Hash->Address map)\n // {\n // \"a\": \"New.Address.Of.a\",\n // \"b\": \"New.Address.Of.b\"\n // }\n //\n // NOTE: This mutates the schema object permanently, altering the base hash.\n // If there is a collision with an existing address, it can lead to overwrites.\n // TODO: Discuss what should happen on collisions.\n\tresolveAddressMappings(pManyfestSchemaDescriptors, pAddressMapping)\n\t{\n\t\tif (typeof(pManyfestSchemaDescriptors) != 'object')\n\t\t{\n\t\t\tthis.logError(`Attempted to resolve address mapping but the descriptor was not an object.`);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (typeof(pAddressMapping) != 'object')\n\t\t{\n\t\t\t// No mappings were passed in\n\t\t\treturn true;\n\t\t}\n\n\t\t// Get the arrays of both the schema definition and the hash mapping\n\t\tlet tmpManyfestAddresses = Object.keys(pManyfestSchemaDescriptors);\n\t\tlet tmpHashMapping = {};\n\t\ttmpManyfestAddresses.forEach(\n\t\t\t(pAddress) =>\n\t\t\t{\n\t\t\t\tif ('Hash' in pManyfestSchemaDescriptors[pAddress])\n\t\t\t\t{\n\t\t\t\t\ttmpHashMapping[pManyfestSchemaDescriptors[pAddress].Hash] = pAddress;\n\t\t\t\t}\n\t\t\t});\n\n\t\tlet tmpAddressMappingSet = Object.keys(pAddressMapping);\n\n\t\ttmpAddressMappingSet.forEach(\n\t\t\t(pInputAddress) =>\n\t\t\t{\n\t\t\t\tlet tmpNewDescriptorAddress = pAddressMapping[pInputAddress];\n\t\t\t\tlet tmpOldDescriptorAddress = false;\n\t\t\t\tlet tmpDescriptor = false;\n\n\t\t\t\t// See if there is a matching descriptor either by Address directly or Hash\n\t\t\t\tif (pInputAddress in pManyfestSchemaDescriptors)\n\t\t\t\t{\n\t\t\t\t\ttmpOldDescriptorAddress = pInputAddress;\n\t\t\t\t}\n\t\t\t\telse if (pInputAddress in tmpHashMapping)\n\t\t\t\t{\n\t\t\t\t\ttmpOldDescriptorAddress = tmpHashMapping[pInputAddress];\n\t\t\t\t}\n\n\t\t\t\t// If there was a matching descriptor in the manifest, store it in the temporary descriptor\n\t\t\t\tif (tmpOldDescriptorAddress)\n\t\t\t\t{\n\t\t\t\t\ttmpDescriptor = pManyfestSchemaDescriptors[tmpOldDescriptorAddress];\n\t\t\t\t\tdelete pManyfestSchemaDescriptors[tmpOldDescriptorAddress];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Create a new descriptor! Map it to the input address.\n\t\t\t\t\ttmpDescriptor = { Hash:pInputAddress };\n\t\t\t\t}\n\n\t\t\t\t// Now re-add the descriptor to the manyfest schema\n\t\t\t\tpManyfestSchemaDescriptors[tmpNewDescriptorAddress] = tmpDescriptor;\n\t\t\t});\n\n\t\treturn true;\n\t}\n\n\tsafeResolveAddressMappings(pManyfestSchemaDescriptors, pAddressMapping)\n\t{\n\t\t// This returns the descriptors as a new object, safely remapping without mutating the original schema Descriptors\n\t\tlet tmpManyfestSchemaDescriptors = JSON.parse(JSON.stringify(pManyfestSchemaDescriptors));\n\t\tthis.resolveAddressMappings(tmpManyfestSchemaDescriptors, pAddressMapping);\n\t\treturn tmpManyfestSchemaDescriptors;\n\t}\n\n\tmergeAddressMappings(pManyfestSchemaDescriptorsDestination, pManyfestSchemaDescriptorsSource)\n\t{\n\t\tif ((typeof(pManyfestSchemaDescriptorsSource) != 'object') || (typeof(pManyfestSchemaDescriptorsDestination) != 'object'))\n\t\t{\n\t\t\tthis.logError(`Attempted to merge two schema descriptors but both were not objects.`);\n\t\t\treturn false;\n\t\t}\n\n\t\tlet tmpSource = JSON.parse(JSON.stringify(pManyfestSchemaDescriptorsSource));\n\t\tlet tmpNewManyfestSchemaDescriptors = JSON.parse(JSON.stringify(pManyfestSchemaDescriptorsDestination));\n\n\t\t// The first passed-in set of descriptors takes precedence.\n\t\tlet tmpDescriptorAddresses = Object.keys(tmpSource);\n\n\t\ttmpDescriptorAddresses.forEach(\n\t\t\t(pDescriptorAddress) =>\n\t\t\t{\n\t\t\t\tif (!(pDescriptorAddress in tmpNewManyfestSchemaDescriptors))\n\t\t\t\t{\n\t\t\t\t\ttmpNewManyfestSchemaDescriptors[pDescriptorAddress] = tmpSource[pDescriptorAddress];\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn tmpNewManyfestSchemaDescriptors;\n\t}\n}\n\nmodule.exports = ManyfestSchemaManipulation;\n},{\"./Manyfest-LogToConsole.js\":5}],14:[function(require,module,exports){\n/**\n* @author <steven@velozo.com>\n*/\nconst libFableServiceProviderBase = require('fable-serviceproviderbase');\n\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\nlet libHashTranslation = require('./Manyfest-HashTranslation.js');\nlet libObjectAddressCheckAddressExists = require('./Manyfest-ObjectAddress-CheckAddressExists.js');\nlet libObjectAddressGetValue = require('./Manyfest-ObjectAddress-GetValue.js');\nlet libObjectAddressSetValue = require('./Manyfest-ObjectAddress-SetValue.js');\nlet libObjectAddressDeleteValue = require('./Manyfest-ObjectAddress-DeleteValue.js');\nlet libObjectAddressGeneration = require('./Manyfest-ObjectAddressGeneration.js');\nlet libSchemaManipulation = require('./Manyfest-SchemaManipulation.js');\n\nconst _DefaultConfiguration = { Scope:'DEFAULT', Descriptors: {} }\n\n/**\n * @typedef {{\n * Hash?: string,\n * Name?: string,\n * DataType?: string,\n * Required?: boolean,\n * Address?: string,\n * Description?: string,\n * [key: string]: any,\n * }} ManifestDescriptor\n */\n\n/**\n* Manyfest object address-based descriptions and manipulations.\n*\n* @class Manyfest\n*/\nclass Manyfest extends libFableServiceProviderBase\n{\n\tconstructor(pFable, pManifest, pServiceHash)\n\t{\n\t\tif (pFable === undefined)\n\t\t{\n\t\t\tsuper({});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsuper(pFable, pManifest, pServiceHash);\n\t\t}\n\n\t\t/** @type {Record<string, any>} */\n\t\tthis.options;\n\n this.serviceType = 'Manifest';\n\n\t\t// Wire in logging\n\t\tthis.logInfo = libSimpleLog;\n\t\tthis.logError = libSimpleLog;\n\n\t\t// Create an object address resolver and map in the functions\n\t\tthis.objectAddressCheckAddressExists = new libObjectAddressCheckAddressExists(this.logInfo, this.logError);\n\t\tthis.objectAddressGetValue = new libObjectAddressGetValue(this.logInfo, this.logError);\n\t\tthis.objectAddressSetValue = new libObjectAddressSetValue(this.logInfo, this.logError);\n\t\tthis.objectAddressDeleteValue = new libObjectAddressDeleteValue(this.logInfo, this.logError);\n\n\t\tif (!('defaultValues' in this.options))\n\t\t{\n\t\t\tthis.options.defaultValues = (\n\t\t\t\t{\n\t\t\t\t\t\"String\": \"\",\n\t\t\t\t\t\"Number\": 0,\n\t\t\t\t\t\"Float\": 0.0,\n\t\t\t\t\t\"Integer\": 0,\n\t\t\t\t\t\"PreciseNumber\": \"0.0\",\n\t\t\t\t\t\"Boolean\": false,\n\t\t\t\t\t\"Binary\": 0,\n\t\t\t\t\t\"DateTime\": 0,\n\t\t\t\t\t\"Array\": [],\n\t\t\t\t\t\"Object\": {},\n\t\t\t\t\t\"Null\": null\n\t\t\t\t});\n\t\t}\n\t\tif (!('strict' in this.options))\n\t\t{\n\t\t\tthis.options.strict = false;\n\t\t}\n\n\t\tthis.scope = undefined;\n\t\tthis.elementAddresses = undefined;\n\t\tthis.elementHashes = undefined;\n\t\tthis.elementDescriptors = undefined;\n\n\t\tthis.reset();\n\n\t\tif (typeof(this.options) === 'object')\n\t\t{\n\t\t\tthis.loadManifest(this.options);\n\t\t}\n\n\t\tthis.schemaManipulations = new libSchemaManipulation(this.logInfo, this.logError);\n\t\tthis.objectAddressGeneration = new libObjectAddressGeneration(this.logInfo, this.logError);\n\n\t\tthis.hashTranslations = new libHashTranslation(this.logInfo, this.logError);\n\n\t\tthis.numberRegex = /^[+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?$/;\n\t}\n\n\t/*************************************************************************\n\t * Schema Manifest Loading, Reading, Manipulation and Serialization Functions\n\t */\n\n\t// Reset critical manifest properties\n\treset()\n\t{\n\t\tthis.scope = 'DEFAULT';\n\t\tthis.elementAddresses = [];\n\t\tthis.elementHashes = {};\n\t\tthis.elementDescriptors = {};\n\t}\n\n\tclone()\n\t{\n\t\t// Make a copy of the options in-place\n\t\tlet tmpNewOptions = JSON.parse(JSON.stringify(this.options));\n\n\t\tlet tmpNewManyfest = new Manyfest(this.getManifest(), this.logInfo, this.logError, tmpNewOptions);\n\n\t\t// Import the hash translations\n\t\ttmpNewManyfest.hashTranslations.addTranslation(this.hashTranslations.translationTable);\n\n\t\treturn tmpNewManyfest;\n\t}\n\n\t// Deserialize a Manifest from a string\n\tdeserialize(pManifestString)\n\t{\n\t\t// TODO: Add guards for bad manifest string\n\t\treturn this.loadManifest(JSON.parse(pManifestString));\n\t}\n\n\t// Load a manifest from an object\n\tloadManifest(pManifest)\n\t{\n\t\tif (typeof(pManifest) !== 'object')\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading manifest; expecting an object but parameter was type ${typeof(pManifest)}.`);\n\t\t}\n\n\t\tlet tmpManifest = (typeof(pManifest) == 'object') ? pManifest : {};\n\n\t\tlet tmpDescriptorKeys = Object.keys(_DefaultConfiguration);\n\n\t\tfor (let i = 0; i < tmpDescriptorKeys.length; i++)\n\t\t{\n\t\t\tif (!(tmpDescriptorKeys[i] in tmpManifest))\n\t\t\t{\n\t\t\t\ttmpManifest[tmpDescriptorKeys[i]] = JSON.parse(JSON.stringify(_DefaultConfiguration[tmpDescriptorKeys[i]]));\n\t\t\t}\n\t\t}\n\n\t\tif ('Scope' in tmpManifest)\n\t\t{\n\t\t\tif (typeof(tmpManifest.Scope) === 'string')\n\t\t\t{\n\t\t\t\tthis.scope = tmpManifest.Scope;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis.logError(`(${this.scope}) Error loading scope from manifest; expecting a string but property was type ${typeof(tmpManifest.Scope)}.`, tmpManifest);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading scope from manifest object. Property \"Scope\" does not exist in the root of the object.`, tmpManifest);\n\t\t}\n\n\t\tif ('Descriptors' in tmpManifest)\n\t\t{\n\t\t\tif (typeof(tmpManifest.Descriptors) === 'object')\n\t\t\t{\n\t\t\t\tlet tmpDescriptionAddresses = Object.keys(tmpManifest.Descriptors);\n\t\t\t\tfor (let i = 0; i < tmpDescriptionAddresses.length; i++)\n\t\t\t\t{\n\t\t\t\t\tthis.addDescriptor(tmpDescriptionAddresses[i], tmpManifest.Descriptors[tmpDescriptionAddresses[i]]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis.logError(`(${this.scope}) Error loading description object from manifest object. Expecting an object in 'Manifest.Descriptors' but the property was type ${typeof(tmpManifest.Descriptors)}.`, tmpManifest);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading object description from manifest object. Property \"Descriptors\" does not exist in the root of the Manifest object.`, tmpManifest);\n\t\t}\n\n\t\tif ('HashTranslations' in tmpManifest)\n\t\t{\n\t\t\tif (typeof(tmpManifest.HashTranslations) === 'object')\n\t\t\t{\n\t\t\t\tfor (let i = 0; i < tmpManifest.HashTranslations.length; i++)\n\t\t\t\t{\n\t\t\t\t\t// Each translation is \n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Serialize the Manifest to a string\n\tserialize()\n\t{\n\t\treturn JSON.stringify(this.getManifest());\n\t}\n\n\tgetManifest()\n\t{\n\t\treturn (\n\t\t\t{\n\t\t\t\tScope: this.scope,\n\t\t\t\tDescriptors: JSON.parse(JSON.stringify(this.elementDescriptors)),\n\t\t\t\tHashTranslations: JSON.parse(JSON.stringify(this.hashTranslations.translationTable))\n\t\t\t});\n\t}\n\n\t/**\n\t * Add a descriptor to the manifest\n\t *\n\t * @param {string} pAddress - The address of the element to add the descriptor for.\n\t * @param {ManifestDescriptor} pDescriptor - The descriptor object to add.\n\t */\n\taddDescriptor(pAddress, pDescriptor)\n\t{\n\t\tif (typeof(pDescriptor) === 'object')\n\t\t{\n\t\t\t// Add the Address into the Descriptor if it doesn't exist:\n\t\t\tif (!('Address' in pDescriptor))\n\t\t\t{\n\t\t\t\tpDescriptor.Address = pAddress;\n\t\t\t}\n\n\t\t\tif (!(pAddress in this.elementDescriptors))\n\t\t\t{\n\t\t\t\tthis.elementAddresses.push(pAddress);\n\t\t\t}\n\n\t\t\t// Add the element descriptor to the schema\n\t\t\tthis.elementDescriptors[pAddress] = pDescriptor;\n\n\t\t\t// Always add the address as a hash\n\t\t\tthis.elementHashes[pAddress] = pAddress;\n\n\t\t\tif ('Hash' in pDescriptor)\n\t\t\t{\n\t\t\t\t// TODO: Check if this is a good idea or not..\n\t\t\t\t// Collisions are bound to happen with both representations of the address/hash in here and developers being able to create their own hashes.\n\t\t\t\tthis.elementHashes[pDescriptor.Hash] = pAddress;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpDescriptor.Hash = pAddress;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading object descriptor for address '${pAddress}' from manifest object. Expecting an object but property was type ${typeof(pDescriptor)}.`);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} pHash - The hash of the address to resolve.\n\t *\n\t * @return {ManifestDescriptor} The descriptor for the address\n\t */\n\tgetDescriptorByHash(pHash)\n\t{\n\t\treturn this.getDescriptor(this.resolveHashAddress(pHash));\n\t}\n\n\t/**\n\t * @param {string} pAddress - The address of the element to get the descriptor for.\n\t *\n\t * @return {ManifestDescriptor} The descriptor for the address\n\t */\n\tgetDescriptor(pAddress)\n\t{\n\t\treturn this.elementDescriptors[pAddress];\n\t}\n\n\t/**\n\t * execute an action function for each descriptor\n\t * @param {(d: ManifestDescriptor) => void} fAction - The action function to execute for each descriptor.\n\t */\n\teachDescriptor(fAction)\n\t{\n let tmpDescriptorAddresses = Object.keys(this.elementDescriptors);\n for (let i = 0; i < tmpDescriptorAddresses.length; i++)\n {\n fAction(this.elementDescriptors[tmpDescriptorAddresses[i]]);\n }\n\n\t}\n\n\t/*************************************************************************\n\t * Beginning of Object Manipulation (read & write) Functions\n\t */\n\t// Check if an element exists by its hash\n\tcheckAddressExistsByHash (pObject, pHash)\n\t{\n\t\treturn this.checkAddressExists(pObject,this.resolveHashAddress(pHash));\n\t}\n\n\t// Check if an element exists at an address\n\tcheckAddressExists (pObject, pAddress)\n\t{\n\t\treturn this.objectAddressCheckAddressExists.checkAddressExists(pObject, pAddress);\n\t}\n\n\t// Turn a hash into an address, factoring in the translation table.\n\tresolveHashAddress(pHash)\n\t{\n\t\tlet tmpAddress = undefined;\n\n\t\tlet tmpInElementHashTable = (pHash in this.elementHashes);\n\t\tlet tmpInTranslationTable = (pHash in this.hashTranslations.translationTable);\n\n\t\t// The most straightforward: the hash exists, no translations.\n\t\tif (tmpInElementHashTable && !tmpInTranslationTable)\n\t\t{\n\t\t\ttmpAddress = this.elementHashes[pHash];\n\t\t}\n\t\t// There is a translation from one hash to another, and, the elementHashes contains the pointer end\n\t\telse if (tmpInTranslationTable && (this.hashTranslations.translate(pHash) in this.elementHashes))\n\t\t{\n\t\t\ttmpAddress = this.elementHashes[this.hashTranslations.translate(pHash)];\n\t\t}\n\t\t// Use the level of indirection only in the Translation Table\n\t\telse if (tmpInTranslationTable)\n\t\t{\n\t\t\ttmpAddress = this.hashTranslations.translate(pHash);\n\t\t}\n\t\t// Just treat the hash as an address.\n\t\t// TODO: Discuss this ... it is magic but controversial\n\t\telse\n\t\t{\n\t\t\ttmpAddress = pHash;\n\t\t}\n\n\t\treturn tmpAddress;\n\t}\n\n\t// Get the value of an element by its hash\n\tgetValueByHash (pObject, pHash)\n\t{\n\t\tlet tmpValue = this.getValueAtAddress(pObject, this.resolveHashAddress(pHash));\n\n\t\tif (typeof(tmpValue) == 'undefined')\n\t\t{\n\t\t\t// Try to get a default if it exists\n\t\t\ttmpValue = this.getDefaultValue(this.getDescriptorByHash(pHash));\n\t\t}\n\n\t\treturn tmpValue;\n\t}\n\n\tlintAddress(pAddress)\n\t{\n\t\tlet tmpLintedAddress = pAddress.trim();\n\t\t// Check for a single . (but not a ..) at the end of the address and remove it.\n\t\tif (tmpLintedAddress.endsWith('..'))\n\t\t{\n\t\t\ttmpLintedAddress = tmpLintedAddress.slice(0, -1);\n\t\t}\n\t\telse if (tmpLintedAddress.endsWith('.'))\n\t\t{\n\t\t\ttmpLintedAddress = tmpLintedAddress.slice(0, -1);\n\t\t}\n\n\t\treturn tmpLintedAddress;\n\t}\n\n\t// Get the value of an element at an address\n\tgetValueAtAddress (pObject, pAddress)\n\t{\n\t\tlet tmpLintedAddress = this.lintAddress(pAddress);\n\t\tif (tmpLintedAddress == '')\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error getting value at address; address is an empty string.`, pObject);\n\t\t\treturn undefined;\n\t\t}\n\t\tlet tmpValue = this.objectAddressGetValue.getValueAtAddress(pObject, tmpLintedAddress);\n\n\t\tif (typeof(tmpValue) == 'undefined')\n\t\t{\n\t\t\t// Try to get a default if it exists\n\t\t\ttmpValue = this.getDefaultValue(this.getDescriptor(tmpLintedAddress));\n\t\t}\n\n\t\treturn tmpValue;\n\t}\n\n\t// Set the value of an element by its hash\n\tsetValueByHash(pObject, pHash, pValue)\n\t{\n\t\treturn this.setValueAtAddress(pObject, this.resolveHashAddress(pHash), pValue);\n\t}\n\n\t// Set the value of an element at an address\n\tsetValueAtAddress (pObject, pAddress, pValue)\n\t{\n\t\tlet tmpLintedAddress = this.lintAddress(pAddress);\n\t\treturn this.objectAddressSetValue.setValueAtAddress(pObject, tmpLintedAddress, pValue);\n\t}\n\n\t// Delete the value of an element by its hash\n\tdeleteValueByHash(pObject, pHash, pValue)\n\t{\n\t\treturn this.deleteValueAtAddress(pObject, this.resolveHashAddress(pHash), pValue);\n\t}\n\n\t// Delete the value of an element at an address\n\tdeleteValueAtAddress (pObject, pAddress, pValue)\n\t{\n\t\tlet tmpLintedAddress = this.lintAddress(pAddress);\n\t\treturn this.objectAddressDeleteValue.deleteValueAtAddress(pObject, tmpLintedAddress, pValue);\n\t}\n\n\t// Validate the consistency of an object against the schema\n\tvalidate(pObject)\n\t{\n\t\tlet tmpValidationData =\n\t\t{\n\t\t\tError: null,\n\t\t\tErrors: [],\n\t\t\tMissingElements:[]\n\t\t};\n\n\t\tif (typeof(pObject) !== 'object')\n\t\t{\n\t\t\ttmpValidationData.Error = true;\n\t\t\ttmpValidationData.Errors.push(`Expected passed in object to be type object but was passed in ${typeof(pObject)}`);\n\t\t}\n\n\t\tlet addValidationError = (pAddress, pErrorMessage) =>\n\t\t{\n\t\t\ttmpValidationData.Error = true;\n\t\t\ttmpValidationData.Errors.push(`Element at address \"${pAddress}\" ${pErrorMessage}.`);\n\t\t};\n\n\t\t// Now enumerate through the values and check for anomalies based on the schema\n\t\tfor (let i = 0; i < this.elementAddresses.length; i++)\n\t\t{\n\t\t\tlet tmpDescriptor = this.getDescriptor(this.elementAddresses[i]);\n\t\t\tlet tmpValueExists = this.checkAddressExists(pObject, tmpDescriptor.Address);\n\t\t\tlet tmpValue = this.getValueAtAddress(pObject, tmpDescriptor.Address);\n\n\t\t\tif ((typeof(tmpValue) == 'undefined') || !tmpValueExists)\n\t\t\t{\n\t\t\t\t// This will technically mean that `Object.Some.Value = undefined` will end up showing as \"missing\"\n\t\t\t\t// TODO: Do we want to do a different message based on if the property exists but is undefined?\n\t\t\t\ttmpValidationData.MissingElements.push(tmpDescriptor.Address);\n\t\t\t\tif (tmpDescriptor.Required || this.options.strict)\n\t\t\t\t{\n\t\t\t\t\taddValidationError(tmpDescriptor.Address, 'is flagged REQUIRED but is not set in the object');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now see if there is a data type specified for this element\n\t\t\tif (tmpDescriptor.DataType)\n\t\t\t{\n\t\t\t\tlet tmpElementType = typeof(tmpValue);\n\t\t\t\tswitch(tmpDescriptor.DataType.toString().trim().toLowerCase())\n\t\t\t\t{\n\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tif (tmpElementType != 'string')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"precisenumber\":\n\t\t\t\t\t\tif (tmpElementType != 'string')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (!this.numberRegex.test(tmpValue))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is not a valid number`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tif (tmpElementType != 'number')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'integer':\n\t\t\t\t\t\tif (tmpElementType != 'number')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlet tmpValueString = tmpValue.toString();\n\t\t\t\t\t\t\tif (tmpValueString.indexOf('.') > -1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// TODO: Is this an error?\n\t\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but has a decimal point in the number.`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'float':\n\t\t\t\t\t\tif (tmpElementType != 'number')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'datetime':\n\t\t\t\t\t\tlet tmpValueDate = new Date(tmpValue);\n\t\t\t\t\t\tif (tmpValueDate.toString() == 'Invalid Date')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is not parsable as a Date by Javascript`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// Check if this is a string, in the default case\n\t\t\t\t\t\t// Note this is only when a DataType is specified and it is an unrecognized data type.\n\t\t\t\t\t\tif (tmpElementType != 'string')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} (which auto-converted to String because it was unrecognized) but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn tmpValidationData;\n\t}\n\n\t/**\n\t * Returns a default value, or, the default value for the data type (which is overridable with configuration)\n\t *\n\t * @param {ManifestDescriptor} pDescriptor - The descriptor definition.\n\t */\n\tgetDefaultValue(pDescriptor)\n\t{\n\t\tif (typeof(pDescriptor) != 'object')\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ('Default' in pDescriptor)\n\t\t{\n\t\t\treturn pDescriptor.Default;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Default to a null if it doesn't have a type specified.\n\t\t\t// This will ensure a placeholder is created but isn't misinterpreted.\n\t\t\tlet tmpDataType = ('DataType' in pDescriptor) ? pDescriptor.DataType : 'String';\n\t\t\tif (tmpDataType in this.options.defaultValues)\n\t\t\t{\n\t\t\t\treturn this.options.defaultValues[tmpDataType];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// give up and return null\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Enumerate through the schema and populate default values if they don't exist.\n\tpopulateDefaults(pObject, pOverwriteProperties)\n\t{\n\t\treturn this.populateObject(pObject, pOverwriteProperties,\n\t\t\t// This just sets up a simple filter to see if there is a default set.\n\t\t\t(pDescriptor) =>\n\t\t\t{\n\t\t\t\treturn ('Default' in pDescriptor);\n\t\t\t});\n\t}\n\n\t// Forcefully populate all values even if they don't have defaults.\n\t// Based on type, this can do unexpected things.\n\tpopulateObject(pObject, pOverwriteProperties, fFilter)\n\t{\n\t\t// Automatically create an object if one isn't passed in.\n\t\tlet tmpObject = (typeof(pObject) === 'object') ? pObject : {};\n\t\t// Default to *NOT OVERWRITING* properties\n\t\tlet tmpOverwriteProperties = (typeof(pOverwriteProperties) == 'undefined') ? false : pOverwriteProperties;\n\t\t// This is a filter function, which is passed the schema and allows complex filtering of population\n\t\t// The default filter function just returns true, populating everything.\n\t\tlet tmpFilterFunction = (typeof(fFilter) == 'function') ? fFilter : (pDescriptor) => { return true; };\n\n\t\tthis.elementAddresses.forEach(\n\t\t\t(pAddress) =>\n\t\t\t{\n\t\t\t\tlet tmpDescriptor = this.getDescriptor(pAddress);\n\t\t\t\t// Check the filter function to see if this is an address we want to set the value for.\n\t\t\t\tif (tmpFilterFunction(tmpDescriptor))\n\t\t\t\t{\n\t\t\t\t\t// If we are overwriting properties OR the property does not exist\n\t\t\t\t\tif (tmpOverwriteProperties || !this.checkAddressExists(tmpObject, pAddress))\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.setValueAtAddress(tmpObject, pAddress, this.getDefaultValue(tmpDescriptor));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn tmpObject;\n\t}\n};\n\nmodule.exports = Manyfest;\n\n},{\"./Manyfest-HashTranslation.js\":4,\"./Manyfest-LogToConsole.js\":5,\"./Manyfest-ObjectAddress-CheckAddressExists.js\":6,\"./Manyfest-ObjectAddress-DeleteValue.js\":7,\"./Manyfest-ObjectAddress-GetValue.js\":8,\"./Manyfest-ObjectAddress-SetValue.js\":10,\"./Manyfest-ObjectAddressGeneration.js\":11,\"./Manyfest-SchemaManipulation.js\":13,\"fable-serviceproviderbase\":2}]},{},[14])(14)\n});\n\n","/**\n* Fable Service Base\n* @author <steven@velozo.com>\n*/\n\nconst libPackage = require('../package.json');\n\nclass FableServiceProviderBase\n{\n\t// The constructor can be used in two ways:\n\t// 1) With a fable, options object and service hash (the options object and service hash are optional)\n\t// 2) With an object or nothing as the first parameter, where it will be treated as the options object\n\tconstructor(pFable, pOptions, pServiceHash)\n\t{\n\t\t// Check if a fable was passed in; connect it if so\n\t\tif ((typeof(pFable) === 'object') && pFable.isFable)\n\t\t{\n\t\t\tthis.connectFable(pFable);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.fable = false;\n\t\t}\n\n\t\t// Initialize the services map if it wasn't passed in\n\t\t/** @type {Object} */\n\t\tthis._PackageFableServiceProvider = libPackage;\n\n\t\t// initialize options and UUID based on whether the fable was passed in or not.\n\t\tif (this.fable)\n\t\t{\n\t\t\tthis.UUID = pFable.getUUID();\n\t\t\tthis.options = (typeof(pOptions) === 'object') ? pOptions\n\t\t\t\t\t\t\t: {};\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// With no fable, check to see if there was an object passed into either of the first two\n\t\t\t// Parameters, and if so, treat it as the options object\n\t\t\tthis.options = ((typeof(pFable) === 'object') && !pFable.isFable) ? pFable\n\t\t\t\t\t\t\t: (typeof(pOptions) === 'object') ? pOptions\n\t\t\t\t\t\t\t: {};\n\t\t\tthis.UUID = `CORE-SVC-${Math.floor((Math.random() * (99999 - 10000)) + 10000)}`\n\t\t}\n\n\t\t// It's expected that the deriving class will set this\n\t\tthis.serviceType = `Unknown-${this.UUID}`;\n\n\t\t// The service hash is used to identify the specific instantiation of the service in the services map\n\t\tthis.Hash = (typeof(pServiceHash) === 'string') ? pServiceHash \n\t\t\t\t\t: (!this.fable && (typeof(pOptions) === 'string')) ? pOptions\n\t\t\t\t\t: `${this.UUID}`;\n\t}\n\n\tconnectFable(pFable)\n\t{\n\t\tif ((typeof(pFable) !== 'object') || (!pFable.isFable))\n\t\t{\n\t\t\tlet tmpErrorMessage = `Fable Service Provider Base: Cannot connect to Fable, invalid Fable object passed in. The pFable parameter was a [${typeof(pFable)}].}`;\n\t\t\tconsole.log(tmpErrorMessage);\n\t\t\treturn new Error(tmpErrorMessage);\n\t\t}\n\n\t\tif (!this.fable)\n\t\t{\n\t\t\tthis.fable = pFable;\n\t\t}\n\n\t\tif (!this.log)\n\t\t{\n\t\t\tthis.log = this.fable.Logging;\n\t\t}\n\t\tif (!this.services)\n\t\t{\n\t\t\tthis.services = this.fable.services;\n\t\t}\n\n\t\tif (!this.servicesMap)\n\t\t{\n\t\t\tthis.servicesMap = this.fable.servicesMap;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tstatic isFableService = true;\n}\n\nmodule.exports = FableServiceProviderBase;\n\n// This is left here in case we want to go back to having different code/base class for \"core\" services\nmodule.exports.CoreServiceProviderBase = FableServiceProviderBase;","// When a boxed property is passed in, it should have quotes of some\n// kind around it.\n//\n// For instance:\n// \t\tMyValues['Name']\n// \t\tMyValues[\"Age\"]\n// \t\tMyValues[`Cost`]\n//\n// This function removes the wrapping quotes.\n//\n// Please note it *DOES NOT PARSE* template literals, so backticks just\n// end up doing the same thing as other quote types.\n//\n// TODO: Should template literals be processed? If so what state do they have access to? That should happen here if so.\n// TODO: Make a simple class include library with these\nconst cleanWrapCharacters = (pCharacter, pString) =>\n{\n\tif (pString.startsWith(pCharacter) && pString.endsWith(pCharacter))\n\t{\n\t\treturn pString.substring(1, pString.length - 1);\n\t}\n\telse\n\t{\n\t\treturn pString;\n\t}\n};\n\nmodule.exports = cleanWrapCharacters;","/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\n/**\n* Hash Translation\n*\n* This is a very simple translation table for hashes, which allows the same schema to resolve\n* differently based on a loaded translation table.\n*\n* This is to prevent the requirement for mutating schemas over and over again when we want to\n* reuse the structure but look up data elements by different addresses.\n*\n* One side-effect of this is that a translation table can \"override\" the built-in hashes, since\n* this is always used to resolve hashes before any of the functionCallByHash(pHash, ...) perform\n* their lookups by hash.\n*\n* @class ManyfestHashTranslation\n*/\nclass ManyfestHashTranslation\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) === 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) === 'function') ? pErrorLog : libSimpleLog;\n\n this.translationTable = {};\n\t}\n\n translationCount()\n {\n return Object.keys(this.translationTable).length;\n }\n\n addTranslation(pTranslation)\n {\n // This adds a translation in the form of:\n // { \"SourceHash\": \"DestinationHash\", \"SecondSourceHash\":\"SecondDestinationHash\" }\n if (typeof(pTranslation) != 'object')\n {\n this.logError(`Hash translation addTranslation expected a translation be type object but was passed in ${typeof(pTranslation)}`);\n return false;\n }\n\n let tmpTranslationSources = Object.keys(pTranslation)\n\n tmpTranslationSources.forEach(\n (pTranslationSource) =>\n {\n if (typeof(pTranslation[pTranslationSource]) != 'string')\n {\n this.logError(`Hash translation addTranslation expected a translation destination hash for [${pTranslationSource}] to be a string but the referrant was a ${typeof(pTranslation[pTranslationSource])}`);\n }\n else\n {\n this.translationTable[pTranslationSource] = pTranslation[pTranslationSource];\n }\n });\n }\n\n removeTranslationHash(pTranslationHash)\n {\n if (pTranslationHash in this.translationTable)\n {\n delete this.translationTable[pTranslationHash];\n }\n }\n\n // This removes translations.\n // If passed a string, just removes the single one.\n // If passed an object, it does all the source keys.\n removeTranslation(pTranslation)\n {\n if (typeof(pTranslation) == 'string')\n {\n this.removeTranslationHash(pTranslation);\n return true;\n }\n else if (typeof(pTranslation) == 'object')\n {\n let tmpTranslationSources = Object.keys(pTranslation)\n\n tmpTranslationSources.forEach(\n (pTranslationSource) =>\n {\n this.removeTranslation(pTranslationSource);\n });\n return true;\n }\n else\n {\n this.logError(`Hash translation removeTranslation expected either a string or an object but the passed-in translation was type ${typeof(pTranslation)}`);\n return false;\n }\n }\n\n clearTranslations()\n {\n this.translationTable = {};\n }\n\n translate(pTranslation)\n {\n if (pTranslation in this.translationTable)\n {\n return this.translationTable[pTranslation];\n }\n else\n {\n return pTranslation;\n }\n }\n}\n\nmodule.exports = ManyfestHashTranslation;","/**\n* @author <steven@velozo.com>\n*/\n\n/**\n* Manyfest simple logging shim (for browser and dependency-free running)\n*/\n\nconst logToConsole = (pLogLine, pLogObject) =>\n{\n let tmpLogLine = (typeof(pLogLine) === 'string') ? pLogLine : '';\n\n console.log(`[Manyfest] ${tmpLogLine}`);\n\n if (pLogObject) console.log(JSON.stringify(pLogObject));\n};\n\nmodule.exports = logToConsole;","/**\n* @author <steven@velozo.com>\n*/\nconst libSimpleLog = require('./Manyfest-LogToConsole.js');\n// This is for resolving functions mid-address\nconst libGetObjectValue = require('./Manyfest-ObjectAddress-GetValue.js');\n\n// TODO: Just until this is a fable service.\nlet _MockFable = { DataFormat: require('./Manyfest-ObjectAddress-Parser.js') };\n\n/**\n* Object Address Resolver\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n*\n* @class ManyfestObjectAddressResolverCheckAddressExists\n*/\nclass ManyfestObjectAddressResolverCheckAddressExists\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.getObjectValueClass = new libGetObjectValue(this.logInfo, this.logError);\n\t}\n\n\t// Check if an address exists.\n\t//\n\t// This is necessary because the getValueAtAddress function is ambiguous on\n\t// whether the element/property is actually there or not (it returns\n\t// undefined whether the property exists or not). This function checks for\n\t// existance and returns true or false dependent.\n\tcheckAddressExists (pObject, pAddress, pRootObject)\n\t{\n\t\t// TODO: Should these throw an error?\n\t\t// Make sure pObject is an object\n\t\tif (typeof(pObject) != 'object') return false;\n\t\t// Make sure pAddress is a string\n\t\tif (typeof(pAddress) != 'string') return false;\n\n\t\t// Set the root object to the passed-in object if it isn't set yet. This is expected to be the root object.\n\t\t// NOTE: This was added to support functions mid-stream\n\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t// DONE: Make this work for things like SomeRootObject.Metadata[\"Some.People.Use.Bad.Object.Property.Names\"]\n\t\tlet tmpAddressPartBeginning = _MockFable.DataFormat.stringGetFirstSegment(pAddress);\n\n\t\t// This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)\n\t\tif (tmpAddressPartBeginning.length == pAddress.length)\n\t\t{\n\t\t\t// Check if the address refers to a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = pAddress.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(pAddress) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = pAddress.substring(0, tmpFunctionStartIndex).trim();\n\n\t\t\t\tif (((tmpFunctionAddress in pObject)) && (typeof(pObject[tmpFunctionAddress]) == 'function'))\n\t\t\t\t{\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Check if the property exists.\n\t\t\t\t\treturn (tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Use the new in operator to see if the element is in the array\n\t\t\t\t\treturn (tmpBoxedPropertyNumber in pObject[tmpBoxedPropertyName]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Check if the property exists\n\t\t\t\treturn (pAddress in pObject);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet tmpSubObjectName = tmpAddressPartBeginning;\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpAddressPartBeginning.length+1);\n\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = tmpSubObjectName.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(tmpSubObjectName) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = tmpSubObjectName.substring(0, tmpFunctionStartIndex).trim();\n\t\t\t\t//tmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\n\t\t\t\tif (!typeof(pObject[tmpFunctionAddress]) == 'function')\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Now see if the function has arguments.\n\t\t\t\t// Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *\n\t\t\t\tlet tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(tmpSubObjectName.substring(tmpFunctionAddress.length), 0), ',');\n\t\t\t\tif ((tmpFunctionArguments.length == 0) || (tmpFunctionArguments[0] == ''))\n\t\t\t\t{\n\t\t\t\t\t// No arguments... just call the function (bound to the scope of the object it is contained withing)\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject), tmpNewAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tlibSimpleLog.log(`Error calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tlibSimpleLog.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlet tmpArgumentValues = [];\n\n\t\t\t\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t\t\t\t// Now get the value for each argument\n\t\t\t\t\tfor (let i = 0; i < tmpFunctionArguments.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Resolve the values for each subsequent entry\n\t\t\t\t\t\t// NOTE: This is where the resolves get really tricky. Recursion within recursion. Programming gom jabbar, yo.\n\t\t\t\t\t\ttmpArgumentValues.push(this.getObjectValueClass.getValueAtAddress(tmpRootObject, tmpFunctionArguments[i]));\n\t\t\t\t\t}\n\n\t\t\t\t\t//return this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpRootObject);\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.checkAddressExists(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tlibSimpleLog.log(`Error calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tlibSimpleLog.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// Because this is an impossible address, the property doesn't exist\n\t\t\t\t\t// TODO: Should we throw an error in this condition?\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.checkAddressExists(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.checkAddressExists(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\treturn this.checkAddressExists(pObject[tmpSubObjectName], tmpNewAddress, tmpRootObject);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.checkAddressExists(pObject[tmpSubObjectName], tmpNewAddress, tmpRootObject);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressResolverCheckAddressExists;\n","/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\nlet fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');\nlet fParseConditionals = require(`../source/Manyfest-ParseConditionals.js`)\n\n/**\n* Object Address Resolver - DeleteValue\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n* TODO: Once we validate this pattern is good to go, break these out into\n* three separate modules.\n*\n* @class ManyfestObjectAddressResolverDeleteValue\n*/\nclass ManyfestObjectAddressResolverDeleteValue\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.cleanWrapCharacters = fCleanWrapCharacters;\n\t}\n\n\t// TODO: Dry me\n\tcheckRecordFilters(pAddress, pRecord)\n\t{\n\t\treturn fParseConditionals(this, pAddress, pRecord);\n\t}\n\n\t// Delete the value of an element at an address\n\tdeleteValueAtAddress (pObject, pAddress, pParentAddress)\n\t{\n\t\t// Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object)\n\t\tif (typeof(pObject) != 'object') return undefined;\n\t\t// Make sure pAddress (the address we are resolving) is a string\n\t\tif (typeof(pAddress) != 'string') return undefined;\n\t\t// Stash the parent address for later resolution\n\t\tlet tmpParentAddress = \"\";\n\t\tif (typeof(pParentAddress) == 'string')\n\t\t{\n\t\t\ttmpParentAddress = pParentAddress;\n\t\t}\n\n\t\t// TODO: Make this work for things like SomeRootObject.Metadata[\"Some.People.Use.Bad.Object.Property.Names\"]\n\t\tlet tmpSeparatorIndex = pAddress.indexOf('.');\n\n\t\t// This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)\n\t\tif (tmpSeparatorIndex == -1)\n\t\t{\n\t\t\t// Check if the address refers to a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\n\t\t\t// Check for the Object Set Type marker.\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Return the value in the property\n\t\t\t\t\tdelete pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference];\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tdelete pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber];\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlet tmpInputArray = pObject[tmpBoxedPropertyName];\n\t\t\t\t// Count from the end to the beginning so splice doesn't %&%#$ up the array\n\t\t\t\tfor (let i = tmpInputArray.length - 1; i >= 0; i--)\n\t\t\t\t{\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpInputArray[i]);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Delete elements end to beginning\n\t\t\t\t\t\ttmpInputArray.splice(i, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t// The object has been flagged as an object set, so treat it as such\n\t\t\telse if (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tdelete pObject[tmpObjectPropertyName];\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Now is the point in recursion to return the value in the address\n\t\t\t\tdelete pObject[pAddress];\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);\n\n\t\t\t// BOXED ELEMENTS\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// Check if the boxed property is an object.\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, tmpParentAddress);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, tmpParentAddress);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the array and grab the addresses from there.\n\t\t\t\tlet tmpArrayProperty = pObject[tmpBoxedPropertyName];\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpBoxedPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpArrayProperty.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}[${i}]`;\n\t\t\t\t\tlet tmpValue = this.deleteValueAtAddress(pObject[tmpBoxedPropertyName][i], tmpNewAddress, tmpPropertyParentAddress);\n\n\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// OBJECT SET\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\t\t\tif (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the Object and grab the addresses from there.\n\t\t\t\tlet tmpObjectProperty = pObject[tmpObjectPropertyName];\n\t\t\t\tlet tmpObjectPropertyKeys = Object.keys(tmpObjectProperty);\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpObjectPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpObjectPropertyKeys.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}.${tmpObjectPropertyKeys[i]}`;\n\t\t\t\t\tlet tmpValue = this.deleteValueAtAddress(pObject[tmpObjectPropertyName][tmpObjectPropertyKeys[i]], tmpNewAddress, tmpPropertyParentAddress);\n\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpValue);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.deleteValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressResolverDeleteValue;","/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\nlet fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');\nlet fParseConditionals = require(`../source/Manyfest-ParseConditionals.js`);\n\nlet _MockFable = { DataFormat: require('./Manyfest-ObjectAddress-Parser.js') };\n\n/**\n* Object Address Resolver - GetValue\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n* TODO: Once we validate this pattern is good to go, break these out into\n* three separate modules.\n*\n* @class ManyfestObjectAddressResolverGetValue\n*/\nclass ManyfestObjectAddressResolverGetValue\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.cleanWrapCharacters = fCleanWrapCharacters;\n\t}\n\n\tcheckRecordFilters(pAddress, pRecord)\n\t{\n\t\treturn fParseConditionals(this, pAddress, pRecord);\n\t}\n\n\t// Get the value of an element at an address\n\tgetValueAtAddress (pObject, pAddress, pParentAddress, pRootObject)\n\t{\n\t\t// Make sure pObject (the object we are meant to be recursing) is an object (which could be an array or object)\n\t\tif (typeof(pObject) != 'object')\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\t\tif (pObject === null)\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\t\t// Make sure pAddress (the address we are resolving) is a string\n\t\tif (typeof(pAddress) != 'string')\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\t\t// Stash the parent address for later resolution\n\t\tlet tmpParentAddress = \"\";\n\t\tif (typeof(pParentAddress) == 'string')\n\t\t{\n\t\t\ttmpParentAddress = pParentAddress;\n\t\t}\n\n\t\t// Set the root object to the passed-in object if it isn't set yet. This is expected to be the root object.\n\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t// DONE: Make this work for things like SomeRootObject.Metadata[\"Some.People.Use.Bad.Object.Property.Names\"]\n\t\tlet tmpAddressPartBeginning = _MockFable.DataFormat.stringGetFirstSegment(pAddress);\n\n\t\t// Adding simple back-navigation in objects\n\t\tif (tmpAddressPartBeginning == '')\n\t\t{\n\t\t\t// Given an address of \"Bundle.Contract.IDContract...Project.IDProject\" the ... would be interpreted as two back-navigations from IDContract.\n\t\t\t// When the address is passed in, though, the first . is already eliminated. So we can count the dots.\n\t\t\tlet tmpParentAddressParts = _MockFable.DataFormat.stringGetSegments(tmpParentAddress);\n\n\t\t\tlet tmpBackNavigationCount = 0;\n\n\t\t\t// Count the number of dots\n\t\t\tfor (let i = 0; i < pAddress.length; i++)\n\t\t\t{\n\t\t\t\tif (pAddress.charAt(i) != '.')\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttmpBackNavigationCount++;\n\t\t\t}\n\n\t\t\tlet tmpParentAddressLength = tmpParentAddressParts.length - tmpBackNavigationCount;\n\n\t\t\tif (tmpParentAddressLength < 0)\n\t\t\t{\n\t\t\t\t// We are trying to back navigate more than we can.\n\t\t\t\t// TODO: Should this be undefined or should we bank out at the bottom and try to go forward?\n\t\t\t\t// This seems safest for now.\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// We are trying to back navigate to a parent object.\n\t\t\t\t// Recurse with the back-propagated parent address, and, the new address without the back-navigation dots.\n\t\t\t\tlet tmpRecurseAddress = pAddress.slice(tmpBackNavigationCount);\n\t\t\t\tif (tmpParentAddressLength > 0)\n\t\t\t\t{\n\t\t\t\t\ttmpRecurseAddress = `${tmpParentAddressParts.slice(0, tmpParentAddressLength).join('.')}.${tmpRecurseAddress}`;\n\t\t\t\t}\n\t\t\t\tthis.logInfo(`Back-navigation detected. Recursing back to address [${tmpRecurseAddress}]`);\n\t\t\t\treturn this.getValueAtAddress(tmpRootObject, tmpRecurseAddress);\n\t\t\t}\n\t\t}\n\n\t\t// This is the terminal address string (no more dots so the RECUSION ENDS IN HERE somehow)\n\t\tif (tmpAddressPartBeginning.length == pAddress.length)\n\t\t{\n\t\t\t// TODO: Optimize this by having these calls only happen when the previous fails.\n\t\t\t// TODO: Alternatively look for all markers in one pass?\n\t\t\t// Check if the address refers to a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\n\t\t\t// Check for the Object Set Type marker.\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = pAddress.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(pAddress) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = pAddress.substring(0, tmpFunctionStartIndex).trim();\n\n\t\t\t\tif (!typeof(pObject[tmpFunctionAddress]) == 'function')\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Now see if the function has arguments.\n\t\t\t\t// Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *\n\t\t\t\tlet tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(pAddress.substring(tmpFunctionAddress.length), 0), ',');\n\t\t\t\tif ((tmpFunctionArguments.length == 0) || (tmpFunctionArguments[0] == ''))\n\t\t\t\t{\n\t\t\t\t\t// No arguments... just call the function (bound to the scope of the object it is contained withing)\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn pObject[tmpFunctionAddress].apply(pObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlet tmpArgumentValues = [];\n\n\t\t\t\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t\t\t\t// Now get the value for each argument\n\t\t\t\t\tfor (let i = 0; i < tmpFunctionArguments.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Resolve the values for each subsequent entry\n\t\t\t\t\t\t// Check if the argument value is a string literal or a reference to an address\n\t\t\t\t\t\tif ((tmpFunctionArguments[i].length >= 2)\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(0) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"`\"))\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"`\")))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a string literal\n\t\t\t\t\t\t\ttmpArgumentValues.push(tmpFunctionArguments[i].substring(1, tmpFunctionArguments[i].length-1));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a hash address\n\t\t\t\t\t\t\ttmpArgumentValues.push(this.getValueAtAddress(tmpRootObject, tmpFunctionArguments[i]));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Return the value in the property\n\t\t\t\t\treturn pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber];\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tlet tmpInputArray = pObject[tmpBoxedPropertyName];\n\t\t\t\tlet tmpOutputArray = [];\n\t\t\t\tfor (let i = 0; i < tmpInputArray.length; i++)\n\t\t\t\t{\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpInputArray[i]);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpOutputArray.push(tmpInputArray[i]);\n\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmpOutputArray;\n\t\t\t}\n\t\t\t// The object has been flagged as an object set, so treat it as such\n\t\t\telse if (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn pObject[tmpObjectPropertyName];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Now is the point in recursion to return the value in the address\n\t\t\t\tif (typeof(pObject[pAddress]) != null)\n\t\t\t\t{\n\t\t\t\t\treturn pObject[pAddress];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//let tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);\n\t\t\t//let tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);\n\t\t\tlet tmpSubObjectName = tmpAddressPartBeginning;\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpAddressPartBeginning.length+1);\n\n\t\t\t// BOXED ELEMENTS\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\n\t\t\t// Check if there is a function somewhere in the address... parenthesis start should only be in a function\n\t\t\tlet tmpFunctionStartIndex = tmpSubObjectName.indexOf('(');\n\n\t\t\t// NOTE THAT FUNCTIONS MUST RESOLVE FIRST\n\t\t\t// Functions look like this\n\t\t\t// \t\tMyFunction()\n\t\t\t// \t\tMyFunction(Some.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address)\n\t\t\t// \t\tMyFunction(Some.Address,Some.Other.Address,Some.Third.Address)\n\t\t\t//\n\t\t\t// This could be enhanced to allow purely numeric and string values to be passed to the function. For now,\n\t\t\t// To heck with that. This is a simple function call.\n\t\t\t//\n\t\t\t// The requirements to detect a function are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpFunctionStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (_MockFable.DataFormat.stringCountEnclosures(tmpSubObjectName) > 0))\n\t\t\t{\n\t\t\t\tlet tmpFunctionAddress = tmpSubObjectName.substring(0, tmpFunctionStartIndex).trim();\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\n\t\t\t\tif (!typeof(pObject[tmpFunctionAddress]) == 'function')\n\t\t\t\t{\n\t\t\t\t\t// The address suggests it is a function, but it is not.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Now see if the function has arguments.\n\t\t\t\t// Implementation notes: * ARGUMENTS MUST SHARE THE SAME ROOT OBJECT CONTEXT *\n\t\t\t\tlet tmpFunctionArguments = _MockFable.DataFormat.stringGetSegments(_MockFable.DataFormat.stringGetEnclosureValueByIndex(tmpSubObjectName.substring(tmpFunctionAddress.length), 0), ',');\n\t\t\t\tif ((tmpFunctionArguments.length == 0) || (tmpFunctionArguments[0] == ''))\n\t\t\t\t{\n\t\t\t\t\t// No arguments... just call the function (bound to the scope of the object it is contained withing)\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpFunctionAddress].apply(pObject), tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlet tmpArgumentValues = [];\n\n\t\t\t\t\tlet tmpRootObject = (typeof(pRootObject) == 'undefined') ? pObject : pRootObject;\n\n\t\t\t\t\t// Now get the value for each argument\n\t\t\t\t\tfor (let i = 0; i < tmpFunctionArguments.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Resolve the values for each subsequent entry\n\t\t\t\t\t\t// Check if the argument value is a string literal or a reference to an address\n\t\t\t\t\t\tif ((tmpFunctionArguments[i].length >= 2)\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(0) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(0) == \"`\"))\n\t\t\t\t\t\t\t&&\n\t\t\t\t\t\t\t((tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == '\"')\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"'\")\n\t\t\t\t\t\t\t|| (tmpFunctionArguments[i].charAt(tmpFunctionArguments[i].length-1) == \"`\")))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a string literal\n\t\t\t\t\t\t\ttmpArgumentValues.push(tmpFunctionArguments[i].substring(1, tmpFunctionArguments[i].length-1));\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// This is a hash address\n\t\t\t\t\t\t\ttmpArgumentValues.push(this.getValueAtAddress(tmpRootObject, tmpFunctionArguments[i]));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tmpFunctionAddress in pObject)\n\t\t\t\t\t{\n\t\t\t\t\t\ttry\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpFunctionAddress].apply(pObject, tmpArgumentValues), tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch(pError)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// The function call failed, so the address doesn't exist\n\t\t\t\t\t\t\tconsole.log(`Error in getValueAtAddress calling function ${tmpFunctionAddress} (address [${pAddress}]): ${pError.message}`);\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// The function doesn't exist, so the address doesn't exist\n\t\t\t\t\t\tconsole.log(`Function ${tmpFunctionAddress} does not exist (address [${pAddress}])`);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\t// Check if the boxed property is an object.\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.getValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// The requirements to detect a boxed set element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\telse if ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket is after the start bracket\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is nothing in the brackets\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex == 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tif (!Array.isArray(pObject[tmpBoxedPropertyName]))\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the array and grab the addresses from there.\n\t\t\t\tlet tmpArrayProperty = pObject[tmpBoxedPropertyName];\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpBoxedPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpArrayProperty.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}[${i}]`;\n\t\t\t\t\tlet tmpValue = this.getValueAtAddress(pObject[tmpBoxedPropertyName][i], tmpNewAddress, tmpPropertyParentAddress, tmpRootObject);\n\n\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// OBJECT SET\n\t\t\t// Note this will not work with a bracket in the same address box set\n\t\t\tlet tmpObjectTypeMarkerIndex = pAddress.indexOf('{}');\n\t\t\tif (tmpObjectTypeMarkerIndex > 0)\n\t\t\t{\n\t\t\t\tlet tmpObjectPropertyName = pAddress.substring(0, tmpObjectTypeMarkerIndex).trim();\n\n\t\t\t\tif (typeof(pObject[tmpObjectPropertyName]) != 'object')\n\t\t\t\t{\n\t\t\t\t\t// We asked for a set from an array but it isnt' an array.\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// We need to enumerate the Object and grab the addresses from there.\n\t\t\t\tlet tmpObjectProperty = pObject[tmpObjectPropertyName];\n\t\t\t\tlet tmpObjectPropertyKeys = Object.keys(tmpObjectProperty);\n\t\t\t\t// Managing the parent address is a bit more complex here -- the box will be added for each element.\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpObjectPropertyName}`;\n\t\t\t\t// The container object is where we have the \"Address\":SOMEVALUE pairs\n\t\t\t\tlet tmpContainerObject = {};\n\t\t\t\tfor (let i = 0; i < tmpObjectPropertyKeys.length; i++)\n\t\t\t\t{\n\t\t\t\t\tlet tmpPropertyParentAddress = `${tmpParentAddress}.${tmpObjectPropertyKeys[i]}`;\n\t\t\t\t\tlet tmpValue = this.getValueAtAddress(pObject[tmpObjectPropertyName][tmpObjectPropertyKeys[i]], tmpNewAddress, tmpPropertyParentAddress, tmpRootObject);\n\n\t\t\t\t\t// The filtering is complex but allows config-based metaprogramming directly from schema\n\t\t\t\t\tlet tmpKeepRecord = this.checkRecordFilters(pAddress, tmpValue);\n\t\t\t\t\tif (tmpKeepRecord)\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpContainerObject[`${tmpPropertyParentAddress}.${tmpNewAddress}`] = tmpValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmpContainerObject;\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\treturn this.getValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\t// Continue to manage the parent address for recursion\n\t\t\t\ttmpParentAddress = `${tmpParentAddress}${(tmpParentAddress.length > 0) ? '.' : ''}${tmpSubObjectName}`;\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.getValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, tmpParentAddress, tmpRootObject);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressResolverGetValue;","// TODO: This is an inelegant solution to delay the rewrite of Manyfest.\n\n// Fable 3.0 has a service for data formatting that deals well with nested enclosures.\n\n// The Manyfest library predates fable 3.0 and the services structure of it, so the functions\n// are more or less pure javascript and as functional as they can be made to be.\n\n// Until we shift Manyfest to be a fable service, these three functions were pulled out of\n// fable to aid in parsing functions with nested enclosures.\n\nmodule.exports = {\n\t/**\n\t * Count the number of segments in a string, respecting enclosures\n\t * \n\t * @param {string} pString \n\t * @param {string} pSeparator \n\t * @param {object} pEnclosureStartSymbolMap \n\t * @param {object} pEnclosureEndSymbolMap \n\t * @returns the count of segments in the string as a number\n\t */\n\tstringCountSegments: (pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\n\t\tlet tmpSeparator = (typeof(pSeparator) == 'string') ? pSeparator : '.';\n\n\t\tlet tmpEnclosureStartSymbolMap = (typeof(pEnclosureStartSymbolMap) == 'object') ? pEnclosureStart : { '{': 0, '[': 1, '(': 2 };\n\t\tlet tmpEnclosureEndSymbolMap = (typeof(pEnclosureEndSymbolMap) == 'object') ? pEnclosureEnd : { '}': 0, ']': 1, ')': 2 };\n\n\t\tif (pString.length < 1)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet tmpSegmentCount = 1;\n\t\tlet tmpEnclosureStack = [];\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// IF This is the start of a segment\n\t\t\tif ((tmpString[i] == tmpSeparator)\n\t\t\t\t// AND we are not in a nested portion of the string\n\t\t\t\t&& (tmpEnclosureStack.length == 0))\n\t\t\t{\n\t\t\t\t// Increment the segment count\n\t\t\t\ttmpSegmentCount++;\n\t\t\t}\n\t\t\t// IF This is the start of an enclosure\n\t\t\telse if (tmpString[i] in tmpEnclosureStartSymbolMap)\n\t\t\t{\n\t\t\t\t// Add it to the stack!\n\t\t\t\ttmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);\n\t\t\t}\n\t\t\t// IF This is the end of an enclosure\n\t\t\telse if ((tmpString[i] in tmpEnclosureEndSymbolMap)\n\t\t\t\t// AND it matches the current nest level symbol\n\t\t\t\t&& tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1])\n\t\t\t{\n\t\t\t\t// Pop it off the stack!\n\t\t\t\ttmpEnclosureStack.pop();\n\t\t\t}\n\t\t}\n\n\t\treturn tmpSegmentCount;\n\t},\n\n\t/**\n\t * Get the first segment in a string, respecting enclosures\n\t * \n\t * @param {string} pString \n\t * @param {string} pSeparator \n\t * @param {object} pEnclosureStartSymbolMap \n\t * @param {object} pEnclosureEndSymbolMap \n\t * @returns the first segment in the string as a string\n\t */\n\tstringGetFirstSegment: (pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\n\t\tlet tmpSeparator = (typeof(pSeparator) == 'string') ? pSeparator : '.';\n\n\t\tlet tmpEnclosureStartSymbolMap = (typeof(pEnclosureStartSymbolMap) == 'object') ? pEnclosureStart : { '{': 0, '[': 1, '(': 2 };\n\t\tlet tmpEnclosureEndSymbolMap = (typeof(pEnclosureEndSymbolMap) == 'object') ? pEnclosureEnd : { '}': 0, ']': 1, ')': 2 };\n\n\t\tif (pString.length < 1)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet tmpEnclosureStack = [];\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// IF This is the start of a segment\n\t\t\tif ((tmpString[i] == tmpSeparator)\n\t\t\t\t// AND we are not in a nested portion of the string\n\t\t\t\t&& (tmpEnclosureStack.length == 0))\n\t\t\t{\n\t\t\t\t// Return the segment\n\t\t\t\treturn tmpString.substring(0, i);\n\t\t\t}\n\t\t\t// IF This is the start of an enclosure\n\t\t\telse if (tmpString[i] in tmpEnclosureStartSymbolMap)\n\t\t\t{\n\t\t\t\t// Add it to the stack!\n\t\t\t\ttmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);\n\t\t\t}\n\t\t\t// IF This is the end of an enclosure\n\t\t\telse if ((tmpString[i] in tmpEnclosureEndSymbolMap)\n\t\t\t\t// AND it matches the current nest level symbol\n\t\t\t\t&& tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1])\n\t\t\t{\n\t\t\t\t// Pop it off the stack!\n\t\t\t\ttmpEnclosureStack.pop();\n\t\t\t}\n\t\t}\n\n\t\treturn tmpString;\n\t},\n\n\t/**\n\t * Get all segments in a string, respecting enclosures\n\t * \n\t * @param {string} pString \n\t * @param {string} pSeparator \n\t * @param {object} pEnclosureStartSymbolMap \n\t * @param {object} pEnclosureEndSymbolMap \n\t * @returns the first segment in the string as a string\n\t */\n\tstringGetSegments: (pString, pSeparator, pEnclosureStartSymbolMap, pEnclosureEndSymbolMap)=>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\n\t\tlet tmpSeparator = (typeof(pSeparator) == 'string') ? pSeparator : '.';\n\n\t\tlet tmpEnclosureStartSymbolMap = (typeof(pEnclosureStartSymbolMap) == 'object') ? pEnclosureStart : { '{': 0, '[': 1, '(': 2 };\n\t\tlet tmpEnclosureEndSymbolMap = (typeof(pEnclosureEndSymbolMap) == 'object') ? pEnclosureEnd : { '}': 0, ']': 1, ')': 2 };\n\n\t\tlet tmpCurrentSegmentStart = 0;\n\t\tlet tmpSegmentList = [];\n\n\t\tif (pString.length < 1)\n\t\t{\n\t\t\treturn tmpSegmentList;\n\t\t}\n\n\t\tlet tmpEnclosureStack = [];\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// IF This is the start of a segment\n\t\t\tif ((tmpString[i] == tmpSeparator)\n\t\t\t\t// AND we are not in a nested portion of the string\n\t\t\t\t&& (tmpEnclosureStack.length == 0))\n\t\t\t{\n\t\t\t\t// Return the segment\n\t\t\t\ttmpSegmentList.push(tmpString.substring(tmpCurrentSegmentStart, i));\n\t\t\t\ttmpCurrentSegmentStart = i+1;\n\t\t\t}\n\t\t\t// IF This is the start of an enclosure\n\t\t\telse if (tmpString[i] in tmpEnclosureStartSymbolMap)\n\t\t\t{\n\t\t\t\t// Add it to the stack!\n\t\t\t\ttmpEnclosureStack.push(tmpEnclosureStartSymbolMap[tmpString[i]]);\n\t\t\t}\n\t\t\t// IF This is the end of an enclosure\n\t\t\telse if ((tmpString[i] in tmpEnclosureEndSymbolMap)\n\t\t\t\t// AND it matches the current nest level symbol\n\t\t\t\t&& tmpEnclosureEndSymbolMap[tmpString[i]] == tmpEnclosureStack[tmpEnclosureStack.length - 1])\n\t\t\t{\n\t\t\t\t// Pop it off the stack!\n\t\t\t\ttmpEnclosureStack.pop();\n\t\t\t}\n\t\t}\n\n\t\tif (tmpCurrentSegmentStart < tmpString.length)\n\t\t{\n\t\t\ttmpSegmentList.push(tmpString.substring(tmpCurrentSegmentStart));\n\t\t}\n\n\t\treturn tmpSegmentList;\n\t},\n\n\t/**\n\t * Count the number of enclosures in a string based on the start and end characters.\n\t *\n\t * If no start or end characters are specified, it will default to parentheses. If the string is not a string, it will return 0.\n\t *\n\t * @param {string} pString\n\t * @param {string} pEnclosureStart\n\t * @param {string} pEnclosureEnd\n\t * @returns the count of full in the string\n\t */\n\tstringCountEnclosures: (pString, pEnclosureStart, pEnclosureEnd) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\t\tlet tmpEnclosureStart = (typeof(pEnclosureStart) == 'string') ? pEnclosureStart : '(';\n\t\tlet tmpEnclosureEnd = (typeof(pEnclosureEnd) == 'string') ? pEnclosureEnd : ')';\n\n\t\tlet tmpEnclosureCount = 0;\n\t\tlet tmpEnclosureDepth = 0;\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// This is the start of an enclosure\n\t\t\tif (tmpString[i] == tmpEnclosureStart)\n\t\t\t{\n\t\t\t\tif (tmpEnclosureDepth == 0)\n\t\t\t\t{\n\t\t\t\t\ttmpEnclosureCount++;\n\t\t\t\t}\n\t\t\t\ttmpEnclosureDepth++;\n\t\t\t}\n\t\t\telse if (tmpString[i] == tmpEnclosureEnd)\n\t\t\t{\n\t\t\t\ttmpEnclosureDepth--;\n\t\t\t}\n\t\t}\n\n\t\treturn tmpEnclosureCount;\n\t},\n\n\n\t/**\n\t * Get the value of the enclosure at the specified index.\n\t *\n\t * If the index is not a number, it will default to 0. If the string is not a string, it will return an empty string. If the enclosure is not found, it will return an empty string. If the enclosure\n\t *\n\t * @param {string} pString\n\t * @param {number} pEnclosureIndexToGet\n\t * @param {string} pEnclosureStart\n\t * @param {string}} pEnclosureEnd\n\t * @returns {string}\n\t */\n\tstringGetEnclosureValueByIndex: (pString, pEnclosureIndexToGet, pEnclosureStart, pEnclosureEnd) =>\n\t{\n\t\tlet tmpString = (typeof(pString) == 'string') ? pString : '';\n\t\tlet tmpEnclosureIndexToGet = (typeof(pEnclosureIndexToGet) == 'number') ? pEnclosureIndexToGet : 0;\n\t\tlet tmpEnclosureStart = (typeof(pEnclosureStart) == 'string') ? pEnclosureStart : '(';\n\t\tlet tmpEnclosureEnd = (typeof(pEnclosureEnd) == 'string') ? pEnclosureEnd : ')';\n\n\t\tlet tmpEnclosureCount = 0;\n\t\tlet tmpEnclosureDepth = 0;\n\n\t\tlet tmpMatchedEnclosureIndex = false;\n\t\tlet tmpEnclosedValueStartIndex = 0;\n\t\tlet tmpEnclosedValueEndIndex = 0;\n\n\t\tfor (let i = 0; i < tmpString.length; i++)\n\t\t{\n\t\t\t// This is the start of an enclosure\n\t\t\tif (tmpString[i] == tmpEnclosureStart)\n\t\t\t{\n\t\t\t\ttmpEnclosureDepth++;\n\n\t\t\t\t// Only count enclosures at depth 1, but still this parses both pairs of all of them.\n\t\t\t\tif (tmpEnclosureDepth == 1)\n\t\t\t\t{\n\t\t\t\t\ttmpEnclosureCount++;\n\t\t\t\t\tif (tmpEnclosureIndexToGet == (tmpEnclosureCount - 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t// This is the start of *the* enclosure\n\t\t\t\t\t\ttmpMatchedEnclosureIndex = true;\n\t\t\t\t\t\ttmpEnclosedValueStartIndex = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// This is the end of an enclosure\n\t\t\telse if (tmpString[i] == tmpEnclosureEnd)\n\t\t\t{\n\t\t\t\ttmpEnclosureDepth--;\n\n\t\t\t\t// Again, only count enclosures at depth 1, but still this parses both pairs of all of them.\n\t\t\t\tif ((tmpEnclosureDepth == 0) &&\n\t\t\t\t\ttmpMatchedEnclosureIndex &&\n\t\t\t\t\t(tmpEnclosedValueEndIndex <= tmpEnclosedValueStartIndex))\n\t\t\t\t{\n\t\t\t\t\ttmpEnclosedValueEndIndex = i;\n\t\t\t\t\ttmpMatchedEnclosureIndex = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (tmpEnclosureCount <= tmpEnclosureIndexToGet)\n\t\t{\n\t\t\t// Return an empty string if the enclosure is not found\n\t\t\treturn '';\n\t\t}\n\n\t\tif ((tmpEnclosedValueEndIndex > 0) && (tmpEnclosedValueEndIndex > tmpEnclosedValueStartIndex))\n\t\t{\n\t\t\treturn tmpString.substring(tmpEnclosedValueStartIndex+1, tmpEnclosedValueEndIndex);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn tmpString.substring(tmpEnclosedValueStartIndex+1);\n\t\t}\n\t}\n}","/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\nlet fCleanWrapCharacters = require('./Manyfest-CleanWrapCharacters.js');\n\n/**\n* Object Address Resolver - SetValue\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n*\n* @class ManyfestObjectAddressSetValue\n*/\nclass ManyfestObjectAddressSetValue\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\n\t\tthis.cleanWrapCharacters = fCleanWrapCharacters;\n\t}\n\n\t// Set the value of an element at an address\n\tsetValueAtAddress (pObject, pAddress, pValue)\n\t{\n\t\t// Make sure pObject is an object\n\t\tif (typeof(pObject) != 'object') return false;\n\t\t// Make sure pAddress is a string\n\t\tif (typeof(pAddress) != 'string') return false;\n\n\t\tlet tmpSeparatorIndex = pAddress.indexOf('.');\n\n\t\tif (tmpSeparatorIndex == -1)\n\t\t{\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = pAddress.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = pAddress.indexOf(']');\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[10]\n\t\t\t// \t\tMyValues['Name']\n\t\t\t// \t\tMyValues[\"Age\"]\n\t\t\t// \t\tMyValues[`Cost`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\t// The \"Name\" of the Object contained too the left of the bracket\n\t\t\t\tlet tmpBoxedPropertyName = pAddress.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\t// The \"Reference\" to the property within it, either an array element or object property\n\t\t\t\tlet tmpBoxedPropertyReference = pAddress.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\t\t\t\t// Attempt to parse the reference as a number, which will be used as an array element\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\t\t\t\tlet tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);\n\n\t\t\t\tif (pObject[tmpBoxedPropertyName] == null)\n\t\t\t\t{\n\t\t\t\t\tif (tmpIndexIsNumeric)\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = [];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If the subproperty doesn't test as a proper Object, none of the rest of this is possible.\n\t\t\t\t// This is a rare case where Arrays testing as Objects is useful\n\t\t\t\tif (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) == isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to treat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynamic object property.\n\t\t\t\t\t// We would expect the property to be wrapped in some kind of quotes so strip them\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\tif (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return the value in the property\n\t\t\t\t\t//TODO: For cases where we have chained [][] properties, this needs to recurse somehow\n\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = pValue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twhile(pObject[tmpBoxedPropertyName].length < (tmpBoxedPropertyNumber + 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName].push({});\n\t\t\t\t\t}\n\n\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber] = pValue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Now is the time in recursion to set the value in the object\n\t\t\t\tpObject[pAddress] = pValue;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlet tmpSubObjectName = pAddress.substring(0, tmpSeparatorIndex);\n\t\t\tlet tmpNewAddress = pAddress.substring(tmpSeparatorIndex+1);\n\n\t\t\t// Test if the tmpNewAddress is an array or object\n\t\t\t// Check if it's a boxed property\n\t\t\tlet tmpBracketStartIndex = tmpSubObjectName.indexOf('[');\n\t\t\tlet tmpBracketStopIndex = tmpSubObjectName.indexOf(']');\n\t\t\t// Boxed elements look like this:\n\t\t\t// \t\tMyValues[42]\n\t\t\t// \t\tMyValues['Color']\n\t\t\t// \t\tMyValues[\"Weight\"]\n\t\t\t// \t\tMyValues[`Diameter`]\n\t\t\t//\n\t\t\t// When we are passed SomeObject[\"Name\"] this code below recurses as if it were SomeObject.Name\n\t\t\t// The requirements to detect a boxed element are:\n\t\t\t// 1) The start bracket is after character 0\n\t\t\tif ((tmpBracketStartIndex > 0)\n\t\t\t// 2) The end bracket has something between them\n\t\t\t\t&& (tmpBracketStopIndex > tmpBracketStartIndex)\n\t\t\t// 3) There is data\n\t\t\t\t&& (tmpBracketStopIndex - tmpBracketStartIndex > 1))\n\t\t\t{\n\t\t\t\tlet tmpBoxedPropertyName = tmpSubObjectName.substring(0, tmpBracketStartIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyReference = tmpSubObjectName.substring(tmpBracketStartIndex+1, tmpBracketStopIndex).trim();\n\n\t\t\t\tlet tmpBoxedPropertyNumber = parseInt(tmpBoxedPropertyReference, 10);\n\t\t\t\tlet tmpIndexIsNumeric = !isNaN(tmpBoxedPropertyNumber);\n\n\t\t\t\t//if (typeof(pObject[tmpBoxedPropertyName]) !== 'object')\n\t\t\t\tif (pObject[tmpBoxedPropertyName] == null)\n\t\t\t\t{\n\t\t\t\t\tif (tmpIndexIsNumeric)\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = [];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName] = {};\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Guard: If the referrant is a number and the boxed property is not an array, or vice versa, return undefined.\n\t\t\t\t// This seems confusing to me at first read, so explaination:\n\t\t\t\t// Is the Boxed Object an Array? TRUE\n\t\t\t\t// And is the Reference inside the boxed Object not a number? TRUE\n\t\t\t\t// --> So when these are in agreement, it's an impossible access state\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[1].Tardy\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an object, so the [1].Tardy is not possible to access\n\t\t\t\t// This could be a failure in the recursion chain because they passed something like this in:\n\t\t\t\t// StudentData.Sections.Algebra.Students[\"JaneDoe\"].Grade\n\t\t\t\t// BUT\n\t\t\t\t// StudentData.Sections.Algebra.Students is an array, so the [\"JaneDoe\"].Grade is not possible to access\n\t\t\t\t// TODO: Should this be an error or something? Should we keep a log of failures like this?\n\t\t\t\tif (Array.isArray(pObject[tmpBoxedPropertyName]) != tmpIndexIsNumeric)\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t//This is a bracketed value\n\t\t\t\t// 4) If the middle part is *only* a number (no single, double or backtick quotes) it is an array element,\n\t\t\t\t// otherwise we will try to reat it as a dynamic object property.\n\t\t\t\tif (isNaN(tmpBoxedPropertyNumber))\n\t\t\t\t{\n\t\t\t\t\t// This isn't a number ... let's treat it as a dynanmic object property.\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('\"', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters('`', tmpBoxedPropertyReference);\n\t\t\t\t\ttmpBoxedPropertyReference = this.cleanWrapCharacters(\"'\", tmpBoxedPropertyReference);\n\n\t\t\t\t\tif (!(tmpBoxedPropertyReference in pObject[tmpBoxedPropertyName]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName][tmpBoxedPropertyReference] = {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Recurse directly into the subobject\n\t\t\t\t\treturn this.setValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyReference], tmpNewAddress, pValue);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\twhile(pObject[tmpBoxedPropertyName].length < (tmpBoxedPropertyNumber + 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t// If the subobject doesn't exist, create it\n\t\t\t\t\t\tpObject[tmpBoxedPropertyName].push({});\n\t\t\t\t\t}\n\n\t\t\t\t\t// We parsed a valid number out of the boxed property name, so recurse into the array\n\t\t\t\t\treturn this.setValueAtAddress(pObject[tmpBoxedPropertyName][tmpBoxedPropertyNumber], tmpNewAddress, pValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If there is an object property already named for the sub object, but it isn't an object\n\t\t\t// then the system can't set the value in there. Error and abort!\n\t\t\tif ((tmpSubObjectName in pObject) && typeof(pObject[tmpSubObjectName]) !== 'object')\n\t\t\t{\n\t\t\t\tif (!('__ERROR' in pObject))\n\t\t\t\t\tpObject['__ERROR'] = {};\n\t\t\t\t// Put it in an error object so data isn't lost\n\t\t\t\tpObject['__ERROR'][pAddress] = pValue;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if (tmpSubObjectName in pObject)\n\t\t\t{\n\t\t\t\t// If there is already a subobject pass that to the recursive thingy\n\t\t\t\treturn this.setValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, pValue);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Create a subobject and then pass that\n\t\t\t\tpObject[tmpSubObjectName] = {};\n\t\t\t\treturn this.setValueAtAddress(pObject[tmpSubObjectName], tmpNewAddress, pValue);\n\t\t\t}\n\t\t}\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressSetValue;","/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\n/**\n* Object Address Generation\n*\n* Automagically generate addresses and properties based on a passed-in object,\n* to be used for easy creation of schemas. Meant to simplify the lives of\n* developers wanting to create schemas without typing a bunch of stuff.\n*\n* IMPORTANT NOTE: This code is intentionally more verbose than necessary, to\n* be extremely clear what is going on in the recursion for\n* each of the three address resolution functions.\n*\n* Although there is some opportunity to repeat ourselves a\n* bit less in this codebase (e.g. with detection of arrays\n* versus objects versus direct properties), it can make\n* debugging.. challenging. The minified version of the code\n* optimizes out almost anything repeated in here. So please\n* be kind and rewind... meaning please keep the codebase less\n* terse and more verbose so humans can comprehend it.\n*\n*\n* @class ManyfestObjectAddressGeneration\n*/\nclass ManyfestObjectAddressGeneration\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) == 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) == 'function') ? pErrorLog : libSimpleLog;\n\t}\n\n\t// generateAddressses\n\t//\n\t// This flattens an object into a set of key:value pairs for *EVERY SINGLE\n\t// POSSIBLE ADDRESS* in the object. It can get ... really insane really\n\t// quickly. This is not meant to be used directly to generate schemas, but\n\t// instead as a starting point for scripts or UIs.\n\t//\n\t// This will return a mega set of key:value pairs with all possible schema\n\t// permutations and default values (when not an object) and everything else.\n\tgenerateAddressses (pObject, pBaseAddress, pSchema)\n\t{\n\t\tlet tmpBaseAddress = (typeof(pBaseAddress) == 'string') ? pBaseAddress : '';\n\t\tlet tmpSchema = (typeof(pSchema) == 'object') ? pSchema : {};\n\n\t\tlet tmpObjectType = typeof(pObject);\n\n\t\tlet tmpSchemaObjectEntry = (\n\t\t\t{\n\t\t\t\tAddress: tmpBaseAddress,\n\t\t\t\tHash: tmpBaseAddress,\n\t\t\t\tName: tmpBaseAddress,\n\t\t\t\t// This is so scripts and UI controls can force a developer to opt-in.\n\t\t\t\tInSchema: false\n\t\t\t}\n\t\t)\n\n\t\tif ((tmpObjectType == 'object') && (pObject == null))\n\t\t{\n\t\t\ttmpObjectType = 'null';\n\t\t}\n\n\t\tswitch(tmpObjectType)\n\t\t{\n\t\t\tcase 'string':\n\t\t\t\ttmpSchemaObjectEntry.DataType = 'String';\n\t\t\t\ttmpSchemaObjectEntry.Default = pObject;\n\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\tbreak;\n\t\t\tcase 'number':\n\t\t\tcase 'bigint':\n\t\t\t\ttmpSchemaObjectEntry.DataType = 'Number';\n\t\t\t\ttmpSchemaObjectEntry.Default = pObject;\n\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\tbreak;\n\t\t\tcase 'undefined':\n\t\t\tcase 'null':\n\t\t\t\ttmpSchemaObjectEntry.DataType = 'Any';\n\t\t\t\ttmpSchemaObjectEntry.Default = pObject;\n\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\tbreak;\n\t\t\tcase 'object':\n\t\t\t\tif (Array.isArray(pObject))\n\t\t\t\t{\n\t\t\t\t\ttmpSchemaObjectEntry.DataType = 'Array';\n\t\t\t\t\tif (tmpBaseAddress != '')\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (let i = 0; i < pObject.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.generateAddressses(pObject[i], `${tmpBaseAddress}[${i}]`, tmpSchema);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttmpSchemaObjectEntry.DataType = 'Object';\n\t\t\t\t\tif (tmpBaseAddress != '')\n\t\t\t\t\t{\n\t\t\t\t\t\ttmpSchema[tmpBaseAddress] = tmpSchemaObjectEntry;\n\t\t\t\t\t\ttmpBaseAddress += '.';\n\t\t\t\t\t}\n\n\t\t\t\t\tlet tmpObjectProperties = Object.keys(pObject);\n\n\t\t\t\t\tfor (let i = 0; i < tmpObjectProperties.length; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.generateAddressses(pObject[tmpObjectProperties[i]], `${tmpBaseAddress}${tmpObjectProperties[i]}`, tmpSchema);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'symbol':\n\t\t\tcase 'function':\n\t\t\t\t// Symbols and functions neither recurse nor get added to the schema\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn tmpSchema;\n\t}\n};\n\nmodule.exports = ManyfestObjectAddressGeneration;","// Given a string, parse out any conditional expressions and set whether or not to keep the record.\n//\n// For instance:\n// \t\t'files[]<<~?format,==,Thumbnail?~>>'\n// 'files[]<<~?format,==,Metadata?~>>'\n// 'files[]<<~?size,>,4000?~>>'\n//\n// The wrapping parts are the <<~? and ?~>> megabrackets.\n//\n// The function does not need to alter the string -- just check the conditionals within.\n\n// TODO: Consider making this an es6 class\n\n// Let's use indexOf since it is apparently the fastest.\nconst _ConditionalStanzaStart = '<<~?';\nconst _ConditionalStanzaStartLength = _ConditionalStanzaStart.length;\nconst _ConditionalStanzaEnd = '?~>>';\nconst _ConditionalStanzaEndLength = _ConditionalStanzaEnd.length;\n\n// Ugh dependency injection. Can't wait to make these all fable services.\n//let libObjectAddressCheckAddressExists = new (require('./Manyfest-ObjectAddress-CheckAddressExists.js'))();\n\n// Test the condition of a value in a record\nconst testCondition = (pManyfest, pRecord, pSearchAddress, pSearchComparator, pValue) =>\n{\n\tswitch(pSearchComparator)\n\t{\n\t\tcase 'TRUE':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) === true);\n\t\t\tbreak;\n\t\tcase 'FALSE':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) === false);\n\t\t\tbreak;\n\t\tcase 'LNGT':\n\t\tcase 'LENGTH_GREATER_THAN':\n\t\t\tswitch(typeof(pManyfest.getValueAtAddress(pRecord, pSearchAddress)))\n\t\t\t{\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length > pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'object':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length > pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'LNLT':\n\t\tcase 'LENGTH_LESS_THAN':\n\t\t\tswitch(typeof(pManyfest.getValueAtAddress(pRecord, pSearchAddress)))\n\t\t\t{\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length < pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'object':\n\t\t\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress).length < pValue);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\t// TODO: Welcome to dependency hell. This fixes itself when we move to fable services.\n\t\t// case 'EX':\n\t\t// case 'EXISTS':\n\t\t// \treturn libObjectAddressCheckAddressExists.checkAddressExists(pRecord, pSearchAddress);\n\t\t// \tbreak;\n\t\t// case 'DNEX':\n\t\t// case 'DOES_NOT_EXIST':\n\t\t// \treturn !libObjectAddressCheckAddressExists.checkAddressExists(pRecord, pSearchAddress);\n\t\t// \tbreak;\n\t\tcase '!=':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) != pValue);\n\t\t\tbreak;\n\t\tcase '<':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) < pValue);\n\t\t\tbreak;\n\t\tcase '>':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) > pValue);\n\t\t\tbreak;\n\t\tcase '<=':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) <= pValue);\n\t\t\tbreak;\n\t\tcase '>=':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) >= pValue);\n\t\t\tbreak;\n\t\tcase '===':\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) === pValue);\n\t\t\tbreak;\n\t\tcase '==':\n\t\tdefault:\n\t\t\treturn (pManyfest.getValueAtAddress(pRecord, pSearchAddress) == pValue);\n\t\t\tbreak;\n\t}\n};\n\nconst parseConditionals = (pManyfest, pAddress, pRecord) =>\n{\n\tlet tmpKeepRecord = true;\n\n\t/*\n\t\tAlgorithm is simple:\n\n\t\t1. Enuerate start points\n\t\t2. Find stop points within each start point\n\t\t3. Check the conditional\n\t*/\n\tlet tmpStartIndex = pAddress.indexOf(_ConditionalStanzaStart);\n\n\twhile (tmpStartIndex != -1)\n\t{\n\t\tlet tmpStopIndex = pAddress.indexOf(_ConditionalStanzaEnd, tmpStartIndex+_ConditionalStanzaStartLength);\n\n\t\tif (tmpStopIndex != -1)\n\t\t{\n\t\t\tlet tmpMagicComparisonPatternSet = pAddress.substring(tmpStartIndex+_ConditionalStanzaStartLength, tmpStopIndex).split(',');\n\n\t\t\t// The address to search for\n\t\t\tlet tmpSearchAddress = tmpMagicComparisonPatternSet[0];\n\n\t\t\t// The copmparison expression (EXISTS as default)\n\t\t\tlet tmpSearchComparator = 'EXISTS';\n\t\t\tif (tmpMagicComparisonPatternSet.length > 1)\n\t\t\t{\n\t\t\t\ttmpSearchComparator = tmpMagicComparisonPatternSet[1];\t\t\t\t\n\t\t\t}\n\n\t\t\t// The value to search for\n\t\t\tlet tmpSearchValue = false;\n\t\t\tif (tmpMagicComparisonPatternSet.length > 2)\n\t\t\t{\n\t\t\t\ttmpSearchValue = tmpMagicComparisonPatternSet[2];\n\t\t\t}\n\n\t\t\t// Process the piece\n\t\t\ttmpKeepRecord = tmpKeepRecord && testCondition(pManyfest, pRecord, tmpSearchAddress, tmpSearchComparator, tmpSearchValue);\n\t\t\ttmpStartIndex = pAddress.indexOf(_ConditionalStanzaStart, tmpStopIndex+_ConditionalStanzaEndLength);\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttmpStartIndex = -1;\n\t\t}\n\t\t\n\t}\n\n\treturn tmpKeepRecord;\n}\n\nmodule.exports = parseConditionals;","/**\n* @author <steven@velozo.com>\n*/\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\n/**\n* Schema Manipulation Functions\n*\n* @class ManyfestSchemaManipulation\n*/\nclass ManyfestSchemaManipulation\n{\n\tconstructor(pInfoLog, pErrorLog)\n\t{\n\t\t// Wire in logging\n\t\tthis.logInfo = (typeof(pInfoLog) === 'function') ? pInfoLog : libSimpleLog;\n\t\tthis.logError = (typeof(pErrorLog) === 'function') ? pErrorLog : libSimpleLog;\n\t}\n\n // This translates the default address mappings to something different.\n //\n // For instance you can pass in manyfest schema descriptor object:\n // \t{\n\t//\t \"Address.Of.a\": { \"Hash\": \"a\", \"Type\": \"Number\" },\n\t//\t \"Address.Of.b\": { \"Hash\": \"b\", \"Type\": \"Number\" }\n\t// }\n //\n //\n // And then an address mapping (basically a Hash->Address map)\n // {\n // \"a\": \"New.Address.Of.a\",\n // \"b\": \"New.Address.Of.b\"\n // }\n //\n // NOTE: This mutates the schema object permanently, altering the base hash.\n // If there is a collision with an existing address, it can lead to overwrites.\n // TODO: Discuss what should happen on collisions.\n\tresolveAddressMappings(pManyfestSchemaDescriptors, pAddressMapping)\n\t{\n\t\tif (typeof(pManyfestSchemaDescriptors) != 'object')\n\t\t{\n\t\t\tthis.logError(`Attempted to resolve address mapping but the descriptor was not an object.`);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (typeof(pAddressMapping) != 'object')\n\t\t{\n\t\t\t// No mappings were passed in\n\t\t\treturn true;\n\t\t}\n\n\t\t// Get the arrays of both the schema definition and the hash mapping\n\t\tlet tmpManyfestAddresses = Object.keys(pManyfestSchemaDescriptors);\n\t\tlet tmpHashMapping = {};\n\t\ttmpManyfestAddresses.forEach(\n\t\t\t(pAddress) =>\n\t\t\t{\n\t\t\t\tif ('Hash' in pManyfestSchemaDescriptors[pAddress])\n\t\t\t\t{\n\t\t\t\t\ttmpHashMapping[pManyfestSchemaDescriptors[pAddress].Hash] = pAddress;\n\t\t\t\t}\n\t\t\t});\n\n\t\tlet tmpAddressMappingSet = Object.keys(pAddressMapping);\n\n\t\ttmpAddressMappingSet.forEach(\n\t\t\t(pInputAddress) =>\n\t\t\t{\n\t\t\t\tlet tmpNewDescriptorAddress = pAddressMapping[pInputAddress];\n\t\t\t\tlet tmpOldDescriptorAddress = false;\n\t\t\t\tlet tmpDescriptor = false;\n\n\t\t\t\t// See if there is a matching descriptor either by Address directly or Hash\n\t\t\t\tif (pInputAddress in pManyfestSchemaDescriptors)\n\t\t\t\t{\n\t\t\t\t\ttmpOldDescriptorAddress = pInputAddress;\n\t\t\t\t}\n\t\t\t\telse if (pInputAddress in tmpHashMapping)\n\t\t\t\t{\n\t\t\t\t\ttmpOldDescriptorAddress = tmpHashMapping[pInputAddress];\n\t\t\t\t}\n\n\t\t\t\t// If there was a matching descriptor in the manifest, store it in the temporary descriptor\n\t\t\t\tif (tmpOldDescriptorAddress)\n\t\t\t\t{\n\t\t\t\t\ttmpDescriptor = pManyfestSchemaDescriptors[tmpOldDescriptorAddress];\n\t\t\t\t\tdelete pManyfestSchemaDescriptors[tmpOldDescriptorAddress];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Create a new descriptor! Map it to the input address.\n\t\t\t\t\ttmpDescriptor = { Hash:pInputAddress };\n\t\t\t\t}\n\n\t\t\t\t// Now re-add the descriptor to the manyfest schema\n\t\t\t\tpManyfestSchemaDescriptors[tmpNewDescriptorAddress] = tmpDescriptor;\n\t\t\t});\n\n\t\treturn true;\n\t}\n\n\tsafeResolveAddressMappings(pManyfestSchemaDescriptors, pAddressMapping)\n\t{\n\t\t// This returns the descriptors as a new object, safely remapping without mutating the original schema Descriptors\n\t\tlet tmpManyfestSchemaDescriptors = JSON.parse(JSON.stringify(pManyfestSchemaDescriptors));\n\t\tthis.resolveAddressMappings(tmpManyfestSchemaDescriptors, pAddressMapping);\n\t\treturn tmpManyfestSchemaDescriptors;\n\t}\n\n\tmergeAddressMappings(pManyfestSchemaDescriptorsDestination, pManyfestSchemaDescriptorsSource)\n\t{\n\t\tif ((typeof(pManyfestSchemaDescriptorsSource) != 'object') || (typeof(pManyfestSchemaDescriptorsDestination) != 'object'))\n\t\t{\n\t\t\tthis.logError(`Attempted to merge two schema descriptors but both were not objects.`);\n\t\t\treturn false;\n\t\t}\n\n\t\tlet tmpSource = JSON.parse(JSON.stringify(pManyfestSchemaDescriptorsSource));\n\t\tlet tmpNewManyfestSchemaDescriptors = JSON.parse(JSON.stringify(pManyfestSchemaDescriptorsDestination));\n\n\t\t// The first passed-in set of descriptors takes precedence.\n\t\tlet tmpDescriptorAddresses = Object.keys(tmpSource);\n\n\t\ttmpDescriptorAddresses.forEach(\n\t\t\t(pDescriptorAddress) =>\n\t\t\t{\n\t\t\t\tif (!(pDescriptorAddress in tmpNewManyfestSchemaDescriptors))\n\t\t\t\t{\n\t\t\t\t\ttmpNewManyfestSchemaDescriptors[pDescriptorAddress] = tmpSource[pDescriptorAddress];\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn tmpNewManyfestSchemaDescriptors;\n\t}\n}\n\nmodule.exports = ManyfestSchemaManipulation;","/**\n* @author <steven@velozo.com>\n*/\nconst libFableServiceProviderBase = require('fable-serviceproviderbase');\n\nlet libSimpleLog = require('./Manyfest-LogToConsole.js');\n\nlet libHashTranslation = require('./Manyfest-HashTranslation.js');\nlet libObjectAddressCheckAddressExists = require('./Manyfest-ObjectAddress-CheckAddressExists.js');\nlet libObjectAddressGetValue = require('./Manyfest-ObjectAddress-GetValue.js');\nlet libObjectAddressSetValue = require('./Manyfest-ObjectAddress-SetValue.js');\nlet libObjectAddressDeleteValue = require('./Manyfest-ObjectAddress-DeleteValue.js');\nlet libObjectAddressGeneration = require('./Manyfest-ObjectAddressGeneration.js');\nlet libSchemaManipulation = require('./Manyfest-SchemaManipulation.js');\n\nconst _DefaultConfiguration = { Scope:'DEFAULT', Descriptors: {} }\n\n/**\n * @typedef {{\n * Hash?: string,\n * Name?: string,\n * DataType?: string,\n * Required?: boolean,\n * Address?: string,\n * Description?: string,\n * [key: string]: any,\n * }} ManifestDescriptor\n */\n\n/**\n* Manyfest object address-based descriptions and manipulations.\n*\n* @class Manyfest\n*/\nclass Manyfest extends libFableServiceProviderBase\n{\n\tconstructor(pFable, pManifest, pServiceHash)\n\t{\n\t\tif (pFable === undefined)\n\t\t{\n\t\t\tsuper({});\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsuper(pFable, pManifest, pServiceHash);\n\t\t}\n\n\t\t/** @type {Record<string, any>} */\n\t\tthis.options;\n\n this.serviceType = 'Manifest';\n\n\t\t// Wire in logging\n\t\tthis.logInfo = libSimpleLog;\n\t\tthis.logError = libSimpleLog;\n\n\t\t// Create an object address resolver and map in the functions\n\t\tthis.objectAddressCheckAddressExists = new libObjectAddressCheckAddressExists(this.logInfo, this.logError);\n\t\tthis.objectAddressGetValue = new libObjectAddressGetValue(this.logInfo, this.logError);\n\t\tthis.objectAddressSetValue = new libObjectAddressSetValue(this.logInfo, this.logError);\n\t\tthis.objectAddressDeleteValue = new libObjectAddressDeleteValue(this.logInfo, this.logError);\n\n\t\tif (!('defaultValues' in this.options))\n\t\t{\n\t\t\tthis.options.defaultValues = (\n\t\t\t\t{\n\t\t\t\t\t\"String\": \"\",\n\t\t\t\t\t\"Number\": 0,\n\t\t\t\t\t\"Float\": 0.0,\n\t\t\t\t\t\"Integer\": 0,\n\t\t\t\t\t\"PreciseNumber\": \"0.0\",\n\t\t\t\t\t\"Boolean\": false,\n\t\t\t\t\t\"Binary\": 0,\n\t\t\t\t\t\"DateTime\": 0,\n\t\t\t\t\t\"Array\": [],\n\t\t\t\t\t\"Object\": {},\n\t\t\t\t\t\"Null\": null\n\t\t\t\t});\n\t\t}\n\t\tif (!('strict' in this.options))\n\t\t{\n\t\t\tthis.options.strict = false;\n\t\t}\n\n\t\tthis.scope = undefined;\n\t\tthis.elementAddresses = undefined;\n\t\tthis.elementHashes = undefined;\n\t\tthis.elementDescriptors = undefined;\n\n\t\tthis.reset();\n\n\t\tif (typeof(this.options) === 'object')\n\t\t{\n\t\t\tthis.loadManifest(this.options);\n\t\t}\n\n\t\tthis.schemaManipulations = new libSchemaManipulation(this.logInfo, this.logError);\n\t\tthis.objectAddressGeneration = new libObjectAddressGeneration(this.logInfo, this.logError);\n\n\t\tthis.hashTranslations = new libHashTranslation(this.logInfo, this.logError);\n\n\t\tthis.numberRegex = /^[+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?$/;\n\t}\n\n\t/*************************************************************************\n\t * Schema Manifest Loading, Reading, Manipulation and Serialization Functions\n\t */\n\n\t// Reset critical manifest properties\n\treset()\n\t{\n\t\tthis.scope = 'DEFAULT';\n\t\tthis.elementAddresses = [];\n\t\tthis.elementHashes = {};\n\t\tthis.elementDescriptors = {};\n\t}\n\n\tclone()\n\t{\n\t\t// Make a copy of the options in-place\n\t\tlet tmpNewOptions = JSON.parse(JSON.stringify(this.options));\n\n\t\tlet tmpNewManyfest = new Manyfest(this.getManifest(), this.logInfo, this.logError, tmpNewOptions);\n\n\t\t// Import the hash translations\n\t\ttmpNewManyfest.hashTranslations.addTranslation(this.hashTranslations.translationTable);\n\n\t\treturn tmpNewManyfest;\n\t}\n\n\t// Deserialize a Manifest from a string\n\tdeserialize(pManifestString)\n\t{\n\t\t// TODO: Add guards for bad manifest string\n\t\treturn this.loadManifest(JSON.parse(pManifestString));\n\t}\n\n\t// Load a manifest from an object\n\tloadManifest(pManifest)\n\t{\n\t\tif (typeof(pManifest) !== 'object')\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading manifest; expecting an object but parameter was type ${typeof(pManifest)}.`);\n\t\t}\n\n\t\tlet tmpManifest = (typeof(pManifest) == 'object') ? pManifest : {};\n\n\t\tlet tmpDescriptorKeys = Object.keys(_DefaultConfiguration);\n\n\t\tfor (let i = 0; i < tmpDescriptorKeys.length; i++)\n\t\t{\n\t\t\tif (!(tmpDescriptorKeys[i] in tmpManifest))\n\t\t\t{\n\t\t\t\ttmpManifest[tmpDescriptorKeys[i]] = JSON.parse(JSON.stringify(_DefaultConfiguration[tmpDescriptorKeys[i]]));\n\t\t\t}\n\t\t}\n\n\t\tif ('Scope' in tmpManifest)\n\t\t{\n\t\t\tif (typeof(tmpManifest.Scope) === 'string')\n\t\t\t{\n\t\t\t\tthis.scope = tmpManifest.Scope;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis.logError(`(${this.scope}) Error loading scope from manifest; expecting a string but property was type ${typeof(tmpManifest.Scope)}.`, tmpManifest);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading scope from manifest object. Property \"Scope\" does not exist in the root of the object.`, tmpManifest);\n\t\t}\n\n\t\tif ('Descriptors' in tmpManifest)\n\t\t{\n\t\t\tif (typeof(tmpManifest.Descriptors) === 'object')\n\t\t\t{\n\t\t\t\tlet tmpDescriptionAddresses = Object.keys(tmpManifest.Descriptors);\n\t\t\t\tfor (let i = 0; i < tmpDescriptionAddresses.length; i++)\n\t\t\t\t{\n\t\t\t\t\tthis.addDescriptor(tmpDescriptionAddresses[i], tmpManifest.Descriptors[tmpDescriptionAddresses[i]]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis.logError(`(${this.scope}) Error loading description object from manifest object. Expecting an object in 'Manifest.Descriptors' but the property was type ${typeof(tmpManifest.Descriptors)}.`, tmpManifest);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading object description from manifest object. Property \"Descriptors\" does not exist in the root of the Manifest object.`, tmpManifest);\n\t\t}\n\n\t\tif ('HashTranslations' in tmpManifest)\n\t\t{\n\t\t\tif (typeof(tmpManifest.HashTranslations) === 'object')\n\t\t\t{\n\t\t\t\tfor (let i = 0; i < tmpManifest.HashTranslations.length; i++)\n\t\t\t\t{\n\t\t\t\t\t// Each translation is \n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Serialize the Manifest to a string\n\tserialize()\n\t{\n\t\treturn JSON.stringify(this.getManifest());\n\t}\n\n\tgetManifest()\n\t{\n\t\treturn (\n\t\t\t{\n\t\t\t\tScope: this.scope,\n\t\t\t\tDescriptors: JSON.parse(JSON.stringify(this.elementDescriptors)),\n\t\t\t\tHashTranslations: JSON.parse(JSON.stringify(this.hashTranslations.translationTable))\n\t\t\t});\n\t}\n\n\t/**\n\t * Add a descriptor to the manifest\n\t *\n\t * @param {string} pAddress - The address of the element to add the descriptor for.\n\t * @param {ManifestDescriptor} pDescriptor - The descriptor object to add.\n\t */\n\taddDescriptor(pAddress, pDescriptor)\n\t{\n\t\tif (typeof(pDescriptor) === 'object')\n\t\t{\n\t\t\t// Add the Address into the Descriptor if it doesn't exist:\n\t\t\tif (!('Address' in pDescriptor))\n\t\t\t{\n\t\t\t\tpDescriptor.Address = pAddress;\n\t\t\t}\n\n\t\t\tif (!(pAddress in this.elementDescriptors))\n\t\t\t{\n\t\t\t\tthis.elementAddresses.push(pAddress);\n\t\t\t}\n\n\t\t\t// Add the element descriptor to the schema\n\t\t\tthis.elementDescriptors[pAddress] = pDescriptor;\n\n\t\t\t// Always add the address as a hash\n\t\t\tthis.elementHashes[pAddress] = pAddress;\n\n\t\t\tif ('Hash' in pDescriptor)\n\t\t\t{\n\t\t\t\t// TODO: Check if this is a good idea or not..\n\t\t\t\t// Collisions are bound to happen with both representations of the address/hash in here and developers being able to create their own hashes.\n\t\t\t\tthis.elementHashes[pDescriptor.Hash] = pAddress;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tpDescriptor.Hash = pAddress;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error loading object descriptor for address '${pAddress}' from manifest object. Expecting an object but property was type ${typeof(pDescriptor)}.`);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} pHash - The hash of the address to resolve.\n\t *\n\t * @return {ManifestDescriptor} The descriptor for the address\n\t */\n\tgetDescriptorByHash(pHash)\n\t{\n\t\treturn this.getDescriptor(this.resolveHashAddress(pHash));\n\t}\n\n\t/**\n\t * @param {string} pAddress - The address of the element to get the descriptor for.\n\t *\n\t * @return {ManifestDescriptor} The descriptor for the address\n\t */\n\tgetDescriptor(pAddress)\n\t{\n\t\treturn this.elementDescriptors[pAddress];\n\t}\n\n\t/**\n\t * execute an action function for each descriptor\n\t * @param {(d: ManifestDescriptor) => void} fAction - The action function to execute for each descriptor.\n\t */\n\teachDescriptor(fAction)\n\t{\n let tmpDescriptorAddresses = Object.keys(this.elementDescriptors);\n for (let i = 0; i < tmpDescriptorAddresses.length; i++)\n {\n fAction(this.elementDescriptors[tmpDescriptorAddresses[i]]);\n }\n\n\t}\n\n\t/*************************************************************************\n\t * Beginning of Object Manipulation (read & write) Functions\n\t */\n\t// Check if an element exists by its hash\n\tcheckAddressExistsByHash (pObject, pHash)\n\t{\n\t\treturn this.checkAddressExists(pObject,this.resolveHashAddress(pHash));\n\t}\n\n\t// Check if an element exists at an address\n\tcheckAddressExists (pObject, pAddress)\n\t{\n\t\treturn this.objectAddressCheckAddressExists.checkAddressExists(pObject, pAddress);\n\t}\n\n\t// Turn a hash into an address, factoring in the translation table.\n\tresolveHashAddress(pHash)\n\t{\n\t\tlet tmpAddress = undefined;\n\n\t\tlet tmpInElementHashTable = (pHash in this.elementHashes);\n\t\tlet tmpInTranslationTable = (pHash in this.hashTranslations.translationTable);\n\n\t\t// The most straightforward: the hash exists, no translations.\n\t\tif (tmpInElementHashTable && !tmpInTranslationTable)\n\t\t{\n\t\t\ttmpAddress = this.elementHashes[pHash];\n\t\t}\n\t\t// There is a translation from one hash to another, and, the elementHashes contains the pointer end\n\t\telse if (tmpInTranslationTable && (this.hashTranslations.translate(pHash) in this.elementHashes))\n\t\t{\n\t\t\ttmpAddress = this.elementHashes[this.hashTranslations.translate(pHash)];\n\t\t}\n\t\t// Use the level of indirection only in the Translation Table\n\t\telse if (tmpInTranslationTable)\n\t\t{\n\t\t\ttmpAddress = this.hashTranslations.translate(pHash);\n\t\t}\n\t\t// Just treat the hash as an address.\n\t\t// TODO: Discuss this ... it is magic but controversial\n\t\telse\n\t\t{\n\t\t\ttmpAddress = pHash;\n\t\t}\n\n\t\treturn tmpAddress;\n\t}\n\n\t// Get the value of an element by its hash\n\tgetValueByHash (pObject, pHash)\n\t{\n\t\tlet tmpValue = this.getValueAtAddress(pObject, this.resolveHashAddress(pHash));\n\n\t\tif (typeof(tmpValue) == 'undefined')\n\t\t{\n\t\t\t// Try to get a default if it exists\n\t\t\ttmpValue = this.getDefaultValue(this.getDescriptorByHash(pHash));\n\t\t}\n\n\t\treturn tmpValue;\n\t}\n\n\tlintAddress(pAddress)\n\t{\n\t\tlet tmpLintedAddress = pAddress.trim();\n\t\t// Check for a single . (but not a ..) at the end of the address and remove it.\n\t\tif (tmpLintedAddress.endsWith('..'))\n\t\t{\n\t\t\ttmpLintedAddress = tmpLintedAddress.slice(0, -1);\n\t\t}\n\t\telse if (tmpLintedAddress.endsWith('.'))\n\t\t{\n\t\t\ttmpLintedAddress = tmpLintedAddress.slice(0, -1);\n\t\t}\n\n\t\treturn tmpLintedAddress;\n\t}\n\n\t// Get the value of an element at an address\n\tgetValueAtAddress (pObject, pAddress)\n\t{\n\t\tlet tmpLintedAddress = this.lintAddress(pAddress);\n\t\tif (tmpLintedAddress == '')\n\t\t{\n\t\t\tthis.logError(`(${this.scope}) Error getting value at address; address is an empty string.`, pObject);\n\t\t\treturn undefined;\n\t\t}\n\t\tlet tmpValue = this.objectAddressGetValue.getValueAtAddress(pObject, tmpLintedAddress);\n\n\t\tif (typeof(tmpValue) == 'undefined')\n\t\t{\n\t\t\t// Try to get a default if it exists\n\t\t\ttmpValue = this.getDefaultValue(this.getDescriptor(tmpLintedAddress));\n\t\t}\n\n\t\treturn tmpValue;\n\t}\n\n\t// Set the value of an element by its hash\n\tsetValueByHash(pObject, pHash, pValue)\n\t{\n\t\treturn this.setValueAtAddress(pObject, this.resolveHashAddress(pHash), pValue);\n\t}\n\n\t// Set the value of an element at an address\n\tsetValueAtAddress (pObject, pAddress, pValue)\n\t{\n\t\tlet tmpLintedAddress = this.lintAddress(pAddress);\n\t\treturn this.objectAddressSetValue.setValueAtAddress(pObject, tmpLintedAddress, pValue);\n\t}\n\n\t// Delete the value of an element by its hash\n\tdeleteValueByHash(pObject, pHash, pValue)\n\t{\n\t\treturn this.deleteValueAtAddress(pObject, this.resolveHashAddress(pHash), pValue);\n\t}\n\n\t// Delete the value of an element at an address\n\tdeleteValueAtAddress (pObject, pAddress, pValue)\n\t{\n\t\tlet tmpLintedAddress = this.lintAddress(pAddress);\n\t\treturn this.objectAddressDeleteValue.deleteValueAtAddress(pObject, tmpLintedAddress, pValue);\n\t}\n\n\t// Validate the consistency of an object against the schema\n\tvalidate(pObject)\n\t{\n\t\tlet tmpValidationData =\n\t\t{\n\t\t\tError: null,\n\t\t\tErrors: [],\n\t\t\tMissingElements:[]\n\t\t};\n\n\t\tif (typeof(pObject) !== 'object')\n\t\t{\n\t\t\ttmpValidationData.Error = true;\n\t\t\ttmpValidationData.Errors.push(`Expected passed in object to be type object but was passed in ${typeof(pObject)}`);\n\t\t}\n\n\t\tlet addValidationError = (pAddress, pErrorMessage) =>\n\t\t{\n\t\t\ttmpValidationData.Error = true;\n\t\t\ttmpValidationData.Errors.push(`Element at address \"${pAddress}\" ${pErrorMessage}.`);\n\t\t};\n\n\t\t// Now enumerate through the values and check for anomalies based on the schema\n\t\tfor (let i = 0; i < this.elementAddresses.length; i++)\n\t\t{\n\t\t\tlet tmpDescriptor = this.getDescriptor(this.elementAddresses[i]);\n\t\t\tlet tmpValueExists = this.checkAddressExists(pObject, tmpDescriptor.Address);\n\t\t\tlet tmpValue = this.getValueAtAddress(pObject, tmpDescriptor.Address);\n\n\t\t\tif ((typeof(tmpValue) == 'undefined') || !tmpValueExists)\n\t\t\t{\n\t\t\t\t// This will technically mean that `Object.Some.Value = undefined` will end up showing as \"missing\"\n\t\t\t\t// TODO: Do we want to do a different message based on if the property exists but is undefined?\n\t\t\t\ttmpValidationData.MissingElements.push(tmpDescriptor.Address);\n\t\t\t\tif (tmpDescriptor.Required || this.options.strict)\n\t\t\t\t{\n\t\t\t\t\taddValidationError(tmpDescriptor.Address, 'is flagged REQUIRED but is not set in the object');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Now see if there is a data type specified for this element\n\t\t\tif (tmpDescriptor.DataType)\n\t\t\t{\n\t\t\t\tlet tmpElementType = typeof(tmpValue);\n\t\t\t\tswitch(tmpDescriptor.DataType.toString().trim().toLowerCase())\n\t\t\t\t{\n\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tif (tmpElementType != 'string')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase \"precisenumber\":\n\t\t\t\t\t\tif (tmpElementType != 'string')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (!this.numberRegex.test(tmpValue))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is not a valid number`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tif (tmpElementType != 'number')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'integer':\n\t\t\t\t\t\tif (tmpElementType != 'number')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlet tmpValueString = tmpValue.toString();\n\t\t\t\t\t\t\tif (tmpValueString.indexOf('.') > -1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t// TODO: Is this an error?\n\t\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but has a decimal point in the number.`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'float':\n\t\t\t\t\t\tif (tmpElementType != 'number')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 'datetime':\n\t\t\t\t\t\tlet tmpValueDate = new Date(tmpValue);\n\t\t\t\t\t\tif (tmpValueDate.toString() == 'Invalid Date')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} but is not parsable as a Date by Javascript`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t// Check if this is a string, in the default case\n\t\t\t\t\t\t// Note this is only when a DataType is specified and it is an unrecognized data type.\n\t\t\t\t\t\tif (tmpElementType != 'string')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taddValidationError(tmpDescriptor.Address, `has a DataType ${tmpDescriptor.DataType} (which auto-converted to String because it was unrecognized) but is of the type ${tmpElementType}`);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn tmpValidationData;\n\t}\n\n\t/**\n\t * Returns a default value, or, the default value for the data type (which is overridable with configuration)\n\t *\n\t * @param {ManifestDescriptor} pDescriptor - The descriptor definition.\n\t */\n\tgetDefaultValue(pDescriptor)\n\t{\n\t\tif (typeof(pDescriptor) != 'object')\n\t\t{\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif ('Default' in pDescriptor)\n\t\t{\n\t\t\treturn pDescriptor.Default;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Default to a null if it doesn't have a type specified.\n\t\t\t// This will ensure a placeholder is created but isn't misinterpreted.\n\t\t\tlet tmpDataType = ('DataType' in pDescriptor) ? pDescriptor.DataType : 'String';\n\t\t\tif (tmpDataType in this.options.defaultValues)\n\t\t\t{\n\t\t\t\treturn this.options.defaultValues[tmpDataType];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// give up and return null\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Enumerate through the schema and populate default values if they don't exist.\n\tpopulateDefaults(pObject, pOverwriteProperties)\n\t{\n\t\treturn this.populateObject(pObject, pOverwriteProperties,\n\t\t\t// This just sets up a simple filter to see if there is a default set.\n\t\t\t(pDescriptor) =>\n\t\t\t{\n\t\t\t\treturn ('Default' in pDescriptor);\n\t\t\t});\n\t}\n\n\t// Forcefully populate all values even if they don't have defaults.\n\t// Based on type, this can do unexpected things.\n\tpopulateObject(pObject, pOverwriteProperties, fFilter)\n\t{\n\t\t// Automatically create an object if one isn't passed in.\n\t\tlet tmpObject = (typeof(pObject) === 'object') ? pObject : {};\n\t\t// Default to *NOT OVERWRITING* properties\n\t\tlet tmpOverwriteProperties = (typeof(pOverwriteProperties) == 'undefined') ? false : pOverwriteProperties;\n\t\t// This is a filter function, which is passed the schema and allows complex filtering of population\n\t\t// The default filter function just returns true, populating everything.\n\t\tlet tmpFilterFunction = (typeof(fFilter) == 'function') ? fFilter : (pDescriptor) => { return true; };\n\n\t\tthis.elementAddresses.forEach(\n\t\t\t(pAddress) =>\n\t\t\t{\n\t\t\t\tlet tmpDescriptor = this.getDescriptor(pAddress);\n\t\t\t\t// Check the filter function to see if this is an address we want to set the value for.\n\t\t\t\tif (tmpFilterFunction(tmpDescriptor))\n\t\t\t\t{\n\t\t\t\t\t// If we are overwriting properties OR the property does not exist\n\t\t\t\t\tif (tmpOverwriteProperties || !this.checkAddressExists(tmpObject, pAddress))\n\t\t\t\t\t{\n\t\t\t\t\t\tthis.setValueAtAddress(tmpObject, pAddress, this.getDefaultValue(tmpDescriptor));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\treturn tmpObject;\n\t}\n};\n\nmodule.exports = Manyfest;\n"]}