All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dropbox.core.DbxEntry Maven / Gradle / Ivy

The newest version!
package com.dropbox.core;

import static com.dropbox.core.util.StringUtil.jq;

import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

import com.dropbox.core.json.JsonArrayExtractor;
import com.dropbox.core.json.JsonDateExtractor;
import com.dropbox.core.json.JsonExtractionException;
import com.dropbox.core.json.JsonExtractor;
import com.dropbox.core.util.Collector;
import com.dropbox.core.util.DumpWriter;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

/**
 * Holds the metadata for a Dropbox file system entry.  Can either be a regular file or a folder.
 */
public abstract class DbxEntry extends DbxDataObject implements Serializable
{
    public static final long serialVersionUID = 0;

    /**
     * Just the last part of {@link #path}.  Derived automatically from {@link #path}.
     *
     * @see DbxPath#getName
     */
    public final String name;

    /**
     * The path to the file or folder, relative to your application's root.
     * The path always starts with a {@code "/"}.
     *
     * 

* For full-Dropbox apps, the path is relative to the root * of the user's Dropbox. For App Folder apps, the path * is relative to your application's App Folder within the user's Dropbox. *

*/ public final String path; /** * The name of the icon to use for this file. The set of names returned by this call match up * with icons in a set of icons provided by Dropbox. Read more about the icon * field in * Dropbox's documentation for the {@code /metadata} HTTP endpoint. */ public final String iconName; /** * Whether this file or folder might have a thumbnail image you can retrieve via * the [TODO: thumbnail call]. * If this is {@code true}, there might be a thumbnail available. If this is * {@code false}, there is definitely no thumbnail available. */ public final boolean mightHaveThumbnail; /** * @param path {@link #path} * @param iconName {@link #iconName} * @param mightHaveThumbnail {@link #mightHaveThumbnail} */ private DbxEntry(String path, String iconName, boolean mightHaveThumbnail) { this.name = DbxPath.getName(path); this.path = path; this.iconName = iconName; this.mightHaveThumbnail = mightHaveThumbnail; } protected void dumpFields(DumpWriter w) { w.field("path"); dump(w, path); w.field("iconName"); dump(w, iconName); w.field("mightHaveThumbnail"); w.writeln(Boolean.toString(mightHaveThumbnail)); } /** * Whether this metadata is for a folder, which can be cast to type * {@link Folder}. (Every metadata object is either for a file or a folder.) */ public abstract boolean isFolder(); /** * Whether this metadata is for a file, which can be cast to type * {@link File}. (Every metadata object is either for a file or a folder.) */ public abstract boolean isFile(); /** * If this metadata entry is a folder, return it as a {@code DbxEntry.Folder} * instance. If it's not a folder, return {@code null}. */ public abstract Folder asFolder(); /** * If this metadata entry is a file, return it as a {@code DbxEntry.File} * instance. If it's not a file, return {@code null}. */ public abstract File asFile(); /** * The subclass of {@link DbxEntry} used to represent folder metadata. Folders * actually only have the same set of fields as {@link DbxEntry}. */ public static final class Folder extends DbxEntry { public static final long serialVersionUID = 0; /** * @param path {@link #path} * @param iconName {@link #iconName} * @param mightHaveThumbnail {@link #mightHaveThumbnail} */ public Folder(String path, String iconName, boolean mightHaveThumbnail) { super(path, iconName, mightHaveThumbnail); } protected String getTypeName() { return "Folder"; } /** * A abbreviated version of {@link #toStringMultiline}. Only includes the path. */ public String toString() { return "Folder(" + jq(path) + ")"; } public boolean isFolder() { return true; } public boolean isFile() { return false; } public Folder asFolder() { return this; } public File asFile() { return null; } } /** * The subclass of {@link DbxEntry} used to represent file metadata (as opposed * to folder metadata). */ public static final class File extends DbxEntry { public static final long serialVersionUID = 0; /** * The size, in bytes, of the file content. */ public final long numBytes; /** * A human-readable string version of the file size (ex: "13 kb"). This string will * be localized based on the {@link java.util.Locale Locale} in {@link DbxRequestConfig#userLocale} * (passed in to the {@link DbxClient} constructor). */ public final String humanSize; /** * The time the file was added, moved, or last had it's contents changed on the Dropbox * server. (This probably won't match the time on the Dropbox user's filesystem. For that * the {@link #clientMtime} is a better estimate.) * */ public final Date lastModified; /** * The modification time sent up by the Dropbox desktop client when the file was added * or modified. This time is based on the system clock of the particular host that the * client was running on, as opposed to the system clock of the Dropbox servers. * *

* This field should not be used to determine if a file has changed, but only as * a way to sort files by date (when displaying a list of files to the user). *

*/ public final Date clientMtime; public final String mimeType; /** * The revision of the file at this path. This can be used with {@link DbxClient#uploadFile} * and the {@link DbxWriteMode#update} mode to make sure you're overwriting the revision of * the file you think you're overwriting. */ public final String revision; /** * @param path {@link #path} * @param iconName {@link #iconName} * @param mightHaveThumbnail {@link #mightHaveThumbnail} * @param numBytes {@link #numBytes} * @param humanSize {@link #humanSize} * @param lastModified {@link #lastModified} * @param clientMtime {@link #clientMtime} * @param mimeType {@link #mimeType} * @param revision {@link #revision} */ public File(String path, String iconName, boolean mightHaveThumbnail, long numBytes, String humanSize, Date lastModified, Date clientMtime, String mimeType, String revision) { super(path, iconName, mightHaveThumbnail); this.numBytes = numBytes; this.humanSize = humanSize; this.lastModified = lastModified; this.clientMtime = clientMtime; this.mimeType = mimeType; this.revision = revision; } protected void dumpFields(DumpWriter w) { super.dumpFields(w); w.field("numBytes"); w.writeln(Long.toString(numBytes)); w.field("humanSize"); dump(w, humanSize); w.field("lastModified"); dump(w, lastModified); w.field("clientMtime"); dump(w, clientMtime); w.field("mimeType"); dump(w, mimeType); w.field("revision"); dump(w, revision); } protected String getTypeName() { return "File"; } /** * A abbreviated version of {@link #toStringMultiline}. Only includes the path. */ public String toString() { return "File(" + jq(path) + ", numBytes=" + numBytes + ", lastModified=" + toStringDate(lastModified) + ", revision=" + jq(revision) + ")"; } public boolean isFolder() { return false; } public boolean isFile() { return true; } public Folder asFolder() { return null; } public File asFile() { return this; } } // ------------------------------------------------------ // JSON parsing public static final JsonExtractor Extractor = new JsonExtractor() { public final DbxEntry extract(JsonParser parser) throws IOException, JsonExtractionException { return DbxEntry.extract(parser, null).entry; } }; /** * Holds the metadata for a file or folder; if it's a folder, we also store the folder's * hash and the metadata of its immediate children. * * @see DbxClient#getMetadataWithChildren * @see DbxClient#getMetadataWithChildrenIfChanged */ public static final class WithChildren implements Serializable { public static final long serialVersionUID = 0; public final DbxEntry entry; /** * If {@link #entry} is a folder, this will contain a hash that identifies the folder's * contents. This value can be used with {@link DbxClient#getMetadataWithChildrenIfChanged} * to void downloading the folder contents if they havne't changed. */ public final String hash; /** * If {@link #entry} is a folder, this will contain the metadata of the folder's * immediate children. If it's not a folder, this will be {@code null}. */ public final List children; /** * @param entry {@link #entry} * @param hash {@link #hash} * @param children {@link #children} */ public WithChildren(DbxEntry entry, String hash, List children) { this.entry = entry; this.hash = hash; this.children = children; } public static final JsonExtractor Extractor = new JsonExtractor() { public final WithChildren extract(JsonParser parser) throws IOException, JsonExtractionException { WithChildrenC> c = DbxEntry.>extract(parser, new Collector.ArrayListCollector()); return new WithChildren(c.entry, c.hash, c.children); } }; } /** * The more general case of {@link WithChildren}. It's used in the {@code C}-suffixed * variants ({@link DbxClient#getMetadataWithChildrenC} and {@link DbxClient#getMetadataWithChildrenIfChanged} * to allow you to process the {@link DbxEntry} values as the come in and aggregate them into * your own object (instead of the default {@link List}) using a custom {@link Collector}. */ public static final class WithChildrenC implements Serializable { public static final long serialVersionUID = 0; public final DbxEntry entry; /** * If {@link #entry} is a folder, this will contain a hash that identifies the folder's * contents. This value can be used with {@link DbxClient#getMetadataWithChildrenIfChanged} * to void downloading the folder contents if they havne't changed. */ public final String hash; /** * If {@link #entry} is a folder, this will contain the metadata of the folder's * immediate children. If it's not a folder, this will be {@code null}. */ public final C children; /** * @param entry {@link #entry} * @param hash {@link #hash} * @param children {@link #children} */ public WithChildrenC(DbxEntry entry, String hash, C children) { this.entry = entry; this.hash = hash; this.children = children; } public static class Extractor extends JsonExtractor> { private final Collector collector; public Extractor(Collector collector) { this.collector = collector; } public final WithChildrenC extract(JsonParser parser) throws IOException, JsonExtractionException { return DbxEntry.extract(parser, collector); } } } /** * @return * {@code null} if the entry is an 'is_deleted' entry. */ public static WithChildrenC extract(JsonParser parser, Collector collector) throws IOException, JsonExtractionException { JsonLocation top = JsonExtractor.expectObjectStart(parser); String size = null; long bytes = -1; String path = null; Boolean is_dir = null; Boolean is_deleted = null; String rev = null; Boolean thumb_exists = null; String icon = null; Date modified = null; Date client_mtime = null; String mime_type = null; String hash = null; C contents = null; while (parser.getCurrentToken() == JsonToken.FIELD_NAME) { String fieldName = parser.getCurrentName(); JsonExtractor.nextToken(parser); int fi = FM.get(fieldName); try { switch (fi) { case -1: JsonExtractor.skipValue(parser); break; case FM_size: size = JsonExtractor.StringExtractor.extractField(parser, fieldName, size); break; case FM_bytes: bytes = JsonExtractor.extractUnsignedLongField(parser, fieldName, bytes); break; case FM_path: path = JsonExtractor.StringExtractor.extractField(parser, fieldName, path); break; case FM_is_dir: is_dir = JsonExtractor.BooleanExtractor.extractField(parser, fieldName, is_dir); break; case FM_is_deleted: is_deleted = JsonExtractor.BooleanExtractor.extractField(parser, fieldName, is_deleted); break; case FM_rev: rev = JsonExtractor.StringExtractor.extractField(parser, fieldName, rev); break; case FM_thumb_exists: thumb_exists = JsonExtractor.BooleanExtractor.extractField(parser, fieldName, thumb_exists); break; case FM_icon: icon = JsonExtractor.StringExtractor.extractField(parser, fieldName, icon); break; case FM_modified: modified = JsonDateExtractor.Dropbox.extractField(parser, fieldName, modified); break; case FM_client_mtime: client_mtime = JsonDateExtractor.Dropbox.extractField(parser, fieldName, client_mtime); break; case FM_mime_type: mime_type = JsonExtractor.StringExtractor.extractField(parser, fieldName, mime_type); break; case FM_hash: if (collector == null) throw new JsonExtractionException("not expecting \"hash\" field, since we didn't ask for children", parser.getCurrentLocation()); hash = JsonExtractor.StringExtractor.extractField(parser, fieldName, hash); break; case FM_contents: if (collector == null) throw new JsonExtractionException("not expecting \"contents\" field, since we didn't ask for children", parser.getCurrentLocation()); contents = JsonArrayExtractor.mk(Extractor, collector).extractField(parser, fieldName, contents); break; default: throw new AssertionError("bad index: " + fi + ", field = \"" + fieldName + "\""); } } catch (JsonExtractionException ex) { throw ex.addFieldContext(fieldName); } } JsonExtractor.expectObjectEnd(parser); if (path == null) throw new JsonExtractionException("missing field \"path\"", top); if (icon == null) throw new JsonExtractionException("missing field \"icon\"", top); if (is_deleted == null) is_deleted = Boolean.FALSE; if (is_dir == null) is_dir = Boolean.FALSE; if (thumb_exists == null) thumb_exists = Boolean.FALSE; if (is_dir && (contents != null || hash != null)) { if (hash == null) throw new JsonExtractionException("missing \"hash\", when we asked for children", top); if (contents == null) throw new JsonExtractionException("missing \"contents\", when we asked for children", top); } DbxEntry e; if (is_dir) { e = new Folder(path, icon, thumb_exists); } else { // Normal File if (size == null) throw new JsonExtractionException("missing \"size\" for a file entry", top); if (bytes == -1) throw new JsonExtractionException("missing \"bytes\" for a file entry", top); if (modified == null) throw new JsonExtractionException("missing \"modified\" for a file entry", top); if (client_mtime == null) throw new JsonExtractionException("missing \"client_mtime\" for a file entry", top); if (mime_type == null) throw new JsonExtractionException("missing \"mime_type\" for a file entry", top); if (rev == null) throw new JsonExtractionException("missing \"rev\" for a file entry", top); e = new File(path, icon, thumb_exists, bytes, size, modified, client_mtime, mime_type, rev); } if (is_deleted) return null; return new WithChildrenC(e, hash, contents); } private static final int FM_size = 0; private static final int FM_bytes = 1; private static final int FM_path = 2; private static final int FM_is_dir = 3; private static final int FM_is_deleted = 4; private static final int FM_rev = 5; private static final int FM_thumb_exists = 6; private static final int FM_icon = 7; private static final int FM_modified = 8; private static final int FM_client_mtime = 9; private static final int FM_mime_type = 10; private static final int FM_hash = 11; private static final int FM_contents = 12; private static final JsonExtractor.FieldMapping FM; static { JsonExtractor.FieldMapping.Builder b = new JsonExtractor.FieldMapping.Builder(); b.add("size", FM_size); b.add("bytes", FM_bytes); b.add("path", FM_path); b.add("is_dir", FM_is_dir); b.add("is_deleted", FM_is_deleted); b.add("rev", FM_rev); b.add("thumb_exists", FM_thumb_exists); b.add("icon", FM_icon); b.add("modified", FM_modified); b.add("client_mtime", FM_client_mtime); b.add("mime_type", FM_mime_type); b.add("hash", FM_hash); b.add("contents", FM_contents); FM = b.build(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy