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