"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("./typesystem");
var messageRegistry = ts.messageRegistry;
var typesystem_1 = require("./typesystem");
var restrictions_1 = require("./restrictions");
var restrictions_2 = require("./restrictions");
var _ = require("underscore");
var xmlio = require("./xmlio");
var tsInterfaces = require("./typesystem-interfaces");
var MetaInfo = /** @class */ (function (_super) {
    __extends(MetaInfo, _super);
    function MetaInfo(_name, _value, inhertitable) {
        if (inhertitable === void 0) { inhertitable = false; }
        var _this = _super.call(this, inhertitable) || this;
        _this._name = _name;
        _this._value = _value;
        return _this;
    }
    MetaInfo.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(MetaInfo.CLASS_IDENTIFIER_MetaInfo);
    };
    MetaInfo.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), MetaInfo.CLASS_IDENTIFIER_MetaInfo);
    };
    MetaInfo.prototype.value = function () {
        return this._value;
    };
    MetaInfo.prototype.requiredType = function () {
        return ts.ANY;
    };
    MetaInfo.prototype.facetName = function () {
        return this._name;
    };
    MetaInfo.prototype.kind = function () {
        //to be overriden in subtypes
        return null;
    };
    MetaInfo.CLASS_IDENTIFIER_MetaInfo = "metainfo.MetaInfo";
    return MetaInfo;
}(ts.TypeInformation));
exports.MetaInfo = MetaInfo;
var Description = /** @class */ (function (_super) {
    __extends(Description, _super);
    function Description(value) {
        return _super.call(this, "description", value) || this;
    }
    Description.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(Description.CLASS_IDENTIFIER_Description);
    };
    Description.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), Description.CLASS_IDENTIFIER_Description);
    };
    Description.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Description;
    };
    Description.prototype.validateSelfIndividual = function (parentStatus, registry) {
        var vl = this.value();
        var allowedTypes = {
            "string": true,
            "number": true,
            "boolean": true
        };
        var result = ts.ok();
        if (vl !== null && !allowedTypes[typeof vl]) {
            result = ts.error(messageRegistry.INVALID_PROPERTY_RANGE, this, { propName: this.facetName(), range: "string" });
            ts.setValidationPath(result, { name: this.facetName() });
        }
        parentStatus.addSubStatus(result);
        return parentStatus;
    };
    Description.CLASS_IDENTIFIER_Description = "metainfo.Description";
    return Description;
}(MetaInfo));
exports.Description = Description;
var NotScalar = /** @class */ (function (_super) {
    __extends(NotScalar, _super);
    function NotScalar() {
        return _super.call(this, "notScalar", true) || this;
    }
    NotScalar.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(NotScalar.CLASS_IDENTIFIER_NotScalar);
    };
    NotScalar.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), NotScalar.CLASS_IDENTIFIER_NotScalar);
    };
    NotScalar.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.NotScalar;
    };
    NotScalar.CLASS_IDENTIFIER_NotScalar = "metainfo.NotScalar";
    return NotScalar;
}(MetaInfo));
exports.NotScalar = NotScalar;
var ImportedByChain = /** @class */ (function (_super) {
    __extends(ImportedByChain, _super);
    function ImportedByChain(_typeName) {
        var _this = _super.call(this, "importedByChain", _typeName, true) || this;
        _this._typeName = _typeName;
        return _this;
    }
    ImportedByChain.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(ImportedByChain.CLASS_IDENTIFIER_ImportedByChain);
    };
    ImportedByChain.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), ImportedByChain.CLASS_IDENTIFIER_ImportedByChain);
    };
    ImportedByChain.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.ImportedByChain;
    };
    ImportedByChain.CLASS_IDENTIFIER_ImportedByChain = "metainfo.ImportedByChain";
    return ImportedByChain;
}(MetaInfo));
exports.ImportedByChain = ImportedByChain;
var AcceptAllScalarsAsStrings = /** @class */ (function (_super) {
    __extends(AcceptAllScalarsAsStrings, _super);
    function AcceptAllScalarsAsStrings() {
        return _super.call(this, "acceptAllScalarsAsStrings", null, true) || this;
    }
    AcceptAllScalarsAsStrings.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.AcceptAllScalarsAsStrings;
    };
    return AcceptAllScalarsAsStrings;
}(MetaInfo));
exports.AcceptAllScalarsAsStrings = AcceptAllScalarsAsStrings;
var SkipValidation = /** @class */ (function (_super) {
    __extends(SkipValidation, _super);
    function SkipValidation() {
        return _super.call(this, "skipValidation", null, true) || this;
    }
    SkipValidation.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.SkipValidation;
    };
    return SkipValidation;
}(MetaInfo));
exports.SkipValidation = SkipValidation;
var DisplayName = /** @class */ (function (_super) {
    __extends(DisplayName, _super);
    function DisplayName(value) {
        return _super.call(this, "displayName", value) || this;
    }
    DisplayName.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(DisplayName.CLASS_IDENTIFIER_DisplayName);
    };
    DisplayName.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), DisplayName.CLASS_IDENTIFIER_DisplayName);
    };
    DisplayName.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.DisplayName;
    };
    DisplayName.prototype.validateSelfIndividual = function (parentStatus, registry) {
        var vl = this.value();
        var allowedTypes = {
            "string": true,
            "number": true,
            "boolean": true
        };
        var result = ts.ok();
        if (vl !== null && !allowedTypes[typeof vl]) {
            result = ts.error(messageRegistry.INVALID_PROPERTY_RANGE, this, { propName: this.facetName(), range: "string" });
            ts.setValidationPath(result, { name: this.facetName() });
        }
        parentStatus.addSubStatus(result);
        return parentStatus;
    };
    DisplayName.CLASS_IDENTIFIER_DisplayName = "metainfo.DisplayName";
    return DisplayName;
}(MetaInfo));
exports.DisplayName = DisplayName;
var Usage = /** @class */ (function (_super) {
    __extends(Usage, _super);
    function Usage(value) {
        return _super.call(this, "usage", value) || this;
    }
    Usage.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Usage;
    };
    return Usage;
}(MetaInfo));
exports.Usage = Usage;
var Annotation = /** @class */ (function (_super) {
    __extends(Annotation, _super);
    function Annotation(name, value, path, ofExample, _index) {
        if (ofExample === void 0) { ofExample = false; }
        if (_index === void 0) { _index = -1; }
        var _this = _super.call(this, name, value) || this;
        _this.path = path;
        _this.ofExample = ofExample;
        _this._index = _index;
        return _this;
    }
    Annotation.prototype.name = function () {
        return this.facetName();
    };
    Annotation.prototype.definition = function () {
        var owner = this.owner();
        if (owner) {
            var reg = owner.collection();
            if (reg) {
                var tp = reg.getAnnotationType(this.facetName());
                return tp;
            }
        }
        return null;
    };
    Annotation.prototype.validateSelfIndividual = function (parentStatus, registry) {
        var tp = registry.get(this.facetName());
        if (!tp) {
            var err = void 0;
            if (registry.getByChain(this.facetName())) {
                err = ts.error(messageRegistry.LIBRARY_CHAINIG_IN_ANNOTATION_TYPE, this, { typeName: this.facetName() });
            }
            else {
                err = ts.error(messageRegistry.UNKNOWN_ANNOTATION_TYPE, this, { typeName: this.facetName() });
            }
            err.setValidationPath({ name: this.path });
            return err;
        }
        var result = ts.ok();
        var q = this.value();
        if (!q) {
            if (tp.isString()) {
                q = "";
            }
        }
        var aTargets = tp.metaOfType(AllowedTargets);
        var contextTarget = this.ofExample ? "Example" : "TypeDeclaration";
        if (aTargets.length > 0) {
            var arr = [];
            var at = aTargets.filter(function (x) {
                var val = x.value();
                if (Array.isArray(val)) {
                    arr = arr.concat(val);
                    return val.indexOf(contextTarget) >= 0;
                }
                arr.push(val);
                return val == contextTarget;
            });
            if (at.length == 0) {
                var list = arr.map(function (x) { return "'" + x + "'"; }).join(", ");
                var targetStatus = ts.error(messageRegistry.INVALID_ANNOTATION_LOCATION, this, { aName: _super.prototype.facetName.call(this), aValues: list });
                result.addSubStatus(targetStatus);
            }
        }
        var res;
        var chained = tp.metaOfType(ImportedByChain);
        if (chained.length > 0 && ts.isUnknown(tp) && registry.getByChain(tp.name())) {
            var chainedType = chained[0].value();
            res = ts.error(messageRegistry.LIBRARY_CHAINIG_IN_ANNOTATION_TYPE_SUPERTYPE, this, { typeName: this.facetName(), chainedType: chainedType });
        }
        else {
            var valOwner = tp.validateDirect(q, true, false);
            if (!valOwner.isOk()) {
                res = ts.error(messageRegistry.INVALID_ANNOTATION_VALUE, this, { msg: valOwner.getMessage() });
                res.addSubStatus(valOwner);
            }
        }
        if (res) {
            result.addSubStatus(res);
        }
        ts.setValidationPath(result, { name: this.path });
        return result;
    };
    Annotation.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Annotation;
    };
    Annotation.prototype.ownerFacet = function () {
        return this._ownerFacet;
    };
    Annotation.prototype.setOwnerFacet = function (ownerFacet) {
        this._ownerFacet = ownerFacet;
    };
    Annotation.prototype.getPath = function () {
        return this.path;
    };
    return Annotation;
}(MetaInfo));
exports.Annotation = Annotation;
var FacetDeclaration = /** @class */ (function (_super) {
    __extends(FacetDeclaration, _super);
    function FacetDeclaration(name, _type, optional, builtIn) {
        if (builtIn === void 0) { builtIn = false; }
        var _this = _super.call(this, name, _type, true) || this;
        _this.name = name;
        _this._type = _type;
        _this.optional = optional;
        _this.builtIn = builtIn;
        return _this;
    }
    FacetDeclaration.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(FacetDeclaration.CLASS_IDENTIFIER_FacetDeclaration);
    };
    FacetDeclaration.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), FacetDeclaration.CLASS_IDENTIFIER_FacetDeclaration);
    };
    FacetDeclaration.prototype.actualName = function () {
        if (this.name.charAt(this.name.length - 1) == '?') {
            return this.name.substr(0, this.name.length - 1);
        }
        return this.name;
    };
    FacetDeclaration.prototype.isOptional = function () {
        return this.optional;
    };
    FacetDeclaration.prototype.type = function () {
        return this._type;
    };
    FacetDeclaration.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.FacetDeclaration;
    };
    FacetDeclaration.prototype.isBuiltIn = function () {
        return this.builtIn;
    };
    FacetDeclaration.prototype.validateSelfIndividual = function (parentStatue, registry) {
        return restrictions_2.validatePropertyType(this._type, this.name, registry, this, false);
    };
    FacetDeclaration.CLASS_IDENTIFIER_FacetDeclaration = "metainfo.FacetDeclaration";
    return FacetDeclaration;
}(MetaInfo));
exports.FacetDeclaration = FacetDeclaration;
var CustomFacet = /** @class */ (function (_super) {
    __extends(CustomFacet, _super);
    function CustomFacet(name, value) {
        return _super.call(this, name, value, true) || this;
    }
    CustomFacet.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.CustomFacet;
    };
    return CustomFacet;
}(MetaInfo));
exports.CustomFacet = CustomFacet;
function serializeToXml(value, type) {
    return xmlio.serializeToXML(value, type);
}
function parseExampleIfNeeded(val, type) {
    if (typeof val === 'string') {
        if (type.isObject() || type.isArray() || type.isExternal() || type.isUnion()) {
            var exampleString = val;
            var firstChar = exampleString.trim().charAt(0);
            if (!type.isExternal()
                && (firstChar == "{" || firstChar == "[" || exampleString.trim() == "null")) {
                try {
                    return JSON.parse(exampleString);
                }
                catch (e) {
                    if (type.isObject() || type.isArray()) {
                        var c = ts.error(messageRegistry.CAN_NOT_PARSE_JSON, this, { msg: e.message });
                        return c;
                    }
                }
            }
            if (firstChar == "<") {
                try {
                    var jsonFromXml = xmlio.readObject(exampleString, type);
                    var errors = xmlio.getXmlErrors(jsonFromXml);
                    if (errors) {
                        var error = ts.error(messageRegistry.INVALID_XML, null);
                        errors.forEach(function (child) { return error.addSubStatus(child); });
                        return error;
                    }
                    return jsonFromXml;
                }
                catch (e) {
                }
            }
        }
    }
    if (type.getExtra(tsInterfaces.REPEAT)) {
        val = [val];
    }
    return val;
}
var Example = /** @class */ (function (_super) {
    __extends(Example, _super);
    function Example(value) {
        return _super.call(this, "example", value) || this;
    }
    Example.prototype.validateSelfIndividual = function (parentStatus, registry) {
        var status = ts.ok();
        status.addSubStatus(this.validateValue(registry));
        var aStatus = this.validateAnnotations(registry);
        ts.setValidationPath(aStatus, { name: this.facetName() });
        status.addSubStatus(aStatus);
        return status;
    };
    Example.prototype.validateValue = function (registry) {
        if (this.owner().oneMeta(SkipValidation)) {
            return;
        }
        var val = this.value();
        var isVal = false;
        var result = ts.ok();
        if (typeof val === "object" && val) {
            if (val.hasOwnProperty("value")) {
                checkExampleScalarProperties(val, null, registry, result, this.facetName());
                if (val.strict === false || (val.strict && typeof (val.strict) == "object" && val.strict.value === false)) {
                    return result;
                }
                val = val.value;
                isVal = true;
            }
        }
        var rr = val;
        //if(!this.owner().isExternal()){
        rr = parseExampleIfNeeded(val, this.owner());
        if (rr instanceof ts.Status && !rr.isOk()) {
            ts.setValidationPath(rr, { name: "example" });
            result.addSubStatus(rr);
            return result;
        }
        //}
        var valOwner = this.owner().validateDirect(rr, true, false);
        if (!valOwner.isOk()) {
            if (typeof this.value() === "string") {
            }
            var c = ts.error(messageRegistry.INVALID_EXMAPLE, this, { msg: valOwner.getMessage() });
            valOwner.getErrors().forEach(function (x) {
                c.addSubStatus(x);
                if (isVal) {
                    ts.setValidationPath(x, { name: "example", child: { name: "value" } });
                }
                else {
                    ts.setValidationPath(x, { name: "example" });
                }
            });
            result.addSubStatus(c);
        }
        return result;
    };
    Example.prototype.validateAnnotations = function (registry) {
        var status = ts.ok();
        var val = this.value();
        if (typeof val === "object" && val) {
            if (val.value) {
                var usedAnnotations = Object.keys(val).filter(function (x) {
                    return x.length > 2 && x.charAt(0) == "(" && x.charAt(x.length - 1) == ")";
                });
                for (var _i = 0, usedAnnotations_1 = usedAnnotations; _i < usedAnnotations_1.length; _i++) {
                    var ua = usedAnnotations_1[_i];
                    var aValue = val[ua];
                    var aName = ua.substring(1, ua.length - 1);
                    var aInstance = new Annotation(aName, aValue, ua, true);
                    status.addSubStatus(aInstance.validateSelf(registry));
                }
            }
        }
        return status;
    };
    Example.prototype.example = function () {
        var val = this.value();
        if (typeof val === "object" && val) {
            if (val.value) {
                val = val.value;
            }
        }
        return parseExampleIfNeeded(val, this.owner());
    };
    Example.prototype.asXMLString = function () {
        var value = this.value();
        if (typeof value === 'string' && value.trim().indexOf('<') === 0) {
            return value;
        }
        var parsedValue = parseExampleIfNeeded(value, this.owner());
        return serializeToXml(parsedValue, this.owner());
    };
    Example.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Example;
    };
    return Example;
}(MetaInfo));
exports.Example = Example;
var Required = /** @class */ (function (_super) {
    __extends(Required, _super);
    function Required(value) {
        return _super.call(this, "required", value) || this;
    }
    Required.prototype.validateSelfIndividual = function (result, registry) {
        if (typeof this.value() !== "boolean") {
            result = ts.error(messageRegistry.REQUIRED_BOOLEAN, this);
            ts.setValidationPath(result, { name: this.facetName() });
        }
        return result;
    };
    Required.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Required;
    };
    return Required;
}(MetaInfo));
exports.Required = Required;
var HasPropertiesFacet = /** @class */ (function (_super) {
    __extends(HasPropertiesFacet, _super);
    function HasPropertiesFacet() {
        return _super.call(this, "hasPropertiesFacet", null) || this;
    }
    HasPropertiesFacet.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(HasPropertiesFacet.CLASS_IDENTIFIER_HasPropertiesFacet);
    };
    HasPropertiesFacet.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), HasPropertiesFacet.CLASS_IDENTIFIER_HasPropertiesFacet);
    };
    HasPropertiesFacet.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.HasPropertiesFacet;
    };
    HasPropertiesFacet.CLASS_IDENTIFIER_HasPropertiesFacet = "metainfo.HasPropertiesFacet";
    return HasPropertiesFacet;
}(MetaInfo));
exports.HasPropertiesFacet = HasPropertiesFacet;
var AllowedTargets = /** @class */ (function (_super) {
    __extends(AllowedTargets, _super);
    function AllowedTargets(value) {
        return _super.call(this, "allowedTargets", value) || this;
    }
    AllowedTargets.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.AllowedTargets;
    };
    return AllowedTargets;
}(MetaInfo));
exports.AllowedTargets = AllowedTargets;
var Examples = /** @class */ (function (_super) {
    __extends(Examples, _super);
    function Examples(value) {
        return _super.call(this, "examples", value) || this;
    }
    Examples.prototype.examples = function () {
        var _this = this;
        var v = this.value();
        var result = [];
        Object.keys(v).forEach(function (x) {
            if (typeof v[x] == 'object' && v[x]) {
                var val = v[x].value;
                if (!val) {
                    val = v[x];
                }
                var example = parseExampleIfNeeded(val, _this.owner());
                result.push(example);
            }
        });
        return result;
    };
    Examples.prototype.asXMLStrings = function () {
        var _this = this;
        var value = this.value();
        var result = {};
        Object.keys(value).forEach(function (key) {
            var childValue = value[key];
            if (typeof childValue === 'string' && childValue.trim().indexOf('<') === 0) {
                result[key] = childValue;
                return;
            }
            var parsedValue = parseExampleIfNeeded(childValue, _this.owner());
            result[key] = serializeToXml(parsedValue, _this.owner());
        });
        return result;
    };
    Examples.prototype.validateSelfIndividual = function (parentStatus, registry) {
        var _this = this;
        var v = this.value();
        if (typeof v === 'object' && (v == null || !Array.isArray(v))) {
            var rs = new typesystem_1.Status(typesystem_1.Status.OK, "", "", this);
            if (v) {
                Object.keys(v).forEach(function (x) {
                    var exampleObj = v[x];
                    if (exampleObj !== undefined) {
                        var hasVal_1 = (exampleObj != null) && (typeof exampleObj == "object")
                            && exampleObj.hasOwnProperty('value');
                        if (hasVal_1) {
                            Object.keys(exampleObj).forEach(function (key) {
                                if (key.charAt(0) == '(' && key.charAt(key.length - 1) == ')') {
                                    var a = new Annotation(key.substring(1, key.length - 1), v[x][key], key, true);
                                    var aRes = a.validateSelf(registry);
                                    ts.setValidationPath(aRes, { name: "examples", child: { name: x, child: { name: key } } });
                                    rs.addSubStatus(aRes);
                                }
                            });
                        }
                        var val = exampleObj;
                        if (hasVal_1) {
                            val = exampleObj.value;
                            checkExampleScalarProperties(exampleObj, x, registry, rs, _this.facetName());
                            if (exampleObj.strict === false || (exampleObj.strict &&
                                typeof (exampleObj.strict) == "object" && exampleObj.strict.value === false)) {
                                return;
                            }
                        }
                        var example = val;
                        if (!_this.owner().isExternal()) {
                            example = parseExampleIfNeeded(val, _this.owner());
                            if (example instanceof ts.Status) {
                                examplesPatchPath(example, !hasVal_1, x);
                                rs.addSubStatus(example);
                                return;
                            }
                        }
                        var res = _this.owner().validate(example, true, false);
                        res.getErrors().forEach(function (ex) {
                            rs.addSubStatus(ex);
                            examplesPatchPath(ex, !hasVal_1, x);
                        });
                    }
                });
            }
            return rs;
        }
        else {
            return ts.error(messageRegistry.EXMAPLES_MAP, this, {}, typesystem_1.Status.ERROR, true);
        }
    };
    Examples.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Examples;
    };
    return Examples;
}(MetaInfo));
exports.Examples = Examples;
function examplesPatchPath(example, noVal, x) {
    if (noVal) {
        ts.setValidationPath(example, { name: "examples", child: { name: x } });
    }
    else {
        ts.setValidationPath(example, { name: "examples", child: { name: x, child: { name: "value" } } });
    }
}
var XMLInfo = /** @class */ (function (_super) {
    __extends(XMLInfo, _super);
    function XMLInfo(o) {
        return _super.call(this, "xml", o) || this;
    }
    XMLInfo.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.XMLInfo;
    };
    return XMLInfo;
}(MetaInfo));
exports.XMLInfo = XMLInfo;
var Default = /** @class */ (function (_super) {
    __extends(Default, _super);
    function Default(value) {
        return _super.call(this, "default", value) || this;
    }
    Default.prototype.validateSelfIndividual = function (result, registry) {
        var _this = this;
        var valOwner = this.owner().validateDirect(this.value(), true);
        if (!valOwner.isOk()) {
            var c = ts.error(messageRegistry.INVALID_DEFAULT_VALUE, this, { msg: valOwner.getMessage() });
            valOwner.getErrors().forEach(function (x) {
                c.addSubStatus(x);
                ts.setValidationPath(x, { name: _this.facetName() });
            });
            result.addSubStatus(c);
        }
        return result;
    };
    Default.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Default;
    };
    return Default;
}(MetaInfo));
exports.Default = Default;
var SchemaPath = /** @class */ (function (_super) {
    __extends(SchemaPath, _super);
    function SchemaPath(path) {
        return _super.call(this, "schemaPath", path, true) || this;
    }
    SchemaPath.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.SchemaPath;
    };
    return SchemaPath;
}(MetaInfo));
exports.SchemaPath = SchemaPath;
var SourceMap = /** @class */ (function (_super) {
    __extends(SourceMap, _super);
    function SourceMap(value) {
        return _super.call(this, "sourceMap", value) || this;
    }
    SourceMap.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(SourceMap.CLASS_IDENTIFIER_SourceMap);
    };
    SourceMap.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), SourceMap.CLASS_IDENTIFIER_SourceMap);
    };
    SourceMap.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.SourceMap;
    };
    SourceMap.CLASS_IDENTIFIER_SourceMap = "metainfo.SourceMap";
    return SourceMap;
}(MetaInfo));
exports.SourceMap = SourceMap;
var TypeAttributeValue = /** @class */ (function (_super) {
    __extends(TypeAttributeValue, _super);
    function TypeAttributeValue(value) {
        return _super.call(this, "typeAttributeValue", value) || this;
    }
    TypeAttributeValue.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(TypeAttributeValue.CLASS_IDENTIFIER_TypeAttributeValue);
    };
    TypeAttributeValue.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), TypeAttributeValue.CLASS_IDENTIFIER_TypeAttributeValue);
    };
    TypeAttributeValue.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.TypeAttributeValue;
    };
    TypeAttributeValue.CLASS_IDENTIFIER_TypeAttributeValue = "metainfo.TypeAttributeValue";
    return TypeAttributeValue;
}(MetaInfo));
exports.TypeAttributeValue = TypeAttributeValue;
var ParserMetadata = /** @class */ (function (_super) {
    __extends(ParserMetadata, _super);
    function ParserMetadata(value) {
        return _super.call(this, "__METADATA__", value) || this;
    }
    ParserMetadata.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.ParserMetadata;
    };
    return ParserMetadata;
}(MetaInfo));
exports.ParserMetadata = ParserMetadata;
var Discriminator = /** @class */ (function (_super) {
    __extends(Discriminator, _super);
    function Discriminator(property) {
        var _this = _super.call(this, true) || this;
        _this.property = property;
        return _this;
    }
    Discriminator.prototype.requiredType = function () {
        return ts.OBJECT;
    };
    Discriminator.prototype.value = function () {
        return this.property;
    };
    Discriminator.prototype.facetName = function () { return "discriminator"; };
    Discriminator.prototype.validateSelfIndividual = function (result, registry) {
        var _this = this;
        if (this.owner().isUnion()) {
            result = ts.error(messageRegistry.DISCRIMINATOR_FOR_UNION, this);
        }
        else if (!this.owner().isSubTypeOf(ts.OBJECT)) {
            result = ts.error(messageRegistry.DISCRIMINATOR_FOR_OBJECT, this);
        }
        else if (this.owner().getExtra(ts.GLOBAL) === false) {
            result = ts.error(messageRegistry.DISCRIMINATOR_FOR_INLINE, this);
        }
        else {
            var prop = _.find(this.owner().meta(), function (x) { return x instanceof restrictions_1.PropertyIs && x.propertyName() == _this.value(); });
            if (!prop) {
                result = ts.error(messageRegistry.UNKNOWN_FOR_DISCRIMINATOR, this, { value: this.value() }, ts.Status.WARNING);
            }
            else if (!prop.value().isScalar()) {
                result = ts.error(messageRegistry.SCALAR_FOR_DISCRIMINATOR, this);
            }
        }
        if (!result.getValidationPath()) {
            ts.setValidationPath(result, { name: this.facetName() });
        }
        return result;
    };
    Discriminator.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.Discriminator;
    };
    return Discriminator;
}(ts.TypeInformation));
exports.Discriminator = Discriminator;
var DiscriminatorValue = /** @class */ (function (_super) {
    __extends(DiscriminatorValue, _super);
    function DiscriminatorValue(_value, strict) {
        if (strict === void 0) { strict = true; }
        var _this = _super.call(this, false) || this;
        _this._value = _value;
        _this.strict = strict;
        if (_this._value && typeof _this._value === "object") {
            if (typeof _this._value.strict === "boolean") {
                _this.strict = _this._value.strict;
            }
            _this._value = _this._value.value;
        }
        return _this;
    }
    DiscriminatorValue.prototype.getClassIdentifier = function () {
        var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
        return superIdentifiers.concat(DiscriminatorValue.CLASS_IDENTIFIER_DiscriminatorValue);
    };
    DiscriminatorValue.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), DiscriminatorValue.CLASS_IDENTIFIER_DiscriminatorValue);
    };
    DiscriminatorValue.prototype.check = function (i, path) {
        var owner = this.owner(); //_.find([t].concat(t.allSuperTypes()),x=>x.getExtra(TOPLEVEL));
        var dVal = this.value();
        var discriminator = owner.metaOfType(Discriminator);
        if (discriminator.length == 0) {
            return ts.ok();
        }
        var dName = discriminator[0].value();
        // if(owner) {
        //     dVal = owner.name();
        // }
        // var discriminatorValue = t.metaOfType(metaInfo.DiscriminatorValue);
        // if(discriminatorValue.length!=0){
        //     dVal = discriminatorValue[0].value();
        // }
        if (dVal) {
            if (i.hasOwnProperty(dName)) {
                var queue = this.owner().allSubTypes().concat(this.owner());
                var knownDiscriminatorValues = {};
                for (var _i = 0, queue_1 = queue; _i < queue_1.length; _i++) {
                    var t = queue_1[_i];
                    var dvArr = t.metaOfType(DiscriminatorValue);
                    if (dvArr && dvArr.length > 0) {
                        dvArr.forEach(function (dv) { return knownDiscriminatorValues[dv.value()] = true; });
                    }
                }
                var adVal = i[dName];
                if (!knownDiscriminatorValues[adVal]) {
                    var wrng = ts.error(typesystem_1.Status.CODE_INCORRECT_DISCRIMINATOR, this, {
                        rootType: owner.name(),
                        value: adVal,
                        propName: dName
                    }, typesystem_1.Status.WARNING);
                    //var wrng = new Status(Status.WARNING, Status.CODE_INCORRECT_DISCRIMINATOR, dVal, this);
                    ts.setValidationPath(wrng, { name: dName, child: path });
                    return wrng;
                }
                return ts.ok();
            }
            else {
                var err = ts.error(typesystem_1.Status.CODE_MISSING_DISCRIMINATOR, this, {
                    rootType: owner.name(),
                    propName: dName
                });
                //var err = new Status(Status.ERROR, Status.CODE_MISSING_DISCRIMINATOR, dVal, this);
                ts.setValidationPath(err, path);
                return err;
            }
        }
        return ts.ok();
    };
    DiscriminatorValue.prototype.facetName = function () { return "discriminatorValue"; };
    DiscriminatorValue.prototype.validateSelfIndividual = function (st, registry) {
        if (this.strict) {
            var ds = this.owner().oneMeta(Discriminator);
            if (!this.owner().isSubTypeOf(ts.OBJECT)) {
                st.addSubStatus(ts.error(messageRegistry.DISCRIMINATOR_FOR_OBJECT, this));
            }
            else if (this.owner().getExtra(ts.GLOBAL) === false) {
                st.addSubStatus(ts.error(messageRegistry.DISCRIMINATOR_FOR_INLINE, this));
            }
            else if (!ds) {
                st.addSubStatus(ts.error(messageRegistry.DISCRIMINATOR_VALUE_WITHOUT_DISCRIMINATOR, this));
            }
            else {
                var prop = _.find(this.owner().meta(), function (x) {
                    return x instanceof restrictions_1.PropertyIs && x.propertyName() == ds.value();
                });
                if (prop) {
                    var sm = prop.value().validate(this.value());
                    if (!sm.isOk()) {
                        st.addSubStatus(ts.error(messageRegistry.INVALID_DISCRIMINATOR_VALUE, this, { msg: sm.getMessage() }));
                    }
                }
            }
        }
        if (!st.getValidationPath()) {
            ts.setValidationPath(st, { name: this.facetName() });
        }
        return st;
    };
    DiscriminatorValue.prototype.requiredType = function () {
        return ts.OBJECT;
    };
    DiscriminatorValue.prototype.value = function () {
        return this._value;
    };
    DiscriminatorValue.prototype.kind = function () {
        return tsInterfaces.MetaInformationKind.DiscriminatorValue;
    };
    DiscriminatorValue.prototype.isStrict = function () { return this.strict; };
    DiscriminatorValue.CLASS_IDENTIFIER_DiscriminatorValue = "metainfo.DiscriminatorValue";
    return DiscriminatorValue;
}(ts.Constraint));
exports.DiscriminatorValue = DiscriminatorValue;
function checkExampleScalarProperties(exampleObj, exampleName, registry, status, facetName) {
    for (var _i = 0, exampleScalarProperties_1 = exampleScalarProperties; _i < exampleScalarProperties_1.length; _i++) {
        var y = exampleScalarProperties_1[_i];
        checkScalarProperty(exampleObj, exampleName, y, registry, status, facetName);
    }
}
function checkScalarProperty(exampleObj, exampleName, y, registry, status, facetName) {
    var propName = y.propName;
    var propType = y.propType;
    if (!exampleObj
        || (typeof exampleObj != "object")
        || !exampleObj.hasOwnProperty(propName)) {
        return;
    }
    var propObj = exampleObj[propName];
    if (propObj == null) {
        var s = ts.error(y.messageEntry, this);
        var vp = toExampleScalarPropertyPath(exampleName, facetName, { name: propName });
        ts.setValidationPath(s, vp);
        status.addSubStatus(s);
    }
    else if (typeof propObj != propType) {
        var vp = null;
        if (typeof (propObj) == "object") {
            vp = toExampleScalarPropertyPath(exampleName, facetName, { name: "value" });
            Object.keys(propObj).forEach(function (key) {
                if (key.charAt(0) == '(' && key.charAt(key.length - 1) == ')') {
                    var a = new Annotation(key.substring(1, key.length - 1), exampleObj[propName][key], key, true);
                    var aRes = a.validateSelf(registry);
                    var vp_1 = toExampleScalarPropertyPath(exampleName, facetName, { name: propName, child: { name: key } });
                    ts.setValidationPath(aRes, vp_1);
                    status.addSubStatus(aRes);
                }
            });
        }
        if (!propObj.value && typeof (propObj.value) != propType) {
            var s = ts.error(y.messageEntry, this);
            ts.setValidationPath(s, {
                name: "examples",
                child: { name: exampleName, child: { name: propName, child: vp } }
            });
            status.addSubStatus(s);
        }
    }
}
function toExampleScalarPropertyPath(exampleName, facetName, vp) {
    var p = vp;
    if (exampleName) {
        p = {
            name: exampleName,
            child: vp
        };
    }
    return {
        name: facetName,
        child: p
    };
}
var exampleScalarProperties = [
    { propName: "strict", propType: "boolean", messageEntry: messageRegistry.STRICT_BOOLEAN },
    { propName: "displayName", propType: "string", messageEntry: messageRegistry.DISPLAY_NAME_STRING },
    { propName: "description", propType: "string", messageEntry: messageRegistry.DESCRIPTION_STRING }
];
//# sourceMappingURL=metainfo.js.map