Browse Source

Adds a Timer Manager that allows cancelling of timers

Fixes issue CLIENT-101

Change-Id: I47c6b053fe451cfd6f734959195926bad7fc6376
Reviewed-on: http://gerrit.dmdirc.com/1610
Automatic-Compile: DMDirc Local Commits <dmdirc@googlemail.com>
Reviewed-by: Chris Smith <chris@dmdirc.com>
tags/0.6.5
Simon Mott 13 years ago
parent
commit
2fc0c13f5b

+ 30
- 16
src/com/dmdirc/addons/time/TimePlugin.java View File

1
 /*
1
 /*
2
- * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes,
3
+ * Simon Mott
3
  *
4
  *
4
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5
  * of this software and associated documentation files (the "Software"), to deal
6
  * of this software and associated documentation files (the "Software"), to deal
35
  * @author chris
36
  * @author chris
36
  */
37
  */
37
 public final class TimePlugin  extends Plugin {
38
 public final class TimePlugin  extends Plugin {
38
-    
39
+
39
     /** Have we registered our types already? */
40
     /** Have we registered our types already? */
40
     private static boolean registered;
41
     private static boolean registered;
41
-    
42
+
42
     /** The timer to use for scheduling. */
43
     /** The timer to use for scheduling. */
43
     private Timer timer;
44
     private Timer timer;
44
-    
45
+
45
     /** The TimerCommand we've registered. */
46
     /** The TimerCommand we've registered. */
46
     private TimerCommand command;
47
     private TimerCommand command;
47
-    
48
+
49
+    /** The Manager to use for managing timers. */
50
+    private TimerManager manager;
51
+
48
     /** Creates a new instance of TimePlugin. */
52
     /** Creates a new instance of TimePlugin. */
49
     public TimePlugin() {
53
     public TimePlugin() {
50
         super();
54
         super();
51
     }
55
     }
52
-    
56
+
53
     /** {@inheritDoc} */
57
     /** {@inheritDoc} */
54
     @Override
58
     @Override
55
     public void onLoad() {
59
     public void onLoad() {
59
         }
63
         }
60
 
64
 
61
         final int offset = 60 - Calendar.getInstance().get(Calendar.SECOND);
65
         final int offset = 60 - Calendar.getInstance().get(Calendar.SECOND);
62
-        
66
+
63
         timer = new Timer("Time plugin timer");
67
         timer = new Timer("Time plugin timer");
64
-        
68
+
65
         timer.schedule(new TimerTask() {
69
         timer.schedule(new TimerTask() {
66
             /** {@inheritDoc} */
70
             /** {@inheritDoc} */
67
             @Override
71
             @Override
69
                 runTimer();
73
                 runTimer();
70
             }
74
             }
71
         }, 1000 * offset, 1000 * 60);
75
         }, 1000 * offset, 1000 * 60);
72
-        
73
-        command = new TimerCommand();
76
+
77
+        manager = new TimerManager();
78
+        command = new TimerCommand(manager);
74
         CommandManager.registerCommand(command);
79
         CommandManager.registerCommand(command);
75
     }
80
     }
76
-    
81
+
77
     /** Handles a timer event that occurs every minute. */
82
     /** Handles a timer event that occurs every minute. */
78
     public void runTimer() {
83
     public void runTimer() {
79
         final Calendar cal = Calendar.getInstance();
84
         final Calendar cal = Calendar.getInstance();
80
-        
85
+
81
         ActionManager.processEvent(TimeActionType.TIME_MINUTE, null, cal);
86
         ActionManager.processEvent(TimeActionType.TIME_MINUTE, null, cal);
82
-        
87
+
83
         if (cal.get(Calendar.MINUTE) == 0) {
88
         if (cal.get(Calendar.MINUTE) == 0) {
84
             ActionManager.processEvent(TimeActionType.TIME_HOUR, null, cal);
89
             ActionManager.processEvent(TimeActionType.TIME_HOUR, null, cal);
85
-            
90
+
86
             if (cal.get(Calendar.HOUR_OF_DAY) == 0) {
91
             if (cal.get(Calendar.HOUR_OF_DAY) == 0) {
87
                 ActionManager.processEvent(TimeActionType.TIME_DAY, null, cal);
92
                 ActionManager.processEvent(TimeActionType.TIME_DAY, null, cal);
88
             }
93
             }
89
         }
94
         }
90
     }
95
     }
91
-    
96
+
92
     /** {@inheritDoc} */
97
     /** {@inheritDoc} */
93
     @Override
98
     @Override
