+
+
+ /**
+ * @module meteoJS/modelviewer/resourcesTreeNode
+ */
+
+/**
+ * Options for constructor.
+ *
+ * @typedef {Object} module:meteoJS/modelviewer/resourcesTreeNode~options
+ * @param {module:meteoJS/modelviewer/node.Node} node
+ * The object is linked to this node.
+ */
+
+/**
+ * Internal class to manage the available resources inside the
+ * {@link module:meteoJS/modelviewer/node.Node|Node class}. Each
+ * ResourcesTreeNode object is linked to a Node object. It is a many to one
+ * relation. The hierarchy of the ResourcesTree is analogue to the Node
+ * hierarchy. But the tree is build via the
+ * {@link module:meteoJS/modelviewer/variable.Variable|Variable objects}.
+ * So, this class is not only linked to a Node object, but subsequently for a
+ * {@link module:meteoJS/modelviewer/variableCollection.VariableCollection|VariableCollection object}.
+ * If a {@link module:meteoJS/modelviewer/resource.Resource|Resource} for a
+ * certain Variable object from this VariableCollection is added, then a
+ * child ResourcesTreeNode object is inserted in the tree (if it doesn't exists)
+ * for the Variable object.
+ *
+ * @internal
+ */
+export class ResourcesTreeNode {
+
+ /**
+ * @param {module:meteoJS/modelviewer/resourcesNode~options} [options]
+ * Options.
+ */
+ constructor({ node }) {
+
+ /**
+ * @type module:meteoJS/modelviewer/node.Node
+ * @private
+ */
+ this._node = node;
+
+ /**
+ * @type Map.<module:meteoJS/modelviewer/variable.Variable,module:meteoJS/modelviewer/resourcesTreeNode.ResourcesTreeNode>
+ * @private
+ */
+ this._children = new Map();
+
+ /**
+ * @type module:meteoJS/modelviewer/resourcesTreeNode.ResourcesTreeNode
+ * @private
+ */
+ this._parent = undefined;
+ }
+
+ /**
+ * Linked Node object.
+ *
+ * @type module:meteoJS/modelviewer/node.Node
+ * @readonly
+ */
+ get node() {
+ return this._node;
+ }
+
+ /**
+ * Linked VariableCollection object.
+ *
+ * @type module:meteoJS/modelviewer/variableCollection.VariableCollection
+ * @readonly
+ */
+ get variableCollection() {
+ return this._node.variableCollection;
+ }
+
+ get children() {
+ return [...this._children.values()];
+ }
+
+ /**
+ * The parent object of this ResourcesTree-Node.
+ *
+ * @type undefined|module:meteoJS/modelviewer/resourcesTreeNode.ResourcesTreeNode
+ */
+ get parent() {
+ return this._parent;
+ }
+ set parent(parent) {
+ this._parent = parent;
+ }
+
+ /**
+ * Returns the child corresponding to the passed variable.
+ *
+ * @param {module:meteoJS/modelviewer/variable.Variable} variable - Variable.
+ * @returns {module:meteoJS/modelviewer/resourcesTreeNode.ResourcesTreeNode}
+ * Child ResourcesTreeNode object for the passed variable.
+ */
+ getChildByVariable(variable) {
+ return this._children.get(variable);
+ }
+
+ /**
+ * Build tree
+ *
+ * @param {Object} options - Options.
+ * @param {module:meteoJS/modelviewer/resource.Resource} options.resource
+ * The added Resource object.
+ * @param {module:meteoJS/modelviewer/node.Node} options.aimedNode
+ * The Resource object will be inserted into this Node object.
+ * @returns {undefined|module:meteoJS/modelviewer/resourcesTreeNode.ResourcesTreeNode}
+ */
+ buildChildrenTreeForResource({
+ resource,
+ aimedNode
+ }) {
+ if (this.node === aimedNode)
+ return this;
+
+ const variable =
+ resource.getVariableByVariableCollection(this.variableCollection);
+ /* Shouldn't get an unknown Variable. The resource is inserted in the
+ * Node-tree with a Variable in each Node. */
+ if (variable.id === undefined)
+ return undefined;
+
+ let child = this._children.get(variable);
+ if (child !== undefined)
+ return child.buildChildrenTreeForResource({ resource, aimedNode });
+ // Child doesn't already exist
+ this.node.children.forEach(node => {
+ // The resource will belong only to one node.
+ const childVariable =
+ resource.getVariableByVariableCollection(node.variableCollection);
+ if (childVariable.id !== undefined)
+ child = new ResourcesTreeNode({ node });
+ });
+ if (child !== undefined) {
+ this._children.set(variable, child);
+ child.parent = this;
+ return child.buildChildrenTreeForResource({ resource, aimedNode });
+ }
+ return undefined;
+ }
+
+ /**
+ * Removes a child in the Resources-Tree. If this was the only child of this
+ * Resources-Tree-Node, then remove this Tree-Node from the parent.
+ */
+ removeChild({
+ child
+ }) {
+ for (const [variable, c] of this._children.entries())
+ if (c === child)
+ this._children.delete(variable);
+ if (this._children.size < 1
+ && this.parent !== undefined)
+ this.parent.removeChild({ child: this });
+ }
+
+ /**
+ * Returns the bottom most ResourcesTreeNode object. On the way from the top
+ * ResourcesTreeNode to this object, for every passed Variable object a
+ * suitable ResourcesTreeNode is passed.
+ *
+ * @param {...module:meteoJS/modelviewer/variable.Variable} - variables
+ * A set of Variable objects.
+ * @returns {undefined|module:meteoJS/modelviewer/resourcesTreeNode.ResourcesTreeNode}
+ * Bottom most object.
+ */
+ findNodeByVariables(...variables) {
+ let v = undefined;
+ variables.forEach(variable => {
+ if (variable.variableCollection === this.variableCollection)
+ v = variable;
+ });
+ if (v === undefined)
+ return undefined;
+ const child = this._children.get(v);
+ if (child !== undefined) {
+ const result = child.findNodeByVariables(...variables);
+ return (result === undefined) ? this : result;
+ }
+ return this;
+ }
+}
+export default ResourcesTreeNode;
+
+