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 {
35 private static final String ELEM_PROGRAM = "program";
37 private static final String ELEM_NAME = "name";
39 private static final String ELEM_KEYWORDS = "keywords";
41 private static final String ELEM_DESCRIPTION = "description";
43 private static final String ELEM_CHANNEL = "channel";
45 private static final String ELEM_INTERVAL = "interval";
47 private static final String ELEM_END_TIME = "end";
49 private static final String ELEM_BEGIN_TIME = "begin";
52 * Lexicographical comparison of programs based on (time, title, channel).
55 public static class TimeSorter implements Comparator<Program> {
58 * Lexicographical comparison based on start time, program name, and
65 * @return See {@link Comparator#compare(T, T)}
67 public int compare(Program aProgram1, Program aProgram2) {
68 int value = aProgram1.getInterval().getBegin().compareTo(
69 aProgram2.getInterval().getBegin());
73 value = aProgram1.getName().compareTo(aProgram2.getName());
77 return aProgram1.getChannel().compareTo(aProgram2.getChannel());
81 private static final Log LOG = LogFactory.getLog(Program.class);
84 * Name of the record action on the program details page.
86 private static final String RECORD_ACTION = "record";
89 * Result of recording a program.
92 public enum RecordingResult {
94 * Successfully recorded.
99 * Already recorded program.
104 * Recording conflict with another program.
109 * Program occurred in the past.
114 * Program could not be recorded for technical reasons.
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(ELEM_PROGRAM);
327 program.addElement(ELEM_NAME).setText(getName());
328 program.addElement(ELEM_DESCRIPTION).setText(getDescription());
329 program.addElement(ELEM_KEYWORDS).setText(getKeywords());
330 program.addElement(ELEM_CHANNEL).setText(getChannel());
331 Element interval = program.addElement(ELEM_INTERVAL);
332 interval.addElement(ELEM_BEGIN_TIME).setText(
333 getInterval().getBegin().toString());
334 interval.addElement(ELEM_END_TIME).setText(
335 getInterval().getEnd().toString());