1 package de.spiritscorp.datasync.controller;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.nio.file.Path;
24
25 import javafx.application.Platform;
26 import javafx.beans.property.BooleanProperty;
27 import javafx.beans.property.ReadOnlyBooleanProperty;
28 import javafx.beans.property.ReadOnlyStringProperty;
29 import javafx.beans.property.SimpleBooleanProperty;
30 import javafx.beans.property.SimpleStringProperty;
31 import javafx.beans.property.StringProperty;
32 import javafx.collections.FXCollections;
33 import javafx.collections.ObservableList;
34
35 import de.spiritscorp.datasync.ScanType;
36 import de.spiritscorp.datasync.io.Debug;
37 import de.spiritscorp.datasync.io.Preference;
38 import de.spiritscorp.datasync.model.FileAttributes;
39
40
41
42
43
44
45 public class SyncJobContext {
46
47 private final StringProperty jobName = new SimpleStringProperty();
48 private final BooleanProperty running = new SimpleBooleanProperty( false );
49 private final StringProperty statusMessage = new SimpleStringProperty( "Bereit" );
50 private final StringProperty logOutput = new SimpleStringProperty( "" );
51 private final StringProperty selectedMode = new SimpleStringProperty( ScanType.SYNCHRONIZE.getDescription() );
52
53 private final Preference taskPreference;
54 private Thread activeWorkerThread;
55
56 private final ObservableList<FileRow> duplicateFiles = FXCollections.observableArrayList();
57
58
59
60
61
62
63
64 public SyncJobContext( final String name, final Preference taskPreference ) {
65 this.jobName.set( name );
66 this.taskPreference = taskPreference;
67 }
68
69
70
71
72
73 void setActiveWorkerThread( final Thread thread ) { this.activeWorkerThread = thread; }
74
75
76
77
78
79
80
81
82 public synchronized void cancelRunningTask( final long timeoutMs ) {
83 if( activeWorkerThread != null && activeWorkerThread.isAlive() ) {
84 Debug.printDebug( "[Info] Sending interruption signal to worker thread for job: %s", getJobName() );
85 activeWorkerThread.interrupt();
86
87 if( timeoutMs > 0 ) {
88 try {
89
90 activeWorkerThread.join( timeoutMs );
91 if( activeWorkerThread.isAlive() ) {
92 Debug.printDebug( "[Warn] Warning: Worker thread for job '%s' breached timeout matrix.", getJobName() );
93 }
94 }catch( InterruptedException _ ) {
95 Debug.printDebug( "[Info] Thread joining sequence was interrupted for job: %s", getJobName() );
96 Thread.currentThread().interrupt();
97 }
98 }
99
100
101 if( !activeWorkerThread.isAlive() ) {
102 setRunning( false );
103 setStatusMessage( "Aktion erfolgreich beendet." );
104 appendLog( "-> Vorgang sauber beendet." );
105 }else {
106 setRunning( false );
107 setStatusMessage( "Aktion vom Benutzer abgebrochen (Forced)." );
108 appendLog( "-> Vorgang erzwungen abgebrochen." );
109 }
110 }else {
111 updateUIAndLog( "Keine aktive Aktion.", "-> Nichts zu beenden gefunden." );
112 }
113 }
114
115
116
117
118 private void updateUIAndLog( final String status, final String logEntry ) {
119 if( Platform.isFxApplicationThread() ) {
120 setStatusMessage( status );
121 appendLog( logEntry );
122 }else {
123 try {
124 Platform.runLater( () -> {
125 setStatusMessage( status );
126 appendLog( logEntry );
127 } );
128 }catch( IllegalStateException _ ) {
129
130
131 Debug.printDebug( "[Info] GUI framework offline. Suppressed state update: %s (%s)", status, logEntry );
132 }
133 }
134 }
135
136 public void appendLog( final String line ) {
137 this.logOutput.set( this.logOutput.get() + line + System.lineSeparator() );
138 }
139
140 void clearLog() {
141 this.logOutput.set( "" );
142 }
143
144 public String getJobName() { return jobName.get(); }
145
146 void setJobName( final String newTaskName ) {
147 this.jobName.set( newTaskName );
148 }
149
150 public ReadOnlyStringProperty jobNameProperty() {
151 return jobName;
152 }
153
154 public boolean isRunning() { return running.get(); }
155
156 public ReadOnlyBooleanProperty runningProperty() {
157 return running;
158 }
159
160 void setRunning( final boolean value ) {
161 if( Platform.isFxApplicationThread() ) {
162 this.running.set( value );
163 }else {
164 Platform.runLater( () -> this.running.set( value ) );
165 }
166 }
167
168 public String getStatusMessage() { return statusMessage.get(); }
169
170 public ReadOnlyStringProperty statusMessageProperty() {
171 return statusMessage;
172 }
173
174 public void setStatusMessage( final String message ) {
175 this.statusMessage.set( message );
176 }
177
178 public String getLogOutput() { return logOutput.get(); }
179
180 public ReadOnlyStringProperty logOutputProperty() {
181 return logOutput;
182 }
183
184 public ScanType getSelectedMode() { return ScanType.get( selectedMode.get() ); }
185
186 public StringProperty selectedModeProperty() {
187 return selectedMode;
188 }
189
190 public void setSelectedMode( final String mode ) {
191 this.selectedMode.set( mode );
192 }
193
194 public Preference getPreference() { return taskPreference; }
195
196 public ObservableList<FileRow> getDuplicateFiles() { return duplicateFiles; }
197
198
199
200
201 public static class FileRow {
202 private final BooleanProperty selected = new SimpleBooleanProperty( false );
203 private final StringProperty fileName = new SimpleStringProperty();
204 private final StringProperty size = new SimpleStringProperty();
205 private final StringProperty hash = new SimpleStringProperty();
206 private final StringProperty path = new SimpleStringProperty();
207 private final Path fileSystemPath;
208
209 public FileRow( final Path path, final FileAttributes attr, final String readableSize ) {
210 this.fileSystemPath = path;
211 this.fileName.set( attr.getFileName() );
212 this.size.set( readableSize );
213 this.hash.set( attr.getFileHash() );
214 this.path.set( path.toString() );
215 }
216
217 public ReadOnlyBooleanProperty selectedProperty() {
218 return selected;
219 }
220
221 public boolean isSelected() { return selected.get(); }
222
223 public void setSelected( final boolean val ) {
224 this.selected.set( val );
225 }
226
227 public ReadOnlyStringProperty fileNameProperty() {
228 return fileName;
229 }
230
231 public ReadOnlyStringProperty sizeProperty() {
232 return size;
233 }
234
235 public ReadOnlyStringProperty hashProperty() {
236 return hash;
237 }
238
239 public ReadOnlyStringProperty pathProperty() {
240 return path;
241 }
242
243 public Path getFileSystemPath() { return fileSystemPath; }
244 }
245 }