68a4c13dc78da97717f66b33f13241c3bd09b1cb
[utils] / crawler / kiss / src / main / java / 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      * @param aReport Report to use. 
55      */
56     public ProgramActionExecutor(Report aReport) {
57         _showsToRecord = new TreeMap<Integer, Set<Program>>();
58         _report = aReport;
59     }
60
61     /**
62      * Called by an action to indicate the desire to record a program.
63      * 
64      * @param aPriority
65      *            Priority of the program. Used to resolve conflicts.
66      * @param aProgram
67      *            Program to record.
68      */
69     public void recordProgram(int aPriority, Program aProgram) {
70         LOG.info("priority = " + aPriority + ", program: " + aProgram);
71         // Putting -priority into the set makes sure that iteration order
72         // over the priorities will go from higher priority to lower priority.
73         Set<Program> programs = _showsToRecord.get(-aPriority);
74         if (programs == null) {
75             programs = new TreeSet<Program>(new Program.TimeComparator());
76             _showsToRecord.put(-aPriority, programs);
77         }
78         programs.add(aProgram);
79     }
80
81     /**
82      * Called by an action to indicate that a program is interesting.
83      * 
84      * @param aCategory
85      *            Category of the program.
86      * @param aProgram
87      *            Program.
88      */
89     public void interestingProgram(String aCategory, Program aProgram) {
90         LOG.info("category = '" + aCategory + "', program: " + aProgram);
91         _report.interestingProgram(aCategory, aProgram);
92     }
93
94     /**
95      * Makes sure that the actions are performed.
96      */
97     public void commit() {
98         Set<TimeInterval> previouslyRecorded = new HashSet<TimeInterval>();
99         for (Integer priority : _showsToRecord.keySet()) {
100             for (Program program : _showsToRecord.get(priority)) {
101                 TimeInterval interval = program.getInterval();
102                 if (recordingConflictExists(previouslyRecorded, interval)) {
103                     _report.setRecordingResult(RecordingResult.CONFLICT, program);
104                 } else {
105                     RecordingResult result = program.record();
106                     _report.setRecordingResult(result, program);
107                     previouslyRecorded.add(interval);
108                 }
109             }
110         }
111     }
112
113     /**
114      * Checks an interval for overlap with a previously recorded program.
115      * 
116      * @param aPreviouslyRecorded
117      *            Previously recorded programs.
118      * @param aInterval
119      *            Interval.
120      * @return True iff there is a recording conflict.
121      */
122     private boolean recordingConflictExists(
123             Set<TimeInterval> aPreviouslyRecorded, TimeInterval aInterval) {
124         for (TimeInterval recordedInterval : aPreviouslyRecorded) {
125             if (aInterval.overlap(recordedInterval)) {
126                 return true;
127             }
128         }
129         return false;
130     }
131 }