text: /// <reference path="../../../typings/main.d.ts" />
  "use strict";
  var defs = require("raml-definition-system");
  var hl = require("../highLevelAST");
  var yaml = require("yaml-ast-parser");
  var _ = require("underscore");
  var def = defs;
  var hlimpl = require("../highLevelImpl");
  var proxy = require("./LowLevelASTProxy");
  var search = require("../../search/search-interface");
  var universes = require("../tools/universe");
  var universeHelpers = require("../tools/universeHelpers");
  var services = defs;
  var ramlTypes = defs.rt;
  var messageRegistry = require("../../../resources/errorMessages");
  var mediaTypeParser = require("media-typer");
  var KeyMatcher = (function () {
      function KeyMatcher(_props) {
          this._props = _props;
          this.parentValue = _.find(_props, function (x) { return x.isFromParentValue(); });
          this.parentKey = _.find(_props, function (x) { return x.isFromParentKey(); });
          this.canBeValue = _.find(_props, function (x) { return x.canBeValue(); });
      }
      KeyMatcher.prototype.add = function (p) {
          this._props.push(p);
      };
      KeyMatcher.prototype.match = function (key) {
          var _this = this;
          var _res = null;
          var lastPref = "";
          this._props.forEach(function (p) {
              if (p.getAdapter(services.RAMLPropertyService).isSystem()) {
                  return;
              }
              if (p != _this.parentValue && p != _this.parentKey && p.matchKey(key)) {
                  if (p.keyPrefix() != null) {
                      if (p.keyPrefix().length >= lastPref.length) {
                          lastPref = p.keyPrefix();
                          _res = p;
                      }
                  }
                  else {
                      _res = p;
                      lastPref = p.nameId();
                  }
              }
          });
          return _res;
      };
      return KeyMatcher;
  }());
  function getAllOptions(c, deep) {
      if (deep === void 0) { deep = 0; }
      if (deep > 20) {
          return [];
      }
      try {
          var result = [];
          var tp = c.leftType();
          if (tp) {
              result.push(tp);
          }
          var r = c.rightType();
          if (r) {
              if (r.hasUnionInHierarchy()) {
                  var options = getAllOptions(r.unionInHierarchy(), deep + 1);
                  result = result.concat(options);
              }
              else {
                  result.push(r);
              }
          }
          return result;
      }
      finally {
      }
  }
  var ad = 0;
  /**
   * Checks if a node is type declaration by a type shortcut having multiple inheritance TE as a value
   * @param node
   */
  function isMultipleInheritanceTypeExpressionTypeDeclaration(node) {
      var definition = node.definition();
      if (!definition || !universeHelpers.isTypeDeclarationDescendant(definition))
          return false;
      var lowLevel = node.lowLevel();
      if (lowLevel.valueKind() !== yaml.Kind.SEQ)
          return false;
      var children = lowLevel.children();
      if (children == null)
          return false;
      for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
          var child = children_1[_i];
          if (child.kind() !== yaml.Kind.SCALAR)
              return false;
      }
      return true;
  }
  var BasicNodeBuilder = (function () {
      function BasicNodeBuilder() {
          this.shouldDescriminate = false;
      }
      BasicNodeBuilder.prototype.process = function (node, childrenToAdopt) {
          var _this = this;
          var nn = node.lowLevel();
          var cv = node;
          cv._mergedChildren = null;
          var cha = nn._node ? nn._node : nn;
          try {
              if (cha['currentChildren']) {
                  return cha['currentChildren'];
              }
              if (!node.definition()) {
                  return;
              }
              if (node.parent() == null && (!this.shouldDescriminate)) {
                  this.shouldDescriminate = true;
                  try {
                      var children = this.process(node, childrenToAdopt);
                      var ts = node;
                      ts._children = children;
                      var t = doDescrimination(node);
                      if (t) {
                          ts.patchType(t);
                      }
                      var children = this.process(node, childrenToAdopt);
                      ts._children = children;
                  }
                  finally {
                      this.shouldDescriminate = false;
                  }
              }
              if (node.definition().hasUnionInHierarchy()) {
                  if (true &&
                      (node.parent() && node.property().nameId() == universes.Universe10.LibraryBase.properties.annotations.name)) {
                      var optins = getAllOptions(node.definition().unionInHierarchy());
                      var actualResult = null;
                      var bestResult = null;
                      var bestType = null;
                      var bestCount = 1000;
                      var llnode = node;
                      optins.forEach(function (x) {
                          if (!actualResult) {
                              //TODO ADD UNION + Descriminator
                              if (!(x).hasUnionInHierarchy()) {
                                  var tp = llnode.patchType(x);
                                  if (ad == 0) {
                                      ad++;
                                      try {
                                          var result = _this.process(node, childrenToAdopt);
                                          var uc = 0;
                                          for (var i = 0; i < result.length; i++) {
                                              if (result[i].isUnknown()) {
                                                  uc++;
                                              }
                                          }
                                          if (uc == 0) {
                                              actualResult = result;
                                          }
                                          if (bestCount > uc) {
                                              bestCount = uc;
                                              bestResult = result;
                                              bestType = x;
                                          }
                                      }
                                      finally {
                                          ad--;
                                      }
                                  }
                              }
                          }
                      });
                      if (actualResult) {
                          llnode.patchType(bestType);
                          return actualResult;
                      }
                      if (bestResult) {
                          llnode.patchType(bestType);
                      }
                  }
              }
              var km = new KeyMatcher(node.definition().allProperties());
              if (node.parent() == null || node.lowLevel().includePath()) {
                  var u = node.definition().universe();
                  if (u.version() == "RAML10") {
                      if (!node.definition().property("uses")) {
                          u.type("FragmentDeclaration").allProperties().forEach(function (x) { return km.add(x); });
                      }
                  }
              }
              var aNode = node;
              var allowsQuestion = aNode._allowQuestion || node.definition().getAdapter(services.RAMLService).getAllowQuestion();
              var res = [];
              //cha['currentChildren']=res;
              if (km.parentKey) {
                  if (node.lowLevel().key()) {
                      var keyAttr = new hlimpl.ASTPropImpl(node.lowLevel(), node, km.parentKey.range(), km.parentKey, true);
                      res.push(keyAttr);
                      var isDefaultMediaType = node.property()
                          && universeHelpers.isBodyProperty(node.property())
                          && node.lowLevel().key() == node.property().nameId();
                      if (isDefaultMediaType) {
                          var isInsideTraitOrResourceType = isInTtraitOrResourceType(aNode);
                          if (!isInsideTraitOrResourceType && aNode._computedKey) {
                              keyAttr.overrideValue(aNode._computedKey);
                          }
                      }
                  }
                  if (node.lowLevel().valueKind() === yaml.Kind.SEQ
                      && !isMultipleInheritanceTypeExpressionTypeDeclaration(node)) {
                      var error = new hlimpl.BasicASTNode(node.lowLevel(), aNode);
                      error.errorMessage = {
                          entry: messageRegistry.DEFINITION_SHOULD_BE_A_MAP,
                          parameters: { typeName: node.definition().nameId() }
                      };
                      res.push(error);
                      return res;
                  }
              }
              if (node.lowLevel().value(true) != null) {
                  if (km.parentValue) {
                      res.push(new hlimpl.ASTPropImpl(node.lowLevel(), node, km.parentValue.range(), km.parentValue));
                  }
                  else if (km.canBeValue) {
                      var s = node.lowLevel().value();
                      if (s == null) {
                          s = node.lowLevel().value(true);
                      }
                      if (typeof s == 'string' && s.trim().length > 0) {
                          //if (km.canBeValue.nameId()==universes.Universe10.Resource.properties.signature.name){
                          //      if (s.trim().charAt(0)=='('){
                          //          //TODO BETTER DECITION current one prevents completion from working correctly
                          //          //in few other cases
                          //          res.push(new hlimpl.ASTPropImpl(node.lowLevel(), node, km.canBeValue.range(), km.canBeValue));
                          //      }
                          //}
                          //else {
                          res.push(new hlimpl.ASTPropImpl(node.lowLevel(), node, km.canBeValue.range(), km.canBeValue));
                      }
                  }
              }
              else {
              }
              aNode._children = res;
              if (!aNode.definition().getAdapter(services.RAMLService).isUserDefined()) {
                  if (aNode.definition().key() == universes.Universe08.Api || aNode.definition().key() == universes.Universe10.Api) {
                      var uses = childrenToAdopt.filter(function (x) { return x.key() == "uses"; });
                      res = this.processChildren(uses, aNode, res, allowsQuestion, km);
                      var types = childrenToAdopt.filter(function (x) { return x.key() == "types"; });
                      res = this.processChildren(types, aNode, res, allowsQuestion, km);
                      var other = childrenToAdopt.filter(function (x) { return (x.key() != "types" && x.key() != "uses"); });
                      res = this.processChildren(other, aNode, res, allowsQuestion, km);
                  }
                  else {
                      res = this.processChildren(childrenToAdopt, aNode, res, allowsQuestion, km);
                  }
              }
              else {
                  res = this.processChildren(childrenToAdopt, aNode, res, allowsQuestion, km);
              }
              aNode._children = res;
              return res;
          }
          finally {
          }
      };
      BasicNodeBuilder.prototype.isTypeDeclarationShortcut = function (node, property) {
          var isTypeDeclarationType = universeHelpers.isTypeProperty(property);
          var isTypeDeclaration = node.definition() && universeHelpers.isTypeDeclarationTypeOrDescendant(node.definition());
          if (isTypeDeclaration && isTypeDeclarationType && node.lowLevel() && node.lowLevel().valueKind() === yaml.Kind.SEQ) {
              return true;
          }
          return false;
      };
      BasicNodeBuilder.prototype.processChildren = function (childrenToAdopt, aNode, res, allowsQuestion, km) {
          var _this = this;
          var typeDeclarationName = universes.Universe10.TypeDeclaration.name;
          var typePropertyName = universes.Universe10.TypeDeclaration.properties.type.name;
          var itemsPropertyName = universes.Universe10.ArrayTypeDeclaration.properties.items.name;
          if (aNode.definition() && aNode.definition().isAssignableFrom(typeDeclarationName) && aNode.lowLevel() && (km.canBeValue && (km.canBeValue.nameId() === typePropertyName || km.canBeValue.nameId() === itemsPropertyName)) && aNode.lowLevel()._node && aNode.lowLevel()._node.value && aNode.lowLevel()._node.value.kind === yaml.Kind.SEQ) {
              childrenToAdopt.forEach(function (child) {
                  var property = new hlimpl.ASTPropImpl(child, aNode, km.canBeValue.range(), km.canBeValue);
                  res.push(property);
              });
              return res;
          }
          var rootUnit = aNode.root().lowLevel().unit();
          childrenToAdopt.forEach(function (x) {
              if (km.canBeValue && _this.isTypeDeclarationShortcut(aNode, km.canBeValue)) {
                  res.push(new hlimpl.ASTPropImpl(x, aNode, km.canBeValue.range(), km.canBeValue));
                  return;
              }
              var key = x.key();
              //if (x.optional()&&!allowsQuestion) {
              //    return;
              //}
              var p = key != null ? km.match(key) : null;
              if (p != null) {
                  var range = p.range();
                  if (p.isAnnotation() && key != "annotations") {
                      var pi = new hlimpl.ASTPropImpl(x, aNode, range, p);
                      res.push(pi);
                      return;
                  }
                  var um = false;
                  var multyValue = p.isMultiValue();
                  if (range.isArray()) {
                      multyValue = true;
                      range = range.array().componentType();
                      um = true;
                  }
                  else if (range.hasArrayInHierarchy()) {
                      multyValue = true;
                      um = true;
                  }
                  var xChildren;
                  var gotReuse = false;
                  if (aNode.reuseMode() && x.valueKind() != yaml.Kind.SEQ) {
                      var rNode = aNode.reusedNode();
                      if (rNode) {
                          var arr = [x];
                          var llParent = aNode.lowLevel();
                          if (!p.isMerged() && multyValue) {
                              xChildren = [];
                              arr = x.children();
                              llParent = x;
                          }
                          for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
                              var ch1 = arr_1[_i];
                              var cUnit = ch1.containingUnit();
                              if (cUnit && cUnit.absolutePath() != rootUnit.absolutePath()) {
                                  var rChild = _.find(rNode.children(), function (ch2) { return ch2.lowLevel().key() == ch1.key(); });
                                  if (rChild && rChild.lowLevel().unit().absolutePath() == cUnit.absolutePath()) {
                                      gotReuse = true;
                                      res.push(rChild);
                                      rChild.setReused(true);
                                      rChild.setParent(aNode);
                                      if (rChild.isElement()) {
                                          rChild.resetRuntimeTypes();
                                      }
                                      if (aNode.isExpanded()) {
                                          llParent
                                              .replaceChild(ch1, rChild.lowLevel());
                                          rChild.lowLevel().setTransformer(llParent.transformer());
                                      }
                                      continue;
                                  }
                              }
                              if (xChildren) {
                                  xChildren.push(ch1);
                              }
                          }
                      }
                  }
                  if (!xChildren) {
                      if (gotReuse) {
                          return;
                      }
                      xChildren = x.children();
                  }
                  //TODO DESCRIMINATORS
                  if (range.hasValueTypeInHierarchy()) {
                      var ch = xChildren;
                      var seq = (x.valueKind() == yaml.Kind.SEQ);
                      if ((seq && ch.length > 0 || ch.length > 1) && multyValue) {
                          if (ch.length > 1 && universeHelpers.isTypeDeclarationSibling(aNode.definition())
                              && (universeHelpers.isTypeProperty(p) || universeHelpers.isItemsProperty(p)) && x.valueKind() != yaml.Kind.SEQ) {
                              var pi = new hlimpl.ASTPropImpl(x, aNode, range, p);
                              res.push(pi);
                              aNode.setComputed(p.nameId(), pi);
                          }
                          else {
                              var values = [];
                              ch.forEach(function (y) {
                                  var pi = new hlimpl.ASTPropImpl(y, aNode, range, p);
                                  res.push(pi);
                                  values.push(y.value());
                              });
                              if (p.isInherited()) {
                                  aNode.setComputed(p.nameId(), values);
                              }
                          }
                      }
                      else {
                          if (p.isInherited()) {
                              aNode.setComputed(p.nameId(), x.value());
                          }
                          var attrNode = new hlimpl.ASTPropImpl(x, aNode, range, p);
                          if ((seq || x.valueKind() == yaml.Kind.MAP)) {
                              var rng = p.range().nameId();
                              if (!p.getAdapter(services.RAMLPropertyService).isExampleProperty()) {
                                  if (rng == 'StringType') {
                                      rng = "string";
                                  }
                                  if (rng == 'NumberType') {
                                      rng = "number";
                                  }
                                  if (rng == 'BooleanType') {
                                      rng = "boolean";
                                  }
                                  if (rng == "string" || rng == "number" || rng == "boolean") {
                                      if (!x.isAnnotatedScalar()) {
                                          attrNode.errorMessage = {
                                              entry: messageRegistry.INVALID_PROPERTY_RANGE,
                                              parameters: {
                                                  propName: p.groupName(),
                                                  range: rng
                                              }
                                          };
                                          if (xChildren.length == 0 && p.groupName() == "enum") {
                                              attrNode.errorMessage = {
                                                  entry: messageRegistry.ENUM_IS_EMPTY,
                                                  parameters: {}
                                              };
                                              if (x.valueKind() == yaml.Kind.MAP) {
                                                  attrNode.errorMessage = {
                                                      entry: messageRegistry.ENUM_MUST_BE_AN_ARRAY,
                                                      parameters: {}
                                                  };
                                              }
                                          }
                                      }
                                  }
                              }
                          }
                          res.push(attrNode);
                      }
                      //}
                      return;
                  }
                  else {
                      var rs = [];
                      //now we need determine actual type
                      aNode._children = res;
                      if (x.value() != null && (typeof x.value() == 'string' || typeof x.value() == 'boolean' || typeof x.value() == 'number')) {
                          if (("" + x.value()).trim().length > 0) {
                              var c = p.range();
                              if (!c.allProperties().some(function (x) {
                                  var srv = x;
                                  if (srv) {
                                      return srv.canBeValue() && srv.isFromParentValue();
                                  }
                                  return false;
                              })) {
                                  var bnode = new hlimpl.BasicASTNode(x, aNode);
                                  bnode.getLowLevelEnd = function () {
                                      return -1;
                                  };
                                  bnode.getLowLevelStart = function () {
                                      return -1;
                                  };
                                  bnode.knownProperty = p;
                                  res.push(bnode);
                              }
                          }
                      }
                      if (!p.isMerged()) {
                          if (multyValue) {
                              if (p.getAdapter(services.RAMLPropertyService).isEmbedMap()) {
                                  var chld = xChildren;
                                  var newChld = [];
                                  var hasSequenceComposition = false;
                                  chld.forEach(function (n) {
                                      if (n.kind() == yaml.Kind.INCLUDE_REF) {
                                          if (aNode.universe().version() == "RAML08") {
                                              n.children().forEach(function (y) {
                                                  var node = new hlimpl.ASTNodeImpl(y, aNode, range, p);
                                                  node._allowQuestion = allowsQuestion;
                                                  rs.push(node);
                                                  hasSequenceComposition = true;
                                              });
                                          }
                                          else {
                                              newChld.push(n);
                                          }
                                      }
                                      else {
                                          newChld.push(n);
                                      }
                                  });
                                  chld = newChld;
                                  if (chld.length == 0) {
                                      if (p.range().key() == universes.Universe08.ResourceType) {
                                          if (!hasSequenceComposition) {
                                              var error = new hlimpl.BasicASTNode(x, aNode);
                                              error.errorMessage = {
                                                  entry: messageRegistry.PROPERTY_MUST_BE_A_MAP,
                                                  parameters: { propName: p.nameId() }
                                              };
                                              res.push(error);
                                          }
                                      }
                                      if (x.valueKind() == yaml.Kind.SCALAR) {
                                          if (p.range().key() == universes.Universe08.AbstractSecurityScheme) {
                                              var error = new hlimpl.BasicASTNode(x.parent(), aNode);
                                              error.errorMessage = {
                                                  entry: messageRegistry.PROPERTY_MUST_BE_A_MAP,
                                                  parameters: { propName: p.nameId() }
                                              };
                                              res.push(error);
                                          }
                                      }
                                  }
                                  chld.forEach(function (y) {
                                      //TODO TRACK GROUP KEY
                                      var cld = y.children();
                                      if (!y.key() && cld.length == 1) {
                                          if (aNode.universe().version() != "RAML10" || aNode.parent()) {
                                              var node = new hlimpl.ASTNodeImpl(cld[0], aNode, range, p);
                                              node._allowQuestion = allowsQuestion;
                                              rs.push(node);
                                          }
                                      }
                                      else {
                                          if (aNode.universe().version() == "RAML10") {
                                              var node = new hlimpl.ASTNodeImpl(y, aNode, range, p);
                                              node._allowQuestion = allowsQuestion;
                                              rs.push(node);
                                          }
                                          else {
                                              var bnode = new hlimpl.BasicASTNode(y, aNode);
                                              res.push(bnode);
                                              if (y.key()) {
                                                  bnode.needSequence = true;
                                              }
                                          }
                                      }
                                  });
                                  if (aNode.universe().version() == "RAML10" && x.valueKind() == yaml.Kind.SEQ) {
                                      var bnode = new hlimpl.BasicASTNode(x, aNode);
                                      res.push(bnode);
                                      bnode.needMap = true;
                                      bnode.knownProperty = p;
                                  }
                              }
                              else {
                                  var filter = {};
                                  var inherited = [];
                                  if (defs.NodeClass.isInstance(range)) {
                                      var nc = range;
                                      if (nc.getAdapter(services.RAMLService).getCanInherit().length > 0) {
                                          nc.getAdapter(services.RAMLService).getCanInherit().forEach(function (v) {
                                              var originalValue = aNode.computedValue(v);
                                              var actualValue = Array.isArray(originalValue) ? originalValue : [originalValue];
                                              for (var pos = 0; pos < actualValue.length; pos++) {
                                                  var vl = actualValue[pos];
                                                  if (vl && p.nameId() == universes.Universe10.Response.properties.body.name) {
                                                      var exists = _.find(xChildren, function (x) { return x.key() == vl; });
                                                      var originalParent = x;
                                                      while (originalParent.originalNode) {
                                                          originalParent = originalParent.originalNode();
                                                      }
                                                      var mediaTypeSibling = _.find(originalParent.children(), function (sibling) {
                                                          try {
                                                              mediaTypeParser.parse(sibling.key());
                                                              return true;
                                                          }
                                                          catch (exception) {
                                                              return false;
                                                          }
                                                      });
                                                      if (!mediaTypeSibling) {
                                                          //we can create inherited node;
                                                          var pc = aNode.parent().definition().key();
                                                          var node = new hlimpl.ASTNodeImpl(x, aNode, range, p);
                                                          node._computedKey = vl;
                                                          if (pc == universes.Universe10.MethodBase || pc == universes.Universe08.MethodBase) {
                                                              node.setComputed("form", "true"); //FIXME
                                                          }
                                                          var isInsideTraitOrResourceType = isInTtraitOrResourceType(aNode);
                                                          var t = descriminate(p, aNode, node);
                                                          if (t) {
                                                              if (!isInsideTraitOrResourceType) {
                                                                  t.setName(vl);
                                                              }
                                                              node.patchType(t);
                                                          }
                                                          var ch = node.children();
                                                          //this are false unknowns actual unknowns will be reported by parent node
                                                          node._children = ch.filter(function (x) { return !x.isUnknown(); });
                                                          node._allowQuestion = allowsQuestion;
                                                          if (!exists) {
                                                              inherited.push(node);
                                                          }
                                                          node.children().forEach(function (x) {
                                                              if (x.property().getAdapter(services.RAMLPropertyService).isKey()) {
                                                                  var atr = x;
                                                                  atr._computed = true;
                                                                  return;
                                                              }
                                                              if (x.isElement()) {
                                                                  if (!x.property().getAdapter(services.RAMLPropertyService).isMerged()) {
                                                                      filter[x.property().nameId()] = true;
                                                                  }
                                                              }
                                                              if (x.property().isAnnotation()) {
                                                                  var atr = x;
                                                                  var vl = atr.value();
                                                                  var strVal = "";
                                                                  if (hlimpl.StructuredValue.isInstance(vl)) {
                                                                      strVal = vl.valueName();
                                                                  }
                                                                  else {
                                                                      strVal = "" + vl;
                                                                  }
                                                                  filter["(" + strVal + ")"] = true;
                                                              }
                                                              else {
                                                                  filter[x.name()] = true;
                                                              }
                                                          });
                                                          var ap = node.definition().allProperties();
                                                          ap.forEach(function (p) {
                                                              if (p.getAdapter(services.RAMLPropertyService).isKey()) {
                                                                  return;
                                                              }
                                                              if (p.getAdapter(services.RAMLPropertyService).isSystem()) {
                                                                  return;
                                                              }
                                                              if (node.lowLevel().children().some(function (x) { return x.key() == p.nameId(); })) {
                                                                  filter[p.nameId()] = true;
                                                              }
                                                          });
                                                          node._computed = true;
                                                      }
                                                  }
                                              }
                                          });
                                      }
                                  }
                                  var parsed = [];
                                  if (xChildren.length == 0) {
                                      if (x.valueKind() == yaml.Kind.SEQ) {
                                          if (p.range().key() == universes.Universe08.Parameter) {
                                              var error = new hlimpl.BasicASTNode(x, aNode);
                                              error.errorMessage = {
                                                  entry: messageRegistry.PROPERTY_MUST_BE_A_MAP,
                                                  parameters: { propName: p.nameId() }
                                              };
                                              res.push(error);
                                          }
                                      }
                                  }
                                  if (p.nameId() === "documentation" && x.valueKind() !== yaml.Kind.SEQ) {
                                      if (!aNode.definition().getAdapter(services.RAMLService).isUserDefined()) {
                                          var error = new hlimpl.BasicASTNode(x, aNode);
                                          error.errorMessage = {
                                              entry: messageRegistry.PROPERTY_MUST_BE_A_SEQUENCE,
                                              parameters: { propName: p.nameId() }
                                          };
                                          res.push(error);
                                      }
                                  }
                                  else {
                                      xChildren.forEach(function (y) {
                                          if (filter[y.key()]) {
                                              return;
                                          }
                                          if (y.valueKind() == yaml.Kind.SEQ) {
                                              var isRaml1 = aNode.definition().universe().version() == "RAML10";
                                              y.children().forEach(function (z) {
                                                  var node = new hlimpl.ASTNodeImpl(z, aNode, range, p);
                                                  node._allowQuestion = allowsQuestion;
                                                  node.setNamePatch(y.key());
                                                  if (isRaml1) {
                                                      node.invalidSequence = true;
                                                  }
                                                  parsed.push(node);
                                              });
                                              if (y.children().length == 0) {
                                                  var error = new hlimpl.BasicASTNode(y, aNode);
                                                  if (p.range().key() == universes.Universe08.Parameter) {
                                                      error.errorMessage = {
                                                          entry: messageRegistry.NAMED_PARAMETER_NEEDS_TYPE,
                                                          parameters: {}
                                                      };
                                                  }
                                                  else {
                                                      error.errorMessage = {
                                                          entry: messageRegistry.NODE_SHOULD_HAVE_VALUE,
                                                          parameters: {}
                                                      };
                                                  }
                                                  res.push(error);
                                              }
                                          }
                                          else {
                                              var node = new hlimpl.ASTNodeImpl(y, aNode, range, p);
                                              var dc = p.domain().key();
                                              if (p.nameId() == "body" && (dc == universes.Universe08.MethodBase || dc == universes.Universe10.MethodBase)) {
                                                  node.setComputed("form", "true"); //FIXME
                                              }
                                              node._allowQuestion = allowsQuestion;
                                              parsed.push(node);
                                          }
                                      });
                                  }
                                  if (parsed.length > 0) {
                                      parsed.forEach(function (x) { return rs.push(x); });
                                  }
                                  else {
                                      inherited.forEach(function (x) { return rs.push(x); });
                                  }
                              }
                          }
                          else {
                              //var y=xChildren[0];
                              rs.push(new hlimpl.ASTNodeImpl(x, aNode, range, p));
                          }
                      }
                      else {
                          var node = new hlimpl.ASTNodeImpl(x, aNode, range, p);
                          node._allowQuestion = allowsQuestion;
                          rs.push(node);
                      }
                      aNode._children = aNode._children.concat(rs);
                      res = res.concat(rs);
                      rs.forEach(function (x) {
                          var rt = descriminate(p, aNode, x);
                          if (rt && rt != x.definition()) {
                              x.patchType(rt);
                          }
                          x._associatedDef = null;
                          p.childRestrictions().forEach(function (y) {
                              x.setComputed(y.name, y.value);
                          });
                          var def = x.definition();
                      });
                  }
              }
              else {
                  if (!(proxy.LowLevelCompositeNode.isInstance(x))
                      || x.primaryNode() != null) {
                      res.push(new hlimpl.BasicASTNode(x, aNode));
                  }
              }
          });
          var rNode = aNode.reusedNode();
          if (rNode && aNode.lowLevel().valueKind() != yaml.Kind.SEQ) {
              var cObj = {};
              rNode.elements().forEach(function (x) { return cObj[x.property().nameId() + "_" + x.lowLevel().key()] = x; });
              rNode.attrs().forEach(function (x) { return cObj[x.property().nameId() + "_" + x.lowLevel().key()] = x; });
              res.filter(function (ch) { return ch.isElement() || ch.isAttr(); }).forEach(function (ch) {
                  var rChild = cObj[ch.property().nameId() + "_" + ch.lowLevel().key()];
                  if (rChild && rChild != ch) {
                      if (ch.isElement() && ch.lowLevel().parent().valueKind() != yaml.Kind.SEQ) {
                          ch.setReusedNode(rChild);
                          ch.setReuseMode(aNode.reuseMode());
                      }
                  }
              });
          }
          return res;
      };
      return BasicNodeBuilder;
  }());
  exports.BasicNodeBuilder = BasicNodeBuilder;
  function getBaseType(node, expression) {
      if (!expression) {
          return node.definition().universe().type(universes.Universe10.StringTypeDeclaration.name);
      }
      var pt = node.parsedType();
      if (pt.isString()) {
          return (node.definition().universe().type(universes.Universe10.StringTypeDeclaration.name));
      }
      else if (pt.isNumber()) {
          if (pt.isInteger()) {
              return (node.definition().universe().type(universes.Universe10.IntegerTypeDeclaration.name));
          }
          return (node.definition().universe().type(universes.Universe10.NumberTypeDeclaration.name));
      }
      else if (pt.isBoolean()) {
          return (node.definition().universe().type(universes.Universe10.BooleanTypeDeclaration.name));
      }
      else if (pt.isObject()) {
          return (node.definition().universe().type(universes.Universe10.ObjectTypeDeclaration.name));
      }
      else if (pt.isArray()) {
          return (node.definition().universe().type(universes.Universe10.ArrayTypeDeclaration.name));
      }
      else if (pt.isFile()) {
          return (node.definition().universe().type(universes.Universe10.FileTypeDeclaration.name));
      }
      else if (pt.isDateTime()) {
          return (node.definition().universe().type(universes.Universe10.DateTimeTypeDeclaration.name));
      }
      else if (pt.isDateTimeOnly()) {
          return (node.definition().universe().type(universes.Universe10.DateTimeOnlyTypeDeclaration.name));
      }
      else if (pt.isDateOnly()) {
          return (node.definition().universe().type(universes.Universe10.DateOnlyTypeDeclaration.name));
      }
      else if (pt.isTimeOnly()) {
          return (node.definition().universe().type(universes.Universe10.TimeOnlyTypeDeclaration.name));
      }
      if (pt.isUnion()) {
          return (node.definition().universe().type(universes.Universe10.UnionTypeDeclaration.name));
      }
      return (node.definition().universe().type(universes.Universe10.TypeDeclaration.name));
  }
  function transform(u) {
      return function (x) {
          var m = u.type(x);
          if (!m) {
              var ut = new defs.UserDefinedClass("", u, null, "", "");
          }
          return m;
      };
  }
  function findFacetInTypeNode(typeNode, facetName) {
      var typeNodeElement = typeNode.asElement();
      if (typeNodeElement == null)
          return null;
      var facets = typeNodeElement.elementsOfKind(universes.Universe10.TypeDeclaration.properties.facets.name);
      if (facets == null || facets.length == 0)
          return null;
      return _.find(facets, function (facet) {
          return facetName == facet.attrValue(universes.Universe10.TypeDeclaration.properties.name.name);
      });
  }
  function findFacetDeclaration(facet) {
      var owner = facet.owner();
      if (owner == null)
          return null;
      var facetName = facet.facetName();
      if (!facetName)
          return null;
      var ownerSource = owner.getExtra(ramlTypes.SOURCE_EXTRA);
      if (ownerSource == null)
          return null;
      if (!def.isSourceProvider(ownerSource) && !hl.isParseResult(ownerSource)) {
          return null;
      }
      return {
          getSource: function () {
              if (def.isSourceProvider(ownerSource)) {
                  var resolvedSource = ownerSource.getSource();
                  if (resolvedSource && hl.isParseResult(resolvedSource)) {
                      return findFacetInTypeNode(resolvedSource, facetName);
                  }
              }
              else if (hl.isParseResult(ownerSource)) {
                  return findFacetInTypeNode(ownerSource, facetName);
              }
              return null;
          },
          getClassIdentifier: function () {
              return [defs.SourceProvider.CLASS_IDENTIFIER];
          }
      };
  }
  function patchTypeWithFacets(originalType, nodeReferencingType, parentOfReferencingNode) {
      if (originalType == null)
          return null;
      var patchedType = new defs.NodeClass(nodeReferencingType.name(), nodeReferencingType.definition().universe(), "", "");
      var parsedRType = nodeReferencingType.parsedType();
      patchedType.addAdapter(parsedRType);
      parsedRType.allFacets().forEach(function (facet) {
          if (facet.kind() == defs.tsInterfaces.MetaInformationKind.FacetDeclaration) {
              var propertySource = findFacetDeclaration(facet);
              var facetBasedProperty = null;
              if (propertySource != null) {
                  facetBasedProperty = new defs.UserDefinedProp(facet.facetName(), null);
                  facetBasedProperty.setSourceProvider(propertySource);
              }
              else {
                  facetBasedProperty = new defs.Property(facet.facetName(), "");
              }
              var currentUniverse = null;
              if (parentOfReferencingNode) {
                  currentUniverse = parentOfReferencingNode.definition().universe();
              }
              else {
                  currentUniverse = nodeReferencingType.definition().universe();
              }
              facetBasedProperty.withRange(currentUniverse.type("StringType"));
              facetBasedProperty.withDomain(patchedType);
              facetBasedProperty.withGroupName(facet.facetName());
              facetBasedProperty.withRequired(false);
              facet.value();
              ramlTypes.setPropertyConstructor(function (x) {
                  var v = new defs.Property(x, "");
                  v.unmerge();
                  return v;
              });
              facetBasedProperty.withRange(ramlTypes.toNominal(facet.value(), transform(nodeReferencingType.definition().universe())));
          }
      });
      patchedType._superTypes.push(originalType);
      return patchedType;
      // return originalType;
  }
  function desc1(p, parent, x) {
      var tp = x.attr("type");
      var value = "";
      if (tp) {
          var baseType = getBaseType(x, tp.value());
          var patchedType = patchTypeWithFacets(baseType, x, parent);
          if (patchedType) {
              if (patchedType.superTypes().length == 0) {
                  patchedType._superTypes.push(x.definition().universe().type(universes.Universe10.TypeDeclaration.name));
              }
          }
          return patchedType;
      }
      else {
          var propertiesName = universes.Universe10.ObjectTypeDeclaration.properties.properties.name;
          if (p) {
              if (p.nameId() == "body" || _.find(x.lowLevel().children(), function (x) { return x.key() === propertiesName; })) {
                  return x.definition().universe().type(universes.Universe10.ObjectTypeDeclaration.name);
              }
          }
          else {
              if (!parent && x.lowLevel() && _.find(x.lowLevel().children(), function (x) { return x.key() === propertiesName; })) {
                  return x.definition().universe().type(universes.Universe10.ObjectTypeDeclaration.name);
              }
          }
          return x.definition().universe().type(universes.Universe10.StringTypeDeclaration.name);
      }
  }
  function doDescrimination(node) {
      try {
          var nodeDefenitionName = node.definition().nameId();
          var isApi = nodeDefenitionName === universes.Universe10.Api.name || nodeDefenitionName === universes.Universe08.Api.name;
          if (!isApi && !node.property() && !node.parent() && node.definition().nameId() === hlimpl.getFragmentDefenitionName(node)) {
              if (node.property() && node.property().nameId() === universes.Universe10.LibraryBase.properties.annotationTypes.name) {
                  return descriminate(null, null, node);
              }
              var result = null;
              var subTypes = node.definition().allSubTypes();
              subTypes.forEach(function (subType) {
                  if (!result && match(subType, node, null)) {
                      result = subType;
                  }
              });
              return result;
          }
      }
      catch (exception) {
      }
      return descriminate(node.property(), node.parent(), node);
  }
  exports.doDescrimination = doDescrimination;
  function descriminate(p, parent, x) {
      var n = x.lowLevel();
      if (p) {
          if (p.nameId() == universes.Universe10.FragmentDeclaration.properties.uses.name &&
              p.range().nameId() == universes.Universe10.Library.name) {
          }
      }
      var range = p ? p.range().nameId() : x.definition().nameId();
      if (n._node && n._node['descriminate']) {
          return null;
      }
      if (n._node) {
          n._node['descriminate'] = 1;
      }
      try {
          if (range == universes.Universe10.TypeDeclaration.name) {
              var res = desc1(p, parent, x);
              if (p || (!p && !parent && x.lowLevel())) {
                  if (p && res != null && ((p.nameId() == universes.Universe10.MethodBase.properties.body.name
                      || p.nameId() == universes.Universe10.ArrayTypeDeclaration.properties.items.name
                      || p.nameId() == universes.Universe10.Response.properties.headers.name) ||
                      p.nameId() == universes.Universe10.MethodBase.properties.queryParameters.name)) {
                      var ares = new defs.UserDefinedClass(x.lowLevel().key(), res.universe(), x, x.lowLevel().unit() ? x.lowLevel().unit().path() : "", "");
                      ares._superTypes.push(res);
                      return ares;
                  }
                  if (res != null && universeHelpers.isAnnotationTypeType(x.definition())) {
                      var annotationType = descriminateAnnotationType(res);
                      var ares = new defs.UserDefinedClass(x.lowLevel().key(), res.universe(), x, x.lowLevel().unit() ? x.lowLevel().unit().path() : "", "");
                      ares._superTypes.push(annotationType);
                      ares._superTypes.push(res);
                      return ares;
                  }
              }
              if (res) {
                  return res;
              }
          }
          //generic case;
          var rt = null;
          if (p && parent) {
              var types = search.findAllSubTypes(p, parent);
              if (types.length > 0) {
                  types.forEach(function (y) {
                      if (!rt) {
                          if (match(y, x, rt)) {
                              rt = y;
                          }
                      }
                  });
              }
              return rt;
          }
      }
      finally {
          if (n._node) {
              delete n._node['descriminate'];
          }
      }
  }
  ;
  function descriminateAnnotationType(type) {
      var arr = [type].concat(type.allSuperTypes());
      var candidate;
      for (var i = 0; i < arr.length; i++) {
          var t = arr[i];
          if (t.isUserDefined()) {
              continue;
          }
          if (t.isUnion()) {
              var ut = t;
              var lt = ut.leftType();
              var rt = ut.leftType();
              var lat = descriminateAnnotationType(lt);
              var rat = descriminateAnnotationType(lt);
              if (lat.isAssignableFrom(rat.nameId()) && (candidate == null || lat.isAssignableFrom(candidate.nameId()))) {
                  candidate = lat;
                  continue;
              }
              if (rat.isAssignableFrom(lat.nameId()) && (candidate == null || rat.isAssignableFrom(candidate.nameId()))) {
                  candidate = rat;
                  continue;
              }
              candidate = type.universe().type(universes.Universe10.UnionTypeDeclaration.name);
              break;
          }
          if (t.isArray()) {
              candidate = type.universe().type(universes.Universe10.ArrayTypeDeclaration.name);
              break;
          }
          var subTypes = t.subTypes();
          for (var j = 0; j < subTypes.length; j++) {
              var st = subTypes[j];
              if (st.isAssignableFrom(universes.Universe10.TypeDeclaration.name)) {
                  if (candidate == null) {
                      candidate = st;
                  }
                  else if (st.isAssignableFrom(candidate.nameId())) {
                      candidate = st;
                  }
              }
          }
      }
      return candidate != null ? candidate : type.universe().type(universes.Universe10.TypeDeclaration.name);
  }
  var isInTtraitOrResourceType = function (aNode) {
      var isInsideTraitOrResourceType = false;
      var parent_ = aNode;
      while (parent_) {
          var pDef = parent_.definition();
          if (universeHelpers.isTraitType(pDef)
              || universeHelpers.isResourceTypeType(pDef)) {
              isInsideTraitOrResourceType = true;
              break;
          }
          parent_ = parent_.parent();
      }
      return isInsideTraitOrResourceType;
  };
  function match(t, r, alreadyFound) {
      //this.vReqInitied=true;
      if (r.isAttr() || r.isUnknown()) {
          return false;
      }
      var el = r;
      var hasSuperType = _.find(t.superTypes(), function (x) {
          var dp = _.find(x.allProperties(), function (x) { return (x).isDescriminator(); });
          if (dp) {
              var a = el.attr(dp.nameId());
              if (a) {
                  if (a.value() == t.nameId()) {
                      return true;
                  }
              }
          }
          return false;
      });
      if (hasSuperType) {
          return true;
      }
      if (t.valueRequirements().length == 0) {
          return false;
      }
      var matches = true;
      //descriminating constraint
      t.valueRequirements().forEach(function (x) {
          var a = el.attr(x.name);
          if (a) {
              if (a.value() == x.value) {
              }
              else {
                  if (t.getAdapter(services.RAMLService).getConsumesRefs()) {
                      var vl = a.value();
                      var allSubs = [];
                      t.superTypes().forEach(function (x) { return x.allSubTypes().forEach(function (y) {
                          allSubs.push(y);
                      }); });
                      var allSubNames = [];
                      _.unique(allSubs).forEach(function (x) {
                          allSubNames.push(x.nameId());
                          x.valueRequirements().forEach(function (y) {
                              allSubNames.push(y.value);
                          });
                          x.getAdapter(services.RAMLService).getAliases().forEach(function (y) { return allSubNames.push(y); });
                      });
                      if (_.find(allSubNames, function (x) { return x == vl; })) {
                          matches = false;
                      }
                  }
                  else {
                      matches = false;
                  }
              }
          }
          else {
              var m = t.getAdapter(services.RAMLService).getDefining();
              var ms = false;
              m.forEach(function (x) {
                  el.lowLevel().children().forEach(function (y) {
                      if (y.key() == x) {
                          ms = true;
                      }
                  });
              });
              if (ms) {
                  matches = true;
                  return;
              }
              if (!alreadyFound) {
                  var pr = t.property(x.name);
                  if (pr && pr.defaultValue() == x.value) {
                  }
                  else {
                      matches = false;
                  }
              }
              else {
                  matches = false;
              }
          }
      });
      return matches;
  }
  //# sourceMappingURL=builder.js.map