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

geotrellis.engine.Operation.scala Maven / Gradle / Ivy

Go to download

GeoTrellis is an open source geographic data processing engine for high performance applications.

There is a newer version: 0.10.3
Show newest version
/*
 * Copyright (c) 2014 Azavea.
 *
 * 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 geotrellis.engine

import scala.{PartialFunction => PF}

import akka.actor._

import scala.language.implicitConversions

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
object Op {
  /**
    * Add simple syntax for creating an operation.
    *
    * Define a function after op function that returns:
    *
    * 1) A literal value, e.g.
    *   val plusOne = op { (i: Int) => i + 1 }
    *
    * 2) An operation to be executed:
    *   val localPlusOne = ( (r: Raster, i: Int) => local.Add(r, i + 1) )
    *
    * 3) Or a StepResult (which indicates success or failure)
    *   val plusOne = op { (i: Int) => Result(i + 1) }
    *
    */
  def apply[T](value: => T) = new Op0(() => Result(value))

  /**
    * Create an operation from a 1-arg function that returns StepOutput.
    *
    * For example:
    *
    * val plusOne = op { (i: Int) => Result(i + 1) }
    */
  def apply[A, T](f: (A) => StepOutput[T]): (Op[A]) => Op1[A, T] =
    (a: Op[A]) => new Op1(a)((a) => f(a))

  /**
    * Create an operation from a 1-arg function that returns an operation to be executed.
    *
    * For example:
    *
    * val localPlusOne = ( (r: Raster, i: Int) => local.Add(r, i + 1) )
    *
    */
  def apply[A, T](f: (A) => Op[T])(implicit n: DI): (Op[A]) => Op1[A, T] =
    (a: Op[A]) => new Op1(a)((a) => StepRequiresAsync(List(f(a)), (l) => Result(l.head.asInstanceOf[T])))

  /**
    * Create an operation from a 1-arg function that returns a literal value.
    *
    * For example:
    *
    * val plusOne = op { (i: Int) => i + 1 }
    */
  def apply[A, T](f: (A) => T)(implicit n: DI, o: DI): (Op[A]) => Op1[A, T] =
    (a: Op[A]) => new Op1(a)((a) => Result(f(a)))

  // Op2 methods for op() //

  /**
    * Create an operation from a 2-arg function that returns StepOutput.
    */
  def apply[A, B, T](f: (A, B) => StepOutput[T]): (Op[A], Op[B]) => Op2[A, B, T] =
    (a: Op[A], b: Op[B]) => new Op2(a, b)((a, b) => f(a, b))

  /**
    * Create an operation from a 2-arg function that returns an operation.
    */
  def apply[A, B, T](f: (A, B) => Op[T])(implicit n: DI): (Op[A], Op[B]) => Op2[A, B, T] =
    (a: Op[A], b: Op[B]) => new Op2(a, b)((a, b) => StepRequiresAsync(List(f(a, b)), (l) =>
      Result(l.head.asInstanceOf[T])))

  /**
    * Create an operation from a 2-arg function that returns a literal value.
    */
  def apply[A, B, T](f: (A, B) => T)(implicit n: DI, o: DI): (Op[A], Op[B]) => Op2[A, B, T] =
    (a: Op[A], b: Op[B]) => new Op2(a, b)((a, b) => Result(f(a, b)))

  // Op3 methods for op() //

  /**
    * Create an operation from a 3-arg function that returns StepOutput.
    */
  def apply[A, B, C, T](f: (A, B, C) => StepOutput[T]): (Op[A], Op[B], Op[C]) => Op3[A, B, C, T] =
    (a: Op[A], b: Op[B], c: Op[C]) => new Op3(a, b, c)((a, b, c) => f(a, b, c))

  /**
    * Create an operation from a 3-arg function that returns an operation.
    */
  def apply[A, B, C, T](f: (A, B, C) => Op[T])(implicit  n: DI): (Op[A], Op[B], Op[C]) => Op3[A, B, C, T] =
    (a: Op[A], b: Op[B], c: Op[C]) =>
  new Op3(a, b, c)((a, b, c) => StepRequiresAsync(List(f(a, b, c)), (l) => Result(l.head.asInstanceOf[T])))

  /**
    * Create an operation from a 3-arg function that returns a literal value.
    */
  def apply[A, B, C, T](f: (A, B, C) => T)(implicit n: DI, o: DI): (Op[A], Op[B], Op[C]) => Op3[A, B, C, T] =
    (a: Op[A], b: Op[B], c: Op[C]) => new Op3(a, b, c)((a, b, c) => Result(f(a, b, c)))

  // Op4 methods for op() //

  /**
    * Create an operation from a 4-arg function that returns StepOutput.
    */
  def apply[A, B, C, D, T](f: (A, B, C, D) => StepOutput[T]):
      (Op[A], Op[B], Op[C], Op[D]) => Op4[A, B, C, D, T] =
    (a: Op[A], b: Op[B], c: Op[C], d: Op[D]) => new Op4(a, b, c, d)((a, b, c, d) => f(a, b, c, d))

  /**
    * Create an operation from a 4-arg function that returns an operation.
    */
  def apply[A, B, C, D, T](f: (A, B, C, D) => Op[T])(implicit n: DI):
      (Op[A], Op[B], Op[C], Op[D]) => Op4[A, B, C, D, T] =
    (a: Op[A], b: Op[B], c: Op[C], d: Op[D]) => new Op4(a, b, c, d)((a, b, c, d) =>
      StepRequiresAsync(List(f(a, b, c, d)), (l) => Result(l.head.asInstanceOf[T])))

  /**
    * Create an operation from a 4-arg function that returns a literal value.
    */
  def apply[A, B, C, D, T](f: (A, B, C, D) => T)(implicit n: DI, o: DI):
      (Op[A], Op[B], Op[C], Op[D]) => Op4[A, B, C, D, T] =
    (a: Op[A], b: Op[B], c: Op[C], d: Op[D]) => new Op4(a, b, c, d)((a, b, c, d) =>
      Result(f(a, b, c, d)))
}