94
     public void onUnload() {
99
     public void onUnload() {
96
             timer.cancel();
101
             timer.cancel();
97
             timer = null;
102
             timer = null;
98
         }
103
         }
99
-        
104
+        manager = null;
100
         CommandManager.unregisterCommand(command);
105
         CommandManager.unregisterCommand(command);
101
     }
106
     }
107
+
108
+    /**
109
+     * Returns the manager that is assigned to this Plugin.
110
+     *
111
+     * @return The Instance of TimeManager that is associated with this plugin
112
+     */
113
+    public TimerManager getTimerManager() {
114
+        return manager;
115
+    }
102
 }
116
 }

+ 45
- 14
src/com/dmdirc/addons/time/TimedCommand.java View File

1
 /*
1
 /*
2
- * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes,
3
+ * Simon Mott
3
  *
4
  *
4
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5
  * of this software and associated documentation files (the "Software"), to deal
6
  * of this software and associated documentation files (the "Software"), to deal
35
  * Timed command represents a command that has been scheduled by the user.
36
  * Timed command represents a command that has been scheduled by the user.
36
  */
37
  */
37
 public final class TimedCommand extends TimerTask {
38
 public final class TimedCommand extends TimerTask {
38
-    
39
+
39
     /** The number of repetitions remaining. */
40
     /** The number of repetitions remaining. */
40
     private int repetitions;
41
     private int repetitions;
41
-    
42
+
42
     /** The command to execute. */
43
     /** The command to execute. */
43
     private final String command;
44
     private final String command;
44
-    
45
+
45
     /** The container to use for executing commands. */
46
     /** The container to use for executing commands. */
46
     private final FrameContainer<?> origin;
47
     private final FrameContainer<?> origin;
47
 
48
 
48
     /** The window the command came from. */
49
     /** The window the command came from. */
49
     private final Window window;
50
     private final Window window;
50
-    
51
+
51
     /** The timer we're using for scheduling this command. */
52
     /** The timer we're using for scheduling this command. */
52
     private final Timer timer;
53
     private final Timer timer;
53
-    
54
+
55
+    /** The key for this timer in the Timer Manager */
56
+    private final int timerKey;
57
+
58
+    /** The manager for this timer. */
59
+    private final TimerManager manager;
60
+
54
     /**
61
     /**
55
      * Creates a new instance of TimedCommand.
62
      * Creates a new instance of TimedCommand.
63
+     *
56
      * @param repetitions The number of times this command will be executed
64
      * @param repetitions The number of times this command will be executed
57
      * @param delay The number of seconds between each execution
65
      * @param delay The number of seconds between each execution
58
      * @param command The command to be executed
66
      * @param command The command to be executed
59
      * @param origin The frame container to use for the execution
67
      * @param origin The frame container to use for the execution
60
      * @param window The window the command came from
68
      * @param window The window the command came from
61
      */
69
      */
62
-    public TimedCommand(final int repetitions, final int delay,
63
-            final String command, final FrameContainer<?> origin,
64
-            final Window window) {
70
+    public TimedCommand(final TimerManager manager, final int timerKey,
71
+            final int repetitions, final int delay, final String command,
72
+            final FrameContainer<?> origin, final Window window) {
65
         super();
73
         super();
66
-        
74
+
75
+        this.timerKey = timerKey;
67
         this.repetitions = repetitions;
76
         this.repetitions = repetitions;
68
         this.command = command;
77
         this.command = command;
69
         this.origin = origin;
78
         this.origin = origin;
70
         this.window = window;
79
         this.window = window;
71
-        
80
+        this.manager = manager;
81
+
72
         timer = new Timer("Timed Command Timer");
82
         timer = new Timer("Timed Command Timer");
73
         timer.schedule(this, delay * 1000L, delay * 1000L);
83
         timer.schedule(this, delay * 1000L, delay * 1000L);
74
     }
84
     }
75
 
85
 
86
+    /**
87
+     * Returns the command this timer is due to execute.
88
+     *
89
+     * @return Command the timer will run
90
+     * @since 0.6.5
91
+     */
92
+    public String getCommand() {
93
+        return command;
94
+    }
95
+
96
+    /**
97
+     * Cancels this timer and removes it from the Timer Manager
98
+     *
99
+     * @since 0.6.5
100
+     */
101
+    public void cancelTimer() {
102
+        manager.removeTimer(timerKey);
103
+        timer.cancel();
104
+    }
105
+
76
     /** {@inheritDoc} */
106
     /** {@inheritDoc} */
77
     @Override
107
     @Override
78
     public void run() {
108
     public void run() {
82
         } else {
112
         } else {
83
             parser = ((WritableFrameContainer<?>) origin).getCommandParser();
113
             parser = ((WritableFrameContainer<?>) origin).getCommandParser();
84
         }
114
         }
85
-        
115
+
86
         parser.parseCommand(origin, window, command);
116
         parser.parseCommand(origin, window, command);
87
-                
117
+
88
         if (--repetitions <= 0) {
118
         if (--repetitions <= 0) {
119
+            manager.removeTimer(timerKey);
89
             timer.cancel();
120
             timer.cancel();
90
         }
121
         }
91
     }
122
     }
