Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
lspace.structure.Values.scala Maven / Gradle / Ivy
package lspace.structure
import lspace.datatype.DataType
import lspace.structure.util.ClassTypeable
import monix.eval.Task
import monix.reactive.Observable
import scala.collection.immutable.ListSet
abstract class Values(val graph: Graph) extends RApi[Value[_]] {
import graph._
def apply(): Observable[Value[Any]] = valueStore.all()
def count(): Task[Long] = valueStore.count()
def hasId(id: Long): Task[Option[Value[Any]]] = valueStore.hasId(id)
def cached = new {
def hasId(id: Long): Option[Value[Any]] =
valueStore.cached.hasId(id)
def dereferenceValue(t: Any): Any = t
}
def hasIri(iris: List[String]): Observable[Value[Any]] = {
// println(s"get nodes $iris")
val validIris = iris.distinct.filter(_.nonEmpty)
if (validIris.nonEmpty)
Observable.fromIterable(validIris).flatMap { iri =>
// println(s"get $iri")
valueStore
.hasIri(iri)
.asInstanceOf[Observable[Value[_]]] // println(r.map(_.iri))
} else Observable[Value[_]]()
}
def byValue[T, TOut, CTOut <: ClassType[_]](value: T)(
implicit clsTpbl: ClassTypeable.Aux[T, TOut, CTOut]): Observable[Value[T]] =
valueStore.byValue(value, clsTpbl.ct.asInstanceOf[DataType[T]]).asInstanceOf[Observable[Value[T]]]
def byValue[T](valueSet: List[(T, DataType[T])]): Observable[Value[T]] = {
// val valueList = valueSet.distinct.filter(_ != null)
// if (valueList.nonEmpty) values().filter(v => valueSet.map(_._2).contains(v.value)).toList
// // or(
// // _.has(this.id, p.Within(iriList)),
// // _.has(this.ids, p.Within(iriList))).toSet
// else List[Value[_]]()
Observable.fromIterable(valueSet).flatMap { value =>
valueStore.byValue(value._1, value._2).asInstanceOf[Observable[Value[T]]]
} //distinct
}
def dereferenceValue(t: Any): Task[Any] = t match {
case v: Vector[_] =>
Task.gather[Any, Vector](v.map(dereferenceValue)) //without type parameters it cannot be inferred
case v: ListSet[_] => Task.gather[Any, ListSet](v.map(dereferenceValue))
case v: List[_] => Task.gather[Any, List](v.map(dereferenceValue))
case v: Set[_] => Task.gather[Any, Set](v.map(dereferenceValue))
case v: Map[_, _] =>
Task
.gather(v.toList.map {
case (key, value) =>
for {
a <- dereferenceValue(key)
b <- dereferenceValue(value)
} yield (a, b)
})
.map(_.toMap)
case (v1, v2) =>
for {
a <- dereferenceValue(v1)
b <- dereferenceValue(v2)
} yield (a, b)
case (v1, v2, v3) =>
for {
a <- dereferenceValue(v1)
b <- dereferenceValue(v2)
c <- dereferenceValue(v3)
} yield (a, b, c)
case (v1, v2, v3, v4) =>
for {
a <- dereferenceValue(v1)
b <- dereferenceValue(v2)
c <- dereferenceValue(v3)
d <- dereferenceValue(v4)
} yield (a, b, c, d)
case (v1, v2, v3, v4, v5) =>
for {
a <- dereferenceValue(v1)
b <- dereferenceValue(v2)
c <- dereferenceValue(v3)
d <- dereferenceValue(v4)
e <- dereferenceValue(v5)
} yield (a, b, c, d, e)
case v: Ontology => nodes.upsert(v.iri, Ontology.ontology) //ns.ontologies.store(v))
case v: Property => nodes.upsert(v.iri, Property.ontology) //(ns.properties.store(v))
case v: DataType[_] => nodes.upsert(v.iri, DataType.ontology) //ns.datatypes.store(v))
case v: Node => nodes.upsert(v)
case v: Edge[_, _] => edges.upsert(v)
case v: Value[_] => values.upsert(v)
case _ => Task.now(t)
}
final def create[T, TOut, CTOut <: ClassType[_]](value: T)(
implicit clsTpbl: ClassTypeable.Aux[T, TOut, CTOut]): Task[Value[T]] = { //add implicit DataType[T]
byValue(value).headOptionL.flatMap(_.map(_.asInstanceOf[_Value[T]]).map(Task.now).getOrElse {
for {
dereferencedValue <- dereferenceValue(value).map(_.asInstanceOf[T])
b <- byValue(dereferencedValue)(clsTpbl).headOptionL
.flatMap(_.map(_.asInstanceOf[_Value[T]]).map(Task.now).getOrElse {
for {
id <- idProvider.next
value <- createValue(id, dereferencedValue, ClassType.valueToOntologyResource(dereferencedValue))
} yield value
})
} yield b
})
}
final def create[T](value: T, dt: DataType[T]): Task[Value[T]] = { //add implicit DataType[T]
val detectedDT = ClassType.valueToOntologyResource(value)
val finalDT = if (detectedDT.`@extends`(dt)) detectedDT else dt
for {
dereferencedValue <- dereferenceValue(value).map(_.asInstanceOf[T])
b <- byValue(dereferencedValue -> finalDT :: Nil).headOptionL
.flatMap(_.map(_.asInstanceOf[_Value[T]]).map(Task.now).getOrElse {
for {
id <- idProvider.next
value <- createValue(id, dereferencedValue, finalDT)
} yield value
})
} yield { b }
}
def upsert[V, TOut, CTOut <: ClassType[_]](value: V)(
implicit clsTpbl: ClassTypeable.Aux[V, TOut, CTOut]): Task[Value[V]] = {
byValue(value).toListL.flatMap {
case Nil => create(value)
case List(value) => Task.now(value)
case values =>
mergeValues(values.toSet)
}
}
final def upsert[V](value: V, dt: DataType[V]): Task[Value[V]] = {
// val values = byValue(List(value -> dt))
// values.headOptionL.flatMap(_.map(Task.now).getOrElse(create(value, dt)))
byValue(List(value -> dt)).toListL.flatMap {
case Nil => create(value, dt)
case List(value) => Task.now(value)
case values =>
mergeValues(values.toSet)
}
// val _value: Value[V] = if (values.isEmpty) {
// create(value, dt)
//// } else if (values.size > 1) {
//// GraphUtils.mergeValues(values.toSet)
// } else values.head
// _value
}
final def upsert[V](value: Value[V]): Task[Value[V]] = {
if (value.graph != this) {
upsert(value.value, value.label)
} else Task.now(value)
}
/**
* adds a value to the graph including all edges and (meta) edges on edges as long as edges have edges
* @param value
* @tparam V
* @return
*/
def post[V](value: Value[V]): Task[Value[V]] = {
if (value.graph != this) {
hasIri(value.iri).toListL
.flatMap {
case List() => create(value.value, value.label)
case List(storedValue: Value[_]) if storedValue.value == value.value =>
Task.now(storedValue.asInstanceOf[Value[V]])
case List(value: Value[_], _*) =>
Task.raiseError(new Exception("multiple values with the same iri, what should we do?! Dedup?"))
}
.flatMap { newValue =>
for { u <- addMeta(value, newValue) } yield newValue
}
} else Task.now(value)
}
final def delete(value: Value[_]): Task[Unit] = value match {
case value: _Value[_] => deleteValue(value.asInstanceOf[_Value[_]])
case _ => Task.unit //LOG???
}
/**
* adds a value
* @param value
* @tparam V
* @return
*/
final def +[V](value: Value[V]): Task[Value[V]] = upsert(value)
/**
* deletes a value
* @param value
*/
final def -(value: Value[_]): Task[Unit] = delete(value)
/**
* adds a value and meta-properties (value.outE())
* @param value
* @tparam V
* @return
*/
final def ++[V](value: Value[V]): Task[Value[V]] = post(value)
}