2 * Copyright 2005 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.wamblee.crawler.kiss.guide;
19 import java.util.Comparator;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.dom4j.DocumentFactory;
24 import org.dom4j.Element;
25 import org.wamblee.crawler.Action;
26 import org.wamblee.crawler.Page;
27 import org.wamblee.crawler.PageException;
28 import org.wamblee.crawler.kiss.main.SystemProperties;
31 * Represents a television program.
33 * @author Erik Brakkee
35 public class Program {
37 private static final String ELEM_PROGRAM = "program";
39 private static final String ELEM_NAME = "name";
41 private static final String ELEM_KEYWORDS = "keywords";
43 private static final String ELEM_DESCRIPTION = "description";
45 private static final String ELEM_CHANNEL = "channel";
47 private static final String ELEM_INTERVAL = "interval";
49 private static final String ELEM_END_TIME = "end";
51 private static final String ELEM_BEGIN_TIME = "begin";
54 * Lexicographical comparison of programs based on (time, title, channel).
57 public static class TimeComparator implements Comparator<Program> {
60 * Lexicographical comparison based on start time, program name, and
67 * @return See {@link Comparator#compare(T, T)}
69 public int compare(Program aProgram1, Program aProgram2) {
70 int value = aProgram1.getInterval().getBegin().compareTo(
71 aProgram2.getInterval().getBegin());
75 value = aProgram1.getName().compareTo(aProgram2.getName());
79 return aProgram1.getChannel().compareTo(aProgram2.getChannel());
83 private static final Log LOG = LogFactory.getLog(Program.class);
86 * Name of the record action on the program details page.
88 private static final String RECORD_ACTION = "record";
91 * Result of recording a program.
94 public enum RecordingResult {
96 * Successfully recorded.
101 * Already recorded program.
106 * Recording conflict with another program.
111 * Program occurred in the past.
116 * Program could not be recorded for technical reasons.
122 * Indent string to use for pretty printing.
124 private static final String INDENT = " ";
127 * Channel the program is on.
129 private String _channel;
134 private String _name;
137 * Program description.
139 private String _description;
142 * Keywords or classification of the program.
144 private String _keywords;
147 * Time interval for the program (from/to).
149 private TimeInterval _interval;
152 * Action to execute to obtain program information and/or record the
155 private Action _programInfo;
158 * Constructs the program.
164 * @param aDescription
167 * Keywords/classification.
170 * @param aProgramInfo
171 * Action to execute for detailed program information or for
172 * recording the page.
174 public Program(String aChannel, String aName, String aDescription,
175 String aKeywords, TimeInterval aInterval, Action aProgramInfo) {
178 _description = aDescription;
179 _keywords = aKeywords;
180 _interval = aInterval;
181 _programInfo = aProgramInfo;
189 public String getChannel() {
194 * Gets the program name.
198 public String getName() {
203 * Gets the description.
205 * @return Description.
207 public String getDescription() {
212 * Gets the keywords/classification.
214 * @return Keywords/classification
216 public String getKeywords() {
221 * Gets the time interval.
223 * @return Time interval.
225 public TimeInterval getInterval() {
230 * Checks if recording is possible.
232 * @return True iff recording is possible.
234 public boolean isRecordingPossible() {
236 return _programInfo.execute().getAction(RECORD_ACTION) != null;
237 } catch (PageException e) {
245 * @return Status describing the result of recording.
247 public RecordingResult record() {
248 LOG.info("Recording " + this);
249 if (SystemProperties.isRecordDisabled()) {
250 return RecordingResult.OK;
253 Action record = _programInfo.execute().getAction(RECORD_ACTION);
254 if (record == null) {
255 LOG.info(" result: " + RecordingResult.OLDSHOW);
256 return RecordingResult.OLDSHOW;
258 Page result = record.execute();
259 RecordingResult recordingResult = RecordingResult.valueOf(result
260 .getContent().getText());
261 LOG.info(" result: " + recordingResult);
262 return recordingResult;
263 } catch (PageException e) {
264 LOG.warn("Technical problem recording program: '" + this + "'", e);
265 LOG.info(" result: " + RecordingResult.ERROR);
266 return RecordingResult.ERROR;
271 * Accepts the visitor.
276 public void accept(Visitor aVisitor) {
277 aVisitor.visitProgram(this);
283 * @see java.lang.Object#toString()
286 public String toString() {
287 return _interval + " - " + _name + " (" + _channel + "/" + _keywords
289 + (INDENT + _description).replaceAll("\n", "\n" + INDENT);
295 * @see java.lang.Object#equals(java.lang.Object)
298 public boolean equals(Object aObject) {
299 if (!(aObject instanceof Program)) {
302 Program program = (Program) aObject;
303 return getName().equals(program.getName())
304 && _programInfo.equals(program._programInfo);
310 * @see java.lang.Object#hashCode()
313 public int hashCode() {
314 return getName().hashCode();
318 * Converts program information to XML.
320 * @return XML representation of program information.
322 public Element asXml() {
323 DocumentFactory factory = DocumentFactory.getInstance();
324 Element program = factory.createElement(ELEM_PROGRAM);
325 program.addElement(ELEM_NAME).setText(getName());
326 program.addElement(ELEM_DESCRIPTION).setText(getDescription());
327 program.addElement(ELEM_KEYWORDS).setText(getKeywords());
328 program.addElement(ELEM_CHANNEL).setText(getChannel());
329 Element interval = program.addElement(ELEM_INTERVAL);
330 interval.addElement(ELEM_BEGIN_TIME).setText(
331 getInterval().getBegin().toString());
332 interval.addElement(ELEM_END_TIME).setText(
333 getInterval().getEnd().toString());