/**
 * Base Operation for all GeoTrellis functionality. All other operations must
 * extend this trait.
 */
@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
abstract class Operation[+T] extends Product with Serializable {
  val nextSteps: Steps[T]

  val debug = false
  private def log(msg: String) = if(debug) println(msg)

  /**
   * Return operation identified.
   */
  private var _opId = getClass.getSimpleName
  def opId: String = _opId
  def withName(n: String): Operation[T] = { _opId += s" ($n)"; this }

  protected[geotrellis] def _run(): StepOutput[T]

  /**
   * Execute this operation and return the result.
   */
  def run(): StepOutput[T] =
    _run()

  def runAsync(args: Args): StepOutput[T] = {
    StepRequiresAsync[T](args, { (nextArgs: Args) =>
      processNextSteps(nextArgs)
    })
  }

  def processNextSteps(args: Args): StepOutput[T] = nextSteps(args)

  /**
   * Create a new operation with a function that takes the result of this operation
   * and returns a new operation.
   */
  def flatMap[U](f: T=>Operation[U]): Operation[U] = new CompositeOperation(this, f)

  /**
   * Create a new operation that returns the result of the provided function that
   * takes this operation's result as its argument.
   */
  def map[U](f: (T)=>U): Operation[U] = logic.MapOp(this)(f)

  /**
   * Create an operation that applies the function f to the result of this operation,
   * but returns nothing.
   */
  def foreach[U](f: (T)=>U): Unit = map { t: T =>
    f(t)
    ()
  }

  def flatten[B](implicit f: T=>Op[B]) = flatMap(f(_))

  /**
   * Create a new operation with a function that takes the result of this operation
   * and returns a new operation.
   *
   * Same as flatMap.
   */
  def withResult[U](f: T=>Operation[U]): Operation[U] = flatMap(f)


  def filter(f: (T) => Boolean) = flatMap { t =>
    if(f(t)) { this } else { FailOp[T]("The operation did not meet the required filter.") }
  }

  def withFilter(f: (T) => Boolean) = filter(f)

  def andThen[U](f: T => Op[U]) = flatMap(f)

  /**
   * Call the given function with this operation as its argument.
   *
   * This is primarily useful for code readability.
   * @see http://debasishg.blogspot.com/2009/09/thrush-combinator-in-scala.html
   */
  def into[U] (f: (Operation[T]) => U): U = f(this)

  def prettyString: String = {
    val sb = new StringBuilder
    sb.append(s"$opId(")
    val arity = this.productArity
    for(i <- 0 until arity) {
      this.productElement(i) match {
        case lit: Literal[_] =>
          sb.append(s"LT{${lit.value}}")
        case op: Operation[_] =>
          sb.append(s"OP{${op.opId}}")
        case x =>
          sb.append(s"$x")
      }
      if(i < arity - 1) { sb.append(",") }
    }
    sb.append(")")
    sb.toString
  }
}


/**
 * Given an operation and a function that takes the result of that operation and returns
 * a new operation, return an operation of the return type of the function.
 *
 * If the initial operation is g, you can think of this operation as f(g(x))
 */
