1
1
package fi .helsinki .cs .tmc .actions ;
2
2
3
+ import com .google .common .util .concurrent .FutureCallback ;
4
+ import com .google .common .util .concurrent .Futures ;
5
+ import com .google .common .util .concurrent .ListenableFuture ;
3
6
import hy .tmc .core .domain .Course ;
4
- import fi .helsinki .cs .tmc .data .CourseListUtils ;
5
7
import fi .helsinki .cs .tmc .model .CourseDb ;
6
8
import fi .helsinki .cs .tmc .model .LocalExerciseStatus ;
7
9
import fi .helsinki .cs .tmc .model .ObsoleteClientException ;
8
10
import fi .helsinki .cs .tmc .model .ServerAccess ;
9
11
import fi .helsinki .cs .tmc .model .NBTmcSettings ;
12
+ import fi .helsinki .cs .tmc .model .TmcCoreSingleton ;
10
13
import fi .helsinki .cs .tmc .ui .DownloadOrUpdateExercisesDialog ;
11
14
import fi .helsinki .cs .tmc .ui .ConvenientDialogDisplayer ;
12
15
import fi .helsinki .cs .tmc .ui .TmcNotificationDisplayer ;
13
- import fi .helsinki .cs .tmc .utilities .BgTask ;
14
- import fi .helsinki .cs .tmc .utilities .BgTaskListener ;
15
16
import fi .helsinki .cs .tmc .utilities .Inflector ;
16
17
import fi .helsinki .cs .tmc .utilities .TmcStringUtils ;
18
+ import hy .tmc .core .TmcCore ;
19
+ import hy .tmc .core .exceptions .TmcCoreException ;
17
20
import java .awt .event .ActionEvent ;
18
21
import java .awt .event .ActionListener ;
19
22
import java .util .ArrayList ;
20
- import java .util .List ;
21
23
import javax .swing .AbstractAction ;
22
24
import javax .swing .Icon ;
23
25
import org .apache .commons .lang3 .StringUtils ;
24
26
import org .openide .awt .ActionID ;
25
27
import org .openide .awt .ActionReference ;
26
28
import org .openide .awt .ActionReferences ;
27
29
import org .openide .awt .ActionRegistration ;
30
+ import org .openide .util .Exceptions ;
28
31
import org .openide .util .ImageUtilities ;
29
32
import org .openide .util .NbBundle .Messages ;
30
33
31
34
@ ActionID (category = "TMC" ,
32
- id = "fi.helsinki.cs.tmc.actions.CheckForNewExercisesOrUpdates" )
35
+ id = "fi.helsinki.cs.tmc.actions.CheckForNewExercisesOrUpdates" )
33
36
@ ActionRegistration (displayName = "#CTL_CheckForNewExercisesOrUpdates" )
34
37
@ ActionReferences ({
35
38
@ ActionReference (path = "Menu/TM&C" , position = -50 )
38
41
public class CheckForNewExercisesOrUpdates extends AbstractAction {
39
42
40
43
public static void startTimer () {
41
- int interval = 20 * 60 * 1000 ; // 20 minutes
44
+ int interval = 20 * 60 * 1000 ; // 20 minutes
42
45
javax .swing .Timer timer = new javax .swing .Timer (interval , new CheckForNewExercisesOrUpdates (true , true ));
43
46
timer .setRepeats (true );
44
47
timer .start ();
45
48
}
46
-
49
+
47
50
private static final TmcNotificationDisplayer .SingletonToken notifierToken = TmcNotificationDisplayer .createSingletonToken ();
48
-
51
+
49
52
private CourseDb courseDb ;
50
53
private ServerAccess serverAccess ;
51
54
private TmcNotificationDisplayer notifier ;
52
55
private ConvenientDialogDisplayer dialogs ;
53
56
private boolean beQuiet ;
54
57
private boolean backgroundCheck ;
58
+ private TmcCore tmcCore ;
55
59
56
60
public CheckForNewExercisesOrUpdates () {
57
61
this (false , false );
58
62
}
59
-
63
+
60
64
public CheckForNewExercisesOrUpdates (boolean beQuiet , boolean backgroundCheck ) {
61
65
this .courseDb = CourseDb .getInstance ();
62
66
this .serverAccess = new ServerAccess ();
63
67
this .notifier = TmcNotificationDisplayer .getDefault ();
64
68
this .dialogs = ConvenientDialogDisplayer .getDefault ();
65
69
this .beQuiet = beQuiet ;
66
70
this .backgroundCheck = backgroundCheck ;
71
+ this .tmcCore = TmcCoreSingleton .getInstance ();
67
72
}
68
73
69
74
@ Override
70
75
public void actionPerformed (ActionEvent e ) {
71
76
run ();
72
77
}
73
-
78
+
79
+ //"Checking for new exercises" päivitä tämä näkymään progressHandleen myöhemmin
80
+ /**
81
+ *
82
+ */
74
83
public void run () {
75
- final Course currentCourseBeforeUpdate = courseDb .getCurrentCourse ();
76
-
84
+ try {
85
+ final Course currentCourseBeforeUpdate = courseDb .getCurrentCourse ();
86
+ if (backgroundProcessingOrNoCurrentCourse (currentCourseBeforeUpdate )) {
87
+ return ;
88
+ }
89
+ ListenableFuture <Course > currentCourseFuture = this .tmcCore .getCourse (
90
+ NBTmcSettings .getDefault (), currentCourseBeforeUpdate .getDetailsUrl ()
91
+ );
92
+ Futures .addCallback (currentCourseFuture , new UpdateCourseForExerciseUpdate ());
93
+ } catch (TmcCoreException ex ) {
94
+ Exceptions .printStackTrace (ex );
95
+ }
96
+ }
97
+
98
+ /**
99
+ * If there is something at background or no current course is chosen,
100
+ * return true.
101
+ */
102
+ private boolean backgroundProcessingOrNoCurrentCourse (final Course currentCourseBeforeUpdate ) {
77
103
if (backgroundCheck && !NBTmcSettings .getDefault ().isCheckingForUpdatesInTheBackground ()) {
78
- return ;
104
+ return true ;
79
105
}
80
-
81
106
if (currentCourseBeforeUpdate == null ) {
82
107
if (!beQuiet ) {
83
108
dialogs .displayMessage ("Please select a course in TMC -> Settings." );
84
109
}
85
- return ;
110
+ return true ;
111
+ }
112
+ return false ;
113
+ }
114
+
115
+ class UpdateCourseForExerciseUpdate implements FutureCallback <Course > {
116
+
117
+ /**
118
+ * This should be attached to listenableFuture. When future is ready,
119
+ * receivedCourse will be saved to courseDb and view will be updated.
120
+ */
121
+ public UpdateCourseForExerciseUpdate () {
122
+ }
123
+
124
+ @ Override
125
+ public void onSuccess (Course receivedCourse ) {
126
+ if (receivedCourse != null ) {
127
+ courseDb .putDetailedCourse (receivedCourse );
128
+ final LocalExerciseStatus status = LocalExerciseStatus .get (receivedCourse .getExercises ());
129
+ updateGUI (status );
130
+ }
86
131
}
87
-
88
- BgTask .start ("Checking for new exercises" , serverAccess .getFullCourseInfoTask (currentCourseBeforeUpdate ), new BgTaskListener <Course >() {
89
- @ Override
90
- public void bgTaskReady (Course receivedCourse ) {
91
- if (receivedCourse != null ) {
92
- courseDb .putDetailedCourse (receivedCourse );
93
-
94
- final LocalExerciseStatus status = LocalExerciseStatus .get (receivedCourse .getExercises ());
95
- if (status .thereIsSomethingToDownload (false )) {
96
- if (beQuiet ) {
97
- displayNotification (status , new ActionListener () {
98
- @ Override
99
- public void actionPerformed (ActionEvent e ) {
100
- DownloadOrUpdateExercisesDialog .display (status .unlockable , status .downloadableUncompleted , status .updateable );
101
- }
102
- });
103
- } else {
132
+
133
+ private void updateGUI (final LocalExerciseStatus status ) {
134
+ if (status .thereIsSomethingToDownload (false )) {
135
+ if (beQuiet ) {
136
+ displayNotification (status , new ActionListener () {
137
+ @ Override
138
+ public void actionPerformed (ActionEvent e ) {
104
139
DownloadOrUpdateExercisesDialog .display (status .unlockable , status .downloadableUncompleted , status .updateable );
105
140
}
106
- } else if (! beQuiet ) {
107
- dialogs . displayMessage ( "No new exercises or updates to download." );
108
- }
141
+ });
142
+ } else {
143
+ DownloadOrUpdateExercisesDialog . display ( status . unlockable , status . downloadableUncompleted , status . updateable );
109
144
}
145
+ } else if (!beQuiet ) {
146
+ dialogs .displayMessage ("No new exercises or updates to download." );
110
147
}
148
+ }
111
149
112
- @ Override
113
- public void bgTaskCancelled () {
114
- }
115
-
116
- @ Override
117
- public void bgTaskFailed (Throwable ex ) {
118
- if (!beQuiet || ex instanceof ObsoleteClientException ) {
119
- dialogs .displayError ("Failed to check for new exercises.\n " + ServerErrorHelper .getServerExceptionMsg (ex ));
120
- }
150
+ @ Override
151
+ public void onFailure (Throwable ex ) {
152
+ if (!beQuiet || ex instanceof ObsoleteClientException ) {
153
+ dialogs .displayError ("Failed to check for new exercises.\n " + ServerErrorHelper .getServerExceptionMsg (ex ));
121
154
}
122
- });
155
+ }
123
156
}
124
157
125
158
private void displayNotification (LocalExerciseStatus status , ActionListener action ) {
126
159
ArrayList <String > items = new ArrayList <String >();
127
160
ArrayList <String > actions = new ArrayList <String >();
128
-
161
+
129
162
if (!status .unlockable .isEmpty ()) {
130
163
items .add (Inflector .pluralize (status .unlockable .size (), "an unlockable exercise" ));
131
164
actions .add ("unlock" );
@@ -138,18 +171,18 @@ private void displayNotification(LocalExerciseStatus status, ActionListener acti
138
171
items .add (Inflector .pluralize (status .updateable .size (), "an update" ));
139
172
actions .add ("update" );
140
173
}
141
-
142
- int total =
143
- status .unlockable .size () +
144
- status .downloadableUncompleted .size () +
145
- status .updateable .size ();
146
-
174
+
175
+ int total
176
+ = status .unlockable .size ()
177
+ + status .downloadableUncompleted .size ()
178
+ + status .updateable .size ();
179
+
147
180
String msg = TmcStringUtils .joinCommaAnd (items );
148
181
msg += " " + Inflector .pluralize (total , "is" ) + " available." ;
149
182
msg = StringUtils .capitalize (msg );
150
-
183
+
151
184
String prompt = "Click here to " + TmcStringUtils .joinCommaAnd (actions ) + "." ;
152
-
185
+
153
186
notifier .notify (notifierToken , msg , getNotificationIcon (), prompt , action );
154
187
}
155
188
0 commit comments