diff --git a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollection.java b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollection.java index 410fcab69..469b4c9a8 100644 --- a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollection.java +++ b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollection.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Optional; public class JavaModelCollection implements Collection, WorkflowModelCollection { @@ -156,4 +157,17 @@ public Optional as(Class clazz) { return CollectionConversionUtils.as(object, clazz); } + + @Override + public int hashCode() { + return Objects.hash(object); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof JavaModelCollection)) return false; + JavaModelCollection other = (JavaModelCollection) obj; + return Objects.equals(object, other.object); + } } diff --git a/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollectionMarshaller.java b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollectionMarshaller.java new file mode 100644 index 000000000..385e197f3 --- /dev/null +++ b/experimental/model/src/main/java/io/serverlessworkflow/impl/model/func/JavaModelCollectionMarshaller.java @@ -0,0 +1,45 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.impl.model.func; + +import io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller; +import io.serverlessworkflow.impl.marshaller.WorkflowInputBuffer; +import io.serverlessworkflow.impl.marshaller.WorkflowOutputBuffer; +import java.util.Collection; + +public class JavaModelCollectionMarshaller implements CustomObjectMarshaller { + + @Override + public void write(WorkflowOutputBuffer buffer, JavaModelCollection object) { + buffer.writeObject(object.asJavaObject()); + } + + @Override + public JavaModelCollection read( + WorkflowInputBuffer buffer, Class clazz) { + return new JavaModelCollection((Collection) buffer.readObject()); + } + + @Override + public Class getObjectClass() { + return JavaModelCollection.class; + } + + @Override + public int priority() { + return Integer.MAX_VALUE; + } +} diff --git a/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller b/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller index a3fee7dc1..b79cfb3e5 100644 --- a/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller +++ b/experimental/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller @@ -1,2 +1,3 @@ io.serverlessworkflow.impl.model.func.JavaModelMarshaller +io.serverlessworkflow.impl.model.func.JavaModelCollectionMarshaller io.serverlessworkflow.impl.model.func.SerializableObjectMarshaller \ No newline at end of file diff --git a/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java index 84ae9c55d..4d7f07456 100644 --- a/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java +++ b/experimental/model/src/test/java/io/serverlessworkflow/impl/model/func/JavaModelSerializationTest.java @@ -23,6 +23,7 @@ import io.serverlessworkflow.impl.marshaller.WorkflowOutputBuffer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.List; import org.junit.jupiter.api.Test; class JavaModelSerializationTest { @@ -33,6 +34,13 @@ void testSerializableJavaModel() { new JavaModel(new Person("Pepe Gotera", 32, new Address("Rue del Percebe", 13)))); } + @Test + void testSerializableJavaModelCollection() { + testMarshallUnMarshall( + new JavaModelCollection( + List.of(new Person("Pepe Gotera", 32, new Address("Rue del Percebe", 13))))); + } + private void testMarshallUnMarshall(Object object) { WorkflowBufferFactory factory = DefaultBufferFactory.factory(); ByteArrayOutputStream output = new ByteArrayOutputStream(); diff --git a/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java index 4bc599870..6816b31fd 100644 --- a/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java +++ b/impl/core/src/main/java/io/serverlessworkflow/impl/marshaller/AbstractOutputBuffer.java @@ -15,6 +15,7 @@ */ package io.serverlessworkflow.impl.marshaller; +import io.serverlessworkflow.impl.WorkflowModel; import java.time.Instant; import java.util.Collection; import java.util.Map; @@ -64,6 +65,8 @@ public WorkflowOutputBuffer writeCollection(Collection col) { public WorkflowOutputBuffer writeObject(Object object) { if (object == null) { writeType(Type.NULL); + } else if (object instanceof WorkflowModel) { + internalWriteObject(object); } else if (object instanceof Short number) { writeType(Type.SHORT); writeShort(number); @@ -101,8 +104,7 @@ public WorkflowOutputBuffer writeObject(Object object) { writeType(Type.BYTES); writeBytes(bytes); } else { - writeType(Type.CUSTOM); - writeCustomObject(object); + internalWriteObject(object); } return this; } @@ -111,6 +113,11 @@ protected void writeClass(Class objectClass) { writeString(objectClass.getCanonicalName()); } + private void internalWriteObject(Object object) { + writeType(Type.CUSTOM); + writeCustomObject(object); + } + @SuppressWarnings({"rawtypes", "unchecked"}) protected void writeCustomObject(Object object) { Class objectClass = object.getClass(); diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollection.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollection.java index aff21cca4..76aaab65e 100644 --- a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollection.java +++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollection.java @@ -16,6 +16,8 @@ package io.serverlessworkflow.impl.model.jackson; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.node.ArrayNode; import io.serverlessworkflow.impl.CollectionConversionUtils; import io.serverlessworkflow.impl.WorkflowModel; @@ -25,11 +27,14 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Optional; +@JsonSerialize(using = JacksonModelCollectionSerializer.class) +@JsonDeserialize(using = JacksonModelCollectionDeserializer.class) public class JacksonModelCollection implements WorkflowModelCollection { - private ArrayNode node; + protected ArrayNode node; JacksonModelCollection() { this.node = JsonUtils.array(); @@ -164,4 +169,17 @@ public Object asJavaObject() { public Class objectClass() { return ArrayNode.class; } + + @Override + public int hashCode() { + return Objects.hash(node); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof JacksonModelCollection)) return false; + JacksonModelCollection other = (JacksonModelCollection) obj; + return Objects.equals(node, other.node); + } } diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionDeserializer.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionDeserializer.java new file mode 100644 index 000000000..71011b895 --- /dev/null +++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionDeserializer.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.impl.model.jackson; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; + +public class JacksonModelCollectionDeserializer extends StdDeserializer { + + private static final long serialVersionUID = 1L; + + protected JacksonModelCollectionDeserializer() { + super(JacksonModelCollection.class); + } + + @Override + public JacksonModelCollection deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException, JacksonException { + return new JacksonModelCollection(p.readValueAsTree()); + } +} diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionMarshaller.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionMarshaller.java new file mode 100644 index 000000000..afe4777c1 --- /dev/null +++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionMarshaller.java @@ -0,0 +1,25 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.impl.model.jackson; + +public class JacksonModelCollectionMarshaller + extends AbstractJacksonMarshaller { + + @Override + public Class getObjectClass() { + return JacksonModelCollection.class; + } +} diff --git a/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionSerializer.java b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionSerializer.java new file mode 100644 index 000000000..0fbcc5355 --- /dev/null +++ b/impl/model/src/main/java/io/serverlessworkflow/impl/model/jackson/JacksonModelCollectionSerializer.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.impl.model.jackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import java.io.IOException; + +public class JacksonModelCollectionSerializer extends StdSerializer { + + private static final long serialVersionUID = 1L; + + protected JacksonModelCollectionSerializer() { + super(JacksonModelCollection.class); + } + + @Override + public void serialize( + JacksonModelCollection value, JsonGenerator gen, SerializerProvider provider) + throws IOException { + gen.writeTree(value.node); + } +} diff --git a/impl/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller b/impl/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller index ea94d9455..914f4ffa7 100644 --- a/impl/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller +++ b/impl/model/src/main/resources/META-INF/services/io.serverlessworkflow.impl.marshaller.CustomObjectMarshaller @@ -1,2 +1,3 @@ io.serverlessworkflow.impl.model.jackson.JacksonModelMarshaller +io.serverlessworkflow.impl.model.jackson.JacksonModelCollectionMarshaller io.serverlessworkflow.impl.model.jackson.JacksonObjectMarshaller \ No newline at end of file diff --git a/impl/model/src/test/java/io/serverlessworkflow/impl/model/jackson/JacksonModelSerializationTest.java b/impl/model/src/test/java/io/serverlessworkflow/impl/model/jackson/JacksonModelSerializationTest.java index 15efa7272..1c7f2754c 100644 --- a/impl/model/src/test/java/io/serverlessworkflow/impl/model/jackson/JacksonModelSerializationTest.java +++ b/impl/model/src/test/java/io/serverlessworkflow/impl/model/jackson/JacksonModelSerializationTest.java @@ -39,6 +39,16 @@ void testModel() { new JacksonModel(JsonUtils.mapper().createObjectNode().put("Mortadelo", "TIA"))); } + @Test + void testCollectionModel() { + testMarshallUnMarshall( + new JacksonModelCollection( + JsonUtils.mapper() + .createArrayNode() + .add(JsonUtils.mapper().createObjectNode().put("Mortadelo", "TIA")))); + testMarshallUnMarshall(new JacksonModelCollection(JsonUtils.mapper().createArrayNode().add(1))); + } + private void testMarshallUnMarshall(Object object) { WorkflowBufferFactory factory = DefaultBufferFactory.factory(); ByteArrayOutputStream output = new ByteArrayOutputStream();