28cbec5b406f22b6fee880bfba685047e4557f27
[utils] / crawler / kiss / src / org / wamblee / crawler / kiss / guide / Program.java
1 /*
2  * Copyright 2005 the original author or authors.
3  * 
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
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
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.
15  */
16
17 package org.wamblee.crawler.kiss.guide;
18
19 import java.util.Comparator;
20
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;
29
30 /**
31  * Represents a television program.
32  */
33 public class Program {
34
35     /**
36      * Lexicographical comparison of programs based on (time, title, channel).
37      * 
38      */
39     public static class TimeSorter implements Comparator<Program> {
40
41         /**
42          * Lexicographical comparison based on start time, program name, and
43          * channel.
44          * 
45          * @param aProgram1
46          *            First program.
47          * @param aProgram2
48          *            Second program.
49          * @return See {@link Comparator#compare(T, T)}
50          */
51         public int compare(Program aProgram1, Program aProgram2) {
52             int value = aProgram1.getInterval().getBegin().compareTo(
53                     aProgram2.getInterval().getBegin());
54             if (value != 0) {
55                 return value;
56             }
57             value = aProgram1.getName().compareTo(aProgram2.getName());
58             if (value != 0) {
59                 return value;
60             }
61             return aProgram1.getChannel().compareTo(aProgram2.getChannel());
62         }
63     }
64
65     private static final Log LOG = LogFactory.getLog(Program.class);
66
67     /**
68      * Name of the record action on the program details page.
69      */
70     private static final String RECORD_ACTION = "record";
71
72     /**
73      * Result of recording a program.
74      * 
75      */
76     public enum RecordingResult {
77         /**
78          * Successfully recorded.
79          */
80         OK("Successfully recorded programs"),
81
82         /**
83          * Already recorded program.
84          */
85         DUPLICATE("Already recorded programs"),
86
87         /**
88          * Recording conflict with another program.
89          */
90         CONFLICT("Programs in conflict with another recorded program"),
91
92         /**
93          * Program occurred in the past.
94          */
95         OLDSHOW("Programs that occurred in the past"),
96
97         /**
98          * Program could not be recorded for technical reasons.
99          */
100         ERROR("Programs that could not be recorded for technical reasons");
101
102         private String _description;
103
104         private RecordingResult(String aDescription) {
105             _description = aDescription;
106         }
107
108         /**
109          * Gets the description. 
110          * @return Description. 
111          */
112         public String getDescription() {
113             return _description;
114         }
115     };
116
117     /**
118      * Indent string to use for pretty printing.
119      */
120     private static final String INDENT = "       ";
121
122     /**
123      * Channel the program is on.
124      */
125     private String _channel;
126
127     /**
128      * Program name.
129      */
130     private String _name;
131
132     /**
133      * Program description.
134      */
135     private String _description;
136
137     /**
138      * Keywords or classification of the program.
139      */
140     private String _keywords;
141
142     /**
143      * Time interval for the program (from/to).
144      */
145     private TimeInterval _interval;
146
147     /**
148      * Action to execute to obtain program information and/or record the
149      * program.
150      */
151     private Action _programInfo;
152
153     /**
154      * Constructs the program.
155      * 
156      * @param aChannel
157      *            Channel name.
158      * @param aName
159      *            Program name.
160      * @param aDescription
161      *            Description.
162      * @param aKeywords
163      *            Keywords/classification.
164      * @param aInterval
165      *            Time interval.
166      * @param aProgramInfo
167      *            Action to execute for detailed program information or for
168      *            recording the page.
169      */
170     public Program(String aChannel, String aName, String aDescription,
171             String aKeywords, TimeInterval aInterval, Action aProgramInfo) {
172         _channel = aChannel;
173         _name = aName;
174         _description = aDescription;
175         _keywords = aKeywords;
176         _interval = aInterval;
177         _programInfo = aProgramInfo;
178     }
179
180     /**
181      * Gets the channel.
182      * 
183      * @return Channel.
184      */
185     public String getChannel() {
186         return _channel;
187     }
188
189     /**
190      * Gets the program name.
191      * 
192      * @return Name.
193      */
194     public String getName() {
195         return _name;
196     }
197
198     /**
199      * Gets the description.
200      * 
201      * @return Description.
202      */
203     public String getDescription() {
204         return _description;
205     }
206
207     /**
208      * Gets the keywords/classification.
209      * 
210      * @return Keywords/classification
211      */
212     public String getKeywords() {
213         return _keywords;
214     }
215
216     /**
217      * Gets the time interval.
218      * 
219      * @return Time interval.
220      */
221     public TimeInterval getInterval() {
222         return _interval;
223     }
224
225     /**
226      * Checks if recording is possible.
227      * 
228      * @return True iff recording is possible.
229      */
230     public boolean isRecordingPossible() {
231         try {
232             Action record = _programInfo.execute().getAction(RECORD_ACTION);
233             if (record == null) {
234                 return false;
235             }
236             return true;
237         } catch (PageException e) {
238             return false;
239         }
240     }
241
242     /**
243      * Records the show.
244      * 
245      * @return Status describing the result of recording.
246      */
247     public RecordingResult record() {
248         LOG.info("Recording " + this);
249         if (SystemProperties.isRecordDisabled()) {
250             return RecordingResult.OK;
251         }
252         try {
253             Action record = _programInfo.execute().getAction(RECORD_ACTION);
254             if (record == null) {
255                 LOG.info("  result: " + RecordingResult.OLDSHOW);
256                 return RecordingResult.OLDSHOW;
257             }
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;
267         }
268     }
269
270     /**
271      * Accepts the visitor.
272      * 
273      * @param aVisitor
274      *            Visitor.
275      */
276     public void accept(Visitor aVisitor) {
277         aVisitor.visitProgram(this);
278     }
279
280     /*
281      * (non-Javadoc)
282      * 
283      * @see java.lang.Object#toString()
284      */
285     @Override
286     public String toString() {
287         return _interval + " - " + _name + " (" + _channel + "/" + _keywords
288                 + ")" + "\n"
289                 + (INDENT + _description).replaceAll("\n", "\n" + INDENT);
290     }
291
292     /*
293      * (non-Javadoc)
294      * 
295      * @see java.lang.Object#equals(java.lang.Object)
296      */
297     @Override
298     public boolean equals(Object aObject) {
299         if (!(aObject instanceof Program)) {
300             return false;
301         }
302         Program program = (Program) aObject;
303         return getName().equals(program.getName())
304                 && _programInfo.equals(program._programInfo);
305     }
306
307     /*
308      * (non-Javadoc)
309      * 
310      * @see java.lang.Object#hashCode()
311      */
312     @Override
313     public int hashCode() {
314         return getName().hashCode();
315     }
316
317     /**
318      * Converts program information to XML.
319      * 
320      * @return XML representation of program information.
321      */
322     public Element asXml() {
323         DocumentFactory factory = DocumentFactory.getInstance();
324         Element program = factory.createElement("program");
325         program.addElement("name").setText(getName());
326         program.addElement("description").setText(getDescription());
327         program.addElement("keywords").setText(getKeywords());
328         program.addElement("channel").setText(getChannel());
329         Element interval = program.addElement("interval");
330         interval.addElement("begin").setText(
331                 getInterval().getBegin().toString());
332         interval.addElement("end").setText(getInterval().getEnd().toString());
333         return program;
334     }
335 }