diff options
Diffstat (limited to 'src/plugins/videos/src/com/motorola/studio/android/videos/model/VideoManager.java')
-rw-r--r-- | src/plugins/videos/src/com/motorola/studio/android/videos/model/VideoManager.java | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/src/plugins/videos/src/com/motorola/studio/android/videos/model/VideoManager.java b/src/plugins/videos/src/com/motorola/studio/android/videos/model/VideoManager.java new file mode 100644 index 0000000..4e87470 --- /dev/null +++ b/src/plugins/videos/src/com/motorola/studio/android/videos/model/VideoManager.java @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * 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.motorola.studio.android.videos.model; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.common.utilities.HttpUtils; +import com.motorola.studio.android.videos.Activator; +import com.motorola.studio.android.videos.implementation.youtube.YoutubeVideoServiceProvider; +import com.motorola.studio.android.videos.model.extension.VideoServiceProvider; + +/** + * Manage the actions related to videos, including loading them and + * providing any related information to other classes. + */ +public class VideoManager +{ + + /* + * Sort options + */ + public static final int SORT_MOST_RECENT = 0; + + public static final int SORT_MOST_VIEWED = 1; + + public static final int SORT_TOP_RATED = 2; + + /* + * Video channels and source definitions (XML) + */ + public static final String VIDEOS_DEFINITIONS = "resources/motodev_videos.xml"; + + public static final String TAG_USER = "user"; + + public static final String TAG_USER_ATT_NAME = "name"; + + public static final String TAG_CHANNEL = "channel"; + + public static final String TAG_CHANNEL_ATT_NAME = "name"; + + public static final String TAG_CHANNEL_ATT_DISPLAY_NAME = "display_name"; + + // "fixed" or "variable" + public static final String TAG_CHANNEL_ATT_ORDER = "order"; + + public static final String TAG_CHANNEL_ATT_ORDER_FIXED = "fixed"; + + // "true" or "false" + public static final String TAG_CHANNEL_ATT_DEFAULT = "default"; + + /* + * Singleton + */ + private static VideoManager instance; + + /* + * The selected video service provider + */ + private VideoServiceProvider videoServiceProvider = null; + + /* + * Credentials information to be passed to the video service provider + */ + private String userName = null; + + /* + * The video channel objects (the videos themselves are attributes of these objects) + */ + private String defaultVideoChannel = null; + + // Map "channel name" -> object that represent the video channel + private final Map<String, VideoChannel> channelsMap = new HashMap<String, VideoChannel>(); + + private final List<VideoChannel> channelsList = new ArrayList<VideoChannel>(); + + /** + * Singleton + * + * @return a unique VideoManager instance + * @throws Exception + */ + public static synchronized VideoManager getInstance() throws Exception + { + if (instance == null) + { + instance = new VideoManager(); + } + return instance; + } + + /** + * Load all channels and videos + */ + public void load() throws Exception + { + channelsMap.clear(); + channelsList.clear(); + + File file = + new File(FileLocator.toFileURL( + Activator.getDefault().getBundle().getEntry(VIDEOS_DEFINITIONS)).getPath()); + + DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = documentBuilder.parse(file); + + /* + * Get service username + */ + NodeList user = doc.getElementsByTagName(TAG_USER); + Node userNameNode = user.item(0).getAttributes().getNamedItem(TAG_USER_ATT_NAME); + userName = userNameNode.getNodeValue(); + + /* + * Initialize video service provider + */ + videoServiceProvider = new YoutubeVideoServiceProvider(userName); + + /* + * Get all channels + */ + NodeList channels = doc.getElementsByTagName(TAG_CHANNEL); + + for (int i = 0; i < channels.getLength(); i++) + { + + Node channel = channels.item(i); + String displayName = + channel.getAttributes().getNamedItem(TAG_CHANNEL_ATT_DISPLAY_NAME) + .getTextContent(); + String name = + channel.getAttributes().getNamedItem(TAG_CHANNEL_ATT_NAME).getTextContent(); + boolean order = false; + boolean defaultChannel = false; + if (channel.getAttributes().getNamedItem(TAG_CHANNEL_ATT_ORDER) != null) + { + order = + channel.getAttributes().getNamedItem(TAG_CHANNEL_ATT_ORDER) + .getTextContent().equals(TAG_CHANNEL_ATT_ORDER_FIXED) ? true + : false; + } + if (channel.getAttributes().getNamedItem(TAG_CHANNEL_ATT_DEFAULT) != null) + { + defaultChannel = + channel.getAttributes().getNamedItem(TAG_CHANNEL_ATT_DEFAULT) + .getTextContent().equals(new Boolean(true).toString()) ? true + : false; + } + + /* + * Create and populate the channels + */ + VideoChannel videoChannel = new VideoChannel(name); + videoChannel.setDisplayName(displayName); + videoChannel.setOrdered(order); + videoChannel.setDefaultChannel(defaultChannel); + if (defaultChannel) + { + defaultVideoChannel = name; + } + List<Video> videos = videoServiceProvider.loadVideos(videoChannel); + if (videos != null) + { + videoChannel.setVideos(videos); + } + else + { + videoChannel.setActive(false); + } + channelsMap.put(name, videoChannel); + channelsList.add(videoChannel); + + } + + } + + /** + * Sort all videos from all channels + * + * @param criteria + */ + public void sort(final int criteria) + { + for (VideoChannel channel : channelsList) + { + if (!channel.isOrdered()) + { + List<Video> videos = channel.getVideos(); + Collections.sort(videos, new Comparator<Video>() + { + + public int compare(Video arg0, Video arg1) + { + int result = 0; + + switch (criteria) + { + case VideoManager.SORT_MOST_RECENT: + result = arg0.getDate().compareTo(arg1.getDate()); + break; + case VideoManager.SORT_MOST_VIEWED: + result = arg0.getViews() >= arg1.getViews() ? 1 : -1; + break; + case VideoManager.SORT_TOP_RATED: + result = arg0.getRating() >= arg1.getRating() ? 1 : -1; + break; + + } + return result; + } + }); + } + } + } + + /** + * Get videos from a channel + * + * @param channel channel to retrieve the videos + */ + public List<Video> getVideos(VideoChannel channel) + { + List<Video> videos = null; + if (channelsMap.get(channel.getName()) != null) + { + videos = channelsMap.get(channel.getName()).getVideos(); + } + return videos; + } + + /** + * Get all channels + * + * @return all channels + */ + public List<VideoChannel> getChannels() + { + return channelsList; + } + + /** + * Get only the active channels + * + * @return the active channels, which were found by the video service provider + */ + public List<VideoChannel> getActiveChannels() + { + List<VideoChannel> activeVideoChannels = new ArrayList<VideoChannel>(); + for (VideoChannel channel : channelsList) + { + if (channel.isActive()) + { + activeVideoChannels.add(channel); + } + } + return activeVideoChannels; + } + + /** + * Get the default channel, to be selected in the UI by default + * + * @return the default channel + */ + public VideoChannel getDefaultChannel() + { + return channelsMap.get(defaultVideoChannel); + } + + /** + * Rate a video + * + * @param video video to be rated + * @param rate video rate + */ + public void rate(Video video, int rate) throws Exception + { + // delegate to the video service provider + videoServiceProvider.rate(video, rate); + } + + /** + * Search all videos from all channels + * + * @param keyword search keyword + * @return only the videos that match the keyword + */ + public List<Video> search(String keyword) + { + + List<Video> selectedVideos = new ArrayList<Video>(); + + // split the keyword into tokens + String[] tokens = keyword.split("\\s"); + int numberOfTokens = tokens.length; + + /* + * For each channel, search the videos and try to find all + * tokens on each video + */ + int visibleVideosInChannel; + for (VideoChannel channel : channelsList) + { + visibleVideosInChannel = 0; + for (Video video : channel.getVideos()) + { + + int tokensFound = 0; + + if (numberOfTokens > 0) + { + StringBuffer sb = new StringBuffer(); + sb.append(video.getTitle()); + sb.append(" "); + sb.append(video.getDescription()); + sb.append(" "); + sb.append(video.getKeywords()); + + for (int i = 0; i < tokens.length; i++) + { + String token = tokens[i]; + if (sb.toString().toUpperCase().contains(token.toUpperCase())) + { + tokensFound++; + } + } + } + + // if all tokens were found, mark the video as visible ... + if (tokensFound == numberOfTokens) + { + video.setVisible(true); + visibleVideosInChannel++; + selectedVideos.add(video); + } + // ... otherwise, mark the video as not visible + else + { + video.setVisible(false); + } + } + channel.setVisibleVideos(visibleVideosInChannel); + } + + return selectedVideos; + + } + + /** + * Get the video thumbnail from the internet, given its URL + * + * @param url video URL + * @return the file representing the downloaded thumbnail + */ + public File getThumbnail(URL url) + { + + File cacheIconFile = null; + HttpUtils httpUtils = new HttpUtils(); + InputStream inStream = null; + FileOutputStream outStream = null; + try + { + inStream = httpUtils.getInputStreamForUrl(url.toString(), new NullProgressMonitor()); + + File remoteFile = new File(url.toString()); + String[] remoteFileName = remoteFile.getName().split("\\."); + cacheIconFile = File.createTempFile(remoteFileName[0], "." + remoteFileName[1]); + cacheIconFile.deleteOnExit(); + + outStream = new FileOutputStream(cacheIconFile); + + byte[] buf = new byte[1024]; + int len; + while ((len = inStream.read(buf)) > 0) + { + outStream.write(buf, 0, len); + } + + } + catch (Exception e) + { + StudioLogger.error(this.getClass(), "Error while retrieving video thumbnail", e); + } + finally + { + try + { + inStream.close(); + outStream.close(); + } + catch (Exception e) + { + StudioLogger.error(e.getMessage()); + } + } + + return cacheIconFile; + } + +} |