92
-}
123
+}

+ 100
- 43
src/com/dmdirc/addons/time/TimerCommand.java View File

1
 /*
1
 /*
2
- * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes,
3
+ * Simon Mott
3
  *
4
  *
4
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5
  * of this software and associated documentation files (the "Software"), to deal
6
  * of this software and associated documentation files (the "Software"), to deal
30
 import com.dmdirc.commandparser.commands.IntelligentCommand;
31
 import com.dmdirc.commandparser.commands.IntelligentCommand;
31
 import com.dmdirc.commandparser.commands.context.CommandContext;
32
 import com.dmdirc.commandparser.commands.context.CommandContext;
32
 import com.dmdirc.ui.input.AdditionalTabTargets;
33
 import com.dmdirc.ui.input.AdditionalTabTargets;
33
-import com.dmdirc.ui.input.TabCompleter;
34
+
35
+import java.util.Map.Entry;
36
+import java.util.Set;
34
 
37
 
35
 /**
38
 /**
36
  * The timer command allows users to schedule commands to occur after a certain
39
  * The timer command allows users to schedule commands to occur after a certain
39
  */
42
  */
40
 public final class TimerCommand extends Command implements IntelligentCommand,
43
 public final class TimerCommand extends Command implements IntelligentCommand,
41
         CommandInfo {
44
         CommandInfo {
42
-    
45
+
46
+    /** The TimerManager for this TimerCommand. */
47
+    private final TimerManager manager;
48
+
43
     /**
49
     /**
44
      * Creates a new instance of TimerCommand.
50
      * Creates a new instance of TimerCommand.
51
+     *
52
+     * @param manager The instance of TimerManager associated with this command
45
      */
53
      */
46
-    public TimerCommand() {
54
+    public TimerCommand(final TimerManager manager) {
47
         super();
55
         super();
56
+
57
+        this.manager = manager;
48
     }
58
     }
49
-    
59
+
50
     /** {@inheritDoc} */
60
     /** {@inheritDoc} */
51
     @Override
61
     @Override
52
     public void execute(final FrameContainer<?> origin,
62
     public void execute(final FrameContainer<?> origin,
53
             final CommandArguments args, final CommandContext context) {
63
             final CommandArguments args, final CommandContext context) {
54
-        if (args.getArguments().length < 3) {
55
-            doUsage(origin, args.isSilent());
56
-        } else {
57
-            int repetitions = 0;
58
-            int interval = 0;
59
-            final String command = args.getArgumentsAsString(2);
60
-            
61
-            try {
62
-                repetitions = Integer.parseInt(args.getArguments()[0]);
63
-                interval = Integer.parseInt(args.getArguments()[1]);
64
-            } catch (NumberFormatException ex) {
65
-                doUsage(origin, args.isSilent());
66
-                return;
67
-            }
68
 
64
 
69
-            if (interval < 1) {
70
-                sendLine(origin, args.isSilent(), FORMAT_ERROR, "Cannot use" +
71
-                        " intervals below 1");
72
-                return;
73
-            }
65
+        if (args.getArguments().length > 0) {
66
+            if ("--cancel".equals(args.getArguments()[0])) {
67
+                int timerKey = 0;
68
+
69
+                try {
70
+                    timerKey = Integer.parseInt(args.getArgumentsAsString(1));
71
+                } catch (NumberFormatException ex) {
72
+                    doUsage(origin, args.isSilent());
73
+                    return;
74
+                }
75
+
76
+                if (manager.hasTimerWithID(timerKey)) {
77
+                    manager.getTimerByID(timerKey).cancelTimer();
78
+                    sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Timer cancelled");
79
+                } else {
80
+                    sendLine(origin, args.isSilent(), FORMAT_ERROR, "There is currently" +
81
+                            " no timer with that ID");
82
+                    return;
83
+                }
84
+            } else if ("--list".equals(args.getArguments()[0])) {
85
+                final Set<Entry<Integer, TimedCommand>> timerList
86
+                        = manager.listTimers();
87
+
88
+                if (!timerList.isEmpty()) {
89
+                    for (Entry<Integer, TimedCommand> entry : timerList) {
90
+                        sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Timer"
91
+                                + " ID: " + entry.getKey() + " - " +
92
+                                entry.getValue().getCommand());
93
+                    }
94
+                } else {
95
+                    sendLine(origin, args.isSilent(), FORMAT_ERROR, "There are " +
96
+                                "currently no active timers");
97
+                }
98
+            } else {
99
+                if (args.getArguments().length < 3) {
100
+                    doUsage(origin, args.isSilent());
101
+                } else {
102
+                    int repetitions = 0;
103
+                    int interval = 0;
104
+
105
+                    final String command = args.getArgumentsAsString(2);
106
+
107
+                    try {
108
+                        repetitions = Integer.parseInt(args.getArguments()[0]);
109
+                        interval = Integer.parseInt(args.getArguments()[1]);
110
+                    } catch (NumberFormatException ex) {
111
+                        doUsage(origin, args.isSilent());
112
+                        return;
113
+                    }
74
 
114
 
75
-            new TimedCommand(repetitions, interval, command, origin, context.getSource());
76
-            sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Command scheduled.");
115
+                    if (interval < 1) {
116
+                        sendLine(origin, args.isSilent(), FORMAT_ERROR, "Cannot use" +
117
+                                " intervals below 1");
118
+                        return;
119
+                    }
120
+
121
+                    manager.addTimer(repetitions, interval, command,
122
+                            origin, context.getSource());
123
+
124
+                    sendLine(origin, args.isSilent(), FORMAT_OUTPUT, "Command scheduled.");
125
+                }
126
+            }
127
+        } else {
128
+            doUsage(origin, args.isSilent());
77
         }
129
         }
78
     }
130
     }
79
-    
131
+
80
     /**
132
     /**
81
      * Displays usage information for this command.
133
      * Displays usage information for this command.
82
      * @param origin The window that the command was entered in
134
      * @param origin The window that the command was entered in
83
      * @param isSilent Whether this command is being silenced or not
135
      * @param isSilent Whether this command is being silenced or not
84
      */
136
      */
85
     private void doUsage(final FrameContainer<?> origin, final boolean isSilent) {
137
     private void doUsage(final FrameContainer<?> origin, final boolean isSilent) {
86
-        showUsage(origin, isSilent, "timer", "<repetitions> <interval> <command>");
138
+        showUsage(origin, isSilent, "timer", "[--list|--cancel <timer id> | " +
139
+                "<repetitions> <interval> <command>]");
87
     }
140
     }
88
-    
141
+
89
     /** {@inheritDoc} */
142
     /** {@inheritDoc} */
90
     @Override
143
     @Override
91
     public String getName() {
144
     public String getName() {
92
         return "timer";
145
         return "timer";
93
     }
146
     }
94
-    
147
+
95
     /** {@inheritDoc} */
148
     /** {@inheritDoc} */
96
     @Override
149
     @Override
97
     public boolean showInHelp() {
150
     public boolean showInHelp() {
103
     public CommandType getType() {
156
     public CommandType getType() {
104
         return CommandType.TYPE_GLOBAL;
157
         return CommandType.TYPE_GLOBAL;
105
     }
158
     }
106
-    
159
+
107
     /** {@inheritDoc} */
160
     /** {@inheritDoc} */
108
     @Override
161
     @Override
109
     public String getHelp() {
162
     public String getHelp() {
110
-        return "timer <repetitions> <interval> <command> " +
111
-                "- schedules a command to be executed after a certain time";
163
+        return "timer [--list|--cancel <timer id> | <repetitions> <interval> <command>] " +
164
+                "- lists all active timers / cancells an active timer of given ID" +
165
+                " / schedules a command to be executed after a certain time";
112
     }
166
     }
113
 
167
 
114
     /** {@inheritDoc} */
168
     /** {@inheritDoc} */
115
     @Override
169
     @Override
116
     public AdditionalTabTargets getSuggestions(final int arg,
170
     public AdditionalTabTargets getSuggestions(final int arg,
117
             final IntelligentCommandContext context) {
171
             final IntelligentCommandContext context) {
118
-        AdditionalTabTargets res;
119
-        
120
-        if (arg <= 1) {
121
-            res = new AdditionalTabTargets().excludeAll();
122
-        } else {
123
-            res = TabCompleter.getIntelligentResults(arg, context, 2);
172
+        final AdditionalTabTargets targets = new AdditionalTabTargets();
173
+
174
+        targets.excludeAll();
175
+        if (arg == 0) {
176
+            targets.add("--list");
177
+            targets.add("--cancel");
178
+        } else if (arg == 1 && "--cancel".equals(context.getPreviousArgs().get(0))) {
179
+            for (Integer i : manager.getTimerIDs()) {
180
+                targets.add(i.toString());
181
+            }
124
         }
182
         }
125
-        
126
-        return res;
127
-    } 
128
-    
183
+
184
+        return targets;
185
+    }
129
 }
186
 }

+ 133
- 0
src/com/dmdirc/addons/time/TimerManager.java View File

1
+/*
2
+ * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes,
3
+ * Simon Mott
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in
13
+ * all copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+
24
+package com.dmdirc.addons.time;
25
+
26
+import com.dmdirc.FrameContainer;
27
+import com.dmdirc.ui.interfaces.Window;
28
+
29
+import java.util.HashMap;
30
+import java.util.Map;
31
+import java.util.Map.Entry;
32
+import java.util.Set;
33
+
34
+/**
35
+ * Class to manage Timers.
36
+ *
37
+ * @author Simon Mott
38
+ * @since 0.6.5
39
+ */
40
+public class TimerManager {
41
+
42
+    /** Map of all the timers that are running. */
43
+    private final Map<Integer, TimedCommand> timerList;
44
+
45
+    /** Creates a new instance of TimeManager. */
46
+    public TimerManager() {
47
+        timerList = new HashMap<Integer, TimedCommand>();
48
+    }
49
+
50
+    /**
51
+     * Adds a timer to the internal list and starts the timer.
52
+     *
53
+     * @param repetitions Amount of times the timer repeats
54
+     * @param interval Interval between repetitions
55
+     * @param command Command to be run when the timer fires
56
+     * @param origin The frame container to use for the execution
57
+     * @param commandContext The window the command came from
58
+     */
59
+    public void addTimer(final int repetitions, final int interval, String command,
60
+            final FrameContainer<?> origin, final Window commandContext) {
61
+
62
+        synchronized (this) {
63
+            final int timerKey = findFreeKey();
64
+            timerList.put(timerKey, new TimedCommand(this, timerKey, repetitions,
65
+                interval, command, origin, commandContext));
66
+        }
67
+    }
68
+
69
+    /**
70
+     * Removes a timer from our internal list of active timers. This should only
71
+     * be called when a timer is cancelled.
72
+     *
73
+     * @param timerKey Key of the timer to remove
74
+     */
75
+    public void removeTimer(final int timerKey) {
76
+        timerList.remove(timerKey);
77
+    }
78
+
79
+    /**
80
+     * Gets a list of all current active timers.
81
+     *
82
+     * @return Returns a set of keys for all active timers
83
+     */
84
+    public Set<Entry<Integer, TimedCommand>> listTimers() {
85
+        return timerList.entrySet();
86
+    }
87
+
88
+    /**
89
+     * Returns a list of all known Timer IDs.
90
+     *
91
+     * @return returns an Integer Set of Timer IDs
92
+     */
93
+    public Set<Integer> getTimerIDs() {
94
+        return timerList.keySet();
95
+    }
96
+
97
+    /**
98
+     * Locates a key in our list that is currently not being used by a timer.
99
+     *
100
+     * @return Returns a key that can be used for creating a new timer
101
+     */
102
+    private int findFreeKey() {
103
+        int i = 0;
104
+        while (timerList.containsKey(i)) {
105
+            i++;
106
+        }
107
+        return i;
108
+    }
109
+
110
+    /**
111
+     * Matches a Timer ID to a Timer.
112
+     * This will return null if there is no Timer with the provided ID.
113
+     *
114
+     * @param id ID that we want the timer for
115
+     *
116
+     * @return Returns the Timer for the ID provided or null if none exist
117
+     */
118
+    public TimedCommand getTimerByID(final int id) {
119
+        return timerList.get(id);
120
+    }
121
+
122
+    /**
123
+     * Checkes if there is a timer with the provided ID.
124
+     *
125
+     * @param id ID that we want to check if there is a timer for
126
+     *
127
+     * @return Returns True of there is a timer with the ID. False if there isn't
128
+     */
129
+    public boolean hasTimerWithID(final int id) {
130
+        return timerList.containsKey(id);
131
+    }
132
+
133
+}

Loading…
Cancel
Save