(no commit message)
[utils] / crawler / kiss / src / org / wamblee / crawler / kiss / main / ProgramActionExecutor.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.main;
18
19 import java.util.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.TreeMap;
23 import java.util.TreeSet;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.wamblee.crawler.kiss.guide.Program;
28 import org.wamblee.crawler.kiss.guide.TimeInterval;
29 import org.wamblee.crawler.kiss.guide.Program.RecordingResult;
30
31 /**
32  * Provides execution of actions for programs. Actions use this class to tell
33  * the executor what to do. The executor then decides on exactly what to do and
34  * in what order and makes decisions in case of conflicts.
35  */
36 public class ProgramActionExecutor {
37
38     private static final Log LOG = LogFactory
39             .getLog(ProgramActionExecutor.class);
40
41     /**
42      * Map of priority to set of programs.
43      */
44     private Map<Integer, Set<Program>> _showsToRecord;
45     
46     /**
47      * Report to use. 
48      */
49     private Report _report; 
50
51     /**
52      * Constructs the program action executor.
53      * 
54      */
55     public ProgramActionExecutor(Report aReport) {
56         _showsToRecord = new TreeMap<Integer, Set<Program>>();
57         _report = aReport;
58     }
59
60     /**
61      * Called by an action to indicate the desire to record a program.
62      * 
63      * @param aPriority
64      *            Priority of the program. Used to resolve conflicts.
65      * @param aProgram
66      *            Program to record.
67      */
68     public void recordProgram(int aPriority, Program aProgram) {
69         LOG.info("priority = " + aPriority + ", program: " + aProgram);
70         // Putting -priority into the set makes sure that iteration order
71         // over the priorities will go from higher priority to lower priority.
72         Set<Program> programs = _showsToRecord.get(-aPriority);
73         if (programs == null) {
74             programs = new TreeSet<Program>(new Program.TimeComparator());
75             _showsToRecord.put(-aPriority, programs);
76         }
77         programs.add(aProgram);
78     }
79
80     /**
81      * Called by an action to indicate that a program is interesting.
82      * 
83      * @param aCategory
84      *            Category of the program.
85      * @param aProgram
86      *            Program.
87      */
88     public void interestingProgram(String aCategory, Program aProgram) {
89         LOG.info("category = '" + aCategory + "', program: " + aProgram);
90         _report.interestingProgram(aCategory, aProgram);
91     }
92
93     /**
94      * Makes sure that the actions are performed.
95      */
96     public void commit() {
97         Set<TimeInterval> previouslyRecorded = new HashSet<TimeInterval>();
98         for (Integer priority : _showsToRecord.keySet()) {
99             for (Program program : _showsToRecord.get(priority)) {
100                 TimeInterval interval = program.getInterval();
101                 if (recordingConflictExists(previouslyRecorded, interval)) {
102                     _report.setRecordingResult(RecordingResult.CONFLICT, program);
103                 } else {
104                     RecordingResult result = program.record();
105                     _report.setRecordingResult(result, program);
106                     previouslyRecorded.add(interval);
107                 }
108             }
109         }
110     }
111
112     /**
113      * Checks an interval for overlap with a previously recorded program.
114      * 
115      * @param aPreviouslyRecorded
116      *            Previously recorded programs.
117      * @param aInterval
118      *            Interval.
119      * @return True iff there is a recording conflict.
120      */
121     private boolean recordingConflictExists(
122             Set<TimeInterval> aPreviouslyRecorded, TimeInterval aInterval) {
123         for (TimeInterval recordedInterval : aPreviouslyRecorded) {
124             if (aInterval.overlap(recordedInterval)) {
125                 return true;
126             }
127         }
128         return false;
129     }
130 }