@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
case class CompositeOperation[+T, U](gOp: Op[U], f: (U) => Op[T]) extends Operation[T] {
  def _run() = runAsync('firstOp :: gOp :: Nil)

  val nextSteps: Steps[T] = {
    case 'firstOp :: u :: Nil => runAsync('result :: f(u.asInstanceOf[U]) :: Nil)
    case 'result :: t :: Nil => Result(t.asInstanceOf[T])
  }
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
abstract class OperationWrapper[+T](op: Op[T]) extends Operation[T] {
  def _run() = op._run()
  val nextSteps: Steps[T] = op.nextSteps
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
case class RemoteOperation[+T](val op: Op[T], cluster: Option[ActorRef])
    extends OperationWrapper(op) {}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
object Operation {
  implicit def implicitLiteralVal[A <: AnyVal](a: A)(implicit m: Manifest[A]): Operation[A] = Literal(a)
  implicit def implicitLiteralRef[A <: AnyRef](a: A): Operation[A] = Literal(a)
}

/** Operation that simply fails with the given message */
@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
case class FailOp[T](msg: String) extends Operation[T] {
  def _run() = StepError(msg, "")
  val nextSteps: Steps[T] = { case _ => StepError(msg, "") }
}

/**
 * Below are the Op0 - Op6 abstract classes.
 *
 * These are useful for easily defining operations which just want to evaluate
 * their child operations and then run a single function afterwards.
 *
 * For example:
 *
 * case class Add2(x: Op[Int], y: Op[Int]) extends Op2(x, y)(_ + _)
 */

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
class Op0[T](f: ()=>StepOutput[T]) extends Operation[T] {
  def productArity = 0
  def canEqual(other: Any) = other.isInstanceOf[Op0[_]]
  def productElement(n: Int) = throw new IndexOutOfBoundsException()

  def _run() = f()
  val nextSteps: Steps[T] = {
    case _ => sys.error("should not be called")
  }
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
class Op1[A, T](a: Op[A])(f: (A)=>StepOutput[T]) extends Operation[T] {
  def _run() = runAsync(List(a))

  def productArity = 1
  def canEqual(other: Any) = other.isInstanceOf[Op1[_, _]]
  def productElement(n: Int) = if (n == 0) a else throw new IndexOutOfBoundsException()
  val myNextSteps: PartialFunction[Any, StepOutput[T]] = {
    case a :: Nil => f(a.asInstanceOf[A])
  }
  val nextSteps = myNextSteps
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
class Op2[A, B, T](a: Op[A], b: Op[B]) (f: (A, B)=>StepOutput[T]) extends Operation[T] {
  def productArity = 2
  def canEqual(other: Any) = other.isInstanceOf[Op2[_, _, _]]
  def productElement(n: Int) = n match {
    case 0 => a
    case 1 => b
    case _ => throw new IndexOutOfBoundsException()
  }
  def _run() = runAsync(List(a, b))
  val nextSteps: Steps[T] = {
    case a :: b :: Nil => f(a.asInstanceOf[A], b.asInstanceOf[B])
  }
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
class Op3[A, B, C, T](a: Op[A], b: Op[B], c: Op[C])
(f: (A, B, C)=>StepOutput[T]) extends Operation[T] {
  def productArity = 3
  def canEqual(other: Any) = other.isInstanceOf[Op3[_, _, _, _]]
  def productElement(n: Int) = n match {
    case 0 => a
    case 1 => b
    case 2 => c
    case _ => throw new IndexOutOfBoundsException()
  }
  def _run() = runAsync(List(a, b, c))
  val nextSteps: Steps[T] = {
    case a :: b :: c :: Nil => {
      f(a.asInstanceOf[A], b.asInstanceOf[B], c.asInstanceOf[C])
    }
  }
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
class Op4[A, B, C, D, T](a: Op[A], b: Op[B], c: Op[C], d: Op[D])
(f: (A, B, C, D)=>StepOutput[T]) extends Operation[T] {
  def productArity = 4
  def canEqual(other: Any) = other.isInstanceOf[Op4[_, _, _, _, _]]
  def productElement(n: Int) = n match {
    case 0 => a
    case 1 => b
    case 2 => c
    case 3 => d
    case _ => throw new IndexOutOfBoundsException()
  }
  def _run() = runAsync(List(a, b, c, d))
  val nextSteps: Steps[T] = {
    case a :: b :: c :: d :: Nil => {
      f(a.asInstanceOf[A], b.asInstanceOf[B], c.asInstanceOf[C], d.asInstanceOf[D])
    }
  }

}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
abstract class Op5[A, B, C, D, E, T](a: Op[A], b: Op[B], c: Op[C], d: Op[D], e: Op[E])
(f: (A, B, C, D, E)=>StepOutput[T]) extends Operation[T] {
  def _run() = runAsync(List(a, b, c, d, e))
  val nextSteps: Steps[T] = {
    case a :: b :: c :: d :: e :: Nil => {
      f(a.asInstanceOf[A], b.asInstanceOf[B], c.asInstanceOf[C],
        d.asInstanceOf[D], e.asInstanceOf[E])
    }
  }
}

@deprecated("geotrellis-engine has been deprecated", "Geotrellis Version 0.10")
abstract class Op6[A, B, C, D, E, F, T]
(a: Op[A], b: Op[B], c: Op[C], d: Op[D], e: Op[E], f: Op[F])
(ff: (A, B, C, D, E, F)=>StepOutput[T]) extends Operation[T] {
  def _run() = runAsync(List(a, b, c, d, e, f))
  val nextSteps: Steps[T] = {
    case a :: b :: c :: d :: e :: f :: Nil => {
      ff(a.asInstanceOf[A], b.asInstanceOf[B], c.asInstanceOf[C],
         d.asInstanceOf[D], e.asInstanceOf[E], f.asInstanceOf[F])
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy