-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix all test errors caused by lack of ordering
- Loading branch information
Showing
40 changed files
with
808 additions
and
777 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
parent/commons/src/main/scala/com/tribbloids/spookystuff/utils/data/AttrLike.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.tribbloids.spookystuff.utils.data | ||
|
||
import ai.acyclic.prover.commons.same.EqualBy | ||
import org.apache.spark.ml.dsl.utils.? | ||
|
||
import scala.util.Try | ||
|
||
trait AttrLike[T] extends Serializable with EqualBy { | ||
|
||
def name: String | ||
def aliases: List[String] | ||
|
||
final lazy val allNames: Seq[String] = (Seq(name) ++ aliases).distinct | ||
|
||
def ->(v: T): Magnets.AttrValueMag[T] = { | ||
|
||
Magnets.AttrValueMag[T](this.name, Some(v)) | ||
} | ||
|
||
def -?>(vOpt: T `?` _): Magnets.AttrValueMag[T] = { | ||
|
||
Magnets.AttrValueMag[T](this.name, vOpt.asOption) | ||
} | ||
|
||
def tryGet: Try[T] | ||
|
||
final def get: Option[T] = tryGet.toOption | ||
final def value: T = tryGet.get | ||
|
||
override def samenessDelegatedTo: Any = this.allNames -> get | ||
} | ||
|
||
object AttrLike { | ||
|
||
// implicit def toV[T](attr: AttrLike[T]): T = attr.value | ||
} |
237 changes: 237 additions & 0 deletions
237
parent/commons/src/main/scala/com/tribbloids/spookystuff/utils/data/EAVLike.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
package com.tribbloids.spookystuff.utils.data | ||
|
||
import ai.acyclic.prover.commons.same.EqualBy | ||
import com.tribbloids.spookystuff.relay.RootTagged | ||
import com.tribbloids.spookystuff.relay.xml.Xml | ||
import com.tribbloids.spookystuff.utils.{CommonUtils, TreeThrowable} | ||
import org.apache.spark.ml.dsl.utils.{?, HasEagerInnerObjects} | ||
|
||
import java.util.Properties | ||
import scala.collection.mutable | ||
import scala.collection.mutable.ArrayBuffer | ||
import scala.language.implicitConversions | ||
import scala.util.Try | ||
|
||
/** | ||
* entity-(with)-attribute-value | ||
*/ | ||
trait EAVLike extends HasEagerInnerObjects with EqualBy with RootTagged with Serializable { | ||
|
||
def internal: collection.Map[String, Any] | ||
|
||
def system: EAVSystem | ||
|
||
override def rootTag: String = Xml.ROOT | ||
|
||
protected def getLookup: Map[String, Any] = internal.toMap | ||
@transient final lazy val lookup = getLookup | ||
|
||
@transient private lazy val providedHintStr: Option[String] = { | ||
if (lookup.isEmpty) { | ||
None | ||
} else { | ||
Some(s"only ${KVs.raw.map(_._1).mkString(", ")} are provided") | ||
} | ||
} | ||
|
||
def tryGet(k: String, nullable: Boolean = false): Try[Any] = Try { | ||
val result = lookup.getOrElse( | ||
k, | ||
throw new UnsupportedOperationException( | ||
( | ||
Seq( | ||
s"Parameter $k is missing" | ||
) ++ providedHintStr | ||
).mkString("\n") | ||
) | ||
) | ||
if (!nullable) require(result != null, s"null value for `$k`") | ||
result | ||
} | ||
|
||
def get(k: String, nullable: Boolean = false): Option[Any] = tryGet(k, nullable).toOption | ||
|
||
def contains(k: String): Boolean = tryGet(k).isSuccess | ||
|
||
override def toString: String = KVs.raw.mkString("[", ", ", "]") | ||
|
||
/** | ||
* by default, declared [[Attr]] will be listed in their order of declaration, then non-declared KVs ordered by keys | ||
*/ | ||
@transient object KVs { | ||
|
||
requireInitialised() | ||
|
||
lazy val raw: Seq[(String, Any)] = internal.toSeq.sortBy(_._1) | ||
|
||
lazy val (declared: Vector[(String, Option[Any])], others: Vector[(String, Option[Any])]) = { | ||
|
||
var map = lookup | ||
|
||
val declared = Attr.declared.toVector.map { attr => | ||
attr.allNames.foreach { name => | ||
map = map.removed(name) | ||
} | ||
attr.name -> attr.get | ||
} | ||
|
||
val others = map.keys.toVector.sorted.map { k => | ||
k -> lookup.get(k) | ||
} | ||
|
||
declared -> others | ||
} | ||
|
||
lazy val all: Vector[(String, Option[Any])] = declared ++ others | ||
|
||
lazy val defined: Vector[(String, Any)] = { | ||
all | ||
.collect { | ||
case (k, Some(v)) => k -> v | ||
} | ||
} | ||
} | ||
|
||
@transient protected lazy val sortEvidence: Seq[String] = { | ||
|
||
val result = KVs.declared.map(v => v._2.map(_.toString).orNull) | ||
result | ||
} | ||
override def samenessDelegatedTo: Any = sortEvidence | ||
|
||
@transient lazy val asProperties: Properties = { | ||
val properties = new Properties() | ||
|
||
KVs.defined | ||
.foreach { v => | ||
properties.put(v._1, v._2) | ||
} | ||
|
||
properties | ||
} | ||
|
||
// def attr(v: String): Attr[Any] = new Attr[Any](primaryNameOverride = v) | ||
|
||
@transient object Attr { | ||
|
||
lazy val declared: ArrayBuffer[Attr[_]] = ArrayBuffer.empty | ||
|
||
lazy val nameToAttrMap: mutable.Map[String, Attr[_]] = mutable.Map.empty | ||
|
||
def +=(v: Attr[_]): Unit = { | ||
declared += v | ||
v.allNames.foreach { name => | ||
nameToAttrMap.updateWith(name) { | ||
case Some(existing) => | ||
throw new UnsupportedOperationException(s"Attribute $name is already defined in ${existing}") | ||
case None => | ||
Some(v) | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
trait Accessor[T] { | ||
|
||
protected def compute: T | ||
private lazy val get: T = compute | ||
|
||
def tryGet: Try[T] = Try(get) | ||
} | ||
|
||
abstract class Attr[T]( // has to be declared in the EAVLike | ||
// should only be used in setters | ||
val aliases: List[String] = Nil, | ||
nullable: Boolean = false, | ||
default: T `?` _ = None, | ||
nameOverride: String `?` _ = None | ||
)( | ||
implicit | ||
ev: T <:< Any | ||
) extends AttrLike[T] | ||
with EagerInnerObject | ||
with Accessor[T] | ||
with Product { | ||
|
||
{ | ||
Attr.declared += this | ||
} | ||
|
||
override def toString: String = { | ||
throw new UnsupportedOperationException( | ||
"Attribute cannot be used as string, please use primaryName or value instead" | ||
) | ||
} | ||
|
||
def outer: EAVLike = EAVLike.this | ||
|
||
final def name: String = nameOverride.getOrElse(productPrefix) | ||
|
||
override def compute: T = { | ||
|
||
val getExplicits: Seq[() => T] = allNames.map { name => | ||
{ () => | ||
outer.tryGet(name, nullable).get.asInstanceOf[T] | ||
} | ||
} | ||
|
||
val getDefault = { () => | ||
default.getOrElse { | ||
throw new UnsupportedOperationException(s"Undefined default value for $name") | ||
} | ||
} | ||
|
||
TreeThrowable | ||
.|||^(getExplicits :+ getDefault) | ||
.get | ||
|
||
} | ||
|
||
case class asEnum[EE <: Enumeration](enum: EE)( | ||
implicit | ||
ev: T <:< String | ||
) extends Accessor[EE#Value] { | ||
|
||
override protected def compute: EE#Value = { | ||
|
||
val v = Attr.this.value | ||
|
||
val result = enum.withName(ev(v)) | ||
|
||
result | ||
} | ||
} | ||
|
||
case class asBool()( | ||
implicit | ||
ev: T <:< String | ||
) extends Accessor[Boolean] { | ||
|
||
override protected def compute: Boolean = { | ||
|
||
val v = Attr.this.value | ||
|
||
CommonUtils.tryParseBoolean(v).get | ||
} | ||
} | ||
|
||
case class asInt()( | ||
implicit | ||
ev: T <:< String | ||
) extends Accessor[Int] { | ||
|
||
override protected def compute: Int = { | ||
|
||
val v = Attr.this.value | ||
|
||
ev(v).toInt | ||
} | ||
} | ||
} | ||
} | ||
|
||
object EAVLike { | ||
|
||
implicit def toOps[T <: EAVLike](v: T): EAVOps[T] = EAVOps(v)(v.system.asInstanceOf[EAVSystem.Aux[T]]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.