/* * Copyright 2005 the original author or authors. * * 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 org.wamblee.crawler.kiss.guide; import java.util.Comparator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.DocumentFactory; import org.dom4j.Element; import org.wamblee.crawler.Action; import org.wamblee.crawler.Page; import org.wamblee.crawler.PageException; import org.wamblee.crawler.kiss.main.SystemProperties; /** * Represents a television program. */ public class Program { private static final String ELEM_PROGRAM = "program"; private static final String ELEM_NAME = "name"; private static final String ELEM_KEYWORDS = "keywords"; private static final String ELEM_DESCRIPTION = "description"; private static final String ELEM_CHANNEL = "channel"; private static final String ELEM_INTERVAL = "interval"; private static final String ELEM_END_TIME = "end"; private static final String ELEM_BEGIN_TIME = "begin"; /** * Lexicographical comparison of programs based on (time, title, channel). * */ public static class TimeComparator implements Comparator { /** * Lexicographical comparison based on start time, program name, and * channel. * * @param aProgram1 * First program. * @param aProgram2 * Second program. * @return See {@link Comparator#compare(T, T)} */ public int compare(Program aProgram1, Program aProgram2) { int value = aProgram1.getInterval().getBegin().compareTo( aProgram2.getInterval().getBegin()); if (value != 0) { return value; } value = aProgram1.getName().compareTo(aProgram2.getName()); if (value != 0) { return value; } return aProgram1.getChannel().compareTo(aProgram2.getChannel()); } } private static final Log LOG = LogFactory.getLog(Program.class); /** * Name of the record action on the program details page. */ private static final String RECORD_ACTION = "record"; /** * Result of recording a program. * */ public enum RecordingResult { /** * Successfully recorded. */ OK, /** * Already recorded program. */ DUPLICATE, /** * Recording conflict with another program. */ CONFLICT, /** * Program occurred in the past. */ OLDSHOW, /** * Program could not be recorded for technical reasons. */ ERROR; }; /** * Indent string to use for pretty printing. */ private static final String INDENT = " "; /** * Channel the program is on. */ private String _channel; /** * Program name. */ private String _name; /** * Program description. */ private String _description; /** * Keywords or classification of the program. */ private String _keywords; /** * Time interval for the program (from/to). */ private TimeInterval _interval; /** * Action to execute to obtain program information and/or record the * program. */ private Action _programInfo; /** * Constructs the program. * * @param aChannel * Channel name. * @param aName * Program name. * @param aDescription * Description. * @param aKeywords * Keywords/classification. * @param aInterval * Time interval. * @param aProgramInfo * Action to execute for detailed program information or for * recording the page. */ public Program(String aChannel, String aName, String aDescription, String aKeywords, TimeInterval aInterval, Action aProgramInfo) { _channel = aChannel; _name = aName; _description = aDescription; _keywords = aKeywords; _interval = aInterval; _programInfo = aProgramInfo; } /** * Gets the channel. * * @return Channel. */ public String getChannel() { return _channel; } /** * Gets the program name. * * @return Name. */ public String getName() { return _name; } /** * Gets the description. * * @return Description. */ public String getDescription() { return _description; } /** * Gets the keywords/classification. * * @return Keywords/classification */ public String getKeywords() { return _keywords; } /** * Gets the time interval. * * @return Time interval. */ public TimeInterval getInterval() { return _interval; } /** * Checks if recording is possible. * * @return True iff recording is possible. */ public boolean isRecordingPossible() { try { return _programInfo.execute().getAction(RECORD_ACTION) != null; } catch (PageException e) { return false; } } /** * Records the show. * * @return Status describing the result of recording. */ public RecordingResult record() { LOG.info("Recording " + this); if (SystemProperties.isRecordDisabled()) { return RecordingResult.OK; } try { Action record = _programInfo.execute().getAction(RECORD_ACTION); if (record == null) { LOG.info(" result: " + RecordingResult.OLDSHOW); return RecordingResult.OLDSHOW; } Page result = record.execute(); RecordingResult recordingResult = RecordingResult.valueOf(result .getContent().getText()); LOG.info(" result: " + recordingResult); return recordingResult; } catch (PageException e) { LOG.warn("Technical problem recording program: '" + this + "'", e); LOG.info(" result: " + RecordingResult.ERROR); return RecordingResult.ERROR; } } /** * Accepts the visitor. * * @param aVisitor * Visitor. */ public void accept(Visitor aVisitor) { aVisitor.visitProgram(this); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return _interval + " - " + _name + " (" + _channel + "/" + _keywords + ")" + "\n" + (INDENT + _description).replaceAll("\n", "\n" + INDENT); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object aObject) { if (!(aObject instanceof Program)) { return false; } Program program = (Program) aObject; return getName().equals(program.getName()) && _programInfo.equals(program._programInfo); } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return getName().hashCode(); } /** * Converts program information to XML. * * @return XML representation of program information. */ public Element asXml() { DocumentFactory factory = DocumentFactory.getInstance(); Element program = factory.createElement(ELEM_PROGRAM); program.addElement(ELEM_NAME).setText(getName()); program.addElement(ELEM_DESCRIPTION).setText(getDescription()); program.addElement(ELEM_KEYWORDS).setText(getKeywords()); program.addElement(ELEM_CHANNEL).setText(getChannel()); Element interval = program.addElement(ELEM_INTERVAL); interval.addElement(ELEM_BEGIN_TIME).setText( getInterval().getBegin().toString()); interval.addElement(ELEM_END_TIME).setText( getInterval().getEnd().toString()); return program; } }