diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypeEncoders.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypeEncoders.scala index b9dc1a02614..fdcb708c6e7 100644 --- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypeEncoders.scala +++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypeEncoders.scala @@ -7,7 +7,6 @@ import pl.touk.nussknacker.engine.api.typed.TypingType.{TypingType, decoder} import pl.touk.nussknacker.engine.api.typed.typing._ import pl.touk.nussknacker.engine.util.Implicits.RichScalaMap -import scala.collection.immutable.ListMap import scala.util.{Failure, Success, Try} //TODO: refactor way of encoding to easier handle decoding. @@ -120,7 +119,7 @@ class TypingResultDecoder(loadClass: String => Class[_]) { private def typedObjectTypingResult(obj: HCursor): Decoder.Result[TypingResult] = for { valueClass <- typedClass(obj) - fields <- obj.downField("fields").as[ListMap[String, TypingResult]] + fields <- obj.downField("fields").as[Map[String, TypingResult]] additional <- obj.downField("additionalInfo").as[Option[Map[String, AdditionalDataValue]]].map(_.getOrElse(Map.empty)) } yield TypedObjectTypingResult(fields, valueClass, additional) diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypedObjectDefinition.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypedObjectDefinition.scala index f0bea40444a..c5265086009 100644 --- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypedObjectDefinition.scala +++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/TypedObjectDefinition.scala @@ -2,12 +2,5 @@ package pl.touk.nussknacker.engine.api.typed import pl.touk.nussknacker.engine.api.typed.typing.TypingResult -import scala.collection.immutable.ListMap -object TypedObjectDefinition { - - def apply(fields: List[(String, TypingResult)]): TypedObjectDefinition = - TypedObjectDefinition(ListMap(fields: _*)) -} - -case class TypedObjectDefinition(fields: ListMap[String, TypingResult]) +case class TypedObjectDefinition(fields: Map[String, TypingResult]) diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala index 22c851357c7..cf2eeb3cd8e 100644 --- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala +++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala @@ -92,31 +92,21 @@ class CommonSupertypeFinder(classResolutionStrategy: SupertypeClassResolutionStr } private def unionOfFields(l: TypedObjectTypingResult, r: TypedObjectTypingResult) - (implicit numberPromotionStrategy: NumberTypesPromotionStrategy): List[(String, TypingResult)] = { - val leftFields = l.fields.toList - val rightFields = r.fields.toList - val leftFieldNames = leftFields.map(_._1) - val (rightIntersect, rightDoesNotIntersect) = rightFields.partition { - case (rightFieldName, _) => leftFieldNames.contains(rightFieldName) - } - - val leftFieldsWithRightCommonFields = leftFields.map { case (name, leftType) => - name -> (leftType :: rightIntersect.filter(name == _._1).map(_._2)) - }.flatMap { - case (fieldName, leftType :: rightType :: Nil) if leftType == rightType => - fieldName -> leftType :: Nil - case (fieldName, leftType :: rightType :: Nil) => - val leastUpperBound = commonSupertype(leftType, rightType) - if (leastUpperBound == Typed.empty) - Nil // fields type collision - skipping this field - else - (fieldName, leastUpperBound) :: Nil - case (fieldName, types) => - val leftField = types.head - fieldName -> leftField :: Nil - } - leftFieldsWithRightCommonFields ++ rightDoesNotIntersect -} + (implicit numberPromotionStrategy: NumberTypesPromotionStrategy): Map[String, TypingResult] = + (l.fields.toList ++ r.fields.toList).groupBy(_._1) + .map { case (key, value) => key -> value.map(_._2) } + .flatMap { + case (fieldName, leftType :: rightType :: Nil) => + val common = commonSupertype(leftType, rightType) + if (common == Typed.empty) + None // fields type collision - skipping this field + else + Some(fieldName -> common) + case (fieldName, singleType :: Nil) => + Some(fieldName -> singleType) + case (_, longerList) => + throw new IllegalArgumentException("Computing union of more than two fields: " + longerList) // shouldn't happen + } // This implementation is because TypedObjectTypingResult has underlying TypedClass instead of TypingResult private def klassCommonSupertypeReturningTypedClass(left: TypedClass, right: TypedClass) diff --git a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypedFromInstanceTest.scala b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypedFromInstanceTest.scala index 4088416815e..67455a7109e 100644 --- a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypedFromInstanceTest.scala +++ b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypedFromInstanceTest.scala @@ -4,10 +4,8 @@ import org.scalatest.prop.TableDrivenPropertyChecks import org.scalatest.LoneElement import org.scalatest.matchers.should.Matchers import org.scalatest.funsuite.AnyFunSuite -import org.scalatest.matchers.should.Matchers import pl.touk.nussknacker.engine.api.typed.typing._ -import scala.collection.immutable.ListMap class TypedFromInstanceTest extends AnyFunSuite with Matchers with LoneElement with TableDrivenPropertyChecks { @@ -42,7 +40,7 @@ class TypedFromInstanceTest extends AnyFunSuite with Matchers with LoneElement w } test("should type map types") { - val fieldTypes = ListMap( + val fieldTypes = Map( "a" -> TypedObjectWithValue(Typed.typedClass[Int], 1), "b" -> TypedObjectWithValue(Typed.typedClass[String], "string") ) @@ -81,12 +79,12 @@ class TypedFromInstanceTest extends AnyFunSuite with Matchers with LoneElement w checkTypingResult(listOfSimpleObjects.asJava, classOf[java.util.List[_]], Typed(classOf[Number])) val listOfTypedMaps = List(TypedMap(Map("a" -> 1, "b" -> "B")), TypedMap(Map("a" -> 1))) - val typedMapTypingResult = TypedObjectTypingResult(ListMap("a" -> Typed(classOf[Integer]))) + val typedMapTypingResult = TypedObjectTypingResult(Map("a" -> Typed(classOf[Integer]))) checkTypingResult(listOfTypedMaps, classOf[List[_]], typedMapTypingResult) checkTypingResult(listOfTypedMaps.asJava, classOf[java.util.List[_]], typedMapTypingResult) - checkNotASubclassOfOtherParamTypingResult(listOfTypedMaps, TypedObjectTypingResult(ListMap("c" -> Typed(classOf[Integer])))) - checkNotASubclassOfOtherParamTypingResult(listOfTypedMaps, TypedObjectTypingResult(ListMap("b" -> Typed(classOf[Integer])))) - checkNotASubclassOfOtherParamTypingResult(listOfTypedMaps, TypedObjectTypingResult(ListMap("a" -> Typed(classOf[String])))) + checkNotASubclassOfOtherParamTypingResult(listOfTypedMaps, TypedObjectTypingResult(Map("c" -> Typed(classOf[Integer])))) + checkNotASubclassOfOtherParamTypingResult(listOfTypedMaps, TypedObjectTypingResult(Map("b" -> Typed(classOf[Integer])))) + checkNotASubclassOfOtherParamTypingResult(listOfTypedMaps, TypedObjectTypingResult(Map("a" -> Typed(classOf[String])))) } test("should find element type for lists of different elements") { diff --git a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultDecoderSpec.scala b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultDecoderSpec.scala index 6b5fd596d8b..03fe4bd07cc 100644 --- a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultDecoderSpec.scala +++ b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultDecoderSpec.scala @@ -4,7 +4,6 @@ import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import pl.touk.nussknacker.engine.api.typed.typing.{AdditionalDataValue, Typed, TypedNull, TypedObjectTypingResult, TypedObjectWithValue, TypedUnion, Unknown} -import scala.collection.immutable.ListMap class TypingResultDecoderSpec extends AnyFunSuite with Matchers { @@ -27,8 +26,8 @@ class TypingResultDecoderSpec extends AnyFunSuite with Matchers { TypedUnion(Set(Typed.typedClass[String], Typed.typedClass[java.lang.Long])), //this wont' work, handling primitives should be done with more sophisticated classloading //Typed[Long] - TypedObjectTypingResult(ListMap("field1" -> Typed[String], "field2" -> Unknown)), - TypedObjectTypingResult(ListMap("field1" -> Typed[String]), Typed.typedClass[Map[String, Any]], + TypedObjectTypingResult(Map("field1" -> Typed[String], "field2" -> Unknown)), + TypedObjectTypingResult(Map("field1" -> Typed[String]), Typed.typedClass[Map[String, Any]], Map[String, AdditionalDataValue]("ad1" -> "aaa", "ad2" -> 22L, "ad3" -> true)) ).foreach { typing => decoder.decodeTypingResults.decodeJson(TypeEncoders.typingResultEncoder(typing)) shouldBe Right(typing) diff --git a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultErrorMessagesSpec.scala b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultErrorMessagesSpec.scala index 0c18204ec0c..87bdb391962 100644 --- a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultErrorMessagesSpec.scala +++ b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultErrorMessagesSpec.scala @@ -9,7 +9,7 @@ import pl.touk.nussknacker.engine.api.typed.typing._ class TypingResultErrorMessagesSpec extends AnyFunSuite with Matchers with OptionValues with Inside { - private def typeMap(args: (String, TypingResult)*) = TypedObjectTypingResult(args.toList) + private def typeMap(args: (String, TypingResult)*) = TypedObjectTypingResult(args.toMap) private def list(arg: TypingResult) = Typed.genericTypeClass[java.util.List[_]](List(arg)) diff --git a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultSpec.scala b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultSpec.scala index 9a9f8c80721..5f86cbcc1b6 100644 --- a/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultSpec.scala +++ b/components-api/src/test/scala/pl/touk/nussknacker/engine/api/typed/TypingResultSpec.scala @@ -7,13 +7,12 @@ import pl.touk.nussknacker.engine.api.typed.supertype.{CommonSupertypeFinder, Nu import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedClass, TypedNull, TypedObjectTypingResult, TypedUnion, TypingResult, Unknown} import java.util -import scala.collection.immutable.ListMap class TypingResultSpec extends AnyFunSuite with Matchers with OptionValues with Inside { private val commonSuperTypeFinder = new CommonSupertypeFinder(SupertypeClassResolutionStrategy.Intersection, true) - private def typeMap(args: (String, TypingResult)*) = TypedObjectTypingResult(args.toList) + private def typeMap(args: (String, TypingResult)*) = TypedObjectTypingResult(args.toMap) private def list(arg: TypingResult) = Typed.genericTypeClass[java.util.List[_]](List(arg)) @@ -115,13 +114,13 @@ class TypingResultSpec extends AnyFunSuite with Matchers with OptionValues with commonSuperTypeFinder.commonSupertype(Unknown, Typed[Long]) shouldEqual Unknown commonSuperTypeFinder.commonSupertype( - TypedObjectTypingResult(ListMap("foo" -> Typed[String], "bar" -> Typed[Int], "baz" -> Typed[String])), - TypedObjectTypingResult(ListMap("foo" -> Typed[String], "bar" -> Typed[Long], "baz2" -> Typed[String]))) shouldEqual - TypedObjectTypingResult(ListMap("foo" -> Typed[String], "bar" -> Typed[java.lang.Long], "baz" -> Typed[String], "baz2" -> Typed[String])) + TypedObjectTypingResult(Map("foo" -> Typed[String], "bar" -> Typed[Int], "baz" -> Typed[String])), + TypedObjectTypingResult(Map("foo" -> Typed[String], "bar" -> Typed[Long], "baz2" -> Typed[String]))) shouldEqual + TypedObjectTypingResult(Map("foo" -> Typed[String], "bar" -> Typed[java.lang.Long], "baz" -> Typed[String], "baz2" -> Typed[String])) commonSuperTypeFinder.commonSupertype( - TypedObjectTypingResult(ListMap("foo" -> Typed[String])), TypedObjectTypingResult(ListMap("foo" -> Typed[Long]))) shouldEqual - TypedObjectTypingResult(ListMap.empty[String, TypingResult]) + TypedObjectTypingResult(Map("foo" -> Typed[String])), TypedObjectTypingResult(Map("foo" -> Typed[Long]))) shouldEqual + TypedObjectTypingResult(Map.empty[String, TypingResult]) } test("find common supertype for complex types with inheritance in classes hierarchy") { diff --git a/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/ignite/IgniteQueryHelper.scala b/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/ignite/IgniteQueryHelper.scala index bb230da6a31..7efc6cf2bf7 100644 --- a/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/ignite/IgniteQueryHelper.scala +++ b/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/ignite/IgniteQueryHelper.scala @@ -26,7 +26,7 @@ class IgniteQueryHelper(getConnection: () => Connection) extends LazyLogging { .map { case (tableName, entries) => val columnTypings = entries.map { case (_, columnName, klassName, _) => columnName -> Typed.typedClass(Class.forName(klassName)) } - tableName -> TableDefinition(typedObjectDefinition = TypedObjectDefinition(columnTypings)) + tableName -> TableDefinition(typedObjectDefinition = TypedObjectDefinition(columnTypings.toMap)) } } } diff --git a/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/TableDefinition.scala b/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/TableDefinition.scala index 34aa65b6054..b69be7be439 100644 --- a/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/TableDefinition.scala +++ b/components/sql/src/main/scala/pl/touk/nussknacker/sql/db/schema/TableDefinition.scala @@ -24,7 +24,7 @@ object TableDefinition { } case class TableDefinition(columnDefs: List[ColumnDefinition]) { - val rowType: TypedObjectTypingResult = TypedObjectTypingResult(columnDefs.map(col => col.name -> col.typing)) + val rowType: TypedObjectTypingResult = TypedObjectTypingResult(columnDefs.map(col => col.name -> col.typing).toMap) val resultSetType: TypingResult = Typed.genericTypeClass(classOf[java.util.List[_]], rowType :: Nil) } diff --git a/designer/server/src/test/scala/pl/touk/nussknacker/ui/validation/ProcessValidationSpec.scala b/designer/server/src/test/scala/pl/touk/nussknacker/ui/validation/ProcessValidationSpec.scala index b7b0f5a3574..3de706b72cf 100644 --- a/designer/server/src/test/scala/pl/touk/nussknacker/ui/validation/ProcessValidationSpec.scala +++ b/designer/server/src/test/scala/pl/touk/nussknacker/ui/validation/ProcessValidationSpec.scala @@ -39,7 +39,6 @@ import pl.touk.nussknacker.ui.api.helpers._ import pl.touk.nussknacker.ui.process.marshall.ProcessConverter import pl.touk.nussknacker.ui.process.subprocess.{SubprocessDetails, SubprocessResolver} -import scala.collection.immutable.{ListMap, Map} import scala.jdk.CollectionConverters._ class ProcessValidationSpec extends AnyFunSuite with Matchers { @@ -213,7 +212,7 @@ class ProcessValidationSpec extends AnyFunSuite with Matchers { val result = validator.validate(process) - result.errors.globalErrors shouldBe List((NodeValidationError("DuplicatedNodeIds", "Two nodes cannot have same id", "Duplicate node ids: switchID", None, RenderNotAllowed))) + result.errors.globalErrors shouldBe List(NodeValidationError("DuplicatedNodeIds", "Two nodes cannot have same id", "Duplicate node ids: switchID", None, RenderNotAllowed)) result.errors.invalidNodes shouldBe empty result.warnings shouldBe ValidationWarnings.success } @@ -429,7 +428,7 @@ class ProcessValidationSpec extends AnyFunSuite with Matchers { validationResult.errors.invalidNodes shouldBe Symbol("empty") validationResult.nodeResults("sink2").variableTypes("input") shouldBe typing.Unknown validationResult.nodeResults("sink2").variableTypes("var2") shouldBe Typed.fromInstance("42") - validationResult.nodeResults("sink2").variableTypes("subOut2") shouldBe TypedObjectTypingResult(ListMap( + validationResult.nodeResults("sink2").variableTypes("subOut2") shouldBe TypedObjectTypingResult(Map( "bar" -> Typed.fromInstance("42") )) } diff --git a/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/UnionWithMemoTransformer.scala b/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/UnionWithMemoTransformer.scala index d09cd4ea1c6..3e44a69cc68 100644 --- a/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/UnionWithMemoTransformer.scala +++ b/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/UnionWithMemoTransformer.scala @@ -51,7 +51,7 @@ class UnionWithMemoTransformer(timestampAssigner: Option[TimestampWatermarkHandl val finalContext = finalContextValidated.toOption.get val mapTypeInfo = context.typeInformationDetection - .forType(TypedObjectTypingResult(valueByBranchId.mapValuesNow(_.returnType).toList, Typed.typedClass[java.util.Map[_, _]])) + .forType(TypedObjectTypingResult(valueByBranchId.mapValuesNow(_.returnType), Typed.typedClass[java.util.Map[_, _]])) .asInstanceOf[TypeInformation[java.util.Map[String, AnyRef]]] val processedTypeInfo = context.typeInformationDetection.forValueWithContext(finalContext, KeyedValueType.info(mapTypeInfo)) @@ -98,10 +98,10 @@ class UnionWithMemoTransformer(timestampAssigner: Option[TimestampWatermarkHandl val validatedContext = ContextTransformation.findUniqueParentContext(inputContexts).map { parent => val newType = TypedObjectTypingResult( - (KeyField -> Typed[String]) :: inputContexts.map { + inputContexts.map { case (branchId, _) => ContextTransformation.sanitizeBranchName(branchId) -> valueByBranchId(branchId).returnType - }.toList + } + (KeyField -> Typed[String]) ) ValidationContext(Map(variableName -> newType), Map.empty, parent) } diff --git a/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/aggregates.scala b/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/aggregates.scala index 3b9fe8c3959..f9dc68d2681 100644 --- a/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/aggregates.scala +++ b/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/aggregates.scala @@ -223,7 +223,7 @@ object aggregates { .map(key -> _) .leftMap(m => NonEmptyList.of(s"$key - $m")) }.toList.sequence.leftMap(list => s"Invalid fields: ${list.toList.mkString(", ")}") - validationRes.map(fields => TypedObjectTypingResult(fields, objType = objType)) + validationRes.map(fields => TypedObjectTypingResult(fields.toMap, objType = objType)) case TypedObjectTypingResult(inputFields, _, _) => Invalid(s"Fields do not match, aggregateBy: ${inputFields.keys.mkString(", ")}, aggregator: ${scalaFields.keys.mkString(", ")}") case _ => diff --git a/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/join/FullOuterJoinTransformer.scala b/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/join/FullOuterJoinTransformer.scala index 583762c00de..1a16634128d 100644 --- a/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/join/FullOuterJoinTransformer.scala +++ b/engine/flink/components/base/src/main/scala/pl/touk/nussknacker/engine/flink/util/transformer/join/FullOuterJoinTransformer.scala @@ -73,10 +73,9 @@ class FullOuterJoinTransformer(timestampAssigner: Option[TimestampWatermarkHandl .map(id -> _) }.toList.sequence.map(_.toMap) validatedAggregatorReturnTypes.map(outputTypeByBranchId => { - val outputTypes = outputTypeByBranchId.toList - .map{case (k, v) => ContextTransformation.sanitizeBranchName(k) -> v} - .++(List(KeyFieldName -> Typed.typedClass[String])) - TypedObjectTypingResult(outputTypes, Typed.typedClass[java.util.Map[String, AnyRef]]) + val outputTypes = outputTypeByBranchId + .map { case (k, v) => ContextTransformation.sanitizeBranchName(k) -> v } + (KeyFieldName -> Typed.typedClass[String]) + TypedObjectTypingResult(outputTypes) }) case _ => Validated.validNel(Unknown) @@ -111,7 +110,7 @@ class FullOuterJoinTransformer(timestampAssigner: Option[TimestampWatermarkHandl val types = aggregateByByBranchId.mapValuesNow(_.returnType) val optionTypes = types.mapValuesNow(t => Typed.genericTypeClass(classOf[Option[_]], List(t))) - val inputType = TypedObjectTypingResult(optionTypes.toList, objType = Typed.typedClass[java.util.Map[_, _]]) + val inputType = TypedObjectTypingResult(optionTypes) val storedType = aggregator.computeStoredTypeUnsafe(inputType) val storedTypeInfo = context.typeInformationDetection.forType[AnyRef](storedType) diff --git a/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/AggregatesSpec.scala b/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/AggregatesSpec.scala index 3f360317aaf..785f9d9f99b 100644 --- a/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/AggregatesSpec.scala +++ b/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/AggregatesSpec.scala @@ -72,11 +72,11 @@ class AggregatesSpec extends AnyFunSuite with TableDrivenPropertyChecks with Mat val namedAggregators = aggregators.indices.map(id => s"field$id").zip(aggregators).tail.toMap - val mapAggregator = new MapAggregator(namedAggregators.mapValuesNow(_._1.asInstanceOf[Aggregator]).asJava) - val input = TypedObjectTypingResult(namedAggregators.mapValuesNow(_._2).toList, objType = Typed.typedClass[JMap[_, _]]) + val mapAggregator = new MapAggregator(namedAggregators.mapValuesNow(_._1).asJava.asInstanceOf[JMap[String, Aggregator]]) + val input = TypedObjectTypingResult(namedAggregators.mapValuesNow(_._2), objType = Typed.typedClass[JMap[_, _]]) val el = namedAggregators.mapValuesNow(_._3).asJava - val stored = TypedObjectTypingResult(namedAggregators.mapValuesNow(_._4).toList, objType = Typed.genericTypeClass(classOf[Map[_, _]], List(Typed[String], Unknown))) - val output = TypedObjectTypingResult(namedAggregators.mapValuesNow(_._5).toList, objType = Typed.genericTypeClass(classOf[JMap[_, _]], List(Typed[String], Unknown))) + val stored = TypedObjectTypingResult(namedAggregators.mapValuesNow(_._4), objType = Typed.genericTypeClass(classOf[Map[_, _]], List(Typed[String], Unknown))) + val output = TypedObjectTypingResult(namedAggregators.mapValuesNow(_._5), objType = Typed.genericTypeClass(classOf[JMap[_, _]], List(Typed[String], Unknown))) checkAggregator(mapAggregator, input, el, stored, output) } diff --git a/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/TransformersTest.scala b/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/TransformersTest.scala index 967c8f39ae9..cd34f5daa15 100644 --- a/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/TransformersTest.scala +++ b/engine/flink/components/base/src/test/scala/pl/touk/nussknacker/engine/flink/util/transformer/aggregate/TransformersTest.scala @@ -35,10 +35,8 @@ import java.time.{Duration, OffsetDateTime, ZoneId} import java.util import java.util.Arrays.asList import scala.jdk.CollectionConverters._ -import scala.collection.immutable.ListMap import pl.touk.nussknacker.engine.util.Implicits.RichScalaMap -import java.util.TimeZone class TransformersTest extends AnyFunSuite with FlinkSpec with Matchers with Inside { @@ -59,7 +57,7 @@ class TransformersTest extends AnyFunSuite with FlinkSpec with Matchers with Ins validateOk("#AGG.set", "#input.str", Typed.fromDetailedType[java.util.Set[String]]) validateOk("#AGG.map({f1: #AGG.sum, f2: #AGG.set})", "{f1: #input.eId, f2: #input.str}", - TypedObjectTypingResult(ListMap("f1" -> Typed[java.lang.Long], "f2" -> Typed.fromDetailedType[java.util.Set[String]]))) + TypedObjectTypingResult(Map("f1" -> Typed[java.lang.Long], "f2" -> Typed.fromDetailedType[java.util.Set[String]]))) validateError("#AGG.sum", "#input.str", "Invalid aggregate type: String, should be: Number") validateError("#AGG.map({f1: #AGG.set, f2: #AGG.set})", "{f1: #input.str}", "Fields do not match, aggregateBy: f1, aggregator: f1, f2") @@ -165,7 +163,6 @@ class TransformersTest extends AnyFunSuite with FlinkSpec with Matchers with Ins } test("set tumbling aggregate") { - val id1 = ZoneId.of("Europe/Warsaw") val id = "1" val model = modelData(List( TestRecordHours(id, 10, 1, "a"), diff --git a/engine/flink/executor/src/main/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetection.scala b/engine/flink/executor/src/main/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetection.scala index 74f22a89def..29c5e8a9a53 100644 --- a/engine/flink/executor/src/main/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetection.scala +++ b/engine/flink/executor/src/main/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetection.scala @@ -45,7 +45,7 @@ class TypingResultAwareTypeInformationDetection(customisation: TypingResultAware ) def forContext(validationContext: ValidationContext): TypeInformation[Context] = { - val variables = forType(TypedObjectTypingResult(validationContext.localVariables.toList, Typed.typedClass[Map[String, AnyRef]])) + val variables = forType(TypedObjectTypingResult(validationContext.localVariables, Typed.typedClass[Map[String, AnyRef]])) .asInstanceOf[TypeInformation[Map[String, Any]]] val parentCtx = validationContext.parent.map(forContext) diff --git a/engine/flink/executor/src/test/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetectionSpec.scala b/engine/flink/executor/src/test/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetectionSpec.scala index 98ee9eb4da8..092f1c019a0 100644 --- a/engine/flink/executor/src/test/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetectionSpec.scala +++ b/engine/flink/executor/src/test/scala/pl/touk/nussknacker/engine/process/typeinformation/TypingResultAwareTypeInformationDetectionSpec.scala @@ -23,7 +23,6 @@ import pl.touk.nussknacker.engine.util.Implicits._ import java.util.Collections import scala.jdk.CollectionConverters._ -import scala.collection.immutable.ListMap class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Matchers with FlinkTypeInformationSerializationMixin { @@ -34,7 +33,7 @@ class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Mat test("test map serialization") { val map = Map("intF" -> 11, "strF" -> "sdfasf", "longF" -> 111L, "fixedLong" -> 12L, "taggedString" -> "1") - val typingResult = TypedObjectTypingResult(ListMap("intF" -> Typed[Int], "strF" -> Typed[String], + val typingResult = TypedObjectTypingResult(Map("intF" -> Typed[Int], "strF" -> Typed[String], "longF" -> Typed[Long], "fixedLong" -> Typed.fromInstance(12L), "taggedString" -> Typed.tagged(Typed.typedClass[String], "someTag")), Typed.typedClass[Map[String, Any]]) val typeInfo: TypeInformation[Map[String, Any]] = informationDetection.forType(typingResult) @@ -55,7 +54,7 @@ class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Mat test("map serialization fallbacks to Kryo when available") { val map = Map("obj" -> SomeTestClass("name")) - val typingResult = TypedObjectTypingResult(ListMap("obj" -> Typed[SomeTestClass]), Typed.typedClass[Map[String, Any]]) + val typingResult = TypedObjectTypingResult(Map("obj" -> Typed[SomeTestClass]), Typed.typedClass[Map[String, Any]]) val typeInfo: TypeInformation[Map[String, Any]] = informationDetection.forType(typingResult) @@ -67,7 +66,7 @@ class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Mat test("test context serialization") { val ctx = Context("11").copy(variables = Map("one" -> 11, "two" -> "ala", "three" -> Map("key" -> "value"))) - val vCtx = ValidationContext(Map("one" -> Typed[Int], "two" -> Typed[String], "three" -> TypedObjectTypingResult(ListMap("key" -> Typed[String]), + val vCtx = ValidationContext(Map("one" -> Typed[Int], "two" -> Typed[String], "three" -> TypedObjectTypingResult(Map("key" -> Typed[String]), Typed.typedClass[Map[String, Any]]))) val typeInfo = informationDetection.forContext(vCtx) @@ -98,11 +97,11 @@ class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Mat } test("Test serialization compatibility") { - val typingResult = TypedObjectTypingResult(ListMap("intF" -> Typed[Int], "strF" -> Typed[String]), + val typingResult = TypedObjectTypingResult(Map("intF" -> Typed[Int], "strF" -> Typed[String]), Typed.typedClass[Map[String, Any]]) - val compatibleTypingResult = TypedObjectTypingResult(ListMap("intF" -> Typed[Int], "strF" -> Typed[String], + val compatibleTypingResult = TypedObjectTypingResult(Map("intF" -> Typed[Int], "strF" -> Typed[String], "longF" -> Typed[Long]), Typed.typedClass[Map[String, Any]]) - val incompatibleTypingResult = TypedObjectTypingResult(ListMap("intF" -> Typed[Int], "strF" -> Typed[Long]), + val incompatibleTypingResult = TypedObjectTypingResult(Map("intF" -> Typed[Int], "strF" -> Typed[Long]), Typed.typedClass[Map[String, Any]]) val oldSerializer = informationDetection.forType(typingResult).createSerializer(executionConfigWithoutKryo) @@ -120,7 +119,7 @@ class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Mat test("serialization compatibility with reconfigured serializer") { val map = Map("obj" -> SomeTestClass("name")) - val typingResult = TypedObjectTypingResult(ListMap("obj" -> Typed[SomeTestClass]), Typed.typedClass[Map[String, Any]]) + val typingResult = TypedObjectTypingResult(Map("obj" -> Typed[SomeTestClass]), Typed.typedClass[Map[String, Any]]) val oldSerializer = informationDetection.forType[Map[String, Any]](typingResult).createSerializer(executionConfigWithKryo) val oldSerializerSnapshot = oldSerializer.snapshotConfiguration() @@ -138,11 +137,11 @@ class TypingResultAwareTypeInformationDetectionSpec extends AnyFunSuite with Mat } test("serialization compatibility with custom flag config") { - val typingResult = TypedObjectTypingResult(ListMap("intF" -> Typed[Int], "strF" -> Typed[String]), + val typingResult = TypedObjectTypingResult(Map("intF" -> Typed[Int], "strF" -> Typed[String]), Typed.typedClass[CustomTypedObject]) - val addField = TypedObjectTypingResult(ListMap("intF" -> Typed[Int], "strF" -> Typed[String], + val addField = TypedObjectTypingResult(Map("intF" -> Typed[Int], "strF" -> Typed[String], "longF" -> Typed[Long]), Typed.typedClass[CustomTypedObject]) - val removeField = TypedObjectTypingResult(ListMap("intF" -> Typed[Int]), Typed.typedClass[CustomTypedObject]) + val removeField = TypedObjectTypingResult(Map("intF" -> Typed[Int]), Typed.typedClass[CustomTypedObject]) serializeRoundTrip(CustomTypedObject(Map[String, AnyRef]("intF" -> (5: java.lang.Integer), "strF" -> "").asJava), informationDetection.forType(typingResult))() @@ -198,7 +197,7 @@ object testTypedObject { case class CustomTypedObject(map: java.util.Map[String, AnyRef]) extends java.util.HashMap[String, AnyRef](map) case class CustomObjectTypeInformation(fields: Map[String, TypeInformation[_]]) extends TypedObjectBasedTypeInformation[CustomTypedObject](fields) { - override def createSerializer(serializers: Array[(String, TypeSerializer[_])]): TypeSerializer[CustomTypedObject] = new CustomObjectTypeSerializer(serializers) + override def createSerializer(serializers: Array[(String, TypeSerializer[_])]): TypeSerializer[CustomTypedObject] = CustomObjectTypeSerializer(serializers) } case class CustomObjectTypeSerializer(override val serializers: Array[(String, TypeSerializer[_])]) diff --git a/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/global/ExampleFunctions.scala b/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/global/ExampleFunctions.scala index e028e0c2c84..9497985a9e1 100644 --- a/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/global/ExampleFunctions.scala +++ b/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/global/ExampleFunctions.scala @@ -106,8 +106,8 @@ object ExampleFunctions { if (arguments.exists(!_.canBeSubclassOf(Typed[Number]))) return ArgumentTypeError.invalidNel arguments match { case t :: Nil => t.validNel - case l :: r :: Nil => TypedObjectTypingResult(List("left" -> l, "right" -> r)).validNel - case l :: m :: r :: Nil => TypedObjectTypingResult(List("left" -> l, "mid" -> m, "right" -> r)).validNel + case l :: r :: Nil => TypedObjectTypingResult(Map("left" -> l, "right" -> r)).validNel + case l :: m :: r :: Nil => TypedObjectTypingResult(Map("left" -> l, "mid" -> m, "right" -> r)).validNel case _ => ArgumentTypeError.invalidNel } } diff --git a/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/service/UnionReturnObjectService.scala b/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/service/UnionReturnObjectService.scala index 4006a6a3a73..830f9ad362d 100644 --- a/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/service/UnionReturnObjectService.scala +++ b/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/service/UnionReturnObjectService.scala @@ -8,7 +8,6 @@ import pl.touk.nussknacker.engine.api.typed.typing import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedObjectTypingResult} import pl.touk.nussknacker.engine.util.service.EagerServiceWithStaticParametersAndReturnType -import scala.collection.immutable.ListMap import scala.concurrent.{ExecutionContext, Future} case object UnionReturnObjectService extends EagerServiceWithStaticParametersAndReturnType { @@ -20,7 +19,7 @@ case object UnionReturnObjectService extends EagerServiceWithStaticParametersAnd override def parameters: List[Parameter] = List.empty override def returnType: typing.TypingResult = Typed( - TypedObjectTypingResult(ListMap("foo" -> Typed[Int])), - TypedObjectTypingResult(ListMap("bar" -> Typed[Int]))) + TypedObjectTypingResult(Map("foo" -> Typed[Int])), + TypedObjectTypingResult(Map("bar" -> Typed[Int]))) } diff --git a/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/source/DynamicParametersSource.scala b/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/source/DynamicParametersSource.scala index 92ea3b2b1fc..bdca1e6984d 100644 --- a/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/source/DynamicParametersSource.scala +++ b/engine/flink/management/dev-model/src/main/scala/pl/touk/nussknacker/engine/management/sample/source/DynamicParametersSource.scala @@ -18,7 +18,7 @@ object DynamicParametersSource extends SourceFactory with DynamicParametersMixin override protected def result(validationContext: ValidationContext, otherParams: List[(String, BaseDefinedParameter)])(implicit nodeId: NodeId): FinalResults = { - val paramsTyping = otherParams.map { case (paramName, definedParam) => paramName -> definedParam.returnType } + val paramsTyping = otherParams.map { case (paramName, definedParam) => paramName -> definedParam.returnType }.toMap FinalResults.forValidation(validationContext)(_.withVariable("input", TypedObjectTypingResult(paramsTyping), paramName = None)) } } diff --git a/engine/flink/test-utils/src/main/scala/pl/touk/nussknacker/engine/process/helpers/SampleNodes.scala b/engine/flink/test-utils/src/main/scala/pl/touk/nussknacker/engine/process/helpers/SampleNodes.scala index 92395a4dba5..351cb2c5aac 100644 --- a/engine/flink/test-utils/src/main/scala/pl/touk/nussknacker/engine/process/helpers/SampleNodes.scala +++ b/engine/flink/test-utils/src/main/scala/pl/touk/nussknacker/engine/process/helpers/SampleNodes.scala @@ -369,7 +369,7 @@ object SampleNodes { @ParamName("toFill") toFill: LazyParameter[String], @ParamName("count") count: Int, @OutputVariableName outputVar: String)(implicit nodeId: NodeId): ContextTransformation = { - val listType = TypedObjectTypingResult(definition.asScala.map(_ -> Typed[String]).toList) + val listType = TypedObjectTypingResult(definition.asScala.map(_ -> Typed[String]).toMap) val returnType: typing.TypingResult = Typed.genericTypeClass[java.util.List[_]](List(listType)) EnricherContextTransformation(outputVar, returnType, new ServiceInvoker { @@ -547,7 +547,7 @@ object SampleNodes { private def outputParameters(context: ValidationContext, dependencies: List[NodeDependencyValue], rest: List[(String, BaseDefinedParameter)])(implicit nodeId: NodeId): this.FinalResults = { dependencies.collectFirst { case OutputVariableNameValue(name) => name } match { case Some(name) => - val result = TypedObjectTypingResult(rest.map { case (k, v) => k -> v.returnType }) + val result = TypedObjectTypingResult(rest.map { case (k, v) => k -> v.returnType }.toMap) FinalResults.forValidation(context)(_.withVariable(OutputVar.customNode(name), result)) case None => FinalResults(context, errors = List(CustomNodeError("Output not defined", None))) diff --git a/engine/lite/components/kafka-tests/src/test/scala/pl/touk/nussknacker/engine/lite/components/LiteKafkaUniversalJsonFunctionalTest.scala b/engine/lite/components/kafka-tests/src/test/scala/pl/touk/nussknacker/engine/lite/components/LiteKafkaUniversalJsonFunctionalTest.scala index 72949d45447..cd5e118edfb 100644 --- a/engine/lite/components/kafka-tests/src/test/scala/pl/touk/nussknacker/engine/lite/components/LiteKafkaUniversalJsonFunctionalTest.scala +++ b/engine/lite/components/kafka-tests/src/test/scala/pl/touk/nussknacker/engine/lite/components/LiteKafkaUniversalJsonFunctionalTest.scala @@ -110,7 +110,7 @@ class LiteKafkaUniversalJsonFunctionalTest extends AnyFunSuite with Matchers wit (config(sampleObjMapInt, schemaObjMapLong, schemaObjMapLong), valid(sampleObjMapInt)), (conf(schemaObjMapLong, sampleObjMapIntOutput), valid(sampleObjMapInt)), - (config(samplePerson, schemaPerson, schemaObjStr), invalid(Nil, List("field"), List("age", "first", "last"), Nil)), + (config(samplePerson, schemaPerson, schemaObjStr), invalid(Nil, List("field"), List("last", "first", "age"), Nil)), (conf(schemaObjStr, samplePersonOutput), invalid(Nil, List("field"), List("first", "last", "age"), Nil)), (config(sampleObjMapAny, schemaObjMapAny, schemaObjMapLong), invalidTypes("path 'field.value' actual: 'Unknown' expected: 'Long'")), diff --git a/interpreter/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala b/interpreter/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala index 6a8fd8d4b43..27a2a0e1b6b 100644 --- a/interpreter/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala +++ b/interpreter/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala @@ -192,7 +192,7 @@ class NodeCompiler(definitions: ProcessDefinition[ObjectWithMethodDef], }.sequence val typedObject = compilationResult.map { fieldsComp => - TypedObjectTypingResult(fieldsComp.map(f => (f.fieldName, f.typingResult))) + TypedObjectTypingResult(fieldsComp.map(f => (f.fieldName, f.typingResult)).toMap) }.valueOr(_ => Unknown) val fieldsTypingInfo = compilationResult.map { compilations => @@ -431,7 +431,7 @@ class NodeCompiler(definitions: ProcessDefinition[ObjectWithMethodDef], } } - private def validateGenericTransformer[T](eitherSingleOrJoin: GenericValidationContext, + private def validateGenericTransformer(eitherSingleOrJoin: GenericValidationContext, parameters: List[evaluatedparam.Parameter], branchParameters: List[BranchParameters], outputVar: Option[String], diff --git a/interpreter/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala b/interpreter/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala index cfab2b903f3..9d1cb556d2d 100644 --- a/interpreter/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala +++ b/interpreter/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala @@ -226,7 +226,7 @@ private[spel] class Typer(commonSupertypeFinder: CommonSupertypeFinder, if (literalKeys.size != keys.size) { invalid(MapWithExpressionKeysError) } else { - valid(TypedObjectTypingResult(literalKeys.zip(typedValues))) + valid(TypedObjectTypingResult(literalKeys.zip(typedValues).toMap)) } } case e: MethodReference => @@ -517,9 +517,9 @@ private[spel] class Typer(commonSupertypeFinder: CommonSupertypeFinder, case tc: SingleTypingResult if tc.objType.canBeSubclassOf(Typed[java.util.Collection[_]]) => valid(tc.objType.params.headOption.getOrElse(Unknown)) case tc: SingleTypingResult if tc.objType.canBeSubclassOf(Typed[java.util.Map[_, _]]) => - valid(TypedObjectTypingResult(List( - ("key", tc.objType.params.headOption.getOrElse(Unknown)), - ("value", tc.objType.params.drop(1).headOption.getOrElse(Unknown))))) + valid(TypedObjectTypingResult(Map( + "key" -> tc.objType.params.headOption.getOrElse(Unknown), + "value" -> tc.objType.params.drop(1).headOption.getOrElse(Unknown)))) case tc: SingleTypingResult if tc.objType.klass.isArray => valid(tc.objType.params.headOption.getOrElse(Unknown)) case tc: SingleTypingResult => diff --git a/interpreter/src/main/scala/pl/touk/nussknacker/engine/variables/MetaVariables.scala b/interpreter/src/main/scala/pl/touk/nussknacker/engine/variables/MetaVariables.scala index 5d11b1189f6..435a52ac6ef 100644 --- a/interpreter/src/main/scala/pl/touk/nussknacker/engine/variables/MetaVariables.scala +++ b/interpreter/src/main/scala/pl/touk/nussknacker/engine/variables/MetaVariables.scala @@ -5,7 +5,6 @@ import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedObjectTypingResu import pl.touk.nussknacker.engine.api.typed.{TypedMap, TypedObjectDefinition} import pl.touk.nussknacker.engine.definition.DefinitionExtractor.ObjectWithType -import scala.collection.immutable.ListMap final case class MetaVariables(processName: String, properties: TypedMap) @@ -20,7 +19,7 @@ object MetaVariables { MetaVariables(metaData.id, properties(metaData)) @Hidden - def typingResult(metaData: MetaData): TypingResult = TypedObjectTypingResult(ListMap( + def typingResult(metaData: MetaData): TypingResult = TypedObjectTypingResult(Map( "processName" -> Typed[String], "properties" -> propertiesType(metaData) )) @@ -33,12 +32,9 @@ object MetaVariables { val definedProperties = metaData .additionalFields .map(_.properties) - .map(_.toList.sortBy(_._1)) - .getOrElse(List.empty) + .getOrElse(Map.empty) + .map { case (propertyName, _) => propertyName -> Typed[String] } - val propertiesTyping = TypedObjectDefinition( - definedProperties.map { case (propertyName, _) => propertyName -> Typed[String] } - ) - TypedObjectTypingResult(propertiesTyping) + TypedObjectTypingResult(definedProperties) } } \ No newline at end of file diff --git a/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/CustomNodeValidationSpec.scala b/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/CustomNodeValidationSpec.scala index afe3dceb6f0..f32e4005942 100644 --- a/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/CustomNodeValidationSpec.scala +++ b/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/CustomNodeValidationSpec.scala @@ -22,7 +22,6 @@ import pl.touk.nussknacker.engine.util.namespaces.ObjectNamingProvider import pl.touk.nussknacker.engine.variables.MetaVariables import scala.collection.Set -import scala.collection.immutable.ListMap class CustomNodeValidationSpec extends AnyFunSuite with Matchers with OptionValues { @@ -249,7 +248,7 @@ class CustomNodeValidationSpec extends AnyFunSuite with Matchers with OptionValu case Valid(_) => } validationResult.variablesInNodes("stringService")("outPutVar") shouldBe TypedObjectTypingResult( - ListMap("branch2" -> Typed[Int], "branch1" -> Typed[String])) + Map("branch2" -> Typed[Int], "branch1" -> Typed[String])) } test("invalid scenario using context transformation api - union") { @@ -290,7 +289,7 @@ class CustomNodeValidationSpec extends AnyFunSuite with Matchers with OptionValu ) val validationResult = validator.validate(process) - validationResult.variablesInNodes("stringService")("outPutVar") shouldBe TypedObjectTypingResult(ListMap("branch1" -> Typed[String])) + validationResult.variablesInNodes("stringService")("outPutVar") shouldBe TypedObjectTypingResult(Map("branch1" -> Typed[String])) val errors = validationResult.result.swap.toList.flatMap(_.toList).map(_.nodeIds) errors shouldBe List(Set("invalidFilter")) diff --git a/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/GenericTransformationValidationSpec.scala b/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/GenericTransformationValidationSpec.scala index 4dbf7e483ce..749225a9570 100644 --- a/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/GenericTransformationValidationSpec.scala +++ b/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/GenericTransformationValidationSpec.scala @@ -21,7 +21,6 @@ import pl.touk.nussknacker.engine.dict.SimpleDictRegistry import pl.touk.nussknacker.engine.{CustomProcessValidatorLoader, spel} import pl.touk.nussknacker.engine.util.namespaces.ObjectNamingProvider -import scala.collection.immutable.ListMap class GenericTransformationValidationSpec extends AnyFunSuite with Matchers with OptionValues with Inside { @@ -84,7 +83,7 @@ class GenericTransformationValidationSpec extends AnyFunSuite with Matchers with result.result shouldBe Symbol("valid") val info1 = result.typing("end") - info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(ListMap( + info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(Map( "val1" -> Typed.fromInstance("aa"), "val2" -> Typed.fromInstance(11), "val3" -> Typed.genericTypeClass(classOf[java.util.List[_]], List(Typed.fromInstance(false))) @@ -107,7 +106,7 @@ class GenericTransformationValidationSpec extends AnyFunSuite with Matchers with result.result shouldBe Symbol("valid") val info1 = result.typing("end") - info1.inputValidationContext("otherNameThanInput") shouldBe TypedObjectTypingResult(ListMap( + info1.inputValidationContext("otherNameThanInput") shouldBe TypedObjectTypingResult(Map( "val1" -> Typed.fromInstance("aa"), "val2" -> Typed.fromInstance(11), "val3" -> Typed.genericTypeClass(classOf[java.util.List[_]], List(Typed.fromInstance(false))) @@ -203,7 +202,7 @@ class GenericTransformationValidationSpec extends AnyFunSuite with Matchers with "generic", Some("par1"), "12"))) val info1 = result.typing("end") - info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(ListMap.empty[String, TypingResult]) + info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(Map.empty[String, TypingResult]) } @@ -224,7 +223,7 @@ class GenericTransformationValidationSpec extends AnyFunSuite with Matchers with val info1 = result.typing("end") - info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(ListMap( + info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(Map( "val1" -> Typed.fromInstance(""), "val2" -> Unknown )) @@ -253,7 +252,7 @@ class GenericTransformationValidationSpec extends AnyFunSuite with Matchers with "generic", Some("par1"), "12"))) val info1 = result.typing("end") - info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(ListMap.empty[String, TypingResult]) + info1.inputValidationContext("out1") shouldBe TypedObjectTypingResult(Map.empty[String, TypingResult]) } test("should compute dynamic parameters in joins") { diff --git a/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/validationHelpers.scala b/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/validationHelpers.scala index 35f131afea9..7d092df93cd 100644 --- a/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/validationHelpers.scala +++ b/interpreter/src/test/scala/pl/touk/nussknacker/engine/compile/validationHelpers.scala @@ -73,7 +73,7 @@ object validationHelpers { .definedBy { context => val newType = TypedObjectTypingResult((1 to numberOfFields).map { i => s"field$i" -> Typed[String] - }.toList) + }.toMap) context.withVariable(variableName, newType, paramName = None) } .implementedBy(null) @@ -93,7 +93,7 @@ object validationHelpers { val newType = TypedObjectTypingResult(contexts.toSeq.map { case (branchId, _) => branchId -> valueByBranchId(branchId).returnType - }.toList) + }.toMap) Valid(ValidationContext(Map(variableName -> newType))) } .implementedBy(null) @@ -119,7 +119,7 @@ object validationHelpers { } else { val mainBranchContext = mainBranches.head._2 - val newType = TypedObjectTypingResult(joinedBranches.toList.map { + val newType = TypedObjectTypingResult(joinedBranches.map { case (branchId, _) => branchId -> valueByBranchId(branchId).returnType }) @@ -353,14 +353,14 @@ object validationHelpers { } override protected def fallbackFinalResult(step: TransformationStep, inputContext: ValidationContext, outputVariable: Option[String])(implicit nodeId: NodeId): FinalResults = { - val result = TypedObjectTypingResult(step.parameters.toMap.filterKeysNow(k => k != "par1" && k != "lazyPar1").toList.map { case (k, v) => k -> v.returnType }) + val result = TypedObjectTypingResult(step.parameters.toMap.filterKeysNow(k => k != "par1" && k != "lazyPar1").map { case (k, v) => k -> v.returnType }) prepareFinalResultWithOptionalVariable(inputContext, outputVariable.map(name => (name, result)), step.state) } protected def outputParameters(context: ValidationContext, dependencies: List[NodeDependencyValue], rest: List[(String, BaseDefinedParameter)])(implicit nodeId: NodeId): this.FinalResults protected def finalResult(context: ValidationContext, rest: List[(String, BaseDefinedParameter)], name: String)(implicit nodeId: NodeId): this.FinalResults = { - val result = TypedObjectTypingResult(rest.map { case (k, v) => k -> v.returnType }) + val result = TypedObjectTypingResult(rest.map { case (k, v) => k -> v.returnType }.toMap) prepareFinalResultWithOptionalVariable(context, Some((name, result)), None) } diff --git a/interpreter/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala b/interpreter/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala index ecf55978850..45a68996521 100644 --- a/interpreter/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala +++ b/interpreter/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala @@ -17,9 +17,8 @@ import pl.touk.nussknacker.engine.api.expression.{Expression, TypedExpression} import pl.touk.nussknacker.engine.api.generics.{ExpressionParseError, GenericFunctionTypingError, GenericType, TypingFunction} import pl.touk.nussknacker.engine.api.process.ExpressionConfig._ import pl.touk.nussknacker.engine.api.typed.TypedMap -import pl.touk.nussknacker.engine.api.typed.typing.{KnownTypingResult, SingleTypingResult, Typed, TypedClass, TypedNull, TypedObjectTypingResult, TypedUnion, TypingResult} +import pl.touk.nussknacker.engine.api.typed.typing.{KnownTypingResult, SingleTypingResult, Typed, TypedNull, TypedObjectTypingResult, TypedUnion, TypingResult} import pl.touk.nussknacker.engine.api.{Context, NodeId, SpelExpressionExcludeList} -import pl.touk.nussknacker.engine.definition.TypeInfos.ClazzDefinition import pl.touk.nussknacker.engine.dict.SimpleDictRegistry import pl.touk.nussknacker.engine.spel.SpelExpressionParseError.IllegalOperationError.{InvalidMethodReference, TypeReferenceError} import pl.touk.nussknacker.engine.spel.SpelExpressionParseError.MissingObjectError.{NoPropertyError, UnknownClassError, UnknownMethodError} @@ -36,7 +35,6 @@ import java.time.{LocalDate, LocalDateTime} import java.util import java.util.{Collections, Locale} import scala.annotation.varargs -import scala.collection.immutable.ListMap import scala.jdk.CollectionConverters._ import scala.language.implicitConversions import scala.reflect.runtime.universe._ @@ -434,9 +432,9 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD test("missing keys in Maps") { val validationCtx = ValidationContext.empty - .withVariable("map", TypedObjectTypingResult(ListMap( + .withVariable("map", TypedObjectTypingResult(Map( "foo" -> Typed[Int], - "nested" -> TypedObjectTypingResult(ListMap("bar" -> Typed[Int])) + "nested" -> TypedObjectTypingResult(Map("bar" -> Typed[Int])) )), paramName = None) .toOption.get val ctxWithMap = ctx.withVariable("map", Collections.emptyMap()) @@ -532,14 +530,14 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD test("validate simple literals") { parse[Long]("-1", ctx) shouldBe Symbol("valid") parse[Float]("-1.1", ctx) shouldBe Symbol("valid") - parse[Long]("-1.1", ctx) should not be (Symbol("valid")) + parse[Long]("-1.1", ctx) should not be Symbol("valid") parse[Double]("-1.1", ctx) shouldBe Symbol("valid") parse[java.math.BigDecimal]("-1.1", ctx) shouldBe Symbol("valid") } test("validate ternary operator") { - parse[Long]("'d'? 3 : 4", ctx) should not be (Symbol("valid")) - parse[String]("1 > 2 ? 12 : 23", ctx) should not be (Symbol("valid")) + parse[Long]("'d'? 3 : 4", ctx) should not be Symbol("valid") + parse[String]("1 > 2 ? 12 : 23", ctx) should not be Symbol("valid") parse[Long]("1 > 2 ? 12 : 23", ctx) shouldBe Symbol("valid") parse[Number]("1 > 2 ? 12 : 23.0", ctx) shouldBe Symbol("valid") parse[String]("1 > 2 ? 'ss' : 'dd'", ctx) shouldBe Symbol("valid") @@ -547,7 +545,7 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD } test("validate selection for inline list") { - parse[Long]("{44, 44}.?[#this.alamakota]", ctx) should not be (Symbol("valid")) + parse[Long]("{44, 44}.?[#this.alamakota]", ctx) should not be Symbol("valid") parse[java.util.List[_]]("{44, 44}.?[#this > 4]", ctx) shouldBe Symbol("valid") } @@ -556,7 +554,7 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD parseV[java.util.List[Int]]("#a.![#this.length()].?[#this > 4]", vctx) shouldBe Symbol("valid") parseV[java.util.List[Boolean]]("#a.![#this.length()].?[#this > 4]", vctx) shouldBe Symbol("invalid") - parseV[java.util.List[Int]]("#a.![#this / 5]", vctx) should not be (Symbol("valid")) + parseV[java.util.List[Int]]("#a.![#this / 5]", vctx) should not be Symbol("valid") } test("allow #this reference inside functions") { @@ -634,7 +632,7 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD test("parseV typed map with existing field") { val ctxWithMap = ValidationContext .empty - .withVariable("input", TypedObjectTypingResult(ListMap("str" -> Typed[String], "lon" -> Typed[Long])), paramName = None).toOption.get + .withVariable("input", TypedObjectTypingResult(Map("str" -> Typed[String], "lon" -> Typed[Long])), paramName = None).toOption.get parseV[String]("#input.str", ctxWithMap) should be (Symbol("valid")) @@ -647,7 +645,7 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD test("be able to convert between primitive types") { val ctxWithMap = ValidationContext .empty - .withVariable("input", TypedObjectTypingResult(ListMap("int" -> Typed[Int])), paramName = None).toOption.get + .withVariable("input", TypedObjectTypingResult(Map("int" -> Typed[Int])), paramName = None).toOption.get val ctx = Context("").withVariable("input", TypedMap(Map("int" -> 1))) @@ -657,7 +655,7 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD test("evaluate parsed map") { val valCtxWithMap = ValidationContext .empty - .withVariable("input", TypedObjectTypingResult(ListMap("str" -> Typed[String], "lon" -> Typed[Long])), paramName = None).toOption.get + .withVariable("input", TypedObjectTypingResult(Map("str" -> Typed[String], "lon" -> Typed[Long])), paramName = None).toOption.get val ctx = Context("").withVariable("input", TypedMap(Map("str" -> "aaa", "lon" -> 3444))) @@ -677,8 +675,8 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD val ctxWithMap = ValidationContext .empty .withVariable("input", Typed( - TypedObjectTypingResult(ListMap("str" -> Typed[String])), - TypedObjectTypingResult(ListMap("lon" -> Typed[Long]))), paramName = None).toOption.get + TypedObjectTypingResult(Map("str" -> Typed[String])), + TypedObjectTypingResult(Map("lon" -> Typed[Long]))), paramName = None).toOption.get parseV[String]("#input.str", ctxWithMap) should be (Symbol("valid")) @@ -927,7 +925,7 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD test("should check map values") { val parser = expressionParser() - val expected = Typed.genericTypeClass[java.util.Map[_, _]](List(Typed[String], TypedObjectTypingResult(List(("additional" -> Typed[String]))))) + val expected = Typed.genericTypeClass[java.util.Map[_, _]](List(Typed[String], TypedObjectTypingResult(Map("additional" -> Typed[String])))) inside(parser.parse("""{"aField": {"additional": 1}}""", ValidationContext.empty, expected)) { case Invalid(NonEmptyList(e: ExpressionTypeError, Nil)) => e.expected shouldBe expected diff --git a/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/EspTypeUtilsSpec.scala b/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/EspTypeUtilsSpec.scala index 04cfefa0ece..76c185903ed 100644 --- a/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/EspTypeUtilsSpec.scala +++ b/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/EspTypeUtilsSpec.scala @@ -342,7 +342,7 @@ class EspTypeUtilsSpec extends AnyFunSuite with Matchers with OptionValues { checkApplyFunction(List(scalaClassInfo, javaClassInfo), name, arguments, result.validNel) val typedList = Typed.genericTypeClass[java.util.List[_]](List(Typed[String])) - val typedMap = TypedObjectTypingResult(List("a" -> Typed[Int], "b" -> Typed[String])) + val typedMap = TypedObjectTypingResult(Map("a" -> Typed[Int], "b" -> Typed[String])) val table = Table( ("name", "arguments", "result"), diff --git a/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/MethodTypeInfoSubclassCheckerSpec.scala b/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/MethodTypeInfoSubclassCheckerSpec.scala index 8f90220dabf..0a594f98f99 100644 --- a/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/MethodTypeInfoSubclassCheckerSpec.scala +++ b/interpreter/src/test/scala/pl/touk/nussknacker/engine/types/MethodTypeInfoSubclassCheckerSpec.scala @@ -75,7 +75,7 @@ class MethodTypeInfoSubclassCheckerSpec extends AnyFunSuite with Matchers with V test("should work with typed maps") { check( - List(TypedObjectTypingResult(List("a" -> Typed[String], "b" -> Typed[String]))), + List(TypedObjectTypingResult(Map("a" -> Typed[String], "b" -> Typed[String]))), None, List(Typed[java.util.Map[_, _]]), None, @@ -83,7 +83,7 @@ class MethodTypeInfoSubclassCheckerSpec extends AnyFunSuite with Matchers with V ) check( - List(TypedObjectTypingResult(List("a" -> Typed[Int], "b" -> Typed[Double]))), + List(TypedObjectTypingResult(Map("a" -> Typed[Int], "b" -> Typed[Double]))), None, List(Typed.fromDetailedType[java.util.Map[String, Number]]), None, diff --git a/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/definition/LazyParameterUtils.scala b/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/definition/LazyParameterUtils.scala index 58097e7662c..a142ffeca04 100644 --- a/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/definition/LazyParameterUtils.scala +++ b/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/definition/LazyParameterUtils.scala @@ -11,12 +11,12 @@ object LazyParameterUtils { def typedMap(params: ListMap[String, LazyParameter[AnyRef]]): LazyParameter[TypedMap] = { def wrapResultType(list: List[TypingResult]): TypingResult = { TypedObjectTypingResult( - params.toList.map(_._1).zip(list).map { + params.keys.zip(list).map { case (fieldName, TypedClass(_, _ :: valueType :: Nil)) => fieldName -> valueType case other => throw new IllegalArgumentException(s"Unexpected result of type transformation returned by sequence: $other") - } + }.toMap ) } val paramsSeq = params.toList.map { diff --git a/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/typing/TypingUtils.scala b/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/typing/TypingUtils.scala index 7679bc2a3ce..53a62cef7fb 100644 --- a/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/typing/TypingUtils.scala +++ b/utils/components-utils/src/main/scala/pl/touk/nussknacker/engine/util/typing/TypingUtils.scala @@ -5,6 +5,7 @@ import java.util import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedObjectTypingResult, TypingResult} import pl.touk.nussknacker.engine.util.ThreadUtils +import scala.collection.immutable.HashMap import scala.jdk.CollectionConverters._ @@ -16,7 +17,7 @@ object TypingUtils { def typeMapDefinition(definition: Map[String, _]): TypingResult = { //we force use of Map and not some implicit variants (MapLike) to avoid serialization problems... - TypedObjectTypingResult(definition.mapValuesNow(typedMapDefinitionFromParameters).toList) + TypedObjectTypingResult(Map(definition.mapValuesNow(typedMapDefinitionFromParameters).toList: _*)) } private def typedMapDefinitionFromParameters(definition: Any): TypingResult = definition match { diff --git a/utils/default-helpers/src/main/scala/pl/touk/nussknacker/engine/util/functions/collection.scala b/utils/default-helpers/src/main/scala/pl/touk/nussknacker/engine/util/functions/collection.scala index d4eaae62809..116cb3d4a84 100644 --- a/utils/default-helpers/src/main/scala/pl/touk/nussknacker/engine/util/functions/collection.scala +++ b/utils/default-helpers/src/main/scala/pl/touk/nussknacker/engine/util/functions/collection.scala @@ -1,6 +1,6 @@ package pl.touk.nussknacker.engine.util.functions -import cats.data.{Validated, ValidatedNel} +import cats.data.ValidatedNel import cats.implicits.catsSyntaxValidatedId import org.springframework.util.{NumberUtils => SpringNumberUtils} import pl.touk.nussknacker.engine.api.generics.{GenericFunctionTypingError, GenericType, TypingFunction} @@ -10,7 +10,6 @@ import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedClass, TypedObje import pl.touk.nussknacker.engine.api.{Documentation, HideToString, ParamName} import java.util.{Collections, Objects} -import scala.collection.immutable.ListMap import scala.jdk.CollectionConverters._ import scala.language.higherKinds import scala.reflect.ClassTag @@ -192,7 +191,7 @@ object collection extends HideToString { class CollectionMergeTyping[F[_]](implicit classTag: ClassTag[F[_]]) extends TypingFunction { private val fClass: Class[F[_]] = classTag.runtimeClass.asInstanceOf[Class[F[_]]] - private def commonFieldHasTheSameType(fields1: ListMap[String, typing.TypingResult], fields2: ListMap[String, typing.TypingResult]) = { + private def commonFieldHasTheSameType(fields1: Map[String, typing.TypingResult], fields2: Map[String, typing.TypingResult]) = { val commonFields = fields1.keys.toSet intersect fields2.keys.toSet fields1.filter { case (key, _) => commonFields.contains(key) }.map { case (key, value) => key -> value.withoutValue } == fields2.filter { case (key, _) => commonFields.contains(key) }.map { case (key, value) => key -> value.withoutValue } @@ -202,7 +201,7 @@ object collection extends HideToString { case (listType@TypedClass(`fClass`, firstComponentType :: Nil)) :: TypedClass(`fClass`, secondComponentType :: Nil) :: Nil => (firstComponentType, secondComponentType) match { case (TypedObjectTypingResult(x, _, infoX), TypedObjectTypingResult(y, _, infoY)) if commonFieldHasTheSameType(x, y) => - listType.copy(params = TypedObjectTypingResult(ListMap.empty ++ x.view.map { case (key, value) => key -> value.withoutValue } ++ y.view.map { case (key, value) => key -> value.withoutValue }, Typed.typedClass[java.util.HashMap[_, _]], infoX ++ infoY) :: Nil).validNel + listType.copy(params = TypedObjectTypingResult(Map.empty ++ x.view.map { case (key, value) => key -> value.withoutValue } ++ y.view.map { case (key, value) => key -> value.withoutValue }, Typed.typedClass[java.util.HashMap[_, _]], infoX ++ infoY) :: Nil).validNel case (_: TypedObjectTypingResult, _: TypedObjectTypingResult) => listType.copy(params = Unknown :: Nil).validNel case (`unknownMapType`, _: TypedObjectTypingResult) | diff --git a/utils/json-utils/src/main/scala/pl/touk/nussknacker/engine/json/swagger/SwaggerTyped.scala b/utils/json-utils/src/main/scala/pl/touk/nussknacker/engine/json/swagger/SwaggerTyped.scala index 6b38d99c0b7..7ce352e891c 100644 --- a/utils/json-utils/src/main/scala/pl/touk/nussknacker/engine/json/swagger/SwaggerTyped.scala +++ b/utils/json-utils/src/main/scala/pl/touk/nussknacker/engine/json/swagger/SwaggerTyped.scala @@ -188,12 +188,12 @@ object SwaggerTyped { if (elementType.isEmpty) { val patternPropertiesTypesSet = patternProperties.map { case PatternWithSwaggerTyped(_, propertySwaggerTyped) => typingResult(propertySwaggerTyped)}.toSet additionalProperties match { - case AdditionalPropertiesDisabled if patternPropertiesTypesSet.isEmpty => TypedObjectTypingResult(List.empty) + case AdditionalPropertiesDisabled if patternPropertiesTypesSet.isEmpty => TypedObjectTypingResult(Map.empty[String, TypingResult]) case AdditionalPropertiesDisabled => typedStringKeyMap(Typed(patternPropertiesTypesSet)) case AdditionalPropertiesEnabled(value) => typedStringKeyMap(Typed(patternPropertiesTypesSet + typingResult(value))) } } else { - TypedObjectTypingResult(elementType.mapValuesNow(typingResult).toList.sortBy { case (propertyName, _) => propertyName }) + TypedObjectTypingResult(elementType.mapValuesNow(typingResult)) } } diff --git a/utils/json-utils/src/test/scala/pl/touk/nussknacker/engine/json/SwaggerBasedJsonSchemaTypeDefinitionExtractorTest.scala b/utils/json-utils/src/test/scala/pl/touk/nussknacker/engine/json/SwaggerBasedJsonSchemaTypeDefinitionExtractorTest.scala index c588cc78499..5c55ec7acca 100644 --- a/utils/json-utils/src/test/scala/pl/touk/nussknacker/engine/json/SwaggerBasedJsonSchemaTypeDefinitionExtractorTest.scala +++ b/utils/json-utils/src/test/scala/pl/touk/nussknacker/engine/json/SwaggerBasedJsonSchemaTypeDefinitionExtractorTest.scala @@ -6,7 +6,7 @@ import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper import org.scalatest.prop.TableDrivenPropertyChecks import pl.touk.nussknacker.engine.api.typed.TypedMap -import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedNull, TypedObjectTypingResult, Unknown} +import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypedNull, TypedObjectTypingResult, TypingResult, Unknown} import pl.touk.nussknacker.engine.json.swagger.{AdditionalPropertiesDisabled, AdditionalPropertiesEnabled, SwaggerDateTime, SwaggerLong, SwaggerObject, SwaggerString} import pl.touk.nussknacker.engine.json.swagger.extractor.JsonToNuStruct @@ -69,13 +69,13 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List( + val results = Map( "last" -> Typed.apply[String], "first" -> Typed.apply[String], "age" -> Typed.apply[Long], "profession" -> Typed.genericTypeClass(classOf[java.util.List[String]], List(Typed[String])), ) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support refs") { @@ -109,16 +109,16 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List( - "rectangle" -> TypedObjectTypingResult.apply( - List( + val results = Map( + "rectangle" -> TypedObjectTypingResult( + Map( "a" -> Typed.apply[java.math.BigDecimal], "b" -> Typed.apply[java.math.BigDecimal], "c" -> Typed.apply[String] ) ), ) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support refs using /schemas") { @@ -176,18 +176,18 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List( + val results = Map( "boolField" -> Typed.apply[Boolean], "intArrayField" -> Typed.genericTypeClass(classOf[java.util.List[Long]], List(Typed[Long])), "intField" -> Typed.apply[Long], - "nestedObject" -> TypedObjectTypingResult(List( + "nestedObject" -> TypedObjectTypingResult(Map( "numFieldObj" -> Typed.apply[java.math.BigDecimal], "strFieldObj" -> Typed.apply[String] )), "strField" -> Typed.apply[String], "numField" -> Typed.apply[java.math.BigDecimal] ) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support enums of strings") { @@ -208,10 +208,10 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult val enumType = Typed(Set(Typed.fromInstance("one"), Typed.fromInstance("two"), Typed.fromInstance("three"))) - val results = List( + val results = Map( "profession" -> Typed.genericTypeClass(classOf[java.util.List[String]], List(enumType)), ) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) val onlyEnumSchema = JsonSchemaBuilder.parseSchema("""{ "enum": ["one", "two", "three"] }""".stripMargin) SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(onlyEnumSchema).typingResult shouldBe enumType @@ -276,14 +276,14 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List( + val results = Map( "id" -> Typed.apply[String], "nested" -> Typed.genericTypeClass(classOf[java.util.List[_]], - List(TypedObjectTypingResult.apply(List( + List(TypedObjectTypingResult(Map( "id" -> Typed.apply[String], - "nested2" -> TypedObjectTypingResult.apply(List("name" -> Typed.apply[String])) + "nested2" -> TypedObjectTypingResult(Map("name" -> Typed.apply[String])) ))))) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("typed schema should produce same typingResult as typed swagger for SwaggerDateTime") { @@ -322,9 +322,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List("id" -> Typed(Set(Typed.apply[String], Typed.apply[Long]))) + val results = Map("id" -> Typed(Set(Typed.apply[String], Typed.apply[Long]))) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support union - constructed with 'oneOf'") { @@ -343,9 +343,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List("id" -> Typed(Set(Typed.apply[String], Typed.apply[Long]))) + val results = Map("id" -> Typed(Set(Typed.apply[String], Typed.apply[Long]))) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support union - constructed with 'anyOf'") { @@ -364,9 +364,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List("id" -> Typed(Set(Typed.apply[String], Typed.apply[Long]))) + val results = Map("id" -> Typed(Set(Typed.apply[String], Typed.apply[Long]))) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support anyOf/oneOf for object schemas") { @@ -384,8 +384,8 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema(compositionType)).typingResult result shouldBe Typed( - TypedObjectTypingResult(List(("passport", Typed[String]))), - TypedObjectTypingResult(List(("identityCard", Typed[String]))), + TypedObjectTypingResult(Map("passport" -> Typed[String])), + TypedObjectTypingResult(Map("identityCard" -> Typed[String])), ) } } @@ -406,9 +406,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List("id" -> Typed.apply[Long]) + val results = Map("id" -> Typed.apply[Long]) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support support multiple schemas but of the same type - factored version") { @@ -428,9 +428,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List("id" -> Typed.apply[Long]) + val results = Map("id" -> Typed.apply[Long]) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should support generic map") { @@ -470,9 +470,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - val results = List("id" -> Typed.apply[String]) + val results = Map("id" -> Typed.apply[String]) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } test("should type empty object when additionalProperties is false and no explicitly defined properties") { @@ -482,7 +482,7 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - result shouldBe TypedObjectTypingResult.apply(List.empty) + result shouldBe TypedObjectTypingResult(Map.empty[String, TypingResult]) } test("should handle Recursive schema parsing") { @@ -508,7 +508,7 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema).typingResult - result shouldBe TypedObjectTypingResult(List("items" -> TypedObjectTypingResult(List("next" -> Unknown, "value" -> Typed[String])))) + result shouldBe TypedObjectTypingResult(Map("items" -> TypedObjectTypingResult(Map("next" -> Unknown, "value" -> Typed[String])))) } @@ -559,9 +559,9 @@ class SwaggerBasedJsonSchemaTypeDefinitionExtractorTest extends AnyFunSuite with forAll(table){(minValue, exclusiveMinValue, maxValue, exclusiveMaxValue, expectedType) => val result = SwaggerBasedJsonSchemaTypeDefinitionExtractor.swaggerType(schema(minValue, exclusiveMinValue, maxValue, exclusiveMaxValue)).typingResult - val results = List("id" -> Typed.typedClass(expectedType)) + val results = Map("id" -> Typed.typedClass(expectedType)) - result shouldBe TypedObjectTypingResult.apply(results) + result shouldBe TypedObjectTypingResult(results) } } } diff --git a/utils/schemed-kafka-components-utils/src/main/scala/pl/touk/nussknacker/engine/schemedkafka/typed/AvroSchemaTypeDefinitionExtractor.scala b/utils/schemed-kafka-components-utils/src/main/scala/pl/touk/nussknacker/engine/schemedkafka/typed/AvroSchemaTypeDefinitionExtractor.scala index 36207db2051..d9575c29720 100644 --- a/utils/schemed-kafka-components-utils/src/main/scala/pl/touk/nussknacker/engine/schemedkafka/typed/AvroSchemaTypeDefinitionExtractor.scala +++ b/utils/schemed-kafka-components-utils/src/main/scala/pl/touk/nussknacker/engine/schemedkafka/typed/AvroSchemaTypeDefinitionExtractor.scala @@ -35,7 +35,7 @@ object AvroSchemaTypeDefinitionExtractor { .getFields .asScala .map(field => field.name() -> typeDefinition(field.schema(), possibleTypes)) - .toList + .toMap Typed(possibleTypes.map(pt => TypedObjectTypingResult(fields, pt))) }