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

org.opalj.graphs.MutableNodeLike.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package graphs

import scala.collection.Map

/**
 * Represents a mutable node of a directed graph.
 * This class serves as a base implementation of the [[MutableNode]] trait.
 *
 * ==Thread Safety==
 * This class is thread-safe. It is possible to add multiple child nodes concurrently.
 *
 * @see    The demo project for example usages.
 *
 * @tparam I The type of the object that is associated with this node/the type of
 *         the object for which this node object is created.
 * @param  theIdentifier The underlying object. '''For all nodes of a graph the hashCode method
 *         has to return a unique id unless the nodeId method is overridden.'''
 *         '''The underlying object must correctly implement the equals/hashCode contract.
 *         I.e., the `hashCode` of two object instances that are added to the same graph is
 *         different whenever `equals` is `false`'''.
 * @param  identifierToString A function that converts "an" identifier to a string. By
 *         default the given object's `toString` method is called. It is possible
 *         that a graph has two nodes with the same textual representation representation
 *         but a different identity.
 * @author Michael Eichberg
 */
class MutableNodeLike[I, N <: Node](
        private[this] var theIdentifier:       I,
        val identifierToString:                I ⇒ String,
        private[this] var theVisualProperties: Map[String, String],
        private[this] var theChildren:         List[N]
) extends MutableNode[I, N] {

    def identifier: I = this.synchronized(theIdentifier)

    override def visualProperties: Map[String, String] = this.synchronized(theVisualProperties)

    def mergeVisualProperties(other: Map[String, String]): Unit = {
        theVisualProperties ++= other
    }

    def children: List[N] = this.synchronized(theChildren)

    def updateIdentifier(newIdentifier: I): Unit = this.synchronized {
        theIdentifier = newIdentifier
    }

    override def toHRR: Option[String] = Some(identifierToString(identifier))

    override def nodeId: Int = identifier.hashCode()

    def addChild(node: N): Unit = this.synchronized { theChildren = node :: children }

    def addChildren(furtherChildren: List[N]): Unit = this.synchronized {
        theChildren = theChildren ::: furtherChildren
    }

    def hasOneChild: Boolean = this.synchronized(children.nonEmpty && children.tail.isEmpty)

    def firstChild: N = this.synchronized(children.head)

    def removeLastAddedChild(): Unit = this.synchronized { theChildren = theChildren.tail }

    def removeChild(node: N): Unit = this.synchronized {
        theChildren = theChildren.filterNot(_ == node)
    }

    override def foreachSuccessor(f: Node ⇒ Unit): Unit = this.synchronized { children.foreach(f) }

    override def hasSuccessors: Boolean = this.synchronized { children.nonEmpty }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy