
datomisca.Attribute.scala Maven / Gradle / Ivy
/*
* Copyright 2012 Pellucid and Zenexity
*
* 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 datomisca
import datomic.Util
/** The representation of Datomic attributes
*
* @constructor construct an attribute out of an ident, valueType,
* cardinality, and other optional components
*/
final case class Attribute[DD, Card <: Cardinality](
override val ident: Keyword,
valueType: SchemaType[DD],
cardinality: Card,
tupleTypes: Seq[SchemaType[_]] = Nil,
tupleAttrs: Seq[Attribute[_,_]] = Nil,
doc: Option[String] = None,
unique: Option[Unique] = None,
index: Option[Boolean] = None,
fulltext: Option[Boolean] = None,
isComponent: Option[Boolean] = None,
noHistory: Option[Boolean] = None
) extends TxData with KeywordIdentified {
/**
* When this attribute is of type [[SchemaType.tuple]] and you wish to create a scalar (heterogeneus) tuple, use
* this method to specify the tuple types.
*
* @see [[https://docs.datomic.com/cloud/schema/schema-reference.html#heterogeneous-tuples]]
* @param ttypes the tuple types in the order that they should exist
* @return a copy of this attribute with the tuple types added in.
*/
def withTupleTypes(ttypes: SchemaType[_] *) = copy(tupleTypes = ttypes)
/**
* When this attribute is of tupe [[SchemaType.tuple]] and you wish to create a composite tuple, use
* this method to specify the linked attributes.
*
* @see [[https://docs.datomic.com/cloud/schema/schema-reference.html#composite-tuples]]
* @param attrs the other attributes that this attribute will be a composite of
* @return a copy of this attribute with the tuple attributes added in.
*/
def withTupleAttrs(attrs: Attribute[_,_] *) = copy(tupleAttrs = attrs)
/** Extend this attribute with a documentation string. */
def withDoc(str: String) = copy( doc = Some(str) )
/** Extend this attribute with a uniqueness constraint. */
def withUnique(u: Unique) = copy( unique = Some(u) )
/** Extend this attribute with an indexing property */
def withIndex(b: Boolean) = copy( index = Some(b) )
/** Extend this attribute with a full text indexing property */
def withFullText(b: Boolean) = copy( fulltext = Some(b) )
/** Extend this attribute with a component relationship constraint. */
def withIsComponent(b: Boolean) = copy( isComponent = Some(b) )
/** Extend this attribute with a no history property */
def withNoHistory(b: Boolean) = copy( noHistory = Some(b) )
/** Construct the reverse attribute, if this is a reference attribute */
def reverse(implicit ev: =:=[DatomicRef.type, DD]): Attribute[DatomicRef.type, Cardinality.many.type] =
copy(
ident = clojure.lang.Keyword.intern(ident.getNamespace, "_" + ident.getName),
valueType = SchemaType.ref,
cardinality = Cardinality.many
)
/** Construct the reverse attribute, if this is a component reference attribute */
def reverseComponent(implicit ev: =:=[DatomicRef.type, DD]): Attribute[DatomicRef.type, Cardinality.one.type] = {
require(isComponent.getOrElse(false))
copy(
ident = clojure.lang.Keyword.intern(ident.getNamespace, "_" + ident.getName),
valueType = SchemaType.ref,
cardinality = Cardinality.one
)
}
// using partiton :db.part/db
val id = DId(Partition.DB)
lazy val toAddOps: AddEntity = {
val mb = scala.collection.mutable.Map.from[Keyword, AnyRef](List(
Attribute.id -> id.toDatomicId,
Attribute.ident -> ident,
Attribute.valueType -> valueType.keyword,
Attribute.cardinality -> cardinality.keyword
))
if(tupleAttrs.nonEmpty) mb += Attribute.tupleAttrs -> Util.list(tupleAttrs.map(_.ident):_*)
if(tupleTypes.nonEmpty) mb += Attribute.tupleTypes -> Util.list(tupleTypes.map(_.keyword):_*)
if(doc.isDefined) mb += Attribute.doc -> doc.get
if(unique.isDefined) mb += Attribute.unique -> unique.get.keyword
if(index.isDefined) mb += Attribute.index -> (index.get: java.lang.Boolean)
if(fulltext.isDefined) mb += Attribute.fulltext -> (fulltext.get: java.lang.Boolean)
if(isComponent.isDefined) mb += Attribute.isComponent -> (isComponent.get: java.lang.Boolean)
if(noHistory.isDefined) mb += Attribute.noHistory -> (noHistory.get: java.lang.Boolean)
// installing attribute
mb += Attribute.installAttr -> Partition.DB.keyword
new AddEntity(id, mb.toMap)
}
override def toTxData: AnyRef = toAddOps.toTxData
/** the keyword ident of the attribute as a string */
override def toString = ident.toString
/** Construct the EDN representation of this attribute */
def toEDNString: String = {
val builder = new StringBuilder(100)
(builder append '{'
append Attribute.id append ' ' append id append ", "
append Attribute.ident append ' ' append ident append ", "
append Attribute.valueType append ' ' append valueType.keyword append ", "
append Attribute.cardinality append ' ' append cardinality.keyword)
if (tupleTypes.nonEmpty) {
builder append s", ${Attribute.tupleTypes} ["
tupleTypes.foreach(t => builder append s" ${t.keyword}")
builder append ']'
}
if (doc.isDefined) (
builder append ", " append Attribute.doc append ' ' append doc.get
)
if (unique.isDefined) (
builder append ", " append Attribute.unique append ' ' append unique.get
)
if (index.isDefined) (
builder append ", " append Attribute.index append ' ' append index.get
)
if (fulltext.isDefined) (
builder append ", " append Attribute.fulltext append ' ' append fulltext.get
)
if (isComponent.isDefined) (
builder append ", " append Attribute.isComponent append ' ' append isComponent.get
)
if (noHistory.isDefined) (
builder append ", " append Attribute.noHistory append ' ' append noHistory.get
)
builder append '}'
builder.result()
}
}
object Attribute {
/** :db/id */
val id = Namespace.DB / "id"
/** :db/ident */
val ident = Namespace.DB / "ident"
/** :db/valueType */
val valueType = Namespace.DB / "valueType"
/** :db/cardinality */
val cardinality = Namespace.DB / "cardinality"
/** :db/tupleTypes */
val tupleTypes = Namespace.DB / "tupleTypes"
/** :db/tupleAttrs */
val tupleAttrs = Namespace.DB / "tupleAttrs"
/** :db/doc */
val doc = Namespace.DB / "doc"
/** :db/unique */
val unique = Namespace.DB / "unique"
/** :db/index */
val index = Namespace.DB / "index"
/** :db/fulltext */
val fulltext = Namespace.DB / "fulltext"
/** :db/isComponent */
val isComponent = Namespace.DB / "isComponent"
/** :db/noHistory */
val noHistory = Namespace.DB / "noHistory"
/** :db.install/_attribute */
val installAttr = Namespace.DB.INSTALL / "_attribute"
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy