1 package fr.ifremer.tutti.ui.swing;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Preconditions;
26 import com.google.common.collect.Maps;
27 import com.google.common.collect.Sets;
28 import fr.ifremer.tutti.TuttiConfiguration;
29 import fr.ifremer.tutti.caliper.feed.CaliperFeedReader;
30 import fr.ifremer.tutti.ichtyometer.feed.IchtyometerFeedReader;
31 import fr.ifremer.tutti.persistence.ProgressionModel;
32 import fr.ifremer.tutti.service.ClosedPersistenceService;
33 import fr.ifremer.tutti.service.DecoratorService;
34 import fr.ifremer.tutti.service.PersistenceService;
35 import fr.ifremer.tutti.service.TuttiDataContext;
36 import fr.ifremer.tutti.service.TuttiServiceContext;
37 import fr.ifremer.tutti.service.ValidationService;
38 import fr.ifremer.tutti.service.bigfin.BigfinImportService;
39 import fr.ifremer.tutti.service.catches.ValidateCruiseOperationsService;
40 import fr.ifremer.tutti.service.catches.WeightCleaningService;
41 import fr.ifremer.tutti.service.catches.WeightComputingService;
42 import fr.ifremer.tutti.service.catches.multipost.MultiPostExportService;
43 import fr.ifremer.tutti.service.catches.multipost.MultiPostImportService;
44 import fr.ifremer.tutti.service.export.cps.CalcifiedPiecesSamplingExportService;
45 import fr.ifremer.tutti.service.export.pdf.CatchesPdfExportService;
46 import fr.ifremer.tutti.service.export.sumatra.CatchesSumatraExportService;
47 import fr.ifremer.tutti.service.export.toconfirmreport.ToConfirmReportService;
48 import fr.ifremer.tutti.service.genericformat.GenericFormatExportService;
49 import fr.ifremer.tutti.service.genericformat.GenericFormatImportService;
50 import fr.ifremer.tutti.service.operationimport.FishingOperationImportService;
51 import fr.ifremer.tutti.service.protocol.ProtocolCaracteristicsImportExportService;
52 import fr.ifremer.tutti.service.protocol.ProtocolImportExportService;
53 import fr.ifremer.tutti.service.psionimport.PsionImportService;
54 import fr.ifremer.tutti.service.pupitri.PupitriExportService;
55 import fr.ifremer.tutti.service.pupitri.PupitriImportService;
56 import fr.ifremer.tutti.service.referential.ReferentialTemporaryGearService;
57 import fr.ifremer.tutti.service.referential.ReferentialTemporaryPersonService;
58 import fr.ifremer.tutti.service.referential.ReferentialTemporarySpeciesService;
59 import fr.ifremer.tutti.service.referential.ReferentialTemporaryVesselService;
60 import fr.ifremer.tutti.service.referential.TuttiReferentialSynchronizeService;
61 import fr.ifremer.tutti.service.report.ReportGenerationService;
62 import fr.ifremer.tutti.service.cruise.CruiseCacheLoader;
63 import fr.ifremer.tutti.ui.swing.content.MainUI;
64 import fr.ifremer.tutti.ui.swing.updater.DeleteHelper;
65 import fr.ifremer.tutti.ui.swing.util.SoundEngine;
66 import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil;
67 import fr.ifremer.tutti.ui.swing.util.UIMessageNotifier;
68 import fr.ifremer.tutti.ui.swing.util.auth.AuthenticationInfo;
69 import fr.ifremer.tutti.ui.swing.util.auth.LoginUI;
70 import jaxx.runtime.JAXXContext;
71 import jaxx.runtime.swing.editor.bean.BeanDoubleList;
72 import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox;
73 import jaxx.runtime.swing.help.JAXXHelpBroker;
74 import jaxx.runtime.swing.help.JAXXHelpUIHandler;
75 import jaxx.runtime.swing.session.BeanDoubleListState;
76 import jaxx.runtime.swing.session.BeanFilterableComboBoxState;
77 import jaxx.runtime.swing.session.State;
78 import jaxx.runtime.swing.session.SwingSession;
79 import org.apache.commons.io.IOUtils;
80 import org.apache.commons.lang3.StringUtils;
81 import org.apache.commons.logging.Log;
82 import org.apache.commons.logging.LogFactory;
83 import org.jdesktop.beans.AbstractBean;
84 import org.nuiton.converter.ConverterUtil;
85 import org.nuiton.i18n.I18n;
86 import org.nuiton.i18n.init.DefaultI18nInitializer;
87 import org.nuiton.i18n.init.UserI18nInitializer;
88 import org.nuiton.jaxx.application.ApplicationBusinessException;
89 import org.nuiton.jaxx.application.ApplicationIOUtil;
90 import org.nuiton.jaxx.application.ApplicationTechnicalException;
91 import org.nuiton.jaxx.application.listener.PropagatePropertyChangeListener;
92 import org.nuiton.jaxx.application.swing.ApplicationUIContext;
93 import org.nuiton.jaxx.application.swing.action.ApplicationActionEngine;
94 import org.nuiton.jaxx.application.swing.action.ApplicationActionUI;
95 import org.nuiton.jaxx.application.swing.action.ApplicationUIAction;
96 import org.nuiton.jaxx.application.swing.util.ApplicationErrorHelper;
97
98 import javax.swing.JOptionPane;
99 import java.awt.Color;
100 import java.awt.Component;
101 import java.beans.PropertyChangeListener;
102 import java.io.Closeable;
103 import java.io.File;
104 import java.io.IOException;
105 import java.io.InputStream;
106 import java.net.URI;
107 import java.net.URISyntaxException;
108 import java.util.Date;
109 import java.util.Locale;
110 import java.util.Map;
111 import java.util.Properties;
112 import java.util.Set;
113 import java.util.Timer;
114
115 import static org.nuiton.i18n.I18n.n;
116 import static org.nuiton.i18n.I18n.t;
117
118
119
120
121
122
123
124 public class TuttiUIContext extends AbstractBean implements Closeable, UIMessageNotifier, JAXXHelpUIHandler, PropagatePropertyChangeListener.PropagatePropertyChange, ApplicationUIContext {
125
126
127 private static final Log log = LogFactory.getLog(TuttiUIContext.class);
128
129 public static final String PROPERTY_PROGRAM_ID = "programId";
130
131 public static final String PROPERTY_CRUISE_ID = "cruiseId";
132
133 public static final String PROPERTY_PROTOCOL_ID = "protocolId";
134
135 public static final String PROPERTY_SCREEN = "screen";
136
137
138
139
140
141
142
143 public static final String PROPERTY_VALIDATION_CONTEXT = "validationContext";
144
145 public static final String PROPERTY_ICHTYOMETER_CONNECTED = "ichtyometerConnected";
146
147 public static final String PROPERTY_CALIPER_CONNECTED = "caliperConnected";
148
149 public static final String PROPERTY_BUSY = "busy";
150
151 public static final String PROPERTY_HIDE_BODY = "hideBody";
152
153 public static final String PROPERTY_LOCALE = "locale";
154
155 public static final Set<String> PROPERTIES_TO_SAVE = Sets.newHashSet(
156 PROPERTY_PROGRAM_ID,
157 PROPERTY_CRUISE_ID,
158 PROPERTY_PROTOCOL_ID,
159 PROPERTY_LOCALE);
160
161 public static final String PROPERTY_DB_EXIST = "dbExist";
162
163 public static final String PROPERTY_DB_LOADED = "dbLoaded";
164
165
166
167
168
169
170 private static TuttiUIContext applicationContext;
171
172
173
174
175
176
177 protected final TuttiConfiguration config;
178
179
180
181
182
183
184 protected final TuttiServiceContext serviceContext;
185
186
187
188
189
190
191 protected final SwingSession swingSession;
192
193
194
195
196
197
198 protected final ApplicationErrorHelper errorHelper;
199
200
201
202
203
204
205 protected TuttiDataContext dataContext;
206
207
208
209
210
211
212 protected TuttiHelpBroker helpBroker;
213
214
215
216
217
218
219 protected TuttiScreen screen;
220
221
222
223
224
225
226 protected Locale locale;
227
228
229
230
231
232
233 protected boolean busy;
234
235
236
237
238
239
240 protected boolean hideBody;
241
242
243
244
245
246
247 protected final Set<UIMessageNotifier> messageNotifiers;
248
249
250
251
252
253
254 private String validationContext;
255
256 private MainUI mainUI;
257
258 private ApplicationActionUI actionUI;
259
260
261
262
263
264
265 private boolean dbExist;
266
267
268
269
270
271
272 private boolean dbLoaded;
273
274 private Properties helpMapping;
275
276 private final TuttiActionFactory tuttiActionFactory;
277
278 private final ApplicationActionEngine tuttiActionEngine;
279
280
281
282
283
284
285 private final Map<String, AuthenticationInfo> updateAuthenticationStore;
286
287
288
289
290
291
292 private IchtyometerFeedReader ichtyometerReader;
293
294
295
296
297
298
299 private CaliperFeedReader caliperFeedReader;
300
301
302
303
304
305
306
307 private File lock;
308
309
310
311
312
313
314
315 private boolean closed;
316
317 private final SoundEngine soundEngine;
318
319 public static TuttiUIContext newContext(TuttiConfiguration config) {
320 Preconditions.checkNotNull(config);
321 Preconditions.checkState(applicationContext == null,
322 "Application context was already opened!");
323 applicationContext = new TuttiUIContext(config);
324 return applicationContext;
325 }
326
327 public static TuttiUIContext getApplicationContext() {
328 return applicationContext;
329 }
330
331 public ApplicationErrorHelper getErrorHelper() {
332 return applicationContext.errorHelper;
333 }
334
335 @Override
336 public String getI18nPrefix() {
337 return "tutti.property.";
338 }
339
340 @Override
341 public String getDateFormat() {
342 return getConfig().getDateFormat();
343 }
344
345 @Override
346 public boolean isActionInProgress(ApplicationUIAction action) {
347
348 return false;
349 }
350
351 @Override
352 public void setActionInProgress(ApplicationUIAction action, boolean actionInProgress) {
353
354 }
355
356 protected TuttiUIContext(TuttiConfiguration config) {
357 this.config = config;
358 this.serviceContext = new TuttiServiceContext(config);
359
360 Map<Class, State> additionalStates = Maps.newHashMap();
361 additionalStates.put(BeanFilterableComboBox.class, new BeanFilterableComboBoxState());
362 additionalStates.put(BeanDoubleList.class, new BeanDoubleListState());
363 this.swingSession = SwingSession.newSession(getConfig().getUIConfigFile(), false, additionalStates);
364
365
366 this.errorHelper = new ApplicationErrorHelper(this) {
367
368 @Override
369 public void showWarningDialog(String message) {
370
371 JOptionPane.showMessageDialog(context.getActionUI(), "<html><body>" + message + "</body></html>",
372 t("application.error.ui.business.warning"),
373 JOptionPane.WARNING_MESSAGE);
374 }
375
376 @Override
377 public void showErrorDialog(String message, Throwable cause) {
378 super.showErrorDialog(message, cause);
379 }
380 };
381 this.dataContext = serviceContext.getDataContext();
382 PropagatePropertyChangeListener.listenAndPropagateAll(dataContext, this);
383 UIMessageNotifier logMessageNotifier = new UIMessageNotifier() {
384
385 @Override
386 public void showInformationMessage(String message) {
387 if (StringUtils.isNotBlank(message)) {
388 message = message.replaceAll("\\<strong\\>", "");
389 message = message.replaceAll("\\<.strong\\>", "");
390 message = message.replaceAll("\\<li\\>", "");
391 message = message.replaceAll("\\<.li\\>", "");
392 message = message.replaceAll("\\<ul\\>", "");
393 message = message.replaceAll("\\<.ul\\>", "");
394 if (log.isInfoEnabled()) {
395 log.info(message);
396 }
397 }
398 }
399 };
400 this.messageNotifiers = Sets.newHashSet();
401 addMessageNotifier(logMessageNotifier);
402 tuttiActionFactory = new TuttiActionFactory();
403 tuttiActionEngine = new ApplicationActionEngine(tuttiActionFactory);
404 this.updateAuthenticationStore = Maps.newTreeMap();
405 this.soundEngine = new SoundEngine(config);
406 }
407
408 @Override
409 public TuttiConfiguration getConfiguration() {
410 return config;
411 }
412
413 @Override
414 public Component getBodyUI() {
415 MainUI mainUI = getMainUI();
416 return mainUI == null ? null : mainUI.getBody();
417 }
418
419 @Override
420 public Component getStatusUI() {
421 MainUI mainUI = getMainUI();
422 return mainUI == null ? null : mainUI.getStatus();
423 }
424
425
426
427
428
429 public void init() {
430
431 config.prepareDirectories();
432
433
434
435 ConverterUtil.deregister();
436 ConverterUtil.initConverters();
437
438
439 Runtime.getRuntime().addShutdownHook(new Thread(() -> {
440 if (!closed) {
441 close();
442 }
443 }));
444
445
446
447
448
449 config.initConfig();
450
451
452
453
454
455
456
457
458
459
460
461
462
463 File i18nDirectory = config.getI18nDirectory();
464 if (!config.isFullLaunchMode()) {
465
466 i18nDirectory = new File(config.getDataDirectory(), "i18n");
467
468 if (i18nDirectory.exists()) {
469
470 ApplicationIOUtil.cleanDirectory(
471 i18nDirectory,
472 t("tutti.i18n.deleteCache.error", i18nDirectory));
473 }
474 }
475
476 ApplicationIOUtil.forceMkdir(i18nDirectory,
477 t("tutti.i18n.mkDir.error", i18nDirectory));
478
479 if (log.isDebugEnabled()) {
480 log.debug("I18N directory: " + i18nDirectory);
481 }
482
483 Locale i18nLocale = config.getI18nLocale();
484
485 if (log.isInfoEnabled()) {
486 log.info(String.format("Starts i18n with locale [%s] at [%s]",
487 i18nLocale, i18nDirectory));
488 }
489 I18n.init(new UserI18nInitializer(
490 i18nDirectory, new DefaultI18nInitializer("tutti-i18n")),
491 i18nLocale);
492
493
494
495
496
497
498 lock = new File(config.getBasedir(), "tutti.lock");
499
500 if (lock.exists()) {
501 lock = null;
502 throw new ApplicationBusinessException(t("tutti.error.application.already.started"));
503 }
504
505 ApplicationIOUtil.writeContent(lock, new Date().toString(), "Could not create lock file");
506 if (log.isInfoEnabled()) {
507 log.info("Create lock file: " + lock);
508 }
509
510
511
512
513
514
515 File helpDirectory = config.getHelpDirectory();
516
517 if (!config.isFullLaunchMode()) {
518
519 if (!helpDirectory.exists()) {
520 helpDirectory = new File(config.getDataDirectory(), "help");
521 }
522 }
523
524 if (log.isDebugEnabled()) {
525 log.debug("Help directory: " + helpDirectory);
526 }
527 ApplicationIOUtil.forceMkdir(
528 helpDirectory,
529 t("tutti.help.mkDir.error", helpDirectory));
530
531
532 String mappingProperties = "/tutti-help-fr.properties";
533 try {
534
535 InputStream resourceAsStream =
536 getClass().getResourceAsStream(mappingProperties);
537 helpMapping = new Properties();
538 helpMapping.load(resourceAsStream);
539
540 } catch (Exception eee) {
541 log.error("Failed to load help mapping file at '" +
542 mappingProperties + "'", eee);
543 }
544 if (log.isInfoEnabled()) {
545 log.info(String.format("Starts help with locale at [%s]",
546 helpDirectory));
547 }
548
549
550
551
552 setActionUI(new ApplicationActionUI(null, this));
553 }
554
555 public void open() {
556
557 setLocale(config.getI18nLocale());
558
559 if (getProgramId() == null) {
560
561
562 setProgramId(config.getProgramId());
563 }
564
565 if (getCruiseId() == null) {
566
567
568 setCruiseId(config.getCruiseId());
569 }
570
571 if (getProtocolId() == null) {
572
573
574 setProtocolId(config.getProtocolId());
575 }
576
577 boolean dbExists = config.isDbExists();
578
579 setDbExist(dbExists);
580
581 if (!dbExists) {
582
583 setProtocolId(null);
584 setProgramId(null);
585 setCruiseId(null);
586 setDbLoaded(false);
587 }
588
589
590 saveContextToConfig();
591
592
593 addPropertyChangeListener(evt -> {
594
595 if (PROPERTIES_TO_SAVE.contains(evt.getPropertyName())) {
596 saveContextToConfig();
597 }
598 });
599
600 soundEngine.open();
601
602 }
603
604 @Override
605 public void close() {
606
607 if (log.isInfoEnabled()) {
608 log.info("Closing application context...");
609 }
610 Preconditions.checkState(!closed, "Application was already closed.");
611
612 try {
613
614 messageNotifiers.clear();
615 validationContext = null;
616 IOUtils.closeQuietly(dataContext);
617
618 if (timer != null) {
619 timer.purge();
620 timer.cancel();
621 }
622
623 setScreen(null);
624
625 IOUtils.closeQuietly(serviceContext);
626 IOUtils.closeQuietly(ichtyometerReader);
627 IOUtils.closeQuietly(caliperFeedReader);
628 IOUtils.closeQuietly(soundEngine);
629
630
631 PropertyChangeListener[] listeners = getPropertyChangeListeners();
632 for (PropertyChangeListener listener : listeners) {
633 if (log.isDebugEnabled()) {
634 log.debug("Remove listener: " + listener);
635 }
636 removePropertyChangeListener(listener);
637 }
638 setMainUI(null);
639 if (actionUI != null) {
640
641
642 actionUI.getModel().clear();
643 }
644 setActionUI(null);
645
646 } finally {
647 closed = true;
648 if (lock != null) {
649
650
651 ApplicationIOUtil.deleteFile(lock, "Could not delete lock file");
652 if (log.isInfoEnabled()) {
653 log.info("Delete lock file: " + lock);
654 }
655 }
656 }
657 }
658
659
660
661
662
663 public PersistenceService getPersistenceService() {
664
665 PersistenceService service;
666
667 if (useRealPersistenceService()) {
668 service = dataContext.getService();
669 if (service == null) {
670
671
672 service = serviceContext.getService(PersistenceService.class);
673 dataContext.setPersistenceService(service);
674
675 }
676 } else {
677 service = serviceContext.getService(ClosedPersistenceService.class);
678 }
679 return service;
680 }
681
682 public DecoratorService getDecoratorService() {
683 return serviceContext.getService(DecoratorService.class);
684 }
685
686 public TuttiReferentialSynchronizeService getTuttiReferentialSynchronizeService() {
687 return serviceContext.getService(TuttiReferentialSynchronizeService.class);
688 }
689
690 public ProtocolImportExportService getTuttiProtocolImportExportService() {
691 return serviceContext.getService(ProtocolImportExportService.class);
692 }
693
694 public ProtocolCaracteristicsImportExportService getProtocolCaracteristicsImportExportService() {
695 return serviceContext.getService(ProtocolCaracteristicsImportExportService.class);
696 }
697
698 public PupitriImportService getPupitriImportService() {
699 return serviceContext.getService(PupitriImportService.class);
700 }
701
702 public PupitriExportService getPupitriExportService() {
703 return serviceContext.getService(PupitriExportService.class);
704 }
705
706 public PsionImportService getTuttiPsionImportService() {
707 return serviceContext.getService(PsionImportService.class);
708 }
709
710 public BigfinImportService getTuttiBigfinImportService() {
711 return serviceContext.getService(BigfinImportService.class);
712 }
713
714 public ReferentialTemporaryGearService getReferentialTemporaryGearService() {
715 return serviceContext.getService(ReferentialTemporaryGearService.class);
716 }
717
718 public ReferentialTemporaryPersonService getReferentialTemporaryPersonService() {
719 return serviceContext.getService(ReferentialTemporaryPersonService.class);
720 }
721
722 public ReferentialTemporarySpeciesService getReferentialTemporarySpeciesService() {
723 return serviceContext.getService(ReferentialTemporarySpeciesService.class);
724 }
725
726 public ReferentialTemporaryVesselService getReferentialTemporaryVesselService() {
727 return serviceContext.getService(ReferentialTemporaryVesselService.class);
728 }
729
730 public WeightComputingService getWeightComputingService() {
731 return serviceContext.getService(WeightComputingService.class);
732 }
733
734 public WeightCleaningService getWeightCleaningService() {
735 return serviceContext.getService(WeightCleaningService.class);
736 }
737
738 public ValidateCruiseOperationsService getValidateCruiseOperationsService() {
739 return serviceContext.getService(ValidateCruiseOperationsService.class);
740 }
741
742 public ValidationService getValidationService() {
743 return serviceContext.getService(ValidationService.class);
744 }
745
746 public CatchesPdfExportService getGeneratePDFService() {
747 return serviceContext.getService(CatchesPdfExportService.class);
748 }
749
750 public ToConfirmReportService getToConfirmReportService() {
751 return serviceContext.getService(ToConfirmReportService.class);
752 }
753
754 public GenericFormatExportService getGenericFormatExportService() {
755 return serviceContext.getService(GenericFormatExportService.class);
756 }
757
758 public GenericFormatImportService getGenericFormatImportService() {
759 return serviceContext.getService(GenericFormatImportService.class);
760 }
761
762 public CatchesSumatraExportService getCatchesSumatraExportService() {
763 return serviceContext.getService(CatchesSumatraExportService.class);
764 }
765
766 public CalcifiedPiecesSamplingExportService getCalcifiedPiecesSamplingExportService() {
767 return serviceContext.getService(CalcifiedPiecesSamplingExportService.class);
768 }
769
770 public MultiPostImportService getMultiPostImportService() {
771 return serviceContext.getService(MultiPostImportService.class);
772 }
773
774 public MultiPostExportService getMultiPostExportService() {
775 return serviceContext.getService(MultiPostExportService.class);
776 }
777
778 public FishingOperationImportService getFishingOperationImportService() {
779 return serviceContext.getService(FishingOperationImportService.class);
780 }
781
782 public ReportGenerationService getReportGenerationService() {
783 return serviceContext.getService(ReportGenerationService.class);
784 }
785
786 public SoundEngine getSoundEngine() {
787 return soundEngine;
788 }
789
790 public boolean useRealPersistenceService() {
791 return isDbExist() && isDbLoaded();
792 }
793
794 private PersistenceService reloadPersistenceService() {
795
796 try {
797 serviceContext.close();
798 } catch (IOException e) {
799 throw new ApplicationTechnicalException(t("tutti.context.service.close.error"), e);
800 }
801 dataContext.close();
802
803 return getPersistenceService();
804 }
805
806 public void reloadDecoratorService() {
807 serviceContext.reloadService(DecoratorService.class);
808 }
809
810
811
812
813
814 public TuttiDataContext getDataContext() {
815 return dataContext;
816 }
817
818 public boolean isCruiseFilled() {
819 return dataContext.isCruiseFilled();
820 }
821
822 public String getProgramId() {
823 return dataContext.getProgramId();
824 }
825
826 public boolean isProtocolFilled() {
827 return dataContext.isProtocolFilled();
828 }
829
830 public String getProtocolId() {
831 return dataContext.getProtocolId();
832 }
833
834 public Integer getCruiseId() {
835 return dataContext.getCruiseId();
836 }
837
838 public boolean isProgramFilled() {
839 return dataContext.isProgramFilled();
840 }
841
842 public void setProgramId(String programId) {
843 dataContext.setProgramId(programId);
844 }
845
846 public void setCruiseId(Integer cruiseId) {
847 dataContext.setCruiseId(cruiseId);
848 }
849
850 public void setProtocolId(String protocolId) {
851 dataContext.setProtocolId(protocolId);
852 }
853
854 public void clearDbContext() {
855 dataContext.clearContext();
856 }
857
858 public void checkDbContext() {
859
860
861 dataContext.open(config);
862
863
864 dataContext.checkDbContext();
865
866
867 saveContextToConfig();
868
869 }
870
871 public CruiseCacheLoader createCruiseCacheLoader(ProgressionModel progressionModel) {
872
873 return CruiseCacheLoader.newCacheLoader(getPersistenceService(),
874 getDecoratorService(),
875 progressionModel,
876 getDataContext().getProtocol(),
877 getCruiseId());
878
879 }
880
881
882
883
884
885 public boolean isDbExist() {
886 return dbExist;
887 }
888
889 public void setDbExist(boolean dbExist) {
890 this.dbExist = dbExist;
891 firePropertyChange(PROPERTY_DB_EXIST, null, dbExist);
892 }
893
894 public boolean isDbLoaded() {
895 return dbLoaded;
896 }
897
898 private void setDbLoaded(boolean dbLoaded) {
899 this.dbLoaded = dbLoaded;
900 firePropertyChange(PROPERTY_DB_LOADED, null, dbLoaded);
901 }
902
903
904
905
906
907 public TuttiConfiguration getConfig() {
908 return config;
909 }
910
911 protected void saveContextToConfig() {
912 if (log.isInfoEnabled()) {
913 log.info("Save config (programId: " + getProgramId() + ", cruiseId: " +
914 getCruiseId() + ", protocolId: " + getProtocolId() + ", locale: " +
915 getLocale() + ")");
916 }
917 config.setProgramId(getProgramId());
918 config.setCruiseId(getCruiseId());
919 config.setProtocolId(getProtocolId());
920 config.setI18nLocale(getLocale());
921 config.save();
922 }
923
924
925
926
927
928
929 @Override
930 public MainUI getMainUI() {
931 return mainUI;
932 }
933
934 public void setMainUI(MainUI mainUI) {
935 this.mainUI = mainUI;
936 }
937
938 @Override
939 public ApplicationActionUI getActionUI() {
940 return actionUI;
941 }
942
943 @Override
944 public ApplicationActionUI getExistingActionUI() {
945 while (actionUI == null || !actionUI.isShowing()) {
946
947 try {
948 Thread.sleep(50);
949 } catch (InterruptedException e) {
950
951 }
952 }
953 return actionUI;
954 }
955
956 public void setActionUI(ApplicationActionUI actionUI) {
957 this.actionUI = actionUI;
958 }
959
960 public void addInSwingSession(Component c, boolean replace) {
961
962 try {
963
964 swingSession.add(c, replace);
965
966 saveSwingSession();
967
968 } catch (Exception e) {
969 if (log.isWarnEnabled()) {
970 log.warn("Could not add component " + c + "in swingSession file: " + swingSession.getFile(), e);
971 }
972 }
973
974 }
975
976 public void saveSwingSession() {
977
978 try {
979 swingSession.save();
980 } catch (Exception e) {
981 if (log.isWarnEnabled()) {
982 log.warn("Could not save ui config file: " + swingSession.getFile(), e);
983 }
984 }
985
986 }
987
988 public TuttiScreen getScreen() {
989 return screen;
990 }
991
992 public void setScreen(TuttiScreen screen) {
993 Object oldValue = getScreen();
994 this.screen = screen;
995 firePropertyChange(PROPERTY_SCREEN, oldValue, screen);
996 }
997
998 @Override
999 public boolean isBusy() {
1000 return busy;
1001 }
1002
1003 @Override
1004 public void setBusy(boolean busy) {
1005 this.busy = busy;
1006 firePropertyChange(PROPERTY_BUSY, null, busy);
1007 }
1008
1009 @Override
1010 public boolean isHideBody() {
1011 return hideBody;
1012 }
1013
1014 @Override
1015 public void setHideBody(boolean hideBody) {
1016 this.hideBody = hideBody;
1017 firePropertyChange(PROPERTY_HIDE_BODY, null, hideBody);
1018 }
1019
1020 @Override
1021 public Color getColorBlockingLayer() {
1022 return getConfig().getColorBlockingLayer();
1023 }
1024
1025 @Override
1026 public TuttiActionFactory getActionFactory() {
1027 return tuttiActionFactory;
1028 }
1029
1030 @Override
1031 public ApplicationActionEngine getActionEngine() {
1032 return tuttiActionEngine;
1033 }
1034
1035
1036
1037
1038
1039 public void addMessageNotifier(UIMessageNotifier messageNotifier) {
1040 this.messageNotifiers.add(messageNotifier);
1041 }
1042
1043 public void removeMessageNotifier(UIMessageNotifier messageNotifier) {
1044 this.messageNotifiers.remove(messageNotifier);
1045 }
1046
1047 @Override
1048 public void showInformationMessage(String message) {
1049 for (UIMessageNotifier messageNotifier : messageNotifiers) {
1050 messageNotifier.showInformationMessage(message);
1051 }
1052 }
1053
1054
1055
1056
1057
1058 public TuttiHelpBroker getHelpBroker() {
1059 return helpBroker;
1060 }
1061
1062 public void setHelpBroker(TuttiHelpBroker helpBroker) {
1063 this.helpBroker = helpBroker;
1064 }
1065
1066 @Override
1067 public void showHelp(JAXXContext context,
1068 JAXXHelpBroker broker,
1069 String helpId) {
1070 if (helpId == null) {
1071 helpId = broker.getDefaultID();
1072 }
1073
1074 if (log.isInfoEnabled()) {
1075 log.info("show help " + helpId);
1076 }
1077
1078 String value = (String) helpMapping.get(helpId);
1079
1080 if (value == null) {
1081 throw new ApplicationTechnicalException(t("tutti.context.helpPage.notFound", helpId));
1082 }
1083
1084 String helpDirectory = getConfig().getHelpResourceWithLocale(value);
1085 boolean withFragment = helpDirectory.contains("#");
1086
1087 String fragment = null;
1088 if (withFragment) {
1089 fragment = StringUtils.substringAfter(helpDirectory, "#");
1090 helpDirectory = StringUtils.substringBefore(helpDirectory, "#");
1091 }
1092
1093 URI resolvedUri = new File(helpDirectory).toURI();
1094 try {
1095
1096 if (withFragment) {
1097 resolvedUri = new URI(resolvedUri.toString() + "#" + fragment);
1098 }
1099 if (log.isInfoEnabled()) {
1100 log.info("help uri = " + resolvedUri);
1101 }
1102 TuttiUIUtil.openLink(resolvedUri);
1103 } catch (URISyntaxException e) {
1104 throw new ApplicationTechnicalException(t("tutti.context.helpPage.notFound", resolvedUri));
1105 }
1106
1107 }
1108
1109
1110
1111
1112
1113 public AuthenticationInfo getAuthenticationInfo(String url) {
1114
1115
1116 AuthenticationInfo authentication = updateAuthenticationStore.get(url);
1117
1118
1119 authentication = new LoginUI(this).open(url, authentication).getAuthenticationInfo();
1120
1121 if (authentication != null) {
1122
1123
1124 updateAuthenticationStore.put(url, authentication);
1125 }
1126
1127 return authentication;
1128 }
1129
1130
1131
1132
1133
1134 public IchtyometerFeedReader getIchtyometerReader() {
1135 return ichtyometerReader;
1136 }
1137
1138 public void setIchtyometerReader(IchtyometerFeedReader ichtyometerReader) {
1139 this.ichtyometerReader = ichtyometerReader;
1140 firePropertyChange(PROPERTY_ICHTYOMETER_CONNECTED, null, isIchtyometerConnected());
1141 }
1142
1143 public boolean isIchtyometerConnected() {
1144 return ichtyometerReader != null;
1145 }
1146
1147
1148
1149
1150
1151 public CaliperFeedReader getCaliperReader() {
1152 return caliperFeedReader;
1153 }
1154
1155 public void setCaliperReader(CaliperFeedReader caliperFeedReader) {
1156 this.caliperFeedReader = caliperFeedReader;
1157 firePropertyChange(PROPERTY_CALIPER_CONNECTED, null, isCaliperConnected());
1158 }
1159
1160 public boolean isCaliperConnected() {
1161 return caliperFeedReader != null;
1162 }
1163
1164
1165
1166
1167
1168 public Locale getLocale() {
1169 return locale;
1170 }
1171
1172 public void setLocale(Locale locale) {
1173 this.locale = locale;
1174 firePropertyChange(PROPERTY_LOCALE, null, locale);
1175 }
1176
1177 public void setValidationContext(String validationContext) {
1178 Object oldValue = getValidationContext();
1179 this.validationContext = validationContext;
1180 firePropertyChange(PROPERTY_VALIDATION_CONTEXT, oldValue, validationContext);
1181 }
1182
1183 public String getValidationContext() {
1184 return validationContext;
1185 }
1186
1187 @Override
1188 public void firePropertyChanged(String propertyName,
1189 Object oldValue,
1190 Object newValue) {
1191 firePropertyChange(propertyName, oldValue, newValue);
1192 }
1193
1194 public void setFallBackScreen() {
1195 if (isDbLoaded()) {
1196 setScreen(TuttiScreen.SELECT_CRUISE);
1197 } else {
1198 setScreen(TuttiScreen.MANAGE_DB);
1199 }
1200 }
1201
1202 public boolean checkUpdateApplicationReachable(boolean showErrorInPopup) {
1203
1204 boolean result = true;
1205 String url = config.getUpdateApplicationUrl();
1206
1207 try {
1208 TuttiUIUtil.tryToConnectToUpdateUrl(
1209 url,
1210 n("tutti.error.update.bad.url.syntax"),
1211 n("tutti.error.update.could.not.reach.url"),
1212 n("tutti.error.update.could.not.found.url")
1213 );
1214 } catch (ApplicationBusinessException e) {
1215 if (showErrorInPopup) {
1216
1217 getErrorHelper().showWarningDialog(e.getMessage());
1218 } else {
1219 showInformationMessage(e.getMessage());
1220 }
1221 result = false;
1222 }
1223 return result;
1224 }
1225
1226 public boolean checkUpdateDataReachable(boolean showErrorInPopup) {
1227
1228 boolean result = true;
1229 String url = config.getUpdateDataUrl();
1230
1231 try {
1232 TuttiUIUtil.tryToConnectToUpdateUrl(
1233 url,
1234 n("tutti.error.update.bad.url.syntax"),
1235 n("tutti.error.update.could.not.reach.url"),
1236 n("tutti.error.update.could.not.found.url")
1237 );
1238 } catch (ApplicationBusinessException e) {
1239 if (showErrorInPopup) {
1240
1241 getErrorHelper().showWarningDialog(e.getMessage());
1242 } else {
1243 showInformationMessage(e.getMessage());
1244 }
1245 result = false;
1246 }
1247 return result;
1248 }
1249
1250 public void closePersistenceService() {
1251
1252 setDbLoaded(false);
1253 reloadPersistenceService();
1254
1255 }
1256
1257 public void openPersistenceService() {
1258
1259 setDbLoaded(true);
1260 reloadPersistenceService();
1261
1262 }
1263
1264 public void deleteDbOnExit() {
1265
1266 if (log.isInfoEnabled()) {
1267 log.info("Delete db files on exit.");
1268 }
1269
1270 try {
1271
1272 DeleteHelper.deleteDirectoryOnExit(config.getDbDirectory().toPath());
1273 DeleteHelper.deleteDirectoryOnExit(config.getCacheDirectory().toPath());
1274 DeleteHelper.deleteDirectoryOnExit(config.getDbAttachmentDirectory().toPath());
1275
1276 } catch (IOException e) {
1277 throw new ApplicationTechnicalException("Could not mark db files to be deleted on exit.", e);
1278 }
1279
1280 }
1281
1282 private Timer timer;
1283
1284 public synchronized Timer getTimer() {
1285 if (timer == null) {
1286 timer = new Timer("ShowActions::");
1287 }
1288 return timer;
1289 }
1290
1291 public synchronized Timer reloadTimer() {
1292 timer = null;
1293 return getTimer();
1294 }
1295
1296 }