/* 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.media; import com.google.gdata.client.CoreErrorDomain; import com.google.gdata.client.Service; import com.google.gdata.client.media.MediaService; import com.google.gdata.data.BaseEntry; import com.google.gdata.data.Content; import com.google.gdata.data.ExtensionProfile; import com.google.gdata.data.Link; import com.google.gdata.data.MediaContent; import com.google.gdata.util.ContentType; import com.google.gdata.util.ParseException; import com.google.gdata.util.ServiceException; import org.xml.sax.Attributes; import java.io.IOException; import java.net.URL; /** * The MediaEntry class is an abstract base class for GData services * that support media content. * * @param <E> the entry class for the bound subtype. * */ public abstract class MediaEntry<E extends BaseEntry<E>> extends BaseEntry<E> implements IMediaEntry { /** * Constructs a new BaseEntry instance. */ protected MediaEntry() { super(); } /** * Copy constructor that initializes a new BaseEntry instance to have * identical contents to another instance, using a shared reference to * the same entry state. * {@link com.google.gdata.data.Kind.Adaptor} subclasses * of {@code BaseEntry} can use this constructor to create adaptor * instances of an entry that share state with the original. */ protected MediaEntry(BaseEntry<?> sourceEntry) { super(sourceEntry); } @Override public void setService(Service v) { if (!(v instanceof MediaService)) { throw new IllegalArgumentException("Service does not support media"); } super.setService(v); } public void setMediaSource(MediaSource mediaSource) { MediaContent content; if (state.content == null) { content = new MediaContent(); state.content = content; } else if (state.content instanceof MediaContent) { content = (MediaContent) state.content; } else { throw new IllegalArgumentException("Cannot set media source on entry " + "with existing non-MediaContent: " + state.content); } content.setMediaSource(mediaSource); content.setMimeType(new ContentType(mediaSource.getContentType())); } public MediaSource getMediaSource() { if (state.content instanceof MediaContent) { MediaContent mediaContent = (MediaContent) state.content; if (mediaContent != null) { return mediaContent.getMediaSource(); } } return null; } /** Retrieves the media resource edit link. */ @Override @SuppressWarnings("deprecation") public Link getMediaEditLink() { Link mediaLink = getLink(Link.Rel.MEDIA_EDIT, null); if (mediaLink == null) { // Temporary back compat support for old incorrect media link value. // to the new value. mediaLink = getLink(Link.Rel.MEDIA_EDIT_BACKCOMPAT, null); } return mediaLink; } /** * Updates the media content associated with this entry by sending the * data contained in the {@link MediaSource} of the entry to the associated * GData service. Can optionally update the entry content at the same time. * * @param updateEntry set to {code boolean} true if the current entry * content should be updated with the media. * * @return the updated entry returned by the Service. * * @throws ServiceException * If there is no associated GData service or the service is * unable to perform the update. * * @throws com.google.gdata.util.InvalidEntryException * If the entry does not contain {@code MediaContent} or * there is no {@link MediaSource} associated with the content. * * @throws UnsupportedOperationException * If update is not supported for the target entry. * * @throws IOException * If there is an error communicating with the GData service. */ @SuppressWarnings({"unchecked"}) public E updateMedia(boolean updateEntry) throws IOException, ServiceException { MediaSource media = getMediaSource(); if (media == null) { throw new NullPointerException("Must supply media source"); } if (state.service == null) { throw new ServiceException( CoreErrorDomain.ERR.entryNotAssociated); } Link mediaLink = getMediaEditLink(); if (mediaLink == null) { throw new UnsupportedOperationException("Media cannot be updated"); } URL mediaUrl = new URL(mediaLink.getHref()); MediaService service = (MediaService) state.service; if (!updateEntry) { return (E) service.updateMedia(mediaUrl, getClass(), media); } return (E) service.updateMedia(mediaUrl, this); } // Override content handler lookup to provide media handling. @Override protected Content.ChildHandlerInfo getContentHandlerInfo( ExtensionProfile extProfile, Attributes attrs) throws ParseException, IOException { // Use the extended child handler that supports out-of-line media content. return MediaContent.getChildHandler(extProfile, attrs); } }