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 public class Program {
36 * Lexicographical comparison of programs based on (time, title, channel).
39 public static class TimeSorter implements Comparator<Program> {
42 * Lexicographical comparison based on start time, program name, and
49 * @return See {@link Comparator#compare(T, T)}
51 public int compare(Program aProgram1, Program aProgram2) {
52 int value = aProgram1.getInterval().getBegin().compareTo(
53 aProgram2.getInterval().getBegin());
57 value = aProgram1.getName().compareTo(aProgram2.getName());
61 return aProgram1.getChannel().compareTo(aProgram2.getChannel());
65 private static final Log LOG = LogFactory.getLog(Program.class);
68 * Name of the record action on the program details page.
70 private static final String RECORD_ACTION = "record";
72 private static final String RESULT_ELEM = "result";
75 * Result of recording a program.
78 public enum RecordingResult {
80 * Successfully recorded.
82 OK("Successfully recorded programs"),
85 * Already recorded program.
87 DUPLICATE("Already recorded programs"),
90 * Recording conflict with another program.
92 CONFLICT("Programs in conflict with another recorded program"),
95 * Program occurred in the past.
97 OLDSHOW("Programs that occurred in the past"),
100 * Program could not be recorded for technical reasons.
102 ERROR("Programs that could not be recorded for technical reasons");
104 private String _description;
106 private RecordingResult(String aDescription) {
107 _description = aDescription;
111 * Gets the description.
112 * @return Description.
114 public String getDescription() {
120 * Indent string to use for pretty printing.
122 private static final String INDENT = " ";
125 * Channel the program is on.
127 private String _channel;
132 private String _name;
135 * Program description.
137 private String _description;
140 * Keywords or classification of the program.
142 private String _keywords;
145 * Time interval for the program (from/to).
147 private TimeInterval _interval;
150 * Action to execute to obtain program information and/or record the
153 private Action _programInfo;
156 * Constructs the program.
162 * @param aDescription
165 * Keywords/classification.
168 * @param aProgramInfo
169 * Action to execute for detailed program information or for
170 * recording the page.
172 public Program(String aChannel, String aName, String aDescription,
173 String aKeywords, TimeInterval aInterval, Action aProgramInfo) {
176 _description = aDescription;
177 _keywords = aKeywords;
178 _interval = aInterval;
179 _programInfo = aProgramInfo;
187 public String getChannel() {
192 * Gets the program name.
196 public String getName() {
201 * Gets the description.
203 * @return Description.
205 public String getDescription() {
210 * Gets the keywords/classification.
212 * @return Keywords/classification
214 public String getKeywords() {
219 * Gets the time interval.
221 * @return Time interval.
223 public TimeInterval getInterval() {
228 * Checks if recording is possible.
230 * @return True iff recording is possible.
232 public boolean isRecordingPossible() {
234 Action record = _programInfo.execute().getAction(RECORD_ACTION);
235 if (record == null) {
239 } catch (PageException e) {
247 * @return Status describing the result of recording.
249 public RecordingResult record() {
250 LOG.info("Recording " + this);
251 if (SystemProperties.isRecordDisabled()) {
252 return RecordingResult.OK;
255 Action record = _programInfo.execute().getAction(RECORD_ACTION);
256 if (record == null) {
257 LOG.info(" result: " + RecordingResult.OLDSHOW);
258 return RecordingResult.OLDSHOW;
260 Page result = record.execute();
261 RecordingResult recordingResult = RecordingResult.valueOf(result
262 .getContent().getText());
263 LOG.info(" result: " + recordingResult);
264 return recordingResult;
265 } catch (PageException e) {
266 LOG.warn("Technical problem recording program: '" + this + "'", e);
267 LOG.info(" result: " + RecordingResult.ERROR);
268 return RecordingResult.ERROR;
273 * Accepts the visitor.
278 public void accept(Visitor aVisitor) {
279 aVisitor.visitProgram(this);
285 * @see java.lang.Object#toString()
288 public String toString() {
289 return _interval + " - " + _name + " (" + _channel + "/" + _keywords
291 + (INDENT + _description).replaceAll("\n", "\n" + INDENT);
297 * @see java.lang.Object#equals(java.lang.Object)
300 public boolean equals(Object aObject) {
301 if (!(aObject instanceof Program)) {
304 Program program = (Program) aObject;
305 return getName().equals(program.getName())
306 && _programInfo.equals(program._programInfo);
312 * @see java.lang.Object#hashCode()
315 public int hashCode() {
316 return getName().hashCode();
320 * Converts program information to XML.
322 * @return XML representation of program information.
324 public Element asXml() {
325 DocumentFactory factory = DocumentFactory.getInstance();
326 Element program = factory.createElement("program");
327 program.addElement("name").setText(getName());
328 program.addElement("description").setText(getDescription());
329 program.addElement("keywords").setText(getKeywords());
330 program.addElement("channel").setText(getChannel());
331 Element interval = program.addElement("interval");
332 interval.addElement("begin").setText(
333 getInterval().getBegin().toString());
334 interval.addElement("end").setText(getInterval().getEnd().toString());