diff --git a/Examples/Java/Sources/Board.java b/Examples/Java/Sources/Board.java index e3ef3e69..0a5557c5 100644 --- a/Examples/Java/Sources/Board.java +++ b/Examples/Java/Sources/Board.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -34,7 +40,7 @@ public class Board { @SerializedName("image") private @NonNull Image image; @SerializedName("name") private @Nullable String name; @SerializedName("url") private @Nullable String url; - + static final private int ID_SET = 1 << 0; static final private int CONTRIBUTORS_SET = 1 << 1; static final private int COUNTS_SET = 1 << 2; @@ -44,9 +50,9 @@ public class Board { static final private int IMAGE_SET = 1 << 6; static final private int NAME_SET = 1 << 7; static final private int URL_SET = 1 << 8; - + private int _bits = 0; - + private Board( @Nullable String identifier, @Nullable Set contributors, @@ -70,17 +76,21 @@ private Board( this.url = url; this._bits = _bits; } + public static Board.Builder builder() { return new Board.Builder(); } + public Board.Builder toBuilder() { return new Board.Builder(this); } + public Board mergeFrom(Board model) { Board.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -100,6 +110,7 @@ public boolean equals(Object o) { Objects.equals(this.name, that.name) && Objects.equals(this.url, that.url); } + @Override public int hashCode() { return Objects.hash(identifier, @@ -112,62 +123,81 @@ public int hashCode() { name, url); } + public @Nullable String getIdentifier() { return this.identifier; } + public @Nullable Set getContributors() { return this.contributors; } + public @Nullable Map getCounts() { return this.counts; } + public @Nullable Date getCreatedAt() { return this.createdAt; } + public @Nullable Map getCreator() { return this.creator; } + public @Nullable String getDescriptionText() { return this.descriptionText; } + public @NonNull Image getImage() { return this.image; } + public @Nullable String getName() { return this.name; } + public @Nullable String getUrl() { return this.url; } + public boolean getIdentifierIsSet() { return (this._bits & ID_SET) == ID_SET; } + public boolean getContributorsIsSet() { return (this._bits & CONTRIBUTORS_SET) == CONTRIBUTORS_SET; } + public boolean getCountsIsSet() { return (this._bits & COUNTS_SET) == COUNTS_SET; } + public boolean getCreatedAtIsSet() { return (this._bits & CREATED_AT_SET) == CREATED_AT_SET; } + public boolean getCreatorIsSet() { return (this._bits & CREATOR_SET) == CREATOR_SET; } + public boolean getDescriptionTextIsSet() { return (this._bits & DESCRIPTION_SET) == DESCRIPTION_SET; } + public boolean getImageIsSet() { return (this._bits & IMAGE_SET) == IMAGE_SET; } + public boolean getNameIsSet() { return (this._bits & NAME_SET) == NAME_SET; } + public boolean getUrlIsSet() { return (this._bits & URL_SET) == URL_SET; } + public static class Builder { - + @SerializedName("id") private @Nullable String identifier; @SerializedName("contributors") private @Nullable Set contributors; @SerializedName("counts") private @Nullable Map counts; @@ -177,12 +207,12 @@ public static class Builder { @SerializedName("image") private @NonNull Image image; @SerializedName("name") private @Nullable String name; @SerializedName("url") private @Nullable String url; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull Board model) { this.identifier = model.identifier; this.contributors = model.contributors; @@ -195,78 +225,97 @@ private Builder(@NonNull Board model) { this.url = model.url; this._bits = model._bits; } + public Builder setIdentifier(@Nullable String value) { this.identifier = value; this._bits |= ID_SET; return this; } + public Builder setContributors(@Nullable Set value) { this.contributors = value; this._bits |= CONTRIBUTORS_SET; return this; } + public Builder setCounts(@Nullable Map value) { this.counts = value; this._bits |= COUNTS_SET; return this; } + public Builder setCreatedAt(@Nullable Date value) { this.createdAt = value; this._bits |= CREATED_AT_SET; return this; } + public Builder setCreator(@Nullable Map value) { this.creator = value; this._bits |= CREATOR_SET; return this; } + public Builder setDescriptionText(@Nullable String value) { this.descriptionText = value; this._bits |= DESCRIPTION_SET; return this; } + public Builder setImage(@NonNull Image value) { this.image = value; this._bits |= IMAGE_SET; return this; } + public Builder setName(@Nullable String value) { this.name = value; this._bits |= NAME_SET; return this; } + public Builder setUrl(@Nullable String value) { this.url = value; this._bits |= URL_SET; return this; } + public @Nullable String getIdentifier() { return this.identifier; } + public @Nullable Set getContributors() { return this.contributors; } + public @Nullable Map getCounts() { return this.counts; } + public @Nullable Date getCreatedAt() { return this.createdAt; } + public @Nullable Map getCreator() { return this.creator; } + public @Nullable String getDescriptionText() { return this.descriptionText; } + public @NonNull Image getImage() { return this.image; } + public @Nullable String getName() { return this.name; } + public @Nullable String getUrl() { return this.url; } + public Board build() { return new Board( this.identifier, @@ -281,6 +330,7 @@ public Board build() { this._bits ); } + public void mergeFrom(Board model) { if (model.getIdentifierIsSet()) { this.identifier = model.identifier; @@ -310,6 +360,73 @@ public void mergeFrom(Board model) { this.url = model.url; } } - + } + + public static class BoardTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!Board.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new BoardTypeAdapter(gson, this, typeToken); + } + } + + public static class BoardTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public BoardTypeAdapter(Gson gson, BoardTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, Board value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public Board read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + Board model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("id"): + model._bits |= ID_SET; + break; + case ("contributors"): + model._bits |= CONTRIBUTORS_SET; + break; + case ("counts"): + model._bits |= COUNTS_SET; + break; + case ("created_at"): + model._bits |= CREATED_AT_SET; + break; + case ("creator"): + model._bits |= CREATOR_SET; + break; + case ("description"): + model._bits |= DESCRIPTION_SET; + break; + case ("image"): + model._bits |= IMAGE_SET; + break; + case ("name"): + model._bits |= NAME_SET; + break; + case ("url"): + model._bits |= URL_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Examples/Java/Sources/Everything.java b/Examples/Java/Sources/Everything.java index 56aefc52..49bc1526 100644 --- a/Examples/Java/Sources/Everything.java +++ b/Examples/Java/Sources/Everything.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -34,6 +40,7 @@ interface EverythingMapPolymorphicValuesMatcher { } public final class EverythingMapPolymorphicValues { + @Retention(RetentionPolicy.SOURCE) @IntDef({InternalStorage.USER, InternalStorage.BOARD, InternalStorage.IMAGE, InternalStorage.PIN, InternalStorage.EVERYTHING, InternalStorage.LISTOBJECT, InternalStorage.MAPSTRING_OBJECT}) public @interface InternalStorage { @@ -45,6 +52,7 @@ public final class EverythingMapPolymorphicValues { int LISTOBJECT = 5; int MAPSTRING_OBJECT = 6; } + private @Nullable User value0; private @Nullable Board value1; private @Nullable Image value2; @@ -52,16 +60,14 @@ public final class EverythingMapPolymorphicValues { private @Nullable Everything value4; private @Nullable List value5; private @Nullable Map value6; - + private @InternalStorage int internalStorage; - + private EverythingMapPolymorphicValues() { - } + public R match EverythingMapPolymorphicValues(EverythingMapPolymorphicValuesMatcher) { - } - } interface EverythingPolymorphicPropMatcher { @@ -79,6 +85,7 @@ interface EverythingPolymorphicPropMatcher { } public final class EverythingPolymorphicProp { + @Retention(RetentionPolicy.SOURCE) @IntDef({InternalStorage.USER, InternalStorage.BOARD, InternalStorage.IMAGE, InternalStorage.PIN, InternalStorage.EVERYTHING, InternalStorage.STRING, InternalStorage.BOOLEAN, InternalStorage.INTEGER, InternalStorage.DOUBLE, InternalStorage.DATE, InternalStorage.STRING}) public @interface InternalStorage { @@ -94,6 +101,7 @@ public final class EverythingPolymorphicProp { int DATE = 9; int STRING = 10; } + private @Nullable User value0; private @Nullable Board value1; private @Nullable Image value2; @@ -105,19 +113,18 @@ public final class EverythingPolymorphicProp { private @Nullable Double value8; private @Nullable Date value9; private @Nullable String value10; - + private @InternalStorage int internalStorage; - + private EverythingPolymorphicProp() { - } + public R match EverythingPolymorphicProp(EverythingPolymorphicPropMatcher) { - } - } public class Everything { + @Retention(RetentionPolicy.SOURCE) @IntDef({EverythingIntEnum.INT_CASE_1, EverythingIntEnum.INT_CASE_2, EverythingIntEnum.INT_CASE_3}) public @interface EverythingIntEnum { @@ -125,6 +132,7 @@ public class Everything { int INT_CASE_2 = 2; int INT_CASE_3 = 3; } + @Retention(RetentionPolicy.SOURCE) @StringDef({EverythingStringEnum.CASE1, EverythingStringEnum.CASE2, EverythingStringEnum.CASE3}) public @interface EverythingStringEnum { @@ -132,6 +140,7 @@ public class Everything { String CASE2 = "case2"; String CASE3 = "case3"; } + @SerializedName("array_prop") private @Nullable List arrayProp; @SerializedName("boolean_prop") private @Nullable Boolean booleanProp; @SerializedName("date_prop") private @Nullable Date dateProp; @@ -161,7 +170,7 @@ public class Everything { @SerializedName("string_prop") private @Nullable String stringProp; @SerializedName("type") private @Nullable String type; @SerializedName("uri_prop") private @Nullable String uriProp; - + static final private int ARRAY_PROP_SET = 1 << 0; static final private int BOOLEAN_PROP_SET = 1 << 1; static final private int DATE_PROP_SET = 1 << 2; @@ -191,9 +200,9 @@ public class Everything { static final private int STRING_PROP_SET = 1 << 26; static final private int TYPE_SET = 1 << 27; static final private int URI_PROP_SET = 1 << 28; - + private int _bits = 0; - + private Everything( @Nullable List arrayProp, @Nullable Boolean booleanProp, @@ -257,17 +266,21 @@ private Everything( this.uriProp = uriProp; this._bits = _bits; } + public static Everything.Builder builder() { return new Everything.Builder(); } + public Everything.Builder toBuilder() { return new Everything.Builder(this); } + public Everything mergeFrom(Everything model) { Everything.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -307,6 +320,7 @@ public boolean equals(Object o) { Objects.equals(this.type, that.type) && Objects.equals(this.uriProp, that.uriProp); } + @Override public int hashCode() { return Objects.hash(arrayProp, @@ -339,182 +353,241 @@ public int hashCode() { type, uriProp); } + public @Nullable List getArrayProp() { return this.arrayProp; } + public @Nullable Boolean getBooleanProp() { return this.booleanProp; } + public @Nullable Date getDateProp() { return this.dateProp; } + public @Nullable @EverythingIntEnum int getIntEnum() { return this.intEnum; } + public @Nullable Integer getIntProp() { return this.intProp; } + public @Nullable List getListPolymorphicValues() { return this.listPolymorphicValues; } + public @Nullable List> getListWithListAndOtherModelValues() { return this.listWithListAndOtherModelValues; } + public @Nullable List> getListWithMapAndOtherModelValues() { return this.listWithMapAndOtherModelValues; } + public @Nullable List getListWithObjectValues() { return this.listWithObjectValues; } + public @Nullable List getListWithOtherModelValues() { return this.listWithOtherModelValues; } + public @Nullable List getListWithPrimitiveValues() { return this.listWithPrimitiveValues; } + public @Nullable Map getMapPolymorphicValues() { return this.mapPolymorphicValues; } + public @Nullable Map getMapProp() { return this.mapProp; } + public @Nullable Map> getMapWithListAndOtherModelValues() { return this.mapWithListAndOtherModelValues; } + public @Nullable Map> getMapWithMapAndOtherModelValues() { return this.mapWithMapAndOtherModelValues; } + public @Nullable Map getMapWithObjectValues() { return this.mapWithObjectValues; } + public @Nullable Map getMapWithOtherModelValues() { return this.mapWithOtherModelValues; } + public @Nullable Map getMapWithPrimitiveValues() { return this.mapWithPrimitiveValues; } + public @Nullable Double getNumberProp() { return this.numberProp; } + public @Nullable User getOtherModelProp() { return this.otherModelProp; } + public @Nullable EverythingPolymorphicProp getPolymorphicProp() { return this.polymorphicProp; } + public @Nullable Set getSetProp() { return this.setProp; } + public @Nullable Set getSetPropWithOtherModelValues() { return this.setPropWithOtherModelValues; } + public @Nullable Set getSetPropWithPrimitiveValues() { return this.setPropWithPrimitiveValues; } + public @Nullable Set getSetPropWithValues() { return this.setPropWithValues; } + public @Nullable @EverythingStringEnum String getStringEnum() { return this.stringEnum; } + public @Nullable String getStringProp() { return this.stringProp; } + public @Nullable String getType() { return this.type; } + public @Nullable String getUriProp() { return this.uriProp; } + public boolean getArrayPropIsSet() { return (this._bits & ARRAY_PROP_SET) == ARRAY_PROP_SET; } + public boolean getBooleanPropIsSet() { return (this._bits & BOOLEAN_PROP_SET) == BOOLEAN_PROP_SET; } + public boolean getDatePropIsSet() { return (this._bits & DATE_PROP_SET) == DATE_PROP_SET; } + public boolean getIntEnumIsSet() { return (this._bits & INT_ENUM_SET) == INT_ENUM_SET; } + public boolean getIntPropIsSet() { return (this._bits & INT_PROP_SET) == INT_PROP_SET; } + public boolean getListPolymorphicValuesIsSet() { return (this._bits & LIST_POLYMORPHIC_VALUES_SET) == LIST_POLYMORPHIC_VALUES_SET; } + public boolean getListWithListAndOtherModelValuesIsSet() { return (this._bits & LIST_WITH_LIST_AND_OTHER_MODEL_VALUES_SET) == LIST_WITH_LIST_AND_OTHER_MODEL_VALUES_SET; } + public boolean getListWithMapAndOtherModelValuesIsSet() { return (this._bits & LIST_WITH_MAP_AND_OTHER_MODEL_VALUES_SET) == LIST_WITH_MAP_AND_OTHER_MODEL_VALUES_SET; } + public boolean getListWithObjectValuesIsSet() { return (this._bits & LIST_WITH_OBJECT_VALUES_SET) == LIST_WITH_OBJECT_VALUES_SET; } + public boolean getListWithOtherModelValuesIsSet() { return (this._bits & LIST_WITH_OTHER_MODEL_VALUES_SET) == LIST_WITH_OTHER_MODEL_VALUES_SET; } + public boolean getListWithPrimitiveValuesIsSet() { return (this._bits & LIST_WITH_PRIMITIVE_VALUES_SET) == LIST_WITH_PRIMITIVE_VALUES_SET; } + public boolean getMapPolymorphicValuesIsSet() { return (this._bits & MAP_POLYMORPHIC_VALUES_SET) == MAP_POLYMORPHIC_VALUES_SET; } + public boolean getMapPropIsSet() { return (this._bits & MAP_PROP_SET) == MAP_PROP_SET; } + public boolean getMapWithListAndOtherModelValuesIsSet() { return (this._bits & MAP_WITH_LIST_AND_OTHER_MODEL_VALUES_SET) == MAP_WITH_LIST_AND_OTHER_MODEL_VALUES_SET; } + public boolean getMapWithMapAndOtherModelValuesIsSet() { return (this._bits & MAP_WITH_MAP_AND_OTHER_MODEL_VALUES_SET) == MAP_WITH_MAP_AND_OTHER_MODEL_VALUES_SET; } + public boolean getMapWithObjectValuesIsSet() { return (this._bits & MAP_WITH_OBJECT_VALUES_SET) == MAP_WITH_OBJECT_VALUES_SET; } + public boolean getMapWithOtherModelValuesIsSet() { return (this._bits & MAP_WITH_OTHER_MODEL_VALUES_SET) == MAP_WITH_OTHER_MODEL_VALUES_SET; } + public boolean getMapWithPrimitiveValuesIsSet() { return (this._bits & MAP_WITH_PRIMITIVE_VALUES_SET) == MAP_WITH_PRIMITIVE_VALUES_SET; } + public boolean getNumberPropIsSet() { return (this._bits & NUMBER_PROP_SET) == NUMBER_PROP_SET; } + public boolean getOtherModelPropIsSet() { return (this._bits & OTHER_MODEL_PROP_SET) == OTHER_MODEL_PROP_SET; } + public boolean getPolymorphicPropIsSet() { return (this._bits & POLYMORPHIC_PROP_SET) == POLYMORPHIC_PROP_SET; } + public boolean getSetPropIsSet() { return (this._bits & SET_PROP_SET) == SET_PROP_SET; } + public boolean getSetPropWithOtherModelValuesIsSet() { return (this._bits & SET_PROP_WITH_OTHER_MODEL_VALUES_SET) == SET_PROP_WITH_OTHER_MODEL_VALUES_SET; } + public boolean getSetPropWithPrimitiveValuesIsSet() { return (this._bits & SET_PROP_WITH_PRIMITIVE_VALUES_SET) == SET_PROP_WITH_PRIMITIVE_VALUES_SET; } + public boolean getSetPropWithValuesIsSet() { return (this._bits & SET_PROP_WITH_VALUES_SET) == SET_PROP_WITH_VALUES_SET; } + public boolean getStringEnumIsSet() { return (this._bits & STRING_ENUM_SET) == STRING_ENUM_SET; } + public boolean getStringPropIsSet() { return (this._bits & STRING_PROP_SET) == STRING_PROP_SET; } + public boolean getTypeIsSet() { return (this._bits & TYPE_SET) == TYPE_SET; } + public boolean getUriPropIsSet() { return (this._bits & URI_PROP_SET) == URI_PROP_SET; } + public static class Builder { - + @SerializedName("array_prop") private @Nullable List arrayProp; @SerializedName("boolean_prop") private @Nullable Boolean booleanProp; @SerializedName("date_prop") private @Nullable Date dateProp; @@ -544,12 +617,12 @@ public static class Builder { @SerializedName("string_prop") private @Nullable String stringProp; @SerializedName("type") private @Nullable String type; @SerializedName("uri_prop") private @Nullable String uriProp; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull Everything model) { this.arrayProp = model.arrayProp; this.booleanProp = model.booleanProp; @@ -582,238 +655,297 @@ private Builder(@NonNull Everything model) { this.uriProp = model.uriProp; this._bits = model._bits; } + public Builder setArrayProp(@Nullable List value) { this.arrayProp = value; this._bits |= ARRAY_PROP_SET; return this; } + public Builder setBooleanProp(@Nullable Boolean value) { this.booleanProp = value; this._bits |= BOOLEAN_PROP_SET; return this; } + public Builder setDateProp(@Nullable Date value) { this.dateProp = value; this._bits |= DATE_PROP_SET; return this; } + public Builder setIntEnum(@Nullable @EverythingIntEnum int value) { this.intEnum = value; this._bits |= INT_ENUM_SET; return this; } + public Builder setIntProp(@Nullable Integer value) { this.intProp = value; this._bits |= INT_PROP_SET; return this; } + public Builder setListPolymorphicValues(@Nullable List value) { this.listPolymorphicValues = value; this._bits |= LIST_POLYMORPHIC_VALUES_SET; return this; } + public Builder setListWithListAndOtherModelValues(@Nullable List> value) { this.listWithListAndOtherModelValues = value; this._bits |= LIST_WITH_LIST_AND_OTHER_MODEL_VALUES_SET; return this; } + public Builder setListWithMapAndOtherModelValues(@Nullable List> value) { this.listWithMapAndOtherModelValues = value; this._bits |= LIST_WITH_MAP_AND_OTHER_MODEL_VALUES_SET; return this; } + public Builder setListWithObjectValues(@Nullable List value) { this.listWithObjectValues = value; this._bits |= LIST_WITH_OBJECT_VALUES_SET; return this; } + public Builder setListWithOtherModelValues(@Nullable List value) { this.listWithOtherModelValues = value; this._bits |= LIST_WITH_OTHER_MODEL_VALUES_SET; return this; } + public Builder setListWithPrimitiveValues(@Nullable List value) { this.listWithPrimitiveValues = value; this._bits |= LIST_WITH_PRIMITIVE_VALUES_SET; return this; } + public Builder setMapPolymorphicValues(@Nullable Map value) { this.mapPolymorphicValues = value; this._bits |= MAP_POLYMORPHIC_VALUES_SET; return this; } + public Builder setMapProp(@Nullable Map value) { this.mapProp = value; this._bits |= MAP_PROP_SET; return this; } + public Builder setMapWithListAndOtherModelValues(@Nullable Map> value) { this.mapWithListAndOtherModelValues = value; this._bits |= MAP_WITH_LIST_AND_OTHER_MODEL_VALUES_SET; return this; } + public Builder setMapWithMapAndOtherModelValues(@Nullable Map> value) { this.mapWithMapAndOtherModelValues = value; this._bits |= MAP_WITH_MAP_AND_OTHER_MODEL_VALUES_SET; return this; } + public Builder setMapWithObjectValues(@Nullable Map value) { this.mapWithObjectValues = value; this._bits |= MAP_WITH_OBJECT_VALUES_SET; return this; } + public Builder setMapWithOtherModelValues(@Nullable Map value) { this.mapWithOtherModelValues = value; this._bits |= MAP_WITH_OTHER_MODEL_VALUES_SET; return this; } + public Builder setMapWithPrimitiveValues(@Nullable Map value) { this.mapWithPrimitiveValues = value; this._bits |= MAP_WITH_PRIMITIVE_VALUES_SET; return this; } + public Builder setNumberProp(@Nullable Double value) { this.numberProp = value; this._bits |= NUMBER_PROP_SET; return this; } + public Builder setOtherModelProp(@Nullable User value) { this.otherModelProp = value; this._bits |= OTHER_MODEL_PROP_SET; return this; } + public Builder setPolymorphicProp(@Nullable EverythingPolymorphicProp value) { this.polymorphicProp = value; this._bits |= POLYMORPHIC_PROP_SET; return this; } + public Builder setSetProp(@Nullable Set value) { this.setProp = value; this._bits |= SET_PROP_SET; return this; } + public Builder setSetPropWithOtherModelValues(@Nullable Set value) { this.setPropWithOtherModelValues = value; this._bits |= SET_PROP_WITH_OTHER_MODEL_VALUES_SET; return this; } + public Builder setSetPropWithPrimitiveValues(@Nullable Set value) { this.setPropWithPrimitiveValues = value; this._bits |= SET_PROP_WITH_PRIMITIVE_VALUES_SET; return this; } + public Builder setSetPropWithValues(@Nullable Set value) { this.setPropWithValues = value; this._bits |= SET_PROP_WITH_VALUES_SET; return this; } + public Builder setStringEnum(@Nullable @EverythingStringEnum String value) { this.stringEnum = value; this._bits |= STRING_ENUM_SET; return this; } + public Builder setStringProp(@Nullable String value) { this.stringProp = value; this._bits |= STRING_PROP_SET; return this; } + public Builder setType(@Nullable String value) { this.type = value; this._bits |= TYPE_SET; return this; } + public Builder setUriProp(@Nullable String value) { this.uriProp = value; this._bits |= URI_PROP_SET; return this; } + public @Nullable List getArrayProp() { return this.arrayProp; } + public @Nullable Boolean getBooleanProp() { return this.booleanProp; } + public @Nullable Date getDateProp() { return this.dateProp; } + public @Nullable @EverythingIntEnum int getIntEnum() { return this.intEnum; } + public @Nullable Integer getIntProp() { return this.intProp; } + public @Nullable List getListPolymorphicValues() { return this.listPolymorphicValues; } + public @Nullable List> getListWithListAndOtherModelValues() { return this.listWithListAndOtherModelValues; } + public @Nullable List> getListWithMapAndOtherModelValues() { return this.listWithMapAndOtherModelValues; } + public @Nullable List getListWithObjectValues() { return this.listWithObjectValues; } + public @Nullable List getListWithOtherModelValues() { return this.listWithOtherModelValues; } + public @Nullable List getListWithPrimitiveValues() { return this.listWithPrimitiveValues; } + public @Nullable Map getMapPolymorphicValues() { return this.mapPolymorphicValues; } + public @Nullable Map getMapProp() { return this.mapProp; } + public @Nullable Map> getMapWithListAndOtherModelValues() { return this.mapWithListAndOtherModelValues; } + public @Nullable Map> getMapWithMapAndOtherModelValues() { return this.mapWithMapAndOtherModelValues; } + public @Nullable Map getMapWithObjectValues() { return this.mapWithObjectValues; } + public @Nullable Map getMapWithOtherModelValues() { return this.mapWithOtherModelValues; } + public @Nullable Map getMapWithPrimitiveValues() { return this.mapWithPrimitiveValues; } + public @Nullable Double getNumberProp() { return this.numberProp; } + public @Nullable User getOtherModelProp() { return this.otherModelProp; } + public @Nullable EverythingPolymorphicProp getPolymorphicProp() { return this.polymorphicProp; } + public @Nullable Set getSetProp() { return this.setProp; } + public @Nullable Set getSetPropWithOtherModelValues() { return this.setPropWithOtherModelValues; } + public @Nullable Set getSetPropWithPrimitiveValues() { return this.setPropWithPrimitiveValues; } + public @Nullable Set getSetPropWithValues() { return this.setPropWithValues; } + public @Nullable @EverythingStringEnum String getStringEnum() { return this.stringEnum; } + public @Nullable String getStringProp() { return this.stringProp; } + public @Nullable String getType() { return this.type; } + public @Nullable String getUriProp() { return this.uriProp; } + public Everything build() { return new Everything( this.arrayProp, @@ -848,6 +980,7 @@ public Everything build() { this._bits ); } + public void mergeFrom(Everything model) { if (model.getArrayPropIsSet()) { this.arrayProp = model.arrayProp; @@ -937,6 +1070,133 @@ public void mergeFrom(Everything model) { this.uriProp = model.uriProp; } } - + } + + public static class EverythingTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!Everything.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new EverythingTypeAdapter(gson, this, typeToken); + } + } + + public static class EverythingTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public EverythingTypeAdapter(Gson gson, EverythingTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, Everything value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public Everything read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + Everything model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("array_prop"): + model._bits |= ARRAY_PROP_SET; + break; + case ("boolean_prop"): + model._bits |= BOOLEAN_PROP_SET; + break; + case ("date_prop"): + model._bits |= DATE_PROP_SET; + break; + case ("int_enum"): + model._bits |= INT_ENUM_SET; + break; + case ("int_prop"): + model._bits |= INT_PROP_SET; + break; + case ("list_polymorphic_values"): + model._bits |= LIST_POLYMORPHIC_VALUES_SET; + break; + case ("list_with_list_and_other_model_values"): + model._bits |= LIST_WITH_LIST_AND_OTHER_MODEL_VALUES_SET; + break; + case ("list_with_map_and_other_model_values"): + model._bits |= LIST_WITH_MAP_AND_OTHER_MODEL_VALUES_SET; + break; + case ("list_with_object_values"): + model._bits |= LIST_WITH_OBJECT_VALUES_SET; + break; + case ("list_with_other_model_values"): + model._bits |= LIST_WITH_OTHER_MODEL_VALUES_SET; + break; + case ("list_with_primitive_values"): + model._bits |= LIST_WITH_PRIMITIVE_VALUES_SET; + break; + case ("map_polymorphic_values"): + model._bits |= MAP_POLYMORPHIC_VALUES_SET; + break; + case ("map_prop"): + model._bits |= MAP_PROP_SET; + break; + case ("map_with_list_and_other_model_values"): + model._bits |= MAP_WITH_LIST_AND_OTHER_MODEL_VALUES_SET; + break; + case ("map_with_map_and_other_model_values"): + model._bits |= MAP_WITH_MAP_AND_OTHER_MODEL_VALUES_SET; + break; + case ("map_with_object_values"): + model._bits |= MAP_WITH_OBJECT_VALUES_SET; + break; + case ("map_with_other_model_values"): + model._bits |= MAP_WITH_OTHER_MODEL_VALUES_SET; + break; + case ("map_with_primitive_values"): + model._bits |= MAP_WITH_PRIMITIVE_VALUES_SET; + break; + case ("number_prop"): + model._bits |= NUMBER_PROP_SET; + break; + case ("other_model_prop"): + model._bits |= OTHER_MODEL_PROP_SET; + break; + case ("polymorphic_prop"): + model._bits |= POLYMORPHIC_PROP_SET; + break; + case ("set_prop"): + model._bits |= SET_PROP_SET; + break; + case ("set_prop_with_other_model_values"): + model._bits |= SET_PROP_WITH_OTHER_MODEL_VALUES_SET; + break; + case ("set_prop_with_primitive_values"): + model._bits |= SET_PROP_WITH_PRIMITIVE_VALUES_SET; + break; + case ("set_prop_with_values"): + model._bits |= SET_PROP_WITH_VALUES_SET; + break; + case ("string_enum"): + model._bits |= STRING_ENUM_SET; + break; + case ("string_prop"): + model._bits |= STRING_PROP_SET; + break; + case ("type"): + model._bits |= TYPE_SET; + break; + case ("uri_prop"): + model._bits |= URI_PROP_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Examples/Java/Sources/Image.java b/Examples/Java/Sources/Image.java index ff0b2265..320d62cf 100644 --- a/Examples/Java/Sources/Image.java +++ b/Examples/Java/Sources/Image.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -28,13 +34,13 @@ public class Image { @SerializedName("height") private @Nullable Integer height; @SerializedName("url") private @Nullable String url; @SerializedName("width") private @Nullable Integer width; - + static final private int HEIGHT_SET = 1 << 0; static final private int URL_SET = 1 << 1; static final private int WIDTH_SET = 1 << 2; - + private int _bits = 0; - + private Image( @Nullable Integer height, @Nullable String url, @@ -46,17 +52,21 @@ private Image( this.width = width; this._bits = _bits; } + public static Image.Builder builder() { return new Image.Builder(); } + public Image.Builder toBuilder() { return new Image.Builder(this); } + public Image mergeFrom(Image model) { Image.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -70,71 +80,86 @@ public boolean equals(Object o) { Objects.equals(this.url, that.url) && Objects.equals(this.width, that.width); } + @Override public int hashCode() { return Objects.hash(height, url, width); } + public @Nullable Integer getHeight() { return this.height; } + public @Nullable String getUrl() { return this.url; } + public @Nullable Integer getWidth() { return this.width; } + public boolean getHeightIsSet() { return (this._bits & HEIGHT_SET) == HEIGHT_SET; } + public boolean getUrlIsSet() { return (this._bits & URL_SET) == URL_SET; } + public boolean getWidthIsSet() { return (this._bits & WIDTH_SET) == WIDTH_SET; } + public static class Builder { - + @SerializedName("height") private @Nullable Integer height; @SerializedName("url") private @Nullable String url; @SerializedName("width") private @Nullable Integer width; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull Image model) { this.height = model.height; this.url = model.url; this.width = model.width; this._bits = model._bits; } + public Builder setHeight(@Nullable Integer value) { this.height = value; this._bits |= HEIGHT_SET; return this; } + public Builder setUrl(@Nullable String value) { this.url = value; this._bits |= URL_SET; return this; } + public Builder setWidth(@Nullable Integer value) { this.width = value; this._bits |= WIDTH_SET; return this; } + public @Nullable Integer getHeight() { return this.height; } + public @Nullable String getUrl() { return this.url; } + public @Nullable Integer getWidth() { return this.width; } + public Image build() { return new Image( this.height, @@ -143,6 +168,7 @@ public Image build() { this._bits ); } + public void mergeFrom(Image model) { if (model.getHeightIsSet()) { this.height = model.height; @@ -154,6 +180,55 @@ public void mergeFrom(Image model) { this.width = model.width; } } - + } + + public static class ImageTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!Image.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new ImageTypeAdapter(gson, this, typeToken); + } + } + + public static class ImageTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public ImageTypeAdapter(Gson gson, ImageTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, Image value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public Image read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + Image model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("height"): + model._bits |= HEIGHT_SET; + break; + case ("url"): + model._bits |= URL_SET; + break; + case ("width"): + model._bits |= WIDTH_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Examples/Java/Sources/Model.java b/Examples/Java/Sources/Model.java index 58912a2e..a0431fb5 100644 --- a/Examples/Java/Sources/Model.java +++ b/Examples/Java/Sources/Model.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -26,11 +32,11 @@ public class Model { @SerializedName("id") private @Nullable String identifier; - + static final private int ID_SET = 1 << 0; - + private int _bits = 0; - + private Model( @Nullable String identifier, int _bits @@ -38,17 +44,21 @@ private Model( this.identifier = identifier; this._bits = _bits; } + public static Model.Builder builder() { return new Model.Builder(); } + public Model.Builder toBuilder() { return new Model.Builder(this); } + public Model mergeFrom(Model model) { Model.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -60,48 +70,99 @@ public boolean equals(Object o) { Model that = (Model) o; return Objects.equals(this.identifier, that.identifier); } + @Override public int hashCode() { return Objects.hash(identifier); } + public @Nullable String getIdentifier() { return this.identifier; } + public boolean getIdentifierIsSet() { return (this._bits & ID_SET) == ID_SET; } + public static class Builder { - + @SerializedName("id") private @Nullable String identifier; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull Model model) { this.identifier = model.identifier; this._bits = model._bits; } + public Builder setIdentifier(@Nullable String value) { this.identifier = value; this._bits |= ID_SET; return this; } + public @Nullable String getIdentifier() { return this.identifier; } + public Model build() { return new Model( this.identifier, this._bits ); } + public void mergeFrom(Model model) { if (model.getIdentifierIsSet()) { this.identifier = model.identifier; } } - + } + + public static class ModelTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!Model.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new ModelTypeAdapter(gson, this, typeToken); + } + } + + public static class ModelTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public ModelTypeAdapter(Gson gson, ModelTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, Model value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public Model read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + Model model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("id"): + model._bits |= ID_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Examples/Java/Sources/Pin.java b/Examples/Java/Sources/Pin.java index 71b37146..6e0fca78 100644 --- a/Examples/Java/Sources/Pin.java +++ b/Examples/Java/Sources/Pin.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -29,27 +35,28 @@ interface PinAttributionObjectsMatcher { } public final class PinAttributionObjects { + @Retention(RetentionPolicy.SOURCE) @IntDef({InternalStorage.BOARD, InternalStorage.USER}) public @interface InternalStorage { int BOARD = 0; int USER = 1; } + private @Nullable Board value0; private @Nullable User value1; - + private @InternalStorage int internalStorage; - + private PinAttributionObjects() { - } + public R match PinAttributionObjects(PinAttributionObjectsMatcher) { - } - } public class Pin { + @Retention(RetentionPolicy.SOURCE) @IntDef({PinInStock.UNKNOWN, PinInStock.OUT_OF_STOCK, PinInStock.IN_STOCK}) public @interface PinInStock { @@ -57,6 +64,7 @@ public class Pin { int OUT_OF_STOCK = 0; int IN_STOCK = 1; } + @SerializedName("attribution") private @Nullable Map attribution; @SerializedName("attribution_objects") private @Nullable List attributionObjects; @SerializedName("board") private @Nullable Board board; @@ -74,7 +82,7 @@ public class Pin { @SerializedName("tags") private @Nullable List> tags; @SerializedName("url") private @Nullable String url; @SerializedName("visual_search_attrs") private @Nullable Map visualSearchAttrs; - + static final private int ATTRIBUTION_SET = 1 << 0; static final private int ATTRIBUTION_OBJECTS_SET = 1 << 1; static final private int BOARD_SET = 1 << 2; @@ -92,9 +100,9 @@ public class Pin { static final private int TAGS_SET = 1 << 14; static final private int URL_SET = 1 << 15; static final private int VISUAL_SEARCH_ATTRS_SET = 1 << 16; - + private int _bits = 0; - + private Pin( @Nullable Map attribution, @Nullable List attributionObjects, @@ -134,17 +142,21 @@ private Pin( this.visualSearchAttrs = visualSearchAttrs; this._bits = _bits; } + public static Pin.Builder builder() { return new Pin.Builder(); } + public Pin.Builder toBuilder() { return new Pin.Builder(this); } + public Pin mergeFrom(Pin model) { Pin.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -172,6 +184,7 @@ public boolean equals(Object o) { Objects.equals(this.url, that.url) && Objects.equals(this.visualSearchAttrs, that.visualSearchAttrs); } + @Override public int hashCode() { return Objects.hash(attribution, @@ -192,110 +205,145 @@ public int hashCode() { url, visualSearchAttrs); } + public @Nullable Map getAttribution() { return this.attribution; } + public @Nullable List getAttributionObjects() { return this.attributionObjects; } + public @Nullable Board getBoard() { return this.board; } + public @Nullable String getColor() { return this.color; } + public @Nullable Map getCounts() { return this.counts; } + public @NonNull Date getCreatedAt() { return this.createdAt; } + public @NonNull Map getCreator() { return this.creator; } + public @Nullable String getDescriptionText() { return this.descriptionText; } + public @NonNull String getIdentifier() { return this.identifier; } + public @Nullable Image getImage() { return this.image; } + public @Nullable @PinInStock int getInStock() { return this.inStock; } + public @Nullable String getLink() { return this.link; } + public @Nullable Map getMedia() { return this.media; } + public @Nullable String getNote() { return this.note; } + public @Nullable List> getTags() { return this.tags; } + public @Nullable String getUrl() { return this.url; } + public @Nullable Map getVisualSearchAttrs() { return this.visualSearchAttrs; } + public boolean getAttributionIsSet() { return (this._bits & ATTRIBUTION_SET) == ATTRIBUTION_SET; } + public boolean getAttributionObjectsIsSet() { return (this._bits & ATTRIBUTION_OBJECTS_SET) == ATTRIBUTION_OBJECTS_SET; } + public boolean getBoardIsSet() { return (this._bits & BOARD_SET) == BOARD_SET; } + public boolean getColorIsSet() { return (this._bits & COLOR_SET) == COLOR_SET; } + public boolean getCountsIsSet() { return (this._bits & COUNTS_SET) == COUNTS_SET; } + public boolean getCreatedAtIsSet() { return (this._bits & CREATED_AT_SET) == CREATED_AT_SET; } + public boolean getCreatorIsSet() { return (this._bits & CREATOR_SET) == CREATOR_SET; } + public boolean getDescriptionTextIsSet() { return (this._bits & DESCRIPTION_SET) == DESCRIPTION_SET; } + public boolean getIdentifierIsSet() { return (this._bits & ID_SET) == ID_SET; } + public boolean getImageIsSet() { return (this._bits & IMAGE_SET) == IMAGE_SET; } + public boolean getInStockIsSet() { return (this._bits & IN_STOCK_SET) == IN_STOCK_SET; } + public boolean getLinkIsSet() { return (this._bits & LINK_SET) == LINK_SET; } + public boolean getMediaIsSet() { return (this._bits & MEDIA_SET) == MEDIA_SET; } + public boolean getNoteIsSet() { return (this._bits & NOTE_SET) == NOTE_SET; } + public boolean getTagsIsSet() { return (this._bits & TAGS_SET) == TAGS_SET; } + public boolean getUrlIsSet() { return (this._bits & URL_SET) == URL_SET; } + public boolean getVisualSearchAttrsIsSet() { return (this._bits & VISUAL_SEARCH_ATTRS_SET) == VISUAL_SEARCH_ATTRS_SET; } + public static class Builder { - + @SerializedName("attribution") private @Nullable Map attribution; @SerializedName("attribution_objects") private @Nullable List attributionObjects; @SerializedName("board") private @Nullable Board board; @@ -313,12 +361,12 @@ public static class Builder { @SerializedName("tags") private @Nullable List> tags; @SerializedName("url") private @Nullable String url; @SerializedName("visual_search_attrs") private @Nullable Map visualSearchAttrs; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull Pin model) { this.attribution = model.attribution; this.attributionObjects = model.attributionObjects; @@ -339,142 +387,177 @@ private Builder(@NonNull Pin model) { this.visualSearchAttrs = model.visualSearchAttrs; this._bits = model._bits; } + public Builder setAttribution(@Nullable Map value) { this.attribution = value; this._bits |= ATTRIBUTION_SET; return this; } + public Builder setAttributionObjects(@Nullable List value) { this.attributionObjects = value; this._bits |= ATTRIBUTION_OBJECTS_SET; return this; } + public Builder setBoard(@Nullable Board value) { this.board = value; this._bits |= BOARD_SET; return this; } + public Builder setColor(@Nullable String value) { this.color = value; this._bits |= COLOR_SET; return this; } + public Builder setCounts(@Nullable Map value) { this.counts = value; this._bits |= COUNTS_SET; return this; } + public Builder setCreatedAt(@NonNull Date value) { this.createdAt = value; this._bits |= CREATED_AT_SET; return this; } + public Builder setCreator(@NonNull Map value) { this.creator = value; this._bits |= CREATOR_SET; return this; } + public Builder setDescriptionText(@Nullable String value) { this.descriptionText = value; this._bits |= DESCRIPTION_SET; return this; } + public Builder setIdentifier(@NonNull String value) { this.identifier = value; this._bits |= ID_SET; return this; } + public Builder setImage(@Nullable Image value) { this.image = value; this._bits |= IMAGE_SET; return this; } + public Builder setInStock(@Nullable @PinInStock int value) { this.inStock = value; this._bits |= IN_STOCK_SET; return this; } + public Builder setLink(@Nullable String value) { this.link = value; this._bits |= LINK_SET; return this; } + public Builder setMedia(@Nullable Map value) { this.media = value; this._bits |= MEDIA_SET; return this; } + public Builder setNote(@Nullable String value) { this.note = value; this._bits |= NOTE_SET; return this; } + public Builder setTags(@Nullable List> value) { this.tags = value; this._bits |= TAGS_SET; return this; } + public Builder setUrl(@Nullable String value) { this.url = value; this._bits |= URL_SET; return this; } + public Builder setVisualSearchAttrs(@Nullable Map value) { this.visualSearchAttrs = value; this._bits |= VISUAL_SEARCH_ATTRS_SET; return this; } + public @Nullable Map getAttribution() { return this.attribution; } + public @Nullable List getAttributionObjects() { return this.attributionObjects; } + public @Nullable Board getBoard() { return this.board; } + public @Nullable String getColor() { return this.color; } + public @Nullable Map getCounts() { return this.counts; } + public @NonNull Date getCreatedAt() { return this.createdAt; } + public @NonNull Map getCreator() { return this.creator; } + public @Nullable String getDescriptionText() { return this.descriptionText; } + public @NonNull String getIdentifier() { return this.identifier; } + public @Nullable Image getImage() { return this.image; } + public @Nullable @PinInStock int getInStock() { return this.inStock; } + public @Nullable String getLink() { return this.link; } + public @Nullable Map getMedia() { return this.media; } + public @Nullable String getNote() { return this.note; } + public @Nullable List> getTags() { return this.tags; } + public @Nullable String getUrl() { return this.url; } + public @Nullable Map getVisualSearchAttrs() { return this.visualSearchAttrs; } + public Pin build() { return new Pin( this.attribution, @@ -497,6 +580,7 @@ public Pin build() { this._bits ); } + public void mergeFrom(Pin model) { if (model.getAttributionIsSet()) { this.attribution = model.attribution; @@ -550,6 +634,97 @@ public void mergeFrom(Pin model) { this.visualSearchAttrs = model.visualSearchAttrs; } } - + } + + public static class PinTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!Pin.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new PinTypeAdapter(gson, this, typeToken); + } + } + + public static class PinTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public PinTypeAdapter(Gson gson, PinTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, Pin value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public Pin read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + Pin model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("attribution"): + model._bits |= ATTRIBUTION_SET; + break; + case ("attribution_objects"): + model._bits |= ATTRIBUTION_OBJECTS_SET; + break; + case ("board"): + model._bits |= BOARD_SET; + break; + case ("color"): + model._bits |= COLOR_SET; + break; + case ("counts"): + model._bits |= COUNTS_SET; + break; + case ("created_at"): + model._bits |= CREATED_AT_SET; + break; + case ("creator"): + model._bits |= CREATOR_SET; + break; + case ("description"): + model._bits |= DESCRIPTION_SET; + break; + case ("id"): + model._bits |= ID_SET; + break; + case ("image"): + model._bits |= IMAGE_SET; + break; + case ("in_stock"): + model._bits |= IN_STOCK_SET; + break; + case ("link"): + model._bits |= LINK_SET; + break; + case ("media"): + model._bits |= MEDIA_SET; + break; + case ("note"): + model._bits |= NOTE_SET; + break; + case ("tags"): + model._bits |= TAGS_SET; + break; + case ("url"): + model._bits |= URL_SET; + break; + case ("visual_search_attrs"): + model._bits |= VISUAL_SEARCH_ATTRS_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Examples/Java/Sources/User.java b/Examples/Java/Sources/User.java index 1a2941ab..d733f905 100644 --- a/Examples/Java/Sources/User.java +++ b/Examples/Java/Sources/User.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -24,6 +30,7 @@ import java.util.Set; public class User { + @Retention(RetentionPolicy.SOURCE) @StringDef({UserEmailFrequency.UNSET, UserEmailFrequency.IMMEDIATE, UserEmailFrequency.DAILY}) public @interface UserEmailFrequency { @@ -31,6 +38,7 @@ public class User { String IMMEDIATE = "immediate"; String DAILY = "daily"; } + @SerializedName("bio") private @Nullable String bio; @SerializedName("counts") private @Nullable Map counts; @SerializedName("created_at") private @Nullable Date createdAt; @@ -41,7 +49,7 @@ public class User { @SerializedName("last_name") private @Nullable String lastName; @SerializedName("type") private @Nullable String type; @SerializedName("username") private @Nullable String username; - + static final private int BIO_SET = 1 << 0; static final private int COUNTS_SET = 1 << 1; static final private int CREATED_AT_SET = 1 << 2; @@ -52,9 +60,9 @@ public class User { static final private int LAST_NAME_SET = 1 << 7; static final private int TYPE_SET = 1 << 8; static final private int USERNAME_SET = 1 << 9; - + private int _bits = 0; - + private User( @Nullable String bio, @Nullable Map counts, @@ -80,17 +88,21 @@ private User( this.username = username; this._bits = _bits; } + public static User.Builder builder() { return new User.Builder(); } + public User.Builder toBuilder() { return new User.Builder(this); } + public User mergeFrom(User model) { User.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -111,6 +123,7 @@ public boolean equals(Object o) { Objects.equals(this.type, that.type) && Objects.equals(this.username, that.username); } + @Override public int hashCode() { return Objects.hash(bio, @@ -124,68 +137,89 @@ public int hashCode() { type, username); } + public @Nullable String getBio() { return this.bio; } + public @Nullable Map getCounts() { return this.counts; } + public @Nullable Date getCreatedAt() { return this.createdAt; } + public @Nullable @UserEmailFrequency String getEmailFrequency() { return this.emailFrequency; } + public @Nullable String getFirstName() { return this.firstName; } + public @Nullable String getIdentifier() { return this.identifier; } + public @Nullable Image getImage() { return this.image; } + public @Nullable String getLastName() { return this.lastName; } + public @Nullable String getType() { return this.type; } + public @Nullable String getUsername() { return this.username; } + public boolean getBioIsSet() { return (this._bits & BIO_SET) == BIO_SET; } + public boolean getCountsIsSet() { return (this._bits & COUNTS_SET) == COUNTS_SET; } + public boolean getCreatedAtIsSet() { return (this._bits & CREATED_AT_SET) == CREATED_AT_SET; } + public boolean getEmailFrequencyIsSet() { return (this._bits & EMAIL_FREQUENCY_SET) == EMAIL_FREQUENCY_SET; } + public boolean getFirstNameIsSet() { return (this._bits & FIRST_NAME_SET) == FIRST_NAME_SET; } + public boolean getIdentifierIsSet() { return (this._bits & ID_SET) == ID_SET; } + public boolean getImageIsSet() { return (this._bits & IMAGE_SET) == IMAGE_SET; } + public boolean getLastNameIsSet() { return (this._bits & LAST_NAME_SET) == LAST_NAME_SET; } + public boolean getTypeIsSet() { return (this._bits & TYPE_SET) == TYPE_SET; } + public boolean getUsernameIsSet() { return (this._bits & USERNAME_SET) == USERNAME_SET; } + public static class Builder { - + @SerializedName("bio") private @Nullable String bio; @SerializedName("counts") private @Nullable Map counts; @SerializedName("created_at") private @Nullable Date createdAt; @@ -196,12 +230,12 @@ public static class Builder { @SerializedName("last_name") private @Nullable String lastName; @SerializedName("type") private @Nullable String type; @SerializedName("username") private @Nullable String username; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull User model) { this.bio = model.bio; this.counts = model.counts; @@ -215,86 +249,107 @@ private Builder(@NonNull User model) { this.username = model.username; this._bits = model._bits; } + public Builder setBio(@Nullable String value) { this.bio = value; this._bits |= BIO_SET; return this; } + public Builder setCounts(@Nullable Map value) { this.counts = value; this._bits |= COUNTS_SET; return this; } + public Builder setCreatedAt(@Nullable Date value) { this.createdAt = value; this._bits |= CREATED_AT_SET; return this; } + public Builder setEmailFrequency(@Nullable @UserEmailFrequency String value) { this.emailFrequency = value; this._bits |= EMAIL_FREQUENCY_SET; return this; } + public Builder setFirstName(@Nullable String value) { this.firstName = value; this._bits |= FIRST_NAME_SET; return this; } + public Builder setIdentifier(@Nullable String value) { this.identifier = value; this._bits |= ID_SET; return this; } + public Builder setImage(@Nullable Image value) { this.image = value; this._bits |= IMAGE_SET; return this; } + public Builder setLastName(@Nullable String value) { this.lastName = value; this._bits |= LAST_NAME_SET; return this; } + public Builder setType(@Nullable String value) { this.type = value; this._bits |= TYPE_SET; return this; } + public Builder setUsername(@Nullable String value) { this.username = value; this._bits |= USERNAME_SET; return this; } + public @Nullable String getBio() { return this.bio; } + public @Nullable Map getCounts() { return this.counts; } + public @Nullable Date getCreatedAt() { return this.createdAt; } + public @Nullable @UserEmailFrequency String getEmailFrequency() { return this.emailFrequency; } + public @Nullable String getFirstName() { return this.firstName; } + public @Nullable String getIdentifier() { return this.identifier; } + public @Nullable Image getImage() { return this.image; } + public @Nullable String getLastName() { return this.lastName; } + public @Nullable String getType() { return this.type; } + public @Nullable String getUsername() { return this.username; } + public User build() { return new User( this.bio, @@ -310,6 +365,7 @@ public User build() { this._bits ); } + public void mergeFrom(User model) { if (model.getBioIsSet()) { this.bio = model.bio; @@ -342,6 +398,76 @@ public void mergeFrom(User model) { this.username = model.username; } } - + } + + public static class UserTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!User.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new UserTypeAdapter(gson, this, typeToken); + } + } + + public static class UserTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public UserTypeAdapter(Gson gson, UserTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, User value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public User read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + User model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("bio"): + model._bits |= BIO_SET; + break; + case ("counts"): + model._bits |= COUNTS_SET; + break; + case ("created_at"): + model._bits |= CREATED_AT_SET; + break; + case ("email_frequency"): + model._bits |= EMAIL_FREQUENCY_SET; + break; + case ("first_name"): + model._bits |= FIRST_NAME_SET; + break; + case ("id"): + model._bits |= ID_SET; + break; + case ("image"): + model._bits |= IMAGE_SET; + break; + case ("last_name"): + model._bits |= LAST_NAME_SET; + break; + case ("type"): + model._bits |= TYPE_SET; + break; + case ("username"): + model._bits |= USERNAME_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Examples/Java/Sources/VariableSubtitution.java b/Examples/Java/Sources/VariableSubtitution.java index 65b0185f..8f57080a 100644 --- a/Examples/Java/Sources/VariableSubtitution.java +++ b/Examples/Java/Sources/VariableSubtitution.java @@ -13,8 +13,14 @@ import android.support.annotation.Nullable; import android.support.annotation.StringDef; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; @@ -29,14 +35,14 @@ public class VariableSubtitution { @SerializedName("copy_prop") private @Nullable Integer copyProp; @SerializedName("mutable_copy_prop") private @Nullable Integer mutableCopyProp; @SerializedName("new_prop") private @Nullable Integer newProp; - + static final private int ALLOC_PROP_SET = 1 << 0; static final private int COPY_PROP_SET = 1 << 1; static final private int MUTABLE_COPY_PROP_SET = 1 << 2; static final private int NEW_PROP_SET = 1 << 3; - + private int _bits = 0; - + private VariableSubtitution( @Nullable Integer allocProp, @Nullable Integer copyProp, @@ -50,17 +56,21 @@ private VariableSubtitution( this.newProp = newProp; this._bits = _bits; } + public static VariableSubtitution.Builder builder() { return new VariableSubtitution.Builder(); } + public VariableSubtitution.Builder toBuilder() { return new VariableSubtitution.Builder(this); } + public VariableSubtitution mergeFrom(VariableSubtitution model) { VariableSubtitution.Builder builder = this.toBuilder(); builder.mergeFrom(model); return builder.build(); } + @Override public boolean equals(Object o) { if (this == o) { @@ -75,6 +85,7 @@ public boolean equals(Object o) { Objects.equals(this.mutableCopyProp, that.mutableCopyProp) && Objects.equals(this.newProp, that.newProp); } + @Override public int hashCode() { return Objects.hash(allocProp, @@ -82,42 +93,51 @@ public int hashCode() { mutableCopyProp, newProp); } + public @Nullable Integer getAllocProp() { return this.allocProp; } + public @Nullable Integer getCopyProp() { return this.copyProp; } + public @Nullable Integer getMutableCopyProp() { return this.mutableCopyProp; } + public @Nullable Integer getNewProp() { return this.newProp; } + public boolean getAllocPropIsSet() { return (this._bits & ALLOC_PROP_SET) == ALLOC_PROP_SET; } + public boolean getCopyPropIsSet() { return (this._bits & COPY_PROP_SET) == COPY_PROP_SET; } + public boolean getMutableCopyPropIsSet() { return (this._bits & MUTABLE_COPY_PROP_SET) == MUTABLE_COPY_PROP_SET; } + public boolean getNewPropIsSet() { return (this._bits & NEW_PROP_SET) == NEW_PROP_SET; } + public static class Builder { - + @SerializedName("alloc_prop") private @Nullable Integer allocProp; @SerializedName("copy_prop") private @Nullable Integer copyProp; @SerializedName("mutable_copy_prop") private @Nullable Integer mutableCopyProp; @SerializedName("new_prop") private @Nullable Integer newProp; - + private int _bits = 0; - + private Builder() { - } + private Builder(@NonNull VariableSubtitution model) { this.allocProp = model.allocProp; this.copyProp = model.copyProp; @@ -125,38 +145,47 @@ private Builder(@NonNull VariableSubtitution model) { this.newProp = model.newProp; this._bits = model._bits; } + public Builder setAllocProp(@Nullable Integer value) { this.allocProp = value; this._bits |= ALLOC_PROP_SET; return this; } + public Builder setCopyProp(@Nullable Integer value) { this.copyProp = value; this._bits |= COPY_PROP_SET; return this; } + public Builder setMutableCopyProp(@Nullable Integer value) { this.mutableCopyProp = value; this._bits |= MUTABLE_COPY_PROP_SET; return this; } + public Builder setNewProp(@Nullable Integer value) { this.newProp = value; this._bits |= NEW_PROP_SET; return this; } + public @Nullable Integer getAllocProp() { return this.allocProp; } + public @Nullable Integer getCopyProp() { return this.copyProp; } + public @Nullable Integer getMutableCopyProp() { return this.mutableCopyProp; } + public @Nullable Integer getNewProp() { return this.newProp; } + public VariableSubtitution build() { return new VariableSubtitution( this.allocProp, @@ -166,6 +195,7 @@ public VariableSubtitution build() { this._bits ); } + public void mergeFrom(VariableSubtitution model) { if (model.getAllocPropIsSet()) { this.allocProp = model.allocProp; @@ -180,6 +210,58 @@ public void mergeFrom(VariableSubtitution model) { this.newProp = model.newProp; } } - + } + + public static class VariableSubtitutionTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!VariableSubtitution.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + return (TypeAdapter) new VariableSubtitutionTypeAdapter(gson, this, typeToken); + } + } + + public static class VariableSubtitutionTypeAdapter extends TypeAdapter { + + final private TypeAdapter delegateTypeAdapter; + final private TypeAdapter elementTypeAdapter; + + public VariableSubtitutionTypeAdapter(Gson gson, VariableSubtitutionTypeAdapterFactory factory, TypeToken typeToken) { + this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken); + this.elementTypeAdapter = gson.getAdapter(JsonElement.class); + } + + @Override + public void write(JsonWriter writer, VariableSubtitution value) throws IOException { + this.delegateTypeAdapter.write(writer, value); + } + + @Override + public VariableSubtitution read(JsonReader reader) throws IOException { + JsonElement tree = this.elementTypeAdapter.read(reader); + VariableSubtitution model = this.delegateTypeAdapter.fromJsonTree(tree); + Set keys = tree.getAsJsonObject().keySet(); + for (String key : keys) { + switch (key) { + case ("alloc_prop"): + model._bits |= ALLOC_PROP_SET; + break; + case ("copy_prop"): + model._bits |= COPY_PROP_SET; + break; + case ("mutable_copy_prop"): + model._bits |= MUTABLE_COPY_PROP_SET; + break; + case ("new_prop"): + model._bits |= NEW_PROP_SET; + break; + default: + break; + } + } + return model; + } } } diff --git a/Sources/Core/JavaIR.swift b/Sources/Core/JavaIR.swift index d2c2700a..de6bb191 100644 --- a/Sources/Core/JavaIR.swift +++ b/Sources/Core/JavaIR.swift @@ -26,25 +26,35 @@ struct JavaModifier: OptionSet { } } +enum JavaAnnotation: String { + case override = "Override" + case nullable = "Nullable" + case nonnull = "NonNull" +} + public struct JavaIR { public struct Method { - let annotations: Set + let annotations: Set let modifiers: JavaModifier let body: [String] let signature: String func render() -> [String] { // HACK: We should actually have an enum / optionset that we can check for abstract, static, ... - let annotationLines = annotations.map { "@\($0)" } + let annotationLines = annotations.map { "@\($0.rawValue)" } if modifiers.contains(.abstract) { return annotationLines + ["\(modifiers.render()) \(signature);"] } - return annotationLines + [ - "\(modifiers.render()) \(signature) {", - -->body, - "}", - ] + + var toRender = annotationLines + ["\(modifiers.render()) \(signature) {"] + + if !body.isEmpty { + toRender.append(-->body) + } + + toRender.append("}") + return toRender } } @@ -69,7 +79,7 @@ public struct JavaIR { } } - static func method(annotations: Set = [], _ modifiers: JavaModifier, _ signature: String, body: () -> [String]) -> JavaIR.Method { + static func method(annotations: Set = [], _ modifiers: JavaModifier, _ signature: String, body: () -> [String]) -> JavaIR.Method { return JavaIR.Method(annotations: annotations, modifiers: modifiers, body: body(), signature: signature) } @@ -81,6 +91,40 @@ public struct JavaIR { ].joined(separator: "\n") } + static func forBlock(condition: String, body: () -> [String]) -> String { + return [ + "for (" + condition + ") {", + -->body(), + "}", + ].joined(separator: "\n") + } + + static func switchBlock(variableToCheck: String, defaultBody: [String], cases: () -> [Case]) -> String { + return [ + "switch (" + variableToCheck + ") {", + -->cases().flatMap { $0.render() }, + -->["default:", -->defaultBody], + "}", + ].joined(separator: "\n") + } + + struct Case { + let variableEquals: String + let body: [String] + let shouldBreak: Bool = true + + func render() -> [String] { + var lines = [ + "case (" + variableEquals + "):", + -->body, + ] + if shouldBreak { + lines.append(-->["break;"]) + } + return lines + } + } + struct Enum { let name: String let values: EnumType @@ -121,7 +165,7 @@ public struct JavaIR { } struct Class { - let annotations: Set + let annotations: Set let modifiers: JavaModifier let extends: String? let implements: [String]? // Should this be JavaIR.Interface? @@ -133,24 +177,33 @@ public struct JavaIR { func render() -> [String] { let implementsList = implements?.joined(separator: ", ") ?? "" - let implementsStmt = implementsList == "" ? "" : "implements \(implementsList)" - - var propertiesStrings = [String]() - for propertyBatch in properties { - for property in propertyBatch { - propertiesStrings.append(property.render()) - } - propertiesStrings.append("") // Add an empty line between each batch - } + let implementsStmt = implementsList.isEmpty ? "" : " implements \(implementsList)" - return annotations.map { "@\($0)" } + [ - "\(modifiers.render()) class \(name) \(implementsStmt) {", - -->enums.flatMap { $0.render() }, - -->propertiesStrings, - -->methods.flatMap { $0.render() }, - -->innerClasses.flatMap { $0.render() }, - "}", + let extendsStmt = extends.map { " extends \($0) " } ?? "" + + var lines = annotations.map { "@\($0.rawValue)" } + [ + "\(modifiers.render()) class \(name)\(extendsStmt)\(implementsStmt) {", ] + + if !enums.isEmpty { + lines.append(-->enums.flatMap { [""] + $0.render() }) + } + + if !properties.isEmpty { + lines.append(-->properties.flatMap { [""] + $0.compactMap { $0.render() } }) + } + + if !methods.isEmpty { + lines.append(-->methods.flatMap { [""] + $0.render() }) + } + + if !innerClasses.isEmpty { + lines.append(-->innerClasses.flatMap { [""] + $0.render() }) + } + + lines.append("}") + + return lines } } diff --git a/Sources/Core/JavaModelRenderer.swift b/Sources/Core/JavaModelRenderer.swift index 7b822681..7e1947b6 100644 --- a/Sources/Core/JavaModelRenderer.swift +++ b/Sources/Core/JavaModelRenderer.swift @@ -16,6 +16,8 @@ public struct JavaModelRenderer: JavaFileRenderer { self.params = params } + // MARK: - Top-level Model + func renderModelConstructor() -> JavaIR.Method { let args = -->(transitiveProperties.map { param, schemaObj in self.typeFromSchema(param, schemaObj) + " " + param.snakeCaseToPropertyName() + "," @@ -33,7 +35,7 @@ public struct JavaModelRenderer: JavaFileRenderer { param.snakeCaseToPropertyName() }.joined(separator: ",\n") - return JavaIR.method(annotations: ["Override"], [.public], "int hashCode()") { [ + return JavaIR.method(annotations: [JavaAnnotation.override], [.public], "int hashCode()") { [ "return Objects.hash(" + bodyHashCode + ");", ] } @@ -44,7 +46,7 @@ public struct JavaModelRenderer: JavaFileRenderer { "Objects.equals(this." + param.snakeCaseToPropertyName() + ", that." + param.snakeCaseToPropertyName() + ")" }.joined(separator: " &&\n") - return JavaIR.method(annotations: ["Override"], [.public], "boolean equals(Object o)") { [ + return JavaIR.method(annotations: [JavaAnnotation.override], [.public], "boolean equals(Object o)") { [ JavaIR.ifBlock(condition: "this == o") { [ "return true;", ] }, @@ -110,6 +112,8 @@ public struct JavaModelRenderer: JavaFileRenderer { ] } } + // MARK: - Model.Builder + func renderBuilderConstructors() -> [JavaIR.Method] { let emptyConstructor = JavaIR.method([.private], "Builder()") { [] } @@ -168,6 +172,83 @@ public struct JavaModelRenderer: JavaFileRenderer { return [props, [bits]] } + // MARK: - TypeAdapterFactory + + func renderTypeAdapterFactoryMethods() -> [JavaIR.Method] { + return [JavaIR.method(annotations: [JavaAnnotation.override], [.public], " TypeAdapter create(Gson gson, TypeToken typeToken)") { [ + JavaIR.ifBlock(condition: "!" + className + ".class.isAssignableFrom(typeToken.getRawType())") { [ + "return null;", + ] }, + "return (TypeAdapter) new " + className + "TypeAdapter(gson, this, typeToken);", + ] }] + } + + // MARK: - TypeAdapter + + func renderTypeAdapterProperties() -> [[JavaIR.Property]] { + let delegate = JavaIR.Property( + annotations: [], + modifiers: [.final, .private], + type: "TypeAdapter<" + className + ">", + name: "delegateTypeAdapter", + initialValue: "" + ) + + let elementTypeAdapter = JavaIR.Property( + annotations: [], + modifiers: [.final, .private], + type: "TypeAdapter", + name: "elementTypeAdapter", + initialValue: "" + ) + + return [[delegate, elementTypeAdapter]] + } + + func renderTypeAdapterMethods() -> [JavaIR.Method] { + let constructor = JavaIR.method( + annotations: [], + [.public], + className + "TypeAdapter(Gson gson, " + className + "TypeAdapterFactory factory, TypeToken typeToken)" + ) { [ + "this.delegateTypeAdapter = gson.getDelegateAdapter(factory, typeToken);", + "this.elementTypeAdapter = gson.getAdapter(JsonElement.class);", + ] } + + let write = JavaIR.method( + annotations: [JavaAnnotation.override], + [.public], + "void write(JsonWriter writer, " + className + " value) throws IOException" + ) { [ + "this.delegateTypeAdapter.write(writer, value);", + ] } + + let read = JavaIR.method( + annotations: [JavaAnnotation.override], + [.public], + className + " read(JsonReader reader) throws IOException" + ) { [ + "JsonElement tree = this.elementTypeAdapter.read(reader);", + className + " model = this.delegateTypeAdapter.fromJsonTree(tree);", + "Set keys = tree.getAsJsonObject().keySet();", + JavaIR.forBlock(condition: "String key : keys") { [ + JavaIR.switchBlock(variableToCheck: "key", defaultBody: ["break;"]) { + transitiveProperties.map { param, _ in + JavaIR.Case( + variableEquals: "\"" + param + "\"", + body: ["model._bits |= " + param.uppercased() + "_SET;"] + ) + } + }, + ] }, + "return model;", + ] } + + return [constructor, write, read] + } + + // MARK: - Render from root + func renderRoots() -> [JavaIR.Root] { let packages = params[.packageName].flatMap { [JavaIR.Root.packages(names: [$0])] @@ -177,7 +258,13 @@ public struct JavaModelRenderer: JavaFileRenderer { JavaIR.Root.imports(names: [ "com.google.gson.Gson", "com.google.gson.annotations.SerializedName", + "com.google.gson.JsonElement", "com.google.gson.TypeAdapter", + "com.google.gson.TypeAdapterFactory", + "com.google.gson.reflect.TypeToken", + "com.google.gson.stream.JsonReader", + "com.google.gson.stream.JsonWriter", + "java.io.IOException", "java.util.Date", "java.util.Map", "java.util.Set", @@ -243,6 +330,30 @@ public struct JavaModelRenderer: JavaFileRenderer { properties: renderBuilderProperties() ) + let typeAdapterFactoryClass = JavaIR.Class( + annotations: [], + modifiers: [.public, .static], + extends: nil, + implements: ["TypeAdapterFactory"], + name: className + "TypeAdapterFactory", + methods: renderTypeAdapterFactoryMethods(), + enums: [], + innerClasses: [], + properties: [] + ) + + let typeAdapterClass = JavaIR.Class( + annotations: [], + modifiers: [.public, .static], + extends: "TypeAdapter<" + className + ">", + implements: nil, + name: className + "TypeAdapter", + methods: renderTypeAdapterMethods(), + enums: [], + innerClasses: [], + properties: renderTypeAdapterProperties() + ) + let modelClass = JavaIR.Root.classDecl( aClass: JavaIR.Class( annotations: [], @@ -263,6 +374,8 @@ public struct JavaModelRenderer: JavaFileRenderer { enums: enumProps, innerClasses: [ builderClass, + typeAdapterFactoryClass, + typeAdapterClass, ], properties: renderModelProperties() ) diff --git a/Sources/Core/StringExtensions.swift b/Sources/Core/StringExtensions.swift index d01845a4..cb88e039 100644 --- a/Sources/Core/StringExtensions.swift +++ b/Sources/Core/StringExtensions.swift @@ -44,7 +44,7 @@ import Foundation prefix operator --> prefix func --> (strs: [String]) -> String { - return strs.flatMap { $0.components(separatedBy: "\n").map { $0.indent() } } + return strs.flatMap { $0.components(separatedBy: "\n").map { $0.isEmpty ? $0 : $0.indent() } } .joined(separator: "\n") }