Node
This class is part of our Collection Type API, but it is supposed to be reworked soon.
/**
 * A node of the view tree.
 *
 * @param <N> the type of node
 */
class Node {
  /**
   * Used-defined properties generated for this node. Properties can be anything and thus don't
   * follow a particular schema.
   */
  properties: Map<string, any> = new Map<string, string>();
  /**
   * The name of the node. Used as a fallback for the visualization if no more specific visualization is available.
   */
  name: string;
  /**
   * A map of visualizations generated for this node. The key is the visualization type (e.g.
   * <code>html</code>), the value is the string representation of the visualization.
   */
  visualization: Map<string, string> = new Map<string, string>();
  /**
   * The id of the element this node refers to.
   */
  elementId: string | null;
  /**
   * The child nodes of this node.
   */
  children: Node[] = [];
  /**
   * Whether the node shall be initially expanded when opening the view.
   */
  initiallyExpanded: boolean;
  /**
   * Whether the node can be deleted
   */
  deletable: boolean;
  onDropExecutable: string | null;
  onDragoverExecutable: string | null;
  sortCheckExecutable: string | null;
  sortActionExecutable : string | null;
  lazy: boolean;
  public getProperties(): Map<string, any> {
    return this.properties;
  }
  public setProperties(properties: Map<string, any>): void {
    if (properties) {
      this.properties = properties;
    }
  }
  public getVisualization(): Map<string, string> {
    return this.visualization;
  }
  public setVisualization(visualization: any): void {
    this.visualization = visualization;
  }
  public withProperty(name: string, value: any): Node {
    this.getProperties().set(name, value);
    return this;
  }
  public withVisualization(type: string, representation: string): Node {
    this.getVisualization().set(type, representation);
    return this;
  }
  public getName(): string {
    return this.name;
  }
  public setName(name: string): void {
    this.name = name;
  }
  public getElementId(): string | null {
    return this.elementId;
  }
  public setElementId(elementId: string): void {
    this.elementId = elementId;
  }
  public getChildren(): Node[] {
    return this.children;
  }
  public setChildren(children: Node[]): void {
    if (children) {
      this.children = children;
    }
  }
  public createChild(name: string): Node {
    const child = this.children.find(m => m.getName() === name);
    if (child) {
      return child;
    } else {
      const n = new Node();
      n.setName(name);
      this.children.push(n);
      return n;
    }
  }
  public findChild(name: string): Node | undefined{
    return this.children.find(m => m.getName() === name);
  }
  public createPath(nodePath?: string[]): Node {
    let n: Node;
    n = this;
    if(!nodePath){
      return n;
    }
    for (const p of nodePath) {
      n = n.createChild(p);
    }
    return n;
  }
  public createNode(name: string): Node {
    return this.createPath([name]);
  }
  public findNode(nodePath?: string[]): Node | null {
    let n: Node;
    n = this;
    if(!nodePath){
      return n;
    }
    for (const p of nodePath) {
      const foundNode = n.findChild(p);
      if (!foundNode) {
        return null;
      }
      n = foundNode;
    }
    return n;
  }
  public withElement(e: CollectionElement): Node {
    this.setElementId(e.id);
    return this;
  }
  public createElementNode(e: CollectionElement): Node {
    if(e.specification.type == "collectionReference"){
      const n = this.createPath([e.id]);
      n.lazy = true;
      n.createChild(e.id).withElement(e);
      return n;
    } else {
      return this.createChild(e.id).withElement(e);
    }
  }
  public collapseInitially(): Node {
    this.setInitiallyExpanded(false);
    return this;
  }
  public expandInitially(): Node {
    this.setInitiallyExpanded(true);
    return this;
  }
  public isInitiallyExpanded(): boolean {
    return this.initiallyExpanded;
  }
  public setInitiallyExpanded(initiallyExpanded: boolean): void {
    this.initiallyExpanded = initiallyExpanded;
  }
  public sortable(executable?: string): Node {
    this.sortCheckExecutable = executable ? executable: "return defaultSortCheck()";
    return this;
  }
  public onSortDrop(executable: string): Node {
    this.sortActionExecutable = executable;
    return this;
  }
  public isDeletable(): boolean {
    return this.deletable;
  }
  public setDeletable(value: boolean) {
    this.deletable = value;
  }
  public notDeletable(): Node {
    this.setDeletable(false)
    return this;
  }
  public getOnDragoverExecutable(): string | null {
    return this.onDragoverExecutable;
  }
  public getOnDropExecutable(): string | null {
    return this.onDropExecutable;
  }
  /**
   * The function (defined in parameter 'executable') will be executed when the native Dragover Event is fired.
   * The given executable will be called with the parameter 'event', which is a reference to the JavaScript native DragEvent.
   *
   * @param executable A native JavaScript function.
   * @return This node instance.
   */
  public onDragover(executable: string): Node {
    this.onDragoverExecutable = executable;
    return this;
  }
  /**
   * The function (defined in parameter 'executable') will be executed when the native Drop Event is fired.
   * Whether or not content may be dropped on this Node can be controlled with the 'onDragover' function.
   * The given executable will be called with the parameter 'event', which is a reference to the JavaScript native DragEvent.
   *
   * @param executable A native JavaScript function.
   * @return This node instance.
   */
  public onDrop(executable: string): Node {
    this.onDropExecutable = executable;
    return this;
  }
}