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

scalax.collection.constrained.ConstraintOp.scala Maven / Gradle / Ivy

The newest version!
package scalax.collection.constrained

import scala.language.{higherKinds, postfixOps}
import scala.collection.Set
import scala.collection.mutable.{Map => MMap}

import scalax.collection.GraphPredef._
import PreCheckFollowUp._

sealed trait Op
sealed trait BinaryOp extends Op
case object And extends BinaryOp 
case object Or  extends BinaryOp

abstract class ConstraintOp[N, E[X] <: EdgeLikeIn[X]] (self: Graph[N,E], val operator: Op)
  extends Constraint[N,E] (self)

class ConstraintBinaryOp[N, E[X] <: EdgeLikeIn[X]]
     (override val self: Graph[N,E],
      operator:          BinaryOp,
      left:              Constraint[N,E],
      right:             Constraint[N,E]) 
  extends ConstraintOp[N,E] (self, operator)
{
  assert((self eq left.self) && (left.self eq right.self))

  protected class PreCheckResults(override val followUp: PreCheckFollowUp,
                                  constraint:            Constraint[N,E],
                                  result:                PreCheckResult) 
    extends PreCheckResult(followUp)
  {
    val results: MMap[Constraint[N,E], PreCheckResult] = result match {
      case r: PreCheckResults => MMap(r.results.toSeq: _*)
      case _                  => MMap(constraint -> result)
    }
    def += (op: Constraint[N,E], result: PreCheckResult) = {
      result match {
        case r: PreCheckResults => results ++= r.results
        case _                  => results  += op -> result
      }
      this
    }
    override def get[N, E[X] <: EdgeLikeIn[X]](op: Constraint[N,E]) =
      results.asInstanceOf[MMap[Constraint[N,E], PreCheckResult]] get op
  }
  protected
  def eval(left:  Constraint[N,E], leftResult:  PreCheckResult,
           right: Constraint[N,E], rightResult: => PreCheckResult): PreCheckResult = {
    var rightDone = false
    val       leftFollowUp = leftResult.followUp
    lazy val rightFollowUp = {rightDone = true; rightResult.followUp }
    val followUp =
      operator match {
        case And => if (leftFollowUp != Abort) min(leftFollowUp, rightFollowUp)
                    else                       Abort
        case Or  => if (leftFollowUp != Abort) leftFollowUp
                    else                       rightFollowUp
      }
    if (followUp == Abort) PreCheckResult(Abort)
    else {
      if (rightDone) {
        leftResult match {
          case r: PreCheckResults => r += (right, rightResult)
          case _                  => new PreCheckResults( min(leftFollowUp, rightFollowUp),
                                                          left, leftResult) += (right, rightResult)
        }
      } else leftResult
    }
  }
  protected def eval(left: Boolean, right: => Boolean): Boolean = {
    operator match {
      case And => left && right
      case Or  => left || right
    }
  }
  private type LNodeT = left .self.NodeT
  private type RNodeT = right.self.NodeT
  private type LEdgeT = left .self.EdgeT
  private type REdgeT = right.self.EdgeT

  override final def preCreate(nodes: collection.Traversable[N],
                               edges: collection.Traversable[E[N]]) =
    eval(left,  left  preCreate(nodes, edges),
         right, right preCreate(nodes, edges))
  override final def preAdd(node: N   ) = eval(left, left preAdd node, right, right preAdd node)
  override final def preAdd(edge: E[N]) = eval(left, left preAdd edge, right, right preAdd edge)
  override final def preAdd(elems: InParam[N,E]*) =
    eval(left,  left  preAdd (elems: _*),
         right, right preAdd (elems: _*)) 
  override final def postAdd (newGraph   : scalax.collection.constrained.Graph[N,E],
                                passedNodes: Traversable[N],
                                passedEdges: Traversable[E[N]],
                                preCheck   : PreCheckResult) =
    eval(left  postAdd (newGraph, passedNodes, passedEdges, preCheck),
         right postAdd (newGraph, passedNodes, passedEdges, preCheck))
  override final def preSubtract (node: self.NodeT, forced: Boolean) =
    eval(left,  left  preSubtract (node.asInstanceOf[LNodeT], forced),
         right, right preSubtract (node.asInstanceOf[RNodeT], forced))
  override final def preSubtract (edge: self.EdgeT, simple: Boolean) =
    eval(left,  left  preSubtract (edge.asInstanceOf[LEdgeT], simple),
         right, right preSubtract (edge.asInstanceOf[REdgeT], simple))
  override final def preSubtract (nodes: => Set[self.NodeT],
                                  edges: => Set[self.EdgeT], simple: Boolean) =
    eval(left,  left  preSubtract (nodes.asInstanceOf[Set[LNodeT]], edges.asInstanceOf[Set[LEdgeT]], simple),
         right, right preSubtract (nodes.asInstanceOf[Set[RNodeT]], edges.asInstanceOf[Set[REdgeT]], simple))
  override final def postSubtract(newGraph   : Graph[N,E],
                                    passedNodes: Traversable[N],
                                    passedEdges: Traversable[E[N]],
                                    preCheck   : PreCheckResult) =
    eval(left  postSubtract (newGraph, passedNodes, passedEdges, preCheck),
         right postSubtract (newGraph, passedNodes, passedEdges, preCheck))
  override final def onAdditionRefused (refusedNodes: Traversable[N],
                                        refusedEdges: Traversable[E[N]],
                                        graph:        Graph[N,E]) = {
    left .onAdditionRefused(refusedNodes, refusedEdges, graph) ||
    right.onAdditionRefused(refusedNodes, refusedEdges, graph)
  }
  override final def onSubtractionRefused(refusedNodes: Traversable[Graph[N,E]#NodeT],
                                          refusedEdges: Traversable[Graph[N,E]#EdgeT],
                                          graph:        Graph[N,E]) = {
    left .onSubtractionRefused(refusedNodes, refusedEdges, graph) ||
    right.onSubtractionRefused(refusedNodes, refusedEdges, graph)
  }
}
/** Base class for any operation on `ConstraintCompanion`s. */
abstract class ConstraintCompanionOp (val operator: Op)
  extends ConstraintCompanion[Constraint]

/** Facilitates binary operations on `ConstraintCompanion`s. */
class ConstraintCompanionBinaryOp(operator: BinaryOp,
                                  left:     ConstraintCompanion[Constraint],
                                  right:    ConstraintCompanion[Constraint])
  extends ConstraintCompanionOp(operator)
{
  def apply [N, E[X] <: EdgeLikeIn[X]] (self: Graph[N,E]) =
    new ConstraintBinaryOp[N,E] (self, operator, left(self), right(self))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy