X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=crawler%2Fkiss%2Fsrc%2Forg%2Fwamblee%2Fcrawler%2Fkiss%2Fmain%2FProgramActionExecutor.java;h=51aef60f1a2148f58300f1c085b642e4028a322f;hb=abd7639aeda13c2b87b724f85278deccbe0acfa4;hp=3ef511cffe4ce9c8b36c445d163e12c57dd7886e;hpb=d85bc24e068a68a54786fae5dc71573607b3b0cb;p=utils diff --git a/crawler/kiss/src/org/wamblee/crawler/kiss/main/ProgramActionExecutor.java b/crawler/kiss/src/org/wamblee/crawler/kiss/main/ProgramActionExecutor.java index 3ef511cf..51aef60f 100644 --- a/crawler/kiss/src/org/wamblee/crawler/kiss/main/ProgramActionExecutor.java +++ b/crawler/kiss/src/org/wamblee/crawler/kiss/main/ProgramActionExecutor.java @@ -12,166 +12,185 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.crawler.kiss.main; import java.util.EnumMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.dom4j.DocumentFactory; import org.dom4j.Element; import org.wamblee.crawler.kiss.guide.Program; +import org.wamblee.crawler.kiss.guide.TimeInterval; import org.wamblee.crawler.kiss.guide.Program.RecordingResult; /** - * Provides execution of actions for programs. Actions use - * this class to tell the executor what to do. The executor then decide - * on exactly what to do and in what order and makes decisions in case - * of conflicts. + * Provides execution of actions for programs. Actions use this class to tell + * the executor what to do. The executor then decides on exactly what to do and + * in what order and makes decisions in case of conflicts. */ public class ProgramActionExecutor { - + + private static final Log LOG = LogFactory + .getLog(ProgramActionExecutor.class); + /** - * A map of category name to a set of program. Useful for displaying the output of - * possibly interesting programs on a per category basis. + * A map of category name to a set of program. Useful for displaying the + * output of possibly interesting programs on a per category basis. */ private Map> _interestingShows; - + /** - * Set of programs to record. + * Map of priority to set of programs. */ - private Set _showsToRecord; - + private Map> _showsToRecord; + /** - * Map or recording result to a set of programs. + * Map or recording result to a set of programs. */ private EnumMap> _recordings; - + /** - * Constructs the program action executor. - * + * Constructs the program action executor. + * */ - public ProgramActionExecutor() { - _interestingShows = new TreeMap>(); - _showsToRecord = new TreeSet(new Program.TimeSorter()); + public ProgramActionExecutor() { + _interestingShows = new TreeMap>(); + _showsToRecord = new TreeMap>(); _recordings = new EnumMap>( RecordingResult.class); for (RecordingResult result : RecordingResult.values()) { - _recordings.put(result, new TreeSet(new Program.TimeSorter())); + _recordings.put(result, new TreeSet( + new Program.TimeSorter())); } } - + /** * Called by an action to indicate the desire to record a program. - * @param aPriority Priority of the program. Used to resolve conflicts. - * @param aProgram Program to record. + * + * @param aPriority + * Priority of the program. Used to resolve conflicts. + * @param aProgram + * Program to record. */ - public void recordProgram(int aPriority, Program aProgram) { - _showsToRecord.add(aProgram); + public void recordProgram(int aPriority, Program aProgram) { + LOG.info("priority = " + aPriority + ", program: " + aProgram); + // Putting -priority into the set makes sure that iteration order + // over the priorities will go from higher priority to lower priority. + Set programs = _showsToRecord.get(-aPriority); + if (programs == null) { + programs = new TreeSet(new Program.TimeSorter()); + _showsToRecord.put(-aPriority, programs); + } + programs.add(aProgram); } - + /** - * Called by an action to indicate that a program is interesting. - * @param aCategory Category of the program. - * @param aProgram Program. + * Called by an action to indicate that a program is interesting. + * + * @param aCategory + * Category of the program. + * @param aProgram + * Program. */ - public void interestingProgram(String aCategory, Program aProgram) { - Set programs = _interestingShows.get(aCategory); - if ( programs == null ) { + public void interestingProgram(String aCategory, Program aProgram) { + LOG.info("category = '" + aCategory + "', program: " + aProgram); + Set programs = _interestingShows.get(aCategory); + if (programs == null) { programs = new TreeSet(new Program.TimeSorter()); _interestingShows.put(aCategory, programs); } programs.add(aProgram); } - + /** * Makes sure that the actions are performed. - * */ - public void commit() { - for (Program program: _showsToRecord) { - RecordingResult result = program.record(); - _recordings.get(result).add(program); + public void commit() { + Set previouslyRecorded = new HashSet(); + for (Integer priority : _showsToRecord.keySet()) { + for (Program program : _showsToRecord.get(priority)) { + TimeInterval interval = program.getInterval(); + if ( recordingConflictExists(previouslyRecorded, interval)) { + _recordings.get(RecordingResult.CONFLICT).add(program); + } else { + RecordingResult result = program.record(); + _recordings.get(result).add(program); + previouslyRecorded.add(interval); + } + } } } /** - * Gets the report describing what was done. - * @return Report. + * Checks an interval for overlap with a previously recorded program. + * @param aPreviouslyRecorded Previously recorded programs. + * @param interval Interval. + * @return True iff there is a recording conflict. */ - public String getReport() { - StringBuffer msg = new StringBuffer("Summary of KiSS crawler: \n\n\n"); - - boolean printed = false; - - for (RecordingResult result : RecordingResult.values()) { - if (_recordings.get(result).size() > 0) { - msg.append(result.getDescription() + "\n\n"); - for (Program program : _recordings.get(result)) { - msg.append(program + "\n\n"); - printed = true; - } + private boolean recordingConflictExists(Set aPreviouslyRecorded, TimeInterval interval) { + for (TimeInterval recordedInterval: aPreviouslyRecorded ) { + if ( interval.overlap(recordedInterval)) { + return true; } } - - if ( _interestingShows.size() > 0 ) { - msg.append("Possibly interesting shows:\n\n"); - for (String category: _interestingShows.keySet()) { - if ( category.length() > 0 ) { - msg.append("Category: " + category + "\n\n"); - } - for (Program program: _interestingShows.get(category)) { - msg.append(program + "\n\n"); - printed = true; - } - } - - } - if (!printed) { - msg.append("No suitable programs found"); - } - - return msg.toString(); + return false; } - + /** - * Get report as XML. - * @return XML report + * Get report as XML. + * + * @return XML report */ - public Element getXmlReport() { - DocumentFactory factory = DocumentFactory.getInstance(); - Element report = factory.createElement("report"); + public Element getReport() { + DocumentFactory factory = DocumentFactory.getInstance(); + Element report = factory.createElement("report"); + Set reportedPrograms = new HashSet(); + for (RecordingResult result : RecordingResult.values()) { if (_recordings.get(result).size() > 0) { - Element recordingResult = report.addElement("recorded").addAttribute("result", result.toString()); - + Element recordingResult = report.addElement("recorded") + .addAttribute("result", result.toString()); + for (Program program : _recordings.get(result)) { - recordingResult.add(program.asXml()); + recordingResult.add(program.asXml()); + reportedPrograms.add(program); } } } - - - if ( _interestingShows.size() > 0 ) { + + if (_interestingShows.size() > 0) { Element interesting = report.addElement("interesting"); - for (String category: _interestingShows.keySet()) { - Element categoryElem = interesting; - if ( category.length() > 0 ) { + for (String category : _interestingShows.keySet()) { + Element categoryElem = interesting; + if (category.length() > 0) { categoryElem = interesting.addElement("category"); categoryElem.addAttribute("name", category); } - for (Program program: _interestingShows.get(category)) { - categoryElem.add(program.asXml()); + for (Program program : _interestingShows.get(category)) { + if ( !reportedPrograms.contains(program)) { + categoryElem.add(program.asXml()); + } else { + LOG.info("Category '" + category + "', program " + program + " already reported"); + } + } + if ( categoryElem.elements().size() == 0 ) { + // Remove empty category element. + LOG.info("Removing element for category '" + category + "'"); + interesting.remove(categoryElem); } } - + } - - return report; + + return report; } }