restructuring into packages.
[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         /* (non-Javadoc)
42          * @see java.util.Comparator#compare(T, T)
43          */
44         public int compare(Program o1, Program o2) { 
45             int value = o1.getInterval().getBegin().compareTo(o2.getInterval().getBegin());
46             if ( value != 0 ) { 
47                 return value; 
48             }
49             value = o1.getName().compareTo(o2.getName()); 
50             if (value != 0 ) { 
51                 return value; 
52             }
53             return o1.getChannel().compareTo(o2.getChannel());
54         }
55     }
56     
57     private static final Log LOG = LogFactory.getLog(Program.class);
58
59     /**
60      * Name of the record action on the program details page.
61      */
62     private static final String RECORD_ACTION = "record";
63
64     private static final String RESULT_ELEM = "result";
65
66     public enum RecordingResult {
67         OK("Successfully recorded programs"), DUPLICATE(
68                 "Already recorded programs"), CONFLICT(
69                 "Programs in conflict with another recorded program"), OLDSHOW(
70                 "Programs that occurred in the past"), ERROR(
71                 "Programs that could not be recorded for technical reasons");
72
73         private String _description;
74
75         private RecordingResult(String aDescription) {
76             _description = aDescription;
77         }
78
79         public String getDescription() {
80             return _description;
81         }
82     };
83
84     /**
85      * Indent string to use for pretty printing.
86      */
87     private static final String INDENT = "       ";
88
89     /**
90      * Channel the program is on.
91      */
92     private String _channel;
93
94     /**
95      * Program name.
96      */
97     private String _name;
98
99     /**
100      * Program description.
101      */
102     private String _description;
103
104     /**
105      * Keywords or classification of the program.
106      */
107     private String _keywords;
108
109     /**
110      * Time interval for the program (from/to).
111      */
112     private TimeInterval _interval;
113
114     /**
115      * Action to execute to obtain program information and/or record the
116      * program.
117      */
118     private Action _programInfo;
119
120     /**
121      * Constructs the program.
122      * 
123      * @param aChannel
124      *            Channel name.
125      * @param aName
126      *            Program name.
127      * @param aDescription
128      *            Description.
129      * @param aKeywords
130      *            Keywords/classification.
131      * @param aInterval
132      *            Time interval.
133      * @param aProgramInfo
134      *            Action to execute for detailed program information or for
135      *            recording the page.
136      */
137     public Program(String aChannel, String aName, String aDescription,
138             String aKeywords, TimeInterval aInterval, Action aProgramInfo) {
139         _channel = aChannel;
140         _name = aName;
141         _description = aDescription;
142         _keywords = aKeywords;
143         _interval = aInterval;
144         _programInfo = aProgramInfo;
145     }
146
147     /**
148      * Gets the channel.
149      * 
150      * @return Channel.
151      */
152     public String getChannel() {
153         return _channel;
154     }
155
156     /**
157      * Gets the program name.
158      * 
159      * @return Name.
160      */
161     public String getName() {
162         return _name;
163     }
164
165     /**
166      * Gets the description.
167      * 
168      * @return Description.
169      */
170     public String getDescription() {
171         return _description;
172     }
173
174     /**
175      * Gets the keywords/classification.
176      * 
177      * @return Keywords/classification
178      */
179     public String getKeywords() {
180         return _keywords;
181     }
182
183     /**
184      * Gets the time interval.
185      * 
186      * @return Time interval.
187      */
188     public TimeInterval getInterval() {
189         return _interval;
190     }
191     
192     /**
193      * Checks if recording is possible. 
194      * @return True iff recording is possible. 
195      */
196     public boolean isRecordingPossible() { 
197         try {
198             Action record = _programInfo.execute().getAction(RECORD_ACTION);
199             if (record == null) {
200                 return false; 
201             }
202             return true; 
203         } catch (PageException e) {
204             return false; 
205         }
206     }
207
208     /**
209      * Records the show.
210      * 
211      * @return Status describing the result of recording.
212      */
213     public RecordingResult record() {
214         LOG.info("Recording " + this);
215         if ( SystemProperties.isRecordDisabled() ) { 
216             return RecordingResult.OK;
217         }
218         try {
219             Action record = _programInfo.execute().getAction(RECORD_ACTION);
220             if (record == null) {
221                 LOG.info("  result: " + RecordingResult.OLDSHOW);
222                 return RecordingResult.OLDSHOW;
223             }
224             Page result = record.execute();
225             RecordingResult recordingResult = RecordingResult.valueOf(result.getContent().getText());
226             LOG.info("  result: " + recordingResult);
227             return recordingResult;
228         } catch (PageException e) {
229             LOG.warn("Technical problem recording program: '" + this + "'", e);
230             LOG.info("  result: " + RecordingResult.ERROR);
231             return RecordingResult.ERROR;
232         }
233     }
234
235     /**
236      * Accepts the visitor.
237      * 
238      * @param aVisitor
239      *            Visitor.
240      */
241     public void accept(Visitor aVisitor) {
242         aVisitor.visitProgram(this);
243     }
244
245     /*
246      * (non-Javadoc)
247      * 
248      * @see java.lang.Object#toString()
249      */
250     @Override
251     public String toString() {
252         return _interval + " - " + _name + " (" + _channel + "/" + _keywords
253                 + ")" + "\n"
254                 + (INDENT + _description).replaceAll("\n", "\n" + INDENT);
255     }
256     
257     /* (non-Javadoc)
258      * @see java.lang.Object#equals(java.lang.Object)
259      */
260     @Override
261     public boolean equals(Object obj) {
262         if ( !(obj instanceof Program)) { 
263             return false; 
264         }
265         Program program = (Program)obj; 
266         return getName().equals(program.getName()) && 
267                _programInfo.equals(program._programInfo);
268     }
269     
270     /**
271      * Converts program information to XML. 
272      * @return XML representation of program information.  
273      */
274     public Element asXml() { 
275         DocumentFactory factory = DocumentFactory.getInstance();
276         Element program = factory.createElement("program"); 
277         program.addElement("name").setText(getName());
278         program.addElement("description").setText(getDescription());
279         program.addElement("keywords").setText(getKeywords());
280         program.addElement("channel").setText(getChannel());
281         Element interval = program.addElement("interval");
282         interval.addElement("begin").setText(getInterval().getBegin().toString());
283         interval.addElement("end").setText(getInterval().getEnd().toString());
284         return program; 
285     }
286 }