package org.wikipedia.readinglist.page; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.util.ArraySet; import com.google.gson.annotations.SerializedName; import org.wikipedia.dataclient.WikiSite; import org.wikipedia.model.BaseModel; import org.wikipedia.page.Namespace; import org.wikipedia.readinglist.page.database.ReadingListPageDiskTable; import org.wikipedia.readinglist.page.database.ReadingListPageHttpTable; import org.wikipedia.readinglist.page.database.ReadingListPageTable; import org.wikipedia.util.ValidateUtil; import java.util.Collections; import java.util.Set; public class ReadingListPageRow extends BaseModel { public static final ReadingListPageTable DATABASE_TABLE = new ReadingListPageTable(); public static final ReadingListPageHttpTable HTTP_DATABASE_TABLE = new ReadingListPageHttpTable(); public static final ReadingListPageDiskTable DISK_DATABASE_TABLE = new ReadingListPageDiskTable(); @NonNull private final String key; @NonNull private final Set<String> listKeys; // todo: remove @SerializedName if not pickled @SerializedName("site") @NonNull private final WikiSite wiki; @NonNull private final Namespace namespace; @NonNull private final String title; @Nullable private Long diskPageRevision; private final long mtime; private long atime; @Nullable private String thumbnailUrl; @Nullable private String description; // The size in bytes for an offline page and all page resources downloaded by // SavedPageSyncService. Null or 0 if DiskStatus.ONLINE or not yet downloaded. Outdated if // the saved page cache size is later exceeded and resources are evicted. Written to by // SavedPageSyncService. // @see ReadingListPageContract.PageCol.PHYSICAL_SIZE // @see ReadingListPageContract.PageCol.LOGICAL_SIZE @Nullable private final Long physicalSize; // The size on disk in bytes. @Nullable private final Long logicalSize; public static Builder<?> builder() { //noinspection rawtypes return new Builder(); } @NonNull public String key() { return key; } @NonNull public WikiSite wikiSite() { return wiki; } /** @return an empty list if the page is to be deleted. */ @NonNull public Set<String> listKeys() { return Collections.unmodifiableSet(listKeys); } public void addListKey(@NonNull String listKey) { listKeys.add(listKey); } public void removeListKey(@NonNull String listKey) { listKeys.remove(listKey); } @NonNull public Namespace namespace() { return namespace; } @NonNull public String title() { return title; } @Nullable public Long diskPageRevision() { return diskPageRevision; } /** @return the time of last modification in seconds since epoch. */ public long mtime() { return mtime; } /** @return the time of last access in seconds since epoch. */ public long atime() { return atime; } public void touch() { atime = System.currentTimeMillis(); } @Nullable public String thumbnailUrl() { return thumbnailUrl; } public void setThumbnailUrl(@Nullable String thumbnailUrl) { this.thumbnailUrl = thumbnailUrl; } public void setDescription(@Nullable String description) { this.description = description; } @Nullable public String description() { return description; } @Nullable public Long physicalSize() { return physicalSize; } @Nullable public Long logicalSize() { return logicalSize; } protected ReadingListPageRow(@NonNull Builder<?> builder) { key = builder.key; listKeys = new ArraySet<>(builder.listKeys); wiki = builder.wiki; namespace = builder.namespace; title = builder.title; diskPageRevision = builder.diskPageRevision; mtime = builder.mtime; atime = builder.atime; thumbnailUrl = builder.thumbnailUrl; description = builder.description; physicalSize = builder.physicalSize; logicalSize = builder.logicalSize; } @SuppressWarnings("unchecked") public static class Builder<Clazz extends Builder<Clazz>> { private String key; private Set<String> listKeys = new ArraySet<>(); private WikiSite wiki; private Namespace namespace; private String title; private Long diskPageRevision; private Long mtime; private Long atime; private String thumbnailUrl; private String description; private Long physicalSize; private Long logicalSize; public Clazz copy(@NonNull ReadingListPageRow copy) { return key(copy.key) .listKeys(copy.listKeys) .site(copy.wiki) .namespace(copy.namespace) .title(copy.title) .mtime(copy.mtime) .atime(copy.atime) .thumbnailUrl(copy.thumbnailUrl) .description(copy.description) .physicalSize(copy.physicalSize) .logicalSize(copy.logicalSize); } public Clazz key(@NonNull String key) { this.key = key; return (Clazz) this; } public Clazz listKeys(@NonNull String listKey) { listKeys = new ArraySet<>(); listKeys.add(listKey); return (Clazz) this; } public Clazz listKeys(@NonNull Set<String> listKeys) { this.listKeys = new ArraySet<>(listKeys); return (Clazz) this; } public Clazz site(@NonNull WikiSite wiki) { this.wiki = wiki; return (Clazz) this; } public Clazz namespace(@NonNull Namespace namespace) { this.namespace = namespace; return (Clazz) this; } public Clazz title(@NonNull String title) { this.title = title; return (Clazz) this; } public Clazz diskPageRevision(long diskPageRevision) { this.diskPageRevision = diskPageRevision; return (Clazz) this; } public Clazz mtime(long mtime) { this.mtime = mtime; return (Clazz) this; } public Clazz atime(long atime) { this.atime = atime; return (Clazz) this; } public Clazz thumbnailUrl(@Nullable String thumbnailUrl) { this.thumbnailUrl = thumbnailUrl; return (Clazz) this; } public Clazz description(@Nullable String description) { this.description = description; return (Clazz) this; } public Clazz physicalSize(@Nullable Long physicalSize) { this.physicalSize = physicalSize; return (Clazz) this; } public Clazz logicalSize(@Nullable Long logicalSize) { this.logicalSize = logicalSize; return (Clazz) this; } public ReadingListPageRow build() { validate(); return new ReadingListPageRow(this); } // TODO: listKeys allows empty currently. Should we permit it? It means delete. protected void validate() { ValidateUtil.noNullElements(key, wiki, namespace, title, mtime, atime); } } }