class CubbieMaker[-C](make: C => Cubbie)(implicit m1: Manifest[C]) {
CubbieMaker.makers += this
def tryMake[T](toConvert: T)(implicit m2: Manifest[T]): Option[Cubbie] =
if (m2 <:< m1) Some(make(toConvert.asInstanceOf[C])) else None
}
object CubbieMaker {
val makers = new mutable.ArrayBuffer[CubbieMaker[_]]
// just define overriding CubbieMakers here earlier than the less specific versions and they will be found earlier in search through the "makers" list
implicit val modm = new CubbieMaker[Model](new ModelCubbie(_))
implicit val cdm = new CubbieMaker[CategoricalDomain[String]](new CategoricalDomainCubbie(_))
implicit val smm = new CubbieMaker[mutable.HashMap[String, String]](new StringMapCubbie(_))
implicit val csdm = new CubbieMaker[CategoricalSeqDomain[String]](new CategoricalSeqDomainCubbie(_))
implicit val cdtdm = new CubbieMaker[CategoricalDimensionTensorDomain[String]](new CategoricalDimensionTensorDomainCubbie(_))
def cubbieForType[T](toSerialize: T)(implicit m: Manifest[T], evidenceThatWeHaveCubbieMaker: CubbieMaker[T]): Cubbie =
makers.foldLeft(None: Option[Cubbie])((resOpt, maker) => if (resOpt.isDefined) resOpt else maker.tryMake(toSerialize)).get