text: "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 _ = require("underscore");
  var su = require("./schemaUtil");
  var tsInterfaces = require("./typesystem-interfaces");
  exports.messageRegistry = require("../../resources/errorMessages");
  var Status = /** @class */ (function () {
      function Status(severity, code, message, source, takeNodeFromSource) {
          if (takeNodeFromSource === void 0) { takeNodeFromSource = false; }
          this.takeNodeFromSource = takeNodeFromSource;
          this.subStatus = [];
          this.severity = severity;
          this.code = code;
          this.message = message;
          this.source = source;
      }
      Status.prototype.getValidationPath = function () {
          return this.vp;
      };
      Status.prototype.getValidationPathAsString = function () {
          if (!this.vp) {
              return "";
          }
          var s = "";
          var c = this.vp;
          while (c) {
              s += c.name;
              if (c.child) {
                  s += '/';
              }
              c = c.child;
          }
          return s;
      };
      Status.prototype.setValidationPath = function (_c) {
          this.vp = _c;
      };
      Status.prototype.addSubStatus = function (st, pathName) {
          if (pathName === void 0) { pathName = null; }
          if (!st) {
              return;
          }
          if (pathName) {
              setValidationPath(st, { name: pathName });
          }
          this.subStatus.push(st);
          var otherSeverity = Status.OK;
          if (!st.isOk()) {
              if (st.isError()) {
                  otherSeverity = Status.ERROR;
              }
              else if (st.isWarning()) {
                  otherSeverity = Status.WARNING;
              }
              else if (st.isInfo()) {
                  otherSeverity = Status.INFO;
              }
          }
          if (this.severity < otherSeverity) {
              this.severity = otherSeverity;
              this.message = st.getMessage();
          }
      };
      Status.prototype.getErrors = function () {
          if (this.isError() || this.isWarning()) {
              if (this.subStatus.length > 0) {
                  var rs = [];
                  this.subStatus.forEach(function (x) { return rs = rs.concat(x.getErrors()); });
                  return rs;
              }
              return [this];
          }
          return [];
      };
      Status.prototype.getSubStatuses = function () {
          return this.subStatus;
      };
      Status.prototype.getSeverity = function () {
          return this.severity;
      };
      Status.prototype.getMessage = function () {
          return this.message;
      };
      Status.prototype.setMessage = function (message) {
          this.message = message;
      };
      Status.prototype.getSource = function () {
          return this.source;
      };
      Status.prototype.getCode = function () {
          return this.code;
      };
      Status.prototype.setCode = function (code) {
          this.code = code;
      };
      Status.prototype.isWarning = function () {
          return this.severity == Status.WARNING;
      };
      Status.prototype.isError = function () {
          return this.severity == Status.ERROR;
      };
      Status.prototype.isOk = function () {
          return this.severity === Status.OK;
      };
      Status.prototype.isInfo = function () {
          return this.severity === Status.INFO;
      };
      Status.prototype.setSource = function (s) {
          this.source = s;
      };
      Status.prototype.toString = function () {
          if (this.isOk()) {
              return "OK";
          }
          return this.message;
      };
      Status.prototype.getExtra = function (name) {
          if (this.takeNodeFromSource && name == tsInterfaces.SOURCE_EXTRA) {
              if (this.source instanceof TypeInformation) {
                  return this.source.node();
              }
          }
          return null;
      };
      Status.prototype.putExtra = function (name, value) { };
      Status.prototype.setInternalRange = function (range) {
          this.internalRange = range;
      };
      Status.prototype.getInternalRange = function () { return this.internalRange; };
      Status.prototype.getInternalPath = function () {
          return this.internalPath;
      };
      Status.prototype.setInternalPath = function (ip) {
          this.internalPath = ip;
      };
      Status.prototype.getFilePath = function () {
          return this.filePath;
      };
      Status.prototype.setFilePath = function (filePath) {
          this.filePath = filePath;
      };
      Status.CODE_CONFLICTING_TYPE_KIND = 4;
      Status.CODE_INCORRECT_DISCRIMINATOR = exports.messageRegistry.INCORRECT_DISCRIMINATOR;
      Status.CODE_MISSING_DISCRIMINATOR = exports.messageRegistry.MISSING_DISCRIMINATOR;
      Status.ERROR = 3;
      Status.INFO = 1;
      Status.OK = 0;
      Status.WARNING = 2;
      return Status;
  }());
  exports.Status = Status;
  function ok() { return new Status(Status.OK, "", "", null); }
  exports.ok = ok;
  ;
  exports.SCHEMA_AND_TYPE = tsInterfaces.SCHEMA_AND_TYPE_EXTRA;
  exports.GLOBAL = tsInterfaces.GLOBAL_EXTRA;
  exports.TOPLEVEL = tsInterfaces.TOP_LEVEL_EXTRA;
  exports.SOURCE_EXTRA = tsInterfaces.SOURCE_EXTRA;
  var messageText = function (messageEntry, params) {
      var result = "";
      var msg = messageEntry.message;
      var prev = 0;
      for (var ind = msg.indexOf("{{"); ind >= 0; ind = msg.indexOf("{{", prev)) {
          result += msg.substring(prev, ind);
          prev = msg.indexOf("}}", ind);
          if (prev < 0) {
              prev = ind;
              break;
          }
          ind += "{{".length;
          var paramName = msg.substring(ind, prev);
          prev += "}}".length;
          var paramValue = params[paramName];
          if (paramValue === undefined) {
              throw new Error(messageText(exports.messageRegistry.MESSAGE_PARAMETER_NO_VALUE, { paramName: paramName }));
          }
          result += paramValue;
      }
      result += msg.substring(prev, msg.length);
      return result;
  };
  function error(messageEntry, source, params, severity, takeNodeFromSource) {
      if (params === void 0) { params = {}; }
      if (severity === void 0) { severity = Status.ERROR; }
      if (takeNodeFromSource === void 0) { takeNodeFromSource = false; }
      var message = messageText(messageEntry, params);
      return new Status(severity, messageEntry.code, message, source, takeNodeFromSource);
  }
  exports.error = error;
  var TypeInformation = /** @class */ (function () {
      function TypeInformation(_inheritable) {
          this._inheritable = _inheritable;
          this._annotations = [];
      }
      TypeInformation.prototype.getClassIdentifier = function () {
          var superIdentifiers = [];
          return superIdentifiers.concat(TypeInformation.CLASS_IDENTIFIER_TypeInformation);
      };
      TypeInformation.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), TypeInformation.CLASS_IDENTIFIER_TypeInformation);
      };
      TypeInformation.prototype.node = function () {
          return this._node;
      };
      TypeInformation.prototype.setNode = function (node) {
          this._node = node;
      };
      TypeInformation.prototype.owner = function () {
          return this._owner;
      };
      TypeInformation.prototype.isInheritable = function () {
          return this._inheritable;
      };
      TypeInformation.prototype.validateSelf = function (registry) {
          var result = ok();
          if (this.node() && this.node().getMeta("skipValidation")) {
              return result;
          }
          for (var _i = 0, _a = this._annotations; _i < _a.length; _i++) {
              var a = _a[_i];
              var aStatus = a.validateSelf(registry);
              if (!aStatus.isOk()) {
                  result.addSubStatus(aStatus);
              }
          }
          var facetEntry = new AnnotatedFacet(this, registry);
          var aPluginStatuses = applyAnnotationValidationPlugins(facetEntry);
          for (var _b = 0, aPluginStatuses_1 = aPluginStatuses; _b < aPluginStatuses_1.length; _b++) {
              var ps = aPluginStatuses_1[_b];
              if (!ps.isOk()) {
                  result.addSubStatus(ps);
              }
          }
          setValidationPath(result, { name: this.facetName() });
          return this.validateSelfIndividual(result, registry);
      };
      TypeInformation.prototype.validateSelfIndividual = function (parentStatus, registry) {
          return parentStatus;
      };
      /**
       * Extension of requiredType() method for the case when there are more than a single type
       * hierarchy roots to cover.
       * requiredType() should return the common superclass for the list.
       *
       * @returns {Array} of types or empty list of there is only a single type set by requiredType() method
       */
      TypeInformation.prototype.requiredTypes = function () {
          return [];
      };
      TypeInformation.prototype.annotations = function () {
          return this._annotations;
      };
      TypeInformation.prototype.addAnnotation = function (a) {
          this._annotations.push(a);
      };
      TypeInformation.prototype.isConstraint = function () {
          return false;
      };
      TypeInformation.CLASS_IDENTIFIER_TypeInformation = "typesystem.TypeInformation";
      return TypeInformation;
  }());
  exports.TypeInformation = TypeInformation;
  var stack = null;
  var Constraint = /** @class */ (function (_super) {
      __extends(Constraint, _super);
      function Constraint(_inheritable) {
          if (_inheritable === void 0) { _inheritable = true; }
          return _super.call(this, _inheritable) || this;
      }
      Constraint.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(Constraint.CLASS_IDENTIFIER_Constraint);
      };
      Constraint.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), Constraint.CLASS_IDENTIFIER_Constraint);
      };
      Constraint.prototype.intersect = function (t0, t1) {
          var nm = t0.id() + "" + t1.id();
          if (Constraint.intersections.hasOwnProperty(nm)) {
              return Constraint.intersections[nm];
          }
          var is = intersect(nm, [t0, t1]);
          Constraint.intersections[nm] = is;
          return is;
      };
      Constraint.prototype.release = function (t) {
          delete Constraint.intersections[t.name()];
      };
      Constraint.prototype.nothing = function (c, message) {
          if (message === void 0) { message = "Conflicting restrictions"; }
          return new NothingRestrictionWithLocation(stack, message, c);
      };
      /**
       * inner implementation of  compute composed restriction from this and parameter restriction
       * @param restriction
       * @return  composed restriction or null;
       */
      Constraint.prototype.composeWith = function (r) { return null; };
      /**
       * returns optimized restiction or this
       * @returns {Constraint}
       */
      Constraint.prototype.preoptimize = function () {
          if (stack === null) {
              stack = new RestrictionStackEntry(null, null, "top");
          }
          stack = stack.push(this);
          try {
              return this.innerOptimize();
          }
          finally {
              stack = stack.pop();
          }
      };
      Constraint.prototype.innerOptimize = function () {
          return this;
      };
      /**
       * performs attempt to compute composed restriction from this and parameter restriction
       * @param restriction
       * @return  composed restriction or null;
       */
      Constraint.prototype.tryCompose = function (r) {
          if (stack === null) {
              stack = new RestrictionStackEntry(null, null, "top");
          }
          stack = stack.push(this);
          try {
              return this.composeWith(r);
          }
          finally {
              stack = stack.pop();
          }
      };
      Constraint.prototype.kind = function () {
          return tsInterfaces.MetaInformationKind.Constraint;
      };
      Constraint.prototype.conflictMessage = function (otherPath, otherValue) { return null; };
      Constraint.prototype.isConstraint = function () {
          return true;
      };
      Constraint.CLASS_IDENTIFIER_Constraint = "typesystem.TypeInformation";
      Constraint.intersections = {};
      return Constraint;
  }(TypeInformation));
  exports.Constraint = Constraint;
  var restr = require("./restrictions");
  var metaInfo = require("./metainfo");
  var fr = require("./facetRegistry");
  var restrictions_1 = require("./restrictions");
  var metainfo_1 = require("./metainfo");
  var metainfo_2 = require("./metainfo");
  var restrictions_2 = require("./restrictions");
  var restrictions_3 = require("./restrictions");
  var exO = require("./exampleBuilder");
  var metainfo_3 = require("./metainfo");
  var restrictions_4 = require("./restrictions");
  exports.autoCloseFlag = false;
  /**
   * Registry of the types
   */
  var TypeRegistry = /** @class */ (function () {
      function TypeRegistry(_parent, _c, isAnnotationsReg) {
          if (_parent === void 0) { _parent = null; }
          if (isAnnotationsReg === void 0) { isAnnotationsReg = false; }
          this._parent = _parent;
          this._c = _c;
          this.isAnnotationsReg = isAnnotationsReg;
          this._types = {};
          this.typeList = [];
          this.chainedTypes = {};
      }
      TypeRegistry.prototype.getClassIdentifier = function () {
          var superIdentifiers = [];
          return superIdentifiers.concat(TypeRegistry.CLASS_IDENTIFIER_TypeRegistry);
      };
      TypeRegistry.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), TypeRegistry.CLASS_IDENTIFIER_TypeRegistry);
      };
      TypeRegistry.prototype.put = function (alias, t) {
          this._types[alias] = t;
      };
      TypeRegistry.prototype.addType = function (t) {
          if (t.isAnonymous()) {
              return;
          }
          this._types[t.name()] = t;
          this.typeList.push(t);
      };
      TypeRegistry.prototype.get = function (name) {
          if (this._types.hasOwnProperty(name)) {
              return this._types[name];
          }
          if (this._parent != null) {
              return this._parent.get(name);
          }
          return null;
      };
      TypeRegistry.prototype.getByChain = function (name) {
          var result = this.get(name);
          if (!result) {
              result = this.chainedTypes[name];
          }
          if (result) {
              return result;
          }
          result = this.getTypeByChainFromCollection(name, this._c);
          if (result) {
              this.chainedTypes[name] = result;
          }
          return result;
      };
      TypeRegistry.prototype.getTypeByChainFromCollection = function (name, collection) {
          var result = this.isAnnotationsReg ? collection.getAnnotationType(name) : collection.getType(name);
          if (result) {
              return result;
          }
          for (var dt_1 = name.indexOf('.'); dt_1 >= 0; dt_1 = name.indexOf('.', dt_1 + 1)) {
              var namespace = name.substring(0, dt_1);
              var typeName = name.substr(dt_1 + 1);
              var lib = collection.library(namespace);
              if (lib) {
                  result = this.getTypeByChainFromCollection(typeName, lib);
                  if (result) {
                      return result;
                  }
              }
          }
          return null;
      };
      TypeRegistry.prototype.types = function () {
          return this.typeList;
      };
      TypeRegistry.prototype.typeMap = function () {
          return this._types;
      };
      TypeRegistry.prototype.parent = function () {
          return this._parent;
      };
      TypeRegistry.CLASS_IDENTIFIER_TypeRegistry = "typesystem.TypeRegistry";
      return TypeRegistry;
  }());
  exports.TypeRegistry = TypeRegistry;
  var PropertyCyclesValidator = /** @class */ (function () {
      function PropertyCyclesValidator() {
      }
      PropertyCyclesValidator.prototype.getInfos = function (t) {
          if (t.getExtra("PInfos")) {
              return t.getExtra("PInfos");
          }
          var m = {};
          t.meta().forEach(function (x) {
              if (x instanceof restr.HasProperty) {
                  var id = x.value();
                  m[id] = { name: id, type: null };
              }
          });
          t.meta().forEach(function (x) {
              if (x instanceof restr.PropertyIs) {
                  var id = x.propertyName();
                  if (m[id]) {
                      m[id].type = x.value();
                  }
              }
          });
          t.putExtra("PInfos", m);
          return m;
      };
      PropertyCyclesValidator.prototype.validate = function (t, visited) {
          var _this = this;
          var i = this.getInfos(t);
          var result = false;
          Object.keys(i).forEach(function (x) {
              result = result || _this.validateInfo(i[x], visited);
          });
          return result;
      };
      PropertyCyclesValidator.prototype.validateInfo = function (t, visited) {
          var _this = this;
          if (visited.some(function (y) { return y == t; })) {
              return true;
          }
          else {
              if (t.type instanceof UnionType) {
                  var ut = t.type;
                  var passing = true;
                  ut.options().forEach(function (o) {
                      if (!_this.validate(o, [t].concat(visited))) {
                          passing = false;
                      }
                  });
                  return passing;
              }
              if (t.type.isArray()) {
              }
              else {
                  return this.validate(t.type, [t].concat(visited));
              }
          }
      };
      PropertyCyclesValidator.prototype.validateType = function (t) {
          var _this = this;
          var i = this.getInfos(t);
          var result = [];
          Object.keys(i).forEach(function (x) {
              if (_this.validateInfo(i[x], [])) {
                  result.push(x);
              }
          });
          return result;
      };
      return PropertyCyclesValidator;
  }());
  var RestrictionsConflict = /** @class */ (function (_super) {
      __extends(RestrictionsConflict, _super);
      function RestrictionsConflict(_conflicting, _stack, source) {
          var _this = _super.call(this, Status.ERROR, exports.messageRegistry.RESTRICTIONS_CONFLICT.code, null, source) || this;
          _this._conflicting = _conflicting;
          _this._stack = _stack;
          _this.source = source;
          _this.computeMessage();
          return _this;
      }
      RestrictionsConflict.prototype.computeMessage = function () {
          var conflictingMessage = null;
          if (this._stack != null) {
              if (this._stack.getRestriction() instanceof restr.MinMaxRestriction) {
                  var mmr = this._stack.getRestriction();
                  conflictingMessage = this._conflicting.conflictMessage(mmr.facetPath(), mmr.value());
              }
          }
          if (conflictingMessage == null) {
              conflictingMessage = this._conflicting + " and " + (this._stack != null ? this._stack.getRestriction().toString() : "");
          }
          var typeInfo = "";
          if (this.source instanceof AbstractType) {
              var path = [];
              var rse = this._stack;
              while (rse) {
                  var restri = rse.getRestriction();
                  if (restri instanceof restrictions_2.PropertyIs) {
                      var vp = { name: restri.propId() };
                      if (path.length > 0) {
                          vp.child = path[path.length - 1];
                      }
                      path.push(vp);
                  }
                  rse = rse.pop();
              }
              setValidationPath(this, path.pop());
              var arc = restr.anotherRestrictionComponent();
              if (arc) {
                  typeInfo = " between types '" + typePath(this.source) + "' and '" + typePath(arc) + "'";
              }
              else {
                  typeInfo = " in type '" + typePath(this.source) + "'";
              }
          }
          this.message = "Restrictions conflict" + typeInfo + ": " + conflictingMessage;
      };
      RestrictionsConflict.prototype.getConflictDescription = function () {
          var rs = "";
          rs += "Restrictions coflict:\n";
          rs += this._stack.getRestriction() + " conflicts with " + this._conflicting + "\n";
          rs += "at\n";
          rs += this._stack.pop();
          return rs;
      };
      RestrictionsConflict.prototype.getConflicting = function () {
          return this._conflicting;
      };
      RestrictionsConflict.prototype.getStack = function () {
          return this._stack;
      };
      RestrictionsConflict.prototype.toRestriction = function () {
          return new NothingRestrictionWithLocation(this._stack, this.message, this._conflicting);
      };
      return RestrictionsConflict;
  }(Status));
  exports.RestrictionsConflict = RestrictionsConflict;
  var globalId = 0;
  exports.VALIDATED_TYPE = null;
  var PropertyInfo = /** @class */ (function () {
      function PropertyInfo(obj) {
          if (restr.MatchesProperty.isInstance(obj)) {
              this._matches = obj;
              var fn = this._matches.facetName();
              if (fn == "propertyIs") {
                  this.isProp = true;
              }
              else if (fn == "mapPropertyIs") {
                  this.isMap = true;
              }
              else if (fn == "additionalProperties") {
                  this.isAdditionalProp = true;
              }
          }
          else {
              this.isFacet = true;
              this._facetDecl = obj;
          }
      }
      PropertyInfo.prototype.name = function () {
          return this.isFacet ? this._facetDecl.actualName() : this._matches.path();
      };
      PropertyInfo.prototype.isPattern = function () {
          return this.isMap;
      };
      PropertyInfo.prototype.isAdditional = function () {
          return this.isAdditionalProp;
      };
      PropertyInfo.prototype.declaredAt = function () {
          return this.isFacet ? this._facetDecl.owner() : this._matches.owner();
      };
      PropertyInfo.prototype.range = function () {
          return this.isFacet ? this._facetDecl.type() : this._matches.range();
      };
      PropertyInfo.prototype.required = function () {
          if (this._required !== undefined) {
              return this._required;
          }
          if (this.isProp) {
              return !this.property().isOptional();
          }
          else if (this.isMap) {
              return !this.mapProperty().isOptional();
          }
          else if (this.isAdditionalProp) {
              return !this.additionalProperty().isOptional();
          }
          return false;
      };
      PropertyInfo.prototype.setRequired = function (val) {
          this._required = val;
      };
      PropertyInfo.prototype.property = function () {
          return this.isProp ? this._matches : null;
      };
      PropertyInfo.prototype.mapProperty = function () {
          return this.isMap ? this._matches : null;
      };
      PropertyInfo.prototype.additionalProperty = function () {
          return this.isAdditionalProp ? this._matches : null;
      };
      PropertyInfo.prototype.annotations = function () {
          return this._matches ? this._matches.annotations() : [];
      };
      return PropertyInfo;
  }());
  exports.PropertyInfo = PropertyInfo;
  var AbstractType = /** @class */ (function () {
      function AbstractType(_name) {
          this._name = _name;
          this.metaInfo = [];
          this._subTypes = [];
          this.innerid = globalId++;
          this.extras = {};
          this._locked = false;
      }
      AbstractType.prototype.getClassIdentifier = function () {
          var superIdentifiers = [];
          return superIdentifiers.concat(AbstractType.CLASS_IDENTIFIER_AbstractType);
      };
      AbstractType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), AbstractType.CLASS_IDENTIFIER_AbstractType);
      };
      AbstractType.prototype.annotation = function (name) {
          var res = null;
          for (var _i = 0, _a = this.annotations(); _i < _a.length; _i++) {
              var x = _a[_i];
              if (x.name() == name) {
                  return x.value();
              }
          }
          return null;
      };
      AbstractType.prototype.isAssignableFrom = function (t) {
          if (t.allSuperTypes().indexOf(this) != -1) {
              return true;
          }
          //TODO make it better
          var ms = this.restrictions().filter(function (x) { return !metaInfo.DiscriminatorValue.isInstance(x); });
          var another = t.restrictions();
          var all = true;
          ms.forEach(function (x) {
              var found = false;
              another.forEach(function (y) {
                  var vm = x.composeWith(y);
                  if (vm == y) {
                      found = true;
                  }
                  if (GenericTypeOf.isInstance(y) && vm != null) {
                      if (vm == x) {
                          found = true;
                      }
                  }
              });
              all = all && found;
          });
          return all;
      };
      AbstractType.prototype.registry = function () {
          return this._collection;
      };
      AbstractType.prototype.cloneWithFilter = function (x, f) {
          var c = this.clone();
          var ms = [];
          this.metaInfo.forEach(function (f) {
              var rs = x(f, c);
              if (typeof rs == "boolean") {
                  if (rs) {
                      ms.push(f);
                  }
              }
              else {
                  if (rs) {
                      ms.push(rs);
                  }
              }
          });
          c.metaInfo = ms;
          return c;
      };
      AbstractType.prototype.options = function () {
          if (this.isUnion()) {
              var res = [];
              this.allSuperTypes().forEach(function (x) {
                  if (UnionType.isInstance(x)) {
                      var opts = x.options();
                      res = res.concat(opts);
                  }
              });
              return _.unique(res);
          }
          return [this];
      };
      AbstractType.prototype.allOptions = function () {
          if (this.isUnion()) {
              var res = [];
              this.allSuperTypes().forEach(function (x) {
                  if (UnionType.isInstance(x)) {
                      var opts = x.allOptions();
                      res = res.concat(opts);
                  }
              });
              return _.unique(res);
          }
          return [this];
      };
      AbstractType.prototype.examples = function () {
          return exO.exampleFromInheritedType2(this);
      };
      AbstractType.prototype.collection = function () {
          if (!this._collection) {
              if (this._contextMeta) {
                  var cm = this._contextMeta;
                  if (cm) {
                      return cm.owner().collection();
                  }
              }
          }
          return this._collection;
      };
      AbstractType.prototype.getExtra = function (name) {
          return this.extras[name];
      };
      AbstractType.prototype.putExtra = function (name, v) {
          this.extras[name] = v;
      };
      AbstractType.prototype.id = function () {
          return this.innerid;
      };
      AbstractType.prototype.knownProperties = function () {
          return this.metaOfType(restrictions_4.MatchesProperty);
      };
      AbstractType.prototype.lock = function () {
          this._locked = true;
      };
      AbstractType.prototype.isLocked = function () {
          return this._locked;
      };
      AbstractType.prototype.patchName = function (name) {
          this._name = name;
      };
      AbstractType.prototype.allFacets = function () {
          return this.meta().filter(function (x) {
              if (!metaInfo.DiscriminatorValue.isInstance(x)) {
                  return true;
              }
              return x.isStrict();
          });
      };
      AbstractType.prototype.declaredFacets = function () {
          return this.declaredMeta();
      };
      AbstractType.prototype.isSubTypeOf = function (t) {
          return t === exports.ANY || this === t || this.superTypes().some(function (x) { return x.isSubTypeOf(t); });
      };
      AbstractType.prototype.isSuperTypeOf = function (t) {
          return this === t || this.allSubTypes().indexOf(t) != -1;
      };
      AbstractType.prototype.addMeta = function (info) {
          this.metaInfo.push(info);
          info._owner = this;
          this.propertyInfos = null;
          this.propertiesMap = null;
          this.definedFacetInfos = null;
          this.definedFacetInfosMap = null;
      };
      AbstractType.prototype.name = function () {
          return this._name;
      };
      AbstractType.prototype.label = function () {
          return this._name;
      };
      /**
       * @return directly known sub types of a given type
       */
      AbstractType.prototype.subTypes = function () {
          return this._subTypes;
      };
      /**
       * @return directly known super types of a given type
       */
      AbstractType.prototype.superTypes = function () {
          return [];
      };
      AbstractType.prototype.addSupertypeAnnotation = function (arr, ind) {
          if (!arr || arr.length == 0) {
              return;
          }
          if (!this.supertypeAnnotations) {
              this.supertypeAnnotations = [];
          }
          var aMap = this.supertypeAnnotations[ind];
          if (!aMap) {
              aMap = {};
              this.supertypeAnnotations[ind] = aMap;
          }
          for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
              var a = arr_1[_i];
              aMap[a.facetName()] = a;
          }
      };
      AbstractType.prototype.validateType = function (tr) {
          var _this = this;
          if (tr === void 0) { tr = builtInRegistry(); }
          var rs = new Status(Status.OK, "", "", this);
          this.validateHierarchy(rs);
          if (this.getExtra(tsInterfaces.PARSE_ERROR)) {
              rs.addSubStatus(this.getExtra(tsInterfaces.PARSE_ERROR));
          }
          if (rs.isOk()) {
              rs.addSubStatus(this.checkConfluent());
              if (this.isExternal() && this.kind() == "external") {
                  var extType = this;
                  if (extType.isJSON()) {
                      try {
                          var sch = su.getJSONSchema(extType.schema(), extType.getContentProvider && extType.getContentProvider());
                          if (sch) {
                              sch.validateSelf();
                          }
                      }
                      catch (e) {
                          if (e.message == "Maximum call stack size exceeded") {
                              return error(exports.messageRegistry.CIRCULAR_REFS_IN_JSON_SCHEMA, this);
                          }
                          else if (ValidationError.isInstance(e)) {
                              var ve = e;
                              var errorStatus = error(ve.messageEntry, this, ve.parameters, ve.isWarning ? Status.WARNING : Status.ERROR);
                              errorStatus.setInternalRange(ve.internalRange);
                              errorStatus.setInternalPath(toValidationPath(ve.internalPath));
                              errorStatus.setFilePath(ve.filePath);
                              rs.addSubStatus(errorStatus);
                          }
                          else {
                              rs.addSubStatus(error(exports.messageRegistry.JSON_SCHEMA_VALIDATION_EXCEPTION, this, { msg: e.message }));
                          }
                      }
                  }
              }
              if (rs.isOk()) {
                  this.superTypes().forEach(function (x) {
                      if (x.isAnonymous()) {
                          var superStatus = x.validateType(tr);
                          if (!superStatus.isOk()) {
                              setValidationPath(superStatus, { name: "type" });
                              rs.addSubStatus(superStatus);
                          }
                      }
                  });
              }
          }
          if (this.getExtra(exports.SCHEMA_AND_TYPE)) {
              rs.addSubStatus(error(exports.messageRegistry.SCHEMA_AND_TYPE, this));
          }
          if (rs.isOk()) {
              this.validateMeta(tr).getErrors().forEach(function (x) { return rs.addSubStatus(x); });
          }
          //if (this.isPolymorphic()||(this.isUnion())) {
          //    rs.addSubStatus(this.canDoAc());
          //}
          if (this.isObject()) {
              var required = {};
              this.restrictions().forEach(function (x) {
                  if (x.owner() != _this) {
                      if (x instanceof restr.HasProperty) {
                          required[x.value()] = true;
                      }
                  }
              });
              this.declaredMeta().forEach(function (x) {
                  if (x instanceof restr.HasProperty) {
                      delete required[x.value()];
                  }
              });
              this.declaredMeta().forEach(function (x) {
                  if (x instanceof restr.PropertyIs) {
                      var pr = x;
                      if (required.hasOwnProperty(pr.propertyName())) {
                          rs.addSubStatus(error(exports.messageRegistry.REQUIRED_OVERRIDE_OPTIONAL, _this, { propertyName: pr.propertyName() }));
                      }
                  }
              });
              var propertyCycles = new PropertyCyclesValidator().validateType(this);
              if (propertyCycles.length > 0) {
                  propertyCycles.forEach(function (p) {
                      var st = error(exports.messageRegistry.CYCLIC_DEPENDENCY, _this, { typeName: p });
                      setValidationPath(st, { name: p });
                      rs.addSubStatus(st);
                  });
              }
          }
          if (this.supertypeAnnotations) {
              for (var i = 0; i < this.supertypeAnnotations.length; i++) {
                  var aMap = this.supertypeAnnotations[i];
                  for (var _i = 0, _a = Object.keys(aMap); _i < _a.length; _i++) {
                      var aName = _a[_i];
                      var a = aMap[aName];
                      var aStatus = a.validateSelf(tr);
                      if (!aStatus.isOk()) {
                          setValidationPath(aStatus, { name: "type", child: { name: i } });
                          rs.addSubStatus(aStatus);
                      }
                  }
              }
          }
          var pluginStatuses = applyTypeValidationPlugins(this, tr);
          for (var _b = 0, pluginStatuses_1 = pluginStatuses; _b < pluginStatuses_1.length; _b++) {
              var ps = pluginStatuses_1[_b];
              rs.addSubStatus(ps);
          }
          var typeEntry = new AnnotatedType(this, tr);
          var aPluginStatuses = applyAnnotationValidationPlugins(typeEntry);
          for (var _d = 0, aPluginStatuses_2 = aPluginStatuses; _d < aPluginStatuses_2.length; _d++) {
              var ps = aPluginStatuses_2[_d];
              rs.addSubStatus(ps);
          }
          return rs;
      };
      AbstractType.prototype.validateHierarchy = function (rs) {
          var _this = this;
          if (!this.isAnonymous()) {
              if (this.getExtra(tsInterfaces.TOP_LEVEL_EXTRA) && builtInRegistry().get(this.name())) {
                  rs.addSubStatus(error(exports.messageRegistry.REDEFINIG_BUILDTIN, this, { typeName: this.name() }));
              }
          }
          if (this.isSubTypeOf(exports.RECURRENT)) {
              rs.addSubStatus(error(exports.messageRegistry.RECURRENT_DEFINITION, this), "type");
          }
          if (isUnknown(this)) {
              var chained = this.metaOfType(metaInfo.ImportedByChain);
              if (chained.length > 0) {
                  var issues_1 = [];
                  chained.forEach(function (x) {
                      issues_1.push(error(exports.messageRegistry.INHERITING_TYPE_IMPORTED_THROUGH_LIBRARY_CHAIN, _this, {
                          typeName: x.value()
                      }));
                  });
                  issues_1.forEach(function (x) { return rs.addSubStatus(x, "type"); });
              }
              else {
                  rs.addSubStatus(error(exports.messageRegistry.INHERITING_UNKNOWN_TYPE, this), "type");
              }
          }
          if (this.isUnion()) {
              var tf = this.typeFamily();
              var chained_1 = [];
              var isRecurent = false;
              var isUnknown_1 = false;
              for (var _i = 0, tf_1 = tf; _i < tf_1.length; _i++) {
                  var t = tf_1[_i];
                  if (t.isSubTypeOf(exports.RECURRENT)) {
                      isRecurent = true;
                  }
                  else if (t.isSubTypeOf(exports.UNKNOWN)) {
                      isUnknown_1 = true;
                  }
                  t.metaOfType(metaInfo.ImportedByChain).forEach(function (x) { return chained_1.push(x); });
              }
              if (isRecurent) {
                  rs.addSubStatus(error(exports.messageRegistry.RECURRENT_UNION_OPTION, this), "type");
              }
              if (isUnknown_1) {
                  if (chained_1.length > 0) {
                      chained_1 = _.unique(chained_1);
                      if (chained_1.length > 0) {
                          chained_1.forEach(function (x) {
                              var typeName = x.value();
                              var messageEntry = exports.messageRegistry.UNION_OPTION_TYPE_DEPENDS_ON_TYPE_IMPORTED_THROUGH_LIBRARY_CHAIN;
                              if (_this.options().some(function (y) { return y.name() == typeName; })) {
                                  messageEntry = exports.messageRegistry.UNION_OPTION_TYPE_OPTION_IMPORTED_THROUGH_LIBRARY_CHAIN;
                              }
                              rs.addSubStatus(error(messageEntry, _this, { typeName: typeName }), "type");
                          });
                      }
                  }
                  else {
                      rs.addSubStatus(error(exports.messageRegistry.UNKNOWN_UNION_OPTION, this), "type");
                  }
              }
          }
          if (this.isArray()) {
              var fs_2 = this.familyWithArray();
              var ps = this.getExtra(tsInterfaces.HAS_ITEMS) ? "items" : "type";
              var chained_2 = [];
              var isRecurent = false;
              var isUnknown_2 = false;
              for (var _a = 0, fs_1 = fs_2; _a < fs_1.length; _a++) {
                  var t = fs_1[_a];
                  if (t == this || t === exports.RECURRENT) {
                      isRecurent = true;
                  }
                  else if (t == exports.UNKNOWN) {
                      isUnknown_2 = true;
                  }
                  t.metaOfType(metaInfo.ImportedByChain).forEach(function (x) { return chained_2.push(x); });
              }
              if (isRecurent) {
                  rs.addSubStatus(error(exports.messageRegistry.RECURRENT_ARRAY_DEFINITION, this), ps);
              }
              else if (isUnknown_2) {
                  var componentTypeName = this.oneMeta(restrictions_3.ComponentShouldBeOfType).value().name();
                  if (chained_2.length > 0) {
                      chained_2 = _.unique(chained_2);
                      chained_2.forEach(function (x) {
                          var typeName = componentTypeName;
                          var messageEntry = exports.messageRegistry.ARRAY_COMPONENT_TYPE_IMPORTED_THROUGH_LIBRARY_CHAIN;
                          if (!typeName) {
                              componentTypeName = x.value();
                          }
                          else if (x.value() != typeName) {
                              messageEntry = exports.messageRegistry.ARRAY_COMPONENT_TYPE_DEPENDES_ON_TYPE_IMPORTED_THROUGH_LIBRARY_CHAIN;
                              typeName = x.value();
                          }
                          rs.addSubStatus(error(messageEntry, _this, { componentTypeName: componentTypeName, typeName: typeName }), ps);
                      });
                  }
                  else {
                      rs.addSubStatus(error(exports.messageRegistry.UNKNOWN_ARRAY_COMPONENT_TYPE, this, { componentTypeName: componentTypeName }), ps);
                  }
              }
          }
          var supers = this.superTypes();
          var hasExternal = false;
          var hasNotExternal = false;
          if (supers.length > 1) {
              supers.forEach(function (x) {
                  if (x.isExternal()) {
                      hasExternal = true;
                  }
                  else {
                      hasNotExternal = true;
                  }
              });
          }
          if (hasExternal && hasNotExternal) {
              rs.addSubStatus(error(exports.messageRegistry.EXTERNALS_MIX, this));
          }
          if (this instanceof UnionType) {
              var ut = this;
              ut.options().forEach(function (x) {
                  if (x.isExternal()) {
                      rs.addSubStatus(error(exports.messageRegistry.EXTERNALS_MIX, _this));
                  }
              });
          }
          if (this.isExternal()) {
              if (this.getExtra(tsInterfaces.HAS_FACETS)) {
                  var fArr = this.getExtra(tsInterfaces.HAS_FACETS);
                  if (fArr.length) {
                      var f = fArr[fArr.length - 1];
                      var fs = error(exports.messageRegistry.EXTERNAL_FACET, this, { name: f });
                      setValidationPath(fs, { name: f });
                      rs.addSubStatus(fs);
                  }
              }
          }
      };
      ;
      AbstractType.prototype.familyWithArray = function () {
          if (this.oneMeta(metaInfo.SkipValidation)) {
              return [];
          }
          var ts = [];
          this.fillSuperTypes(ts, true);
          var mn = this.oneMeta(restrictions_3.ComponentShouldBeOfType);
          if (mn) {
              var at = mn.value();
              if (!at.oneMeta(metaInfo.SkipValidation)) {
                  ts = ts.concat(at.familyWithArray().concat(at));
              }
          }
          return ts;
      };
      AbstractType.prototype.validateMeta = function (tr) {
          var rs = new Status(Status.OK, "", "", this);
          this.declaredMeta().forEach(function (x) {
              x.validateSelf(tr).getErrors().forEach(function (y) { return rs.addSubStatus(y); });
          });
          this.validateFacets(rs);
          return rs;
      };
      AbstractType.prototype.validateFacets = function (rs) {
          var _this = this;
          var fds = {};
          var super_facets = {};
          var rfds = {};
          this.meta().forEach(function (x) {
              if (x instanceof metainfo_1.FacetDeclaration) {
                  var fd = x;
                  fds[fd.actualName()] = fd;
                  if (!fd.isOptional()) {
                      if (fd.owner() !== _this) {
                          rfds[fd.actualName()] = fd;
                      }
                  }
                  if (fd.owner() != _this) {
                      super_facets[fd.actualName()] = fd;
                  }
              }
          });
          this.declaredMeta().forEach(function (x) {
              if (x instanceof metainfo_1.FacetDeclaration) {
                  var fd = x;
                  if (fd.owner() == _this) {
                      var an = fd.actualName();
                      if (super_facets.hasOwnProperty(an)) {
                          rs.addSubStatus(error(exports.messageRegistry.OVERRIDE_FACET, _this, { name: an }));
                      }
                      var fp = fr.getInstance().facetPrototypeWithName(an);
                      if (fp && fp.isApplicable(_this) || an == "type" ||
                          fd.facetName() == "properties" || an == "schema" || an == "facets" || an == "uses") {
                          rs.addSubStatus(error(exports.messageRegistry.OVERRIDE_BUILTIN_FACET, _this, { name: an }));
                      }
                      if (an.charAt(0) == '(') {
                          rs.addSubStatus(error(exports.messageRegistry.FACET_START_BRACKET, _this, { name: an }));
                      }
                  }
              }
          });
          var knownPropertySet = {};
          this.meta().forEach(function (x) {
              if (x instanceof restrictions_2.PropertyIs) {
                  knownPropertySet[x.propId()] = true;
              }
          });
          for (var _i = 0, _a = this.meta(); _i < _a.length; _i++) {
              var x = _a[_i];
              if (x instanceof metainfo_2.CustomFacet) {
                  var cd = x;
                  if (cd.node() && cd.node().getMeta("skipValidation")) {
                      continue;
                  }
                  var facetName = cd.facetName();
                  if (fds.hasOwnProperty(facetName)) {
                      var facet = fds[facetName];
                      var ft = facet.value();
                      if (facet.owner() == this && cd.owner() == this) {
                          var err_1 = error(exports.messageRegistry.FACET_CAN_NOT_BE_FIXED_BY_THE_DECLARING_TYPE, cd);
                          err_1.setValidationPath({ name: facetName });
                          rs.addSubStatus(err_1);
                      }
                      else {
                          var st = ft.validateDirect(cd.value(), false, false);
                          for (var _b = 0, _d = st.getErrors(); _b < _d.length; _b++) {
                              var err = _d[_b];
                              setValidationPath(err, { name: facetName });
                              rs.addSubStatus(err);
                          }
                          ;
                          delete rfds[facetName];
                      }
                  }
                  else {
                      if (this.isExternal()) {
                          rs.addSubStatus(error(exports.messageRegistry.FACET_PROHIBITED_FOR_EXTERNALS, cd, { facetName: facetName }, Status.ERROR, true));
                      }
                      else {
                          rs.addSubStatus(error(exports.messageRegistry.UNKNOWN_FACET, cd, { facetName: facetName }, Status.ERROR, true));
                      }
                  }
              }
              // if (x instanceof MapPropertyIs){
              //     var mm:MapPropertyIs=x;
              //     Object.keys(knownPropertySet).forEach(c=>{
              //         try {
              //             if (c.match(mm.regexpValue())) {
              //                 var regexpText = '/' + mm.regexpValue().toString() + '/';
              //                
              //                 rs.addSubStatus(new Status(Status.WARNING, 0, `Pattern property '${regexpText}' conflicts with property: '${c}'`, this));
              //             }
              //         } catch (e){
              //             //ignore incorrect regexps here
              //         }
              //     })
              // }
          }
          if (Object.getOwnPropertyNames(rfds).length > 0) {
              rs.addSubStatus(error(exports.messageRegistry.MISSING_REQUIRED_FACETS, this, { facetsList: Object.keys(rfds).map(function (x) { return "'" + x + "'"; }).join(",") }));
          }
      };
      ;
      AbstractType.prototype.allSuperTypes = function () {
          var rs = [];
          this.fillSuperTypes(rs);
          return rs;
      };
      AbstractType.prototype.fillSuperTypes = function (r, forValidation) {
          if (forValidation === void 0) { forValidation = false; }
          for (var _i = 0, _a = this.superTypes(); _i < _a.length; _i++) {
              var x = _a[_i];
              if (forValidation && x.oneMeta(metaInfo.SkipValidation)) {
                  continue;
              }
              if (!_.contains(r, x)) {
                  r.push(x);
                  x.fillSuperTypes(r);
              }
          }
      };
      AbstractType.prototype.allSubTypes = function () {
          var rs = [];
          this.fillSubTypes(rs);
          return rs;
      };
      AbstractType.prototype.fillSubTypes = function (r) {
          this.subTypes().forEach(function (x) {
              if (!_.contains(r, x)) {
                  r.push(x);
                  x.fillSubTypes(r);
              }
          });
      };
      AbstractType.prototype.inherit = function (name) {
          var rs = new InheritedType(name);
          rs.addSuper(this);
          return rs;
      };
      /**
       *
       * @return true if type is an inplace type and has no name
       */
      AbstractType.prototype.isAnonymous = function () {
          return (!this._name) || this._name.length === 0;
      };
      /**
       *
       * @return true if type has no associated meta information of restrictions
       */
      AbstractType.prototype.isEmpty = function () {
          if (this.extras != null && this.extras.hasOwnProperty(tsInterfaces.PARSE_ERROR)) {
              return false;
          }
          if (this.metaInfo.length > 2) {
              return false;
          }
          return this.metaInfo.filter(function (x) {
              if (metainfo_3.NotScalar.isInstance(x)) {
                  return false;
              }
              else if (metaInfo.DiscriminatorValue.isInstance(x)) {
                  return x.isStrict();
              }
              else if (metaInfo.SourceMap.isInstance(x)) {
                  return false;
              }
              else if (metaInfo.ImportedByChain.isInstance(x)) {
                  return false;
              }
              return true;
          }).length == 0;
      };
      /**
       *
       * @return true if type is an array or extends from an array
       */
      AbstractType.prototype.isArray = function () {
          return this === exports.ARRAY || this.allSuperTypes().indexOf(exports.ARRAY) != -1;
      };
      AbstractType.prototype.propertySet = function () {
          var rs = [];
          this.meta().forEach(function (x) {
              if (x instanceof restrictions_2.PropertyIs) {
                  var p = x;
                  rs.push(p.propertyName());
              }
          });
          return _.uniq(rs);
      };
      AbstractType.prototype.checkConfluent = function () {
          if (this.oneMeta(metaInfo.SkipValidation)) {
              return ok();
          }
          if (this.computeConfluent) {
              return ok();
          }
          this.computeConfluent = true;
          var arcc = restr.anotherRestrictionComponentsCount();
          try {
              var os = restr.optimize(this.restrictions());
              var ns = _.find(os, function (x) { return x instanceof NothingRestriction; });
              if (ns) {
                  var lstack = null;
                  var another = null;
                  if (ns instanceof NothingRestrictionWithLocation) {
                      var nswl = ns;
                      lstack = nswl.getStack();
                      another = nswl.another();
                  }
                  var status = new RestrictionsConflict(another, lstack, this);
                  return status;
              }
              return ok();
          }
          finally {
              this.computeConfluent = false;
              restr.releaseAnotherRestrictionComponent(arcc);
          }
      };
      /**
       *
       * @return true if type is object or inherited from object
       */
      AbstractType.prototype.isObject = function () {
          return this == exports.OBJECT || _.some(this.allSuperTypes(), function (x) { return x.isObject(); });
      };
      /**
       *
       * @return true if type is object or inherited from object
       */
      AbstractType.prototype.isExternal = function () {
          return this == exports.EXTERNAL || this.allSuperTypes().indexOf(exports.EXTERNAL) != -1;
      };
      /**
       *
       * @return true if type is an boolean type or extends from boolean
       */
      AbstractType.prototype.isBoolean = function () {
          return this == exports.BOOLEAN || this.allSuperTypes().indexOf(exports.BOOLEAN) != -1;
      };
      /**
       *
       * @return true if type is string or inherited from string
       */
      AbstractType.prototype.isString = function () {
          return this == exports.STRING || this.allSuperTypes().indexOf(exports.STRING) != -1;
      };
      /**
       *
       * @return true if type is number or inherited from number
       */
      AbstractType.prototype.isNumber = function () {
          return this == exports.NUMBER || this.allSuperTypes().indexOf(exports.NUMBER) != -1;
      };
      /**
       *
       * @return true if type is number or inherited from number
       */
      AbstractType.prototype.isFile = function () {
          return this == exports.FILE || this.allSuperTypes().indexOf(exports.FILE) != -1;
      };
      /**
       *
       * @return true if type is scalar or inherited from scalar
       */
      AbstractType.prototype.isScalar = function () {
          return this == exports.SCALAR || this.allSuperTypes().indexOf(exports.SCALAR) != -1;
      };
      /**
       * returns true if this type inherits from one of date related types
       */
      AbstractType.prototype.isDateTime = function () {
          return this == exports.DATETIME || this.allSuperTypes().indexOf(exports.DATETIME) != -1;
      };
      /**
       * returns true if this type inherits from one of date related types
       */
      AbstractType.prototype.isDateOnly = function () {
          return this == exports.DATE_ONLY || this.allSuperTypes().indexOf(exports.DATE_ONLY) != -1;
      };
      /**
       * returns true if this type inherits from one of date related types
       */
      AbstractType.prototype.isTimeOnly = function () {
          return this == exports.TIME_ONLY || this.allSuperTypes().indexOf(exports.TIME_ONLY) != -1;
      };
      /**
       * returns true if this type inherits from one of date related types
       */
      AbstractType.prototype.isInteger = function () {
          return this == exports.INTEGER || this.allSuperTypes().indexOf(exports.INTEGER) != -1;
      };
      /**
       * returns true if this type inherits from one of date related types
       */
      AbstractType.prototype.isDateTimeOnly = function () {
          return this == exports.DATETIME_ONLY || this.allSuperTypes().indexOf(exports.DATETIME_ONLY) != -1;
      };
      /**
       *
       * @return true if type is scalar or inherited from scalar
       */
      AbstractType.prototype.isUnknown = function () {
          return this == exports.UNKNOWN || this.allSuperTypes().indexOf(exports.UNKNOWN) != -1;
      };
      /**
       *
       * @return true if type is scalar or inherited from scalar
       */
      AbstractType.prototype.isRecurrent = function () {
          return this == exports.RECURRENT || this.allSuperTypes().indexOf(exports.RECURRENT) != -1;
      };
      /**
       *
       * @return true if type is an built-in type
       */
      AbstractType.prototype.isBuiltin = function () {
          return this.metaInfo.indexOf(BUILT_IN) != -1;
      };
      AbstractType.prototype.exampleObject = function () {
          return exO.example(this);
      };
      /**
       *
       * @return true if type is an polymorphic type
       */
      AbstractType.prototype.isPolymorphic = function () {
          return this.meta().some(function (x) { return x instanceof Polymorphic; });
      };
      /**
       * @return all restrictions associated with type
       */
      AbstractType.prototype.restrictions = function (forValidation) {
          if (forValidation === void 0) { forValidation = false; }
          if (this.isUnion()) {
              var rs = [];
              this.superTypes().forEach(function (x) {
                  rs = rs.concat(x.restrictions());
              });
              rs = rs.concat(this.meta().filter(function (x) { return x instanceof Constraint; }));
              return rs;
          }
          var result = [];
          var generic = null;
          this.meta().forEach(function (x) {
              if (x instanceof Constraint) {
                  if (x instanceof GenericTypeOf && forValidation) {
                      if (generic) {
                          return;
                      }
                      generic = x;
                  }
                  result.push(x);
              }
          });
          return result;
      };
      AbstractType.prototype.customFacets = function () {
          return this.declaredMeta().filter(function (x) { return x instanceof metaInfo.CustomFacet; });
      };
      AbstractType.prototype.allCustomFacets = function () {
          return this.meta().filter(function (x) { return x instanceof metaInfo.CustomFacet; });
      };
      AbstractType.prototype.isUnion = function () {
          var rs = false;
          if (this.isBuiltin()) {
              return false;
          }
          this.allSuperTypes().forEach(function (x) { return rs = rs || x instanceof UnionType; });
          return rs;
      };
      AbstractType.prototype.isIntersection = function () {
          var rs = false;
          if (this.isBuiltin()) {
              return false;
          }
          this.allSuperTypes().forEach(function (x) { return rs = rs || x instanceof IntersectionType; });
          return rs;
      };
      /**
       * return all type information associated with type
       */
      AbstractType.prototype.meta = function () {
          return [].concat(this.metaInfo);
      };
      /**
       * validates object against this type without performing AC
       */
      AbstractType.prototype.validateDirect = function (i, autoClose, nullAllowed, path) {
          var _this = this;
          if (autoClose === void 0) { autoClose = false; }
          if (nullAllowed === void 0) { nullAllowed = true; }
          if (path === void 0) { path = null; }
          var prevValidated = exports.VALIDATED_TYPE;
          try {
              var g = exports.autoCloseFlag;
              if (autoClose) {
                  exports.autoCloseFlag = true;
              }
              exports.VALIDATED_TYPE = this;
              var result = new Status(Status.OK, "", "", this);
              if (!nullAllowed && (i === null || i === undefined)) {
                  if (!this.nullable) {
                      var typeRestriction = null;
                      this.restrictions(true).forEach(function (restriction) {
                          if (restriction instanceof TypeOfRestriction) {
                              if (typeRestriction) {
                                  return;
                              }
                              typeRestriction = restriction;
                          }
                      });
                      if (typeRestriction) {
                          return error(exports.messageRegistry.TYPE_EXPECTED, typeRestriction, {
                              expectedType: typeRestriction.value(),
                              actualType: 'null'
                          });
                      }
                      return error(exports.messageRegistry.OBJECT_EXPECTED, this);
                  }
              }
              this.restrictions(true).forEach(function (x) { return result.addSubStatus(x.check(i, path)); });
              if ((autoClose || exports.autoCloseFlag) && this.isObject() && (!this.oneMeta(restrictions_1.KnownPropertyRestriction))) {
                  var cp = new restrictions_1.KnownPropertyRestriction(false);
                  cp.patchOwner(this);
                  cp.check(i).getErrors().forEach(function (x) {
                      var rs = new Status(Status.WARNING, x.getCode(), x.getMessage(), _this);
                      setValidationPath(rs, x.getValidationPath());
                      result.addSubStatus(rs);
                  });
              }
          }
          finally {
              exports.autoCloseFlag = g;
              exports.VALIDATED_TYPE = prevValidated;
          }
          return result;
      };
      AbstractType.prototype.validate = function (i, autoClose, nullAllowed) {
          if (autoClose === void 0) { autoClose = false; }
          if (nullAllowed === void 0) { nullAllowed = true; }
          var g = exports.autoCloseFlag;
          if (!nullAllowed && (i === null || i === undefined)) {
              if (!this.nullable) {
                  return error(exports.messageRegistry.NULL_NOT_ALLOWED, this);
              }
          }
          if (autoClose) {
              exports.autoCloseFlag = true;
          }
          try {
              // for( var subType of this.subTypes()){
              //     var vr = subType.validateDirect(i,autoClose||g);
              //     if(vr.isOk()){
              //         return vr;
              //     }
              // }
              // return this.validateDirect(i, autoClose||g);
              var statuses = [];
              var global = _.find([this].concat(this.allSuperTypes()), function (x) { return x.getExtra(exports.GLOBAL); });
              var queue = this.allSubTypes().concat(this);
              if (global && global != this) {
                  queue = queue.concat(global.allSubTypes());
                  queue.push(global);
              }
              var lastStatus;
              for (var _i = 0, queue_1 = queue; _i < queue_1.length; _i++) {
                  var subType = queue_1[_i];
                  var dStatus = checkDescriminator(i, subType);
                  var vr = subType.validateDirect(i, autoClose || g);
                  if (dStatus) {
                      if (dStatus.isOk()) {
                          return vr;
                      }
                      else {
                          statuses.push(dStatus);
                      }
                  }
                  else if (vr.isOk()) {
                      return vr;
                  }
                  lastStatus = vr;
              }
              if (statuses.length == 0) {
                  return lastStatus;
              }
              var result = ok();
              statuses.forEach(function (x) { return result.addSubStatus(x); });
              return statuses.pop(); //result;
          }
          finally {
              exports.autoCloseFlag = g;
          }
      };
      /**
       * declares a pattern property on this type,
       * note if type is not inherited from an object type this will move
       * type to inconsistent state
       * @param name - regexp
       * @param type - type of the property
       * @return
       */
      AbstractType.prototype.declareMapProperty = function (name, type) {
          if (type != null) {
              this.addMeta(new restr.MapPropertyIs(name, type));
          }
          return type;
      };
      /**
       * make this type closed type (no unknown properties any more)
       */
      AbstractType.prototype.closeUnknownProperties = function () {
          this.addMeta(new restrictions_1.KnownPropertyRestriction(false));
      };
      AbstractType.prototype.annotations = function () {
          return this.metaOfType(metaInfo.Annotation);
      };
      AbstractType.prototype.declaredAnnotations = function () {
          return this.declaredMeta().filter(function (x) { return metaInfo.Annotation.isInstance(x); });
      };
      AbstractType.prototype.scalarsAnnotations = function () {
          return this.sAnnotations(this.meta());
      };
      AbstractType.prototype.declaredScalarsAnnotations = function () {
          return this.sAnnotations(this.declaredFacets());
      };
      AbstractType.prototype.sAnnotations = function (facets) {
          facets = facets.filter(function (x) {
              return x.kind() != tsInterfaces.MetaInformationKind.FacetDeclaration
                  && x.kind() != tsInterfaces.MetaInformationKind.Example
                  && x.kind() != tsInterfaces.MetaInformationKind.Examples
                  && x.facetName() != "propertyIs";
          });
          var result = {};
          var _loop_1 = function (f) {
              var annotations = f.annotations();
              if (!annotations || !annotations.length) {
                  return "continue";
              }
              result[f.facetName()] = [annotations.map(function (x) {
                      var a = new metaInfo.Annotation(x.name(), x.value(), x.getPath());
                      a.setOwnerFacet(f);
                      return a;
                  })];
          };
          for (var _i = 0, facets_1 = facets; _i < facets_1.length; _i++) {
              var f = facets_1[_i];
              _loop_1(f);
          }
          if (this.supertypeAnnotations && this.supertypeAnnotations.length) {
              result['type'] = this.supertypeAnnotations.map(function (x) {
                  return Object.keys(x).map(function (y) { return new metaInfo.Annotation(x[y].name(), x[y].value(), x[y].getPath()); });
              });
          }
          return result;
      };
      AbstractType.prototype.componentType = function () {
          var components = this.metaOfType(restrictions_3.ComponentShouldBeOfType);
          if (components.length == 0) {
              return null;
          }
          else if (components.length == 1) {
              return components[0].value();
          }
          else {
              var componentTypes = components.map(function (x) { return x.value(); });
              var componentTypes1 = [].concat(componentTypes);
              var _loop_2 = function (x) {
                  var toRemove = [];
                  for (var _i = 0, componentTypes_1 = componentTypes; _i < componentTypes_1.length; _i++) {
                      var y = componentTypes_1[_i];
                      if (x == y) {
                          continue;
                      }
                      if (y.isAssignableFrom(x)) {
                          toRemove.push(y);
                      }
                  }
                  componentTypes = componentTypes.filter(function (y) { return toRemove.indexOf(y) < 0; });
              };
              for (var _i = 0, componentTypes1_1 = componentTypes1; _i < componentTypes1_1.length; _i++) {
                  var x = componentTypes1_1[_i];
                  _loop_2(x);
              }
              var ct = derive(null, componentTypes);
              return ct;
          }
      };
      AbstractType.prototype.canDoAc = function () {
          var tf = _.uniq(this.typeFamily());
          var s = new Status(Status.OK, "", "", this);
          for (var i = 0; i < tf.length; i++) {
              for (var j = 0; j < tf.length; j++) {
                  if (i != j) {
                      var t0 = tf[i];
                      var t1 = tf[j];
                      var ed = this.emptyIntersectionOrDiscriminator(t0, t1);
                      s.addSubStatus(ed);
                  }
              }
          }
          return s;
      };
      AbstractType.prototype.emptyIntersectionOrDiscriminator = function (t0, t1) {
          if (t1 === t0) {
              return ok();
          }
          if (t1.isScalar() && t0.isScalar()) {
              return ok();
          }
          var it = intersect("", [t0, t1]);
          var innerCheckConfluent = it.checkConfluent();
          if (innerCheckConfluent.isOk()) {
              return this.checkDiscriminator(t0, t1);
          }
          return ok();
      };
      AbstractType.prototype.properties = function () {
          if (this.propertyInfos == null) {
              this.propertiesMap = {};
              this.propertyInfos = [];
              var meta = this.meta();
              for (var _i = 0, meta_1 = meta; _i < meta_1.length; _i++) {
                  var m = meta_1[_i];
                  if (restr.MatchesProperty.isInstance(m)) {
                      var p = new PropertyInfo(m);
                      var name_1 = p.name();
                      if (!this.propertiesMap[name_1]) {
                          this.propertiesMap[name_1] = p;
                      }
                      this.propertyInfos.push(p);
                  }
              }
          }
          return this.propertyInfos;
      };
      AbstractType.prototype.declaredProperties = function () {
          var _this = this;
          return this.properties().filter(function (x) { return x.declaredAt() == _this; });
      };
      AbstractType.prototype.allDefinedFacets = function () {
          if (this.definedFacetInfos == null) {
              this.definedFacetInfosMap = {};
              this.definedFacetInfos = [];
              var m = this.meta();
              for (var _i = 0, m_1 = m; _i < m_1.length; _i++) {
                  var f = m_1[_i];
                  if (metaInfo.FacetDeclaration.isInstance(f) && !f.isBuiltIn()) {
                      var p = new PropertyInfo(f);
                      if (!this.definedFacetInfosMap[f.facetName()]) {
                          this.definedFacetInfosMap[p.name()] = p;
                      }
                      this.definedFacetInfos.push(p);
                  }
              }
          }
          return this.definedFacetInfos;
      };
      AbstractType.prototype.definedFacets = function () {
          var _this = this;
          return this.allDefinedFacets().filter(function (x) { return x.declaredAt() == _this; });
      };
      AbstractType.prototype.property = function (name) {
          if (!this.propertyInfos) {
              this.properties();
          }
          return this.propertiesMap[name];
      };
      AbstractType.prototype.checkDiscriminator = function (t1, t2) {
          var found = error(exports.messageRegistry.DISCRIMINATOR_NEEDED, this, { name1: t1.name(), name2: t2.name() });
          var oneMeta = t1.oneMeta(metaInfo.Discriminator);
          var anotherMeta = t2.oneMeta(metaInfo.Discriminator);
          if (oneMeta != null && anotherMeta != null && oneMeta.value() === (anotherMeta.value())) {
              var d1 = t1.name();
              var d2 = t2.name();
              var dv1 = t1.oneMeta(metaInfo.DiscriminatorValue);
              if (dv1 != null) {
                  d1 = dv1.value();
              }
              var dv2 = t2.oneMeta(metaInfo.DiscriminatorValue);
              if (dv2 != null) {
                  d2 = dv2.value();
              }
              if (d1 !== d2) {
                  return ok();
              }
              found = error(exports.messageRegistry.SAME_DISCRIMINATOR_VALUE, this, { name1: t1.name(), name2: t2.name() });
          }
          return found;
      };
      /**
       * performs automatic classification of the instance
       * @param obj
       * @returns {AbstractType}
       */
      AbstractType.prototype.ac = function (obj) {
          if (!this.isPolymorphic() && !this.isUnion()) {
              return this;
          }
          if (this.isBuiltin()) {
              return this;
          }
          var tf = _.uniq(this.typeFamily());
          if (tf.length == 0) {
              return exports.NOTHING;
          }
          if (this.isScalar()) {
              if (this.isNumber()) {
                  if (typeof obj == "number") {
                      return this;
                  }
                  return exports.NOTHING;
              }
              if (this.isString()) {
                  if (typeof obj == "string") {
                      return this;
                  }
                  return exports.NOTHING;
              }
              if (this.isBoolean()) {
                  if (typeof obj == "boolean") {
                      return this;
                  }
                  return exports.NOTHING;
              }
              return this;
          }
          if (tf.length === 1) {
              return tf[0];
          }
          var options = [];
          tf.forEach(function (x) {
              var ds = x.validateDirect(obj, true);
              if (ds.isOk()) {
                  options.push(x);
              }
          });
          var t = this.discriminate(obj, options);
          if (!t) {
              return exports.NOTHING;
          }
          return t;
      };
      /**
       * adds new property declaration to this type, note if type is not inherited from an object type this will move
       * type to inconsistent state
       * @param name - name of the property
       * @param type - type of the property
       * @param optional true if property is optinal
       * @return the type with property (this)
       */
      AbstractType.prototype.declareProperty = function (name, t, optional) {
          if (!optional) {
              this.addMeta(new restr.HasProperty(name));
          }
          if (t != null) {
              this.addMeta(new restr.PropertyIs(name, t));
          }
          return this;
      };
      AbstractType.prototype.discriminate = function (obj, opt) {
          var newOpts = [].concat(opt);
          var opts = [].concat(opt);
          while (newOpts.length > 1) {
              var found = false;
              l2: for (var i = 0; i < opts.length; i++) {
                  for (var j = 0; j < opts.length; j++) {
                      var t0 = opts[i];
                      var t1 = opts[j];
                      if (t0 != t1) {
                          var nt = select(obj, t0, t1);
                          if (nt === t0) {
                              opts = opts.filter(function (x) { return x != t1; });
                              found = true;
                              break l2;
                          }
                          else if (nt === t1) {
                              opts = opts.filter(function (x) { return x != t0; });
                              found = true;
                              break l2;
                          }
                          else {
                              opts = opts.filter(function (x) { return x != t0 && x != t1; });
                              found = true;
                              break l2;
                          }
                      }
                  }
              }
              newOpts = opts;
          }
          if (newOpts.length == 1) {
              return newOpts[0];
          }
          return null;
      };
      /**
       * return instance of type information of particular class
       * @param clazz
       * @returns {any}
       */
      AbstractType.prototype.oneMeta = function (clazz) {
          return _.find(this.meta(), function (x) { return x instanceof clazz; });
      };
      /**
       * return all instances of meta information of particular class
       * @param clazz
       * @returns {any}
       */
      AbstractType.prototype.metaOfType = function (clazz) {
          return this.meta().filter(function (x) { return x instanceof clazz; });
      };
      AbstractType.prototype.declaredMeta = function () {
          return this.metaInfo;
      };
      AbstractType.prototype.descValue = function () {
          var dv = this.oneMeta(metaInfo.DiscriminatorValue);
          if (dv) {
              return dv.value();
          }
          return this.name();
      };
      AbstractType.prototype.isAbstractOrInternal = function () {
          return this.metaInfo.some(function (x) { return x instanceof Abstract || x instanceof Internal; });
      };
      AbstractType.prototype.typeFamily = function () {
          if (this.isUnion()) {
              var res = [];
              this.allSuperTypes().forEach(function (x) {
                  if (x instanceof UnionType) {
                      var opts = x.allOptions();
                      for (var i = 0; i < opts.length; i++) {
                          res = res.concat(opts[i].typeFamily());
                      }
                  }
              });
              return _.unique(res);
          }
          var rs = [];
          if (!this.isAbstractOrInternal()) {
              rs.push(this);
          }
          this.allSubTypes().forEach(function (x) {
              if (!x.isAbstractOrInternal()) {
                  rs.push(x);
              }
          });
          return _.unique(rs);
      };
      AbstractType.prototype.hasPropertiesFacet = function () {
          return this.metaInfo.some(function (x) { return x instanceof metaInfo.HasPropertiesFacet; });
      };
      AbstractType.prototype.sourceMap = function () {
          return null;
      };
      AbstractType.CLASS_IDENTIFIER_AbstractType = "typesystem.AbstractType";
      return AbstractType;
  }());
  exports.AbstractType = AbstractType;
  var Modifier = /** @class */ (function (_super) {
      __extends(Modifier, _super);
      function Modifier() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      Modifier.prototype.requiredType = function () {
          return exports.ANY;
      };
      Modifier.prototype.kind = function () {
          return tsInterfaces.MetaInformationKind.Modifier;
      };
      return Modifier;
  }(TypeInformation));
  exports.Modifier = Modifier;
  var Polymorphic = /** @class */ (function (_super) {
      __extends(Polymorphic, _super);
      function Polymorphic() {
          return _super.call(this, true) || this;
      }
      Polymorphic.prototype.facetName = function () {
          return "polymorphic";
      };
      Polymorphic.prototype.value = function () {
          return true;
      };
      return Polymorphic;
  }(Modifier));
  exports.Polymorphic = Polymorphic;
  var Abstract = /** @class */ (function (_super) {
      __extends(Abstract, _super);
      function Abstract() {
          return _super.call(this, false) || this;
      }
      Abstract.prototype.value = function () {
          return true;
      };
      Abstract.prototype.facetName = function () {
          return "abstract";
      };
      return Abstract;
  }(Modifier));
  exports.Abstract = Abstract;
  var Internal = /** @class */ (function (_super) {
      __extends(Internal, _super);
      function Internal() {
          return _super.call(this, false) || this;
      }
      Internal.prototype.facetName = function () {
          return "abstract";
      };
      Internal.prototype.value = function () {
          return true;
      };
      return Internal;
  }(Modifier));
  exports.Internal = Internal;
  var BuiltIn = /** @class */ (function (_super) {
      __extends(BuiltIn, _super);
      function BuiltIn() {
          return _super.call(this, false) || this;
      }
      BuiltIn.prototype.facetName = function () {
          return "builtIn";
      };
      BuiltIn.prototype.value = function () {
          return true;
      };
      return BuiltIn;
  }(Modifier));
  var BUILT_IN = new BuiltIn();
  var RootType = /** @class */ (function (_super) {
      __extends(RootType, _super);
      function RootType() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      RootType.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(RootType.CLASS_IDENTIFIER_RootType);
      };
      RootType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), RootType.CLASS_IDENTIFIER_RootType);
      };
      RootType.prototype.kind = function () {
          return "root";
      };
      RootType.prototype.clone = function () {
          return this;
      };
      RootType.CLASS_IDENTIFIER_RootType = "typesystem.RootType";
      return RootType;
  }(AbstractType));
  exports.RootType = RootType;
  var InheritedType = /** @class */ (function (_super) {
      __extends(InheritedType, _super);
      function InheritedType() {
          var _this = _super !== null && _super.apply(this, arguments) || this;
          _this._superTypes = [];
          return _this;
      }
      InheritedType.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(InheritedType.CLASS_IDENTIFIER_InheritedType);
      };
      InheritedType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), InheritedType.CLASS_IDENTIFIER_InheritedType);
      };
      InheritedType.prototype.superTypes = function () {
          return this._superTypes;
      };
      InheritedType.prototype.clone = function () {
          if (this.isBuiltin()) {
              return this;
          }
          var v = new InheritedType(this._name);
          v._superTypes = this._superTypes;
          return v;
      };
      InheritedType.prototype.knownProperties = function () {
          var vs = this.metaOfType(restrictions_4.MatchesProperty);
          this.superTypes().forEach(function (x) {
              vs = vs.concat(x.knownProperties());
          });
          return vs;
      };
      InheritedType.prototype.kind = function () {
          return "inherited";
      };
      InheritedType.prototype.meta = function () {
          var _this = this;
          var rs = _super.prototype.meta.call(this);
          var hasKp = false;
          this.superTypes().forEach(function (x) {
              x.meta().forEach(function (m) {
                  if (m instanceof restrictions_1.KnownPropertyRestriction) {
                      if (hasKp) {
                          return;
                      }
                      var kp = new restrictions_1.KnownPropertyRestriction(false);
                      kp.patchOwner(_this);
                      rs.push(kp);
                      return;
                  }
                  if (m.isInheritable()) {
                      rs.push(m);
                  }
              });
          });
          return rs;
      };
      InheritedType.prototype.addSuper = function (t) {
          this._superTypes.push(t);
          if (!t.isLocked()) {
              t._subTypes.push(this);
          }
          if (t.nullable) {
              this.nullable = true;
          }
      };
      InheritedType.prototype.label = function () {
          var cmp = this.metaOfType(restrictions_3.ComponentShouldBeOfType);
          if (cmp.length > 0) {
              return cmp[0].value().label() + "[]";
          }
          return _super.prototype.label.call(this);
      };
      InheritedType.prototype.contextMeta = function () {
          return this._contextMeta;
      };
      InheritedType.prototype.setContextMeta = function (contextMeta) {
          this._contextMeta = contextMeta;
      };
      InheritedType.prototype.patch = function (another) {
          var _this = this;
          for (var prop in another) {
              if (another.hasOwnProperty(prop)) {
                  this[prop] = another[prop];
              }
          }
          this.metaInfo.filter(function (m) { return m._owner === another; }).forEach(function (m) { return m._owner = _this; });
          for (var i = 0; i < this._superTypes.length; i++) {
              var st = this._superTypes[i];
              if (st == this || st.allSuperTypes().indexOf(this) >= 0) {
                  this._superTypes[i] = exports.RECURRENT;
              }
          }
      };
      InheritedType.CLASS_IDENTIFIER_InheritedType = "typesystem.InheritedType";
      return InheritedType;
  }(AbstractType));
  exports.InheritedType = InheritedType;
  var DerivedType = /** @class */ (function (_super) {
      __extends(DerivedType, _super);
      function DerivedType(name, _options) {
          var _this = _super.call(this, name) || this;
          _this._options = _options;
          return _this;
      }
      DerivedType.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(DerivedType.CLASS_IDENTIFIER_DerivedType);
      };
      DerivedType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), DerivedType.CLASS_IDENTIFIER_DerivedType);
      };
      DerivedType.prototype.cloneWithFilter = function (x, f) {
          var c = this.clone();
          var ms = [];
          if (f) {
              c._options = this.options().map(function (t) { return f(t); });
          }
          this.metaInfo.forEach(function (f) {
              var rs = x(f, c);
              if (typeof rs == "boolean") {
                  if (rs) {
                      ms.push(f);
                  }
              }
              else {
                  if (rs) {
                      ms.push(rs);
                  }
              }
          });
          c.metaInfo = ms;
          return c;
      };
      /**
       *
       * @returns all possible options
       */
      DerivedType.prototype.allOptions = function () {
          var _this = this;
          var rs = [];
          this._options.forEach(function (x) {
              if (x.kind() == _this.kind()) {
                  rs = rs.concat(x.allOptions());
              }
              else {
                  rs.push(x);
              }
          });
          return _.unique(rs);
      };
      DerivedType.prototype.options = function () {
          return this._options;
      };
      DerivedType.CLASS_IDENTIFIER_DerivedType = "typesystem.DerivedType";
      return DerivedType;
  }(AbstractType));
  exports.DerivedType = DerivedType;
  var UnionType = /** @class */ (function (_super) {
      __extends(UnionType, _super);
      function UnionType(name, _options) {
          var _this = _super.call(this, name, _options) || this;
          _this.options().forEach(function (x) {
              if (x.nullable) {
                  _this.nullable = true;
              }
          });
          return _this;
      }
      UnionType.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(UnionType.CLASS_IDENTIFIER_UnionType);
      };
      UnionType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), UnionType.CLASS_IDENTIFIER_UnionType);
      };
      UnionType.prototype.kind = function () {
          return "union";
      };
      UnionType.prototype.clone = function () {
          return new UnionType(this.name(), this.options());
      };
      UnionType.prototype.isSubTypeOf = function (t) {
          var isSubType = true;
          this.allOptions().forEach(function (x) {
              if (!x.isSubTypeOf(t)) {
                  isSubType = false;
              }
          });
          return isSubType;
          //return t===ANY||this===t|| this.superTypes().some(x=>x.isSubTypeOf(t));
      };
      UnionType.prototype.validate = function (i) {
          return this.validateDirect(i);
      };
      UnionType.prototype.typeFamily = function () {
          var res = [];
          this.allOptions().forEach(function (x) {
              res = res.concat(x.typeFamily());
          });
          return res;
      };
      UnionType.prototype.knownProperties = function () {
          var vs = this.metaOfType(restrictions_4.MatchesProperty);
          this.options().forEach(function (x) {
              vs = vs.concat(x.knownProperties());
          });
          return vs;
      };
      UnionType.prototype.validateDirect = function (i, autoClose) {
          if (autoClose === void 0) { autoClose = false; }
          var result = new Status(Status.OK, "", "", this);
          this.restrictions().forEach(function (x) { return result.addSubStatus(x.check(i, null)); });
          return result;
      };
      UnionType.prototype.isUnion = function () {
          return true;
      };
      UnionType.prototype.isObject = function () {
          return _.all(this.allOptions(), function (x) { return x.isObject(); });
      };
      UnionType.prototype.restrictions = function () {
          return [new OrRestriction(this.allOptions().map(function (x) { return new AndRestriction(x.restrictions()); }), exports.messageRegistry.UNION_TYPE_FAILURE, exports.messageRegistry.UNION_TYPE_FAILURE_DETAILS)];
      };
      UnionType.prototype.label = function () {
          return this.options().map(function (x) { return x.label(); }).join("|");
      };
      UnionType.CLASS_IDENTIFIER_UnionType = "typesystem.UnionType";
      return UnionType;
  }(DerivedType));
  exports.UnionType = UnionType;
  var IntersectionType = /** @class */ (function (_super) {
      __extends(IntersectionType, _super);
      function IntersectionType() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      IntersectionType.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(IntersectionType.CLASS_IDENTIFIER_IntersectionType);
      };
      IntersectionType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), IntersectionType.CLASS_IDENTIFIER_IntersectionType);
      };
      IntersectionType.prototype.kind = function () {
          return "intersection";
      };
      IntersectionType.prototype.clone = function () {
          return new IntersectionType(this.name(), this.options());
      };
      IntersectionType.prototype.restrictions = function () {
          var rs = [];
          this.allOptions().forEach(function (x) {
              if (!x.oneMeta(metaInfo.SkipValidation)) {
                  rs = rs.concat(x.restrictions());
              }
          });
          return [new AndRestriction(rs)];
      };
      IntersectionType.prototype.label = function () {
          return this.options().map(function (x) { return x.label(); }).join("&");
      };
      IntersectionType.prototype.isIntersection = function () {
          return true;
      };
      IntersectionType.CLASS_IDENTIFIER_IntersectionType = "typesystem.IntersectionType";
      return IntersectionType;
  }(DerivedType));
  exports.IntersectionType = IntersectionType;
  var registry = new TypeRegistry();
  function builtInRegistry() {
      return registry;
  }
  exports.builtInRegistry = builtInRegistry;
  function union(name, t) {
      return new UnionType(name, t);
  }
  exports.union = union;
  function intersect(name, t) {
      return new IntersectionType(name, t);
  }
  exports.intersect = intersect;
  /**
   * allows you to extend a type from other types
   * @param name
   * @param t
   * @returns {InheritedType}
   */
  function derive(name, t) {
      var r = new InheritedType(name);
      t.forEach(function (x) { return r.addSuper(x); });
      if (r.isSubTypeOf(exports.NIL)) {
          r.nullable = true;
      }
      else if (t.length == 1 && t[0] == exports.ANY) {
          r.nullable = true;
      }
      return r;
  }
  exports.derive = derive;
  /**
   * this function allows you to quickly derive a new type from object;
   * @param name
   * @returns {InheritedType}
   */
  function deriveObjectType(name) {
      return derive(name, [exports.OBJECT]);
  }
  exports.deriveObjectType = deriveObjectType;
  function select(obj, t0, t1) {
      if (t0.isScalar() && t1.isScalar()) {
          if (t0.allSubTypes().indexOf(t1) != -1) {
              return t0;
          }
          if (t1.allSubTypes().indexOf(t0) != -1) {
              return t1;
          }
      }
      var d0 = t0.oneMeta(metaInfo.Discriminator);
      var d1 = t1.oneMeta(metaInfo.Discriminator);
      if (d0 && d1) {
          if (d0.property === d1.property) {
              var v0 = t0.descValue();
              var v1 = t1.descValue();
              if (v0 !== v1) {
                  var val = obj[d0.property];
                  if (val === v0) {
                      return t0;
                  }
                  if (val === v1) {
                      return t1;
                  }
              }
          }
      }
      return null;
  }
  var NothingRestriction = /** @class */ (function (_super) {
      __extends(NothingRestriction, _super);
      function NothingRestriction() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      NothingRestriction.prototype.check = function (i) {
          if (i === null || i === undefined) {
              return ok();
          }
          return error(exports.messageRegistry.NOTHING, this);
      };
      NothingRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      NothingRestriction.prototype.facetName = function () {
          return "nothing";
      };
      NothingRestriction.prototype.value = function () {
          return "!!!";
      };
      return NothingRestriction;
  }(Constraint));
  exports.NothingRestriction = NothingRestriction;
  var RestrictionStackEntry = /** @class */ (function () {
      function RestrictionStackEntry(_previous, _restriction, id) {
          this._previous = _previous;
          this._restriction = _restriction;
          this.id = id;
      }
      RestrictionStackEntry.prototype.getRestriction = function () { return this._restriction; };
      RestrictionStackEntry.prototype.pop = function () { return this._previous; };
      RestrictionStackEntry.prototype.push = function (r) {
          return new RestrictionStackEntry(this, r, r.toString());
      };
      return RestrictionStackEntry;
  }());
  exports.RestrictionStackEntry = RestrictionStackEntry;
  var NothingRestrictionWithLocation = /** @class */ (function (_super) {
      __extends(NothingRestrictionWithLocation, _super);
      function NothingRestrictionWithLocation(_entry, _message, _another) {
          var _this = _super.call(this) || this;
          _this._entry = _entry;
          _this._message = _message;
          _this._another = _another;
          return _this;
      }
      NothingRestrictionWithLocation.prototype.getMessage = function () { return this._message; };
      NothingRestrictionWithLocation.prototype.getStack = function () { return this._entry; };
      NothingRestrictionWithLocation.prototype.another = function () { return this._another; };
      return NothingRestrictionWithLocation;
  }(NothingRestriction));
  exports.NothingRestrictionWithLocation = NothingRestrictionWithLocation;
  var GenericTypeOf = /** @class */ (function (_super) {
      __extends(GenericTypeOf, _super);
      function GenericTypeOf() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      GenericTypeOf.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(GenericTypeOf.CLASS_IDENTIFIER_GenericTypeOf);
      };
      GenericTypeOf.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), GenericTypeOf.CLASS_IDENTIFIER_GenericTypeOf);
      };
      GenericTypeOf.CLASS_IDENTIFIER_GenericTypeOf = "typesystem.GenericTypeOf";
      return GenericTypeOf;
  }(Constraint));
  exports.GenericTypeOf = GenericTypeOf;
  var TypeOfRestriction = /** @class */ (function (_super) {
      __extends(TypeOfRestriction, _super);
      function TypeOfRestriction(val) {
          var _this = _super.call(this) || this;
          _this.val = val;
          return _this;
      }
      TypeOfRestriction.prototype.check = function (i) {
          var to = typeof i;
          if (i === null || i === undefined) {
              return ok();
          }
          if (Array.isArray(i)) {
              to = "array";
          }
          if (to === this.val) {
              return ok();
          }
          return error(exports.messageRegistry.TYPE_EXPECTED, this, {
              expectedType: this.val,
              actualType: to
          });
      };
      TypeOfRestriction.prototype.value = function () {
          return this.val;
      };
      TypeOfRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      TypeOfRestriction.prototype.facetName = function () {
          return "typeOf";
      };
      TypeOfRestriction.prototype.composeWith = function (r) {
          if (r instanceof TypeOfRestriction) {
              var to = r;
              if (to.val == this.val) {
                  return this;
              }
              return this.nothing(r);
          }
          return null;
      };
      TypeOfRestriction.prototype.toString = function () {
          return "should be of type " + this.val;
      };
      return TypeOfRestriction;
  }(GenericTypeOf));
  exports.TypeOfRestriction = TypeOfRestriction;
  function is_int(value) {
      if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) {
          return true;
      }
      else {
          return false;
      }
  }
  var IntegerRestriction = /** @class */ (function (_super) {
      __extends(IntegerRestriction, _super);
      function IntegerRestriction() {
          return _super.call(this) || this;
      }
      IntegerRestriction.prototype.check = function (i) {
          if (typeof i == "number" && is_int(i)) {
              return ok();
          }
          return error(exports.messageRegistry.INTEGER_EXPECTED, this);
      };
      IntegerRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      IntegerRestriction.prototype.value = function () {
          return true;
      };
      IntegerRestriction.prototype.facetName = function () {
          return "should be integer";
      };
      return IntegerRestriction;
  }(GenericTypeOf));
  exports.IntegerRestriction = IntegerRestriction;
  var NullRestriction = /** @class */ (function (_super) {
      __extends(NullRestriction, _super);
      function NullRestriction() {
          return _super.call(this, "nil") || this;
      }
      NullRestriction.prototype.check = function (i) {
          if (i === null || i == undefined || i === "null") {
              return ok();
          }
          return error(exports.messageRegistry.NULL_EXPECTED, this);
      };
      NullRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      NullRestriction.prototype.facetName = function () {
          return "should be nil";
      };
      return NullRestriction;
  }(TypeOfRestriction));
  exports.NullRestriction = NullRestriction;
  var ScalarRestriction = /** @class */ (function (_super) {
      __extends(ScalarRestriction, _super);
      function ScalarRestriction() {
          return _super.call(this) || this;
      }
      ScalarRestriction.prototype.check = function (i) {
          if (!i) {
              return ok();
          }
          if (typeof i === 'number' || typeof i === 'boolean' || typeof i === 'string') {
              return ok();
          }
          return error(exports.messageRegistry.SCALAR_EXPECTED, this);
      };
      ScalarRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      ScalarRestriction.prototype.facetName = function () {
          return exports.messageRegistry.SHOULD_BE_SCALAR.message;
      };
      ScalarRestriction.prototype.value = function () {
          return true;
      };
      return ScalarRestriction;
  }(GenericTypeOf));
  exports.ScalarRestriction = ScalarRestriction;
  var OrRestriction = /** @class */ (function (_super) {
      __extends(OrRestriction, _super);
      function OrRestriction(val, _extraMessage, _extraOptionMessage) {
          var _this = _super.call(this) || this;
          _this.val = val;
          _this._extraMessage = _extraMessage;
          _this._extraOptionMessage = _extraOptionMessage;
          return _this;
      }
      OrRestriction.prototype.check = function (i, p) {
          var _this = this;
          var cs = new Status(Status.OK, "", "", this);
          var results = [];
          for (var j = 0; j < this.val.length; j++) {
              var m = this.val[j].check(i, p);
              if (m.isOk()) {
                  return ok();
              }
              results.push(m);
          }
          if (results.length > 0) {
              for (var _i = 0, results_1 = results; _i < results_1.length; _i++) {
                  var r = results_1[_i];
                  var ownerName = null;
                  var src = r.getSource();
                  if (src instanceof TypeInformation) {
                      var owner = src.owner();
                      if (owner) {
                          ownerName = owner.label();
                      }
                  }
                  r.getErrors().forEach(function (x) {
                      var msg = x.getMessage();
                      var code = x.getCode();
                      if (ownerName) {
                          msg = ownerName + ": " + msg;
                      }
                      if (_this._extraOptionMessage) {
                          var st = error(_this._extraOptionMessage, _this, { msg: msg });
                          msg = st.getMessage();
                          code = st.getCode();
                      }
                      x.setMessage(msg);
                      x.setCode(code);
                      cs.addSubStatus(x);
                  });
              }
              if (this._extraMessage) {
                  var severity = 0;
                  results.forEach(function (x) { return severity = Math.max(severity, x.getSeverity()); });
                  cs.addSubStatus(new Status(severity, this._extraMessage.code, this._extraMessage.message, this));
              }
          }
          return cs;
      };
      OrRestriction.prototype.value = function () {
          return this.val.map(function (x) { return x.value(); });
      };
      OrRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      OrRestriction.prototype.facetName = function () {
          return "or";
      };
      return OrRestriction;
  }(Constraint));
  exports.OrRestriction = OrRestriction;
  var AndRestriction = /** @class */ (function (_super) {
      __extends(AndRestriction, _super);
      function AndRestriction(val) {
          var _this = _super.call(this) || this;
          _this.val = val;
          return _this;
      }
      AndRestriction.prototype.value = function () {
          return this.val.map(function (x) { return x.value(); });
      };
      AndRestriction.prototype.options = function () {
          return this.val;
      };
      AndRestriction.prototype.check = function (i, p) {
          for (var j = 0; j < this.val.length; j++) {
              var st = this.val[j].check(i, p);
              if (!st.isOk()) {
                  return st;
              }
          }
          return ok();
      };
      AndRestriction.prototype.requiredType = function () {
          return exports.ANY;
      };
      AndRestriction.prototype.facetName = function () {
          return "and";
      };
      return AndRestriction;
  }(Constraint));
  exports.AndRestriction = AndRestriction;
  /***
   *
   * lets declare built in types
   */
  exports.ANY = new RootType("any");
  exports.SCALAR = exports.ANY.inherit("scalar");
  exports.OBJECT = exports.ANY.inherit("object");
  //export const POLYMORPHIC=OBJECT.inherit("polymorphic");
  exports.ARRAY = exports.ANY.inherit("array");
  exports.EXTERNAL = exports.ANY.inherit("external");
  exports.NUMBER = exports.SCALAR.inherit("number");
  exports.INTEGER = exports.NUMBER.inherit("integer");
  exports.BOOLEAN = exports.SCALAR.inherit("boolean");
  exports.STRING = exports.SCALAR.inherit("string");
  exports.NIL = exports.SCALAR.inherit("nil");
  //export const DATE=SCALAR.inherit("date");
  exports.DATE_ONLY = exports.SCALAR.inherit("date-only");
  exports.TIME_ONLY = exports.SCALAR.inherit("time-only");
  exports.DATETIME_ONLY = exports.SCALAR.inherit("datetime-only");
  exports.DATETIME = exports.SCALAR.inherit("datetime");
  exports.FILE = exports.SCALAR.inherit("file");
  exports.NOTHING = new RootType("nothing");
  exports.UNION = exports.ANY.inherit("union");
  exports.UNKNOWN = exports.NOTHING.inherit("unknown");
  exports.REFERENCE = exports.NOTHING.inherit("reference");
  exports.RECURRENT = exports.NOTHING.inherit("recurrent");
  ///
  //POLYMORPHIC.addMeta(new Polymorphic())
  exports.ANY.addMeta(BUILT_IN);
  exports.NIL.addMeta(BUILT_IN);
  exports.UNION.addMeta(BUILT_IN);
  exports.SCALAR.addMeta(BUILT_IN);
  exports.OBJECT.addMeta(BUILT_IN);
  exports.ARRAY.addMeta(BUILT_IN);
  exports.NUMBER.addMeta(BUILT_IN);
  exports.INTEGER.addMeta(BUILT_IN);
  exports.BOOLEAN.addMeta(BUILT_IN);
  exports.STRING.addMeta(BUILT_IN);
  exports.EXTERNAL.addMeta(BUILT_IN);
  exports.UNKNOWN.addMeta(BUILT_IN);
  exports.RECURRENT.addMeta(BUILT_IN);
  exports.DATE_ONLY.addMeta(BUILT_IN);
  exports.TIME_ONLY.addMeta(BUILT_IN);
  exports.DATETIME_ONLY.addMeta(BUILT_IN);
  exports.DATETIME.addMeta(BUILT_IN);
  exports.FILE.addMeta(BUILT_IN);
  //POLYMORPHIC.addMeta(BUILT_IN);
  exports.UNKNOWN.addMeta(BUILT_IN);
  exports.UNKNOWN.lock();
  exports.RECURRENT.addMeta(BUILT_IN);
  exports.RECURRENT.lock();
  exports.EXTERNAL.lock();
  exports.UNION.lock();
  exports.REFERENCE.lock();
  ///lets register all types in registry
  registry.addType(exports.ANY);
  registry.addType(exports.SCALAR);
  registry.addType(exports.OBJECT);
  registry.addType(exports.ARRAY);
  registry.addType(exports.NUMBER);
  registry.addType(exports.INTEGER);
  registry.addType(exports.BOOLEAN);
  registry.addType(exports.NIL);
  registry.addType(exports.STRING);
  registry.addType(exports.DATE_ONLY);
  registry.addType(exports.TIME_ONLY);
  registry.addType(exports.DATETIME_ONLY);
  registry.addType(exports.DATETIME);
  registry.addType(exports.FILE);
  //registry.addType(POLYMORPHIC);
  exports.NOTHING.addMeta(new NothingRestriction());
  exports.NUMBER.addMeta(new TypeOfRestriction("number"));
  exports.NUMBER.addMeta(new metainfo_1.FacetDeclaration("format", exports.STRING, true, true));
  exports.BOOLEAN.addMeta(new TypeOfRestriction("boolean"));
  exports.OBJECT.addMeta(new TypeOfRestriction("object"));
  exports.ARRAY.addMeta(new TypeOfRestriction("array"));
  exports.STRING.addMeta(new TypeOfRestriction("string"));
  exports.INTEGER.addMeta(new IntegerRestriction());
  exports.NIL.addMeta(new NullRestriction());
  var dt = require("./datetime");
  exports.DATE_ONLY.addMeta(new dt.DateOnlyR());
  exports.TIME_ONLY.addMeta(new dt.TimeOnlyR());
  exports.DATETIME_ONLY.addMeta(new dt.DateTimeOnlyR());
  exports.DATETIME.addMeta(new dt.DateTimeR());
  exports.FILE.addMeta(new TypeOfRestriction("string"));
  var arrayOfString = exports.ARRAY.inherit("");
  arrayOfString.addMeta(new restrictions_3.ComponentShouldBeOfType(exports.STRING));
  exports.FILE.addMeta(new metainfo_1.FacetDeclaration("fileTypes", arrayOfString, true, true));
  exports.FILE.addMeta(new metainfo_1.FacetDeclaration("minLength", exports.INTEGER, true, true));
  exports.FILE.addMeta(new metainfo_1.FacetDeclaration("maxLength", exports.INTEGER, true, true));
  exports.DATETIME.addMeta(new metainfo_1.FacetDeclaration("format", exports.STRING, true, true));
  exports.NIL.nullable = true;
  exports.SCALAR.addMeta(new ScalarRestriction());
  registry.types().forEach(function (x) { return x.lock(); });
  var ExternalType = /** @class */ (function (_super) {
      __extends(ExternalType, _super);
      function ExternalType(name, _content, json, provider, typeAttributeProvider) {
          if (typeAttributeProvider === void 0) { typeAttributeProvider = null; }
          var _this = _super.call(this, name) || this;
          _this._content = _content;
          _this.json = json;
          _this.provider = provider;
          _this.addMeta(new restr.MatchToSchema(_content, typeAttributeProvider ? typeAttributeProvider : provider));
          _this.addSuper(exports.EXTERNAL);
          return _this;
      }
      ExternalType.prototype.getClassIdentifier = function () {
          var superIdentifiers = _super.prototype.getClassIdentifier.call(this);
          return superIdentifiers.concat(ExternalType.CLASS_IDENTIFIER_ExternalType);
      };
      ExternalType.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), ExternalType.CLASS_IDENTIFIER_ExternalType);
      };
      ExternalType.prototype.getContentProvider = function () {
          return this.provider;
      };
      ExternalType.prototype.setContentProvider = function (provider) {
          this.provider = provider;
      };
      ExternalType.prototype.kind = function () {
          return "external";
      };
      ExternalType.prototype.isJSON = function () {
          return this.json;
      };
      ExternalType.prototype.schema = function () {
          return this._content;
      };
      ExternalType.CLASS_IDENTIFIER_ExternalType = "typesystem.ExternalType";
      return ExternalType;
  }(InheritedType));
  exports.ExternalType = ExternalType;
  function typePath(t) {
      var arr = [];
      while (t != null) {
          if (t.name() == null) {
              if (t instanceof InheritedType) {
                  var contextMeta = t.contextMeta();
                  if (contextMeta != null) {
                      arr.push(contextMeta.path());
                      t = contextMeta._owner;
                  }
                  else {
                      break;
                  }
              }
              else {
                  break;
              }
          }
          else {
              arr.push(t.name());
              break;
          }
      }
      return arr.reverse();
  }
  exports.typePath = typePath;
  function checkDescriminator(i, t, path) {
      var discriminator = t.metaOfType(metaInfo.Discriminator);
      if (discriminator.length != 0) {
          var dName = discriminator[0].value();
          var owner = _.find([t].concat(t.allSuperTypes()), function (x) { return x.getExtra(exports.GLOBAL); });
          if (!owner) {
              return null;
          }
          var dVal = owner.name();
          var discriminatorValue = t.metaOfType(metaInfo.DiscriminatorValue);
          if (discriminatorValue.length != 0) {
              dVal = discriminatorValue[0].value();
          }
          if (dVal) {
              if (i.hasOwnProperty(dName)) {
                  var adVal = i[dName];
                  if (adVal != dVal) {
                      var wrng = error(Status.CODE_INCORRECT_DISCRIMINATOR, this, {
                          rootType: owner.name(),
                          value: adVal,
                          propName: dName
                      }, Status.WARNING);
                      //var wrng = new Status(Status.WARNING, Status.CODE_INCORRECT_DISCRIMINATOR, dVal, this);
                      setValidationPath(wrng, { name: dName, child: path });
                      return wrng;
                  }
                  return ok();
              }
              else {
                  var err = error(Status.CODE_MISSING_DISCRIMINATOR, this, {
                      rootType: owner.name(),
                      propName: dName
                  });
                  //var err = new Status(Status.ERROR, Status.CODE_MISSING_DISCRIMINATOR, dVal, this);
                  setValidationPath(err, path);
                  return err;
              }
          }
      }
      else {
          return null;
      }
  }
  var ValidationError = /** @class */ (function (_super) {
      __extends(ValidationError, _super);
      function ValidationError(messageEntry, parameters) {
          if (parameters === void 0) { parameters = {}; }
          var _this = _super.call(this) || this;
          _this.messageEntry = messageEntry;
          _this.parameters = parameters;
          _this.isWarning = false;
          _this.message = messageText(messageEntry, parameters);
          _this.getClassIdentifier = ValidationError.prototype.getClassIdentifier;
          return _this;
      }
      ValidationError.prototype.getClassIdentifier = function () {
          var superIdentifiers = [];
          return superIdentifiers.concat(ValidationError.CLASS_IDENTIFIER_ValidationError);
      };
      ValidationError.isInstance = function (instance) {
          return instance != null && instance.getClassIdentifier
              && typeof (instance.getClassIdentifier) == "function"
              && _.contains(instance.getClassIdentifier(), ValidationError.CLASS_IDENTIFIER_ValidationError);
      };
      ValidationError.CLASS_IDENTIFIER_ValidationError = "linter.ValidationError";
      return ValidationError;
  }(Error));
  exports.ValidationError = ValidationError;
  function setValidationPath(_s, _c) {
      if (_s.getValidationPath()) {
          var c = patchPath(_c);
          var m = c;
          while (m.child) {
              m = m.child;
          }
          m.child = _s.getValidationPath();
          _s.setValidationPath(c);
      }
      else {
          _s.setValidationPath(_c);
      }
      _s.getSubStatuses().forEach(function (x) {
          setValidationPath(x, _c);
      });
  }
  exports.setValidationPath = setValidationPath;
  function patchPath(p) {
      if (!p) {
          return null;
      }
      else {
          var c = p;
          var r = null;
          var cp = null;
          while (c) {
              if (!r) {
                  r = { name: c.name };
                  cp = r;
                  c = c.child;
                  cp = r;
              }
              else {
                  var news = { name: c.name };
                  cp.child = news;
                  c = c.child;
                  cp = news;
              }
          }
          return r;
      }
  }
  exports.patchPath = patchPath;
  /**
   * A model of annotated RAML type facet
   */
  var AnnotatedFacet = /** @class */ (function () {
      function AnnotatedFacet(_facet, reg) {
          this._facet = _facet;
          this.reg = reg;
      }
      AnnotatedFacet.prototype.kind = function () { return "AnnotatedFacet"; };
      AnnotatedFacet.prototype.annotationsMap = function () {
          var _this = this;
          if (!this._annotationsMap) {
              this._annotationsMap = {};
              this.annotations().forEach(function (x) { return _this._annotationsMap[x.name()] = x; });
          }
          return this._annotationsMap;
      };
      AnnotatedFacet.prototype.annotations = function () {
          var _this = this;
          if (!this._annotations) {
              this._annotations = this._facet.annotations().map(function (x) { return new AnnotationInstance(x, _this.reg); });
          }
          return this._annotations;
      };
      /**
       * Value of the facet serialized to JSON
       */
      AnnotatedFacet.prototype.value = function () { return this._facet.value(); };
      /**
       * Facet name
       */
      AnnotatedFacet.prototype.name = function () { return this._facet.facetName(); };
      /**
       * The facet itself
       */
      AnnotatedFacet.prototype.entry = function () { return this._facet; };
      return AnnotatedFacet;
  }());
  exports.AnnotatedFacet = AnnotatedFacet;
  var parse = require("./parse");
  /**
   * A model of annotated RAML type
   */
  var AnnotatedType = /** @class */ (function () {
      function AnnotatedType(_type, reg) {
          this._type = _type;
          this.reg = reg;
      }
      AnnotatedType.prototype.kind = function () { return "AnnotatedType"; };
      AnnotatedType.prototype.annotationsMap = function () {
          var _this = this;
          if (!this._annotationsMap) {
              this._annotationsMap = {};
              this.annotations().forEach(function (x) {
                  var n = x.name();
                  var ind = n.lastIndexOf(".");
                  if (ind >= 0) {
                      n = n.substring(ind + 1);
                  }
                  _this._annotationsMap[n] = x;
              });
          }
          return this._annotationsMap;
      };
      AnnotatedType.prototype.annotations = function () {
          var _this = this;
          if (!this._annotations) {
              this._annotations = this._type.meta().filter(function (x) {
                  return x.kind() == tsInterfaces.MetaInformationKind.Annotation;
              }).map(function (x) { return new AnnotationInstance(x, _this.reg); });
          }
          return this._annotations;
      };
      /**
       * JSON representation of the type
       */
      AnnotatedType.prototype.value = function () { return parse.storeAsJSON(this._type); };
      /**
       * Type name
       */
      AnnotatedType.prototype.name = function () { return this._type.name(); };
      /**
       * The type itself
       * @returns {IParsedType}
       */
      AnnotatedType.prototype.entry = function () { return this._type; };
      return AnnotatedType;
  }());
  exports.AnnotatedType = AnnotatedType;
  var AnnotationInstance = /** @class */ (function () {
      function AnnotationInstance(actual, reg) {
          this.actual = actual;
      }
      AnnotationInstance.prototype.name = function () {
          return this.actual.facetName();
      };
      /**
       * Annotation value
       */
      AnnotationInstance.prototype.value = function () {
          return this.actual.value();
      };
      /**
       * Annotation definition type
       */
      AnnotationInstance.prototype.definition = function () {
          var tp = registry.get(this.actual.facetName());
          return tp;
      };
      /**
       * Actual annotation model
       */
      AnnotationInstance.prototype.annotation = function () {
          return this.actual;
      };
      return AnnotationInstance;
  }());
  exports.AnnotationInstance = AnnotationInstance;
  /**
   * Apply registered type validation plugins to the type
   * @param t type to be validated
   * @param reg context type registry
   * @param skipOk whether to omit OK issues
   * @returns an array of {tsInterfaces.IStatus}
   */
  function applyAnnotationValidationPlugins(e) {
      var plugins = tsInterfaces.getAnnotationValidationPlugins();
      var result = [];
      for (var _i = 0, plugins_1 = plugins; _i < plugins_1.length; _i++) {
          var tv = plugins_1[_i];
          var issues = tv.process(e);
          if (issues) {
              issues.forEach(function (x) {
                  result.push(toStatus(x, tv.id(), e.entry()));
              });
          }
      }
      return result;
  }
  exports.applyAnnotationValidationPlugins = applyAnnotationValidationPlugins;
  /**
   * Apply registered type validation plugins to the type
   * @param t type to be validated
   * @param reg context type registry
   * @param skipOk whether to omit OK issues
   * @returns an array of {tsInterfaces.IStatus}
   */
  function applyTypeValidationPlugins(t, reg) {
      var plugins = tsInterfaces.getTypeValidationPlugins();
      var result = [];
      for (var _i = 0, plugins_2 = plugins; _i < plugins_2.length; _i++) {
          var tv = plugins_2[_i];
          var issues = tv.process(t, reg);
          if (issues) {
              issues.forEach(function (x) {
                  result.push(toStatus(x, tv.id(), t));
              });
          }
      }
      return result;
  }
  exports.applyTypeValidationPlugins = applyTypeValidationPlugins;
  function toStatus(pvi, pluginId, src) {
      var severity = pvi.isWarning ? Status.WARNING : Status.ERROR;
      var issueCode = pvi.issueCode || pluginId;
      var message = pvi.message || messageText(exports.messageRegistry.PLUGIN_REPORTS_AN_ERROR, { pluginId: pluginId });
      var status = new Status(severity, issueCode, message, src);
      status.setValidationPath(pvi.path);
      return status;
  }
  function toValidationPath(p) {
      if (!p) {
          return null;
      }
      p = p.trim();
      if (p.length == 0) {
          return null;
      }
      if (p.charAt(0) == "#") {
          p = p.substring(1);
      }
      if (p.charAt(0) == "/") {
          p = p.substring(1);
      }
      if (p.length == 0) {
          return null;
      }
      var arr = p.split("/");
      var result = {
          name: arr[0]
      };
      var prev = result;
      for (var i = 1; i < arr.length; i++) {
          var vp = {
              name: arr[i]
          };
          prev.child = vp;
          prev = vp;
      }
      return result;
  }
  exports.toValidationPath = toValidationPath;
  function isUnknown(t) {
      return !t || (t.isSubTypeOf(exports.UNKNOWN) && !t.oneMeta(metaInfo.SkipValidation));
  }
  exports.isUnknown = isUnknown;
  //# sourceMappingURL=typesystem.js.map