From 76ce2117286d17a500e48962728e199b7a7d7073 Mon Sep 17 00:00:00 2001 From: sonallux <13821543+sonallux@users.noreply.github.com> Date: Sun, 14 Mar 2021 20:30:50 +0100 Subject: [PATCH] generator-java: handle union types - Adds support for generating a shared super object type (issue #7) - Add better union type handling in generator-java (issue #37) fixes #7 fixes #37 --- .../core/SpotifyWebApiObjectUtils.java | 30 +++++++++++++ .../spotify/generator/java/JavaGenerator.java | 4 ++ .../java/templates/BaseObjectTemplate.java | 27 ++++++++++++ .../java/templates/ObjectTemplate.java | 7 +++- .../generator/java/util/JavaUtils.java | 5 +++ .../resources/templates/base-object.mustache | 42 +++++++++++++++++++ .../main/resources/templates/object.mustache | 6 +++ .../de/sonallux/spotify/api/models/Album.java | 20 ++------- .../sonallux/spotify/api/models/Artist.java | 20 ++------- .../spotify/api/models/BaseObject.java | 37 ++++++++++++++++ .../spotify/api/models/CurrentlyPlaying.java | 2 +- .../api/models/CurrentlyPlayingContext.java | 2 +- .../sonallux/spotify/api/models/Episode.java | 20 ++------- .../spotify/api/models/LinkedTrack.java | 20 ++------- .../sonallux/spotify/api/models/Playlist.java | 20 ++------- .../spotify/api/models/PlaylistTrack.java | 2 +- .../spotify/api/models/PrivateUser.java | 20 ++------- .../spotify/api/models/PublicUser.java | 20 ++------- .../de/sonallux/spotify/api/models/Show.java | 20 ++------- .../spotify/api/models/SimplifiedAlbum.java | 20 ++------- .../spotify/api/models/SimplifiedArtist.java | 20 ++------- .../spotify/api/models/SimplifiedEpisode.java | 20 ++------- .../api/models/SimplifiedPlaylist.java | 20 ++------- .../spotify/api/models/SimplifiedShow.java | 20 ++------- .../spotify/api/models/SimplifiedTrack.java | 20 ++------- .../de/sonallux/spotify/api/models/Track.java | 20 ++------- .../sonallux/spotify/api/ConversionTest.java | 16 +++---- 27 files changed, 214 insertions(+), 266 deletions(-) create mode 100644 spotify-web-api-core/src/main/java/de/sonallux/spotify/core/SpotifyWebApiObjectUtils.java create mode 100644 spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/BaseObjectTemplate.java create mode 100644 spotify-web-api-generator-java/src/main/resources/templates/base-object.mustache create mode 100644 spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/BaseObject.java diff --git a/spotify-web-api-core/src/main/java/de/sonallux/spotify/core/SpotifyWebApiObjectUtils.java b/spotify-web-api-core/src/main/java/de/sonallux/spotify/core/SpotifyWebApiObjectUtils.java new file mode 100644 index 00000000..e41a4b07 --- /dev/null +++ b/spotify-web-api-core/src/main/java/de/sonallux/spotify/core/SpotifyWebApiObjectUtils.java @@ -0,0 +1,30 @@ +package de.sonallux.spotify.core; + +import de.sonallux.spotify.core.model.SpotifyWebApiObject; + +import java.util.List; + +public class SpotifyWebApiObjectUtils { + private static final List BASE_OBJECT_PROPERTY_NAMES = List.of("id", "type", "href", "uri"); + public static final List BASE_OBJECT_NAMES = List.of("AlbumObject", "ArtistObject", "EpisodeObject", "PlaylistObject", "ShowObject", "TrackObject", "UserObject"); + public static final String BASE_OBJECT_NAME = "BaseObject"; + public static final SpotifyWebApiObject SPOTIFY_BASE_OBJECT = new SpotifyWebApiObject(BASE_OBJECT_NAME) + .addProperty(new SpotifyWebApiObject.Property("id", "String", "The [Spotify ID](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids) for the object.")) + .addProperty(new SpotifyWebApiObject.Property("type", "String", "The object type.")) + .addProperty(new SpotifyWebApiObject.Property("href", "String", "A link to the Web API endpoint providing full details of the object.")) + .addProperty(new SpotifyWebApiObject.Property("uri", "String", "The [Spotify URI](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids) for the object.")); + + public static boolean isBaseObject(SpotifyWebApiObject object) { + return object.getProperties().stream() + .filter(p -> BASE_OBJECT_PROPERTY_NAMES.contains(p.getName())) + .count() == BASE_OBJECT_PROPERTY_NAMES.size(); + } + + public static boolean removeBaseProperties(SpotifyWebApiObject object) { + if (BASE_OBJECT_NAME.equals(object.getName()) || !isBaseObject(object)) { + return false; + } + object.getProperties().removeIf(p -> BASE_OBJECT_PROPERTY_NAMES.contains(p.getName())); + return true; + } +} diff --git a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/JavaGenerator.java b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/JavaGenerator.java index 30a67c88..af934ec1 100644 --- a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/JavaGenerator.java +++ b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/JavaGenerator.java @@ -2,6 +2,7 @@ import com.github.mustachejava.MustacheFactory; import de.sonallux.spotify.core.EndpointSplitter; +import de.sonallux.spotify.core.SpotifyWebApiObjectUtils; import de.sonallux.spotify.core.model.SpotifyWebApi; import de.sonallux.spotify.generator.java.templates.*; import de.sonallux.spotify.generator.java.util.JavaPackage; @@ -25,6 +26,9 @@ public void generate(SpotifyWebApi spotifyWebApi, Path outputFolder, JavaPackage throw new GeneratorException("Failed to split endpoints", e); } + var baseObjectTemplate = new BaseObjectTemplate().loadTemplate(this.mustacheFactory); + baseObjectTemplate.generate(SpotifyWebApiObjectUtils.SPOTIFY_BASE_OBJECT, outputFolder, javaPackage); + var objectTemplate = new ObjectTemplate().loadTemplate(this.mustacheFactory); for (var object : spotifyWebApi.getObjectList()) { objectTemplate.generate(object, outputFolder, javaPackage); diff --git a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/BaseObjectTemplate.java b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/BaseObjectTemplate.java new file mode 100644 index 00000000..be518776 --- /dev/null +++ b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/BaseObjectTemplate.java @@ -0,0 +1,27 @@ +package de.sonallux.spotify.generator.java.templates; + +import de.sonallux.spotify.core.SpotifyWebApiObjectUtils; +import de.sonallux.spotify.core.model.SpotifyWebApiObject; +import de.sonallux.spotify.generator.java.util.JavaUtils; + +import java.util.Map; + +public class BaseObjectTemplate extends ObjectTemplate { + @Override + public String templateName() { + return "base-object"; + } + + @Override + public String getFileName(SpotifyWebApiObject object) { + return JavaUtils.getFileName(SpotifyWebApiObjectUtils.BASE_OBJECT_NAME); + } + + @Override + public Map buildContext(SpotifyWebApiObject object, Map rootContext) { + var context = super.buildContext(object, rootContext); + context.put("className", SpotifyWebApiObjectUtils.BASE_OBJECT_NAME); + + return context; + } +} diff --git a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/ObjectTemplate.java b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/ObjectTemplate.java index 34254a16..7690e1c4 100644 --- a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/ObjectTemplate.java +++ b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/templates/ObjectTemplate.java @@ -1,7 +1,7 @@ package de.sonallux.spotify.generator.java.templates; -import com.google.common.base.CaseFormat; import com.google.common.base.Strings; +import de.sonallux.spotify.core.SpotifyWebApiObjectUtils; import de.sonallux.spotify.core.model.SpotifyWebApiObject; import de.sonallux.spotify.generator.java.util.JavaPackage; import de.sonallux.spotify.generator.java.util.JavaUtils; @@ -34,6 +34,11 @@ public String getFileName(SpotifyWebApiObject object) { @Override public Map buildContext(SpotifyWebApiObject object, Map context) { + if (SpotifyWebApiObjectUtils.removeBaseProperties(object)) { + context.put("extendsBaseObject", true); + context.put("superClass", SpotifyWebApiObjectUtils.BASE_OBJECT_NAME); + } + context.put("name", object.getName()); context.put("className", getClassName(object)); context.put("properties", object.getProperties().stream().map(this::buildPropertyContext).collect(Collectors.toList())); diff --git a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/util/JavaUtils.java b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/util/JavaUtils.java index 2409aa37..58a2ca2d 100644 --- a/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/util/JavaUtils.java +++ b/spotify-web-api-generator-java/src/main/java/de/sonallux/spotify/generator/java/util/JavaUtils.java @@ -10,6 +10,7 @@ import static com.google.common.base.CaseFormat.LOWER_CAMEL; import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE; +import static de.sonallux.spotify.core.SpotifyWebApiObjectUtils.BASE_OBJECT_NAMES; public class JavaUtils { public static final List RESERVED_WORDS = Arrays.asList( @@ -64,6 +65,10 @@ public static String mapToJavaType(String type) { } else if ((matcher = SpotifyWebApiUtils.CURSOR_PAGING_OBJECT_TYPE_PATTERN.matcher(type)).matches()) { return "CursorPaging<" + mapToJavaType(matcher.group(1)) + ">"; } else if (type.contains(" | ")) { + if (Arrays.stream(type.split(" \\| ")) + .allMatch(BASE_OBJECT_NAMES::contains)) { + return "BaseObject"; + } //Can not be mapped easily, so just use Map return "java.util.Map"; } else { diff --git a/spotify-web-api-generator-java/src/main/resources/templates/base-object.mustache b/spotify-web-api-generator-java/src/main/resources/templates/base-object.mustache new file mode 100644 index 00000000..e34c8d89 --- /dev/null +++ b/spotify-web-api-generator-java/src/main/resources/templates/base-object.mustache @@ -0,0 +1,42 @@ +package {{package}}; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import lombok.*; + +{{#documentationLink}} +/** + * {{name}} + */ +{{/documentationLink}} +@Getter +@Setter +@NoArgsConstructor +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true) +@JsonSubTypes({ + @JsonSubTypes.Type(value = Album.class, name = "album"), + @JsonSubTypes.Type(value = Artist.class, name = "artist"), + @JsonSubTypes.Type(value = Episode.class, name = "episode"), + @JsonSubTypes.Type(value = Playlist.class, name = "playlist"), + @JsonSubTypes.Type(value = Show.class, name = "show"), + @JsonSubTypes.Type(value = Track.class, name = "track"), + @JsonSubTypes.Type(value = PrivateUser.class, name = "user"), +}) +public abstract class {{className}} { +{{#properties}} + {{#hasDescription}} + /** + {{#description}} + * {{.}} + {{/description}} + */ + {{/hasDescription}} + {{#nonNull}} + @NonNull + {{/nonNull}} + {{#isReservedKeywordProperty}} + @lombok.experimental.Accessors(prefix = "_") + {{/isReservedKeywordProperty}} + public {{type}} {{fieldName}}; +{{/properties}} +} diff --git a/spotify-web-api-generator-java/src/main/resources/templates/object.mustache b/spotify-web-api-generator-java/src/main/resources/templates/object.mustache index 91b9de47..c0cb2a18 100644 --- a/spotify-web-api-generator-java/src/main/resources/templates/object.mustache +++ b/spotify-web-api-generator-java/src/main/resources/templates/object.mustache @@ -1,5 +1,8 @@ package {{package}}; +{{#extendsBaseObject}} +import com.fasterxml.jackson.annotation.JsonTypeInfo; +{{/extendsBaseObject}} import lombok.*; {{#documentationLink}} @@ -10,6 +13,9 @@ import lombok.*; @Getter @Setter @NoArgsConstructor +{{#extendsBaseObject}} +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +{{/extendsBaseObject}} public class {{className}}{{#superClass}} extends {{superClass}}{{/superClass}} { {{#properties}} {{#hasDescription}} diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Album.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Album.java index 60b0bb32..89aec983 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Album.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Album.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class Album { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class Album extends BaseObject { /** *

The type of the album: album, single, or compilation.

*/ @@ -37,14 +39,6 @@ public class Album { *

A list of the genres used to classify the album. For example: "Prog Rock" , "Post-Grunge". (If not yet classified, the array is empty.)

*/ public java.util.List genres; - /** - *

A link to the Web API endpoint providing full details of the album.

- */ - public String href; - /** - *

The Spotify ID for the album.

- */ - public String id; /** *

The cover art for the album in various sizes, widest first.

*/ @@ -77,12 +71,4 @@ public class Album { *

The tracks of the album.

*/ public Paging tracks; - /** - *

The object type: "album"

- */ - public String type; - /** - *

The Spotify URI for the album.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Artist.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Artist.java index 46a993ab..5dc917cc 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Artist.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Artist.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class Artist { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class Artist extends BaseObject { /** *

Known external URLs for this artist.

*/ @@ -21,14 +23,6 @@ public class Artist { *

A list of the genres the artist is associated with. For example: "Prog Rock" , "Post-Grunge". (If not yet classified, the array is empty.)

*/ public java.util.List genres; - /** - *

A link to the Web API endpoint providing full details of the artist.

- */ - public String href; - /** - *

The Spotify ID for the artist.

- */ - public String id; /** *

Images of the artist in various sizes, widest first.

*/ @@ -41,12 +35,4 @@ public class Artist { *

The popularity of the artist. The value will be between 0 and 100, with 100 being the most popular. The artist's popularity is calculated from the popularity of all the artist's tracks.

*/ public int popularity; - /** - *

The object type: "artist"

- */ - public String type; - /** - *

The Spotify URI for the artist.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/BaseObject.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/BaseObject.java new file mode 100644 index 00000000..9631b2a3 --- /dev/null +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/BaseObject.java @@ -0,0 +1,37 @@ +package de.sonallux.spotify.api.models; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true) +@JsonSubTypes({ + @JsonSubTypes.Type(value = Album.class, name = "album"), + @JsonSubTypes.Type(value = Artist.class, name = "artist"), + @JsonSubTypes.Type(value = Episode.class, name = "episode"), + @JsonSubTypes.Type(value = Playlist.class, name = "playlist"), + @JsonSubTypes.Type(value = Show.class, name = "show"), + @JsonSubTypes.Type(value = Track.class, name = "track"), + @JsonSubTypes.Type(value = PrivateUser.class, name = "user"), +}) +public abstract class BaseObject { + /** + *

The Spotify ID for the object.

+ */ + public String id; + /** + *

The object type.

+ */ + public String type; + /** + *

A link to the Web API endpoint providing full details of the object.

+ */ + public String href; + /** + *

The Spotify URI for the object.

+ */ + public String uri; +} diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlaying.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlaying.java index c9c4339f..83a04fdc 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlaying.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlaying.java @@ -24,7 +24,7 @@ public class CurrentlyPlaying { /** *

The currently playing track or episode. Can be null.

*/ - public java.util.Map item; + public BaseObject item; /** *

Progress into the currently playing track or episode. Can be null.

*/ diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlayingContext.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlayingContext.java index 4527d3ab..c761757a 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlayingContext.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/CurrentlyPlayingContext.java @@ -32,7 +32,7 @@ public class CurrentlyPlayingContext { /** *

The currently playing track or episode. Can be null.

*/ - public java.util.Map item; + public BaseObject item; /** *

Progress into the currently playing track or episode. Can be null.

*/ diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Episode.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Episode.java index aa250d64..3e8b4a6d 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Episode.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Episode.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class Episode { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class Episode extends BaseObject { /** *

A URL to a 30 second preview (MP3 format) of the episode. null if not available.

*/ @@ -29,14 +31,6 @@ public class Episode { *

External URLs for this episode.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the episode.

- */ - public String href; - /** - *

The Spotify ID for the episode.

- */ - public String id; /** *

The cover art for the episode in various sizes, widest first.

*/ @@ -77,12 +71,4 @@ public class Episode { *

The show on which the episode belongs.

*/ public SimplifiedShow show; - /** - *

The object type: "episode".

- */ - public String type; - /** - *

The Spotify URI for the episode.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/LinkedTrack.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/LinkedTrack.java index 0ca06b32..1665492f 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/LinkedTrack.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/LinkedTrack.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,25 +9,10 @@ @Getter @Setter @NoArgsConstructor -public class LinkedTrack { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class LinkedTrack extends BaseObject { /** *

Known external URLs for this track.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the track.

- */ - public String href; - /** - *

The Spotify ID for the track.

- */ - public String id; - /** - *

The object type: "track".

- */ - public String type; - /** - *

The Spotify URI for the track.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Playlist.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Playlist.java index b96565cd..f13c3f5b 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Playlist.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Playlist.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class Playlist { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class Playlist extends BaseObject { /** *

true if the owner allows other users to modify the playlist.

*/ @@ -25,14 +27,6 @@ public class Playlist { *

Information about the followers of the playlist.

*/ public Followers followers; - /** - *

A link to the Web API endpoint providing full details of the playlist.

- */ - public String href; - /** - *

The Spotify ID for the playlist.

- */ - public String id; /** *

Images for the playlist. The array may be empty or contain up to three images. The images are returned by size in descending order. See Working with Playlists. Note: If returned, the source URL for the image (url) is temporary and will expire in less than a day.

*/ @@ -58,12 +52,4 @@ public class Playlist { *

Information about the tracks of the playlist. Note, a track object may be null. This can happen if a track is no longer available.

*/ public Paging tracks; - /** - *

The object type: "playlist"

- */ - public String type; - /** - *

The Spotify URI for the playlist.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PlaylistTrack.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PlaylistTrack.java index 50686db6..22ecbc24 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PlaylistTrack.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PlaylistTrack.java @@ -24,5 +24,5 @@ public class PlaylistTrack { /** *

Information about the track or episode.

*/ - public java.util.Map track; + public BaseObject track; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PrivateUser.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PrivateUser.java index bcb08811..9691581c 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PrivateUser.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PrivateUser.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class PrivateUser { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class PrivateUser extends BaseObject { /** *

The country of the user, as set in the user's account profile. An ISO 3166-1 alpha-2 country code. This field is only available when the current user has granted access to the user-read-private scope.

*/ @@ -33,14 +35,6 @@ public class PrivateUser { *

Information about the followers of the user.

*/ public Followers followers; - /** - *

A link to the Web API endpoint for this user.

- */ - public String href; - /** - *

The Spotify user ID for the user.

- */ - public String id; /** *

The user's profile image.

*/ @@ -49,12 +43,4 @@ public class PrivateUser { *

The user's Spotify subscription level: "premium", "free", etc. (The subscription level "open" can be considered the same as "free".) This field is only available when the current user has granted access to the user-read-private scope.

*/ public String product; - /** - *

The object type: "user"

- */ - public String type; - /** - *

The Spotify URI for the user.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PublicUser.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PublicUser.java index 767e1653..a8d229a3 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PublicUser.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/PublicUser.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class PublicUser { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class PublicUser extends BaseObject { /** *

The name displayed on the user's profile. null if not available.

*/ @@ -21,24 +23,8 @@ public class PublicUser { *

Information about the followers of this user.

*/ public Followers followers; - /** - *

A link to the Web API endpoint for this user.

- */ - public String href; - /** - *

The Spotify user ID for this user.

- */ - public String id; /** *

The user's profile image.

*/ public java.util.List images; - /** - *

The object type: "user"

- */ - public String type; - /** - *

The Spotify URI for this user.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Show.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Show.java index 7a149876..895d561f 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Show.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Show.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class Show { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class Show extends BaseObject { /** *

A list of the countries in which the show can be played, identified by their ISO 3166-1 alpha-2 code.

*/ @@ -33,14 +35,6 @@ public class Show { *

External URLs for this show.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the show.

- */ - public String href; - /** - *

The Spotify ID for the show.

- */ - public String id; /** *

The cover art for the show in various sizes, widest first.

*/ @@ -65,12 +59,4 @@ public class Show { *

The publisher of the show.

*/ public String publisher; - /** - *

The object type: "show".

- */ - public String type; - /** - *

The Spotify URI for the show.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedAlbum.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedAlbum.java index fb43aad2..c08ee249 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedAlbum.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedAlbum.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class SimplifiedAlbum { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class SimplifiedAlbum extends BaseObject { /** *

The field is present when getting an artist's albums. Possible values are "album", "single", "compilation", "appears_on". Compare to album_type this field represents relationship between the artist and the album.

*/ @@ -29,14 +31,6 @@ public class SimplifiedAlbum { *

Known external URLs for this album.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the album.

- */ - public String href; - /** - *

The Spotify ID for the album.

- */ - public String id; /** *

The cover art for the album in various sizes, widest first.

*/ @@ -57,12 +51,4 @@ public class SimplifiedAlbum { *

Included in the response when a content restriction is applied. See Restriction Object for more details.

*/ public AlbumRestriction restrictions; - /** - *

The object type: "album"

- */ - public String type; - /** - *

The Spotify URI for the album.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedArtist.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedArtist.java index a5fa5f6d..569e6edc 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedArtist.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedArtist.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,29 +9,14 @@ @Getter @Setter @NoArgsConstructor -public class SimplifiedArtist { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class SimplifiedArtist extends BaseObject { /** *

Known external URLs for this artist.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the artist.

- */ - public String href; - /** - *

The Spotify ID for the artist.

- */ - public String id; /** *

The name of the artist.

*/ public String name; - /** - *

The object type: "artist"

- */ - public String type; - /** - *

The Spotify URI for the artist.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedEpisode.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedEpisode.java index 544027a2..1871cace 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedEpisode.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedEpisode.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class SimplifiedEpisode { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class SimplifiedEpisode extends BaseObject { /** *

A URL to a 30 second preview (MP3 format) of the episode. null if not available.

*/ @@ -29,14 +31,6 @@ public class SimplifiedEpisode { *

External URLs for this episode.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the episode.

- */ - public String href; - /** - *

The Spotify ID for the episode.

- */ - public String id; /** *

The cover art for the episode in various sizes, widest first.

*/ @@ -73,12 +67,4 @@ public class SimplifiedEpisode { *

The user's most recent position in the episode. Set if the supplied access token is a user token and has the scope 'user-read-playback-position'.

*/ public ResumePoint resumePoint; - /** - *

The object type: "episode".

- */ - public String type; - /** - *

The Spotify URI for the episode.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedPlaylist.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedPlaylist.java index f5c0318c..4f038bae 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedPlaylist.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedPlaylist.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class SimplifiedPlaylist { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class SimplifiedPlaylist extends BaseObject { /** *

true if the owner allows other users to modify the playlist.

*/ @@ -21,14 +23,6 @@ public class SimplifiedPlaylist { *

Known external URLs for this playlist.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the playlist.

- */ - public String href; - /** - *

The Spotify ID for the playlist.

- */ - public String id; /** *

Images for the playlist. The array may be empty or contain up to three images. The images are returned by size in descending order. See Working with Playlists. Note: If returned, the source URL for the image (url) is temporary and will expire in less than a day.

*/ @@ -54,12 +48,4 @@ public class SimplifiedPlaylist { *

A collection containing a link ( href ) to the Web API endpoint where full details of the playlist's tracks can be retrieved, along with the total number of tracks in the playlist. Note, a track object may be null. This can happen if a track is no longer available.

*/ public PlaylistTracksRef tracks; - /** - *

The object type: "playlist"

- */ - public String type; - /** - *

The Spotify URI for the playlist.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedShow.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedShow.java index 9b6042a4..c9354368 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedShow.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedShow.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class SimplifiedShow { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class SimplifiedShow extends BaseObject { /** *

A list of the countries in which the show can be played, identified by their ISO 3166-1 alpha-2 code.

*/ @@ -29,14 +31,6 @@ public class SimplifiedShow { *

External URLs for this show.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the show.

- */ - public String href; - /** - *

The Spotify ID for the show.

- */ - public String id; /** *

The cover art for the show in various sizes, widest first.

*/ @@ -61,12 +55,4 @@ public class SimplifiedShow { *

The publisher of the show.

*/ public String publisher; - /** - *

The object type: "show".

- */ - public String type; - /** - *

The Spotify URI for the show.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedTrack.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedTrack.java index 27a482a9..f25817de 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedTrack.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/SimplifiedTrack.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class SimplifiedTrack { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class SimplifiedTrack extends BaseObject { /** *

The artists who performed the track. Each artist object includes a link in href to more detailed information about the artist.

*/ @@ -33,14 +35,6 @@ public class SimplifiedTrack { *

External URLs for this track.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the track.

- */ - public String href; - /** - *

The Spotify ID for the track.

- */ - public String id; /** *

Whether or not the track is from a local file.

*/ @@ -69,12 +63,4 @@ public class SimplifiedTrack { *

The number of the track. If an album has several discs, the track number is the number on the specified disc.

*/ public int trackNumber; - /** - *

The object type: "track".

- */ - public String type; - /** - *

The Spotify URI for the track.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Track.java b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Track.java index 418902fa..08e786a0 100644 --- a/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Track.java +++ b/spotify-web-api-java/src/main/generated/de/sonallux/spotify/api/models/Track.java @@ -1,5 +1,6 @@ package de.sonallux.spotify.api.models; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.*; /** @@ -8,7 +9,8 @@ @Getter @Setter @NoArgsConstructor -public class Track { +@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) // Disable deserialization based on @JsonTypeInfo +public class Track extends BaseObject { /** *

The album on which the track appears. The album object includes a link in href to full information about the album.

*/ @@ -41,14 +43,6 @@ public class Track { *

Known external URLs for this track.

*/ public ExternalUrl externalUrls; - /** - *

A link to the Web API endpoint providing full details of the track.

- */ - public String href; - /** - *

The Spotify ID for the track.

- */ - public String id; /** *

Whether or not the track is from a local file.

*/ @@ -83,12 +77,4 @@ public class Track { *

The number of the track. If an album has several discs, the track number is the number on the specified disc.

*/ public int trackNumber; - /** - *

The object type: "track".

- */ - public String type; - /** - *

The Spotify URI for the track.

- */ - public String uri; } diff --git a/spotify-web-api-java/src/test/java/de/sonallux/spotify/api/ConversionTest.java b/spotify-web-api-java/src/test/java/de/sonallux/spotify/api/ConversionTest.java index f3aedd42..7ac0bbc3 100644 --- a/spotify-web-api-java/src/test/java/de/sonallux/spotify/api/ConversionTest.java +++ b/spotify-web-api-java/src/test/java/de/sonallux/spotify/api/ConversionTest.java @@ -1,7 +1,9 @@ package de.sonallux.spotify.api; import de.sonallux.spotify.api.models.ChangePlaylistDetailsRequest; +import de.sonallux.spotify.api.models.Episode; import de.sonallux.spotify.api.models.RemoveTracksPlaylistRequest; +import de.sonallux.spotify.api.models.Track; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okio.Buffer; @@ -44,8 +46,8 @@ void testResponseSnakeCaseToCamelCase() throws Exception { var firstTrack = playlist.getTracks().getItems().get(0); assertNotNull(firstTrack); assertEquals(Instant.parse("2021-03-07T23:01:00Z"), firstTrack.getAddedAt()); - //TODO: adjust when https://github.com/sonallux/spotify-web-api/issues/37 is fixed - assertEquals(6, firstTrack.getTrack().get("track_number")); + assertTrue(firstTrack.getTrack() instanceof Track); + assertEquals(6, ((Track) firstTrack.getTrack()).getTrackNumber()); } @Test @@ -78,18 +80,18 @@ void testRequestWithSnakeCaseToCamelCase() throws Exception { @Test void testUnionTypeHandling() throws Exception { - webServer.enqueue(loadMockResponse("get-playlists-tracks.json")); + webServer.enqueue(loadMockResponse("get-playlists-tracks-union.json")); var response = api.callApiAndReturnBody(api.getPlaylistsApi().getPlaylistsTracks("foo", "DE")); var track = response.getItems().get(0).getTrack(); assertNotNull(track); - assertEquals("track", track.get("type")); - //assertTrue(track instanceof Track);//TODO: enable when https://github.com/sonallux/spotify-web-api/issues/37 is fixed + assertEquals("track", track.getType()); + assertTrue(track instanceof Track); var episode = response.getItems().get(1).getTrack(); assertNotNull(episode); - assertEquals("episode", episode.get("type")); - //assertTrue(track instanceof Episode);//TODO: enable when https://github.com/sonallux/spotify-web-api/issues/37 is fixed + assertEquals("episode", episode.getType()); + assertTrue(episode instanceof Episode); } private MockResponse loadMockResponse(String fileName) throws Exception {