/* Copyright (c) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gdata.data.docs;
import com.google.gdata.util.common.base.StringUtil;
import com.google.gdata.data.BaseEntry;
import com.google.gdata.data.Category;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.ExtensionProfile;
import com.google.gdata.data.Kind;
import com.google.gdata.data.Link;
import com.google.gdata.data.MediaContent;
import com.google.gdata.data.Person;
import com.google.gdata.data.acl.AclFeed;
import com.google.gdata.data.acl.AclNamespace;
import com.google.gdata.data.extensions.Deleted;
import com.google.gdata.data.extensions.Labels;
import com.google.gdata.data.extensions.LastModifiedBy;
import com.google.gdata.data.extensions.LastViewed;
import com.google.gdata.data.extensions.QuotaBytesUsed;
import com.google.gdata.data.extensions.ResourceId;
import com.google.gdata.data.media.MediaEntry;
import com.google.gdata.data.media.MediaFileSource;
import com.google.gdata.util.ContentType;
import com.google.gdata.util.Namespaces;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* An entry representing a single document of any type within a
* {@link DocumentListFeed}.
*
*
*
*
*/
@Kind.Term(DocumentListEntry.KIND)
public class DocumentListEntry extends MediaEntry<DocumentListEntry> {
/**
* Represents the MIME types supported by the doclist GData feed
*/
public enum MediaType {
JPG("image/jpeg"),
JPEG("image/jpeg"),
PNG("image/png"),
BMP("image/bmp"),
GIF("image/gif"),
TXT("text/plain"),
HTML("text/html"),
HTM("text/html"),
ODT("application/vnd.oasis.opendocument.text"),
SXW("application/vnd.sun.xml.writer"),
DOC("application/msword"),
DOCX("application/vnd.openxmlformats-officedocument." +
"wordprocessingml.document"),
RTF("application/rtf"),
PDF("application/pdf"),
PPS("application/vnd.ms-powerpoint"),
PPT("application/vnd.ms-powerpoint"),
XLS("application/vnd.ms-excel"),
XLSX("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
ODS("application/x-vnd.oasis.opendocument.spreadsheet"),
CSV("text/csv"),
TAB("text/tab-separated-value"),
TSV("text/tab-separated-value"),
SWF("application/x-shockwave-flash"),
ZIP("application/zip"),
WMF("application/x-msmetafile")
;
private String mimeType;
private MediaType(String mimeType) {
this.mimeType = mimeType;
}
public String getMimeType() {
return mimeType;
}
public static MediaType fromFileName(String fileName) {
int index = fileName.lastIndexOf('.');
if (index > 0) {
return valueOf(fileName.substring(index + 1).toUpperCase());
} else {
return valueOf(fileName);
}
}
}
/**
* Returns the mime type given a file name. Not intended for extenal
* use, see setFile(File, String) instead. protected access for
* testing.
*
* @throws IllegalArgumentException if the mime type is not known
* given the file name
*/
protected static String getMimeTypeFromFileName(String fileName) {
return MediaType.fromFileName(fileName).getMimeType();
}
/**
* Label for category.
*
* @deprecated Use LABEL instead.
*/
@Deprecated
public static final String UNKNOWN_LABEL = "unknown";
/**
* Kind category term used to label the entries which are
* of document type.
*
* @deprecated Use KIND instead.
*/
@Deprecated
public static final String UNKNOWN_KIND = DocsNamespace.DOCS_PREFIX
+ DocumentListEntry.UNKNOWN_LABEL;
/**
* Category used to label entries which are of document type.
*
* @deprecated Use CATEGORY instead.
*/
@Deprecated
public static final Category UNKNOWN_CATEGORY = new Category(
Namespaces.gKind, UNKNOWN_KIND, UNKNOWN_LABEL);
/**
* Label for category.
*/
public static final String LABEL = "item";
/**
* Kind category term used to label the entries which are
* of item type.
*/
public static final String KIND = DocsNamespace.DOCS_PREFIX
+ DocumentListEntry.LABEL;
/**
* Category used to label entries which are of item type.
*/
public static final Category CATEGORY = new Category(
Namespaces.gKind, KIND, LABEL);
public static final String FOLDERS_NAMESPACE =
DocsNamespace.DOCS + "/folders";
public static final String PARENT_NAMESPACE =
DocsNamespace.DOCS_PREFIX + "parent";
public static final String REVISIONS_NAMESPACE =
DocsNamespace.DOCS + "/revisions";
public static final String THUMBNAIL_NAMESPACE =
DocsNamespace.DOCS + "/thumbnail";
/**
* Constructs a new uninitialized entry, to be populated by the
* GData parsers.
*/
public DocumentListEntry() {
super();
}
/**
* Constructs a new entry by doing a shallow copy from another BaseEntry
* instance.
*/
public DocumentListEntry(BaseEntry<?> sourceEntry) {
super(sourceEntry);
}
@Override
public void declareExtensions(ExtensionProfile extProfile) {
super.declareExtensions(extProfile);
extProfile.declare(DocumentListEntry.class, Description.class);
extProfile.declare(DocumentListEntry.class, DocumentListAclFeedLink.class);
extProfile.declare(DocumentListEntry.class, LastModifiedBy.class);
extProfile.declare(DocumentListEntry.class, LastViewed.class);
extProfile.declare(DocumentListEntry.class, Md5Checksum.class);
extProfile.declare(DocumentListEntry.class, QuotaBytesUsed.class);
extProfile.declare(DocumentListEntry.class, ResourceId.class);
extProfile.declare(DocumentListEntry.class, WritersCanInvite.class);
}
/**
* Gets the link with which you can open up the document in a Web
* browser. This is a link to the full document-specific UI (for
* edit if the requesting user has edit permission, and a read-only
* HTML rendering otherwise).
*
* @return a link to open up the web browser with
*/
public Link getDocumentLink() {
return super.getHtmlLink();
}
/**
* Gets the resource id that is used to access the document entry or export
* the document.
*
* <code>http://docs.google.com/getdoc?id={id}</code>
* <code>http://spreadsheets.google.com/ccc?key={id}</code>
*
* @return the Google Docs & Spreadsheets id
*
* @deprecated use getResourceId() instead.
*/
@Deprecated
public String getKey() {
String result = state.id;
if (result != null) {
int position = result.lastIndexOf("/");
if (position > 0) {
result = result.substring(position + 1);
}
}
return result;
}
/**
* Gets the docId or spreadsheet key from the resource id. This is the id that
* can be used to construct the export url or link to google docs.
*
* <code>http://docs.google.com/present/edit?id={id}</code>
* <code>http://spreadsheets.google.com/ccc?key={id}</code>
*
* @return the Google Docs doc id
* .
*/
public String getDocId() {
String result = getResourceId();
if (result != null) {
int position = result.lastIndexOf(":");
if (position > 0) {
result = result.substring(position + 1);
}
}
return result;
}
/**
* Returns the type document entry from the resource id. If the resource id
* id "document:12345", then "document" is returned.
*
* @return the document type
* .
*/
public String getType() {
String result = getResourceId();
if (result != null) {
int position = result.lastIndexOf(":");
if (position > 0) {
return result.substring(0, position);
}
}
return result;
}
/**
* Associate a File with this entry, implicitly determining the mime type
* from the file's extension.
*
* @deprecated use setFile(File, String) instead.
*/
@Deprecated
public void setFile(File file) {
setFile(file, getMimeTypeFromFileName(file.getName()));
}
/**
* Associate a File with this entry with the specified mime type
*/
public void setFile(File file, String mimeType) {
MediaFileSource fileSource = new MediaFileSource(file, mimeType);
MediaContent content = new MediaContent();
content.setMediaSource(fileSource);
content.setMimeType(new ContentType(mimeType));
setContent(content);
}
/**
* Sets the hidden status of this document for the user this feed request
* has been authenticated under.
*
* @param hidden true if the document should be hidden
*/
public void setHidden(boolean hidden) {
if (hidden) {
this.getCategories().add(Labels.HIDDEN);
} else {
this.getCategories().remove(Labels.HIDDEN);
}
}
/**
* @return true if the document represented by this entry has been hidden
* by the user this feed request has been authenticated under.
*/
public boolean isHidden() {
return this.getCategories().contains(Labels.HIDDEN);
}
/**
* Sets the starred status of this document for the user this feed request
* has been authenticated under.
*
* @param starred true if the document should be starred
*/
public void setStarred(boolean starred) {
if (starred) {
this.getCategories().add(Labels.STARRED);
} else {
this.getCategories().remove(Labels.STARRED);
}
}
/**
* @return true if the document represented by this entry has been starred
* by the user this feed request has been authenticated under.
*/
public boolean isStarred() {
return this.getCategories().contains(Labels.STARRED);
}
/**
* Sets the viewed status of this document for the user this feed request
* has been authenticated under.
*
* @param viewed true if the document has been viewed
*/
public void setViewed(boolean viewed) {
if (viewed) {
this.getCategories().add(Labels.VIEWED);
} else {
this.getCategories().remove(Labels.VIEWED);
}
}
/**
* @return true if the document represented by this entry has been viewed by
* the user this feed request has been authenticated under.
*/
public boolean isViewed() {
return this.getCategories().contains(Labels.VIEWED);
}
/**
* Sets the trashed status of this document for the user this feed request
* has been authenticated under.
*
* @param trashed true if the document should be trashed
*/
public void setTrashed(boolean trashed) {
if (trashed) {
this.getCategories().add(Labels.TRASHED);
this.setExtension(new Deleted());
} else {
this.getCategories().remove(Labels.TRASHED);
this.removeExtension(Deleted.class);
}
}
/**
* @return true if the document represented by this entry has been trashed
* by the user this feed request has been authenticated under.
*/
public boolean isTrashed() {
return this.getCategories().contains(Labels.TRASHED)
|| this.hasExtension(Deleted.class);
}
/**
* Adds a user-specific folder that parents this document
*
* @param owner the owner of the folder
* @param folderName the name of the folder
* @deprecated use {@link #addLink(Link)} with link relation PARENT_NAMESPACE
* instead.
*/
@Deprecated
public void addFolder(Person owner, String folderName) {
String scheme = FOLDERS_NAMESPACE + "/" + owner.getEmail();
Category folderCategory = new Category(scheme, folderName, folderName);
this.getCategories().add(folderCategory);
}
private static final Pattern FOLDER_PATTERN =
Pattern.compile("^" + Pattern.quote(FOLDERS_NAMESPACE) + "(:?/[^/]+)?$");
/**
* @deprecated use {@link #getParentLinks()} instead.
*/
@Deprecated
public Set<String> getFolders() {
Set<String> folders = new HashSet<String>();
for (Category category : this.getCategories()) {
Matcher matcher = FOLDER_PATTERN.matcher(category.getScheme());
if (matcher.matches()) {
String folderName = category.getLabel();
if (StringUtil.isEmpty(folderName)) {
folderName = category.getTerm();
}
folders.add(folderName);
}
}
return folders;
}
public DocumentListAclFeedLink getAclFeedLink() {
List<DocumentListAclFeedLink> links =
getRepeatingExtension(DocumentListAclFeedLink.class);
for (DocumentListAclFeedLink feedLink : links) {
if (AclNamespace.LINK_REL_ACCESS_CONTROL_LIST.equals(feedLink.getRel())) {
return feedLink;
}
}
return null;
}
public AclFeed getAclFeed() {
DocumentListAclFeedLink feedLink = getAclFeedLink();
return (feedLink != null) ? feedLink.getFeed() : null;
}
public List<Link> getParentLinks() {
return getLinks(PARENT_NAMESPACE, Link.Type.ATOM);
}
/**
* Returns the description of this document.
*
* @return the description ({@code null} means no description was set, whereas the empty-string
* means the description is empty)
*/
public String getDescription() {
Description description = getExtension(Description.class);
if (description == null) {
return null;
}
return description.getValue() == null ? "" : description.getValue();
}
/**
* Sets the description of this document.
*
* @param description the description
*/
public void setDescription(String description) {
if (description == null) {
removeExtension(Description.class);
} else {
setExtension(new Description(description));
}
}
/**
* Returns the time when the document was last viewed by the user.
*
* @return the last viewed time
*/
public DateTime getLastViewed() {
LastViewed lastViewed = getExtension(LastViewed.class);
return lastViewed == null ? null : lastViewed.getValue();
}
/**
* Sets the time when the document was last viewed by the user.
*
* @param lastViewed the last viewed time
*/
public void setLastViewed(DateTime lastViewed) {
if (lastViewed == null) {
removeExtension(LastViewed.class);
} else {
setExtension(new LastViewed(lastViewed));
}
}
/**
* Returns the MD5 checksum calculated for the document.
*
* @return the MD5 checksum
*/
public String getMd5Checksum() {
Md5Checksum md5Checksum = getExtension(Md5Checksum.class);
return md5Checksum == null ? null : md5Checksum.getValue();
}
/**
* Set the MD5 checksum calculated for the document.
*
* @param md5Checksum the MD5 checksum
*/
public void setMd5Checksum(String md5Checksum) {
if (md5Checksum == null) {
removeExtension(Md5Checksum.class);
} else {
setExtension(new Md5Checksum(md5Checksum));
}
}
/**
* Returns the amount of quota consumed by the document.
*
* @return the quota used
*/
public Long getQuotaBytesUsed() {
QuotaBytesUsed quotaBytes = getExtension(QuotaBytesUsed.class);
return quotaBytes == null ? null : quotaBytes.getValue();
}
/**
* Sets the amount of quota consumed by the document.
*
* @param quotaBytesUsed the quota used
*/
public void setQuotaBytesUsed(Long quotaBytesUsed) {
if (quotaBytesUsed == null) {
removeExtension(QuotaBytesUsed.class);
} else {
setExtension(new QuotaBytesUsed(quotaBytesUsed));
}
}
/**
* Returns a flag for whether writers can invite other collaborators
*
* @return whether writers can invite
*/
public Boolean isWritersCanInvite(){
WritersCanInvite writersCanInvite = getExtension(WritersCanInvite.class);
return writersCanInvite == null ? null : writersCanInvite.getValue();
}
/**
* Sets whether users classed as writers can invite other collaborators
*
* @param writersCanInvite true if writers can invite
*/
public void setWritersCanInvite(Boolean writersCanInvite) {
if (writersCanInvite == null) {
removeExtension(WritersCanInvite.class);
} else {
this.setExtension(new WritersCanInvite(writersCanInvite));
}
}
/**
* Returns the user who last modified the document.
*
* @return the user who last modified the document
*/
public LastModifiedBy getLastModifiedBy() {
LastModifiedBy lastModifiedBy = getExtension(LastModifiedBy.class);
return lastModifiedBy == null ? null : lastModifiedBy;
}
/**
* Sets the amount of quota consumed by the document.
*
* @param lastModifiedBy the quota used
*/
public void setLastModifiedBy(LastModifiedBy lastModifiedBy) {
if (lastModifiedBy == null) {
removeExtension(LastModifiedBy.class);
} else {
setExtension(lastModifiedBy);
}
}
/**
* Returns the document's resource id.
*
* @return the resource id.
*/
public String getResourceId() {
ResourceId resourceId = getExtension(ResourceId.class);
return resourceId == null ? null : resourceId.getValue();
}
/**
* Sets the document's resource id.
*
* @param resourceId the resource id.
*/
public void setResourceId(String resourceId) {
if (resourceId == null) {
removeExtension(ResourceId.class);
} else {
setExtension(new ResourceId(resourceId));
}
}
}