Reputation: 13
I have this lazy iterator that pretty much receives a function and a string as parameters, goes to an API, receives a DTO from the API and converts that DTO to a domain object (in this case an Event). This Event, as seen below is made up of an Artist and several Tracks. My problem (not only here) is that, when in my EventIterator, I try to populate my artistSupplier by passing a lambda expression, I get the error "Bad return type in lambda expression ArtistDto cant be converted to T".
public class EventIterator<T, U, R> extends SetListIterator<T, U, R> implements Iterator<R> {
private Function<U, T[]> function;
private String s;
private LastfmApi lastfmApi;
public EventIterator(String s, Function<U, T[]> function, LastfmApi lastfmApi) {
this.lastfmApi = lastfmApi;
this.s = s;
this.function = function;
page = 1;
}
@Override
public R convertToDomainType(T[] ret) {
EventDto [] eventDtos = (EventDto[]) ret;
LinkedList list = new LinkedList<Event>();
for (EventDto e:
eventDtos) {
Event event = new Event(
e.getArtistName(),
e.getEventDate(),
e.getTour(),
e.getTracksNames(),
getTracks(e.getTracksNames(), e.getArtistName()),
e.getSetListId()
);
event.setArtistSupplier(
(b, c) -> new ArtistIterator<R, U, T>(
e.getArtistName(),
(a) -> lastfmApi.getArtistInfo(e.getArtistName())
)
);
list.add(event);
}
return (R) list;
}
public class Event {
private Artist artist;
private Function<String, Artist> artistSupplier;
private String artistName;
private String eventDate;
private String tour;
private String [] tracksNames;
private Iterable<Track> tracks;
private String setlistId;
public void setArtistSupplier(Function<T, U> supplier) {
this.artistSupplier = supplier;
}
public Artist artist(String s) {
return artist = (Artist) artistSupplier.apply((T) s);
}
}
public class Artist {
private String name;
private String bio;
private String url;
private String [] imagesUri;
private String mbid;
}
public abstract class SetListIterator<T, U, R> implements Iterator<R> {
protected String s;
protected int page;
protected T []dtos;
@Override
public R next() {
T[] ret = dtos;
if (!hasNext())
throw new NoSuchElementException();
dtos = moveNext();
return convertToDomainType(ret);
}
public abstract T[] moveNext();
public abstract R convertToDomainType(T[] ret);
}
Upvotes: 1
Views: 10904
Reputation:
Your artistSupplier
function is defined as Function<String, Artist>
with single String
input and Artist
output, while you are trying to pass some function which accepts two arguments (b,c)
and returns ArtistIterator
:
event.setArtistSupplier(
(b, c) -> new ArtistIterator<R, U, T>(
e.getArtistName(),
(a) -> lastfmApi.getArtistInfo(e.getArtistName())
)
);
Since your code does include Event#setArtistSupplier
implementation I can just assume, that it is something like this:
setArtistSupplier(Function<String,Artist> function) {artistSupplier = function;}
EDIT
What you need to do is:
event.setArtistSupplier((name) -> {
Artist artist = ...; // convert name to Artist (e. g. load artist based on name)
return artist;
});
Upvotes: 1