/**
 * Base class for all node types in all data models.
 * @author eric.wittmann@gmail.com
 * @class
 */
var Node = /** @class */ (function () {
    function Node() {
        if (this._ownerDocument === undefined)
            this._ownerDocument = null;
        if (this._parent === undefined)
            this._parent = null;
        this._modelId = Node.__modelIdCounter++;
        if (this._attributes === undefined)
            this._attributes = null;
        if (this._extraProperties === undefined)
            this._extraProperties = null;
        this._validationProblems = ({});
    }
    /**
     * Gets the owner document.
     * @return {Document}
     */
    Node.prototype.ownerDocument = function () {
        return this._ownerDocument;
    };
    /**
     * Returns true if this node is extensible.
     * @return {boolean}
     */
    Node.prototype.isExtensible = function () {
        return false;
    };
    /**
     * Gets the parent.
     * @return {Node}
     */
    Node.prototype.parent = function () {
        return this._parent;
    };
    /**
     * Gets the model's unique ID.
     * @return {number}
     */
    Node.prototype.modelId = function () {
        return this._modelId;
    };
    /**
     * Gets a single attribute by name.
     * @param {string} attributeName
     * @return {*}
     */
    Node.prototype.getAttribute = function (attributeName) {
        if (this._attributes != null) {
            return /* get */ (function (m, k) { return m[k] === undefined ? null : m[k]; })(this._attributes, attributeName);
        }
        else {
            return null;
        }
    };
    /**
     * Sets a single named attribute value.
     * @param {string} attributeName
     * @param {*} attributeValue
     */
    Node.prototype.setAttribute = function (attributeName, attributeValue) {
        if (this._attributes == null) {
            this._attributes = ({});
        }
        /* put */ (this._attributes[attributeName] = attributeValue);
    };
    /**
     * Gets a collection of all the attribute names.
     * @return {string[]}
     */
    Node.prototype.getAttributeNames = function () {
        if (this._attributes != null) {
            return /* keySet */ Object.keys(this._attributes);
        }
        else {
            return /* emptyList */ [];
        }
    };
    /**
     * Deletes all attributes in the node.
     */
    Node.prototype.clearAttributes = function () {
        if (this._attributes != null) {
            /* clear */ (function (obj) { for (var member in obj)
                delete obj[member]; })(this._attributes);
        }
    };
    /**
     * Gets a list of all the validation problem codes for this node (and this node only).  Returns
     * an empty list if no problems are found for this node.
     * @return {string[]}
     */
    Node.prototype.getValidationProblemCodes = function () {
        return ( /* keySet */Object.keys(this._validationProblems).slice(0));
    };
    /**
     * Gets a list of all the validation problems detected for this node.
     * @return {ValidationProblem[]}
     */
    Node.prototype.getValidationProblems = function () {
        return ( /* values */(function (obj) { return Object.keys(obj).map(function (key) { return obj[key]; }); })(this._validationProblems).slice(0));
    };
    /**
     * Gets a list of all validation problems detected for this node, filtered by only those
     * problems that apply to the given property name.
     * @param {string} propertyName
     * @return {ValidationProblem[]}
     */
    Node.prototype.getValidationProblemsFor = function (propertyName) {
        var rval = ([]);
        {
            var array127 = /* values */ (function (obj) { return Object.keys(obj).map(function (key) { return obj[key]; }); })(this._validationProblems);
            for (var index126 = 0; index126 < array127.length; index126++) {
                var problem = array127[index126];
                {
                    if ( /* equals */(function (o1, o2) { if (o1 && o1.equals) {
                        return o1.equals(o2);
                    }
                    else {
                        return o1 === o2;
                    } })(problem.property, propertyName)) {
                        /* add */ (rval.push(problem) > 0);
                    }
                }
            }
        }
        return rval;
    };
    /**
     * Adds a validation problem to the data model.  Typically this is only used by the validation
     * layer when performing validation on the data model.
     * @param {string} errorCode
     * @param {NodePath} nodePath
     * @param {string} property
     * @param {string} message
     * @param {ValidationProblemSeverity} severity
     * @return {ValidationProblem}
     */
    Node.prototype.addValidationProblem = function (errorCode, nodePath, property, message, severity) {
        var problem = new ValidationProblem(errorCode, nodePath, property, message, severity);
        /* put */ (this._validationProblems[errorCode] = problem);
        return problem;
    };
    /**
     * Deletes all validation problems previously discovered for this node.  Typically called by
     * the validation layer to reset the data model prior to performing validation.
     */
    Node.prototype.clearValidationProblems = function () {
        /* clear */ (function (obj) { for (var member in obj)
            delete obj[member]; })(this._validationProblems);
    };
    /**
     * Adds an extra property to the data model.  This is called when the reader encounters a property
     * that is unexpected based on the expected schema.
     * @param {string} key
     * @param {*} value
     */
    Node.prototype.addExtraProperty = function (key, value) {
        if (this._extraProperties == null) {
            this._extraProperties = ({});
        }
        /* put */ (this._extraProperties[key] = value);
    };
    Node.prototype.removeExtraProperty = function (name) {
        var _this = this;
        if (this._extraProperties != null && /* containsKey */ this._extraProperties.hasOwnProperty(name)) {
            return /* remove */ (function (map) { var deleted = _this._extraProperties[name]; delete _this._extraProperties[name]; return deleted; })(this._extraProperties);
        }
        return null;
    };
    Node.prototype.hasExtraProperties = function () {
        return this._extraProperties != null && /* size */ Object.keys(this._extraProperties).length > 0;
    };
    Node.prototype.getExtraPropertyNames = function () {
        if (this.hasExtraProperties()) {
            return ( /* keySet */Object.keys(this._extraProperties).slice(0));
        }
        return /* emptyList */ [];
    };
    Node.prototype.getExtraProperty = function (name) {
        if (this.hasExtraProperties()) {
            return /* get */ (function (m, k) { return m[k] === undefined ? null : m[k]; })(this._extraProperties, name);
        }
        return null;
    };
    /**
     * Determine if this node has a parent and owner document defined.
     *
     * @throws java.lang.IllegalStateException if the state is inconsistent, i.e. one is set but not the other
     * @return {boolean}
     */
    Node.prototype.isAttached = function () {
        if (this._parent == null || this._ownerDocument == null) {
            if (this._parent == null && this._ownerDocument == null)
                return false;
            else
                throw Object.defineProperty(new Error("Partially attached."), '__classes', { configurable: true, value: ['java.lang.Throwable', 'java.lang.IllegalStateException', 'java.lang.Object', 'java.lang.RuntimeException', 'java.lang.Exception'] });
        }
        return true;
    };
    /**
     * Set this {@link io.apicurio.datamodels.core.models.Node} to have the argument as its parent,
     * and the same {@link io.apicurio.datamodels.core.models.Document}.
     *
     * Warning: The parent MUST attach this child node separately.
     *
     * @throws java.lang.IllegalArgumentException if the parent is not attached itself
     * @throws java.lang.IllegalStateException if the parent's {@link Node#isAttached()} throws the exception
     * @param {Node} parent
     */
    Node.prototype.attachToParent = function (parent) {
        if (!parent.isAttached())
            throw Object.defineProperty(new Error("Target parent node (method argument) is not itself attached."), '__classes', { configurable: true, value: ['java.lang.Throwable', 'java.lang.Object', 'java.lang.RuntimeException', 'java.lang.IllegalArgumentException', 'java.lang.Exception'] });
        this._ownerDocument = parent.ownerDocument();
        this._parent = parent;
    };
    Node.__modelIdCounter = 0;
    return Node;
}());
export { Node };
Node["__class"] = "io.apicurio.datamodels.core.models.Node";
Node["__interfaces"] = ["io.apicurio.datamodels.core.models.IVisitable"];
import { ValidationProblem } from './ValidationProblem';
//# sourceMappingURL=Node.js.map