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,5 +1,6 @@
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 5
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5 6
  * of this software and associated documentation files (the "Software"), to deal
@@ -35,21 +36,24 @@ import java.util.TimerTask;
35 36
  * @author chris
36 37
  */
37 38
 public final class TimePlugin  extends Plugin {
38
-    
39
+
39 40
     /** Have we registered our types already? */
40 41
     private static boolean registered;
41
-    
42
+
42 43
     /** The timer to use for scheduling. */
43 44
     private Timer timer;
44
-    
45
+
45 46
     /** The TimerCommand we've registered. */
46 47
     private TimerCommand command;
47
-    
48
+
49
+    /** The Manager to use for managing timers. */
50
+    private TimerManager manager;
51
+
48 52
     /** Creates a new instance of TimePlugin. */
49 53
     public TimePlugin() {
50 54
         super();
51 55
     }
52
-    
56
+
53 57
     /** {@inheritDoc} */
54 58
     @Override
55 59
     public void onLoad() {
@@ -59,9 +63,9 @@ public final class TimePlugin  extends Plugin {
59 63
         }
60 64
 
61 65
         final int offset = 60 - Calendar.getInstance().get(Calendar.SECOND);
62
-        
66
+
63 67
         timer = new Timer("Time plugin timer");
64
-        
68
+
65 69
         timer.schedule(new TimerTask() {
66 70
             /** {@inheritDoc} */
67 71
             @Override
@@ -69,26 +73,27 @@ public final class TimePlugin  extends Plugin {
69 73
                 runTimer();
70 74
             }
71 75
         }, 1000 * offset, 1000 * 60);
72
-        
73
-        command = new TimerCommand();
76
+
77
+        manager = new TimerManager();
78
+        command = new TimerCommand(manager);
74 79
         CommandManager.registerCommand(command);
75 80
     }
76
-    
81
+
77 82
     /** Handles a timer event that occurs every minute. */
78 83
     public void runTimer() {
79 84
         final Calendar cal = Calendar.getInstance();
80
-        
85
+
81 86
         ActionManager.processEvent(TimeActionType.TIME_MINUTE, null, cal);
82
-        
87
+
83 88
         if (cal.get(Calendar.MINUTE) == 0) {
84 89
             ActionManager.processEvent(TimeActionType.TIME_HOUR, null, cal);
85
-            
90
+
86 91
             if (cal.get(Calendar.HOUR_OF_DAY) == 0) {
87 92
                 ActionManager.processEvent(TimeActionType.TIME_DAY, null, cal);
88 93
             }
89 94
         }
90 95
     }
91
-    
96
+
92 97
     /** {@inheritDoc} */
93 98
     @Override
94 99
     public void onUnload() {
@@ -96,7 +101,16 @@ public final class TimePlugin  extends Plugin {
96 101
             timer.cancel();
97 102
             timer = null;
98 103
         }
99
-        
104
+        manager = null;
100 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,5 +1,6 @@
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 5
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5 6
  * of this software and associated documentation files (the "Software"), to deal
@@ -35,44 +36,73 @@ import java.util.TimerTask;
35 36
  * Timed command represents a command that has been scheduled by the user.
36 37
  */
37 38
 public final class TimedCommand extends TimerTask {
38
-    
39
+
39 40
     /** The number of repetitions remaining. */
40 41
     private int repetitions;
41
-    
42
+
42 43
     /** The command to execute. */
43 44
     private final String command;
44
-    
45
+
45 46
     /** The container to use for executing commands. */
46 47
     private final FrameContainer<?> origin;
47 48
 
48 49
     /** The window the command came from. */
49 50
     private final Window window;
50
-    
51
+
51 52
     /** The timer we're using for scheduling this command. */
52 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 62
      * Creates a new instance of TimedCommand.
63
+     *
56 64
      * @param repetitions The number of times this command will be executed
57 65
      * @param delay The number of seconds between each execution
58 66
      * @param command The command to be executed
59 67
      * @param origin The frame container to use for the execution
60 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 73
         super();
66
-        
74
+
75
+        this.timerKey = timerKey;
67 76
         this.repetitions = repetitions;
68 77
         this.command = command;
69 78
         this.origin = origin;
70 79
         this.window = window;
71
-        
80
+        this.manager = manager;
81
+
72 82
         timer = new Timer("Timed Command Timer");
73 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 106
     /** {@inheritDoc} */
77 107
     @Override
78 108
     public void run() {
@@ -82,11 +112,12 @@ public final class TimedCommand extends TimerTask {
82 112
         } else {
83 113
             parser = ((WritableFrameContainer<?>) origin).getCommandParser();
84 114
         }
85
-        
115
+
86 116
         parser.parseCommand(origin, window, command);
87
-                
117
+
88 118
         if (--repetitions <= 0) {
119
+            manager.removeTimer(timerKey);
89 120
             timer.cancel();
90 121
         }
91 122
     }
92
-}
123
+}

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

@@ -1,5 +1,6 @@
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 5
  * Permission is hereby granted, free of charge, to any person obtaining a copy
5 6
  * of this software and associated documentation files (the "Software"), to deal
@@ -30,7 +31,9 @@ import com.dmdirc.commandparser.commands.Command;
30 31
 import com.dmdirc.commandparser.commands.IntelligentCommand;
31 32
 import com.dmdirc.commandparser.commands.context.CommandContext;
32 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 39
  * The timer command allows users to schedule commands to occur after a certain
@@ -39,59 +42,109 @@ import com.dmdirc.ui.input.TabCompleter;
39 42
  */
40 43
 public final class TimerCommand extends Command implements IntelligentCommand,
41 44
         CommandInfo {
42
-    
45
+
46
+    /** The TimerManager for this TimerCommand. */
47
+    private final TimerManager manager;
48
+
43 49
     /**
44 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 55
         super();
56
+
57
+        this.manager = manager;
48 58
     }
49
-    
59
+
50 60
     /** {@inheritDoc} */
51 61
     @Override
52 62
     public void execute(final FrameContainer<?> origin,
53 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 133
      * Displays usage information for this command.
82 134
      * @param origin The window that the command was entered in
83 135
      * @param isSilent Whether this command is being silenced or not
84 136
      */
85 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 142
     /** {@inheritDoc} */
90 143
     @Override
91 144
     public String getName() {
92 145
         return "timer";
93 146
     }
94
-    
147
+
95 148
     /** {@inheritDoc} */
96 149
     @Override
97 150
     public boolean showInHelp() {
@@ -103,27 +156,31 @@ public final class TimerCommand extends Command implements IntelligentCommand,
103 156
     public CommandType getType() {
104 157
         return CommandType.TYPE_GLOBAL;
105 158
     }
106
-    
159
+
107 160
     /** {@inheritDoc} */
108 161
     @Override
109 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 168
     /** {@inheritDoc} */
115 169
     @Override
116 170
     public AdditionalTabTargets getSuggestions(final int arg,
117 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

@@ -0,0 +1,133 @@
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