package com.florianmski.tracktoid.data.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import com.florianmski.tracktoid.data.database.columns.EpisodeColumns;
import com.florianmski.tracktoid.data.database.columns.MovieColumns;
import com.florianmski.tracktoid.data.database.columns.SeasonColumns;
import com.florianmski.tracktoid.data.database.columns.ShowColumns;
import net.simonvt.schematic.annotation.ContentProvider;
import net.simonvt.schematic.annotation.ContentUri;
import net.simonvt.schematic.annotation.InexactContentUri;
import net.simonvt.schematic.annotation.MapColumns;
import net.simonvt.schematic.annotation.NotifyDelete;
import net.simonvt.schematic.annotation.NotifyInsert;
import net.simonvt.schematic.annotation.NotifyUpdate;
import net.simonvt.schematic.annotation.TableEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.observables.ConnectableObservable;
import rx.subjects.PublishSubject;
import rx.subjects.SerializedSubject;
import rx.subjects.Subject;
import timber.log.Timber;
@ContentProvider(authority = ProviderSchematic.AUTHORITY, database = DatabaseSchematic.class, name = "GeneratedProvider", packageName = "com.florianmski.tracktoid.data.provider")
public final class ProviderSchematic
{
private static Subject<Uri, Uri> subject = new SerializedSubject<>(PublishSubject.<Uri>create());
private ProviderSchematic() {}
public static void init(final Context context)
{
ConnectableObservable<Uri> notifyUrisEmitter = subject.publish();
notifyUrisEmitter.publish(new Func1<Observable<Uri>, Observable<List<Uri>>>()
{
@Override
public Observable<List<Uri>> call(Observable<Uri> stream)
{
return stream.buffer(stream.debounce(1, TimeUnit.SECONDS));
}
}).flatMap(new Func1<List<Uri>, Observable<Uri>>()
{
@Override
public Observable<Uri> call(List<Uri> uris)
{
Timber.d("TIME TO NOTIFY!");
return Observable.from(uris).distinct();
}
}).subscribe(new Action1<Uri>()
{
@Override
public void call(Uri uri)
{
Timber.d("notifying : " + uri.toString().replace("content://com.florianmski.tracktoid.data.provider.TraktoidProvider/", ""));
context.getContentResolver().notifyChange(uri, null);
}
});
notifyUrisEmitter.connect();
}
public static final String AUTHORITY = "com.florianmski.tracktoid.data.provider.TraktoidProvider";
static final Uri BASE_CONTENT_URI = Uri.parse("content://" + AUTHORITY);
interface Path
{
String SHOWS = "shows";
String FROM_SHOW = "fromShow";
String SEASONS = "seasons";
String FROM_SEASON = "fromSeason";
String EPISODES = "episodes";
String MOVIES = "movies";
}
private static Uri buildUri(String... paths)
{
Uri.Builder builder = BASE_CONTENT_URI.buildUpon();
for (String path : paths)
builder.appendPath(path);
return builder.build();
}
static Uri getBaseUri(Uri uri)
{
return BASE_CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(0)).build();
}
@NotifyDelete()
public static Uri[] defaultNotifyDelete(Uri uri)
{
sendUrisToSubject(getBaseUri(uri));
return new Uri[]{};
}
@TableEndpoint(table = DatabaseSchematic.SHOWS)
public static class Shows
{
public static String[] PROJECTION = new String[]{
ShowColumns.ID,
ShowColumns.AIR_DAY,
ShowColumns.AIR_TIME,
ShowColumns.AIR_TIMEZONE,
ShowColumns.CERTIFICATION,
ShowColumns.COUNTRY,
ShowColumns.EPISODES_AIRED,
ShowColumns.FIRST_AIRED,
ShowColumns.GENRES,
ShowColumns.HOMEPAGE,
ShowColumns.LANGUAGE,
ShowColumns.NETWORK,
ShowColumns.OVERVIEW,
ShowColumns.RUNTIME,
ShowColumns.STATUS,
ShowColumns.TITLE,
ShowColumns.TRAILER,
ShowColumns.UPDATED_AT,
ShowColumns.YEAR,
ShowColumns.EPISODES_COLLECTED,
ShowColumns.EPISODES_WATCHED,
ShowColumns.LAST_COLLECTED_AT,
ShowColumns.LAST_WATCHED_AT,
ShowColumns.PLAYS,
ShowColumns.RATED_AT,
ShowColumns.RATING,
ShowColumns.WATCHLISTED,
ShowColumns.WATCHLISTED_AT,
ShowColumns.PUBLIC_RATING,
ShowColumns.VOTES,
ShowColumns.ID_IMDB,
ShowColumns.ID_SLUG,
ShowColumns.ID_TRAKT,
ShowColumns.ID_TMDB,
ShowColumns.ID_TVDB,
ShowColumns.ID_TVRAGE,
ShowColumns.IMAGE_FANART_FULL,
ShowColumns.IMAGE_FANART_MEDIUM,
ShowColumns.IMAGE_FANART_THUMB,
ShowColumns.IMAGE_POSTER_FULL,
ShowColumns.IMAGE_POSTER_MEDIUM,
ShowColumns.IMAGE_POSTER_THUMB,
ShowColumns.IMAGE_BANNER,
ShowColumns.IMAGE_CLEARART,
ShowColumns.IMAGE_LOGO,
ShowColumns.IMAGE_THUMB
};
@MapColumns
public static Map<String, String> mapColumns()
{
Map<String, String> map = new HashMap<>();
map.put(ShowColumns.EPISODES_AIRED, EPISODES_AIRED_COUNT);
map.put(ShowColumns.EPISODES_COLLECTED, EPISODES_COLLECTED_COUNT);
map.put(ShowColumns.EPISODES_WATCHED, EPISODES_WATCHED_COUNT);
map.put(ShowColumns.LAST_COLLECTED_AT, LAST_COLLECTED_AT);
map.put(ShowColumns.LAST_WATCHED_AT, LAST_WATCHED_AT);
map.put(ShowColumns.PLAYS, PLAYS);
return map;
}
private static final String EPISODES_AIRED_COUNT = episodesCount(
EpisodeColumns.FIRST_AIRED + ">0",
EpisodeColumns.FIRST_AIRED + "<=" + System.currentTimeMillis()
);
// ensure we count the right episodes (user could have mark as watched/collected episodes in the future)
private static final String EPISODES_COLLECTED_COUNT = episodesCount(
EpisodeColumns.COLLECTED + "=1",
EpisodeColumns.FIRST_AIRED + ">0",
EpisodeColumns.FIRST_AIRED + "<=" + System.currentTimeMillis()
);
private static final String EPISODES_WATCHED_COUNT = episodesCount(
EpisodeColumns.WATCHED + "=1",
EpisodeColumns.FIRST_AIRED + ">0",
EpisodeColumns.FIRST_AIRED + "<=" + System.currentTimeMillis()
);
private static String episodesCount(String... conditions)
{
return createQuery("COUNT(*)", false, conditions);
}
private static final String LAST_COLLECTED_AT = createQuery("MAX(" + EpisodeColumns.COLLECTED_AT + ")", true);
private static final String LAST_WATCHED_AT = createQuery("MAX(" + EpisodeColumns.LAST_WATCHED_AT + ")", true);
private static final String PLAYS = createQuery("SUM(" + EpisodeColumns.PLAYS + ")", true);
private static String createQuery(String select, boolean includeSpecials, String... conditions)
{
String sqlQuery = "(SELECT " + select + " FROM "
+ DatabaseSchematic.EPISODES
+ " WHERE "
+ DatabaseSchematic.EPISODES + "." + EpisodeColumns.SHOW_ID
+ "="
+ DatabaseSchematic.SHOWS + "." + ShowColumns.ID_TRAKT;
if (!includeSpecials)
sqlQuery += " AND " + EpisodeColumns.SEASON + "!=0";
for (String condition : conditions)
sqlQuery += " AND " + condition;
return sqlQuery + ")";
}
@ContentUri(
path = Path.SHOWS,
type = "vnd.android.cursor.dir/show",
defaultSort = ShowColumns.TITLE + " ASC")
public static final Uri CONTENT_URI = buildUri(Path.SHOWS);
@InexactContentUri(
path = Path.SHOWS + "/#",
name = "SHOW_ID",
type = "vnd.android.cursor.item/show",
whereColumn = ShowColumns.ID_TRAKT,
pathSegment = 1)
public static Uri withId(String showId)
{
return buildUri(Path.SHOWS, showId);
}
@NotifyInsert(paths = Path.SHOWS)
public static Uri[] notifyInsert(ContentValues values)
{
final String showId = values.getAsString(ShowColumns.ID_TRAKT);
sendUrisToSubject(CONTENT_URI, withId(showId));
return new Uri[]{};
}
@NotifyUpdate(paths = Path.SHOWS + "/#")
public static Uri[] notifyUpdate(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
@NotifyDelete(paths = Path.SHOWS + "/#")
public static Uri[] notifyDelete(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
private static Uri[] getUrisToNotify(Context context, Uri uri, String where, String[] whereArgs)
{
// Notify every show concerned by the where clause + the CONTENT_URI
Set<Uri> uris = new HashSet<>();
Cursor c = context.getContentResolver().query(uri, new String[]{ShowColumns.ID_TRAKT}, where, whereArgs, null);
while (c.moveToNext())
{
final String id = c.getString(0);
uris.add(withId(id));
}
c.close();
uris.add(CONTENT_URI);
sendUrisToSubject(uris);
return new Uri[]{};
}
}
@TableEndpoint(table = DatabaseSchematic.SEASONS)
public static class Seasons
{
public static String[] PROJECTION = new String[]{
SeasonColumns.ID,
SeasonColumns.EPISODES_AIRED,
SeasonColumns.NUMBER,
SeasonColumns.OVERVIEW,
SeasonColumns.SHOW_ID,
SeasonColumns.EPISODES_COLLECTED,
SeasonColumns.EPISODES_WATCHED,
SeasonColumns.LAST_COLLECTED_AT,
SeasonColumns.LAST_WATCHED_AT,
SeasonColumns.PLAYS,
SeasonColumns.RATED_AT,
SeasonColumns.RATING,
SeasonColumns.WATCHLISTED,
SeasonColumns.WATCHLISTED_AT,
SeasonColumns.PUBLIC_RATING,
SeasonColumns.VOTES,
SeasonColumns.ID_TRAKT,
SeasonColumns.ID_TMDB,
SeasonColumns.ID_TVDB,
SeasonColumns.ID_TVRAGE,
SeasonColumns.IMAGE_POSTER_FULL,
SeasonColumns.IMAGE_POSTER_MEDIUM,
SeasonColumns.IMAGE_POSTER_THUMB,
SeasonColumns.IMAGE_THUMB
};
@MapColumns
public static Map<String, String> mapColumns()
{
Map<String, String> map = new HashMap<>();
map.put(SeasonColumns.EPISODES_AIRED, EPISODES_AIRED_COUNT);
map.put(SeasonColumns.EPISODES_COLLECTED, EPISODES_COLLECTED_COUNT);
map.put(SeasonColumns.EPISODES_WATCHED, EPISODES_WATCHED_COUNT);
map.put(SeasonColumns.LAST_COLLECTED_AT, LAST_COLLECTED_AT);
map.put(SeasonColumns.LAST_WATCHED_AT, LAST_WATCHED_AT);
map.put(SeasonColumns.PLAYS, PLAYS);
return map;
}
private static final String EPISODES_AIRED_COUNT = episodesCount(
EpisodeColumns.FIRST_AIRED + ">0",
EpisodeColumns.FIRST_AIRED + "<=" + System.currentTimeMillis()
);
private static final String EPISODES_COLLECTED_COUNT = episodesCount(
EpisodeColumns.COLLECTED + "=1",
EpisodeColumns.FIRST_AIRED + ">0",
EpisodeColumns.FIRST_AIRED + "<=" + System.currentTimeMillis()
);
private static final String EPISODES_WATCHED_COUNT = episodesCount(
EpisodeColumns.WATCHED + "=1",
EpisodeColumns.FIRST_AIRED + ">0",
EpisodeColumns.FIRST_AIRED + "<=" + System.currentTimeMillis()
);
private static String episodesCount(String... conditions)
{
return createQuery("COUNT(*)", conditions);
}
private static final String LAST_COLLECTED_AT = createQuery("MAX(" + EpisodeColumns.COLLECTED_AT + ")");
private static final String LAST_WATCHED_AT = createQuery("MAX(" + EpisodeColumns.LAST_WATCHED_AT + ")");
private static final String PLAYS = createQuery("SUM(" + EpisodeColumns.PLAYS + ")");
private static String createQuery(String select, String... conditions)
{
String sqlQuery = "(SELECT " + select + " FROM "
+ DatabaseSchematic.EPISODES
+ " WHERE "
+ DatabaseSchematic.EPISODES + "." + EpisodeColumns.SEASON_ID
+ "="
+ DatabaseSchematic.SEASONS + "." + SeasonColumns.ID_TRAKT;
for (String condition : conditions)
sqlQuery += " AND " + condition;
return sqlQuery + ")";
}
@ContentUri(
path = Path.SEASONS,
type = "vnd.android.cursor.dir/season")
public static final Uri CONTENT_URI = buildUri(Path.SEASONS);
@InexactContentUri(
name = "SEASON_ID",
path = Path.SEASONS + "/#",
type = "vnd.android.cursor.item/season",
whereColumn = SeasonColumns.ID_TRAKT,
pathSegment = 1)
public static Uri withId(String seasonId)
{
return buildUri(Path.SEASONS, seasonId);
}
@InexactContentUri(
name = "SEASONS_FROM_SHOW",
path = Path.SEASONS + "/" + Path.FROM_SHOW + "/#",
type = "vnd.android.cursor.dir/season",
whereColumn = SeasonColumns.SHOW_ID,
pathSegment = 2)
public static Uri fromShow(String showId)
{
return buildUri(Path.SEASONS, Path.FROM_SHOW, showId);
}
@NotifyInsert(paths = Path.SEASONS)
public static Uri[] notifyInsert(ContentValues values)
{
final String showId = values.getAsString(SeasonColumns.SHOW_ID);
sendUrisToSubject(
CONTENT_URI, fromShow(showId), // notify seasons
Shows.CONTENT_URI, Shows.withId(showId) // notify shows
);
return new Uri[]{};
}
@NotifyUpdate(paths = {
Path.SEASONS + "/#",
Path.SEASONS + "/" + Path.FROM_SHOW + "/#"})
public static Uri[] notifyUpdate(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
@NotifyDelete(paths = {
Path.SEASONS + "/#",
Path.SEASONS + "/" + Path.FROM_SHOW + "/#"})
public static Uri[] notifyDelete(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
private static Uri[] getUrisToNotify(Context context, Uri uri, String where, String[] whereArgs)
{
Set<Uri> uris = new HashSet<>();
Cursor c = context.getContentResolver().query(uri, new String[]{
SeasonColumns.ID_TRAKT, SeasonColumns.SHOW_ID,
}, where, whereArgs, null);
while (c.moveToNext())
{
final String id = c.getString(0);
final String showId = c.getString(1);
uris.add(withId(id));
uris.add(fromShow(showId));
uris.add(Episodes.fromShow(showId));
uris.add(Episodes.fromSeason(id));
}
c.close();
uris.add(CONTENT_URI);
uris.add(Seasons.CONTENT_URI);
uris.add(Shows.CONTENT_URI);
sendUrisToSubject(uris);
return new Uri[]{};
}
}
@TableEndpoint(table = DatabaseSchematic.EPISODES)
public static class Episodes
{
public static String[] PROJECTION = new String[]{
EpisodeColumns.ID,
EpisodeColumns.FIRST_AIRED,
EpisodeColumns.NUMBER,
EpisodeColumns.NUMBER_ABS,
EpisodeColumns.OVERVIEW,
EpisodeColumns.SEASON,
EpisodeColumns.SEASON_ID,
EpisodeColumns.SHOW_ID,
EpisodeColumns.TITLE,
EpisodeColumns.UPDATED_AT,
EpisodeColumns.COLLECTED,
EpisodeColumns.COLLECTED_AT,
EpisodeColumns.LAST_WATCHED_AT,
EpisodeColumns.PLAYS,
EpisodeColumns.RATED_AT,
EpisodeColumns.RATING,
EpisodeColumns.WATCHED,
EpisodeColumns.WATCHLISTED,
EpisodeColumns.WATCHLISTED_AT,
EpisodeColumns.PUBLIC_RATING,
EpisodeColumns.VOTES,
EpisodeColumns.ID_IMDB,
EpisodeColumns.ID_TRAKT,
EpisodeColumns.ID_TMDB,
EpisodeColumns.ID_TVDB,
EpisodeColumns.ID_TVRAGE,
EpisodeColumns.IMAGE_SCREENSHOT_FULL,
EpisodeColumns.IMAGE_SCREENSHOT_MEDIUM,
EpisodeColumns.IMAGE_SCREENSHOT_THUMB
};
@ContentUri(
path = Path.EPISODES,
type = "vnd.android.cursor.dir/episode")
public static final Uri CONTENT_URI = buildUri(Path.EPISODES);
@InexactContentUri(
name = "EPISODE_ID",
path = Path.EPISODES + "/#",
type = "vnd.android.cursor.item/episode",
whereColumn = EpisodeColumns.ID_TRAKT,
pathSegment = 1)
public static Uri withId(String episodeId)
{
return buildUri(Path.EPISODES, episodeId);
}
@InexactContentUri(
name = "EPISODES_FROM_SEASON",
path = Path.EPISODES + "/" + Path.FROM_SEASON + "/#",
type = "vnd.android.cursor.dir/episode",
whereColumn = EpisodeColumns.SEASON_ID,
pathSegment = 2)
public static Uri fromSeason(String seasonId)
{
return buildUri(Path.EPISODES, Path.FROM_SEASON, seasonId);
}
@InexactContentUri(
name = "EPISODES_FROM_SHOW",
path = Path.EPISODES + "/" + Path.FROM_SHOW + "/#",
type = "vnd.android.cursor.dir/episode",
whereColumn = EpisodeColumns.SHOW_ID,
pathSegment = 2)
public static Uri fromShow(String showId)
{
return buildUri(Path.EPISODES, Path.FROM_SHOW, showId);
}
@NotifyInsert(paths = Path.EPISODES)
public static Uri[] notifyInsert(ContentValues values)
{
final String showId = values.getAsString(EpisodeColumns.SHOW_ID);
final String seasonId = values.getAsString(EpisodeColumns.SEASON_ID);
sendUrisToSubject(
CONTENT_URI, fromShow(showId), fromSeason(seasonId), // notify episodes
Seasons.CONTENT_URI, Seasons.withId(seasonId), Seasons.fromShow(showId), // notify seasons
Shows.CONTENT_URI, Shows.withId(showId) // notify shows
);
return new Uri[]{};
}
@NotifyUpdate(paths = {
Path.EPISODES + "/#",
Path.EPISODES + "/" + Path.FROM_SEASON + "/#",
Path.EPISODES + "/" + Path.FROM_SHOW + "/#"})
public static Uri[] notifyUpdate(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
@NotifyDelete(paths = {
Path.EPISODES + "/#",
Path.EPISODES + "/" + Path.FROM_SEASON + "/#",
Path.EPISODES + "/" + Path.FROM_SHOW + "/#"})
public static Uri[] notifyDelete(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
private static Uri[] getUrisToNotify(Context context, Uri uri, String where, String[] whereArgs)
{
Set<Uri> uris = new HashSet<>();
Cursor c = context.getContentResolver().query(uri, new String[]{
EpisodeColumns.ID_TRAKT, EpisodeColumns.SHOW_ID, EpisodeColumns.SEASON_ID,
}, where, whereArgs, null);
while (c.moveToNext())
{
final String id = c.getString(0);
final String showId = c.getString(1);
final String seasonId = c.getString(2);
uris.add(withId(id));
uris.add(fromShow(showId));
uris.add(fromSeason(seasonId));
uris.add(Seasons.withId(seasonId));
uris.add(Seasons.fromShow(showId));
uris.add(Shows.withId(showId));
}
c.close();
uris.add(CONTENT_URI);
uris.add(Seasons.CONTENT_URI);
uris.add(Shows.CONTENT_URI);
sendUrisToSubject(uris);
return new Uri[]{};
}
}
@TableEndpoint(table = DatabaseSchematic.MOVIES)
public static class Movies
{
public static String[] PROJECTION = new String[]{
MovieColumns.ID,
MovieColumns.CERTIFICATION,
MovieColumns.GENRES,
MovieColumns.HOMEPAGE,
MovieColumns.LANGUAGE,
MovieColumns.OVERVIEW,
MovieColumns.RELEASED,
MovieColumns.RUNTIME,
MovieColumns.TAGLINE,
MovieColumns.TITLE,
MovieColumns.TRAILER,
MovieColumns.UPDATED_AT,
MovieColumns.YEAR,
MovieColumns.COLLECTED,
MovieColumns.COLLECTED_AT,
MovieColumns.LAST_WATCHED_AT,
MovieColumns.PLAYS,
MovieColumns.RATED_AT,
MovieColumns.RATING,
MovieColumns.WATCHED,
MovieColumns.WATCHLISTED,
MovieColumns.WATCHLISTED_AT,
MovieColumns.PUBLIC_RATING,
MovieColumns.VOTES,
MovieColumns.ID_IMDB,
MovieColumns.ID_SLUG,
MovieColumns.ID_TRAKT,
MovieColumns.ID_TMDB,
MovieColumns.IMAGE_FANART_FULL,
MovieColumns.IMAGE_FANART_MEDIUM,
MovieColumns.IMAGE_FANART_THUMB,
MovieColumns.IMAGE_POSTER_FULL,
MovieColumns.IMAGE_POSTER_MEDIUM,
MovieColumns.IMAGE_POSTER_THUMB,
MovieColumns.IMAGE_BANNER,
MovieColumns.IMAGE_CLEARART,
MovieColumns.IMAGE_LOGO,
MovieColumns.IMAGE_THUMB
};
@ContentUri(
path = Path.MOVIES,
type = "vnd.android.cursor.dir/movie",
defaultSort = MovieColumns.TITLE + " ASC")
public static final Uri CONTENT_URI = buildUri(Path.MOVIES);
@InexactContentUri(
path = Path.MOVIES + "/#",
name = "MOVIE_ID",
type = "vnd.android.cursor.item/movie",
whereColumn = MovieColumns.ID_TRAKT,
pathSegment = 1)
public static Uri withId(String traktId)
{
return buildUri(Path.MOVIES, traktId);
}
@NotifyInsert(paths = Path.MOVIES)
public static Uri[] notifyInsert(ContentValues values)
{
final String movieId = values.getAsString(MovieColumns.ID_TRAKT);
sendUrisToSubject(CONTENT_URI, withId(movieId));
return new Uri[]{};
}
@NotifyUpdate(paths = Path.MOVIES + "/#")
public static Uri[] notifyUpdate(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
@NotifyDelete(paths = Path.MOVIES + "/#")
public static Uri[] notifyDelete(Context context, Uri uri, String where, String[] whereArgs)
{
return getUrisToNotify(context, uri, where, whereArgs);
}
private static Uri[] getUrisToNotify(Context context, Uri uri, String where, String[] whereArgs)
{
// Notify every movie concerned by the where clause + the CONTENT_URI
Set<Uri> uris = new HashSet<>();
Cursor c = context.getContentResolver().query(uri, new String[]{MovieColumns.ID_TRAKT}, where, whereArgs, null);
while (c.moveToNext())
{
final String id = c.getString(0);
uris.add(withId(id));
}
c.close();
uris.add(CONTENT_URI);
sendUrisToSubject(uris);
return new Uri[]{};
}
}
private static void sendUrisToSubject(Uri... uris)
{
for(Uri uri : uris)
subject.onNext(uri);
}
private static void sendUrisToSubject(Collection<Uri> uris)
{
sendUrisToSubject(uris.toArray(new Uri[uris.size()]));
}
}