All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.apicurio.datamodels.core.models.Node Maven / Gradle / Ivy

/*
 * Copyright 2019 Red Hat
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.apicurio.datamodels.core.models;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import io.apicurio.datamodels.core.visitors.IVisitor;

/**
 * Base class for all node types in all data models.
 * @author [email protected]
 */
public abstract class Node implements IVisitable {
    
    private static int __modelIdCounter = 0;

    public Document _ownerDocument;
    public Node _parent;
    protected int _modelId = __modelIdCounter++;
    protected Map _attributes;

	/**
	 * Properties that are present in the source document,
	 * but are not defined in the specification for this node,
	 * so they can't be read directly into the data model fields.
	 */
	protected Map _extraProperties;
    protected Map _validationProblems = new LinkedHashMap<>();

    /**
     * Gets the owner document.
     */
    public Document ownerDocument() {
        return this._ownerDocument;
    }
    
    /**
     * Returns true if this node is extensible.
     */
    public boolean isExtensible() {
        return false;
    }

    /**
     * Gets the parent.
     */
    public Node parent() {
        return this._parent;
    }

    /**
     * Gets the model's unique ID.
     */
    public int modelId() {
        return this._modelId;
    }

	/**
	 * @see io.apicurio.datamodels.core.models.IVisitable#accept(io.apicurio.datamodels.core.visitors.IVisitor)
	 */
	public abstract void accept(IVisitor visitor);
	
	/**
	 * Gets a single attribute by name.
	 * @param attributeName
	 */
	public Object getAttribute(String attributeName) {
	    if (this._attributes != null) {
	        return this._attributes.get(attributeName);
	    } else {
	        return null;
	    }
	}

	/**
	 * Sets a single named attribute value.
	 * @param attributeName
	 * @param attributeValue
	 */
	public void setAttribute(String attributeName, Object attributeValue) {
	    if (this._attributes == null) {
	        this._attributes = new HashMap<>();
	    }
	    this._attributes.put(attributeName, attributeValue);
	}
	
	/**
	 * Gets a collection of all the attribute names.
	 */
	public Collection getAttributeNames() {
	    if (this._attributes != null) {
	        return this._attributes.keySet();
	    } else {
	        return Collections.emptyList();
	    }
	}
	
	/**
	 * Deletes all attributes in the node.
	 */
	public void clearAttributes() {
	    if (this._attributes != null) {
	        this._attributes.clear();
	    }
	}
	
	/**
	 * 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.
	 */
	public List getValidationProblemCodes() {
	    return new ArrayList<>(this._validationProblems.keySet());
	}

	/**
	 * Gets a list of all the validation problems detected for this node.
	 */
	public List getValidationProblems() {
	    return new ArrayList<>(this._validationProblems.values());
	}
	
	/**
	 * Gets a list of all validation problems detected for this node, filtered by only those
	 * problems that apply to the given property name.
	 * @param propertyName
	 */
	public List getValidationProblemsFor(String propertyName) {
	    List rval = new ArrayList<>();
	    for (ValidationProblem problem : this._validationProblems.values()) {
            if (problem.property.equals(propertyName)) {
                rval.add(problem);
            }
        }
	    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 errorCode
	 * @param nodePath
	 * @param property
	 * @param message
	 * @param severity
	 */
    public ValidationProblem addValidationProblem(String errorCode, NodePath nodePath, String property,
            String message, ValidationProblemSeverity severity) {
        ValidationProblem problem = new ValidationProblem(errorCode, nodePath, property, message, severity);
        this._validationProblems.put(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.
     */
	public void clearValidationProblems() {
	    this._validationProblems.clear();
	}

    /**
     * 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 key
     * @param value
     */
    public void addExtraProperty(String key, Object value) {
        if (this._extraProperties == null) {
            this._extraProperties = new LinkedHashMap<>();
        }
        this._extraProperties.put(key, value);
    }
    
    public Object removeExtraProperty(String name) {
        if (this._extraProperties != null && this._extraProperties.containsKey(name)) {
            return this._extraProperties.remove(name);
        }
        return null;
    }

    public boolean hasExtraProperties() {
        return this._extraProperties != null && this._extraProperties.size() > 0;
    }

    public List getExtraPropertyNames() {
        if (this.hasExtraProperties()) {
            return new ArrayList(this._extraProperties.keySet());
        }
        return Collections.emptyList();
    }

    public Object getExtraProperty(String name) {
        if (this.hasExtraProperties()) {
            return this._extraProperties.get(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
	 */
	public boolean isAttached() {
    	if(_parent == null || _ownerDocument == null) {
			if(_parent == null && _ownerDocument == null)
				return false;
			else
				throw new IllegalStateException("Partially attached.");
		}
    	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
	 */
	public void attachToParent(Node parent) {
		if(!parent.isAttached())
			throw new IllegalArgumentException("Target parent node (method argument) is not itself attached.");
    	this._ownerDocument = parent.ownerDocument();
    	this._parent = parent;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy