From 68ad5a8c3c6fa872febbf2f5e7f1826d7b5ccc0c Mon Sep 17 00:00:00 2001 From: Matthew Tovbin Date: Wed, 15 Aug 2018 10:48:16 -0700 Subject: [PATCH] Match feature type map hierarchy with regular feature types (#49) --- .../salesforce/op/features/types/Maps.scala | 50 +++--- .../salesforce/op/features/types/OPMap.scala | 13 ++ .../op/features/types/package.scala | 4 + .../op/features/types/ListTest.scala | 25 +-- .../op/features/types/MapTest.scala | 163 ++++++++++++++++-- .../op/features/types/PredictionTest.scala | 3 + 6 files changed, 206 insertions(+), 52 deletions(-) diff --git a/features/src/main/scala/com/salesforce/op/features/types/Maps.scala b/features/src/main/scala/com/salesforce/op/features/types/Maps.scala index 4834f64815..bc3e72b7f7 100644 --- a/features/src/main/scala/com/salesforce/op/features/types/Maps.scala +++ b/features/src/main/scala/com/salesforce/op/features/types/Maps.scala @@ -30,7 +30,7 @@ package com.salesforce.op.features.types -import org.apache.spark.ml.linalg.{Vector, Vectors} +import org.apache.spark.ml.linalg.Vector /** * Map of text values @@ -48,7 +48,7 @@ object TextMap { * * @param value map of email values */ -class EmailMap(val value: Map[String, String]) extends OPMap[String] +class EmailMap(value: Map[String, String]) extends TextMap(value) object EmailMap { def apply(value: Map[String, String]): EmailMap = new EmailMap(value) def empty: EmailMap = FeatureTypeDefaults.EmailMap @@ -59,7 +59,7 @@ object EmailMap { * * @param value map of base64 binary encoded values */ -class Base64Map(val value: Map[String, String]) extends OPMap[String] +class Base64Map(value: Map[String, String]) extends TextMap(value) object Base64Map { def apply(value: Map[String, String]): Base64Map = new Base64Map(value) def empty: Base64Map = FeatureTypeDefaults.Base64Map @@ -70,7 +70,7 @@ object Base64Map { * * @param value map of phone values */ -class PhoneMap(val value: Map[String, String]) extends OPMap[String] +class PhoneMap(value: Map[String, String]) extends TextMap(value) object PhoneMap { def apply(value: Map[String, String]): PhoneMap = new PhoneMap(value) def empty: PhoneMap = FeatureTypeDefaults.PhoneMap @@ -81,7 +81,7 @@ object PhoneMap { * * @param value map of ID values */ -class IDMap(val value: Map[String, String]) extends OPMap[String] +class IDMap(value: Map[String, String]) extends TextMap(value) object IDMap { def apply(value: Map[String, String]): IDMap = new IDMap(value) def empty: IDMap = FeatureTypeDefaults.IDMap @@ -92,7 +92,7 @@ object IDMap { * * @param value map of URL values */ -class URLMap(val value: Map[String, String]) extends OPMap[String] +class URLMap(value: Map[String, String]) extends TextMap(value) object URLMap { def apply(value: Map[String, String]): URLMap = new URLMap(value) def empty: URLMap = FeatureTypeDefaults.URLMap @@ -103,7 +103,7 @@ object URLMap { * * @param value map of text area values */ -class TextAreaMap(val value: Map[String, String]) extends OPMap[String] +class TextAreaMap(value: Map[String, String]) extends TextMap(value) object TextAreaMap { def apply(value: Map[String, String]): TextAreaMap = new TextAreaMap(value) def empty: TextAreaMap = FeatureTypeDefaults.TextAreaMap @@ -114,7 +114,7 @@ object TextAreaMap { * * @param value map of picklist values */ -class PickListMap(val value: Map[String, String]) extends OPMap[String] +class PickListMap(value: Map[String, String]) extends TextMap(value) with SingleResponse object PickListMap { def apply(value: Map[String, String]): PickListMap = new PickListMap(value) def empty: PickListMap = FeatureTypeDefaults.PickListMap @@ -125,7 +125,7 @@ object PickListMap { * * @param value map of combobox values */ -class ComboBoxMap(val value: Map[String, String]) extends OPMap[String] +class ComboBoxMap(value: Map[String, String]) extends TextMap(value) object ComboBoxMap { def apply(value: Map[String, String]): ComboBoxMap = new ComboBoxMap(value) def empty: ComboBoxMap = FeatureTypeDefaults.ComboBoxMap @@ -136,7 +136,9 @@ object ComboBoxMap { * * @param value map of binary values */ -class BinaryMap(val value: Map[String, Boolean]) extends OPMap[Boolean] +class BinaryMap(val value: Map[String, Boolean]) extends OPMap[Boolean] with NumericMap with SingleResponse { + def toDoubleMap: Map[String, Double] = value +} object BinaryMap { def apply(value: Map[String, Boolean]): BinaryMap = new BinaryMap(value) def empty: BinaryMap = FeatureTypeDefaults.BinaryMap @@ -147,7 +149,9 @@ object BinaryMap { * * @param value map of integral values */ -class IntegralMap(val value: Map[String, Long]) extends OPMap[Long] +class IntegralMap(val value: Map[String, Long]) extends OPMap[Long] with NumericMap { + def toDoubleMap: Map[String, Double] = value +} object IntegralMap { def apply(value: Map[String, Long]): IntegralMap = new IntegralMap(value) def empty: IntegralMap = FeatureTypeDefaults.IntegralMap @@ -158,7 +162,9 @@ object IntegralMap { * * @param value map of real values */ -class RealMap(val value: Map[String, Double]) extends OPMap[Double] +class RealMap(val value: Map[String, Double]) extends OPMap[Double] with NumericMap { + def toDoubleMap: Map[String, Double] = value +} object RealMap { def apply(value: Map[String, Double]): RealMap = new RealMap(value) def empty: RealMap = FeatureTypeDefaults.RealMap @@ -169,7 +175,7 @@ object RealMap { * * @param value map of percent values */ -class PercentMap(val value: Map[String, Double]) extends OPMap[Double] +class PercentMap(value: Map[String, Double]) extends RealMap(value) object PercentMap { def apply(value: Map[String, Double]): PercentMap = new PercentMap(value) def empty: PercentMap = FeatureTypeDefaults.PercentMap @@ -180,7 +186,7 @@ object PercentMap { * * @param value map of currency values */ -class CurrencyMap(val value: Map[String, Double]) extends OPMap[Double] +class CurrencyMap(value: Map[String, Double]) extends RealMap(value) object CurrencyMap { def apply(value: Map[String, Double]): CurrencyMap = new CurrencyMap(value) def empty: CurrencyMap = FeatureTypeDefaults.CurrencyMap @@ -191,7 +197,7 @@ object CurrencyMap { * * @param value map of date values */ -class DateMap(val value: Map[String, Long]) extends OPMap[Long] +class DateMap(value: Map[String, Long]) extends IntegralMap(value) object DateMap { def apply(value: Map[String, Long]): DateMap = new DateMap(value) def empty: DateMap = FeatureTypeDefaults.DateMap @@ -202,7 +208,7 @@ object DateMap { * * @param value map of date & time values */ -class DateTimeMap(val value: Map[String, Long]) extends OPMap[Long] +class DateTimeMap(value: Map[String, Long]) extends DateMap(value) object DateTimeMap { def apply(value: Map[String, Long]): DateTimeMap = new DateTimeMap(value) def empty: DateTimeMap = FeatureTypeDefaults.DateTimeMap @@ -213,7 +219,7 @@ object DateTimeMap { * * @param value map of multi picklist values */ -class MultiPickListMap(val value: Map[String, Set[String]]) extends OPMap[Set[String]] +class MultiPickListMap(val value: Map[String, Set[String]]) extends OPMap[Set[String]] with MultiResponse object MultiPickListMap { def apply(value: Map[String, Set[String]]): MultiPickListMap = new MultiPickListMap(value) def empty: MultiPickListMap = FeatureTypeDefaults.MultiPickListMap @@ -224,7 +230,7 @@ object MultiPickListMap { * * @param value map of country values */ -class CountryMap(val value: Map[String, String]) extends OPMap[String] with Location +class CountryMap(value: Map[String, String]) extends TextMap(value) with Location object CountryMap { def apply(value: Map[String, String]): CountryMap = new CountryMap(value) def empty: CountryMap = FeatureTypeDefaults.CountryMap @@ -235,7 +241,7 @@ object CountryMap { * * @param value map of state values */ -class StateMap(val value: Map[String, String]) extends OPMap[String] with Location +class StateMap(value: Map[String, String]) extends TextMap(value) with Location object StateMap { def apply(value: Map[String, String]): StateMap = new StateMap(value) def empty: StateMap = FeatureTypeDefaults.StateMap @@ -246,7 +252,7 @@ object StateMap { * * @param value map of city values */ -class CityMap(val value: Map[String, String]) extends OPMap[String] with Location +class CityMap(value: Map[String, String]) extends TextMap(value) with Location object CityMap { def apply(value: Map[String, String]): CityMap = new CityMap(value) def empty: CityMap = FeatureTypeDefaults.CityMap @@ -257,7 +263,7 @@ object CityMap { * * @param value map of postal code values */ -class PostalCodeMap(val value: Map[String, String]) extends OPMap[String] with Location +class PostalCodeMap(value: Map[String, String]) extends TextMap(value) with Location object PostalCodeMap { def apply(value: Map[String, String]): PostalCodeMap = new PostalCodeMap(value) def empty: PostalCodeMap = FeatureTypeDefaults.PostalCodeMap @@ -268,7 +274,7 @@ object PostalCodeMap { * * @param value map of street values */ -class StreetMap(val value: Map[String, String]) extends OPMap[String] with Location +class StreetMap(value: Map[String, String]) extends TextMap(value) with Location object StreetMap { def apply(value: Map[String, String]): StreetMap = new StreetMap(value) def empty: StreetMap = FeatureTypeDefaults.StreetMap diff --git a/features/src/main/scala/com/salesforce/op/features/types/OPMap.scala b/features/src/main/scala/com/salesforce/op/features/types/OPMap.scala index d8dd84c8b8..3194fab15d 100644 --- a/features/src/main/scala/com/salesforce/op/features/types/OPMap.scala +++ b/features/src/main/scala/com/salesforce/op/features/types/OPMap.scala @@ -41,5 +41,18 @@ abstract class OPMap[A] extends OPCollection { override type Value = Map[String, A] final def isEmpty: Boolean = value.isEmpty +} + +/** + * Numeric Map mixin + */ +trait NumericMap { + self: OPMap[_] => + /** + * Convert map of numeric values to map of [[Double]] values + * + * @return map of [[Double]] values + */ + def toDoubleMap: Map[String, Double] } diff --git a/features/src/main/scala/com/salesforce/op/features/types/package.scala b/features/src/main/scala/com/salesforce/op/features/types/package.scala index 16972e8d56..0d367ca72b 100644 --- a/features/src/main/scala/com/salesforce/op/features/types/package.scala +++ b/features/src/main/scala/com/salesforce/op/features/types/package.scala @@ -235,9 +235,13 @@ package object types extends FeatureTypeSparkConverters { } implicit class MapLongConversions(val v: Map[String, Long]) extends AnyVal { def toIntegralMap: IntegralMap = new IntegralMap(v) + def toDateMap: DateMap = new DateMap(v) + def toDateTimeMap: DateTimeMap = new DateTimeMap(v) } implicit class MapDoubleConversions(val v: Map[String, Double]) extends AnyVal { def toRealMap: RealMap = new RealMap(v) + def toPercentMap: PercentMap = new PercentMap(v) + def toCurrencyMap: CurrencyMap = new CurrencyMap(v) def toPrediction: Prediction = new Prediction(v) } implicit class MapBooleanConversions(val v: Map[String, Boolean]) extends AnyVal { diff --git a/features/src/test/scala/com/salesforce/op/features/types/ListTest.scala b/features/src/test/scala/com/salesforce/op/features/types/ListTest.scala index c54d2361ee..6a8fe4d8a0 100644 --- a/features/src/test/scala/com/salesforce/op/features/types/ListTest.scala +++ b/features/src/test/scala/com/salesforce/op/features/types/ListTest.scala @@ -48,10 +48,10 @@ class ListTest extends FlatSpec with TestCommon { myTextList shouldBe a[OPList[_]] } it should "compare values correctly" in { - new TextList(List("Hello", "Bye")).equals(new TextList(List("Hello", "Bye"))) shouldBe true - new TextList(List("Bye", "Hello")).equals(new TextList(List("Hello", "Bye"))) shouldBe false - FeatureTypeDefaults.TextList.equals(new TextList(List("Hello", "Bye"))) shouldBe false - FeatureTypeDefaults.TextList.equals(TextList(List.empty[String])) shouldBe true + new TextList(List("Hello", "Bye")) shouldBe new TextList(List("Hello", "Bye")) + new TextList(List("Bye", "Hello")) should not be new TextList(List("Hello", "Bye")) + FeatureTypeDefaults.TextList should not be new TextList(List("Hello", "Bye")) + FeatureTypeDefaults.TextList shouldBe TextList(List.empty[String]) List("Goodbye", "world").toTextList shouldBe a[TextList] } @@ -64,10 +64,10 @@ class ListTest extends FlatSpec with TestCommon { myDateList shouldBe a[OPList[_]] } it should "compare values correctly" in { - new DateList(List(456L, 13L)).equals(new DateList(List(456L, 13L))) shouldBe true - new DateList(List(13L, 456L)).equals(new DateList(List(456L, 13L))) shouldBe false - FeatureTypeDefaults.DateList.equals(new DateList(List(456L, 13L))) shouldBe false - FeatureTypeDefaults.DateList.equals(DateList(List.empty[Long])) shouldBe true + new DateList(List(456L, 13L)) shouldBe new DateList(List(456L, 13L)) + new DateList(List(13L, 456L)) should not be new DateList(List(456L, 13L)) + FeatureTypeDefaults.DateList should not be new DateList(List(456L, 13L)) + FeatureTypeDefaults.DateList shouldBe new DateList(List.empty[Long]) List(44829L, 389093L).toDateList shouldBe a[DateList] } @@ -78,12 +78,13 @@ class ListTest extends FlatSpec with TestCommon { myDateTimeList shouldBe a[FeatureType] myDateTimeList shouldBe a[OPCollection] myDateTimeList shouldBe a[OPList[_]] + myDateTimeList shouldBe a[DateList] } it should "compare values correctly" in { - new DateTimeList(List(456L, 13L)).equals(new DateTimeList(List(456L, 13L))) shouldBe true - new DateTimeList(List(13L, 456L)).equals(new DateTimeList(List(456L, 13L))) shouldBe false - FeatureTypeDefaults.DateTimeList.equals(new DateTimeList(List(456L, 13L))) shouldBe false - FeatureTypeDefaults.DateTimeList.equals(DateTimeList(List.empty[Long])) shouldBe true + new DateTimeList(List(456L, 13L)) shouldBe new DateTimeList(List(456L, 13L)) + new DateTimeList(List(13L, 456L)) should not be new DateTimeList(List(456L, 13L)) + FeatureTypeDefaults.DateTimeList should not be new DateTimeList(List(456L, 13L)) + FeatureTypeDefaults.DateTimeList shouldBe DateTimeList(List.empty[Long]) List(12237834L, 4890489839L).toDateTimeList shouldBe a[DateTimeList] } diff --git a/features/src/test/scala/com/salesforce/op/features/types/MapTest.scala b/features/src/test/scala/com/salesforce/op/features/types/MapTest.scala index e74bf9479c..7d87b7fa55 100644 --- a/features/src/test/scala/com/salesforce/op/features/types/MapTest.scala +++ b/features/src/test/scala/com/salesforce/op/features/types/MapTest.scala @@ -41,158 +41,172 @@ import scala.reflect.runtime.universe._ class MapTest extends FlatSpec with TestCommon { /* TextMap tests */ - Spec[TextMap] should "extend OPMap[_]" in { + Spec[TextMap] should "extend correct base classes and have a working shortcut" in { val myTextMap = new TextMap(Map.empty[String, String]) myTextMap shouldBe a[FeatureType] myTextMap shouldBe a[OPCollection] myTextMap shouldBe a[OPMap[_]] + + Map("aaa" -> "bbb").toTextMap shouldBe a[TextMap] } it should "compare values correctly" in { new TextMap(Map("Hello" -> "Bye")).equals(new TextMap(Map("Hello" -> "Bye"))) shouldBe true new TextMap(Map("Bye" -> "Hello")).equals(new TextMap(Map("Hello" -> "Bye"))) shouldBe false FeatureTypeDefaults.TextMap.equals(new TextMap(Map("Hello" -> "Bye"))) shouldBe false FeatureTypeDefaults.TextMap.equals(TextMap(Map.empty[String, String])) shouldBe true - - Map("Hello" -> "Good Day").toTextMap shouldBe a[TextMap] } /* EmailMap tests */ - Spec[EmailMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[EmailMap] should "extend correct base classes and have a working shortcut" in { val myEmailMap = new EmailMap(Map.empty[String, String]) myEmailMap shouldBe a[FeatureType] myEmailMap shouldBe a[OPCollection] myEmailMap shouldBe a[OPMap[_]] + myEmailMap shouldBe a[TextMap] Map("aaa" -> "bbb").toEmailMap shouldBe a[EmailMap] } /* Base64Map tests */ - Spec[Base64Map] should "extend OPMap[_], and have a working shortcut" in { + Spec[Base64Map] should "extend correct base classes and have a working shortcut" in { val myBase64Map = new Base64Map(Map.empty[String, String]) myBase64Map shouldBe a[FeatureType] myBase64Map shouldBe a[OPCollection] myBase64Map shouldBe a[OPMap[_]] + myBase64Map shouldBe a[TextMap] Map("aaa" -> "bbb").toBase64Map shouldBe a[Base64Map] } /* PhoneMap tests */ - Spec[PhoneMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[PhoneMap] should "extend correct base classes and have a working shortcut" in { val myPhoneMap = new PhoneMap(Map.empty[String, String]) myPhoneMap shouldBe a[FeatureType] myPhoneMap shouldBe a[OPCollection] myPhoneMap shouldBe a[OPMap[_]] + myPhoneMap shouldBe a[TextMap] Map("aaa" -> "bbb").toPhoneMap shouldBe a[PhoneMap] } /* IDMap tests */ - Spec[IDMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[IDMap] should "extend correct base classes and have a working shortcut" in { val myIDMap = new IDMap(Map.empty[String, String]) myIDMap shouldBe a[FeatureType] myIDMap shouldBe a[OPCollection] myIDMap shouldBe a[OPMap[_]] + myIDMap shouldBe a[TextMap] Map("aaa" -> "bbb").toIDMap shouldBe a[IDMap] } /* URLMap tests */ - Spec[URLMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[URLMap] should "extend correct base classes and have a working shortcut" in { val myURLMap = new URLMap(Map.empty[String, String]) myURLMap shouldBe a[FeatureType] myURLMap shouldBe a[OPCollection] myURLMap shouldBe a[OPMap[_]] + myURLMap shouldBe a[TextMap] - Map("aaa" -> "bbb").toURLMap shouldBe a[URLMap] + Map("homepage" -> "http://www.salesforce.com").toURLMap shouldBe a[URLMap] } /* TextAreaMap tests */ - Spec[TextAreaMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[TextAreaMap] should "extend correct base classes and have a working shortcut" in { val myTextAreaMap = new TextAreaMap(Map.empty[String, String]) myTextAreaMap shouldBe a[FeatureType] myTextAreaMap shouldBe a[OPCollection] myTextAreaMap shouldBe a[OPMap[_]] + myTextAreaMap shouldBe a[TextMap] Map("aaa" -> "bbb").toTextAreaMap shouldBe a[TextAreaMap] } /* PickListMap tests */ - Spec[PickListMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[PickListMap] should "extend correct base classes and have a working shortcut" in { val myPickListMap = new PickListMap(Map.empty[String, String]) myPickListMap shouldBe a[FeatureType] myPickListMap shouldBe a[OPCollection] myPickListMap shouldBe a[OPMap[_]] + myPickListMap shouldBe a[TextMap] + myPickListMap shouldBe a[SingleResponse] Map("aaa" -> "bbb").toPickListMap shouldBe a[PickListMap] } /* ComboBoxMap tests */ - Spec[ComboBoxMap] should "extend OPMap[_], and have a working shortcut" in { + Spec[ComboBoxMap] should "extend correct base classes and have a working shortcut" in { val myComboBoxMap = new ComboBoxMap(Map.empty[String, String]) myComboBoxMap shouldBe a[FeatureType] myComboBoxMap shouldBe a[OPCollection] myComboBoxMap shouldBe a[OPMap[_]] + myComboBoxMap shouldBe a[TextMap] Map("aaa" -> "bbb").toComboBoxMap shouldBe a[ComboBoxMap] } /* CountryMap tests */ - Spec[CountryMap] should "extend OPMap[_] and Location, and have a working shortcut" in { + Spec[CountryMap] should "extend correct base classes and have a working shortcut" in { val myCountryMap = new CountryMap(Map.empty[String, String]) myCountryMap shouldBe a[FeatureType] myCountryMap shouldBe a[OPCollection] myCountryMap shouldBe a[OPMap[_]] + myCountryMap shouldBe a[TextMap] myCountryMap shouldBe a[Location] Map("Tuesday" -> "Bahrain").toCountryMap shouldBe a[CountryMap] } /* StateMap tests */ - Spec[StateMap] should "extend OPMap[_] and Location, and have a working shortcut" in { + Spec[StateMap] should "extend correct base classes and have a working shortcut" in { val myStateMap = new StateMap(Map.empty[String, String]) myStateMap shouldBe a[FeatureType] myStateMap shouldBe a[OPCollection] myStateMap shouldBe a[OPMap[_]] + myStateMap shouldBe a[TextMap] myStateMap shouldBe a[Location] Map("Thursday" -> "British Columbia").toStateMap shouldBe a[StateMap] } /* CityMap tests */ - Spec[CityMap] should "extend OPMap[_] and Location, and have a working shortcut" in { + Spec[CityMap] should "extend correct base classes and have a working shortcut" in { val myCityMap = new CityMap(Map.empty[String, String]) myCityMap shouldBe a[FeatureType] myCityMap shouldBe a[OPCollection] myCityMap shouldBe a[OPMap[_]] + myCityMap shouldBe a[TextMap] myCityMap shouldBe a[Location] Map("Wednesday" -> "Kyoto").toCityMap shouldBe a[CityMap] } /* PostalCodeMap tests */ - Spec[PostalCodeMap] should "extend OPMap[_] and Location, and have a working shortcut" in { + Spec[PostalCodeMap] should "extend correct base classes and have a working shortcut" in { val myPostalCodeMap = new PostalCodeMap(Map.empty[String, String]) myPostalCodeMap shouldBe a[FeatureType] myPostalCodeMap shouldBe a[OPCollection] myPostalCodeMap shouldBe a[OPMap[_]] + myPostalCodeMap shouldBe a[TextMap] myPostalCodeMap shouldBe a[Location] Map("Wednesday" -> "78492").toPostalCodeMap shouldBe a[PostalCodeMap] } /* StreetMap tests */ - Spec[StreetMap] should "extend OPMap[_] and Location, and have a working shortcut" in { + Spec[StreetMap] should "extend correct base classes and have a working shortcut" in { val myStreetMap = new StreetMap(Map.empty[String, String]) myStreetMap shouldBe a[FeatureType] myStreetMap shouldBe a[OPCollection] myStreetMap shouldBe a[OPMap[_]] + myStreetMap shouldBe a[TextMap] myStreetMap shouldBe a[Location] Map("Friday" -> "341 Evergreen Terrace").toStreetMap shouldBe a[StreetMap] } /* GeolocationMap tests */ - Spec[GeolocationMap] should "extend OPMap[Seq[Double]] and Location, and have a working shortcut" in { + Spec[GeolocationMap] should "extend correct base classes and have a working shortcut" in { val myGeolocationMap = new GeolocationMap(Map.empty[String, Seq[Double]]) myGeolocationMap shouldBe a[FeatureType] myGeolocationMap shouldBe a[OPCollection] @@ -202,4 +216,117 @@ class MapTest extends FlatSpec with TestCommon { Map("Friday" -> Seq(-23.11, 45.20, 4.0)).toGeolocationMap shouldBe a[GeolocationMap] } + /* BinaryMao tests */ + Spec[BinaryMap] should "extend correct base classes and have a working shortcut" in { + val binMap = new BinaryMap(Map.empty[String, Boolean]) + binMap shouldBe a[FeatureType] + binMap shouldBe a[OPCollection] + binMap shouldBe a[OPMap[_]] + binMap shouldBe a[NumericMap] + binMap shouldBe a[SingleResponse] + + Map("aaa" -> false).toBinaryMap shouldBe a[BinaryMap] + Map("aaa" -> false, "bbb" -> true).toBinaryMap.toDoubleMap shouldBe Map("aaa" -> 0.0, "bbb" -> 1.0) + } + + /* IntegralMap tests */ + Spec[IntegralMap] should "extend correct base classes and have a working shortcut" in { + val intMap = new IntegralMap(Map.empty[String, Long]) + intMap shouldBe a[FeatureType] + intMap shouldBe a[OPCollection] + intMap shouldBe a[OPMap[_]] + intMap shouldBe a[NumericMap] + + Map("aaa" -> 1L).toIntegralMap shouldBe a[IntegralMap] + Map("aaa" -> 1L).toIntegralMap.toDoubleMap shouldBe Map("aaa" -> 1.0) + } + + /* RealMap tests */ + Spec[RealMap] should "extend correct base classes and have a working shortcut" in { + val rMap = new RealMap(Map.empty[String, Double]) + rMap shouldBe a[FeatureType] + rMap shouldBe a[OPCollection] + rMap shouldBe a[OPMap[_]] + rMap shouldBe a[NumericMap] + + Map("aaa" -> 1.0).toRealMap shouldBe a[RealMap] + Map("aaa" -> 2.0).toRealMap.toDoubleMap shouldBe Map("aaa" -> 2.0) + } + + /* PercentMap tests */ + Spec[PercentMap] should "extend correct base classes and have a working shortcut" in { + val pMap = new PercentMap(Map.empty[String, Double]) + pMap shouldBe a[FeatureType] + pMap shouldBe a[OPCollection] + pMap shouldBe a[OPMap[_]] + pMap shouldBe a[RealMap] + pMap shouldBe a[NumericMap] + + Map("aaa" -> 1.0).toPercentMap shouldBe a[PercentMap] + Map("aaa" -> 2.0).toPercentMap.toDoubleMap shouldBe Map("aaa" -> 2.0) + } + + /* CurrencyMap tests */ + Spec[CurrencyMap] should "extend correct base classes and have a working shortcut" in { + val cMap = new CurrencyMap(Map.empty[String, Double]) + cMap shouldBe a[FeatureType] + cMap shouldBe a[OPCollection] + cMap shouldBe a[OPMap[_]] + cMap shouldBe a[RealMap] + cMap shouldBe a[NumericMap] + + Map("aaa" -> 1.0).toCurrencyMap shouldBe a[CurrencyMap] + Map("aaa" -> 2.0).toCurrencyMap.toDoubleMap shouldBe Map("aaa" -> 2.0) + } + + /* DateMap tests */ + Spec[DateMap] should "extend correct base classes and have a working shortcut" in { + val m = new DateMap(Map.empty[String, Long]) + m shouldBe a[FeatureType] + m shouldBe a[OPCollection] + m shouldBe a[OPMap[_]] + m shouldBe a[IntegralMap] + m shouldBe a[NumericMap] + + Map("aaa" -> 1L).toDateMap shouldBe a[DateMap] + Map("aaa" -> 2L).toDateMap.toDoubleMap shouldBe Map("aaa" -> 2.0) + } + + /* DateTimeMap tests */ + Spec[DateTimeMap] should "extend correct base classes and have a working shortcut" in { + val m = new DateTimeMap(Map.empty[String, Long]) + m shouldBe a[FeatureType] + m shouldBe a[OPCollection] + m shouldBe a[OPMap[_]] + m shouldBe a[DateTimeMap] + m shouldBe a[IntegralMap] + m shouldBe a[NumericMap] + + Map("aaa" -> 1L).toDateTimeMap shouldBe a[DateTimeMap] + Map("aaa" -> 2L).toDateTimeMap.toDoubleMap shouldBe Map("aaa" -> 2.0) + } + + /* MultiPickListMap tests */ + Spec[MultiPickListMap] should "extend correct base classes and have a working shortcut" in { + val m = new MultiPickListMap(Map.empty[String, Set[String]]) + m shouldBe a[FeatureType] + m shouldBe a[OPCollection] + m shouldBe a[OPMap[_]] + m shouldBe a[MultiResponse] + + Map("aaa" -> Set("b")).toMultiPickListMap shouldBe a[MultiPickListMap] + } + + /* Prediction tests */ + Spec[Prediction] should "extend correct base classes" in { + val m = Prediction(0.0) + m shouldBe a[FeatureType] + m shouldBe a[OPCollection] + m shouldBe a[OPMap[_]] + m shouldBe a[RealMap] + + Map("prediction" -> 1.0).toPrediction shouldBe a[Prediction] + Map("prediction" -> 1.0).toPrediction.toDoubleMap shouldBe Map("prediction" -> 1.0) + } + } diff --git a/features/src/test/scala/com/salesforce/op/features/types/PredictionTest.scala b/features/src/test/scala/com/salesforce/op/features/types/PredictionTest.scala index 8e57d4deca..48c423fe1d 100644 --- a/features/src/test/scala/com/salesforce/op/features/types/PredictionTest.scala +++ b/features/src/test/scala/com/salesforce/op/features/types/PredictionTest.scala @@ -42,6 +42,9 @@ class PredictionTest extends FlatSpec with TestCommon { Spec[Prediction] should "extend FeatureType" in { Prediction(1.0) shouldBe a[FeatureType] + Prediction(1.0) shouldBe a[OPMap[_]] + Prediction(1.0) shouldBe a[NumericMap] + Prediction(1.0) shouldBe a[RealMap] } it should "error if prediction is missing" in { intercept[NonNullableEmptyException](new Prediction(null))