Skip to content

Commit

Permalink
[#394] Don't use generics when marshalling collections
Browse files Browse the repository at this point in the history
* A temporary workaround for the issue. Full support for generic
  parameter types will need to be added to type mirroring
  • Loading branch information
tristantarrant authored and ryanemerson committed Jan 13, 2025
1 parent 7476705 commit 67873a1
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public abstract class AbstractMarshallerCodeGenerator {

private final String protobufSchemaPackage;

private final boolean useGenerics = false;

protected AbstractMarshallerCodeGenerator(XTypeFactory typeFactory, String protobufSchemaPackage) {
this.typeFactory = typeFactory;
this.protobufSchemaPackage = protobufSchemaPackage;
Expand Down Expand Up @@ -719,7 +721,11 @@ protected void generateWriteMethodBody(IndentWriter iw, ProtoMessageTypeMetadata
mapFieldMetadata.getValue().getJavaTypeName()
);
} else {
iw.printf("java.util.Collection<%s>", fieldMetadata.getJavaTypeName());
if (useGenerics) {
iw.printf("java.util.Collection<%s>", fieldMetadata.getJavaTypeName());
} else {
iw.printf("java.util.Collection");
}
}
} else {
iw.print(fieldMetadata.getJavaTypeName());
Expand Down Expand Up @@ -769,9 +775,15 @@ protected void generateWriteMethodBody(IndentWriter iw, ProtoMessageTypeMetadata
iw.println("}");
iw.printf("$out = (%s) $1.getWriter();\n", TagWriterImpl.class.getName());
} else {
iw.printf("for (java.util.Iterator<%s> it = %s.iterator(); it.hasNext(); ) {\n", fieldMetadata.getJavaTypeName(), f);
iw.inc();
iw.printf("final %s %s = it.next();\n", fieldMetadata.getJavaTypeName(), v);
if (useGenerics) {
iw.printf("for (java.util.Iterator<%s> it = %s.iterator(); it.hasNext(); ) {\n", fieldMetadata.getJavaTypeName(), f);
iw.inc();
iw.printf("final %s %s = it.next();\n", fieldMetadata.getJavaTypeName(), v);
} else {
iw.printf("for (java.util.Iterator it = %s.iterator(); it.hasNext(); ) {\n", f);
iw.inc();
iw.printf("final %s %s = (%s) it.next();\n", fieldMetadata.getJavaTypeName(), v, fieldMetadata.getJavaTypeName());
}
}
}
if (!fieldMetadata.isMap()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* @author anistor@redhat.com
Expand Down Expand Up @@ -197,7 +196,7 @@ public String toString() {
", creationDate='" + creationDate + '\'' +
", limits=" + limits +
", hardLimits=" + hardLimits +
", blurb=" + (blurb != null ? blurb.stream().map(Arrays::toString).collect(Collectors.toList()) : "null") +
", blurb=" + (blurb != null ? blurb.stream().map(Arrays::toString).toList() : "null") +
", currencies=" + Arrays.toString(currencies) +
'}';
}
Expand Down
19 changes: 19 additions & 0 deletions core/src/test/java/org/infinispan/protostream/domain/Pair.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.infinispan.protostream.domain;

public class Pair<L, R> {
private final L l;
private final R r;

public Pair(L l, R r) {
this.l = l;
this.r = r;
}

public L left() {
return l;
}

public R right() {
return r;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.infinispan.protostream.domain;

import org.infinispan.protostream.WrappedMessage;
import org.infinispan.protostream.annotations.ProtoAdapter;
import org.infinispan.protostream.annotations.ProtoFactory;
import org.infinispan.protostream.annotations.ProtoField;

@ProtoAdapter(Pair.class)
public class PairAdapter {

@ProtoFactory
public Pair<?, ?> create(WrappedMessage left, WrappedMessage right) {
return new Pair<>(left.getValue(), right.getValue());
}

@ProtoField(number = 1)
public WrappedMessage getLeft(Pair<?, ?> pair) {
return new WrappedMessage(pair.left());
}

@ProtoField(number = 2)
public WrappedMessage getRight(Pair<?, ?> pair) {
return new WrappedMessage(pair.right());
}
}
32 changes: 30 additions & 2 deletions core/src/test/java/org/infinispan/protostream/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public enum Gender {
private boolean someBoolean = true;
private long someLong = 34;
private boolean someOtherBoolean;
private Set<Pair<String, String>> properties;

@ProtoField(number = 1, defaultValue = "0")
public int getId() {
Expand Down Expand Up @@ -227,6 +228,15 @@ public void setSomeOtherBoolean(boolean someOtherBoolean) {
this.someOtherBoolean = someOtherBoolean;
}

@ProtoField(number = 21)
public Set<Pair<String, String>> getProperties() {
return properties;
}

public void setProperties(Set<Pair<String, String>> properties) {
this.properties = properties;
}

@Override
public String toString() {
return "User{" +
Expand All @@ -250,6 +260,7 @@ public String toString() {
", someBoolean=" + someBoolean +
", someLong=" + someLong +
", someOtherBoolean=" + someOtherBoolean +
", properties=" + properties +
'}';
}

Expand Down Expand Up @@ -346,6 +357,15 @@ public void writeExternal(ObjectOutput out) throws IOException {
out.writeBoolean(someBoolean);
out.writeLong(someLong);
out.writeBoolean(someOtherBoolean);
if (properties == null) {
out.writeInt(-1);
} else {
out.writeInt(properties.size());
for (Pair<String, String> property : properties) {
out.writeUTF(property.left());
out.writeUTF(property.right());
}
}
}

@Override
Expand Down Expand Up @@ -408,6 +428,13 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept
someBoolean = in.readBoolean();
someLong = in.readLong();
someOtherBoolean = in.readBoolean();
int numProperties = in.readInt();
if (numProperties >= 0) {
properties = new HashSet<>(numProperties);
for (int i = 0; i < numProperties; i++) {
properties.add(new Pair<>(in.readUTF(), in.readUTF()));
}
}
}

@Override
Expand All @@ -434,13 +461,14 @@ public boolean equals(Object o) {
someDouble == user.someDouble &&
someBoolean == user.someBoolean &&
someLong == user.someLong &&
someOtherBoolean == user.someOtherBoolean;
someOtherBoolean == user.someOtherBoolean &&
Objects.equals(properties, user.properties);
}

@Override
public int hashCode() {
return Objects.hash(id, name, surname, salutation, accountIds, addresses, age, gender, notes, creationDate,
passwordExpirationDate, qrCode, primaryAddress, someDate, someFloat, someString, someDouble, someBoolean,
someLong, someOtherBoolean);
someLong, someOtherBoolean, properties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.infinispan.protostream.config.Configuration;
import org.infinispan.protostream.domain.Address;
import org.infinispan.protostream.domain.Note;
import org.infinispan.protostream.domain.PairAdapter;
import org.infinispan.protostream.domain.User;
import org.infinispan.protostream.domain.marshallers.NoteMarshaller;
import org.infinispan.protostream.domain.marshallers.UserMarshaller;
Expand Down Expand Up @@ -149,7 +150,8 @@ private SerializationContext createCtxWithGeneratedMarshaller() throws IOExcepti
includeClasses = {
Address.class,
Note.class,
User.class
User.class,
PairAdapter.class
}
)
interface NoteSchema extends GeneratedSchema {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder;
import org.infinispan.protostream.annotations.ProtoSyntax;
import org.infinispan.protostream.domain.Address;
import org.infinispan.protostream.domain.PairAdapter;
import org.infinispan.protostream.domain.User;

@AutoProtoSchemaBuilder(
includeClasses = {
User.class,
Address.class,
PairAdapter.class
},
schemaFileName = "user.proto",
schemaFilePath = "proto/",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public XClass fromTypeMirror(TypeMirror typeMirror) {

switch (typeMirror.getKind()) {
case ERROR:
throw new IllegalStateException("Unresolved type : " + typeMirror.toString());
throw new IllegalStateException("Unresolved type : " + typeMirror);
case VOID:
return voidType;
case BOOLEAN:
Expand Down Expand Up @@ -187,6 +187,9 @@ public XClass fromTypeMirror(TypeMirror typeMirror) {
String fqn = "[" + componentType.getName();
return classCache.computeIfAbsent(fqn, k -> new MirrorArray(componentType));
}
case TYPEVAR: {
throw new UnsupportedOperationException("Protostream cannot generate marshallers for generic types. Please use a ProtoAdapter with WrappedMessages");
}
default:
throw new IllegalStateException("Unexpected type kind : " + typeMirror.getKind());
}
Expand Down Expand Up @@ -459,7 +462,7 @@ public Element getElement() {
/**
* Only for declared types, not for primitives, arrays, or void.
*/
private final class MirrorClass implements XClass, HasModelElement {
private class MirrorClass implements XClass, HasModelElement {

private final DeclaredType typeMirror;

Expand Down

0 comments on commit 67873a1

Please sign in to comment.