app/mxscopy/models/MxsMetadata.scala (56 lines of code) (raw):
package mxscopy.models
import java.time.{Instant, LocalDateTime, ZoneOffset, ZonedDateTime}
import com.om.mxs.client.japi.Attribute
import org.slf4j.LoggerFactory
case class MxsMetadata (stringValues:Map[String,String], boolValues:Map[String,Boolean], longValues:Map[String,Long], intValues:Map[String,Int]) {
private val logger = LoggerFactory.getLogger(getClass)
/**
* Converts the data to a Seq[com.om.mxs.client.japi.Attribute], suitable for passing to ObjectMatrix API calls
* @return Sequence of Attributes.
*/
def toAttributes:Seq[Attribute] = {
stringValues.map(entry=>
Option(entry._2).map(realValue=>Attribute.createTextAttribute(entry._1,realValue,true))
).toSeq.collect({case Some(attrib)=>attrib}) ++
boolValues.map(entry=>new Attribute(entry._1,entry._2,true)) ++
longValues
.filterNot(entry=>MxsMetadata.disallowedWriteLongs.contains(entry._1)) //make sure we filter out internal fields
.map(entry=>new Attribute(entry._1, entry._2, true)) ++
intValues
.filterNot(entry=>MxsMetadata.disallowedWriteInts.contains(entry._1))
.map(entry=>new Attribute(entry._1, entry._2, true))
}
/**
* Convenience function to set a string value. Internally calls `withValue`.
* @param key Key to set
* @param value String value to set it to
* @return An updated [[MxsMetadata]] object
*/
def withString(key:String, value:String):MxsMetadata = {
withValue[String](key,value)
}
/**
* Sets the given value for the given key and returns an updated [[MxsMetadata]] object.
* If the type of `value` is not supported, then it emits a warning and returns the original [[MxsMetadata]]
* @param key Key to identify the metadata
* @param value Value to set. This must be either Boolean, String, Int, Long or ZonedDateTime. ZonedDateTime is converted
* to epoch millisenconds and stored as a long
* @tparam T The data type of `value`. Normally the compiler can infer this from the argument
* @return An updated [[MxsMetadata]] object
*/
def withValue[T](key:String, value:T):MxsMetadata = {
value match {
case boolValue:Boolean=>this.copy(boolValues = this.boolValues ++ Map(key->boolValue))
case stringValue:String=>this.copy(stringValues = this.stringValues ++ Map(key->stringValue))
case intValue:Int=>this.copy(intValues = this.intValues ++ Map(key->intValue))
case longValue:Long=>this.copy(longValues = this.longValues ++ Map(key->longValue))
case timeValue:ZonedDateTime=>this.copy(longValues = this.longValues ++ Map(key->timeValue.toInstant.toEpochMilli))
case timeValue:LocalDateTime=>this.copy(longValues = this.longValues ++ Map(key->timeValue.toInstant(ZoneOffset.UTC).toEpochMilli))
case instant:Instant=>this.copy(longValues = this.longValues ++ Map(key->instant.toEpochMilli))
case _=>
logger.warn(s"Could not set key $key to value $value (type ${value.getClass.toGenericString}), type not recognised")
this
}
}
/**
* Merge this metadata with another one. If the case of conflicts, the other instances metadata takes priority
* @param other Another MxsMetadata object to merge with
*/
def merge(other:MxsMetadata) = {
this.copy(
stringValues=stringValues++other.stringValues,
boolValues=boolValues++other.boolValues,
longValues=longValues++other.longValues,
intValues=intValues++other.intValues
)
}
}
object MxsMetadata {
def apply(stringValues: Map[String, String], boolValues: Map[String, Boolean], longValues: Map[String, Long], intValues: Map[String, Int]): MxsMetadata = new MxsMetadata(stringValues, boolValues, longValues, intValues)
def empty = new MxsMetadata(Map(),Map(),Map(),Map())
/**
* A client is not allowed to write to any of these fields on the MatrixStore
*/
val disallowedWriteLongs = Seq(
"MXFS_ARCHIVE_TIME",
)
val disallowedWriteInts = Seq(
"MXFS_ARCHYEAR",
"MXFS_ARCHMONTH",
"MXFS_ARCHDAY"
)
}