From cfc3aef20ebaf90b02cce6e3712bfe30eab7b30f Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 10:06:36 -0400 Subject: [PATCH 01/48] Formatting updates --- .../client/task/ClientTaskDispatcher.java | 14 ++++----- .../client/server/ClientServerManager.java | 6 ++-- .../vcell/clientdb/ClientDocumentManager.java | 30 ++++++++----------- .../org/vcell/util/VCellThreadChecker.java | 24 ++++----------- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 42153d8ba5..6e6749aa3e 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -89,26 +89,26 @@ public class ClientTaskDispatcher { * @param tasks cbit.vcell.desktop.controls.ClientTask[] */ public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks) { - dispatch(requester,hash,tasks,false, false, false, null, false); + ClientTaskDispatcher.dispatch(requester,hash,tasks,false, false, false, null, false); } public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { - dispatch(requester,hash,tasks, true, bKnowProgress, false, null, false); + ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, false, null, false); } public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener) { - dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, false); } public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } private static int entryCounter = 0; @@ -259,7 +259,7 @@ public static void dispatch(final Component requester, final Hashtable taskList = new ArrayList(); + final List taskList = new ArrayList<>(); for (int i = 0; i < tasks.length; i++){ if (tasks[i].getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING && i < tasks.length - 1) { diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java index 74d8a907ca..7cc0fee463 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java @@ -636,9 +636,9 @@ public synchronized User getUser() { */ public synchronized UserMetaDbServer getUserMetaDbServer() throws DataAccessException { VCellThreadChecker.checkRemoteInvocation(); - if (userMetaDbServer!=null){ - return userMetaDbServer; - }else if (getVcellConnection()==null){ + if (userMetaDbServer != null) return userMetaDbServer; + + if (getVcellConnection()==null){ throw new RuntimeException("cannot get Database Server, no VCell Connection\ntry Server->Reconnect"); }else{ try { diff --git a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java index a84c82554a..aed308adab 100644 --- a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java +++ b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java @@ -803,24 +803,20 @@ public BioModelInfo[] getBioModelInfos() { private XMLHolder getBioModelXML(KeyValue vKey) throws DataAccessException { - try{ - String xmlString = (String)xmlHash.get(vKey); - if (xmlString==null){ - BigString xmlBS = sessionManager.getUserMetaDbServer().getBioModelXML(vKey); - xmlString = (xmlBS != null?xmlBS.toString():null); - if(xmlString != null){ - BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(xmlString)); - String newXmlString = XmlHelper.bioModelToXML(bioModel); - xmlHash.put(vKey,newXmlString); - return new XMLHolder(newXmlString,bioModel); - }else{ - throw new RuntimeException("unexpected: UserMetaDbServer.getBioModelXML() returned null"); - } - }else{ - return new XMLHolder(xmlString); - } - }catch (ObjectNotFoundException e){ + String xmlString = xmlHash.get(vKey); + if (null != xmlString) return new XMLHolder<>(xmlString); + BigString xmlBS = sessionManager.getUserMetaDbServer().getBioModelXML(vKey); + xmlString = (xmlBS != null?xmlBS.toString():null); + if(xmlString != null){ + BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(xmlString)); + String newXmlString = XmlHelper.bioModelToXML(bioModel); + xmlHash.put(vKey,newXmlString); + return new XMLHolder<>(newXmlString, bioModel); + }else{ + throw new RuntimeException("unexpected: UserMetaDbServer.getBioModelXML() returned null"); + } + }catch (ObjectNotFoundException e){ throw new DataAccessException("BioModel (id=" + vKey + ") does not exist. It either " + "has been deleted or its reference is outdated. Please use menu 'Server->Reconnect' to update document references."); }catch(Exception e){ diff --git a/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java b/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java index 13997ecf5a..a2e95f5c7d 100644 --- a/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java +++ b/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java @@ -14,31 +14,16 @@ public class VCellThreadChecker { - private static final ThreadLocal cpuSuppressed = new ThreadLocal() { - @Override - protected Integer initialValue() { - return 0; - } - }; + private static final ThreadLocal cpuSuppressed = ThreadLocal.withInitial(() -> 0); - private static final ThreadLocal remoteSuppressed = new ThreadLocal() { - @Override - protected Integer initialValue() { - return 0; - } - }; + private static final ThreadLocal remoteSuppressed = ThreadLocal.withInitial(() -> 0); public interface GUIThreadChecker { - public boolean isEventDispatchThread(); + boolean isEventDispatchThread(); } - private static GUIThreadChecker guiThreadChecker = new GUIThreadChecker() { - - public boolean isEventDispatchThread() { - return SwingUtilities.isEventDispatchThread(); - } - }; + private static GUIThreadChecker guiThreadChecker = SwingUtilities::isEventDispatchThread; public static void setGUIThreadChecker(GUIThreadChecker argGuiThreadChecker){ guiThreadChecker = argGuiThreadChecker; @@ -85,6 +70,7 @@ public SuppressIntensive() { super(cpuSuppressed); } } + public static class SuppressRemote extends Suppressor { public SuppressRemote() { super(remoteSuppressed); From 0687ef5534b5fdb02a9579148e0838878a040a57 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 10:07:33 -0400 Subject: [PATCH 02/48] [WIP] Added dispatch call to schedule check This isn't a solution; more work is needed --- .../vcell/client/ClientRequestManager.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index 44af99645f..f8dd1b13d0 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -340,8 +340,29 @@ private CloseOption checkBeforeClosing(DocumentWindowManager windowManager) { return CloseOption.CLOSE_IN_ANY_CASE; } boolean isChanged = true; + String IS_CHANGED_KEY = this.getClass().getName() + ".DocumentManager::isChanged"; + Hashtable hashtable = new Hashtable<>(); try { - isChanged = getDocumentManager().isChanged(vcDocument); + AsynchClientTask checkIfChanged = new AsynchClientTask( + "Checking if model has changed...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + boolean hasBeenChanged = ClientRequestManager.this.getDocumentManager().isChanged(vcDocument); + hashTable.put(IS_CHANGED_KEY, hasBeenChanged); + } + }; + ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[]{checkIfChanged}, + false, false, null, true); + ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[] {checkIfChanged}); + if (hashtable.containsKey(IS_CHANGED_KEY)) + isChanged = (Boolean)hashtable.get(IS_CHANGED_KEY); + else if (hashtable.containsKey("clientTaskDispatcherStackTraceArray")){ + StringBuilder stackTrace = new StringBuilder(); + for (StackTraceElement elem : (StackTraceElement[]) hashtable.get("clientTaskDispatcherStackTraceArray")) + stackTrace.append(" \tat ").append(elem.toString()).append("\n"); + lg.error("Unknown error occurred during task 'Checking if model has changed'\n{}", stackTrace); + } } catch (Exception exc) { exc.printStackTrace(); String choice = PopupGenerator.showWarningDialog(windowManager, getUserPreferences(), From 3171869f9afb196d3fa7a2182d43bbf7a29d2188 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 10:55:37 -0400 Subject: [PATCH 03/48] Formatting fixes --- .../client/task/ClientTaskDispatcher.java | 1268 ++++++++--------- 1 file changed, 612 insertions(+), 656 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 6e6749aa3e..879804bcc0 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -9,6 +9,7 @@ */ package cbit.vcell.client.task; + import java.awt.Component; import java.awt.Cursor; import java.awt.Window; @@ -44,681 +45,636 @@ import cbit.vcell.client.task.AsynchClientTask.KeyInfo; import cbit.vcell.simdata.PDEDataContext; import swingthreads.SwingWorker; + /** * Insert the type's description here. * Creation date: (5/28/2004 2:44:22 AM) + * * @author: Ion Moraru */ public class ClientTaskDispatcher { -// public static final String PROGRESS_POPUP = "asynchProgressPopup"; + // public static final String PROGRESS_POPUP = "asynchProgressPopup"; // public static final String TASK_PROGRESS_INTERVAL = "progressRange"; - public static final String TASK_ABORTED_BY_ERROR = "abort"; - public static final String TASK_ABORTED_BY_USER = "cancel"; - public static final String TASKS_TO_BE_SKIPPED = "conditionalSkip"; - /** - * hash key to internally flag problem with hash table data - */ - private static final String HASH_DATA_ERROR = "hdeHdeHde"; - /** - * hash key to store stack trace if {@link #lg} enabled for INFO - */ - private static final String STACK_TRACE_ARRAY = "clientTaskDispatcherStackTraceArray"; - private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); - /** - * used to count / generate thread names - */ - private static long serial = 0; - /** - * set of all scheduled tasks; used to avoid calling System.exit() prematurely on Application exit - */ - private static final Set allTasks; - /** - * hash key for final window - */ - private static final String FINAL_WINDOW = "finalWindowInterface"; - - static { - WeakHashMap whm = new WeakHashMap( ); - allTasks = Collections.synchronizedSet( Collections.newSetFromMap(whm) ); - } - - -/** - * don't show popup. - * Creation date: (5/31/2004 5:37:06 PM) - * @param tasks cbit.vcell.desktop.controls.ClientTask[] - */ -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks) { - ClientTaskDispatcher.dispatch(requester,hash,tasks,false, false, false, null, false); -} - -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { - ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, false, null, false); -} - -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener) { - ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, false); -} - -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); -} - -public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); -} - -private static int entryCounter = 0; -public static boolean isBusy(){ - if(entryCounter>0){ -// System.out.println("----------Busy----------"); - return true; - } - return false; -} - -public static class BlockingTimer extends Timer{ - private static AsynchProgressPopup pp; - private static ArrayList allBlockingTimers = new ArrayList<>(); - private static Timer ppStop = new Timer(1000, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - synchronized (allBlockingTimers) { - if(pp != null && allBlockingTimers.size() == 0){ + public static final String TASK_ABORTED_BY_ERROR = "abort"; + public static final String TASK_ABORTED_BY_USER = "cancel"; + public static final String TASKS_TO_BE_SKIPPED = "conditionalSkip"; + /** + * hash key to internally flag problem with hash table data + */ + private static final String HASH_DATA_ERROR = "hdeHdeHde"; + /** + * hash key to store stack trace if {@link #lg} enabled for INFO + */ + private static final String STACK_TRACE_ARRAY = "clientTaskDispatcherStackTraceArray"; + private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); + /** + * used to count / generate thread names + */ + private static long serial = 0; + /** + * set of all scheduled tasks; used to avoid calling System.exit() prematurely on Application exit + */ + private static final Set allTasks; + /** + * hash key for final window + */ + private static final String FINAL_WINDOW = "finalWindowInterface"; + + static { + WeakHashMap whm = new WeakHashMap(); + allTasks = Collections.synchronizedSet(Collections.newSetFromMap(whm)); + } + + + /** + * don't show popup. + * Creation date: (5/31/2004 5:37:06 PM) + * + * @param tasks cbit.vcell.desktop.controls.ClientTask[] + */ + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, false, false, false, null, false); + } + + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, false, null, false); + } + + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + } + + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + private static int entryCounter = 0; + + public static boolean isBusy() { + // System.out.println("----------Busy----------"); + return entryCounter > 0; + } + + public static class BlockingTimer extends Timer { + private static AsynchProgressPopup pp; + private static final ArrayList allBlockingTimers = new ArrayList<>(); + private static final Timer ppStop = new Timer(1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + synchronized (allBlockingTimers) { + if (pp != null && allBlockingTimers.isEmpty()) { // System.out.println("stopping "+System.currentTimeMillis()); - pp.stop(); - pp = null; - } - ppStop.stop(); - } - } - }); - private static ProgressDialogListener cancelListener = new ProgressDialogListener() { - @Override - public void cancelButton_actionPerformed(EventObject newEvent) { - synchronized (allBlockingTimers) { - while(allBlockingTimers.size() > 0){ - allBlockingTimers.remove(0); - } - ppStop.restart(); - } - } - }; - private static class ALHelper implements ActionListener { - private ActionListener argActionListener; - private BlockingTimer argBlockingTimer; - public ALHelper(ActionListener argActionListener) { - super(); - this.argActionListener = argActionListener; - } - @Override - public void actionPerformed(ActionEvent e) { - String actionMessage = null; - synchronized (allBlockingTimers) { - //if I'm next in the list do my action else repeat timer - if(BlockingTimer.allBlockingTimers.get(0) == argBlockingTimer){ - actionMessage = BlockingTimer.allBlockingTimers.get(0).getMessage(); - }else{ - if(allBlockingTimers.contains(argBlockingTimer)){ - argBlockingTimer.start(); - } - } - } - if(actionMessage != null){ - if(pp != null){ - pp.setMessage(actionMessage); - } - argActionListener.actionPerformed(e); - - } - } - public void setBlockingTimer(BlockingTimer argBlockingTimer){ - this.argBlockingTimer = argBlockingTimer; - } - } - private String message; - public BlockingTimer(Component requester,int delay,String message){ - super(delay, new ALHelper(null)); - ((ALHelper)getActionListeners()[0]).setBlockingTimer(this); - ppStop.setRepeats(false); - setRepeats(false); - if(pp == null){ - pp = new AsynchProgressPopup(requester, "Waiting for actions to finish...", message, null, true, false,true,cancelListener); - pp.startKeepOnTop(); - } - synchronized (allBlockingTimers) { - allBlockingTimers.add(this); - } - } - public String getMessage(){ - return message; - } - @Override - public void start() { - // TODO Auto-generated method stub - super.start(); - } - @Override - public void stop() { - // TODO Auto-generated method stub - super.stop(); - synchronized (allBlockingTimers) { + pp.stop(); + pp = null; + } + ppStop.stop(); + } + } + }); + private static final ProgressDialogListener cancelListener = new ProgressDialogListener() { + @Override + public void cancelButton_actionPerformed(EventObject newEvent) { + synchronized (allBlockingTimers) { + while (!allBlockingTimers.isEmpty()) { + allBlockingTimers.remove(0); + } + ppStop.restart(); + } + } + }; + + private static class ALHelper implements ActionListener { + private final ActionListener argActionListener; + private BlockingTimer argBlockingTimer; + + public ALHelper(ActionListener argActionListener) { + super(); + this.argActionListener = argActionListener; + } + + @Override + public void actionPerformed(ActionEvent e) { + String actionMessage = null; + synchronized (allBlockingTimers) { + //if I'm next in the list do my action else repeat timer + if (BlockingTimer.allBlockingTimers.get(0) == this.argBlockingTimer) { + actionMessage = BlockingTimer.allBlockingTimers.get(0).getMessage(); + } else { + if (allBlockingTimers.contains(this.argBlockingTimer)) { + this.argBlockingTimer.start(); + } + } + } + if (actionMessage != null) { + if (pp != null) { + pp.setMessage(actionMessage); + } + this.argActionListener.actionPerformed(e); + + } + } + + public void setBlockingTimer(BlockingTimer argBlockingTimer) { + this.argBlockingTimer = argBlockingTimer; + } + } + + private String message; + + public BlockingTimer(Component requester, int delay, String message) { + super(delay, new ALHelper(null)); + ((ALHelper) this.getActionListeners()[0]).setBlockingTimer(this); + ppStop.setRepeats(false); + this.setRepeats(false); + if (pp == null) { + pp = new AsynchProgressPopup(requester, "Waiting for actions to finish...", message, null, true, false, true, cancelListener); + pp.startKeepOnTop(); + } + synchronized (allBlockingTimers) { + allBlockingTimers.add(this); + } + } + + public String getMessage() { + return this.message; + } + + @Override + public void start() { + // TODO Auto-generated method stub + super.start(); + } + + @Override + public void stop() { + // TODO Auto-generated method stub + super.stop(); + synchronized (allBlockingTimers) { // if(allBlockingTimers.size()>0 && allBlockingTimers.get(0) != BlockingTimer.this){ // System.err.println("Unexpected position of stopped Blockingtimer, not beginning of list"); // } - allBlockingTimers.remove(BlockingTimer.this); + allBlockingTimers.remove(BlockingTimer.this); // System.out.println("starting stop "+System.currentTimeMillis()); - ppStop.restart(); - } - } - private static void replace(BlockingTimer replaceThis, BlockingTimer withThis){ - synchronized (allBlockingTimers) { - replaceThis.stop(); - allBlockingTimers.add(withThis); - } - } -} -public static boolean isBusy(PDEDataContext busyPDEDatacontext1,PDEDataContext busyPDEDatacontext2){ - return ClientTaskDispatcher.isBusy() || (busyPDEDatacontext1 != null && busyPDEDatacontext1.isBusy()) || (busyPDEDatacontext2 != null && busyPDEDatacontext2.isBusy()); -} -public static BlockingTimer getBlockingTimer(Component requester,PDEDataContext busyPDEDatacontext1,PDEDataContext busyPDEDatacontext2,BlockingTimer activeTimerOld,ActionListener actionListener,String actionMessage){ - if(actionMessage == null){ - actionMessage = "no message..."; - } - if(isBusy(busyPDEDatacontext1,busyPDEDatacontext2)){ - BlockingTimer activeTimerNew = new BlockingTimer(requester,200,actionMessage); - if(activeTimerOld != null){ - BlockingTimer.replace(activeTimerOld, activeTimerNew); - } - ActionListener[] currentActionlListeners = activeTimerNew.getActionListeners(); - for (int i = 0; i < currentActionlListeners.length; i++) { - activeTimerNew.removeActionListener(currentActionlListeners[i]); - } - activeTimerNew.addActionListener(actionListener); + ppStop.restart(); + } + } + + private static void replace(BlockingTimer replaceThis, BlockingTimer withThis) { + synchronized (allBlockingTimers) { + replaceThis.stop(); + allBlockingTimers.add(withThis); + } + } + } + + public static boolean isBusy(PDEDataContext busyPDEDatacontext1, PDEDataContext busyPDEDatacontext2) { + return ClientTaskDispatcher.isBusy() || (busyPDEDatacontext1 != null && busyPDEDatacontext1.isBusy()) || (busyPDEDatacontext2 != null && busyPDEDatacontext2.isBusy()); + } + + public static BlockingTimer getBlockingTimer(Component requester, PDEDataContext busyPDEDatacontext1, PDEDataContext busyPDEDatacontext2, BlockingTimer activeTimerOld, ActionListener actionListener, String actionMessage) { + if (actionMessage == null) { + actionMessage = "no message..."; + } + if (isBusy(busyPDEDatacontext1, busyPDEDatacontext2)) { + BlockingTimer activeTimerNew = new BlockingTimer(requester, 200, actionMessage); + if (activeTimerOld != null) { + BlockingTimer.replace(activeTimerOld, activeTimerNew); + } + ActionListener[] currentActionlListeners = activeTimerNew.getActionListeners(); + for (int i = 0; i < currentActionlListeners.length; i++) { + activeTimerNew.removeActionListener(currentActionlListeners[i]); + } + activeTimerNew.addActionListener(actionListener); // if(activeTimerNew.isRunning()){ // System.err.println("----------getBlockingTimer: single fire timer should not be running"); // } - activeTimerNew.restart(); - return activeTimerNew; - }else if(activeTimerOld != null){ - activeTimerOld.stop(); - activeTimerOld = null; - } - return null; -} - -public enum StopStrategy { - THREAD_INTERRUPT, - @Deprecated THREAD_KILL -} - -public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, - final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, - final boolean cancelable, final ProgressDialogListener progressDialogListener, - final boolean bInputBlocking) { - ClientTaskDispatcher.dispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, - bInputBlocking, StopStrategy.THREAD_INTERRUPT); -} - - -public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, - final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, - final boolean cancelable, final ProgressDialogListener progressDialogListener, - final boolean bInputBlocking, final StopStrategy stopStrategy) { - // check tasks - swing non-blocking can be only at the end - entryCounter++; - if(entryCounter>1){ - System.out.println("Reentrant"); - } - -// if (bInProgress) { -// Thread.dumpStack(); -// } - if (lg.isInfoEnabled()) { - hash.put(STACK_TRACE_ARRAY, Thread.currentThread().getStackTrace()); - } - if (bShowProgressPopup && requester == null) { - System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); - } - - final List taskList = new ArrayList<>(); - - for (int i = 0; i < tasks.length; i++){ - if (tasks[i].getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING && i < tasks.length - 1) { - throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); - } - taskList.add(tasks[i]); - if (lg.isDebugEnabled()) { - lg.debug("added task name " + tasks[i].getTaskName()); - } - } - - final String threadBaseName = "ClientTaskDispatcher " + ( serial++ ) + ' '; - // dispatch tasks to a new worker - SwingWorker worker = new SwingWorker() { - private AsynchProgressPopup pp = null; - private Window windowParent = null; - private Component focusOwner = null; - public Object construct() { - if (bShowProgressPopup) { - if (customDialog == null) { - pp = new AsynchProgressPopup(requester, "WORKING...", "Initializing request", Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } else { - pp = new AsynchProgressPopup(requester, customDialog, Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } - pp.setStopStrategy(stopStrategy); - if (bInputBlocking) { - pp.startKeepOnTop(); - } else { - pp.start(); - } - } - if (requester != null) { - windowParent = GuiUtils.getWindowForComponent(requester); - } - try { - if (windowParent != null) { - focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - ClientMDIManager.blockWindow(windowParent); - windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - } - }); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - for (int i = 0; i < taskList.size(); i++){ - // run all tasks - // after abort, run only non-skippable tasks - // also skip selected tasks specified by conditionalSkip tag - final AsynchClientTask currentTask = taskList.get(i); - try { - currentTask.setClientTaskStatusSupport(pp); - setSwingWorkerThreadName(this,threadBaseName + currentTask.getTaskName()); - - //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); - if (pp != null ) { - pp.setVisible(currentTask.showProgressPopup()); - if(!bKnowProgress) - { - pp.setProgress(i*100/taskList.size()); // beginning of task - } - pp.setMessage(currentTask.getTaskName()); - } - boolean shouldRun = !hash.containsKey(HASH_DATA_ERROR); - if (hash.containsKey(TASK_ABORTED_BY_ERROR) && currentTask.skipIfAbort()) { - shouldRun = false; - } - if (hash.containsKey(TASKS_TO_BE_SKIPPED)) { - String[] toSkip = (String[])hash.get(TASKS_TO_BE_SKIPPED); - if (ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName())) { - shouldRun = false; - } - } - if (pp != null && pp.isInterrupted()) { - recordException(UserCancelException.CANCEL_GENERIC, hash); - } - - if (hash.containsKey(TASK_ABORTED_BY_USER)) { - UserCancelException exc = (UserCancelException)hash.get(TASK_ABORTED_BY_USER); - if (currentTask.skipIfCancel(exc)) { - shouldRun = false; - } - } - if (shouldRun) { - try { - if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - runTask(currentTask,hash, taskList); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - try { - runTask(currentTask,hash, taskList); - } catch (Throwable exc) { - recordException(exc, hash); - } - } - }); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - try { - runTask(currentTask,hash, taskList); - } catch (Throwable exc) { - recordException(exc, hash); - } - } - }); - } - } catch (Throwable exc) { - recordException(exc, hash); - } - } - // AsynchClientTask[] followupTasks = currentTask.getFollowupTasks(); - // if (followupTasks != null) { - // for (int j = 0; j < followupTasks.length; j++) { - // taskList.add(i+j+1, followupTasks[j]); - // } - // } - } - finally { - allTasks.remove(currentTask); - } + activeTimerNew.restart(); + return activeTimerNew; + } else if (activeTimerOld != null) { + activeTimerOld.stop(); + activeTimerOld = null; + } + return null; + } + + public enum StopStrategy { + THREAD_INTERRUPT, + @Deprecated THREAD_KILL + } + + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, + bInputBlocking, StopStrategy.THREAD_INTERRUPT); + } + + + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy) { + final String threadBaseName = "ClientTaskDispatcher " + (serial++) + ' '; + final List taskList = new ArrayList<>(); + + // check tasks - swing non-blocking can be only at the end + ClientTaskDispatcher.entryCounter++; + if (ClientTaskDispatcher.entryCounter > 1) lg.debug("Reentrant: {}", ClientTaskDispatcher.entryCounter); + + // if (bInProgress) { + // Thread.dumpStack(); + // } + if (lg.isInfoEnabled()) hash.put(STACK_TRACE_ARRAY, Thread.currentThread().getStackTrace()); + + if (bShowProgressPopup && requester == null) { + System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); + Thread.dumpStack(); + } + + for (AsynchClientTask task : tasks){ + if (AsynchClientTask.TASKTYPE_SWING_NONBLOCKING== task.getTaskType() && taskList.size() + 1 != tasks.length) { + throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); } - return hash; + taskList.add(task); + lg.debug("added task name {}", task.getTaskName()); } - - public void finished() { -//System.out.println("DISPATCHING: finished() called at "+ new Date(System.currentTimeMillis())); - entryCounter--; -// System.out.println("----------Leave----------entryCounter="+entryCounter); - - if (pp != null) { - pp.stop(); - } - if (hash.containsKey(TASK_ABORTED_BY_ERROR)) { - // something went wrong - StringBuffer allCausesErrorMessageSB = new StringBuffer(); - Throwable causeError = (Throwable)hash.get(TASK_ABORTED_BY_ERROR); - do{ - allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-").append(causeError.getMessage() == null || causeError.getMessage().length() == 0 ? "" : causeError.getMessage()); - allCausesErrorMessageSB.append("\n"); - }while((causeError = causeError.getCause()) != null); - if (requester == null) { - System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); - } - if (lg.isInfoEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - String stackTraceString = StringUtils.join(ste,'\n'); - lg.info(stackTraceString,(Throwable)hash.get(TASK_ABORTED_BY_ERROR)); - } - else { - lg.info("Unexpected " + STACK_TRACE_ARRAY + " obj " + obj); - } - } - PopupGenerator.showErrorDialog(requester, allCausesErrorMessageSB.toString(), (Throwable)hash.get(TASK_ABORTED_BY_ERROR)); - } else if (hash.containsKey(TASK_ABORTED_BY_USER)) { - // depending on where user canceled we might want to automatically start a new job - dispatchFollowUp(hash); - } - - FinalWindow fw = AsynchClientTask.fetch(hash, FINAL_WINDOW,FinalWindow.class,false); - if (lg.isDebugEnabled() && fw != null) { - lg.debug("FinalWindow retrieved from hash"); - } - //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocatoin - if (windowParent != null) { - ClientMDIManager.unBlockWindow(windowParent); - windowParent.setCursor(Cursor.getDefaultCursor()); - if (fw == null && focusOwner != null) { - fw = () -> { windowParent.requestFocusInWindow(); focusOwner.requestFocusInWindow(); }; - if (lg.isDebugEnabled()) { - lg.debug("FinalWindow built from " + windowParent.toString() + " and " + focusOwner.toString()); - } - } - } - if (fw != null) { - if (lg.isDebugEnabled()) { - lg.debug("scheduling " + fw.getClass().getName() + ".run on " + fw.toString()); - SwingUtilities.invokeLater(debugWrapper(fw)); - } - else { - SwingUtilities.invokeLater(fw); - } - } - else { - lg.debug("no Final Window"); - } -// BeanUtils.setCursorThroughout(frameParent, Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); -//System.out.println("DISPATCHING: done at "+ new Date(System.currentTimeMillis())); - } - }; - setSwingWorkerThreadName(worker,threadBaseName); - allTasks.addAll(taskList); - worker.start(); -} - -/** - * wrap runnable in debug print statement - * @param r payload - * @return wrapper - */ -private static Runnable debugWrapper(Runnable r) { - Runnable wrapper = () -> - { - lg.debug("calling " + r.getClass().getName() + ".run on " + r.toString()); - r.run(); - }; - return wrapper; -} - - - -/** - * Insert the method's description here. - * Creation date: (6/1/2004 8:58:38 PM) - * @param hash java.util.Hashtable - */ -private static void dispatchFollowUp(Hashtable hash) { - // - // we deal with a task dispatch that aborted due to some user choice on prompts - // - UserCancelException e = (UserCancelException)hash.get("cancel"); - if (e == UserCancelException.CHOOSE_SAVE_AS) { - // user chose to save as during a save or save/edition of a documnet found to be unchanged - ((DocumentWindowManager)hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); - } -} - - -/** - * Insert the method's description here. - * Creation date: (5/28/2004 2:17:22 AM) - * @param exc java.lang.Exception - */ -public static void recordException(Throwable exc, Hashtable hash) { - lg.error(exc.getMessage(), exc); - if (exc instanceof UserCancelException) { - hash.put(TASK_ABORTED_BY_USER, exc); - } else { - exc.printStackTrace(System.out); - hash.put(TASK_ABORTED_BY_ERROR, exc); - } -} - -/** - * @return list of outstanding tasks, or empty set if none - */ -public static Collection outstandingTasks( ) { - if (allTasks.isEmpty()) { - return Collections.emptyList(); - } - - synchronized(allTasks) { - List taskNames = new ArrayList<>(); - for (AsynchClientTask ct : allTasks) { - String tn = ct.getTaskName(); - taskNames.add(tn); - } - return taskNames; - } -} - -/** - * @return true if there are uncompleted tasks - */ -public static boolean hasOutstandingTasks( ) { - return !allTasks.isEmpty(); -} -/** - * convert Collection to array - * @param coll - * @return new array - */ -private static AsynchClientTask[] collToArray(Collection coll) { - return coll.toArray(new AsynchClientTask[coll.size()]); -} -//updated API -public static void dispatchColl(Component requester, Hashtable hash, Collection coll) { - dispatch(requester,hash,collToArray(coll)); -} - -public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { - dispatch(requester,hash,collToArray(coll),bKnowProgress); -} - -public static void dispatchColl(Component requester, Hashtable hash, Collectioncoll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener) { - dispatch(requester, hash, collToArray(coll) ,bKnowProgress,cancelable,progressDialogListener); -} - -public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - dispatch(requester, hash, collToArray(coll) ,bKnowProgress,cancelable,progressDialogListener,bInputBlocking); -} - -public static void dispatchColl(final Component requester, final Hashtable hash, Collectioncoll, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - dispatch(requester, hash, collToArray(coll) ,bShowProgressPopup,bKnowProgress,cancelable,progressDialogListener,bInputBlocking); -} - -/** - * Insert the method's description here. - * Creation date: (5/31/2004 5:37:06 PM) - * @param tasks cbit.vcell.desktop.controls.ClientTask[] - */ -public static void dispatchColl(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { -} - - - -/** - * set {@link SwingWorker} thread name - * @param sw - * @param name may not be null - * @throws IllegalArgumentException if name is null - */ -private static void setSwingWorkerThreadName(SwingWorker sw, String name) { - if (name != null ) { - try { - Field threadVarField = SwingWorker.class.getDeclaredField("threadVar"); - threadVarField.setAccessible(true); - Object threadVar = threadVarField.get(sw); - Field threadField = threadVar.getClass().getDeclaredField("thread"); - threadField.setAccessible(true); - Thread thread = (Thread) threadField.get(threadVar); - thread.setName(name); - } - catch (NoSuchFieldException | SecurityException | IllegalAccessException e) { - lg.warn("setSwingWorkerName fail", e); - } - return; - } - throw new IllegalArgumentException("name may not be null"); -} - -/** - * call currentTask.run(hash) with log4j logging; check for required keys - * @param currentTask not null - * @param hash not null - * @param taskList current set of tasks being dispatched - * @throws Exception - */ -private static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { - if (lg.isDebugEnabled()) { - String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); - if (lg.isDebugEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - msg += '\n' + StringUtils.join(ste,'\n'); - } - lg.debug(msg); - } - else { - lg.debug(msg); - } - } - //check required elements present - StringBuilder sb = null; - for (KeyInfo requiredKey : currentTask.requiredKeys()) { - Object obj = hash.get(requiredKey.name); - if (obj == null) { - if (sb == null) sb = initStringBuilder(currentTask) ; - sb.append("Missing required key ").append(requiredKey.name).append('\n'); - continue; - } - Class foundClass = obj.getClass(); - if (!requiredKey.clzz.isAssignableFrom(foundClass)) { - if (sb == null) sb = initStringBuilder(currentTask) ; - sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); - sb.append('\n'); - } - } - - if (sb == null) { //no problems found - currentTask.run(hash); - return; - } - - sb.append("Prior tasks\n"); - for ( AsynchClientTask pt : taskList) { - if (pt == currentTask) { - break; - } - sb.append('\t').append(pt.getTaskName()).append('\n'); - } - hash.put(HASH_DATA_ERROR,HASH_DATA_ERROR); - throw new ProgrammingException(sb.toString()); -} - -/** - * @param currentTask non null - * @return {@link StringBuilder} initialized with task name - */ -private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { - StringBuilder sb = new StringBuilder(); - sb.append("Data error for task " + currentTask.getTaskName() + '\n'); - return sb; -} + // dispatch tasks to a new worker + SwingWorker worker = new SwingWorker() { + private AsynchProgressPopup pp = null; + private Window windowParent = null; + private Component focusOwner = null; + + public Object construct() { + if (bShowProgressPopup) { + if (customDialog == null) { + this.pp = new AsynchProgressPopup(requester, "WORKING...", "Initializing request", Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); + } else { + this.pp = new AsynchProgressPopup(requester, customDialog, Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); + } + this.pp.setStopStrategy(stopStrategy); + if (bInputBlocking) { + this.pp.startKeepOnTop(); + } else { + this.pp.start(); + } + } + if (requester != null) this.windowParent = GuiUtils.getWindowForComponent(requester); + + try { + if (this.windowParent != null) { + Window targetWindow = this.windowParent; + this.focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + SwingUtilities.invokeAndWait(() -> { + ClientMDIManager.blockWindow(targetWindow); + targetWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + } + } catch (InterruptedException | InvocationTargetException e) { + lg.warn(e); + } + for (int i = 0; i < taskList.size(); i++) { + // run all tasks + // after abort, run only non-skippable tasks + // also skip selected tasks specified by conditionalSkip tag + final AsynchClientTask currentTask = taskList.get(i); + try { + currentTask.setClientTaskStatusSupport(this.pp); + ClientTaskDispatcher.setSwingWorkerThreadName(this, threadBaseName + currentTask.getTaskName()); + + //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); + if (this.pp != null) { + this.pp.setVisible(currentTask.showProgressPopup()); + if (!bKnowProgress) { + this.pp.setProgress(i * 100 / taskList.size()); // beginning of task + } + this.pp.setMessage(currentTask.getTaskName()); + } + boolean shouldRun = !hash.containsKey(HASH_DATA_ERROR); + if (hash.containsKey(TASK_ABORTED_BY_ERROR) && currentTask.skipIfAbort()) { + shouldRun = false; + } + if (hash.containsKey(TASKS_TO_BE_SKIPPED)) { + String[] toSkip = (String[]) hash.get(TASKS_TO_BE_SKIPPED); + boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); + if (taskShouldBeSkipped) shouldRun = false; + } + if (this.pp != null && this.pp.isInterrupted()) { + ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, hash); + } + + if (hash.containsKey(TASK_ABORTED_BY_USER)) { + UserCancelException exc = (UserCancelException) hash.get(TASK_ABORTED_BY_USER); + if (currentTask.skipIfCancel(exc)) shouldRun = false; + } + if (shouldRun) { + try { + if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + ClientTaskDispatcher.runTask(currentTask, hash, taskList); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + SwingUtilities.invokeAndWait(() -> { + try { + ClientTaskDispatcher.runTask(currentTask, hash, taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, hash); + } + }); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + SwingUtilities.invokeLater(() -> { + try { + ClientTaskDispatcher.runTask(currentTask, hash, taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, hash); + } + }); + } + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, hash); + } + } + } finally { + ClientTaskDispatcher.allTasks.remove(currentTask); + } + } + return hash; + } + + public void finished() { + ClientTaskDispatcher.entryCounter--; + + if (this.pp != null) { + this.pp.stop(); + } + if (hash.containsKey(TASK_ABORTED_BY_ERROR)) { + // something went wrong + StringBuilder allCausesErrorMessageSB = new StringBuilder(); + Throwable causeError = (Throwable) hash.get(TASK_ABORTED_BY_ERROR); + do { + allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-") + .append(causeError.getMessage() == null || causeError.getMessage().isEmpty() ? + "" : causeError.getMessage()); + allCausesErrorMessageSB.append("\n"); + } while ((causeError = causeError.getCause()) != null); + if (requester == null) { + lg.warn("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); + Thread.dumpStack(); + } + if (lg.isInfoEnabled()) { + Object obj = hash.get(STACK_TRACE_ARRAY); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + String stackTraceString = StringUtils.join(ste, '\n'); + lg.info(stackTraceString, (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); + } else { + lg.info("Unexpected {} obj {}", STACK_TRACE_ARRAY, obj); + } + } + PopupGenerator.showErrorDialog(requester, allCausesErrorMessageSB.toString(), + (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); + } else if (hash.containsKey(TASK_ABORTED_BY_USER)) { + // depending on where user canceled we might want to automatically start a new job + ClientTaskDispatcher.dispatchFollowUp(hash); + } + + FinalWindow fw = AsynchClientTask.fetch(hash, FINAL_WINDOW, FinalWindow.class, false); + if (lg.isDebugEnabled() && fw != null) { + lg.debug("FinalWindow retrieved from hash"); + } + //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocation + if (this.windowParent != null) { + ClientMDIManager.unBlockWindow(this.windowParent); + this.windowParent.setCursor(Cursor.getDefaultCursor()); + if (fw == null && this.focusOwner != null) { + fw = () -> { + this.windowParent.requestFocusInWindow(); + this.focusOwner.requestFocusInWindow(); + }; + lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); + } + } + if (fw != null) { + lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); + Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; + SwingUtilities.invokeLater(runnable); + } else { + lg.debug("no Final Window"); + } + } + }; + setSwingWorkerThreadName(worker, threadBaseName); + allTasks.addAll(taskList); + worker.start(); + } + + /** + * wrap runnable in debug print statement + * + * @param r payload + * @return wrapper + */ + private static Runnable debugWrapper(Runnable r) { + return () -> + { + lg.debug("calling " + r.getClass().getName() + ".run on " + r); + r.run(); + }; + } + + private static void dispatchFollowUp(Hashtable hash) { + // we deal with a task dispatch that aborted due to some user choice on prompts + UserCancelException e = (UserCancelException) hash.get("cancel"); + if (e == UserCancelException.CHOOSE_SAVE_AS) { + // user chose to save as during a save or save/edition of a document found to be unchanged + ((DocumentWindowManager) hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); + } + } + + public static void recordException(Throwable exc, Hashtable hash) { + lg.error(exc.getMessage(), exc); + if (exc instanceof UserCancelException userCancelException) { + hash.put(TASK_ABORTED_BY_USER, userCancelException); + } else { + exc.printStackTrace(System.out); + hash.put(TASK_ABORTED_BY_ERROR, exc); + } + } + + /** + * @return list of outstanding tasks, or empty set if none + */ + public static Collection outstandingTasks() { + if (ClientTaskDispatcher.allTasks.isEmpty()) return Collections.emptyList(); + + + synchronized (ClientTaskDispatcher.allTasks) { + List taskNames = new ArrayList<>(); + for (AsynchClientTask ct : ClientTaskDispatcher.allTasks) { + String tn = ct.getTaskName(); + taskNames.add(tn); + } + return taskNames; + } + } + + /** + * @return true if there are uncompleted tasks + */ + public static boolean hasOutstandingTasks() { + return !ClientTaskDispatcher.allTasks.isEmpty(); + } + + //updated API + public static void dispatchColl(Component requester, Hashtable hash, Collection coll) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new)); + } + + public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress); + } + + public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener); + } + + public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchColl(final Component requester, final Hashtable hash, Collection coll, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchColl(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + } + + + /** + * set {@link SwingWorker} thread name + * + * @param sw + * @param name may not be null + * @throws IllegalArgumentException if name is null + */ + private static void setSwingWorkerThreadName(SwingWorker sw, String name) { + if (name != null) { + try { + Field threadVarField = SwingWorker.class.getDeclaredField("threadVar"); + threadVarField.setAccessible(true); + Object threadVar = threadVarField.get(sw); + Field threadField = threadVar.getClass().getDeclaredField("thread"); + threadField.setAccessible(true); + Thread thread = (Thread) threadField.get(threadVar); + thread.setName(name); + } catch (NoSuchFieldException | SecurityException | IllegalAccessException e) { + lg.warn("setSwingWorkerName fail", e); + } + return; + } + throw new IllegalArgumentException("name may not be null"); + } + + /** + * call currentTask.run(hash) with log4j logging; check for required keys + * + * @param currentTask not null + * @param hash not null + * @param taskList current set of tasks being dispatched + * @throws Exception + */ + private static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { + if (lg.isDebugEnabled()) { + String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); + if (lg.isDebugEnabled()) { + Object obj = hash.get(STACK_TRACE_ARRAY); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + msg += '\n' + StringUtils.join(ste, '\n'); + } + lg.debug(msg); + } else { + lg.debug(msg); + } + } + //check required elements present + StringBuilder sb = null; + for (KeyInfo requiredKey : currentTask.requiredKeys()) { + Object obj = hash.get(requiredKey.name); + if (obj == null) { + if (sb == null) sb = initStringBuilder(currentTask); + sb.append("Missing required key ").append(requiredKey.name).append('\n'); + continue; + } + Class foundClass = obj.getClass(); + if (!requiredKey.clzz.isAssignableFrom(foundClass)) { + if (sb == null) sb = initStringBuilder(currentTask); + sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); + sb.append('\n'); + } + } + + if (sb == null) { //no problems found + currentTask.run(hash); + return; + } + + sb.append("Prior tasks\n"); + for (AsynchClientTask pt : taskList) { + if (pt == currentTask) { + break; + } + sb.append('\t').append(pt.getTaskName()).append('\n'); + } + hash.put(HASH_DATA_ERROR, HASH_DATA_ERROR); + throw new ProgrammingException(sb.toString()); + } + + /** + * @param currentTask non null + * @return {@link StringBuilder} initialized with task name + */ + private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { + StringBuilder sb = new StringBuilder(); + sb.append("Data error for task " + currentTask.getTaskName() + '\n'); + return sb; + } + + //package + interface FinalWindow extends Runnable { + } + + /** + * set final window in hash + * + * @param hash non null + * @param fWindow non null + * @throws ProgrammingException if more than one set in the same hash + * @see AsynchClientTask#setFinalWindow(Hashtable, cbit.vcell.client.ChildWindowManager.ChildWindow) + * @see AsynchClientTask#setFinalWindow(Hashtable, java.awt.Container) + */ //package -interface FinalWindow extends Runnable{ -} - -/** - * set final window in hash - * @param hash non null - * @param fWindow non null - * @throws ProgrammingException if more than one set in the same hash - * @see AsynchClientTask#setFinalWindow(Hashtable, cbit.vcell.client.ChildWindowManager.ChildWindow) - * @see AsynchClientTask#setFinalWindow(Hashtable, java.awt.Container) - */ -//package -static void setFinalWindow(Hashtable hash, FinalWindow fWindow) { - if (!hash.contains(FINAL_WINDOW)) { - hash.put(FINAL_WINDOW, fWindow); - return; - } - Object existing = hash.get(FINAL_WINDOW); - final String def = "null"; - String e = ClassUtils.getShortClassName(existing ,def); - String n = ClassUtils.getShortClassName(fWindow ,def); - throw new ProgrammingException("duplicate final windows" + e + " and " + n); -} - + static void setFinalWindow(Hashtable hash, FinalWindow fWindow) { + if (!hash.contains(FINAL_WINDOW)) { + hash.put(FINAL_WINDOW, fWindow); + return; + } + Object existing = hash.get(FINAL_WINDOW); + final String def = "null"; + String e = ClassUtils.getShortClassName(existing, def); + String n = ClassUtils.getShortClassName(fWindow, def); + throw new ProgrammingException("duplicate final windows" + e + " and " + n); + } } From 337ac53e3088aba8b73a9883d3f36f176628d428 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 11:02:37 -0400 Subject: [PATCH 04/48] Create instance of SwingWorker to help separate responsibility. --- .../src/main/java/swingthreads/ClientSwingWorker.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 vcell-client/src/main/java/swingthreads/ClientSwingWorker.java diff --git a/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java b/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java new file mode 100644 index 0000000000..4da654151d --- /dev/null +++ b/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java @@ -0,0 +1,11 @@ +package swingthreads; + +public class ClientSwingWorker extends SwingWorker { + /** + * Compute the value to be returned by the get method. + */ + @Override + public Object construct() { + return null; + } +} From 75f702bb0723de121484eac422f116dbccab543b Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 11:03:42 -0400 Subject: [PATCH 05/48] Clean-up SwingWorker --- .../main/java/swingthreads/SwingWorker.java | 77 +++++++++++-------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index 8675ab0f7e..4cc3f6e28f 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -7,9 +7,9 @@ * SwingWorker 3), an abstract class that you subclass to * perform GUI-related work in a dedicated thread. For * instructions on using this class, see: - * + *

* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html - * + *

* Note that the API changed slightly in the 3rd version: * You must now invoke start() on the SwingWorker after * creating it. @@ -18,36 +18,45 @@ public abstract class SwingWorker { private Object value; // see getValue(), setValue() private Thread thread; - /** + /** * Class to maintain reference to current worker thread * under separate synchronization control. */ private static class ThreadVar { private Thread thread; - ThreadVar(Thread t) { thread = t; } - synchronized Thread get() { return thread; } - synchronized void clear() { thread = null; } + + ThreadVar(Thread t) { + this.thread = t; + } + + synchronized Thread get() { + return this.thread; + } + + synchronized void clear() { + this.thread = null; + } } - private ThreadVar threadVar; + private final ThreadVar threadVar; - /** - * Get the value produced by the worker thread, or null if it + /** + * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ - protected synchronized Object getValue() { - return value; + protected synchronized Object getValue() { + return this.value; } - /** - * Set the value produced by worker thread + /** + * Set the value produced by worker thread */ - private synchronized void setValue(Object x) { - value = x; + private synchronized void setValue(Object x) { + this.value = x; } - /** - * Compute the value to be returned by the get method. + /** + * Compute the value to be returned by the get method. */ public abstract Object construct(); @@ -63,30 +72,29 @@ public void finished() { * to force the worker to stop what it's doing. */ public void interrupt() { - Thread t = threadVar.get(); + Thread t = this.threadVar.get(); if (t != null) { t.interrupt(); } - threadVar.clear(); + this.threadVar.clear(); } /** - * Return the value created by the construct method. + * Return the value created by the construct method. * Returns null if either the constructing thread or the current * thread was interrupted before a value was produced. - * + * * @return the value created by the construct method */ public Object get() { - while (true) { - Thread t = threadVar.get(); + while (true) { + Thread t = this.threadVar.get(); if (t == null) { - return getValue(); + return this.getValue(); } try { t.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); // propagate return null; } @@ -100,16 +108,17 @@ public Object get() { */ public SwingWorker() { final Runnable doFinished = new Runnable() { - public void run() { finished(); } + public void run() { + SwingWorker.this.finished(); + } }; - Runnable doConstruct = new Runnable() { + Runnable doConstruct = new Runnable() { public void run() { try { - setValue(construct()); - } - finally { - threadVar.clear(); + SwingWorker.this.setValue(SwingWorker.this.construct()); + } finally { + SwingWorker.this.threadVar.clear(); } SwingUtilities.invokeLater(doFinished); @@ -117,14 +126,14 @@ public void run() { }; Thread t = new Thread(doConstruct); - threadVar = new ThreadVar(t); + this.threadVar = new ThreadVar(t); } /** * Start the worker thread. */ public void start() { - Thread t = threadVar.get(); + Thread t = this.threadVar.get(); if (t != null) { t.start(); } From d126ca01492f6e02506ab8853ad12690790a24c5 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 11:16:09 -0400 Subject: [PATCH 06/48] Cleaning up Swing Worker logic Part 1 --- ...ngWorker.java => StandardSwingWorker.java} | 2 +- .../main/java/swingthreads/SwingWorker.java | 25 ++++++------------- 2 files changed, 8 insertions(+), 19 deletions(-) rename vcell-client/src/main/java/swingthreads/{ClientSwingWorker.java => StandardSwingWorker.java} (77%) diff --git a/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java similarity index 77% rename from vcell-client/src/main/java/swingthreads/ClientSwingWorker.java rename to vcell-client/src/main/java/swingthreads/StandardSwingWorker.java index 4da654151d..bb0dddc289 100644 --- a/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java @@ -1,6 +1,6 @@ package swingthreads; -public class ClientSwingWorker extends SwingWorker { +public class StandardSwingWorker extends SwingWorker { /** * Compute the value to be returned by the get method. */ diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index 4cc3f6e28f..f0f488d1fa 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -15,9 +15,6 @@ * creating it. */ public abstract class SwingWorker { - private Object value; // see getValue(), setValue() - private Thread thread; - /** * Class to maintain reference to current worker thread * under separate synchronization control. @@ -38,6 +35,8 @@ synchronized void clear() { } } + // Instance Variables + private Object value; // see getValue(), setValue() private final ThreadVar threadVar; /** @@ -64,8 +63,7 @@ private synchronized void setValue(Object x) { * Called on the event dispatching thread (not on the worker thread) * after the construct method has returned. */ - public void finished() { - } + public void finished() {} /** * A new method that interrupts the worker thread. Call this method @@ -73,9 +71,7 @@ public void finished() { */ public void interrupt() { Thread t = this.threadVar.get(); - if (t != null) { - t.interrupt(); - } + if (t != null) t.interrupt(); this.threadVar.clear(); } @@ -89,9 +85,8 @@ public void interrupt() { public Object get() { while (true) { Thread t = this.threadVar.get(); - if (t == null) { - return this.getValue(); - } + if (t == null) return this.getValue(); + try { t.join(); } catch (InterruptedException e) { @@ -101,17 +96,12 @@ public Object get() { } } - /** * Start a thread that will call the construct method * and then exit. */ public SwingWorker() { - final Runnable doFinished = new Runnable() { - public void run() { - SwingWorker.this.finished(); - } - }; + final Runnable doFinished = SwingWorker.this::finished; Runnable doConstruct = new Runnable() { public void run() { @@ -120,7 +110,6 @@ public void run() { } finally { SwingWorker.this.threadVar.clear(); } - SwingUtilities.invokeLater(doFinished); } }; From 05c82ab800f22079feb67b19a8ed505159f387fe Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 13:31:01 -0400 Subject: [PATCH 07/48] Separate anonymous SwingWorker instance into independent class Some inversion of control was implemented --- .../cbit/vcell/client/ClientSimManager.java | 5 +- .../vcell/client/data/KymographPanel.java | 4 +- .../vcell/client/data/SimResultsViewer.java | 5 +- .../vcell/client/task/AsynchClientTask.java | 44 +-- .../cbit/vcell/client/task/ChooseFile.java | 2 +- .../client/task/ClientTaskDispatcher.java | 327 ++---------------- .../vcell/client/task/DeleteOldDocument.java | 6 +- .../vcell/client/task/ExportDocument.java | 8 +- .../vcell/client/task/ResultsHashUtils.java | 52 +++ .../swingthreads/StandardSwingWorker.java | 291 +++++++++++++++- .../main/java/swingthreads/SwingWorker.java | 21 ++ .../main/java/swingthreads/TaskEventKeys.java | 24 ++ 12 files changed, 432 insertions(+), 357 deletions(-) create mode 100644 vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java create mode 100644 vcell-client/src/main/java/swingthreads/TaskEventKeys.java diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java index 400ef6ad28..0432bc61fc 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java @@ -20,11 +20,11 @@ import cbit.vcell.client.desktop.simulation.SimulationWindow; import cbit.vcell.client.desktop.simulation.SimulationWindow.LocalState; import cbit.vcell.client.desktop.simulation.SimulationWorkspace; -import cbit.vcell.client.server.ClientServerManager; import cbit.vcell.client.server.UserPreferences; import cbit.vcell.client.task.AsynchClientTask; import cbit.vcell.client.task.AsynchClientTaskFunction; import cbit.vcell.client.task.ClientTaskDispatcher; +import cbit.vcell.client.task.ResultsHashUtils; import cbit.vcell.export.server.ExportServiceImpl; import cbit.vcell.field.FieldDataIdentifierSpec; import cbit.vcell.mapping.SimulationContext; @@ -33,7 +33,6 @@ import cbit.vcell.messaging.server.SimulationTask; import cbit.vcell.parser.ExpressionException; import cbit.vcell.resource.ResourceUtil; -import cbit.vcell.server.DataSetController; import cbit.vcell.server.SimulationStatus; import cbit.vcell.simdata.*; import cbit.vcell.solver.*; @@ -402,7 +401,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask displayResultsTask = new AsynchClientTask("Showing results", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { @SuppressWarnings("unchecked") public void run(Hashtable hashTable) throws Exception { - boolean isLocal = fetch(hashTable,H_LOCAL_SIM,Boolean.class,true); + boolean isLocal = ResultsHashUtils.fetch(hashTable,H_LOCAL_SIM,Boolean.class,true); SimulationWindow.LocalState localState = isLocal ? LocalState.LOCAL : LocalState.SERVER; Hashtable failures = (Hashtable)hashTable.get(H_FAILURES); Simulation[] simsToShow = (Simulation[])hashTable.get("simsArray"); diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java b/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java index 9b93a06817..8515cfa7be 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java @@ -47,6 +47,8 @@ import cbit.vcell.simdata.DataIdentifier; import cbit.vcell.simdata.SimDataConstants; import cbit.vcell.simdata.gui.PdeTimePlotMultipleVariablesPanel.MultiTimePlotHelper; +import swingthreads.TaskEventKeys; + /** * Insert the type's description here. * Creation date: (12/14/2004 9:38:13 AM) @@ -2039,7 +2041,7 @@ public void run(Hashtable hashTable) throws Exception { Throwable timeSeriesJobFailed = (Throwable)hashTable.get(PDEDataViewer.StringKey_timeSeriesJobException); if (timeSeriesJobFailed == null) { - timeSeriesJobFailed = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_USER); + timeSeriesJobFailed = (Throwable)hashTable.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()); } if (failMethod(timeSeriesJobFailed, dataIdentifer)) { return; diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java b/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java index 59a2fe642a..7009a001fa 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java @@ -29,6 +29,7 @@ import org.vcell.util.DataAccessException; import org.vcell.util.UserCancelException; import org.vcell.util.document.VCDataIdentifier; +import swingthreads.TaskEventKeys; import javax.swing.*; import javax.swing.event.ListSelectionListener; @@ -446,7 +447,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask task2 = new AsynchClientTask("show results", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null && hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_USER) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null && hashTable.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()) == null) { ODEDataManager odeDatamanager = (ODEDataManager)hashTable.get("odeDatamanager"); odeDataViewer.setOdeSolverResultSet(odeDatamanager.getODESolverResultSet()); odeDataViewer.setVcDataIdentifier(vcdid); @@ -477,7 +478,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask task2 = new AsynchClientTask("show results", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null) { ClientPDEDataContext newPDEDC = (ClientPDEDataContext)hashTable.get("newPDEDC"); pdeDataViewer.setPdeDataContext(newPDEDC); pdeDataViewer.setSimNameSimDataID(new ExportSpecs.SimNameSimDataID(getSimulation().getName(), getSimulation().getSimulationInfo().getAuthoritativeVCSimulationIdentifier(), ExportSpecs.getParamScanInfo(getSimulation(), vcdid.getJobIndex()))); diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java index 5bc2913d6f..bcf90f3f7e 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java @@ -20,7 +20,6 @@ import org.vcell.util.ClientTaskStatusSupport; import org.vcell.util.ProgrammingException; import org.vcell.util.UserCancelException; -import org.vcell.util.VCAssert; import org.vcell.util.gui.GuiUtils; import cbit.vcell.client.ChildWindowManager.ChildWindow; @@ -92,45 +91,6 @@ public final boolean skipIfAbort() { public ClientTaskStatusSupport getClientTaskStatusSupport() { return clientTaskStatusSupport; } - - /** - * fetch and type convert object from hash - * @param hashTable not null - * @param key name (not null) - * @param clzz required type, not null - * @param required throw exception if required and not present - * @return object cast to correct type or possibly null if !required - * @throws ProgrammingException if key not of required type - * @throws ProgrammingException required is true and key not present - */ - @SuppressWarnings("unchecked") - static protected T fetch(Hashtable hashTable, String key, Class clzz, boolean required) { - Object obj = hashTable.get(key); - if (obj != null) { - Class oclzz = obj.getClass(); - if (clzz.isAssignableFrom(oclzz)) { - return (T) obj; - } - throw new ProgrammingException("object " + obj + " of type " + oclzz.getName() + " not instance of " + clzz.getName()); - } - if (required) { - throw new ProgrammingException("key " + key + " not found in async hashtable"); - } - return null; - } - - /** - * typesafe (verified) fetch of object from hash - * @param hashTable non null - * @param keyInfo non null - * @return object of correct type - */ - static protected Object fetch(Hashtable hashTable, KeyInfo keyInfo) { - Object obj = hashTable.get(keyInfo.name); - VCAssert.assertTrue(obj != null, "ClientTaskDispatcher failed to verify object"); - VCAssert.assertTrue(keyInfo.clzz.isAssignableFrom(obj.getClass()),"ClientTaskDispatcher failed to verify type"); - return obj; - } /** * Insert the method's description here. @@ -189,7 +149,7 @@ protected void setFinalWindow(Hashtable hashTable,Container cntr * return list of keys need by task * @return non-null Collection */ - protected Collection requiredKeys( ) { + public Collection requiredKeys( ) { return Collections.emptyList(); } @@ -198,7 +158,7 @@ protected Collection requiredKeys( ) { */ public static final class KeyInfo { public final String name; - final Class clzz; + public final Class clzz; /** * @param name non null * @param clzz non null diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java b/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java index 3e48f42b22..478cd87c95 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java @@ -111,7 +111,7 @@ private void checkForOverwrites(File selectedFile, Component parent, UserPrefere * @param clientWorker cbit.vcell.desktop.controls.ClientWorker */ public void run(Hashtable hashTable) throws java.lang.Exception { - VCDocument documentToExport = fetch(hashTable,DocumentToExport.EXPORT_DOCUMENT,VCDocument.class, true) ; + VCDocument documentToExport = ResultsHashUtils.fetch(hashTable,DocumentToExport.EXPORT_DOCUMENT,VCDocument.class, true) ; File exportFile = null; if (documentToExport instanceof BioModel) { exportFile = showBioModelXMLFileChooser(hashTable); diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 879804bcc0..56edbf81b9 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -11,12 +11,8 @@ package cbit.vcell.client.task; import java.awt.Component; -import java.awt.Cursor; -import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -26,25 +22,19 @@ import java.util.Set; import java.util.WeakHashMap; -import javax.swing.FocusManager; -import javax.swing.SwingUtilities; import javax.swing.Timer; import org.apache.commons.lang3.ClassUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.vcell.util.*; import org.vcell.util.gui.AsynchProgressPopup; -import org.vcell.util.gui.GuiUtils; import org.vcell.util.gui.ProgressDialog; -import cbit.vcell.client.ClientMDIManager; -import cbit.vcell.client.DocumentWindowManager; -import cbit.vcell.client.PopupGenerator; -import cbit.vcell.client.task.AsynchClientTask.KeyInfo; import cbit.vcell.simdata.PDEDataContext; +import swingthreads.StandardSwingWorker; import swingthreads.SwingWorker; +import swingthreads.TaskEventKeys; /** * Insert the type's description here. @@ -53,19 +43,6 @@ * @author: Ion Moraru */ public class ClientTaskDispatcher { - // public static final String PROGRESS_POPUP = "asynchProgressPopup"; -// public static final String TASK_PROGRESS_INTERVAL = "progressRange"; - public static final String TASK_ABORTED_BY_ERROR = "abort"; - public static final String TASK_ABORTED_BY_USER = "cancel"; - public static final String TASKS_TO_BE_SKIPPED = "conditionalSkip"; - /** - * hash key to internally flag problem with hash table data - */ - private static final String HASH_DATA_ERROR = "hdeHdeHde"; - /** - * hash key to store stack trace if {@link #lg} enabled for INFO - */ - private static final String STACK_TRACE_ARRAY = "clientTaskDispatcherStackTraceArray"; private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); /** * used to count / generate thread names @@ -282,194 +259,48 @@ public static void dispatch(final Component requester, final Hashtable taskList = new ArrayList<>(); + final String threadBaseName = "ClientTaskDispatcher " + (serial++) + ' '; + final List taskList = new ArrayList<>(); // check tasks - swing non-blocking can be only at the end ClientTaskDispatcher.entryCounter++; if (ClientTaskDispatcher.entryCounter > 1) lg.debug("Reentrant: {}", ClientTaskDispatcher.entryCounter); - // if (bInProgress) { - // Thread.dumpStack(); - // } - if (lg.isInfoEnabled()) hash.put(STACK_TRACE_ARRAY, Thread.currentThread().getStackTrace()); + // if (bInProgress) { + // Thread.dumpStack(); + // } + if (lg.isInfoEnabled()) + hash.put(TaskEventKeys.STACK_TRACE_ARRAY.toString(), Thread.currentThread().getStackTrace()); if (bShowProgressPopup && requester == null) { System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); Thread.dumpStack(); } - for (AsynchClientTask task : tasks){ - if (AsynchClientTask.TASKTYPE_SWING_NONBLOCKING== task.getTaskType() && taskList.size() + 1 != tasks.length) { - throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); - } - taskList.add(task); - lg.debug("added task name {}", task.getTaskName()); - } + for (AsynchClientTask task : tasks) { + if (AsynchClientTask.TASKTYPE_SWING_NONBLOCKING == task.getTaskType() && taskList.size() + 1 != tasks.length) { + throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); + } + taskList.add(task); + lg.debug("added task name {}", task.getTaskName()); + } // dispatch tasks to a new worker - SwingWorker worker = new SwingWorker() { - private AsynchProgressPopup pp = null; - private Window windowParent = null; - private Component focusOwner = null; - - public Object construct() { - if (bShowProgressPopup) { - if (customDialog == null) { - this.pp = new AsynchProgressPopup(requester, "WORKING...", "Initializing request", Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } else { - this.pp = new AsynchProgressPopup(requester, customDialog, Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } - this.pp.setStopStrategy(stopStrategy); - if (bInputBlocking) { - this.pp.startKeepOnTop(); - } else { - this.pp.start(); - } - } - if (requester != null) this.windowParent = GuiUtils.getWindowForComponent(requester); - - try { - if (this.windowParent != null) { - Window targetWindow = this.windowParent; - this.focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - SwingUtilities.invokeAndWait(() -> { - ClientMDIManager.blockWindow(targetWindow); - targetWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - }); - } - } catch (InterruptedException | InvocationTargetException e) { - lg.warn(e); - } - for (int i = 0; i < taskList.size(); i++) { - // run all tasks - // after abort, run only non-skippable tasks - // also skip selected tasks specified by conditionalSkip tag - final AsynchClientTask currentTask = taskList.get(i); - try { - currentTask.setClientTaskStatusSupport(this.pp); - ClientTaskDispatcher.setSwingWorkerThreadName(this, threadBaseName + currentTask.getTaskName()); - - //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); - if (this.pp != null) { - this.pp.setVisible(currentTask.showProgressPopup()); - if (!bKnowProgress) { - this.pp.setProgress(i * 100 / taskList.size()); // beginning of task - } - this.pp.setMessage(currentTask.getTaskName()); - } - boolean shouldRun = !hash.containsKey(HASH_DATA_ERROR); - if (hash.containsKey(TASK_ABORTED_BY_ERROR) && currentTask.skipIfAbort()) { - shouldRun = false; - } - if (hash.containsKey(TASKS_TO_BE_SKIPPED)) { - String[] toSkip = (String[]) hash.get(TASKS_TO_BE_SKIPPED); - boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); - if (taskShouldBeSkipped) shouldRun = false; - } - if (this.pp != null && this.pp.isInterrupted()) { - ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, hash); - } + SwingWorker worker = new StandardSwingWorker(threadBaseName, requester, stopStrategy, bKnowProgress, + progressDialogListener, bShowProgressPopup, customDialog, bInputBlocking, cancelable) { - if (hash.containsKey(TASK_ABORTED_BY_USER)) { - UserCancelException exc = (UserCancelException) hash.get(TASK_ABORTED_BY_USER); - if (currentTask.skipIfCancel(exc)) shouldRun = false; - } - if (shouldRun) { - try { - if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - ClientTaskDispatcher.runTask(currentTask, hash, taskList); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - SwingUtilities.invokeAndWait(() -> { - try { - ClientTaskDispatcher.runTask(currentTask, hash, taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, hash); - } - }); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - SwingUtilities.invokeLater(() -> { - try { - ClientTaskDispatcher.runTask(currentTask, hash, taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, hash); - } - }); - } - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, hash); - } - } - } finally { - ClientTaskDispatcher.allTasks.remove(currentTask); - } - } - return hash; + @Override + public void removeTaskFromDispatcher(AsynchClientTask task) { + ClientTaskDispatcher.allTasks.remove(task); } - public void finished() { - ClientTaskDispatcher.entryCounter--; - - if (this.pp != null) { - this.pp.stop(); - } - if (hash.containsKey(TASK_ABORTED_BY_ERROR)) { - // something went wrong - StringBuilder allCausesErrorMessageSB = new StringBuilder(); - Throwable causeError = (Throwable) hash.get(TASK_ABORTED_BY_ERROR); - do { - allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-") - .append(causeError.getMessage() == null || causeError.getMessage().isEmpty() ? - "" : causeError.getMessage()); - allCausesErrorMessageSB.append("\n"); - } while ((causeError = causeError.getCause()) != null); - if (requester == null) { - lg.warn("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); - } - if (lg.isInfoEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - String stackTraceString = StringUtils.join(ste, '\n'); - lg.info(stackTraceString, (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); - } else { - lg.info("Unexpected {} obj {}", STACK_TRACE_ARRAY, obj); - } - } - PopupGenerator.showErrorDialog(requester, allCausesErrorMessageSB.toString(), - (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); - } else if (hash.containsKey(TASK_ABORTED_BY_USER)) { - // depending on where user canceled we might want to automatically start a new job - ClientTaskDispatcher.dispatchFollowUp(hash); - } - - FinalWindow fw = AsynchClientTask.fetch(hash, FINAL_WINDOW, FinalWindow.class, false); - if (lg.isDebugEnabled() && fw != null) { - lg.debug("FinalWindow retrieved from hash"); - } - //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocation - if (this.windowParent != null) { - ClientMDIManager.unBlockWindow(this.windowParent); - this.windowParent.setCursor(Cursor.getDefaultCursor()); - if (fw == null && this.focusOwner != null) { - fw = () -> { - this.windowParent.requestFocusInWindow(); - this.focusOwner.requestFocusInWindow(); - }; - lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); - } - } - if (fw != null) { - lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); - Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; - SwingUtilities.invokeLater(runnable); - } else { - lg.debug("no Final Window"); - } + @Override + public void announceTaskComplete() { + ClientTaskDispatcher.entryCounter--; } }; - setSwingWorkerThreadName(worker, threadBaseName); + + worker.setThreadName(threadBaseName); allTasks.addAll(taskList); worker.start(); } @@ -480,7 +311,7 @@ public void finished() { * @param r payload * @return wrapper */ - private static Runnable debugWrapper(Runnable r) { + public static Runnable debugWrapper(Runnable r) { return () -> { lg.debug("calling " + r.getClass().getName() + ".run on " + r); @@ -488,22 +319,14 @@ private static Runnable debugWrapper(Runnable r) { }; } - private static void dispatchFollowUp(Hashtable hash) { - // we deal with a task dispatch that aborted due to some user choice on prompts - UserCancelException e = (UserCancelException) hash.get("cancel"); - if (e == UserCancelException.CHOOSE_SAVE_AS) { - // user chose to save as during a save or save/edition of a document found to be unchanged - ((DocumentWindowManager) hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); - } - } public static void recordException(Throwable exc, Hashtable hash) { lg.error(exc.getMessage(), exc); if (exc instanceof UserCancelException userCancelException) { - hash.put(TASK_ABORTED_BY_USER, userCancelException); + hash.put(TaskEventKeys.TASK_ABORTED_BY_USER.toString(), userCancelException); } else { exc.printStackTrace(System.out); - hash.put(TASK_ABORTED_BY_ERROR, exc); + hash.put(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString(), exc); } } @@ -560,98 +383,8 @@ public static void dispatchColl(final Component requester, final Hashtable hash, Collection taskList) throws Exception { - if (lg.isDebugEnabled()) { - String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); - if (lg.isDebugEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - msg += '\n' + StringUtils.join(ste, '\n'); - } - lg.debug(msg); - } else { - lg.debug(msg); - } - } - //check required elements present - StringBuilder sb = null; - for (KeyInfo requiredKey : currentTask.requiredKeys()) { - Object obj = hash.get(requiredKey.name); - if (obj == null) { - if (sb == null) sb = initStringBuilder(currentTask); - sb.append("Missing required key ").append(requiredKey.name).append('\n'); - continue; - } - Class foundClass = obj.getClass(); - if (!requiredKey.clzz.isAssignableFrom(foundClass)) { - if (sb == null) sb = initStringBuilder(currentTask); - sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); - sb.append('\n'); - } - } - - if (sb == null) { //no problems found - currentTask.run(hash); - return; - } - - sb.append("Prior tasks\n"); - for (AsynchClientTask pt : taskList) { - if (pt == currentTask) { - break; - } - sb.append('\t').append(pt.getTaskName()).append('\n'); - } - hash.put(HASH_DATA_ERROR, HASH_DATA_ERROR); - throw new ProgrammingException(sb.toString()); - } - - /** - * @param currentTask non null - * @return {@link StringBuilder} initialized with task name - */ - private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { - StringBuilder sb = new StringBuilder(); - sb.append("Data error for task " + currentTask.getTaskName() + '\n'); - return sb; - } - //package - interface FinalWindow extends Runnable { + public interface FinalWindow extends Runnable { } /** diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java b/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java index fc5ef63c36..b0dcf05086 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java @@ -37,7 +37,7 @@ public DeleteOldDocument() { @Override -protected Collection requiredKeys() { +public Collection requiredKeys() { ArrayList rval = new ArrayList<>(); rval.add(DOCUMENT_WINDOW_MANAGER); rval.add(DOCUMENT_MANAGER); @@ -52,9 +52,9 @@ protected Collection requiredKeys() { * @param clientWorker cbit.vcell.desktop.controls.ClientWorker */ public void run(Hashtable hashTable) throws java.lang.Exception { - DocumentWindowManager dwm = (DocumentWindowManager) fetch(hashTable,DOCUMENT_WINDOW_MANAGER); + DocumentWindowManager dwm = (DocumentWindowManager) ResultsHashUtils.fetch(hashTable,DOCUMENT_WINDOW_MANAGER); VCDocument currentDocument = dwm.getVCDocument(); - DocumentManager documentManager = (DocumentManager)fetch(hashTable,DOCUMENT_MANAGER); + DocumentManager documentManager = (DocumentManager) ResultsHashUtils.fetch(hashTable,DOCUMENT_MANAGER); switch (currentDocument.getDocumentType()) { case BIOMODEL_DOC: { // make the info diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java b/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java index c95d051c53..879f8e2d35 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java @@ -118,10 +118,10 @@ public void close(){ */ public void run(Hashtable hashTable) throws java.lang.Exception { VCDocument documentToExport = (VCDocument)hashTable.get("documentToExport"); - File exportFile = fetch(hashTable,EXPORT_FILE,File.class, true); - ExtensionFilter fileFilter = fetch(hashTable,FILE_FILTER,ExtensionFilter.class, true); + File exportFile = ResultsHashUtils.fetch(hashTable,EXPORT_FILE,File.class, true); + ExtensionFilter fileFilter = ResultsHashUtils.fetch(hashTable,FILE_FILTER,ExtensionFilter.class, true); - DocumentManager documentManager = fetch(hashTable,DocumentManager.IDENT,DocumentManager.class,true); + DocumentManager documentManager = ResultsHashUtils.fetch(hashTable,DocumentManager.IDENT,DocumentManager.class,true); String resultString = null; FileCloseHelper closeThis = null; try{ @@ -130,7 +130,7 @@ public void run(Hashtable hashTable) throws java.lang.Exception throw new Exception("Expecting fileFilter type "+SelectorExtensionFilter.class.getName()+" but got "+fileFilter.getClass().getName()); } BioModel bioModel = (BioModel)documentToExport; - SimulationContext chosenSimContext = fetch(hashTable,SIM_CONTEXT,SimulationContext.class, false); + SimulationContext chosenSimContext = ResultsHashUtils.fetch(hashTable,SIM_CONTEXT,SimulationContext.class, false); ((SelectorExtensionFilter)fileFilter).writeBioModel(documentManager, bioModel, exportFile, chosenSimContext); /* DELETE this after finishing validation testing diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java b/vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java new file mode 100644 index 0000000000..f4091f2241 --- /dev/null +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java @@ -0,0 +1,52 @@ +package cbit.vcell.client.task; + +import org.vcell.util.ProgrammingException; +import org.vcell.util.VCAssert; + +import java.util.Hashtable; + +public class ResultsHashUtils { + // TODO: Change this class to `ResultsHash extends Hashtable`, + // and implement everywhere the hash is already used + /** + * fetch and type convert object from hash + * @param hashTable not null + * @param key name (not null) + * @param clzz required type, not null + * @param required throw exception if required and not present + * @return object cast to correct type or possibly null if !required + * @throws ProgrammingException if key not of required type + * @throws ProgrammingException required is true and key not present + */ + + public static T fetch(Hashtable hashTable, String key, Class clzz, boolean required) { + if (null == hashTable) throw new IllegalArgumentException("hashTable may not be null"); + if (null == key) throw new IllegalArgumentException("key may not be null"); + if (null == clzz) throw new IllegalArgumentException("clzz may not be null"); + + if (required && !hashTable.containsKey(key)) throw new ProgrammingException("key " + key + " not found in async hashtable"); + + Object obj = hashTable.get(key); + if (obj == null) return null; + + Class classOfObj = obj.getClass(); + if (clzz.isAssignableFrom(classOfObj)) return clzz.cast(obj); + + String exceptionFormat = "object `%s` of type `%s` is not an instance of `%s`"; + String exceptionMessage = String.format(exceptionFormat, obj, classOfObj.getName(), clzz.getName()); + throw new ProgrammingException(exceptionMessage); + } + + /** + * typesafe (verified) fetch of object from hash + * @param hashTable non null + * @param keyInfo non null + * @return object of correct type + */ + static protected Object fetch(Hashtable hashTable, AsynchClientTask.KeyInfo keyInfo) { + Object obj = hashTable.get(keyInfo.name); + VCAssert.assertTrue(obj != null, "ClientTaskDispatcher failed to verify object"); + VCAssert.assertTrue(keyInfo.clzz.isAssignableFrom(obj.getClass()),"ClientTaskDispatcher failed to verify type"); + return obj; + } +} diff --git a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java index bb0dddc289..ff26a55423 100644 --- a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java @@ -1,11 +1,294 @@ package swingthreads; -public class StandardSwingWorker extends SwingWorker { +import cbit.vcell.client.ClientMDIManager; +import cbit.vcell.client.DocumentWindowManager; +import cbit.vcell.client.PopupGenerator; +import cbit.vcell.client.task.AsynchClientTask; +import cbit.vcell.client.task.ClientTaskDispatcher; +import cbit.vcell.client.task.CommonTask; +import cbit.vcell.client.task.ResultsHashUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.vcell.util.*; +import org.vcell.util.gui.AsynchProgressPopup; +import org.vcell.util.gui.GuiUtils; +import org.vcell.util.gui.ProgressDialog; + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.Hashtable; +import java.util.List; + +public abstract class StandardSwingWorker extends SwingWorker { + private static final Logger lg = LogManager.getLogger(StandardSwingWorker.class); + + private AsynchProgressPopup pp = null; + private Window windowParent = null; + private Component focusOwner = null; + + private List taskList; + private Hashtable resultsHash; + + private boolean shouldShowProgressPopup; + private boolean shouldBlockInput; + private boolean shouldInformOfProgress; + private boolean shouldBeCancelable; + private String threadBaseName; + private ProgressDialog customProgressDialog; + private Component requestingComponent; + private ProgressDialogListener progressDialogListener; + + private ClientTaskDispatcher.StopStrategy stopStrategy; + + public StandardSwingWorker(String threadBaseName, Component requestingComponent, + ClientTaskDispatcher.StopStrategy stopStrategy, boolean shouldInformOfProgress, + ProgressDialogListener progressDialogListener, boolean shouldShowProgressPopup, + ProgressDialog customProgressDialog, boolean shouldBlockInput, boolean shouldBeCancelable) { + super(); + this.threadBaseName = threadBaseName; + this.requestingComponent = requestingComponent; + this.stopStrategy = stopStrategy; + this.shouldInformOfProgress = shouldInformOfProgress; + this.progressDialogListener = progressDialogListener; + this.shouldShowProgressPopup = shouldShowProgressPopup; + this.customProgressDialog = customProgressDialog; + this.shouldBlockInput = shouldBlockInput; + this.shouldBeCancelable = shouldBeCancelable; + } + /** - * Compute the value to be returned by the get method. + * call currentTask.run(hash) with log4j logging; check for required keys + * + * @param currentTask not null + * @param hash not null + * @param taskList current set of tasks being dispatched + * @throws Exception */ - @Override + public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { + if (lg.isDebugEnabled()) { + String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); + if (lg.isDebugEnabled()) { + Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + msg += '\n' + StringUtils.join(ste, '\n'); + } + lg.debug(msg); + } else { + lg.debug(msg); + } + } + //check required elements present + StringBuilder sb = null; + for (AsynchClientTask.KeyInfo requiredKey : currentTask.requiredKeys()) { + Object obj = hash.get(requiredKey.name); + if (obj == null) { + if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + sb.append("Missing required key ").append(requiredKey.name).append('\n'); + continue; + } + Class foundClass = obj.getClass(); + if (!requiredKey.clzz.isAssignableFrom(foundClass)) { + if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); + sb.append('\n'); + } + } + + if (sb == null) { //no problems found + currentTask.run(hash); + return; + } + + sb.append("Prior tasks\n"); + for (AsynchClientTask pt : taskList) { + if (pt == currentTask) { + break; + } + sb.append('\t').append(pt.getTaskName()).append('\n'); + } + hash.put(TaskEventKeys.HASH_DATA_ERROR.toString(), TaskEventKeys.HASH_DATA_ERROR.toString()); + throw new ProgrammingException(sb.toString()); + } + public Object construct() { - return null; + if (this.shouldShowProgressPopup) { + if (this.customProgressDialog == null) { + this.pp = new AsynchProgressPopup(this.requestingComponent, "WORKING...", "Initializing request", Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + } else { + this.pp = new AsynchProgressPopup(this.requestingComponent, this.customProgressDialog, Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + } + this.pp.setStopStrategy(this.stopStrategy); + if (this.shouldBlockInput) { + this.pp.startKeepOnTop(); + } else { + this.pp.start(); + } + } + if (this.requestingComponent != null) this.windowParent = GuiUtils.getWindowForComponent(this.requestingComponent); + + try { + if (this.windowParent != null) { + Window targetWindow = this.windowParent; + this.focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + SwingUtilities.invokeAndWait(() -> { + ClientMDIManager.blockWindow(targetWindow); + targetWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + } + } catch (InterruptedException | InvocationTargetException e) { + lg.warn(e); + } + for (int i = 0; i < this.taskList.size(); i++) { + // run all tasks + // after abort, run only non-skippable tasks + // also skip selected tasks specified by conditionalSkip tag + final AsynchClientTask currentTask = this.taskList.get(i); + try { + currentTask.setClientTaskStatusSupport(this.pp); + this.setThreadName(this.threadBaseName + currentTask.getTaskName()); + + //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); + if (this.pp != null) { + this.pp.setVisible(currentTask.showProgressPopup()); + if (!this.shouldInformOfProgress) { + this.pp.setProgress(i * 100 / this.taskList.size()); // beginning of task + } + this.pp.setMessage(currentTask.getTaskName()); + } + boolean shouldRun = !this.resultsHash.containsKey(TaskEventKeys.HASH_DATA_ERROR.toString()); + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) && currentTask.skipIfAbort()) { + shouldRun = false; + } + if (this.resultsHash.containsKey(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString())) { + String[] toSkip = (String[]) this.resultsHash.get(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString()); + boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); + if (taskShouldBeSkipped) shouldRun = false; + } + if (this.pp != null && this.pp.isInterrupted()) { + ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, this.resultsHash); + } + + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { + UserCancelException exc = (UserCancelException) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()); + if (currentTask.skipIfCancel(exc)) shouldRun = false; + } + if (shouldRun) { + try { + if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + SwingUtilities.invokeAndWait(() -> { + try { + StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + SwingUtilities.invokeLater(() -> { + try { + StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); + } + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + } + } finally { + this.removeTaskFromDispatcher(currentTask); + } + } + return this.resultsHash; + } + + public void finished() { + this.announceTaskComplete(); + + if (this.pp != null) { + this.pp.stop(); + } + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())) { + // something went wrong + StringBuilder allCausesErrorMessageSB = new StringBuilder(); + Throwable causeError = (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); + do { + allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-") + .append(causeError.getMessage() == null || causeError.getMessage().isEmpty() ? + "" : causeError.getMessage()); + allCausesErrorMessageSB.append("\n"); + } while ((causeError = causeError.getCause()) != null); + if (this.requestingComponent == null) { + lg.warn("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); + Thread.dumpStack(); + } + if (lg.isInfoEnabled()) { + Object obj = this.resultsHash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + String stackTraceString = StringUtils.join(ste, '\n'); + lg.info(stackTraceString, (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())); + } else { + lg.info("Unexpected {} obj {}", TaskEventKeys.STACK_TRACE_ARRAY.toString(), obj); + } + } + PopupGenerator.showErrorDialog(this.requestingComponent, allCausesErrorMessageSB.toString(), + (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())); + } else if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { + // depending on where user canceled we might want to automatically start a new job + StandardSwingWorker.dispatchFollowUp(this.resultsHash); + } + + ClientTaskDispatcher.FinalWindow fw = ResultsHashUtils.fetch(this.resultsHash, TaskEventKeys.FINAL_WINDOW.toString(), ClientTaskDispatcher.FinalWindow.class, false); + if (fw != null) lg.debug("FinalWindow retrieved from hash"); + + //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocation + if (this.windowParent != null) { + ClientMDIManager.unBlockWindow(this.windowParent); + this.windowParent.setCursor(Cursor.getDefaultCursor()); + if (fw == null && this.focusOwner != null) { + fw = () -> { + this.windowParent.requestFocusInWindow(); + this.focusOwner.requestFocusInWindow(); + }; + lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); + } + } + if (fw != null) { + lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); + Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; + SwingUtilities.invokeLater(runnable); + } else { + lg.debug("no Final Window"); + } + } + + private static void dispatchFollowUp(Hashtable hash) { + // we deal with a task dispatch that aborted due to some user choice on prompts + UserCancelException e = (UserCancelException) hash.get("cancel"); + if (e == UserCancelException.CHOOSE_SAVE_AS) { + // user chose to save as during a save or save/edition of a document found to be unchanged + ((DocumentWindowManager) hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); + } } + + /** + * @param currentTask non null + * @return {@link StringBuilder} initialized with task name + */ + private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { + StringBuilder sb = new StringBuilder(); + sb.append("Data error for task " + currentTask.getTaskName() + '\n'); + return sb; + } + + public abstract void removeTaskFromDispatcher(AsynchClientTask task); + + public abstract void announceTaskComplete(); } diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index f0f488d1fa..86f6caff57 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -1,6 +1,11 @@ package swingthreads; +import cbit.vcell.client.task.ClientTaskDispatcher; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import javax.swing.SwingUtilities; +import java.lang.reflect.Field; /** * This is the 3rd version of SwingWorker (also known as @@ -15,6 +20,22 @@ * creating it. */ public abstract class SwingWorker { + private static final Logger lg = LogManager.getLogger(SwingWorker.class); + /** + * set {@link SwingWorker} thread name + * + * @param name may not be null + * @throws IllegalArgumentException if name is null + */ + public void setThreadName(String name) { + if (name == null) throw new IllegalArgumentException("name may not be null"); + try { + this.threadVar.thread.setName(name); + } catch (SecurityException e) { + lg.warn("setSwingWorkerName fail", e); + } + } + /** * Class to maintain reference to current worker thread * under separate synchronization control. diff --git a/vcell-client/src/main/java/swingthreads/TaskEventKeys.java b/vcell-client/src/main/java/swingthreads/TaskEventKeys.java new file mode 100644 index 0000000000..1cc50f9264 --- /dev/null +++ b/vcell-client/src/main/java/swingthreads/TaskEventKeys.java @@ -0,0 +1,24 @@ +package swingthreads; + +public enum TaskEventKeys { + //PROGRESS_POPUP("asynchProgressPopup"), + //TASK_PROGRESS_INTERVAL("progressRange"), + TASK_ABORTED_BY_ERROR("abort"), + TASK_ABORTED_BY_USER("cancel"), + TASKS_TO_BE_SKIPPED("conditionalSkip"), + FINAL_WINDOW("finalWindowInterface"), + STACK_TRACE_ARRAY("clientTaskDispatcherStackTraceArray"), // hash key to store stack trace if {@link #lg} enabled for INFO + HASH_DATA_ERROR("hdeHdeHde"), // hash key to internally flag problem with hash table data + ; + + private final String value; + + TaskEventKeys(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } +} From 2deef2846c9dd93f8c898102b5ea7ac807115fc1 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 14:53:02 -0400 Subject: [PATCH 08/48] Formatting and Rearranging --- .../vcell/client/task/AsynchClientTask.java | 288 +++++++++--------- .../vcell/client/task/AsynchTaskType.java | 7 + .../client/task/ClientTaskDispatcher.java | 20 +- .../main/java/swingthreads/SwingWorker.java | 43 +-- .../vcell/clientdb/ClientDocumentManager.java | 2 +- 5 files changed, 184 insertions(+), 176 deletions(-) create mode 100644 vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java index bcf90f3f7e..eb86117b7c 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java @@ -23,153 +23,157 @@ import org.vcell.util.gui.GuiUtils; import cbit.vcell.client.ChildWindowManager.ChildWindow; + /** * Insert the type's description here. * Creation date: (5/31/2004 6:09:07 PM) + * * @author: Ion Moraru */ public abstract class AsynchClientTask { - public final static int TASKTYPE_NONSWING_BLOCKING = 1; - public final static int TASKTYPE_SWING_NONBLOCKING = 2; - public final static int TASKTYPE_SWING_BLOCKING = 3; + public final static int TASKTYPE_NONSWING_BLOCKING = 1; + public final static int TASKTYPE_SWING_NONBLOCKING = 2; + public final static int TASKTYPE_SWING_BLOCKING = 3; -/** - * Insert the method's description here. - * Creation date: (5/31/2004 7:18:33 PM) - * @return boolean - */ - private boolean bSkipIfAbort = true; - private boolean bSkipIfCancel = true; - private int taskType = TASKTYPE_NONSWING_BLOCKING; - private String taskName = ""; - private ClientTaskStatusSupport clientTaskStatusSupport = null; - private boolean bShowProgressPopup = true; - //private AsynchClientTask[] followupTasks = null; - - /** - * defaults showPopup, skip if abort, skip if cancel to true - * @param name - * @param taskType - */ - public AsynchClientTask(String name, int taskType) { - this(name, taskType, true, true, true); - } - - /** - * defaults skip if abort, skip if cancel to true - * @param name - * @param taskType - * @param bShowPopup - */ - public AsynchClientTask(String name, int taskType, boolean bShowPopup) { - this(name, taskType, bShowPopup, true, true); - } - - /** - * defaults showPopup, skip if abort, skip if cancel to true - * @param name - * @param taskType - * @param skipIfAbort - * @param skipIfCancel - */ - public AsynchClientTask(String name, int taskType, boolean skipIfAbort, boolean skipIfCancel) { - this(name, taskType, true, skipIfAbort, skipIfCancel); - } - - public AsynchClientTask(String name, int taskType, boolean bShowPopup, boolean skipIfAbort, boolean skipIfCancel) { - this.taskName = name; - this.taskType = taskType; - this.bShowProgressPopup = bShowPopup; - this.bSkipIfAbort = skipIfAbort; - this.bSkipIfCancel = skipIfCancel; - } - - public final boolean skipIfAbort() { - return bSkipIfAbort; - } - - public ClientTaskStatusSupport getClientTaskStatusSupport() { - return clientTaskStatusSupport; - } - - /** - * Insert the method's description here. - * Creation date: (5/31/2004 7:18:33 PM) - * @return boolean - */ - public boolean skipIfCancel(UserCancelException exc) { - return bSkipIfCancel; - } - - public final int getTaskType() { - return taskType; - } - - public final String getTaskName() { - return taskName; - } - - public abstract void run(Hashtable hashTable) throws Exception; - - public void setClientTaskStatusSupport(ClientTaskStatusSupport clientTaskStatusSupport) { - this.clientTaskStatusSupport = clientTaskStatusSupport; - } - public boolean showProgressPopup() { - return bShowProgressPopup; - } - - /** - * set final window to be raised - * @param hashTable non null - * @param cw non null - * @throws ProgrammingException if more than one set in the same hash - */ - protected void setFinalWindow(Hashtable hashTable,ChildWindow cw) { - Objects.requireNonNull(cw); - ClientTaskDispatcher.setFinalWindow(hashTable,() -> cw.toFront( ) ); - } - - /** - * set final window to be raised - * @param hashTable non null - * @param cntr non null - * @throws ProgrammingException if more than one set in the same hash - */ - protected void setFinalWindow(Hashtable hashTable,Container cntr) { - Objects.requireNonNull(cntr); - Window w= GuiUtils.getWindowForComponent(cntr); - if (w != null) { - ClientTaskDispatcher.setFinalWindow(hashTable,() -> w.toFront( ) ); - return; - } - throw new ProgrammingException("Container " + cntr.getName() + " has no window parent"); - } - - /** - * return list of keys need by task - * @return non-null Collection - */ - public Collection requiredKeys( ) { - return Collections.emptyList(); - } - - /** - * required hash key name and type - */ - public static final class KeyInfo { - public final String name; - public final Class clzz; - /** - * @param name non null - * @param clzz non null - */ - protected KeyInfo(String name, Class clzz) { - this.name = name; - this.clzz = clzz; - Objects.requireNonNull(name); - Objects.requireNonNull(clzz); - } - } - - + /** + * Insert the method's description here. + * Creation date: (5/31/2004 7:18:33 PM) + * + * @return boolean + */ + private final boolean bSkipIfAbort; + private final boolean bSkipIfCancel; + private final int taskType; + private final String taskName; + private ClientTaskStatusSupport clientTaskStatusSupport = null; + private final boolean bShowProgressPopup; + //private AsynchClientTask[] followupTasks = null; + + /** + * defaults showPopup, skip if abort, skip if cancel to true + * + * @param name + * @param taskType + */ + public AsynchClientTask(String name, int taskType) { + this(name, taskType, true, true, true); + } + + /** + * defaults skip if abort, skip if cancel to true + * + * @param name + * @param taskType + * @param bShowPopup + */ + public AsynchClientTask(String name, int taskType, boolean bShowPopup) { + this(name, taskType, bShowPopup, true, true); + } + + /** + * defaults showPopup, skip if aborted and skip if canceled to true + * + * @param name + * @param taskType + * @param skipIfAbort + * @param skipIfCancel + */ + public AsynchClientTask(String name, int taskType, boolean skipIfAbort, boolean skipIfCancel) { + this(name, taskType, true, skipIfAbort, skipIfCancel); + } + + public AsynchClientTask(String name, int taskType, boolean bShowPopup, boolean skipIfAbort, boolean skipIfCancel) { + this.taskName = name; + this.taskType = taskType; + this.bShowProgressPopup = bShowPopup; + this.bSkipIfAbort = skipIfAbort; + this.bSkipIfCancel = skipIfCancel; + } + + public final boolean skipIfAbort() { + return this.bSkipIfAbort; + } + + public ClientTaskStatusSupport getClientTaskStatusSupport() { + return this.clientTaskStatusSupport; + } + + public boolean skipIfCancel(UserCancelException exc) { + return this.bSkipIfCancel; + } + + public final int getTaskType() { + return this.taskType; + } + + public final String getTaskName() { + return this.taskName; + } + + public abstract void run(Hashtable hashTable) throws Exception; + + public void setClientTaskStatusSupport(ClientTaskStatusSupport clientTaskStatusSupport) { + this.clientTaskStatusSupport = clientTaskStatusSupport; + } + + public boolean showProgressPopup() { + return this.bShowProgressPopup; + } + + /** + * set final window to be raised + * + * @param hashTable non null + * @param cw non null + * @throws ProgrammingException if more than one set in the same hash + */ + protected void setFinalWindow(Hashtable hashTable, ChildWindow cw) { + Objects.requireNonNull(cw); + ClientTaskDispatcher.setFinalWindow(hashTable, cw::toFront); + } + + /** + * set final window to be raised + * + * @param hashTable non null + * @param cntr non null + * @throws ProgrammingException if more than one set in the same hash + */ + protected void setFinalWindow(Hashtable hashTable, Container cntr) { + Objects.requireNonNull(cntr); + Window w = GuiUtils.getWindowForComponent(cntr); + if (w != null) { + ClientTaskDispatcher.setFinalWindow(hashTable, w::toFront); + return; + } + throw new ProgrammingException("Container " + cntr.getName() + " has no window parent"); + } + + /** + * return list of keys need by task + * + * @return non-null Collection + */ + public Collection requiredKeys() { + return Collections.emptyList(); + } + + /** + * required hash key name and type + */ + public static final class KeyInfo { + public final String name; + public final Class clzz; + + /** + * @param name non null + * @param clzz non null + */ + KeyInfo(String name, Class clzz) { + this.name = name; + this.clzz = clzz; + Objects.requireNonNull(name); + Objects.requireNonNull(clzz); + } + } } diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java new file mode 100644 index 0000000000..9783a121a6 --- /dev/null +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java @@ -0,0 +1,7 @@ +package cbit.vcell.client.task; + +public enum AsynchTaskType { + NON_SWING_BLOCKING, + SWING_BLOCKING, + SWING_NON_BLOCKING, +} diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 56edbf81b9..f7c21f2757 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -48,6 +48,7 @@ public class ClientTaskDispatcher { * used to count / generate thread names */ private static long serial = 0; + private static int entryCounter = 0; /** * set of all scheduled tasks; used to avoid calling System.exit() prematurely on Application exit */ @@ -58,7 +59,7 @@ public class ClientTaskDispatcher { private static final String FINAL_WINDOW = "finalWindowInterface"; static { - WeakHashMap whm = new WeakHashMap(); + WeakHashMap whm = new WeakHashMap<>(); allTasks = Collections.synchronizedSet(Collections.newSetFromMap(whm)); } @@ -92,8 +93,6 @@ public static void dispatch(final Component requester, final Hashtable 0; @@ -115,15 +114,12 @@ public void actionPerformed(ActionEvent e) { } } }); - private static final ProgressDialogListener cancelListener = new ProgressDialogListener() { - @Override - public void cancelButton_actionPerformed(EventObject newEvent) { - synchronized (allBlockingTimers) { - while (!allBlockingTimers.isEmpty()) { - allBlockingTimers.remove(0); - } - ppStop.restart(); + private static final ProgressDialogListener cancelListener = newEvent -> { + synchronized (allBlockingTimers) { + while (!allBlockingTimers.isEmpty()) { + allBlockingTimers.remove(0); } + ppStop.restart(); } }; @@ -408,6 +404,4 @@ static void setFinalWindow(Hashtable hash, FinalWindow fWindow) String n = ClassUtils.getShortClassName(fWindow, def); throw new ProgrammingException("duplicate final windows" + e + " and " + n); } - - } diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index 86f6caff57..f8df2c5e18 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -21,20 +21,7 @@ */ public abstract class SwingWorker { private static final Logger lg = LogManager.getLogger(SwingWorker.class); - /** - * set {@link SwingWorker} thread name - * - * @param name may not be null - * @throws IllegalArgumentException if name is null - */ - public void setThreadName(String name) { - if (name == null) throw new IllegalArgumentException("name may not be null"); - try { - this.threadVar.thread.setName(name); - } catch (SecurityException e) { - lg.warn("setSwingWorkerName fail", e); - } - } + /** * Class to maintain reference to current worker thread @@ -60,6 +47,22 @@ synchronized void clear() { private Object value; // see getValue(), setValue() private final ThreadVar threadVar; + + /** + * set {@link SwingWorker} thread name + * + * @param name may not be null + * @throws IllegalArgumentException if name is null + */ + public void setThreadName(String name) { + if (name == null) throw new IllegalArgumentException("name may not be null"); + try { + this.threadVar.thread.setName(name); + } catch (SecurityException e) { + lg.warn("setSwingWorkerName fail", e); + } + } + /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. @@ -80,12 +83,6 @@ private synchronized void setValue(Object x) { */ public abstract Object construct(); - /** - * Called on the event dispatching thread (not on the worker thread) - * after the construct method has returned. - */ - public void finished() {} - /** * A new method that interrupts the worker thread. Call this method * to force the worker to stop what it's doing. @@ -139,6 +136,12 @@ public void run() { this.threadVar = new ThreadVar(t); } + /** + * Called on the event dispatching thread (not on the worker thread) + * after the construct method has returned. + */ + public void finished() {} + /** * Start the worker thread. */ diff --git a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java index aed308adab..e6de21237a 100644 --- a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java +++ b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java @@ -102,7 +102,7 @@ import cbit.vcell.xml.XmlParseException; import cbit.vcell.xml.XmlReader; -public class ClientDocumentManager implements DocumentManager{ +public class ClientDocumentManager implements DocumentManager { private static final Logger lg = LogManager.getLogger(ClientDocumentManager.class); // // From cf75f95308709b104adcc93161c71fb26aed925d Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 16:04:31 -0400 Subject: [PATCH 09/48] Added missing parameters --- .../client/task/ClientTaskDispatcher.java | 2 +- .../swingthreads/StandardSwingWorker.java | 55 +++++++++---------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index f7c21f2757..3d25b7839a 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -282,7 +282,7 @@ public static void dispatch(final Component requester, final Hashtable taskList; private Hashtable resultsHash; - private boolean shouldShowProgressPopup; - private boolean shouldBlockInput; - private boolean shouldInformOfProgress; - private boolean shouldBeCancelable; - private String threadBaseName; - private ProgressDialog customProgressDialog; - private Component requestingComponent; - private ProgressDialogListener progressDialogListener; + private final boolean shouldShowProgressPopup; + private final boolean shouldBlockInput; + private final boolean shouldInformOfProgress; + private final boolean shouldBeCancelable; + private final String threadBaseName; + private final ProgressDialog customProgressDialog; + private final Component requestingComponent; + private final ProgressDialogListener progressDialogListener; - private ClientTaskDispatcher.StopStrategy stopStrategy; + private final ClientTaskDispatcher.StopStrategy stopStrategy; - public StandardSwingWorker(String threadBaseName, Component requestingComponent, - ClientTaskDispatcher.StopStrategy stopStrategy, boolean shouldInformOfProgress, - ProgressDialogListener progressDialogListener, boolean shouldShowProgressPopup, - ProgressDialog customProgressDialog, boolean shouldBlockInput, boolean shouldBeCancelable) { + public StandardSwingWorker(String threadBaseName, List taskList, Component requestingComponent, + ClientTaskDispatcher.StopStrategy stopStrategy, Hashtable resultsHash, + boolean shouldInformOfProgress, ProgressDialogListener progressDialogListener, + boolean shouldShowProgressPopup, ProgressDialog customProgressDialog, + boolean shouldBlockInput, boolean shouldBeCancelable) { super(); this.threadBaseName = threadBaseName; + this.taskList = taskList; this.requestingComponent = requestingComponent; this.stopStrategy = stopStrategy; + this.resultsHash = resultsHash; this.shouldInformOfProgress = shouldInformOfProgress; this.progressDialogListener = progressDialogListener; this.shouldShowProgressPopup = shouldShowProgressPopup; @@ -70,16 +73,10 @@ public StandardSwingWorker(String threadBaseName, Component requestingComponent, public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { if (lg.isDebugEnabled()) { String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); - if (lg.isDebugEnabled()) { - Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - msg += '\n' + StringUtils.join(ste, '\n'); - } - lg.debug(msg); - } else { - lg.debug(msg); - } + Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) msg += '\n' + StringUtils.join(ste, '\n'); + lg.debug(msg); } //check required elements present StringBuilder sb = null; @@ -90,12 +87,13 @@ public static void runTask(AsynchClientTask currentTask, Hashtable foundClass = obj.getClass(); - if (!requiredKey.clzz.isAssignableFrom(foundClass)) { - if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); - sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); - sb.append('\n'); - } + if (requiredKey.clzz.isAssignableFrom(foundClass)) continue; + + if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); + sb.append('\n'); } if (sb == null) { //no problems found @@ -103,6 +101,7 @@ public static void runTask(AsynchClientTask currentTask, Hashtable Date: Tue, 23 Jul 2024 14:40:24 -0400 Subject: [PATCH 10/48] class name changes --- ...ker.java => StandardVCellSwingWorker.java} | 158 +++++++++--------- ...SwingWorker.java => VCellSwingWorker.java} | 58 ++++--- 2 files changed, 114 insertions(+), 102 deletions(-) rename vcell-client/src/main/java/swingthreads/{StandardSwingWorker.java => StandardVCellSwingWorker.java} (65%) rename vcell-client/src/main/java/swingthreads/{SwingWorker.java => VCellSwingWorker.java} (70%) diff --git a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java similarity index 65% rename from vcell-client/src/main/java/swingthreads/StandardSwingWorker.java rename to vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java index f9a7f3664a..ebd30de5b4 100644 --- a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java @@ -3,10 +3,7 @@ import cbit.vcell.client.ClientMDIManager; import cbit.vcell.client.DocumentWindowManager; import cbit.vcell.client.PopupGenerator; -import cbit.vcell.client.task.AsynchClientTask; -import cbit.vcell.client.task.ClientTaskDispatcher; -import cbit.vcell.client.task.CommonTask; -import cbit.vcell.client.task.ResultsHashUtils; +import cbit.vcell.client.task.*; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,39 +15,40 @@ import javax.swing.*; import java.awt.*; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.List; -public abstract class StandardSwingWorker extends SwingWorker { - private static final Logger lg = LogManager.getLogger(StandardSwingWorker.class); +public abstract class StandardVCellSwingWorker extends VCellSwingWorker { + private static final Logger lg = LogManager.getLogger(StandardVCellSwingWorker.class); - private AsynchProgressPopup pp = null; - private Window windowParent = null; - private Component focusOwner = null; + protected AsynchProgressPopup progressPopup = null; + protected Window windowParent = null; + protected Component focusOwner = null; - private List taskList; - private Hashtable resultsHash; + protected final List taskList; + protected final Hashtable resultsHash; - private final boolean shouldShowProgressPopup; - private final boolean shouldBlockInput; - private final boolean shouldInformOfProgress; - private final boolean shouldBeCancelable; - private final String threadBaseName; - private final ProgressDialog customProgressDialog; - private final Component requestingComponent; - private final ProgressDialogListener progressDialogListener; + protected final boolean shouldShowProgressPopup; + protected final boolean shouldBlockInput; + protected final boolean shouldInformOfProgress; + protected final boolean shouldBeCancelable; + protected final String threadBaseName; + protected final ProgressDialog customProgressDialog; + protected final Component requestingComponent; + protected final ProgressDialogListener progressDialogListener; - private final ClientTaskDispatcher.StopStrategy stopStrategy; + protected final ClientTaskDispatcher.StopStrategy stopStrategy; - public StandardSwingWorker(String threadBaseName, List taskList, Component requestingComponent, - ClientTaskDispatcher.StopStrategy stopStrategy, Hashtable resultsHash, - boolean shouldInformOfProgress, ProgressDialogListener progressDialogListener, - boolean shouldShowProgressPopup, ProgressDialog customProgressDialog, - boolean shouldBlockInput, boolean shouldBeCancelable) { + public StandardVCellSwingWorker(String threadBaseName, List taskList, Component requestingComponent, + ClientTaskDispatcher.StopStrategy stopStrategy, Hashtable resultsHash, + boolean shouldInformOfProgress, ProgressDialogListener progressDialogListener, + boolean shouldShowProgressPopup, ProgressDialog customProgressDialog, + boolean shouldBlockInput, boolean shouldBeCancelable) { super(); this.threadBaseName = threadBaseName; - this.taskList = taskList; + this.taskList = new ArrayList<>(taskList); this.requestingComponent = requestingComponent; this.stopStrategy = stopStrategy; this.resultsHash = resultsHash; @@ -68,7 +66,7 @@ public StandardSwingWorker(String threadBaseName, List taskLis * @param currentTask not null * @param hash not null * @param taskList current set of tasks being dispatched - * @throws Exception + * @throws Exception if an exception was generated by running the task */ public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { if (lg.isDebugEnabled()) { @@ -83,7 +81,7 @@ public static void runTask(AsynchClientTask currentTask, Hashtable foundClass = obj.getClass(); if (requiredKey.clzz.isAssignableFrom(foundClass)) continue; - if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + if (sb == null) sb = StandardVCellSwingWorker.initStringBuilder(currentTask); sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); sb.append('\n'); } - if (sb == null) { //no problems found - currentTask.run(hash); + if (sb == null) { // no problems found + currentTask.run(hash); // Run the AsyncClientTask the user provided...many layers ago. return; } @@ -113,18 +111,18 @@ public static void runTask(AsynchClientTask currentTask, Hashtable verifyAndRun() { if (this.shouldShowProgressPopup) { if (this.customProgressDialog == null) { - this.pp = new AsynchProgressPopup(this.requestingComponent, "WORKING...", "Initializing request", Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + this.progressPopup = new AsynchProgressPopup(this.requestingComponent, "WORKING...", "Initializing request", Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); } else { - this.pp = new AsynchProgressPopup(this.requestingComponent, this.customProgressDialog, Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + this.progressPopup = new AsynchProgressPopup(this.requestingComponent, this.customProgressDialog, Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); } - this.pp.setStopStrategy(this.stopStrategy); + this.progressPopup.setStopStrategy(this.stopStrategy); if (this.shouldBlockInput) { - this.pp.startKeepOnTop(); + this.progressPopup.startKeepOnTop(); } else { - this.pp.start(); + this.progressPopup.start(); } } if (this.requestingComponent != null) this.windowParent = GuiUtils.getWindowForComponent(this.requestingComponent); @@ -147,58 +145,67 @@ public Object construct() { // also skip selected tasks specified by conditionalSkip tag final AsynchClientTask currentTask = this.taskList.get(i); try { - currentTask.setClientTaskStatusSupport(this.pp); + currentTask.setClientTaskStatusSupport(this.progressPopup); this.setThreadName(this.threadBaseName + currentTask.getTaskName()); //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); - if (this.pp != null) { - this.pp.setVisible(currentTask.showProgressPopup()); + if (this.progressPopup != null) { + this.progressPopup.setVisible(currentTask.shouldShowProgressPopup()); if (!this.shouldInformOfProgress) { - this.pp.setProgress(i * 100 / this.taskList.size()); // beginning of task + this.progressPopup.setProgress(i * 100 / this.taskList.size()); // beginning of task } - this.pp.setMessage(currentTask.getTaskName()); + this.progressPopup.setMessage(currentTask.getTaskName()); } - boolean shouldRun = !this.resultsHash.containsKey(TaskEventKeys.HASH_DATA_ERROR.toString()); + + // If the hash results have an error, don't run the task. + if (this.resultsHash.containsKey(TaskEventKeys.HASH_DATA_ERROR.toString())) continue; + + // If the task has an error, don't run it. if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) && currentTask.skipIfAbort()) { - shouldRun = false; + continue; } + + // If task is supposed to be skipped, don't run it. if (this.resultsHash.containsKey(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString())) { String[] toSkip = (String[]) this.resultsHash.get(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString()); boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); - if (taskShouldBeSkipped) shouldRun = false; + if (taskShouldBeSkipped) continue; } - if (this.pp != null && this.pp.isInterrupted()) { + + // If the popup recorded an interruption, don't run it. + if (this.progressPopup != null && this.progressPopup.isInterrupted()) { ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, this.resultsHash); } + // If task was aborted, don't run it. if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { UserCancelException exc = (UserCancelException) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()); - if (currentTask.skipIfCancel(exc)) shouldRun = false; + if (currentTask.skipIfCancel(exc)) continue; } - if (shouldRun) { - try { - if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - SwingUtilities.invokeAndWait(() -> { - try { - StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); - } - }); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - SwingUtilities.invokeLater(() -> { - try { - StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); - } - }); - } - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); + + // All indicators, green; launch it! + try { + if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + SwingUtilities.invokeAndWait(() -> { + try { + StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + SwingUtilities.invokeLater(() -> { + try { + StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); } + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); } } finally { this.removeTaskFromDispatcher(currentTask); @@ -207,12 +214,11 @@ public Object construct() { return this.resultsHash; } - public void finished() { + public void performSwingPostProcessing() { this.announceTaskComplete(); - if (this.pp != null) { - this.pp.stop(); - } + if (this.progressPopup != null) this.progressPopup.stop(); + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())) { // something went wrong StringBuilder allCausesErrorMessageSB = new StringBuilder(); @@ -241,7 +247,7 @@ public void finished() { (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())); } else if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { // depending on where user canceled we might want to automatically start a new job - StandardSwingWorker.dispatchFollowUp(this.resultsHash); + StandardVCellSwingWorker.dispatchFollowUp(this.resultsHash); } ClientTaskDispatcher.FinalWindow fw = ResultsHashUtils.fetch(this.resultsHash, TaskEventKeys.FINAL_WINDOW.toString(), ClientTaskDispatcher.FinalWindow.class, false); @@ -283,7 +289,7 @@ private static void dispatchFollowUp(Hashtable hash) { */ private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { StringBuilder sb = new StringBuilder(); - sb.append("Data error for task " + currentTask.getTaskName() + '\n'); + sb.append("Data error for task ").append(currentTask.getTaskName()).append('\n'); return sb; } diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java similarity index 70% rename from vcell-client/src/main/java/swingthreads/SwingWorker.java rename to vcell-client/src/main/java/swingthreads/VCellSwingWorker.java index f8df2c5e18..f31f0c8690 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java @@ -1,11 +1,13 @@ package swingthreads; -import cbit.vcell.client.task.ClientTaskDispatcher; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.swing.SwingUtilities; -import java.lang.reflect.Field; +import java.util.Hashtable; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; /** * This is the 3rd version of SwingWorker (also known as @@ -43,11 +45,6 @@ synchronized void clear() { } } - // Instance Variables - private Object value; // see getValue(), setValue() - private final ThreadVar threadVar; - - /** * set {@link SwingWorker} thread name * @@ -63,26 +60,25 @@ public void setThreadName(String name) { } } + // Instance Variables + private Hashtable value; // see getValue(), setValue() + private final ThreadVar threadVar; + /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ - protected synchronized Object getValue() { + protected synchronized Hashtable getValue() { return this.value; } /** * Set the value produced by worker thread */ - private synchronized void setValue(Object x) { + private synchronized void setValue(Hashtable x) { this.value = x; } - /** - * Compute the value to be returned by the get method. - */ - public abstract Object construct(); - /** * A new method that interrupts the worker thread. Call this method * to force the worker to stop what it's doing. @@ -100,10 +96,10 @@ public void interrupt() { * * @return the value created by the construct method */ - public Object get() { + public Hashtable get() { while (true) { Thread t = this.threadVar.get(); - if (t == null) return this.getValue(); + if (t == null) return this.getValue(); // thread finished! try { t.join(); @@ -119,36 +115,46 @@ public Object get() { * and then exit. */ public SwingWorker() { - final Runnable doFinished = SwingWorker.this::finished; - - Runnable doConstruct = new Runnable() { + Runnable doWork = new Runnable() { public void run() { try { - SwingWorker.this.setValue(SwingWorker.this.construct()); + SwingWorker.this.setValue(SwingWorker.this.verifyAndRun()); // Invoke now, on the current thread } finally { + // At the time this is called, the thread is running SwingWorker.this.threadVar.clear(); + // We do this to make sure we never accidentally re-run the same thread. + // We must ensure "one and done" threading. } - SwingUtilities.invokeLater(doFinished); + SwingUtilities.invokeLater(SwingWorker.this::performSwingPostProcessing); } }; - Thread t = new Thread(doConstruct); - this.threadVar = new ThreadVar(t); + this.threadVar = new ThreadVar(new Thread(doWork)); } + /** + * Compute the value to be returned by the get method. + */ + public abstract Hashtable verifyAndRun(); + /** * Called on the event dispatching thread (not on the worker thread) * after the construct method has returned. */ - public void finished() {} + public abstract void performSwingPostProcessing(); /** * Start the worker thread. */ - public void start() { + public Future> start() { Thread t = this.threadVar.get(); + FutureTask> ft = new FutureTask<>(t.start(), this.); if (t != null) { - t.start(); + ft.run(); + return ft; } + + // Generally, getting here means we've already run the thread. + return t.start(); } } \ No newline at end of file From 9fb88feac83771fcb1a20136fa1dcdca79959397 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 14:41:27 -0400 Subject: [PATCH 11/48] Change API logging to display certain info notices when debug is enabled --- .../org/vcell/api/client/VCellApiClient.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java index 1c7b284458..22ba2e0da3 100644 --- a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java +++ b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java @@ -202,13 +202,13 @@ public SimulationTaskRepresentation[] getSimTasks(SimTasksQuerySpec simTasksQuer HttpGet httpget = new HttpGet(getApiUrlPrefix() + "/simtask?" + simTasksQuerySpec.getQueryString()); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation tasks " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getSimTasks()", httpget), httpClientContext); String simTasksJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(simTasksJson)); } @@ -231,13 +231,13 @@ public BiomodelRepresentation[] getBioModels(BioModelsQuerySpec bioModelsQuerySp HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel?"+bioModelsQuerySpec.getQueryString()); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve biomodels " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getBioModels()", httpget), httpClientContext); String bimodelsJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(bimodelsJson)); } @@ -251,13 +251,13 @@ public EventWrapper[] getEvents(long beginTimestamp) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/events?beginTimestamp="+beginTimestamp); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve user events " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getEvents()", httpget), httpClientContext); String eventWrappersJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(eventWrappersJson)); } @@ -271,13 +271,13 @@ public BiomodelRepresentation getBioModel(String bmId) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve biomodel " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getBioModel()", httpget), httpClientContext); String bimodelsJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(bimodelsJson)); } @@ -291,7 +291,7 @@ public String getBioModelVCML(String bmId) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId+"/biomodel.vcml"); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve biomodel " + httpget.getRequestLine()); } @@ -306,13 +306,13 @@ public SimulationRepresentation getSimulation(String bmId, String simKey) throws HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getSimulation()", httpget), httpClientContext); String simulationJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(simulationJson)); } @@ -326,12 +326,12 @@ public String getOptRunJson(String optimizationId,boolean bStop) throws IOExcept HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/optimization/"+optimizationId+"?bStop="+bStop); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve optimization run " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getOptRunJson()", httpget), httpClientContext); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(responseBody)); } return responseBody; @@ -429,7 +429,7 @@ public SimulationTaskRepresentation[] startSimulation(String bmId, String simKey HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey+"/startSimulation"); httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation " + httppost.getRequestLine()); } @@ -453,13 +453,13 @@ public SimulationTaskRepresentation[] stopSimulation(String bmId, String simKey) HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey+"/stopSimulation"); httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation " + httppost.getRequestLine()); } String responseBody = httpclient.execute(httppost, new VCellStringResponseHandler("stopSimulation()", httppost), httpClientContext); String simTaskReps = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(simTaskReps)); } @@ -826,7 +826,7 @@ public String getServerSoftwareVersion() throws ClientProtocolException, IOExcep HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/swversion"); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve server software version " + httpget.getRequestLine()); } From 4b5d06316e057d7b02b5f5e1a2e51ab04a4ec883 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 15:59:26 -0400 Subject: [PATCH 12/48] More transition from magic strings to enums --- .../src/main/java/cbit/vcell/client/ClientRequestManager.java | 4 ++-- .../main/java/cbit/vcell/client/DatabaseWindowManager.java | 3 ++- .../main/java/cbit/vcell/client/DocumentWindowManager.java | 3 ++- .../src/main/java/cbit/vcell/client/data/PDEDataViewer.java | 4 ++-- .../src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java | 3 ++- .../java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java | 2 +- .../src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java | 4 ++-- .../java/cbit/vcell/mapping/gui/InitialConditionsPanel.java | 4 ++-- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index f8dd1b13d0..dccc7126e6 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -474,7 +474,7 @@ public boolean closeWindow(final java.lang.String windowID, final boolean exitIf @Override public void run(Hashtable hashTable) throws Exception { // if there is error saving the document, try to unblock the window - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) != null) { + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { getMdiManager().unBlockWindow(windowID); getMdiManager().showWindow(windowID); } else { @@ -3544,7 +3544,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { try { - Throwable exc = (Throwable) hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + Throwable exc = (Throwable) hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); if (exc == null) { boolean isSEDML = (boolean) hashTable.get("isSEDML"); if (isSEDML) { diff --git a/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java b/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java index e2228d5513..5340889359 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java @@ -40,6 +40,7 @@ import org.vcell.util.gui.GeneralGuiUtils; import org.vcell.util.gui.VCFileChooser; import org.vcell.util.gui.exporter.FileFilters; +import swingthreads.TaskEventKeys; import javax.swing.Timer; import javax.swing.*; @@ -541,7 +542,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { try { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null) { XmlTreeDiff xmlTreeDiff = (XmlTreeDiff) hashTable.get("xmlTreeDiff"); String baselineDesc = docInfo1.getVersion().getName() + ", " + docInfo1.getVersion().getDate(); String modifiedDesc = docInfo2.getVersion().getName() + ", " + docInfo2.getVersion().getDate(); diff --git a/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java b/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java index 47b0825404..881caab1c5 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java @@ -37,6 +37,7 @@ import cbit.vcell.simdata.OutputContext; import cbit.vcell.solver.VCSimulationIdentifier; import cbit.xml.merge.XmlTreeDiff; +import swingthreads.TaskEventKeys; public abstract class DocumentWindowManager extends TopLevelWindowManager implements java.awt.event.ActionListener, DataViewerManager { @@ -119,7 +120,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { try { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null) { XmlTreeDiff xmlTreeDiff = (XmlTreeDiff)hashTable.get("xmlTreeDiff"); String baselineDesc = getVCDocument()+ ", " + (getVCDocument().getVersion() == null ? "not saved" : getVCDocument().getVersion().getDate()); String modifiedDesc = "Opened document instance"; diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java b/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java index 311550adf0..baff043ac0 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java @@ -3333,7 +3333,7 @@ private boolean errorAutoAllTimes(boolean bPPInfo,Boolean bVarMatch,boolean isFi // }; // AsynchClientTask task3 = new AsynchClientTask("Setting cursor", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { // public void run(Hashtable hashTable) throws Exception { -// Throwable exc = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); +// Throwable exc = (Throwable)hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); // if (exc == null) { // updateTimeTextField(getPdeDataContext().getTimePoint()); // } else { @@ -3404,7 +3404,7 @@ private boolean errorAutoAllTimes(boolean bPPInfo,Boolean bVarMatch,boolean isFi // // AsynchClientTask task3 = new AsynchClientTask("Setting cursor", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { // public void run(Hashtable hashTable) throws Exception { -// Throwable e = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); +// Throwable e = (Throwable)hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); // if (e != null) { // int index = -1; // if(getPdeDataContext() != null && getPdeDataContext().getDataIdentifier() != null){ diff --git a/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java b/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java index b9e264192f..6bb376a3a5 100644 --- a/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java @@ -80,6 +80,7 @@ import cbit.vcell.simdata.SimulationData; import cbit.vcell.solver.SimulationInfo; import cbit.vcell.solvers.CartesianMesh; +import swingthreads.TaskEventKeys; public class FieldDataGUIPanel extends JPanel{ @@ -1388,7 +1389,7 @@ public int compare(DataIdentifier o1, DataIdentifier o2) { getJTree1().expandPath(new TreePath(varNode.getPath())); } }catch(Throwable e){ - hash.put(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR,e); + hash.put(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString(), e); } } }; diff --git a/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java b/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java index b6f69641ba..c944a4aa02 100644 --- a/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java +++ b/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java @@ -429,7 +429,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask failTask = new AsynchClientTask("Check fail...",AsynchClientTask.TASKTYPE_SWING_BLOCKING,false,false,true) { @Override public void run(Hashtable hashTable) throws Exception { - Throwable throwable = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + Throwable throwable = (Throwable)hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); if(throwable != null){ //cleanup ComboboxROIName[] comboboxROINames = overlayEditorPanelJAI.getAllCompositeROINamesAndColors(); diff --git a/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java b/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java index d6076e75ac..af0035b3c2 100644 --- a/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java +++ b/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java @@ -634,9 +634,9 @@ public void run(Hashtable hashTable)throws Exception { AsynchClientTask reshowInterface = new AsynchClientTask("Reshow interface...",AsynchClientTask.TASKTYPE_NONSWING_BLOCKING,false,true) { @Override public void run(Hashtable hashTable) throws Exception { - Object error = hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + Object error = hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); if(assignmentHelper.getAssignmentInterface() != null && error != null) { - hashTable.remove(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + hashTable.remove(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); //Reshow the interface if there was an error new Thread(new Runnable() { @Override diff --git a/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java b/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java index d08fa5dbf1..5a02858678 100644 --- a/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java @@ -306,7 +306,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) != null) { + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { getSimulationContext().setUsingConcentration(false, true); updateTopScrollPanel(); } @@ -347,7 +347,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) != null) { + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { getSimulationContext().setUsingConcentration(true, true); updateTopScrollPanel(); } From 1f416bb1a80a75bb0b942cc25066a83c8e243f4a Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 15:59:47 -0400 Subject: [PATCH 13/48] Changed name to match similar closures --- .../src/main/java/cbit/vcell/client/ClientSimManager.java | 2 +- .../cbit/vcell/client/desktop/biomodel/MathematicsPanel.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java index 0432bc61fc..eb42d8ef30 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java @@ -607,7 +607,7 @@ public void cancelButton_actionPerformed(EventObject newEvent) { } }; tasks.add(pv); - ClientTaskDispatcher.dispatchColl(documentWindowManager.getComponent(), new Hashtable(), tasks, false, true, null); + ClientTaskDispatcher.dispatch(documentWindowManager.getComponent(), new Hashtable(), tasks, false, true, null); } public void runQuickSimulation(final Simulation originalSimulation, ViewerType viewerType) { diff --git a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java index f35db026df..7b89a71edb 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java @@ -184,14 +184,14 @@ private javax.swing.JRadioButton getViewVCMDLRadioButton() { } private void refreshMath() { - ClientTaskDispatcher.dispatchColl(MathematicsPanel.this, new Hashtable(), ClientRequestManager.updateMath(this, simulationContext, true,NetworkGenerationRequirements.ComputeFullStandardTimeout), false); + ClientTaskDispatcher.dispatch(MathematicsPanel.this, new Hashtable(), ClientRequestManager.updateMath(this, simulationContext, true,NetworkGenerationRequirements.ComputeFullStandardTimeout), false); } private void createMathModel(final ActionEvent e) { // relays an action event with this as the source Collection tasks = ClientRequestManager.updateMath(this, simulationContext, true,NetworkGenerationRequirements.ComputeFullStandardTimeout); tasks.add(new AsynchClientTaskFunction(ht -> refireActionPerformed(e),"creating math model", AsynchClientTask.TASKTYPE_SWING_BLOCKING) ); - ClientTaskDispatcher.dispatchColl(this, new Hashtable(), tasks, false); + ClientTaskDispatcher.dispatch(this, new Hashtable(), tasks, false); } public synchronized void addActionListener(ActionListener l) { From f6316908f6cd5e1d54ceb2cbcf0415d57c4f220c Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 16:01:01 -0400 Subject: [PATCH 14/48] Integrated Futures into newly named VCellSwingWorker system --- .../vcell/client/task/AsynchClientTask.java | 2 +- .../client/task/ClientTaskDispatcher.java | 152 ++++++++++++++---- .../StandardVCellSwingWorker.java | 2 +- .../java/swingthreads/VCellSwingWorker.java | 75 +++++---- 4 files changed, 165 insertions(+), 66 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java index eb86117b7c..1adb2c52da 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java @@ -116,7 +116,7 @@ public void setClientTaskStatusSupport(ClientTaskStatusSupport clientTaskStatusS this.clientTaskStatusSupport = clientTaskStatusSupport; } - public boolean showProgressPopup() { + public boolean shouldShowProgressPopup() { return this.bShowProgressPopup; } diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 3d25b7839a..264ea6c091 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -16,11 +16,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.EventObject; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.WeakHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import javax.swing.Timer; @@ -32,8 +35,8 @@ import org.vcell.util.gui.ProgressDialog; import cbit.vcell.simdata.PDEDataContext; -import swingthreads.StandardSwingWorker; -import swingthreads.SwingWorker; +import swingthreads.StandardVCellSwingWorker; +import swingthreads.VCellSwingWorker; import swingthreads.TaskEventKeys; /** @@ -44,6 +47,7 @@ */ public class ClientTaskDispatcher { private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); + private static final long DEFAULT_TIMEOUT = 5000;//ms /** * used to count / generate thread names */ @@ -74,25 +78,71 @@ public static void dispatch(Component requester, Hashtable hash, ClientTaskDispatcher.dispatch(requester, hash, tasks, false, false, false, null, false); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, false, false, false, null, false); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, false, false, false, null, false); + } + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, false, null, false); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, true, bKnowProgress, false, null, false); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, true, bKnowProgress, false, null, false); + } + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener) { ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + } + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } + public static Future> dispatchWithFuture(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchAndWait(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + public static boolean isBusy() { // System.out.println("----------Busy----------"); return entryCounter > 0; @@ -250,11 +300,51 @@ public static void dispatch(final Component requester, final Hashtable> dispatchWithFuture(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, + bInputBlocking, StopStrategy.THREAD_INTERRUPT); + } + + public static void dispatchAndWait(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, + bInputBlocking, StopStrategy.THREAD_INTERRUPT); + } + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking, final StopStrategy stopStrategy) { + ClientTaskDispatcher.masterDispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, + progressDialogListener, bInputBlocking, stopStrategy, false); + } + + public static Future> dispatchWithFuture(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy){ + return ClientTaskDispatcher.masterDispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, + progressDialogListener, bInputBlocking, stopStrategy, false); + } + + public static void dispatchAndWait(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy){ + ClientTaskDispatcher.masterDispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, + progressDialogListener, bInputBlocking, stopStrategy, true); + } + + private static Future> masterDispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy, final boolean blockUntilDone){ final String threadBaseName = "ClientTaskDispatcher " + (serial++) + ' '; final List taskList = new ArrayList<>(); @@ -281,8 +371,8 @@ public static void dispatch(final Component requester, final Hashtable> futureResult = worker.start(); + if (!blockUntilDone) return futureResult; + try { + futureResult.get(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + lg.error("Unexpected exception occurred during execution of {} : ", threadBaseName, e); + lg.error(e); + } catch (InterruptedException e) { + lg.error("Unexpected thread interruption of {}: ", threadBaseName); + lg.error(e); + } catch (TimeoutException e) { + lg.error("Unexpected timeout occurred during execution of {} : ", threadBaseName); + lg.error(e); + } + return futureResult; } /** @@ -308,8 +412,7 @@ public void announceTaskComplete() { * @return wrapper */ public static Runnable debugWrapper(Runnable r) { - return () -> - { + return () -> { lg.debug("calling " + r.getClass().getName() + ".run on " + r); r.run(); }; @@ -351,33 +454,16 @@ public static boolean hasOutstandingTasks() { } //updated API - public static void dispatchColl(Component requester, Hashtable hash, Collection coll) { - dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new)); - } - - public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { + // Extend if desired! + public static void dispatch(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress); } - public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener) { + public static void dispatch(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener); } - public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener, bInputBlocking); - } - - public static void dispatchColl(final Component requester, final Hashtable hash, Collection coll, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); - } - - public static void dispatchColl(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - } - //package public interface FinalWindow extends Runnable { @@ -404,4 +490,12 @@ static void setFinalWindow(Hashtable hash, FinalWindow fWindow) String n = ClassUtils.getShortClassName(fWindow, def); throw new ProgrammingException("duplicate final windows" + e + " and " + n); } + + private void removeTaskFromDispatcher(AsynchClientTask task) { + ClientTaskDispatcher.allTasks.remove(task); + } + + public void announceTaskComplete() { + ClientTaskDispatcher.entryCounter--; + } } diff --git a/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java index ebd30de5b4..002942e312 100644 --- a/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java @@ -192,7 +192,7 @@ public Hashtable verifyAndRun() { try { StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); + ClientTaskDispatcher.recordException(exc, StandardVCellSwingWorker.this.resultsHash); } }); } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { diff --git a/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java index f31f0c8690..16b7a40b5b 100644 --- a/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java @@ -10,8 +10,11 @@ import java.util.concurrent.FutureTask; /** - * This is the 3rd version of SwingWorker (also known as - * SwingWorker 3), an abstract class that you subclass to + * This class is based upon the 3rd version of SwingWorker (also known as + * SwingWorker 3). Its job is to serve as a worker that dispatches tasks to the correct endpoints (swing or otherwise), + * based on the type of AsynchClientTask requested. + *

+ * SwingWorker 3 is an abstract class that you subclass to * perform GUI-related work in a dedicated thread. For * instructions on using this class, see: *

@@ -21,19 +24,21 @@ * You must now invoke start() on the SwingWorker after * creating it. */ -public abstract class SwingWorker { - private static final Logger lg = LogManager.getLogger(SwingWorker.class); +public abstract class VCellSwingWorker { + private static final Logger lg = LogManager.getLogger(VCellSwingWorker.class); /** * Class to maintain reference to current worker thread * under separate synchronization control. */ - private static class ThreadVar { + private static class TaskThread { private Thread thread; + private final FutureTask> futureTask; - ThreadVar(Thread t) { - this.thread = t; + TaskThread(Callable> callableTask) { + this.futureTask = new FutureTask<>(callableTask); + this.thread = new Thread(this.futureTask); } synchronized Thread get() { @@ -43,10 +48,16 @@ synchronized Thread get() { synchronized void clear() { this.thread = null; } + + Future> start(){ + if (this.thread == null) return this.futureTask; // do not rerun the task! It's already done. + this.thread.start(); + return this.futureTask; + } } /** - * set {@link SwingWorker} thread name + * set {@link VCellSwingWorker} thread name * * @param name may not be null * @throws IllegalArgumentException if name is null @@ -54,29 +65,29 @@ synchronized void clear() { public void setThreadName(String name) { if (name == null) throw new IllegalArgumentException("name may not be null"); try { - this.threadVar.thread.setName(name); + this.threadedTask.thread.setName(name); } catch (SecurityException e) { lg.warn("setSwingWorkerName fail", e); } } // Instance Variables - private Hashtable value; // see getValue(), setValue() - private final ThreadVar threadVar; + private Hashtable hashResults; // see getValue(), setValue() + private final TaskThread threadedTask; /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ - protected synchronized Hashtable getValue() { - return this.value; + protected synchronized Hashtable getHashResults() { + return this.hashResults; } /** * Set the value produced by worker thread */ - private synchronized void setValue(Hashtable x) { - this.value = x; + private synchronized void setHashResults(Hashtable x) { + this.hashResults = x; } /** @@ -84,9 +95,9 @@ private synchronized void setValue(Hashtable x) { * to force the worker to stop what it's doing. */ public void interrupt() { - Thread t = this.threadVar.get(); + Thread t = this.threadedTask.get(); if (t != null) t.interrupt(); - this.threadVar.clear(); + this.threadedTask.clear(); } /** @@ -98,8 +109,8 @@ public void interrupt() { */ public Hashtable get() { while (true) { - Thread t = this.threadVar.get(); - if (t == null) return this.getValue(); // thread finished! + Thread t = this.threadedTask.get(); + if (t == null) return this.getHashResults(); // thread finished! try { t.join(); @@ -114,22 +125,24 @@ public Hashtable get() { * Start a thread that will call the construct method * and then exit. */ - public SwingWorker() { - Runnable doWork = new Runnable() { - public void run() { + public VCellSwingWorker() { + Callable> doWork = new Callable<>() { + @Override + public Hashtable call() { try { - SwingWorker.this.setValue(SwingWorker.this.verifyAndRun()); // Invoke now, on the current thread + VCellSwingWorker.this.setHashResults(VCellSwingWorker.this.verifyAndRun()); // Invoke now, on the current thread } finally { // At the time this is called, the thread is running - SwingWorker.this.threadVar.clear(); + VCellSwingWorker.this.threadedTask.clear(); // We do this to make sure we never accidentally re-run the same thread. // We must ensure "one and done" threading. } - SwingUtilities.invokeLater(SwingWorker.this::performSwingPostProcessing); + SwingUtilities.invokeLater(VCellSwingWorker.this::performSwingPostProcessing); + return VCellSwingWorker.this.hashResults; } }; - this.threadVar = new ThreadVar(new Thread(doWork)); + this.threadedTask = new TaskThread(doWork); } /** @@ -147,14 +160,6 @@ public void run() { * Start the worker thread. */ public Future> start() { - Thread t = this.threadVar.get(); - FutureTask> ft = new FutureTask<>(t.start(), this.); - if (t != null) { - ft.run(); - return ft; - } - - // Generally, getting here means we've already run the thread. - return t.start(); + return this.threadedTask.start(); } } \ No newline at end of file From 7550f35e7a52c1c72577c7f49e9f3215582cdfa5 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 10:16:06 -0400 Subject: [PATCH 15/48] Changed to blocking call; currently negligible delay --- .../src/main/java/cbit/vcell/client/ClientRequestManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index dccc7126e6..746127fc9f 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -352,9 +352,8 @@ public void run(Hashtable hashTable) throws Exception { hashTable.put(IS_CHANGED_KEY, hasBeenChanged); } }; - ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[]{checkIfChanged}, + ClientTaskDispatcher.dispatchAndWait(null, hashtable, new AsynchClientTask[]{checkIfChanged}, false, false, null, true); - ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[] {checkIfChanged}); if (hashtable.containsKey(IS_CHANGED_KEY)) isChanged = (Boolean)hashtable.get(IS_CHANGED_KEY); else if (hashtable.containsKey("clientTaskDispatcherStackTraceArray")){ @@ -463,6 +462,7 @@ public boolean closeWindow(final java.lang.String windowID, final boolean exitIf getMdiManager().showWindow(windowID); getMdiManager().blockWindow(windowID); CloseOption closeOption = checkBeforeClosing((DocumentWindowManager) windowManager); + lg.error("Yup, he's not dead Jim"); if (closeOption.equals(CloseOption.CANCEL_CLOSE)) { // user canceled getMdiManager().unBlockWindow(windowID); From 9fec4a766c4a409fcbe5bbfa106dfd3cb561374c Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 11:19:24 -0400 Subject: [PATCH 16/48] changed to debug call --- .../vcell/client/desktop/biomodel/AnnotationsPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java index 88c39fd626..5fd1d38c45 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java @@ -26,6 +26,8 @@ import cbit.vcell.model.*; import cbit.vcell.xml.gui.MiriamTreeModel; import cbit.vcell.xml.gui.MiriamTreeModel.LinkNode; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.vcell.model.rbm.MolecularType; import org.vcell.pathway.BioPaxObject; import org.vcell.sybil.models.AnnotationQualifiers; @@ -59,6 +61,8 @@ */ @SuppressWarnings("serial") public class AnnotationsPanel extends DocumentEditorSubPanel { + private static Logger lg = LogManager.getLogger(AnnotationsPanel.class); + private BioModel bioModel = null; private VCMetaData vcMetaData = null; MiriamTreeModel miriamTreeModel = null; @@ -517,7 +521,7 @@ public JComboBox getJComboBoxURI() { @Override public void actionPerformed(ActionEvent e) { VCMetaDataDataType mdt = (VCMetaDataDataType)jComboBoxURI.getSelectedItem(); - System.out.println("aici"); + lg.debug("aici"); if(mdt != null && mdt.isSearchable()) { getJButtonSearchRef().setEnabled(true); } else { From 3c1296e285e0e0c5059c817ed7b0ce1506911baf Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 11:20:12 -0400 Subject: [PATCH 17/48] Removed object synchronization, and instead locked on the object; may need to synchronize on the specific manager, but not sure. --- .../client/server/AsynchMessageManager.java | 309 ++++++------------ 1 file changed, 98 insertions(+), 211 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index a7931d8085..a2d7ffbf61 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -54,22 +54,19 @@ public class AsynchMessageManager implements SimStatusListener, DataAccessExcept private static Logger lg = LogManager.getLogger(AsynchMessageManager.class); private EventListenerList listenerList = new EventListenerList(); - private ClientServerManager clientServerManager = null; + private ClientServerManager clientServerManager; private int failureCount = 0; private ScheduledExecutorService executorService = null; private long counter = 0; private long pollTime = BASE_POLL_SECONDS; - private AtomicBoolean bPoll = new AtomicBoolean(false); + private AtomicBoolean isPollingEnabled = new AtomicBoolean(false); private ScheduledFuture pollingHandle = null; /** * for {@link #schedule(long)} method */ private final ReentrantLock scheduleLock = new ReentrantLock(); + private final ReentrantLock connectionLock = new ReentrantLock(); -/** - * Insert the method's description here. - * Creation date: (6/9/2004 4:55:22 PM) - */ public AsynchMessageManager(ClientServerManager csm) { this.clientServerManager = csm; } @@ -78,19 +75,19 @@ public AsynchMessageManager(ClientServerManager csm) { * no-op if already called */ public synchronized void startPolling() { - if (!bPoll.get()) { - bPoll.set(true); - if (executorService == null) { - executorService = VCellExecutorService.get(); - DataAccessException.addListener(this); - } - schedule(pollTime); + if (isPollingEnabled.get()) return; + isPollingEnabled.set(true); + if (executorService == null) { + executorService = VCellExecutorService.get(); + DataAccessException.addListener(this); } + schedule(pollTime); + } public void stopPolling() { // lg.trace("stopping polling"); - bPoll.set(false); + isPollingEnabled.set(false); } @Override @@ -101,73 +98,57 @@ public void created(DataAccessException dae) { schedule(0); } private void poll( ) { - if (!bPoll.get()) { - if (lg.isDebugEnabled()){ - lg.debug("polling stopped"); - } + if (!isPollingEnabled.get()) { + lg.debug("polling stopped"); return; } - - if (lg.isDebugEnabled()){ - lg.debug("polling"); - } - boolean report = counter%50 == 0; + + lg.debug("polling"); + boolean shouldReport = counter % 50 == 0; long begin = 0; long end = 0; - // + // ask remote message listener (really should be "message producer") for any queued events. - // try { - MessageEvent[] queuedEvents = null; - if (report) { - // time the call - begin = System.currentTimeMillis(); - } - synchronized (this) { - if (!clientServerManager.isStatusConnected()) { - clientServerManager.attemptReconnect( ); - return; - } - pollTime = BASE_POLL_SECONDS; - queuedEvents = clientServerManager.getMessageEvents(); + MessageEvent[] queuedEvents; + if (shouldReport) begin = System.currentTimeMillis(); // time the call + + if (!clientServerManager.isStatusConnected()){ + connectionLock.lock(); + clientServerManager.attemptReconnect(); + return; } - if (report) { - end = System.currentTimeMillis(); - } + pollTime = BASE_POLL_SECONDS; + queuedEvents = clientServerManager.getMessageEvents(); + + if (shouldReport) end = System.currentTimeMillis(); + failureCount = 0; //this is skipped if the connection has failed:w // deal with events, if any - if (queuedEvents != null) { - for (MessageEvent messageEvent : queuedEvents){ - onMessageEvent(messageEvent); - } - } - // report polling call performance - if (report) { - double duration = ((double)(end - begin)) / 1000; - PerformanceMonitorEvent performanceMonitorEvent = new PerformanceMonitorEvent( - this, null, new PerformanceData( - "AsynchMessageManager.poll()", - MessageEvent.POLLING_STAT, - new PerformanceDataEntry[] {new PerformanceDataEntry("remote call duration", Double.toString(duration))} - ) - ); - } + if (queuedEvents != null) for (MessageEvent messageEvent : queuedEvents) onMessageEvent(messageEvent); + if (!shouldReport) return; + + // report polling call performance + double duration = ((double) (end - begin)) / 1000; + PerformanceMonitorEvent performanceMonitorEvent = new PerformanceMonitorEvent( + this, null, new PerformanceData( + "AsynchMessageManager.poll()", + MessageEvent.POLLING_STAT, + new PerformanceDataEntry[] {new PerformanceDataEntry("remote call duration", Double.toString(duration))} + ) + ); } catch (Exception exc) { - System.out.println(">> polling failure << " + exc.getMessage()); + lg.error(">> POLLING FAILURE <<", exc); pollTime = ATTEMPT_POLL_SECONDS; failureCount ++; if (failureCount % 3 == 0) { - bPoll.set(false); + isPollingEnabled.set(false); clientServerManager.setDisconnected(); } - } - finally { - if (lg.isDebugEnabled()) { - lg.debug(ExecutionTrace.justClassName(this) + " poll time " + pollTime + " seconds"); - } - if (bPoll.get()){ - schedule(pollTime); - } + } finally { + connectionLock.unlock(); + lg.debug(ExecutionTrace.justClassName(this) + " poll time " + pollTime + " seconds"); + if (isPollingEnabled.get()) schedule(pollTime); } } @@ -203,56 +184,39 @@ private void onMessageEvent(MessageEvent event) { } } -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void addDataJobListener(DataJobListener listener) { - listenerList.add(DataJobListener.class, listener); +public void addDataJobListener(DataJobListener listener) { + synchronized (listenerList){ + listenerList.add(DataJobListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void addExportListener(ExportListener listener) { - listenerList.add(ExportListener.class, listener); +public void addExportListener(ExportListener listener) { + synchronized (listenerList){ + listenerList.add(ExportListener.class, listener); + } } - -/** - * addSimulationStatusEventListener method comment. - */ -public synchronized void addSimStatusListener(SimStatusListener listener) { - listenerList.add(SimStatusListener.class, listener); +public void addSimStatusListener(SimStatusListener listener) { + synchronized (listenerList){ + listenerList.add(SimStatusListener.class, listener); + } } -/** - * addSimulationStatusEventListener method comment. - */ -public synchronized void addSimulationJobStatusListener(SimulationJobStatusListener listener) { - listenerList.add(SimulationJobStatusListener.class, listener); +public void addSimulationJobStatusListener(SimulationJobStatusListener listener) { + synchronized (listenerList){ + listenerList.add(SimulationJobStatusListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (6/19/2006 12:51:56 PM) - * @param listener cbit.vcell.desktop.controls.ExportListener - */ public void addVCellMessageEventListener(VCellMessageEventListener listener) { - listenerList.add(VCellMessageEventListener.class, listener); + synchronized (listenerList){ + listenerList.add(VCellMessageEventListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.ExportEvent - */ protected void fireDataJobEvent(DataJobEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -261,31 +225,15 @@ protected void fireDataJobEvent(DataJobEvent event) { // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==DataJobListener.class) { - fireDataJobEvent(event, (DataJobListener)listeners[i+1]); - } - } + if (listeners[i] != DataJobListener.class) continue; + fireDataJobEvent(event, (DataJobListener) listeners[i + 1]); + } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireDataJobEvent(final DataJobEvent event, final DataJobListener listener) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - listener.dataJobMessage(event); - } - }); + SwingUtilities.invokeLater(() -> listener.dataJobMessage(event)); } - -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.ExportEvent - */ protected void fireExportEvent(ExportEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -294,58 +242,31 @@ protected void fireExportEvent(ExportEvent event) { // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==ExportListener.class) { - fireExportEvent(event, (ExportListener)listeners[i+1]); - } - } + if (listeners[i] != ExportListener.class) continue; + fireExportEvent(event, (ExportListener) listeners[i + 1]); + } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireExportEvent(final ExportEvent event, final ExportListener listener) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - listener.exportMessage(event); - } - }); + SwingUtilities.invokeLater(() -> listener.exportMessage(event)); } -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.JobCompletedEvent - */ protected void fireSimStatusEvent(SimStatusEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==SimStatusListener.class) { - fireSimStatusEvent(event, (SimStatusListener)listeners[i+1]); - } + if (listeners[i] != SimStatusListener.class) continue; + fireSimStatusEvent(event, (SimStatusListener)listeners[i+1]); } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireSimStatusEvent(final SimStatusEvent event, final SimStatusListener listener) { listener.simStatusChanged(event); } - -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.JobCompletedEvent - */ protected void fireSimulationJobStatusEvent(SimulationJobStatusEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -354,27 +275,15 @@ protected void fireSimulationJobStatusEvent(SimulationJobStatusEvent event) { // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==SimulationJobStatusListener.class) { - fireSimulationJobStatusEvent(event, (SimulationJobStatusListener)listeners[i+1]); - } + if (listeners[i] != SimulationJobStatusListener.class) continue; + fireSimulationJobStatusEvent(event, (SimulationJobStatusListener)listeners[i+1]); } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireSimulationJobStatusEvent(final SimulationJobStatusEvent event, final SimulationJobStatusListener listener) { listener.simulationJobStatusChanged(event); } - -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.ExportEvent - */ protected void fireVCellMessageEvent(VCellMessageEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -389,71 +298,49 @@ protected void fireVCellMessageEvent(VCellMessageEvent event) { } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireVCellMessageEvent(final VCellMessageEvent event, final VCellMessageEventListener listener) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - listener.onVCellMessageEvent(event); - } - }); + SwingUtilities.invokeLater(() -> listener.onVCellMessageEvent(event)); } -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void removeDataJobListener(DataJobListener listener) { - listenerList.remove(DataJobListener.class, listener); +public void removeDataJobListener(DataJobListener listener) { + synchronized (listenerList){ + listenerList.remove(DataJobListener.class, listener); + } } - -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void removeExportListener(ExportListener listener) { - listenerList.remove(ExportListener.class, listener); +public void removeExportListener(ExportListener listener) { + synchronized (listenerList){ + listenerList.remove(ExportListener.class, listener); + } } /** * removeSimulationStatusEventListener method comment. */ -public synchronized void removeSimStatusListener(SimStatusListener listener) { - listenerList.remove(SimStatusListener.class, listener); +public void removeSimStatusListener(SimStatusListener listener) { + synchronized (listenerList){ + listenerList.remove(SimStatusListener.class, listener); + } } /** * removeSimulationStatusEventListener method comment. */ -public synchronized void removeSimulationJobStatusListener(SimulationJobStatusListener listener) { - listenerList.remove(SimulationJobStatusListener.class, listener); +public void removeSimulationJobStatusListener(SimulationJobStatusListener listener) { + synchronized (listenerList){ + listenerList.remove(SimulationJobStatusListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (6/19/2006 12:54:05 PM) - * @param listener cbit.vcell.desktop.controls.ExportListener - */ public void removeVCellMessageEventListener(VCellMessageEventListener listener) { - listenerList.remove(VCellMessageEventListener.class, listener); + synchronized (listenerList){ + listenerList.remove(VCellMessageEventListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (6/9/2004 2:27:28 PM) - * @param newJobStatus cbit.vcell.messaging.db.SimulationJobStatus - * @param progress java.lang.Double - * @param timePoint java.lang.Double - */ public void simStatusChanged(SimStatusEvent simStatusEvent) { // refire for swing fireSimStatusEvent(simStatusEvent); From 975aee641176e8ab076aee2cc1a118c468153ce8 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 10:06:36 -0400 Subject: [PATCH 18/48] Formatting updates --- .../client/task/ClientTaskDispatcher.java | 14 ++++----- .../client/server/ClientServerManager.java | 6 ++-- .../vcell/clientdb/ClientDocumentManager.java | 30 ++++++++----------- .../org/vcell/util/VCellThreadChecker.java | 24 ++++----------- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 42153d8ba5..6e6749aa3e 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -89,26 +89,26 @@ public class ClientTaskDispatcher { * @param tasks cbit.vcell.desktop.controls.ClientTask[] */ public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks) { - dispatch(requester,hash,tasks,false, false, false, null, false); + ClientTaskDispatcher.dispatch(requester,hash,tasks,false, false, false, null, false); } public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { - dispatch(requester,hash,tasks, true, bKnowProgress, false, null, false); + ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, false, null, false); } public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener) { - dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, false); } public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } private static int entryCounter = 0; @@ -259,7 +259,7 @@ public static void dispatch(final Component requester, final Hashtable taskList = new ArrayList(); + final List taskList = new ArrayList<>(); for (int i = 0; i < tasks.length; i++){ if (tasks[i].getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING && i < tasks.length - 1) { diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java index 74d8a907ca..7cc0fee463 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java @@ -636,9 +636,9 @@ public synchronized User getUser() { */ public synchronized UserMetaDbServer getUserMetaDbServer() throws DataAccessException { VCellThreadChecker.checkRemoteInvocation(); - if (userMetaDbServer!=null){ - return userMetaDbServer; - }else if (getVcellConnection()==null){ + if (userMetaDbServer != null) return userMetaDbServer; + + if (getVcellConnection()==null){ throw new RuntimeException("cannot get Database Server, no VCell Connection\ntry Server->Reconnect"); }else{ try { diff --git a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java index a84c82554a..aed308adab 100644 --- a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java +++ b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java @@ -803,24 +803,20 @@ public BioModelInfo[] getBioModelInfos() { private XMLHolder getBioModelXML(KeyValue vKey) throws DataAccessException { - try{ - String xmlString = (String)xmlHash.get(vKey); - if (xmlString==null){ - BigString xmlBS = sessionManager.getUserMetaDbServer().getBioModelXML(vKey); - xmlString = (xmlBS != null?xmlBS.toString():null); - if(xmlString != null){ - BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(xmlString)); - String newXmlString = XmlHelper.bioModelToXML(bioModel); - xmlHash.put(vKey,newXmlString); - return new XMLHolder(newXmlString,bioModel); - }else{ - throw new RuntimeException("unexpected: UserMetaDbServer.getBioModelXML() returned null"); - } - }else{ - return new XMLHolder(xmlString); - } - }catch (ObjectNotFoundException e){ + String xmlString = xmlHash.get(vKey); + if (null != xmlString) return new XMLHolder<>(xmlString); + BigString xmlBS = sessionManager.getUserMetaDbServer().getBioModelXML(vKey); + xmlString = (xmlBS != null?xmlBS.toString():null); + if(xmlString != null){ + BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(xmlString)); + String newXmlString = XmlHelper.bioModelToXML(bioModel); + xmlHash.put(vKey,newXmlString); + return new XMLHolder<>(newXmlString, bioModel); + }else{ + throw new RuntimeException("unexpected: UserMetaDbServer.getBioModelXML() returned null"); + } + }catch (ObjectNotFoundException e){ throw new DataAccessException("BioModel (id=" + vKey + ") does not exist. It either " + "has been deleted or its reference is outdated. Please use menu 'Server->Reconnect' to update document references."); }catch(Exception e){ diff --git a/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java b/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java index 13997ecf5a..a2e95f5c7d 100644 --- a/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java +++ b/vcell-util/src/main/java/org/vcell/util/VCellThreadChecker.java @@ -14,31 +14,16 @@ public class VCellThreadChecker { - private static final ThreadLocal cpuSuppressed = new ThreadLocal() { - @Override - protected Integer initialValue() { - return 0; - } - }; + private static final ThreadLocal cpuSuppressed = ThreadLocal.withInitial(() -> 0); - private static final ThreadLocal remoteSuppressed = new ThreadLocal() { - @Override - protected Integer initialValue() { - return 0; - } - }; + private static final ThreadLocal remoteSuppressed = ThreadLocal.withInitial(() -> 0); public interface GUIThreadChecker { - public boolean isEventDispatchThread(); + boolean isEventDispatchThread(); } - private static GUIThreadChecker guiThreadChecker = new GUIThreadChecker() { - - public boolean isEventDispatchThread() { - return SwingUtilities.isEventDispatchThread(); - } - }; + private static GUIThreadChecker guiThreadChecker = SwingUtilities::isEventDispatchThread; public static void setGUIThreadChecker(GUIThreadChecker argGuiThreadChecker){ guiThreadChecker = argGuiThreadChecker; @@ -85,6 +70,7 @@ public SuppressIntensive() { super(cpuSuppressed); } } + public static class SuppressRemote extends Suppressor { public SuppressRemote() { super(remoteSuppressed); From 318e233b9767d9e5cb0c1baae518a33dc7ed9b77 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 10:07:33 -0400 Subject: [PATCH 19/48] [WIP] Added dispatch call to schedule check This isn't a solution; more work is needed --- .../vcell/client/ClientRequestManager.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index 44af99645f..f8dd1b13d0 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -340,8 +340,29 @@ private CloseOption checkBeforeClosing(DocumentWindowManager windowManager) { return CloseOption.CLOSE_IN_ANY_CASE; } boolean isChanged = true; + String IS_CHANGED_KEY = this.getClass().getName() + ".DocumentManager::isChanged"; + Hashtable hashtable = new Hashtable<>(); try { - isChanged = getDocumentManager().isChanged(vcDocument); + AsynchClientTask checkIfChanged = new AsynchClientTask( + "Checking if model has changed...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + boolean hasBeenChanged = ClientRequestManager.this.getDocumentManager().isChanged(vcDocument); + hashTable.put(IS_CHANGED_KEY, hasBeenChanged); + } + }; + ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[]{checkIfChanged}, + false, false, null, true); + ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[] {checkIfChanged}); + if (hashtable.containsKey(IS_CHANGED_KEY)) + isChanged = (Boolean)hashtable.get(IS_CHANGED_KEY); + else if (hashtable.containsKey("clientTaskDispatcherStackTraceArray")){ + StringBuilder stackTrace = new StringBuilder(); + for (StackTraceElement elem : (StackTraceElement[]) hashtable.get("clientTaskDispatcherStackTraceArray")) + stackTrace.append(" \tat ").append(elem.toString()).append("\n"); + lg.error("Unknown error occurred during task 'Checking if model has changed'\n{}", stackTrace); + } } catch (Exception exc) { exc.printStackTrace(); String choice = PopupGenerator.showWarningDialog(windowManager, getUserPreferences(), From 9ad335bd08d71cd50af5f0676a6fe393bc0f3057 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 10:55:37 -0400 Subject: [PATCH 20/48] Formatting fixes --- .../client/task/ClientTaskDispatcher.java | 1268 ++++++++--------- 1 file changed, 612 insertions(+), 656 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 6e6749aa3e..879804bcc0 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -9,6 +9,7 @@ */ package cbit.vcell.client.task; + import java.awt.Component; import java.awt.Cursor; import java.awt.Window; @@ -44,681 +45,636 @@ import cbit.vcell.client.task.AsynchClientTask.KeyInfo; import cbit.vcell.simdata.PDEDataContext; import swingthreads.SwingWorker; + /** * Insert the type's description here. * Creation date: (5/28/2004 2:44:22 AM) + * * @author: Ion Moraru */ public class ClientTaskDispatcher { -// public static final String PROGRESS_POPUP = "asynchProgressPopup"; + // public static final String PROGRESS_POPUP = "asynchProgressPopup"; // public static final String TASK_PROGRESS_INTERVAL = "progressRange"; - public static final String TASK_ABORTED_BY_ERROR = "abort"; - public static final String TASK_ABORTED_BY_USER = "cancel"; - public static final String TASKS_TO_BE_SKIPPED = "conditionalSkip"; - /** - * hash key to internally flag problem with hash table data - */ - private static final String HASH_DATA_ERROR = "hdeHdeHde"; - /** - * hash key to store stack trace if {@link #lg} enabled for INFO - */ - private static final String STACK_TRACE_ARRAY = "clientTaskDispatcherStackTraceArray"; - private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); - /** - * used to count / generate thread names - */ - private static long serial = 0; - /** - * set of all scheduled tasks; used to avoid calling System.exit() prematurely on Application exit - */ - private static final Set allTasks; - /** - * hash key for final window - */ - private static final String FINAL_WINDOW = "finalWindowInterface"; - - static { - WeakHashMap whm = new WeakHashMap( ); - allTasks = Collections.synchronizedSet( Collections.newSetFromMap(whm) ); - } - - -/** - * don't show popup. - * Creation date: (5/31/2004 5:37:06 PM) - * @param tasks cbit.vcell.desktop.controls.ClientTask[] - */ -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks) { - ClientTaskDispatcher.dispatch(requester,hash,tasks,false, false, false, null, false); -} - -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { - ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, false, null, false); -} - -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener) { - ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, false); -} - -public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - ClientTaskDispatcher.dispatch(requester,hash,tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); -} - -public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); -} - -private static int entryCounter = 0; -public static boolean isBusy(){ - if(entryCounter>0){ -// System.out.println("----------Busy----------"); - return true; - } - return false; -} - -public static class BlockingTimer extends Timer{ - private static AsynchProgressPopup pp; - private static ArrayList allBlockingTimers = new ArrayList<>(); - private static Timer ppStop = new Timer(1000, new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - synchronized (allBlockingTimers) { - if(pp != null && allBlockingTimers.size() == 0){ + public static final String TASK_ABORTED_BY_ERROR = "abort"; + public static final String TASK_ABORTED_BY_USER = "cancel"; + public static final String TASKS_TO_BE_SKIPPED = "conditionalSkip"; + /** + * hash key to internally flag problem with hash table data + */ + private static final String HASH_DATA_ERROR = "hdeHdeHde"; + /** + * hash key to store stack trace if {@link #lg} enabled for INFO + */ + private static final String STACK_TRACE_ARRAY = "clientTaskDispatcherStackTraceArray"; + private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); + /** + * used to count / generate thread names + */ + private static long serial = 0; + /** + * set of all scheduled tasks; used to avoid calling System.exit() prematurely on Application exit + */ + private static final Set allTasks; + /** + * hash key for final window + */ + private static final String FINAL_WINDOW = "finalWindowInterface"; + + static { + WeakHashMap whm = new WeakHashMap(); + allTasks = Collections.synchronizedSet(Collections.newSetFromMap(whm)); + } + + + /** + * don't show popup. + * Creation date: (5/31/2004 5:37:06 PM) + * + * @param tasks cbit.vcell.desktop.controls.ClientTask[] + */ + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, false, false, false, null, false); + } + + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, false, null, false); + } + + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + } + + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + private static int entryCounter = 0; + + public static boolean isBusy() { + // System.out.println("----------Busy----------"); + return entryCounter > 0; + } + + public static class BlockingTimer extends Timer { + private static AsynchProgressPopup pp; + private static final ArrayList allBlockingTimers = new ArrayList<>(); + private static final Timer ppStop = new Timer(1000, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + synchronized (allBlockingTimers) { + if (pp != null && allBlockingTimers.isEmpty()) { // System.out.println("stopping "+System.currentTimeMillis()); - pp.stop(); - pp = null; - } - ppStop.stop(); - } - } - }); - private static ProgressDialogListener cancelListener = new ProgressDialogListener() { - @Override - public void cancelButton_actionPerformed(EventObject newEvent) { - synchronized (allBlockingTimers) { - while(allBlockingTimers.size() > 0){ - allBlockingTimers.remove(0); - } - ppStop.restart(); - } - } - }; - private static class ALHelper implements ActionListener { - private ActionListener argActionListener; - private BlockingTimer argBlockingTimer; - public ALHelper(ActionListener argActionListener) { - super(); - this.argActionListener = argActionListener; - } - @Override - public void actionPerformed(ActionEvent e) { - String actionMessage = null; - synchronized (allBlockingTimers) { - //if I'm next in the list do my action else repeat timer - if(BlockingTimer.allBlockingTimers.get(0) == argBlockingTimer){ - actionMessage = BlockingTimer.allBlockingTimers.get(0).getMessage(); - }else{ - if(allBlockingTimers.contains(argBlockingTimer)){ - argBlockingTimer.start(); - } - } - } - if(actionMessage != null){ - if(pp != null){ - pp.setMessage(actionMessage); - } - argActionListener.actionPerformed(e); - - } - } - public void setBlockingTimer(BlockingTimer argBlockingTimer){ - this.argBlockingTimer = argBlockingTimer; - } - } - private String message; - public BlockingTimer(Component requester,int delay,String message){ - super(delay, new ALHelper(null)); - ((ALHelper)getActionListeners()[0]).setBlockingTimer(this); - ppStop.setRepeats(false); - setRepeats(false); - if(pp == null){ - pp = new AsynchProgressPopup(requester, "Waiting for actions to finish...", message, null, true, false,true,cancelListener); - pp.startKeepOnTop(); - } - synchronized (allBlockingTimers) { - allBlockingTimers.add(this); - } - } - public String getMessage(){ - return message; - } - @Override - public void start() { - // TODO Auto-generated method stub - super.start(); - } - @Override - public void stop() { - // TODO Auto-generated method stub - super.stop(); - synchronized (allBlockingTimers) { + pp.stop(); + pp = null; + } + ppStop.stop(); + } + } + }); + private static final ProgressDialogListener cancelListener = new ProgressDialogListener() { + @Override + public void cancelButton_actionPerformed(EventObject newEvent) { + synchronized (allBlockingTimers) { + while (!allBlockingTimers.isEmpty()) { + allBlockingTimers.remove(0); + } + ppStop.restart(); + } + } + }; + + private static class ALHelper implements ActionListener { + private final ActionListener argActionListener; + private BlockingTimer argBlockingTimer; + + public ALHelper(ActionListener argActionListener) { + super(); + this.argActionListener = argActionListener; + } + + @Override + public void actionPerformed(ActionEvent e) { + String actionMessage = null; + synchronized (allBlockingTimers) { + //if I'm next in the list do my action else repeat timer + if (BlockingTimer.allBlockingTimers.get(0) == this.argBlockingTimer) { + actionMessage = BlockingTimer.allBlockingTimers.get(0).getMessage(); + } else { + if (allBlockingTimers.contains(this.argBlockingTimer)) { + this.argBlockingTimer.start(); + } + } + } + if (actionMessage != null) { + if (pp != null) { + pp.setMessage(actionMessage); + } + this.argActionListener.actionPerformed(e); + + } + } + + public void setBlockingTimer(BlockingTimer argBlockingTimer) { + this.argBlockingTimer = argBlockingTimer; + } + } + + private String message; + + public BlockingTimer(Component requester, int delay, String message) { + super(delay, new ALHelper(null)); + ((ALHelper) this.getActionListeners()[0]).setBlockingTimer(this); + ppStop.setRepeats(false); + this.setRepeats(false); + if (pp == null) { + pp = new AsynchProgressPopup(requester, "Waiting for actions to finish...", message, null, true, false, true, cancelListener); + pp.startKeepOnTop(); + } + synchronized (allBlockingTimers) { + allBlockingTimers.add(this); + } + } + + public String getMessage() { + return this.message; + } + + @Override + public void start() { + // TODO Auto-generated method stub + super.start(); + } + + @Override + public void stop() { + // TODO Auto-generated method stub + super.stop(); + synchronized (allBlockingTimers) { // if(allBlockingTimers.size()>0 && allBlockingTimers.get(0) != BlockingTimer.this){ // System.err.println("Unexpected position of stopped Blockingtimer, not beginning of list"); // } - allBlockingTimers.remove(BlockingTimer.this); + allBlockingTimers.remove(BlockingTimer.this); // System.out.println("starting stop "+System.currentTimeMillis()); - ppStop.restart(); - } - } - private static void replace(BlockingTimer replaceThis, BlockingTimer withThis){ - synchronized (allBlockingTimers) { - replaceThis.stop(); - allBlockingTimers.add(withThis); - } - } -} -public static boolean isBusy(PDEDataContext busyPDEDatacontext1,PDEDataContext busyPDEDatacontext2){ - return ClientTaskDispatcher.isBusy() || (busyPDEDatacontext1 != null && busyPDEDatacontext1.isBusy()) || (busyPDEDatacontext2 != null && busyPDEDatacontext2.isBusy()); -} -public static BlockingTimer getBlockingTimer(Component requester,PDEDataContext busyPDEDatacontext1,PDEDataContext busyPDEDatacontext2,BlockingTimer activeTimerOld,ActionListener actionListener,String actionMessage){ - if(actionMessage == null){ - actionMessage = "no message..."; - } - if(isBusy(busyPDEDatacontext1,busyPDEDatacontext2)){ - BlockingTimer activeTimerNew = new BlockingTimer(requester,200,actionMessage); - if(activeTimerOld != null){ - BlockingTimer.replace(activeTimerOld, activeTimerNew); - } - ActionListener[] currentActionlListeners = activeTimerNew.getActionListeners(); - for (int i = 0; i < currentActionlListeners.length; i++) { - activeTimerNew.removeActionListener(currentActionlListeners[i]); - } - activeTimerNew.addActionListener(actionListener); + ppStop.restart(); + } + } + + private static void replace(BlockingTimer replaceThis, BlockingTimer withThis) { + synchronized (allBlockingTimers) { + replaceThis.stop(); + allBlockingTimers.add(withThis); + } + } + } + + public static boolean isBusy(PDEDataContext busyPDEDatacontext1, PDEDataContext busyPDEDatacontext2) { + return ClientTaskDispatcher.isBusy() || (busyPDEDatacontext1 != null && busyPDEDatacontext1.isBusy()) || (busyPDEDatacontext2 != null && busyPDEDatacontext2.isBusy()); + } + + public static BlockingTimer getBlockingTimer(Component requester, PDEDataContext busyPDEDatacontext1, PDEDataContext busyPDEDatacontext2, BlockingTimer activeTimerOld, ActionListener actionListener, String actionMessage) { + if (actionMessage == null) { + actionMessage = "no message..."; + } + if (isBusy(busyPDEDatacontext1, busyPDEDatacontext2)) { + BlockingTimer activeTimerNew = new BlockingTimer(requester, 200, actionMessage); + if (activeTimerOld != null) { + BlockingTimer.replace(activeTimerOld, activeTimerNew); + } + ActionListener[] currentActionlListeners = activeTimerNew.getActionListeners(); + for (int i = 0; i < currentActionlListeners.length; i++) { + activeTimerNew.removeActionListener(currentActionlListeners[i]); + } + activeTimerNew.addActionListener(actionListener); // if(activeTimerNew.isRunning()){ // System.err.println("----------getBlockingTimer: single fire timer should not be running"); // } - activeTimerNew.restart(); - return activeTimerNew; - }else if(activeTimerOld != null){ - activeTimerOld.stop(); - activeTimerOld = null; - } - return null; -} - -public enum StopStrategy { - THREAD_INTERRUPT, - @Deprecated THREAD_KILL -} - -public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, - final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, - final boolean cancelable, final ProgressDialogListener progressDialogListener, - final boolean bInputBlocking) { - ClientTaskDispatcher.dispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, - bInputBlocking, StopStrategy.THREAD_INTERRUPT); -} - - -public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, - final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, - final boolean cancelable, final ProgressDialogListener progressDialogListener, - final boolean bInputBlocking, final StopStrategy stopStrategy) { - // check tasks - swing non-blocking can be only at the end - entryCounter++; - if(entryCounter>1){ - System.out.println("Reentrant"); - } - -// if (bInProgress) { -// Thread.dumpStack(); -// } - if (lg.isInfoEnabled()) { - hash.put(STACK_TRACE_ARRAY, Thread.currentThread().getStackTrace()); - } - if (bShowProgressPopup && requester == null) { - System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); - } - - final List taskList = new ArrayList<>(); - - for (int i = 0; i < tasks.length; i++){ - if (tasks[i].getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING && i < tasks.length - 1) { - throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); - } - taskList.add(tasks[i]); - if (lg.isDebugEnabled()) { - lg.debug("added task name " + tasks[i].getTaskName()); - } - } - - final String threadBaseName = "ClientTaskDispatcher " + ( serial++ ) + ' '; - // dispatch tasks to a new worker - SwingWorker worker = new SwingWorker() { - private AsynchProgressPopup pp = null; - private Window windowParent = null; - private Component focusOwner = null; - public Object construct() { - if (bShowProgressPopup) { - if (customDialog == null) { - pp = new AsynchProgressPopup(requester, "WORKING...", "Initializing request", Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } else { - pp = new AsynchProgressPopup(requester, customDialog, Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } - pp.setStopStrategy(stopStrategy); - if (bInputBlocking) { - pp.startKeepOnTop(); - } else { - pp.start(); - } - } - if (requester != null) { - windowParent = GuiUtils.getWindowForComponent(requester); - } - try { - if (windowParent != null) { - focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - ClientMDIManager.blockWindow(windowParent); - windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - } - }); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - for (int i = 0; i < taskList.size(); i++){ - // run all tasks - // after abort, run only non-skippable tasks - // also skip selected tasks specified by conditionalSkip tag - final AsynchClientTask currentTask = taskList.get(i); - try { - currentTask.setClientTaskStatusSupport(pp); - setSwingWorkerThreadName(this,threadBaseName + currentTask.getTaskName()); - - //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); - if (pp != null ) { - pp.setVisible(currentTask.showProgressPopup()); - if(!bKnowProgress) - { - pp.setProgress(i*100/taskList.size()); // beginning of task - } - pp.setMessage(currentTask.getTaskName()); - } - boolean shouldRun = !hash.containsKey(HASH_DATA_ERROR); - if (hash.containsKey(TASK_ABORTED_BY_ERROR) && currentTask.skipIfAbort()) { - shouldRun = false; - } - if (hash.containsKey(TASKS_TO_BE_SKIPPED)) { - String[] toSkip = (String[])hash.get(TASKS_TO_BE_SKIPPED); - if (ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName())) { - shouldRun = false; - } - } - if (pp != null && pp.isInterrupted()) { - recordException(UserCancelException.CANCEL_GENERIC, hash); - } - - if (hash.containsKey(TASK_ABORTED_BY_USER)) { - UserCancelException exc = (UserCancelException)hash.get(TASK_ABORTED_BY_USER); - if (currentTask.skipIfCancel(exc)) { - shouldRun = false; - } - } - if (shouldRun) { - try { - if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - runTask(currentTask,hash, taskList); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - try { - runTask(currentTask,hash, taskList); - } catch (Throwable exc) { - recordException(exc, hash); - } - } - }); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - try { - runTask(currentTask,hash, taskList); - } catch (Throwable exc) { - recordException(exc, hash); - } - } - }); - } - } catch (Throwable exc) { - recordException(exc, hash); - } - } - // AsynchClientTask[] followupTasks = currentTask.getFollowupTasks(); - // if (followupTasks != null) { - // for (int j = 0; j < followupTasks.length; j++) { - // taskList.add(i+j+1, followupTasks[j]); - // } - // } - } - finally { - allTasks.remove(currentTask); - } + activeTimerNew.restart(); + return activeTimerNew; + } else if (activeTimerOld != null) { + activeTimerOld.stop(); + activeTimerOld = null; + } + return null; + } + + public enum StopStrategy { + THREAD_INTERRUPT, + @Deprecated THREAD_KILL + } + + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking) { + ClientTaskDispatcher.dispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, + bInputBlocking, StopStrategy.THREAD_INTERRUPT); + } + + + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy) { + final String threadBaseName = "ClientTaskDispatcher " + (serial++) + ' '; + final List taskList = new ArrayList<>(); + + // check tasks - swing non-blocking can be only at the end + ClientTaskDispatcher.entryCounter++; + if (ClientTaskDispatcher.entryCounter > 1) lg.debug("Reentrant: {}", ClientTaskDispatcher.entryCounter); + + // if (bInProgress) { + // Thread.dumpStack(); + // } + if (lg.isInfoEnabled()) hash.put(STACK_TRACE_ARRAY, Thread.currentThread().getStackTrace()); + + if (bShowProgressPopup && requester == null) { + System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); + Thread.dumpStack(); + } + + for (AsynchClientTask task : tasks){ + if (AsynchClientTask.TASKTYPE_SWING_NONBLOCKING== task.getTaskType() && taskList.size() + 1 != tasks.length) { + throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); } - return hash; + taskList.add(task); + lg.debug("added task name {}", task.getTaskName()); } - - public void finished() { -//System.out.println("DISPATCHING: finished() called at "+ new Date(System.currentTimeMillis())); - entryCounter--; -// System.out.println("----------Leave----------entryCounter="+entryCounter); - - if (pp != null) { - pp.stop(); - } - if (hash.containsKey(TASK_ABORTED_BY_ERROR)) { - // something went wrong - StringBuffer allCausesErrorMessageSB = new StringBuffer(); - Throwable causeError = (Throwable)hash.get(TASK_ABORTED_BY_ERROR); - do{ - allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-").append(causeError.getMessage() == null || causeError.getMessage().length() == 0 ? "" : causeError.getMessage()); - allCausesErrorMessageSB.append("\n"); - }while((causeError = causeError.getCause()) != null); - if (requester == null) { - System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); - } - if (lg.isInfoEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - String stackTraceString = StringUtils.join(ste,'\n'); - lg.info(stackTraceString,(Throwable)hash.get(TASK_ABORTED_BY_ERROR)); - } - else { - lg.info("Unexpected " + STACK_TRACE_ARRAY + " obj " + obj); - } - } - PopupGenerator.showErrorDialog(requester, allCausesErrorMessageSB.toString(), (Throwable)hash.get(TASK_ABORTED_BY_ERROR)); - } else if (hash.containsKey(TASK_ABORTED_BY_USER)) { - // depending on where user canceled we might want to automatically start a new job - dispatchFollowUp(hash); - } - - FinalWindow fw = AsynchClientTask.fetch(hash, FINAL_WINDOW,FinalWindow.class,false); - if (lg.isDebugEnabled() && fw != null) { - lg.debug("FinalWindow retrieved from hash"); - } - //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocatoin - if (windowParent != null) { - ClientMDIManager.unBlockWindow(windowParent); - windowParent.setCursor(Cursor.getDefaultCursor()); - if (fw == null && focusOwner != null) { - fw = () -> { windowParent.requestFocusInWindow(); focusOwner.requestFocusInWindow(); }; - if (lg.isDebugEnabled()) { - lg.debug("FinalWindow built from " + windowParent.toString() + " and " + focusOwner.toString()); - } - } - } - if (fw != null) { - if (lg.isDebugEnabled()) { - lg.debug("scheduling " + fw.getClass().getName() + ".run on " + fw.toString()); - SwingUtilities.invokeLater(debugWrapper(fw)); - } - else { - SwingUtilities.invokeLater(fw); - } - } - else { - lg.debug("no Final Window"); - } -// BeanUtils.setCursorThroughout(frameParent, Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); -//System.out.println("DISPATCHING: done at "+ new Date(System.currentTimeMillis())); - } - }; - setSwingWorkerThreadName(worker,threadBaseName); - allTasks.addAll(taskList); - worker.start(); -} - -/** - * wrap runnable in debug print statement - * @param r payload - * @return wrapper - */ -private static Runnable debugWrapper(Runnable r) { - Runnable wrapper = () -> - { - lg.debug("calling " + r.getClass().getName() + ".run on " + r.toString()); - r.run(); - }; - return wrapper; -} - - - -/** - * Insert the method's description here. - * Creation date: (6/1/2004 8:58:38 PM) - * @param hash java.util.Hashtable - */ -private static void dispatchFollowUp(Hashtable hash) { - // - // we deal with a task dispatch that aborted due to some user choice on prompts - // - UserCancelException e = (UserCancelException)hash.get("cancel"); - if (e == UserCancelException.CHOOSE_SAVE_AS) { - // user chose to save as during a save or save/edition of a documnet found to be unchanged - ((DocumentWindowManager)hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); - } -} - - -/** - * Insert the method's description here. - * Creation date: (5/28/2004 2:17:22 AM) - * @param exc java.lang.Exception - */ -public static void recordException(Throwable exc, Hashtable hash) { - lg.error(exc.getMessage(), exc); - if (exc instanceof UserCancelException) { - hash.put(TASK_ABORTED_BY_USER, exc); - } else { - exc.printStackTrace(System.out); - hash.put(TASK_ABORTED_BY_ERROR, exc); - } -} - -/** - * @return list of outstanding tasks, or empty set if none - */ -public static Collection outstandingTasks( ) { - if (allTasks.isEmpty()) { - return Collections.emptyList(); - } - - synchronized(allTasks) { - List taskNames = new ArrayList<>(); - for (AsynchClientTask ct : allTasks) { - String tn = ct.getTaskName(); - taskNames.add(tn); - } - return taskNames; - } -} - -/** - * @return true if there are uncompleted tasks - */ -public static boolean hasOutstandingTasks( ) { - return !allTasks.isEmpty(); -} -/** - * convert Collection to array - * @param coll - * @return new array - */ -private static AsynchClientTask[] collToArray(Collection coll) { - return coll.toArray(new AsynchClientTask[coll.size()]); -} -//updated API -public static void dispatchColl(Component requester, Hashtable hash, Collection coll) { - dispatch(requester,hash,collToArray(coll)); -} - -public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { - dispatch(requester,hash,collToArray(coll),bKnowProgress); -} - -public static void dispatchColl(Component requester, Hashtable hash, Collectioncoll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener) { - dispatch(requester, hash, collToArray(coll) ,bKnowProgress,cancelable,progressDialogListener); -} - -public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - dispatch(requester, hash, collToArray(coll) ,bKnowProgress,cancelable,progressDialogListener,bInputBlocking); -} - -public static void dispatchColl(final Component requester, final Hashtable hash, Collectioncoll, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - dispatch(requester, hash, collToArray(coll) ,bShowProgressPopup,bKnowProgress,cancelable,progressDialogListener,bInputBlocking); -} - -/** - * Insert the method's description here. - * Creation date: (5/31/2004 5:37:06 PM) - * @param tasks cbit.vcell.desktop.controls.ClientTask[] - */ -public static void dispatchColl(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { -} - - - -/** - * set {@link SwingWorker} thread name - * @param sw - * @param name may not be null - * @throws IllegalArgumentException if name is null - */ -private static void setSwingWorkerThreadName(SwingWorker sw, String name) { - if (name != null ) { - try { - Field threadVarField = SwingWorker.class.getDeclaredField("threadVar"); - threadVarField.setAccessible(true); - Object threadVar = threadVarField.get(sw); - Field threadField = threadVar.getClass().getDeclaredField("thread"); - threadField.setAccessible(true); - Thread thread = (Thread) threadField.get(threadVar); - thread.setName(name); - } - catch (NoSuchFieldException | SecurityException | IllegalAccessException e) { - lg.warn("setSwingWorkerName fail", e); - } - return; - } - throw new IllegalArgumentException("name may not be null"); -} - -/** - * call currentTask.run(hash) with log4j logging; check for required keys - * @param currentTask not null - * @param hash not null - * @param taskList current set of tasks being dispatched - * @throws Exception - */ -private static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { - if (lg.isDebugEnabled()) { - String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); - if (lg.isDebugEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - msg += '\n' + StringUtils.join(ste,'\n'); - } - lg.debug(msg); - } - else { - lg.debug(msg); - } - } - //check required elements present - StringBuilder sb = null; - for (KeyInfo requiredKey : currentTask.requiredKeys()) { - Object obj = hash.get(requiredKey.name); - if (obj == null) { - if (sb == null) sb = initStringBuilder(currentTask) ; - sb.append("Missing required key ").append(requiredKey.name).append('\n'); - continue; - } - Class foundClass = obj.getClass(); - if (!requiredKey.clzz.isAssignableFrom(foundClass)) { - if (sb == null) sb = initStringBuilder(currentTask) ; - sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); - sb.append('\n'); - } - } - - if (sb == null) { //no problems found - currentTask.run(hash); - return; - } - - sb.append("Prior tasks\n"); - for ( AsynchClientTask pt : taskList) { - if (pt == currentTask) { - break; - } - sb.append('\t').append(pt.getTaskName()).append('\n'); - } - hash.put(HASH_DATA_ERROR,HASH_DATA_ERROR); - throw new ProgrammingException(sb.toString()); -} - -/** - * @param currentTask non null - * @return {@link StringBuilder} initialized with task name - */ -private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { - StringBuilder sb = new StringBuilder(); - sb.append("Data error for task " + currentTask.getTaskName() + '\n'); - return sb; -} + // dispatch tasks to a new worker + SwingWorker worker = new SwingWorker() { + private AsynchProgressPopup pp = null; + private Window windowParent = null; + private Component focusOwner = null; + + public Object construct() { + if (bShowProgressPopup) { + if (customDialog == null) { + this.pp = new AsynchProgressPopup(requester, "WORKING...", "Initializing request", Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); + } else { + this.pp = new AsynchProgressPopup(requester, customDialog, Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); + } + this.pp.setStopStrategy(stopStrategy); + if (bInputBlocking) { + this.pp.startKeepOnTop(); + } else { + this.pp.start(); + } + } + if (requester != null) this.windowParent = GuiUtils.getWindowForComponent(requester); + + try { + if (this.windowParent != null) { + Window targetWindow = this.windowParent; + this.focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + SwingUtilities.invokeAndWait(() -> { + ClientMDIManager.blockWindow(targetWindow); + targetWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + } + } catch (InterruptedException | InvocationTargetException e) { + lg.warn(e); + } + for (int i = 0; i < taskList.size(); i++) { + // run all tasks + // after abort, run only non-skippable tasks + // also skip selected tasks specified by conditionalSkip tag + final AsynchClientTask currentTask = taskList.get(i); + try { + currentTask.setClientTaskStatusSupport(this.pp); + ClientTaskDispatcher.setSwingWorkerThreadName(this, threadBaseName + currentTask.getTaskName()); + + //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); + if (this.pp != null) { + this.pp.setVisible(currentTask.showProgressPopup()); + if (!bKnowProgress) { + this.pp.setProgress(i * 100 / taskList.size()); // beginning of task + } + this.pp.setMessage(currentTask.getTaskName()); + } + boolean shouldRun = !hash.containsKey(HASH_DATA_ERROR); + if (hash.containsKey(TASK_ABORTED_BY_ERROR) && currentTask.skipIfAbort()) { + shouldRun = false; + } + if (hash.containsKey(TASKS_TO_BE_SKIPPED)) { + String[] toSkip = (String[]) hash.get(TASKS_TO_BE_SKIPPED); + boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); + if (taskShouldBeSkipped) shouldRun = false; + } + if (this.pp != null && this.pp.isInterrupted()) { + ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, hash); + } + + if (hash.containsKey(TASK_ABORTED_BY_USER)) { + UserCancelException exc = (UserCancelException) hash.get(TASK_ABORTED_BY_USER); + if (currentTask.skipIfCancel(exc)) shouldRun = false; + } + if (shouldRun) { + try { + if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + ClientTaskDispatcher.runTask(currentTask, hash, taskList); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + SwingUtilities.invokeAndWait(() -> { + try { + ClientTaskDispatcher.runTask(currentTask, hash, taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, hash); + } + }); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + SwingUtilities.invokeLater(() -> { + try { + ClientTaskDispatcher.runTask(currentTask, hash, taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, hash); + } + }); + } + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, hash); + } + } + } finally { + ClientTaskDispatcher.allTasks.remove(currentTask); + } + } + return hash; + } + + public void finished() { + ClientTaskDispatcher.entryCounter--; + + if (this.pp != null) { + this.pp.stop(); + } + if (hash.containsKey(TASK_ABORTED_BY_ERROR)) { + // something went wrong + StringBuilder allCausesErrorMessageSB = new StringBuilder(); + Throwable causeError = (Throwable) hash.get(TASK_ABORTED_BY_ERROR); + do { + allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-") + .append(causeError.getMessage() == null || causeError.getMessage().isEmpty() ? + "" : causeError.getMessage()); + allCausesErrorMessageSB.append("\n"); + } while ((causeError = causeError.getCause()) != null); + if (requester == null) { + lg.warn("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); + Thread.dumpStack(); + } + if (lg.isInfoEnabled()) { + Object obj = hash.get(STACK_TRACE_ARRAY); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + String stackTraceString = StringUtils.join(ste, '\n'); + lg.info(stackTraceString, (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); + } else { + lg.info("Unexpected {} obj {}", STACK_TRACE_ARRAY, obj); + } + } + PopupGenerator.showErrorDialog(requester, allCausesErrorMessageSB.toString(), + (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); + } else if (hash.containsKey(TASK_ABORTED_BY_USER)) { + // depending on where user canceled we might want to automatically start a new job + ClientTaskDispatcher.dispatchFollowUp(hash); + } + + FinalWindow fw = AsynchClientTask.fetch(hash, FINAL_WINDOW, FinalWindow.class, false); + if (lg.isDebugEnabled() && fw != null) { + lg.debug("FinalWindow retrieved from hash"); + } + //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocation + if (this.windowParent != null) { + ClientMDIManager.unBlockWindow(this.windowParent); + this.windowParent.setCursor(Cursor.getDefaultCursor()); + if (fw == null && this.focusOwner != null) { + fw = () -> { + this.windowParent.requestFocusInWindow(); + this.focusOwner.requestFocusInWindow(); + }; + lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); + } + } + if (fw != null) { + lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); + Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; + SwingUtilities.invokeLater(runnable); + } else { + lg.debug("no Final Window"); + } + } + }; + setSwingWorkerThreadName(worker, threadBaseName); + allTasks.addAll(taskList); + worker.start(); + } + + /** + * wrap runnable in debug print statement + * + * @param r payload + * @return wrapper + */ + private static Runnable debugWrapper(Runnable r) { + return () -> + { + lg.debug("calling " + r.getClass().getName() + ".run on " + r); + r.run(); + }; + } + + private static void dispatchFollowUp(Hashtable hash) { + // we deal with a task dispatch that aborted due to some user choice on prompts + UserCancelException e = (UserCancelException) hash.get("cancel"); + if (e == UserCancelException.CHOOSE_SAVE_AS) { + // user chose to save as during a save or save/edition of a document found to be unchanged + ((DocumentWindowManager) hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); + } + } + + public static void recordException(Throwable exc, Hashtable hash) { + lg.error(exc.getMessage(), exc); + if (exc instanceof UserCancelException userCancelException) { + hash.put(TASK_ABORTED_BY_USER, userCancelException); + } else { + exc.printStackTrace(System.out); + hash.put(TASK_ABORTED_BY_ERROR, exc); + } + } + + /** + * @return list of outstanding tasks, or empty set if none + */ + public static Collection outstandingTasks() { + if (ClientTaskDispatcher.allTasks.isEmpty()) return Collections.emptyList(); + + + synchronized (ClientTaskDispatcher.allTasks) { + List taskNames = new ArrayList<>(); + for (AsynchClientTask ct : ClientTaskDispatcher.allTasks) { + String tn = ct.getTaskName(); + taskNames.add(tn); + } + return taskNames; + } + } + + /** + * @return true if there are uncompleted tasks + */ + public static boolean hasOutstandingTasks() { + return !ClientTaskDispatcher.allTasks.isEmpty(); + } + + //updated API + public static void dispatchColl(Component requester, Hashtable hash, Collection coll) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new)); + } + + public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress); + } + + public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener); + } + + public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchColl(final Component requester, final Hashtable hash, Collection coll, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchColl(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + } + + + /** + * set {@link SwingWorker} thread name + * + * @param sw + * @param name may not be null + * @throws IllegalArgumentException if name is null + */ + private static void setSwingWorkerThreadName(SwingWorker sw, String name) { + if (name != null) { + try { + Field threadVarField = SwingWorker.class.getDeclaredField("threadVar"); + threadVarField.setAccessible(true); + Object threadVar = threadVarField.get(sw); + Field threadField = threadVar.getClass().getDeclaredField("thread"); + threadField.setAccessible(true); + Thread thread = (Thread) threadField.get(threadVar); + thread.setName(name); + } catch (NoSuchFieldException | SecurityException | IllegalAccessException e) { + lg.warn("setSwingWorkerName fail", e); + } + return; + } + throw new IllegalArgumentException("name may not be null"); + } + + /** + * call currentTask.run(hash) with log4j logging; check for required keys + * + * @param currentTask not null + * @param hash not null + * @param taskList current set of tasks being dispatched + * @throws Exception + */ + private static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { + if (lg.isDebugEnabled()) { + String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); + if (lg.isDebugEnabled()) { + Object obj = hash.get(STACK_TRACE_ARRAY); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + msg += '\n' + StringUtils.join(ste, '\n'); + } + lg.debug(msg); + } else { + lg.debug(msg); + } + } + //check required elements present + StringBuilder sb = null; + for (KeyInfo requiredKey : currentTask.requiredKeys()) { + Object obj = hash.get(requiredKey.name); + if (obj == null) { + if (sb == null) sb = initStringBuilder(currentTask); + sb.append("Missing required key ").append(requiredKey.name).append('\n'); + continue; + } + Class foundClass = obj.getClass(); + if (!requiredKey.clzz.isAssignableFrom(foundClass)) { + if (sb == null) sb = initStringBuilder(currentTask); + sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); + sb.append('\n'); + } + } + + if (sb == null) { //no problems found + currentTask.run(hash); + return; + } + + sb.append("Prior tasks\n"); + for (AsynchClientTask pt : taskList) { + if (pt == currentTask) { + break; + } + sb.append('\t').append(pt.getTaskName()).append('\n'); + } + hash.put(HASH_DATA_ERROR, HASH_DATA_ERROR); + throw new ProgrammingException(sb.toString()); + } + + /** + * @param currentTask non null + * @return {@link StringBuilder} initialized with task name + */ + private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { + StringBuilder sb = new StringBuilder(); + sb.append("Data error for task " + currentTask.getTaskName() + '\n'); + return sb; + } + + //package + interface FinalWindow extends Runnable { + } + + /** + * set final window in hash + * + * @param hash non null + * @param fWindow non null + * @throws ProgrammingException if more than one set in the same hash + * @see AsynchClientTask#setFinalWindow(Hashtable, cbit.vcell.client.ChildWindowManager.ChildWindow) + * @see AsynchClientTask#setFinalWindow(Hashtable, java.awt.Container) + */ //package -interface FinalWindow extends Runnable{ -} - -/** - * set final window in hash - * @param hash non null - * @param fWindow non null - * @throws ProgrammingException if more than one set in the same hash - * @see AsynchClientTask#setFinalWindow(Hashtable, cbit.vcell.client.ChildWindowManager.ChildWindow) - * @see AsynchClientTask#setFinalWindow(Hashtable, java.awt.Container) - */ -//package -static void setFinalWindow(Hashtable hash, FinalWindow fWindow) { - if (!hash.contains(FINAL_WINDOW)) { - hash.put(FINAL_WINDOW, fWindow); - return; - } - Object existing = hash.get(FINAL_WINDOW); - final String def = "null"; - String e = ClassUtils.getShortClassName(existing ,def); - String n = ClassUtils.getShortClassName(fWindow ,def); - throw new ProgrammingException("duplicate final windows" + e + " and " + n); -} - + static void setFinalWindow(Hashtable hash, FinalWindow fWindow) { + if (!hash.contains(FINAL_WINDOW)) { + hash.put(FINAL_WINDOW, fWindow); + return; + } + Object existing = hash.get(FINAL_WINDOW); + final String def = "null"; + String e = ClassUtils.getShortClassName(existing, def); + String n = ClassUtils.getShortClassName(fWindow, def); + throw new ProgrammingException("duplicate final windows" + e + " and " + n); + } } From 3059360231486ef1b6eb92f614958d866e05d05b Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 11:02:37 -0400 Subject: [PATCH 21/48] Create instance of SwingWorker to help separate responsibility. --- .../src/main/java/swingthreads/ClientSwingWorker.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 vcell-client/src/main/java/swingthreads/ClientSwingWorker.java diff --git a/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java b/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java new file mode 100644 index 0000000000..4da654151d --- /dev/null +++ b/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java @@ -0,0 +1,11 @@ +package swingthreads; + +public class ClientSwingWorker extends SwingWorker { + /** + * Compute the value to be returned by the get method. + */ + @Override + public Object construct() { + return null; + } +} From 94efc81a448d903ed543c57f1a4bfec0efcb4dde Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 11:03:42 -0400 Subject: [PATCH 22/48] Clean-up SwingWorker --- .../main/java/swingthreads/SwingWorker.java | 77 +++++++++++-------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index 8675ab0f7e..4cc3f6e28f 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -7,9 +7,9 @@ * SwingWorker 3), an abstract class that you subclass to * perform GUI-related work in a dedicated thread. For * instructions on using this class, see: - * + *

* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html - * + *

* Note that the API changed slightly in the 3rd version: * You must now invoke start() on the SwingWorker after * creating it. @@ -18,36 +18,45 @@ public abstract class SwingWorker { private Object value; // see getValue(), setValue() private Thread thread; - /** + /** * Class to maintain reference to current worker thread * under separate synchronization control. */ private static class ThreadVar { private Thread thread; - ThreadVar(Thread t) { thread = t; } - synchronized Thread get() { return thread; } - synchronized void clear() { thread = null; } + + ThreadVar(Thread t) { + this.thread = t; + } + + synchronized Thread get() { + return this.thread; + } + + synchronized void clear() { + this.thread = null; + } } - private ThreadVar threadVar; + private final ThreadVar threadVar; - /** - * Get the value produced by the worker thread, or null if it + /** + * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ - protected synchronized Object getValue() { - return value; + protected synchronized Object getValue() { + return this.value; } - /** - * Set the value produced by worker thread + /** + * Set the value produced by worker thread */ - private synchronized void setValue(Object x) { - value = x; + private synchronized void setValue(Object x) { + this.value = x; } - /** - * Compute the value to be returned by the get method. + /** + * Compute the value to be returned by the get method. */ public abstract Object construct(); @@ -63,30 +72,29 @@ public void finished() { * to force the worker to stop what it's doing. */ public void interrupt() { - Thread t = threadVar.get(); + Thread t = this.threadVar.get(); if (t != null) { t.interrupt(); } - threadVar.clear(); + this.threadVar.clear(); } /** - * Return the value created by the construct method. + * Return the value created by the construct method. * Returns null if either the constructing thread or the current * thread was interrupted before a value was produced. - * + * * @return the value created by the construct method */ public Object get() { - while (true) { - Thread t = threadVar.get(); + while (true) { + Thread t = this.threadVar.get(); if (t == null) { - return getValue(); + return this.getValue(); } try { t.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); // propagate return null; } @@ -100,16 +108,17 @@ public Object get() { */ public SwingWorker() { final Runnable doFinished = new Runnable() { - public void run() { finished(); } + public void run() { + SwingWorker.this.finished(); + } }; - Runnable doConstruct = new Runnable() { + Runnable doConstruct = new Runnable() { public void run() { try { - setValue(construct()); - } - finally { - threadVar.clear(); + SwingWorker.this.setValue(SwingWorker.this.construct()); + } finally { + SwingWorker.this.threadVar.clear(); } SwingUtilities.invokeLater(doFinished); @@ -117,14 +126,14 @@ public void run() { }; Thread t = new Thread(doConstruct); - threadVar = new ThreadVar(t); + this.threadVar = new ThreadVar(t); } /** * Start the worker thread. */ public void start() { - Thread t = threadVar.get(); + Thread t = this.threadVar.get(); if (t != null) { t.start(); } From 64046b91b6733ea7b23b55c3a618e75546e08b46 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 11:16:09 -0400 Subject: [PATCH 23/48] Cleaning up Swing Worker logic Part 1 --- ...ngWorker.java => StandardSwingWorker.java} | 2 +- .../main/java/swingthreads/SwingWorker.java | 25 ++++++------------- 2 files changed, 8 insertions(+), 19 deletions(-) rename vcell-client/src/main/java/swingthreads/{ClientSwingWorker.java => StandardSwingWorker.java} (77%) diff --git a/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java similarity index 77% rename from vcell-client/src/main/java/swingthreads/ClientSwingWorker.java rename to vcell-client/src/main/java/swingthreads/StandardSwingWorker.java index 4da654151d..bb0dddc289 100644 --- a/vcell-client/src/main/java/swingthreads/ClientSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java @@ -1,6 +1,6 @@ package swingthreads; -public class ClientSwingWorker extends SwingWorker { +public class StandardSwingWorker extends SwingWorker { /** * Compute the value to be returned by the get method. */ diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index 4cc3f6e28f..f0f488d1fa 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -15,9 +15,6 @@ * creating it. */ public abstract class SwingWorker { - private Object value; // see getValue(), setValue() - private Thread thread; - /** * Class to maintain reference to current worker thread * under separate synchronization control. @@ -38,6 +35,8 @@ synchronized void clear() { } } + // Instance Variables + private Object value; // see getValue(), setValue() private final ThreadVar threadVar; /** @@ -64,8 +63,7 @@ private synchronized void setValue(Object x) { * Called on the event dispatching thread (not on the worker thread) * after the construct method has returned. */ - public void finished() { - } + public void finished() {} /** * A new method that interrupts the worker thread. Call this method @@ -73,9 +71,7 @@ public void finished() { */ public void interrupt() { Thread t = this.threadVar.get(); - if (t != null) { - t.interrupt(); - } + if (t != null) t.interrupt(); this.threadVar.clear(); } @@ -89,9 +85,8 @@ public void interrupt() { public Object get() { while (true) { Thread t = this.threadVar.get(); - if (t == null) { - return this.getValue(); - } + if (t == null) return this.getValue(); + try { t.join(); } catch (InterruptedException e) { @@ -101,17 +96,12 @@ public Object get() { } } - /** * Start a thread that will call the construct method * and then exit. */ public SwingWorker() { - final Runnable doFinished = new Runnable() { - public void run() { - SwingWorker.this.finished(); - } - }; + final Runnable doFinished = SwingWorker.this::finished; Runnable doConstruct = new Runnable() { public void run() { @@ -120,7 +110,6 @@ public void run() { } finally { SwingWorker.this.threadVar.clear(); } - SwingUtilities.invokeLater(doFinished); } }; From f7495a4a367f8d908b12c8dbcbb8939ff55ec638 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 13:31:01 -0400 Subject: [PATCH 24/48] Separate anonymous SwingWorker instance into independent class Some inversion of control was implemented --- .../cbit/vcell/client/ClientSimManager.java | 5 +- .../vcell/client/data/KymographPanel.java | 4 +- .../vcell/client/data/SimResultsViewer.java | 5 +- .../vcell/client/task/AsynchClientTask.java | 44 +-- .../cbit/vcell/client/task/ChooseFile.java | 2 +- .../client/task/ClientTaskDispatcher.java | 327 ++---------------- .../vcell/client/task/DeleteOldDocument.java | 6 +- .../vcell/client/task/ExportDocument.java | 8 +- .../vcell/client/task/ResultsHashUtils.java | 52 +++ .../swingthreads/StandardSwingWorker.java | 291 +++++++++++++++- .../main/java/swingthreads/SwingWorker.java | 21 ++ .../main/java/swingthreads/TaskEventKeys.java | 24 ++ 12 files changed, 432 insertions(+), 357 deletions(-) create mode 100644 vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java create mode 100644 vcell-client/src/main/java/swingthreads/TaskEventKeys.java diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java index 400ef6ad28..0432bc61fc 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java @@ -20,11 +20,11 @@ import cbit.vcell.client.desktop.simulation.SimulationWindow; import cbit.vcell.client.desktop.simulation.SimulationWindow.LocalState; import cbit.vcell.client.desktop.simulation.SimulationWorkspace; -import cbit.vcell.client.server.ClientServerManager; import cbit.vcell.client.server.UserPreferences; import cbit.vcell.client.task.AsynchClientTask; import cbit.vcell.client.task.AsynchClientTaskFunction; import cbit.vcell.client.task.ClientTaskDispatcher; +import cbit.vcell.client.task.ResultsHashUtils; import cbit.vcell.export.server.ExportServiceImpl; import cbit.vcell.field.FieldDataIdentifierSpec; import cbit.vcell.mapping.SimulationContext; @@ -33,7 +33,6 @@ import cbit.vcell.messaging.server.SimulationTask; import cbit.vcell.parser.ExpressionException; import cbit.vcell.resource.ResourceUtil; -import cbit.vcell.server.DataSetController; import cbit.vcell.server.SimulationStatus; import cbit.vcell.simdata.*; import cbit.vcell.solver.*; @@ -402,7 +401,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask displayResultsTask = new AsynchClientTask("Showing results", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { @SuppressWarnings("unchecked") public void run(Hashtable hashTable) throws Exception { - boolean isLocal = fetch(hashTable,H_LOCAL_SIM,Boolean.class,true); + boolean isLocal = ResultsHashUtils.fetch(hashTable,H_LOCAL_SIM,Boolean.class,true); SimulationWindow.LocalState localState = isLocal ? LocalState.LOCAL : LocalState.SERVER; Hashtable failures = (Hashtable)hashTable.get(H_FAILURES); Simulation[] simsToShow = (Simulation[])hashTable.get("simsArray"); diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java b/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java index 9b93a06817..8515cfa7be 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/KymographPanel.java @@ -47,6 +47,8 @@ import cbit.vcell.simdata.DataIdentifier; import cbit.vcell.simdata.SimDataConstants; import cbit.vcell.simdata.gui.PdeTimePlotMultipleVariablesPanel.MultiTimePlotHelper; +import swingthreads.TaskEventKeys; + /** * Insert the type's description here. * Creation date: (12/14/2004 9:38:13 AM) @@ -2039,7 +2041,7 @@ public void run(Hashtable hashTable) throws Exception { Throwable timeSeriesJobFailed = (Throwable)hashTable.get(PDEDataViewer.StringKey_timeSeriesJobException); if (timeSeriesJobFailed == null) { - timeSeriesJobFailed = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_USER); + timeSeriesJobFailed = (Throwable)hashTable.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()); } if (failMethod(timeSeriesJobFailed, dataIdentifer)) { return; diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java b/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java index 59a2fe642a..7009a001fa 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/SimResultsViewer.java @@ -29,6 +29,7 @@ import org.vcell.util.DataAccessException; import org.vcell.util.UserCancelException; import org.vcell.util.document.VCDataIdentifier; +import swingthreads.TaskEventKeys; import javax.swing.*; import javax.swing.event.ListSelectionListener; @@ -446,7 +447,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask task2 = new AsynchClientTask("show results", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null && hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_USER) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null && hashTable.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()) == null) { ODEDataManager odeDatamanager = (ODEDataManager)hashTable.get("odeDatamanager"); odeDataViewer.setOdeSolverResultSet(odeDatamanager.getODESolverResultSet()); odeDataViewer.setVcDataIdentifier(vcdid); @@ -477,7 +478,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask task2 = new AsynchClientTask("show results", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null) { ClientPDEDataContext newPDEDC = (ClientPDEDataContext)hashTable.get("newPDEDC"); pdeDataViewer.setPdeDataContext(newPDEDC); pdeDataViewer.setSimNameSimDataID(new ExportSpecs.SimNameSimDataID(getSimulation().getName(), getSimulation().getSimulationInfo().getAuthoritativeVCSimulationIdentifier(), ExportSpecs.getParamScanInfo(getSimulation(), vcdid.getJobIndex()))); diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java index 5bc2913d6f..bcf90f3f7e 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java @@ -20,7 +20,6 @@ import org.vcell.util.ClientTaskStatusSupport; import org.vcell.util.ProgrammingException; import org.vcell.util.UserCancelException; -import org.vcell.util.VCAssert; import org.vcell.util.gui.GuiUtils; import cbit.vcell.client.ChildWindowManager.ChildWindow; @@ -92,45 +91,6 @@ public final boolean skipIfAbort() { public ClientTaskStatusSupport getClientTaskStatusSupport() { return clientTaskStatusSupport; } - - /** - * fetch and type convert object from hash - * @param hashTable not null - * @param key name (not null) - * @param clzz required type, not null - * @param required throw exception if required and not present - * @return object cast to correct type or possibly null if !required - * @throws ProgrammingException if key not of required type - * @throws ProgrammingException required is true and key not present - */ - @SuppressWarnings("unchecked") - static protected T fetch(Hashtable hashTable, String key, Class clzz, boolean required) { - Object obj = hashTable.get(key); - if (obj != null) { - Class oclzz = obj.getClass(); - if (clzz.isAssignableFrom(oclzz)) { - return (T) obj; - } - throw new ProgrammingException("object " + obj + " of type " + oclzz.getName() + " not instance of " + clzz.getName()); - } - if (required) { - throw new ProgrammingException("key " + key + " not found in async hashtable"); - } - return null; - } - - /** - * typesafe (verified) fetch of object from hash - * @param hashTable non null - * @param keyInfo non null - * @return object of correct type - */ - static protected Object fetch(Hashtable hashTable, KeyInfo keyInfo) { - Object obj = hashTable.get(keyInfo.name); - VCAssert.assertTrue(obj != null, "ClientTaskDispatcher failed to verify object"); - VCAssert.assertTrue(keyInfo.clzz.isAssignableFrom(obj.getClass()),"ClientTaskDispatcher failed to verify type"); - return obj; - } /** * Insert the method's description here. @@ -189,7 +149,7 @@ protected void setFinalWindow(Hashtable hashTable,Container cntr * return list of keys need by task * @return non-null Collection */ - protected Collection requiredKeys( ) { + public Collection requiredKeys( ) { return Collections.emptyList(); } @@ -198,7 +158,7 @@ protected Collection requiredKeys( ) { */ public static final class KeyInfo { public final String name; - final Class clzz; + public final Class clzz; /** * @param name non null * @param clzz non null diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java b/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java index 3e48f42b22..478cd87c95 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ChooseFile.java @@ -111,7 +111,7 @@ private void checkForOverwrites(File selectedFile, Component parent, UserPrefere * @param clientWorker cbit.vcell.desktop.controls.ClientWorker */ public void run(Hashtable hashTable) throws java.lang.Exception { - VCDocument documentToExport = fetch(hashTable,DocumentToExport.EXPORT_DOCUMENT,VCDocument.class, true) ; + VCDocument documentToExport = ResultsHashUtils.fetch(hashTable,DocumentToExport.EXPORT_DOCUMENT,VCDocument.class, true) ; File exportFile = null; if (documentToExport instanceof BioModel) { exportFile = showBioModelXMLFileChooser(hashTable); diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 879804bcc0..56edbf81b9 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -11,12 +11,8 @@ package cbit.vcell.client.task; import java.awt.Component; -import java.awt.Cursor; -import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -26,25 +22,19 @@ import java.util.Set; import java.util.WeakHashMap; -import javax.swing.FocusManager; -import javax.swing.SwingUtilities; import javax.swing.Timer; import org.apache.commons.lang3.ClassUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.vcell.util.*; import org.vcell.util.gui.AsynchProgressPopup; -import org.vcell.util.gui.GuiUtils; import org.vcell.util.gui.ProgressDialog; -import cbit.vcell.client.ClientMDIManager; -import cbit.vcell.client.DocumentWindowManager; -import cbit.vcell.client.PopupGenerator; -import cbit.vcell.client.task.AsynchClientTask.KeyInfo; import cbit.vcell.simdata.PDEDataContext; +import swingthreads.StandardSwingWorker; import swingthreads.SwingWorker; +import swingthreads.TaskEventKeys; /** * Insert the type's description here. @@ -53,19 +43,6 @@ * @author: Ion Moraru */ public class ClientTaskDispatcher { - // public static final String PROGRESS_POPUP = "asynchProgressPopup"; -// public static final String TASK_PROGRESS_INTERVAL = "progressRange"; - public static final String TASK_ABORTED_BY_ERROR = "abort"; - public static final String TASK_ABORTED_BY_USER = "cancel"; - public static final String TASKS_TO_BE_SKIPPED = "conditionalSkip"; - /** - * hash key to internally flag problem with hash table data - */ - private static final String HASH_DATA_ERROR = "hdeHdeHde"; - /** - * hash key to store stack trace if {@link #lg} enabled for INFO - */ - private static final String STACK_TRACE_ARRAY = "clientTaskDispatcherStackTraceArray"; private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); /** * used to count / generate thread names @@ -282,194 +259,48 @@ public static void dispatch(final Component requester, final Hashtable taskList = new ArrayList<>(); + final String threadBaseName = "ClientTaskDispatcher " + (serial++) + ' '; + final List taskList = new ArrayList<>(); // check tasks - swing non-blocking can be only at the end ClientTaskDispatcher.entryCounter++; if (ClientTaskDispatcher.entryCounter > 1) lg.debug("Reentrant: {}", ClientTaskDispatcher.entryCounter); - // if (bInProgress) { - // Thread.dumpStack(); - // } - if (lg.isInfoEnabled()) hash.put(STACK_TRACE_ARRAY, Thread.currentThread().getStackTrace()); + // if (bInProgress) { + // Thread.dumpStack(); + // } + if (lg.isInfoEnabled()) + hash.put(TaskEventKeys.STACK_TRACE_ARRAY.toString(), Thread.currentThread().getStackTrace()); if (bShowProgressPopup && requester == null) { System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); Thread.dumpStack(); } - for (AsynchClientTask task : tasks){ - if (AsynchClientTask.TASKTYPE_SWING_NONBLOCKING== task.getTaskType() && taskList.size() + 1 != tasks.length) { - throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); - } - taskList.add(task); - lg.debug("added task name {}", task.getTaskName()); - } + for (AsynchClientTask task : tasks) { + if (AsynchClientTask.TASKTYPE_SWING_NONBLOCKING == task.getTaskType() && taskList.size() + 1 != tasks.length) { + throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); + } + taskList.add(task); + lg.debug("added task name {}", task.getTaskName()); + } // dispatch tasks to a new worker - SwingWorker worker = new SwingWorker() { - private AsynchProgressPopup pp = null; - private Window windowParent = null; - private Component focusOwner = null; - - public Object construct() { - if (bShowProgressPopup) { - if (customDialog == null) { - this.pp = new AsynchProgressPopup(requester, "WORKING...", "Initializing request", Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } else { - this.pp = new AsynchProgressPopup(requester, customDialog, Thread.currentThread(), bInputBlocking, bKnowProgress, cancelable, progressDialogListener); - } - this.pp.setStopStrategy(stopStrategy); - if (bInputBlocking) { - this.pp.startKeepOnTop(); - } else { - this.pp.start(); - } - } - if (requester != null) this.windowParent = GuiUtils.getWindowForComponent(requester); - - try { - if (this.windowParent != null) { - Window targetWindow = this.windowParent; - this.focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - SwingUtilities.invokeAndWait(() -> { - ClientMDIManager.blockWindow(targetWindow); - targetWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - }); - } - } catch (InterruptedException | InvocationTargetException e) { - lg.warn(e); - } - for (int i = 0; i < taskList.size(); i++) { - // run all tasks - // after abort, run only non-skippable tasks - // also skip selected tasks specified by conditionalSkip tag - final AsynchClientTask currentTask = taskList.get(i); - try { - currentTask.setClientTaskStatusSupport(this.pp); - ClientTaskDispatcher.setSwingWorkerThreadName(this, threadBaseName + currentTask.getTaskName()); - - //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); - if (this.pp != null) { - this.pp.setVisible(currentTask.showProgressPopup()); - if (!bKnowProgress) { - this.pp.setProgress(i * 100 / taskList.size()); // beginning of task - } - this.pp.setMessage(currentTask.getTaskName()); - } - boolean shouldRun = !hash.containsKey(HASH_DATA_ERROR); - if (hash.containsKey(TASK_ABORTED_BY_ERROR) && currentTask.skipIfAbort()) { - shouldRun = false; - } - if (hash.containsKey(TASKS_TO_BE_SKIPPED)) { - String[] toSkip = (String[]) hash.get(TASKS_TO_BE_SKIPPED); - boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); - if (taskShouldBeSkipped) shouldRun = false; - } - if (this.pp != null && this.pp.isInterrupted()) { - ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, hash); - } + SwingWorker worker = new StandardSwingWorker(threadBaseName, requester, stopStrategy, bKnowProgress, + progressDialogListener, bShowProgressPopup, customDialog, bInputBlocking, cancelable) { - if (hash.containsKey(TASK_ABORTED_BY_USER)) { - UserCancelException exc = (UserCancelException) hash.get(TASK_ABORTED_BY_USER); - if (currentTask.skipIfCancel(exc)) shouldRun = false; - } - if (shouldRun) { - try { - if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - ClientTaskDispatcher.runTask(currentTask, hash, taskList); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - SwingUtilities.invokeAndWait(() -> { - try { - ClientTaskDispatcher.runTask(currentTask, hash, taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, hash); - } - }); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - SwingUtilities.invokeLater(() -> { - try { - ClientTaskDispatcher.runTask(currentTask, hash, taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, hash); - } - }); - } - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, hash); - } - } - } finally { - ClientTaskDispatcher.allTasks.remove(currentTask); - } - } - return hash; + @Override + public void removeTaskFromDispatcher(AsynchClientTask task) { + ClientTaskDispatcher.allTasks.remove(task); } - public void finished() { - ClientTaskDispatcher.entryCounter--; - - if (this.pp != null) { - this.pp.stop(); - } - if (hash.containsKey(TASK_ABORTED_BY_ERROR)) { - // something went wrong - StringBuilder allCausesErrorMessageSB = new StringBuilder(); - Throwable causeError = (Throwable) hash.get(TASK_ABORTED_BY_ERROR); - do { - allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-") - .append(causeError.getMessage() == null || causeError.getMessage().isEmpty() ? - "" : causeError.getMessage()); - allCausesErrorMessageSB.append("\n"); - } while ((causeError = causeError.getCause()) != null); - if (requester == null) { - lg.warn("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); - } - if (lg.isInfoEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - String stackTraceString = StringUtils.join(ste, '\n'); - lg.info(stackTraceString, (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); - } else { - lg.info("Unexpected {} obj {}", STACK_TRACE_ARRAY, obj); - } - } - PopupGenerator.showErrorDialog(requester, allCausesErrorMessageSB.toString(), - (Throwable) hash.get(TASK_ABORTED_BY_ERROR)); - } else if (hash.containsKey(TASK_ABORTED_BY_USER)) { - // depending on where user canceled we might want to automatically start a new job - ClientTaskDispatcher.dispatchFollowUp(hash); - } - - FinalWindow fw = AsynchClientTask.fetch(hash, FINAL_WINDOW, FinalWindow.class, false); - if (lg.isDebugEnabled() && fw != null) { - lg.debug("FinalWindow retrieved from hash"); - } - //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocation - if (this.windowParent != null) { - ClientMDIManager.unBlockWindow(this.windowParent); - this.windowParent.setCursor(Cursor.getDefaultCursor()); - if (fw == null && this.focusOwner != null) { - fw = () -> { - this.windowParent.requestFocusInWindow(); - this.focusOwner.requestFocusInWindow(); - }; - lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); - } - } - if (fw != null) { - lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); - Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; - SwingUtilities.invokeLater(runnable); - } else { - lg.debug("no Final Window"); - } + @Override + public void announceTaskComplete() { + ClientTaskDispatcher.entryCounter--; } }; - setSwingWorkerThreadName(worker, threadBaseName); + + worker.setThreadName(threadBaseName); allTasks.addAll(taskList); worker.start(); } @@ -480,7 +311,7 @@ public void finished() { * @param r payload * @return wrapper */ - private static Runnable debugWrapper(Runnable r) { + public static Runnable debugWrapper(Runnable r) { return () -> { lg.debug("calling " + r.getClass().getName() + ".run on " + r); @@ -488,22 +319,14 @@ private static Runnable debugWrapper(Runnable r) { }; } - private static void dispatchFollowUp(Hashtable hash) { - // we deal with a task dispatch that aborted due to some user choice on prompts - UserCancelException e = (UserCancelException) hash.get("cancel"); - if (e == UserCancelException.CHOOSE_SAVE_AS) { - // user chose to save as during a save or save/edition of a document found to be unchanged - ((DocumentWindowManager) hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); - } - } public static void recordException(Throwable exc, Hashtable hash) { lg.error(exc.getMessage(), exc); if (exc instanceof UserCancelException userCancelException) { - hash.put(TASK_ABORTED_BY_USER, userCancelException); + hash.put(TaskEventKeys.TASK_ABORTED_BY_USER.toString(), userCancelException); } else { exc.printStackTrace(System.out); - hash.put(TASK_ABORTED_BY_ERROR, exc); + hash.put(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString(), exc); } } @@ -560,98 +383,8 @@ public static void dispatchColl(final Component requester, final Hashtable hash, Collection taskList) throws Exception { - if (lg.isDebugEnabled()) { - String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); - if (lg.isDebugEnabled()) { - Object obj = hash.get(STACK_TRACE_ARRAY); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - msg += '\n' + StringUtils.join(ste, '\n'); - } - lg.debug(msg); - } else { - lg.debug(msg); - } - } - //check required elements present - StringBuilder sb = null; - for (KeyInfo requiredKey : currentTask.requiredKeys()) { - Object obj = hash.get(requiredKey.name); - if (obj == null) { - if (sb == null) sb = initStringBuilder(currentTask); - sb.append("Missing required key ").append(requiredKey.name).append('\n'); - continue; - } - Class foundClass = obj.getClass(); - if (!requiredKey.clzz.isAssignableFrom(foundClass)) { - if (sb == null) sb = initStringBuilder(currentTask); - sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); - sb.append('\n'); - } - } - - if (sb == null) { //no problems found - currentTask.run(hash); - return; - } - - sb.append("Prior tasks\n"); - for (AsynchClientTask pt : taskList) { - if (pt == currentTask) { - break; - } - sb.append('\t').append(pt.getTaskName()).append('\n'); - } - hash.put(HASH_DATA_ERROR, HASH_DATA_ERROR); - throw new ProgrammingException(sb.toString()); - } - - /** - * @param currentTask non null - * @return {@link StringBuilder} initialized with task name - */ - private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { - StringBuilder sb = new StringBuilder(); - sb.append("Data error for task " + currentTask.getTaskName() + '\n'); - return sb; - } - //package - interface FinalWindow extends Runnable { + public interface FinalWindow extends Runnable { } /** diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java b/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java index fc5ef63c36..b0dcf05086 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/DeleteOldDocument.java @@ -37,7 +37,7 @@ public DeleteOldDocument() { @Override -protected Collection requiredKeys() { +public Collection requiredKeys() { ArrayList rval = new ArrayList<>(); rval.add(DOCUMENT_WINDOW_MANAGER); rval.add(DOCUMENT_MANAGER); @@ -52,9 +52,9 @@ protected Collection requiredKeys() { * @param clientWorker cbit.vcell.desktop.controls.ClientWorker */ public void run(Hashtable hashTable) throws java.lang.Exception { - DocumentWindowManager dwm = (DocumentWindowManager) fetch(hashTable,DOCUMENT_WINDOW_MANAGER); + DocumentWindowManager dwm = (DocumentWindowManager) ResultsHashUtils.fetch(hashTable,DOCUMENT_WINDOW_MANAGER); VCDocument currentDocument = dwm.getVCDocument(); - DocumentManager documentManager = (DocumentManager)fetch(hashTable,DOCUMENT_MANAGER); + DocumentManager documentManager = (DocumentManager) ResultsHashUtils.fetch(hashTable,DOCUMENT_MANAGER); switch (currentDocument.getDocumentType()) { case BIOMODEL_DOC: { // make the info diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java b/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java index c95d051c53..879f8e2d35 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ExportDocument.java @@ -118,10 +118,10 @@ public void close(){ */ public void run(Hashtable hashTable) throws java.lang.Exception { VCDocument documentToExport = (VCDocument)hashTable.get("documentToExport"); - File exportFile = fetch(hashTable,EXPORT_FILE,File.class, true); - ExtensionFilter fileFilter = fetch(hashTable,FILE_FILTER,ExtensionFilter.class, true); + File exportFile = ResultsHashUtils.fetch(hashTable,EXPORT_FILE,File.class, true); + ExtensionFilter fileFilter = ResultsHashUtils.fetch(hashTable,FILE_FILTER,ExtensionFilter.class, true); - DocumentManager documentManager = fetch(hashTable,DocumentManager.IDENT,DocumentManager.class,true); + DocumentManager documentManager = ResultsHashUtils.fetch(hashTable,DocumentManager.IDENT,DocumentManager.class,true); String resultString = null; FileCloseHelper closeThis = null; try{ @@ -130,7 +130,7 @@ public void run(Hashtable hashTable) throws java.lang.Exception throw new Exception("Expecting fileFilter type "+SelectorExtensionFilter.class.getName()+" but got "+fileFilter.getClass().getName()); } BioModel bioModel = (BioModel)documentToExport; - SimulationContext chosenSimContext = fetch(hashTable,SIM_CONTEXT,SimulationContext.class, false); + SimulationContext chosenSimContext = ResultsHashUtils.fetch(hashTable,SIM_CONTEXT,SimulationContext.class, false); ((SelectorExtensionFilter)fileFilter).writeBioModel(documentManager, bioModel, exportFile, chosenSimContext); /* DELETE this after finishing validation testing diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java b/vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java new file mode 100644 index 0000000000..f4091f2241 --- /dev/null +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ResultsHashUtils.java @@ -0,0 +1,52 @@ +package cbit.vcell.client.task; + +import org.vcell.util.ProgrammingException; +import org.vcell.util.VCAssert; + +import java.util.Hashtable; + +public class ResultsHashUtils { + // TODO: Change this class to `ResultsHash extends Hashtable`, + // and implement everywhere the hash is already used + /** + * fetch and type convert object from hash + * @param hashTable not null + * @param key name (not null) + * @param clzz required type, not null + * @param required throw exception if required and not present + * @return object cast to correct type or possibly null if !required + * @throws ProgrammingException if key not of required type + * @throws ProgrammingException required is true and key not present + */ + + public static T fetch(Hashtable hashTable, String key, Class clzz, boolean required) { + if (null == hashTable) throw new IllegalArgumentException("hashTable may not be null"); + if (null == key) throw new IllegalArgumentException("key may not be null"); + if (null == clzz) throw new IllegalArgumentException("clzz may not be null"); + + if (required && !hashTable.containsKey(key)) throw new ProgrammingException("key " + key + " not found in async hashtable"); + + Object obj = hashTable.get(key); + if (obj == null) return null; + + Class classOfObj = obj.getClass(); + if (clzz.isAssignableFrom(classOfObj)) return clzz.cast(obj); + + String exceptionFormat = "object `%s` of type `%s` is not an instance of `%s`"; + String exceptionMessage = String.format(exceptionFormat, obj, classOfObj.getName(), clzz.getName()); + throw new ProgrammingException(exceptionMessage); + } + + /** + * typesafe (verified) fetch of object from hash + * @param hashTable non null + * @param keyInfo non null + * @return object of correct type + */ + static protected Object fetch(Hashtable hashTable, AsynchClientTask.KeyInfo keyInfo) { + Object obj = hashTable.get(keyInfo.name); + VCAssert.assertTrue(obj != null, "ClientTaskDispatcher failed to verify object"); + VCAssert.assertTrue(keyInfo.clzz.isAssignableFrom(obj.getClass()),"ClientTaskDispatcher failed to verify type"); + return obj; + } +} diff --git a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java index bb0dddc289..ff26a55423 100644 --- a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java @@ -1,11 +1,294 @@ package swingthreads; -public class StandardSwingWorker extends SwingWorker { +import cbit.vcell.client.ClientMDIManager; +import cbit.vcell.client.DocumentWindowManager; +import cbit.vcell.client.PopupGenerator; +import cbit.vcell.client.task.AsynchClientTask; +import cbit.vcell.client.task.ClientTaskDispatcher; +import cbit.vcell.client.task.CommonTask; +import cbit.vcell.client.task.ResultsHashUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.vcell.util.*; +import org.vcell.util.gui.AsynchProgressPopup; +import org.vcell.util.gui.GuiUtils; +import org.vcell.util.gui.ProgressDialog; + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.Hashtable; +import java.util.List; + +public abstract class StandardSwingWorker extends SwingWorker { + private static final Logger lg = LogManager.getLogger(StandardSwingWorker.class); + + private AsynchProgressPopup pp = null; + private Window windowParent = null; + private Component focusOwner = null; + + private List taskList; + private Hashtable resultsHash; + + private boolean shouldShowProgressPopup; + private boolean shouldBlockInput; + private boolean shouldInformOfProgress; + private boolean shouldBeCancelable; + private String threadBaseName; + private ProgressDialog customProgressDialog; + private Component requestingComponent; + private ProgressDialogListener progressDialogListener; + + private ClientTaskDispatcher.StopStrategy stopStrategy; + + public StandardSwingWorker(String threadBaseName, Component requestingComponent, + ClientTaskDispatcher.StopStrategy stopStrategy, boolean shouldInformOfProgress, + ProgressDialogListener progressDialogListener, boolean shouldShowProgressPopup, + ProgressDialog customProgressDialog, boolean shouldBlockInput, boolean shouldBeCancelable) { + super(); + this.threadBaseName = threadBaseName; + this.requestingComponent = requestingComponent; + this.stopStrategy = stopStrategy; + this.shouldInformOfProgress = shouldInformOfProgress; + this.progressDialogListener = progressDialogListener; + this.shouldShowProgressPopup = shouldShowProgressPopup; + this.customProgressDialog = customProgressDialog; + this.shouldBlockInput = shouldBlockInput; + this.shouldBeCancelable = shouldBeCancelable; + } + /** - * Compute the value to be returned by the get method. + * call currentTask.run(hash) with log4j logging; check for required keys + * + * @param currentTask not null + * @param hash not null + * @param taskList current set of tasks being dispatched + * @throws Exception */ - @Override + public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { + if (lg.isDebugEnabled()) { + String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); + if (lg.isDebugEnabled()) { + Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + msg += '\n' + StringUtils.join(ste, '\n'); + } + lg.debug(msg); + } else { + lg.debug(msg); + } + } + //check required elements present + StringBuilder sb = null; + for (AsynchClientTask.KeyInfo requiredKey : currentTask.requiredKeys()) { + Object obj = hash.get(requiredKey.name); + if (obj == null) { + if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + sb.append("Missing required key ").append(requiredKey.name).append('\n'); + continue; + } + Class foundClass = obj.getClass(); + if (!requiredKey.clzz.isAssignableFrom(foundClass)) { + if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); + sb.append('\n'); + } + } + + if (sb == null) { //no problems found + currentTask.run(hash); + return; + } + + sb.append("Prior tasks\n"); + for (AsynchClientTask pt : taskList) { + if (pt == currentTask) { + break; + } + sb.append('\t').append(pt.getTaskName()).append('\n'); + } + hash.put(TaskEventKeys.HASH_DATA_ERROR.toString(), TaskEventKeys.HASH_DATA_ERROR.toString()); + throw new ProgrammingException(sb.toString()); + } + public Object construct() { - return null; + if (this.shouldShowProgressPopup) { + if (this.customProgressDialog == null) { + this.pp = new AsynchProgressPopup(this.requestingComponent, "WORKING...", "Initializing request", Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + } else { + this.pp = new AsynchProgressPopup(this.requestingComponent, this.customProgressDialog, Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + } + this.pp.setStopStrategy(this.stopStrategy); + if (this.shouldBlockInput) { + this.pp.startKeepOnTop(); + } else { + this.pp.start(); + } + } + if (this.requestingComponent != null) this.windowParent = GuiUtils.getWindowForComponent(this.requestingComponent); + + try { + if (this.windowParent != null) { + Window targetWindow = this.windowParent; + this.focusOwner = FocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + SwingUtilities.invokeAndWait(() -> { + ClientMDIManager.blockWindow(targetWindow); + targetWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + }); + } + } catch (InterruptedException | InvocationTargetException e) { + lg.warn(e); + } + for (int i = 0; i < this.taskList.size(); i++) { + // run all tasks + // after abort, run only non-skippable tasks + // also skip selected tasks specified by conditionalSkip tag + final AsynchClientTask currentTask = this.taskList.get(i); + try { + currentTask.setClientTaskStatusSupport(this.pp); + this.setThreadName(this.threadBaseName + currentTask.getTaskName()); + + //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); + if (this.pp != null) { + this.pp.setVisible(currentTask.showProgressPopup()); + if (!this.shouldInformOfProgress) { + this.pp.setProgress(i * 100 / this.taskList.size()); // beginning of task + } + this.pp.setMessage(currentTask.getTaskName()); + } + boolean shouldRun = !this.resultsHash.containsKey(TaskEventKeys.HASH_DATA_ERROR.toString()); + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) && currentTask.skipIfAbort()) { + shouldRun = false; + } + if (this.resultsHash.containsKey(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString())) { + String[] toSkip = (String[]) this.resultsHash.get(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString()); + boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); + if (taskShouldBeSkipped) shouldRun = false; + } + if (this.pp != null && this.pp.isInterrupted()) { + ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, this.resultsHash); + } + + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { + UserCancelException exc = (UserCancelException) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()); + if (currentTask.skipIfCancel(exc)) shouldRun = false; + } + if (shouldRun) { + try { + if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + SwingUtilities.invokeAndWait(() -> { + try { + StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + SwingUtilities.invokeLater(() -> { + try { + StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); + } + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + } + } finally { + this.removeTaskFromDispatcher(currentTask); + } + } + return this.resultsHash; + } + + public void finished() { + this.announceTaskComplete(); + + if (this.pp != null) { + this.pp.stop(); + } + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())) { + // something went wrong + StringBuilder allCausesErrorMessageSB = new StringBuilder(); + Throwable causeError = (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); + do { + allCausesErrorMessageSB.append(causeError.getClass().getSimpleName()).append("-") + .append(causeError.getMessage() == null || causeError.getMessage().isEmpty() ? + "" : causeError.getMessage()); + allCausesErrorMessageSB.append("\n"); + } while ((causeError = causeError.getCause()) != null); + if (this.requestingComponent == null) { + lg.warn("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); + Thread.dumpStack(); + } + if (lg.isInfoEnabled()) { + Object obj = this.resultsHash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) { + String stackTraceString = StringUtils.join(ste, '\n'); + lg.info(stackTraceString, (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())); + } else { + lg.info("Unexpected {} obj {}", TaskEventKeys.STACK_TRACE_ARRAY.toString(), obj); + } + } + PopupGenerator.showErrorDialog(this.requestingComponent, allCausesErrorMessageSB.toString(), + (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())); + } else if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { + // depending on where user canceled we might want to automatically start a new job + StandardSwingWorker.dispatchFollowUp(this.resultsHash); + } + + ClientTaskDispatcher.FinalWindow fw = ResultsHashUtils.fetch(this.resultsHash, TaskEventKeys.FINAL_WINDOW.toString(), ClientTaskDispatcher.FinalWindow.class, false); + if (fw != null) lg.debug("FinalWindow retrieved from hash"); + + //focusOwner is legacy means of shifting focus -- FinalWindow is newer explicit invocation + if (this.windowParent != null) { + ClientMDIManager.unBlockWindow(this.windowParent); + this.windowParent.setCursor(Cursor.getDefaultCursor()); + if (fw == null && this.focusOwner != null) { + fw = () -> { + this.windowParent.requestFocusInWindow(); + this.focusOwner.requestFocusInWindow(); + }; + lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); + } + } + if (fw != null) { + lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); + Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; + SwingUtilities.invokeLater(runnable); + } else { + lg.debug("no Final Window"); + } + } + + private static void dispatchFollowUp(Hashtable hash) { + // we deal with a task dispatch that aborted due to some user choice on prompts + UserCancelException e = (UserCancelException) hash.get("cancel"); + if (e == UserCancelException.CHOOSE_SAVE_AS) { + // user chose to save as during a save or save/edition of a document found to be unchanged + ((DocumentWindowManager) hash.get(CommonTask.DOCUMENT_WINDOW_MANAGER.name)).saveDocumentAsNew(); + } } + + /** + * @param currentTask non null + * @return {@link StringBuilder} initialized with task name + */ + private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { + StringBuilder sb = new StringBuilder(); + sb.append("Data error for task " + currentTask.getTaskName() + '\n'); + return sb; + } + + public abstract void removeTaskFromDispatcher(AsynchClientTask task); + + public abstract void announceTaskComplete(); } diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index f0f488d1fa..86f6caff57 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -1,6 +1,11 @@ package swingthreads; +import cbit.vcell.client.task.ClientTaskDispatcher; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import javax.swing.SwingUtilities; +import java.lang.reflect.Field; /** * This is the 3rd version of SwingWorker (also known as @@ -15,6 +20,22 @@ * creating it. */ public abstract class SwingWorker { + private static final Logger lg = LogManager.getLogger(SwingWorker.class); + /** + * set {@link SwingWorker} thread name + * + * @param name may not be null + * @throws IllegalArgumentException if name is null + */ + public void setThreadName(String name) { + if (name == null) throw new IllegalArgumentException("name may not be null"); + try { + this.threadVar.thread.setName(name); + } catch (SecurityException e) { + lg.warn("setSwingWorkerName fail", e); + } + } + /** * Class to maintain reference to current worker thread * under separate synchronization control. diff --git a/vcell-client/src/main/java/swingthreads/TaskEventKeys.java b/vcell-client/src/main/java/swingthreads/TaskEventKeys.java new file mode 100644 index 0000000000..1cc50f9264 --- /dev/null +++ b/vcell-client/src/main/java/swingthreads/TaskEventKeys.java @@ -0,0 +1,24 @@ +package swingthreads; + +public enum TaskEventKeys { + //PROGRESS_POPUP("asynchProgressPopup"), + //TASK_PROGRESS_INTERVAL("progressRange"), + TASK_ABORTED_BY_ERROR("abort"), + TASK_ABORTED_BY_USER("cancel"), + TASKS_TO_BE_SKIPPED("conditionalSkip"), + FINAL_WINDOW("finalWindowInterface"), + STACK_TRACE_ARRAY("clientTaskDispatcherStackTraceArray"), // hash key to store stack trace if {@link #lg} enabled for INFO + HASH_DATA_ERROR("hdeHdeHde"), // hash key to internally flag problem with hash table data + ; + + private final String value; + + TaskEventKeys(String value) { + this.value = value; + } + + @Override + public String toString() { + return this.value; + } +} From 05291f4c34e0cd9a1f03c0fe31a9470b8fdc4da0 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 14:53:02 -0400 Subject: [PATCH 25/48] Formatting and Rearranging --- .../vcell/client/task/AsynchClientTask.java | 288 +++++++++--------- .../vcell/client/task/AsynchTaskType.java | 7 + .../client/task/ClientTaskDispatcher.java | 20 +- .../main/java/swingthreads/SwingWorker.java | 43 +-- .../vcell/clientdb/ClientDocumentManager.java | 2 +- 5 files changed, 184 insertions(+), 176 deletions(-) create mode 100644 vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java index bcf90f3f7e..eb86117b7c 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java @@ -23,153 +23,157 @@ import org.vcell.util.gui.GuiUtils; import cbit.vcell.client.ChildWindowManager.ChildWindow; + /** * Insert the type's description here. * Creation date: (5/31/2004 6:09:07 PM) + * * @author: Ion Moraru */ public abstract class AsynchClientTask { - public final static int TASKTYPE_NONSWING_BLOCKING = 1; - public final static int TASKTYPE_SWING_NONBLOCKING = 2; - public final static int TASKTYPE_SWING_BLOCKING = 3; + public final static int TASKTYPE_NONSWING_BLOCKING = 1; + public final static int TASKTYPE_SWING_NONBLOCKING = 2; + public final static int TASKTYPE_SWING_BLOCKING = 3; -/** - * Insert the method's description here. - * Creation date: (5/31/2004 7:18:33 PM) - * @return boolean - */ - private boolean bSkipIfAbort = true; - private boolean bSkipIfCancel = true; - private int taskType = TASKTYPE_NONSWING_BLOCKING; - private String taskName = ""; - private ClientTaskStatusSupport clientTaskStatusSupport = null; - private boolean bShowProgressPopup = true; - //private AsynchClientTask[] followupTasks = null; - - /** - * defaults showPopup, skip if abort, skip if cancel to true - * @param name - * @param taskType - */ - public AsynchClientTask(String name, int taskType) { - this(name, taskType, true, true, true); - } - - /** - * defaults skip if abort, skip if cancel to true - * @param name - * @param taskType - * @param bShowPopup - */ - public AsynchClientTask(String name, int taskType, boolean bShowPopup) { - this(name, taskType, bShowPopup, true, true); - } - - /** - * defaults showPopup, skip if abort, skip if cancel to true - * @param name - * @param taskType - * @param skipIfAbort - * @param skipIfCancel - */ - public AsynchClientTask(String name, int taskType, boolean skipIfAbort, boolean skipIfCancel) { - this(name, taskType, true, skipIfAbort, skipIfCancel); - } - - public AsynchClientTask(String name, int taskType, boolean bShowPopup, boolean skipIfAbort, boolean skipIfCancel) { - this.taskName = name; - this.taskType = taskType; - this.bShowProgressPopup = bShowPopup; - this.bSkipIfAbort = skipIfAbort; - this.bSkipIfCancel = skipIfCancel; - } - - public final boolean skipIfAbort() { - return bSkipIfAbort; - } - - public ClientTaskStatusSupport getClientTaskStatusSupport() { - return clientTaskStatusSupport; - } - - /** - * Insert the method's description here. - * Creation date: (5/31/2004 7:18:33 PM) - * @return boolean - */ - public boolean skipIfCancel(UserCancelException exc) { - return bSkipIfCancel; - } - - public final int getTaskType() { - return taskType; - } - - public final String getTaskName() { - return taskName; - } - - public abstract void run(Hashtable hashTable) throws Exception; - - public void setClientTaskStatusSupport(ClientTaskStatusSupport clientTaskStatusSupport) { - this.clientTaskStatusSupport = clientTaskStatusSupport; - } - public boolean showProgressPopup() { - return bShowProgressPopup; - } - - /** - * set final window to be raised - * @param hashTable non null - * @param cw non null - * @throws ProgrammingException if more than one set in the same hash - */ - protected void setFinalWindow(Hashtable hashTable,ChildWindow cw) { - Objects.requireNonNull(cw); - ClientTaskDispatcher.setFinalWindow(hashTable,() -> cw.toFront( ) ); - } - - /** - * set final window to be raised - * @param hashTable non null - * @param cntr non null - * @throws ProgrammingException if more than one set in the same hash - */ - protected void setFinalWindow(Hashtable hashTable,Container cntr) { - Objects.requireNonNull(cntr); - Window w= GuiUtils.getWindowForComponent(cntr); - if (w != null) { - ClientTaskDispatcher.setFinalWindow(hashTable,() -> w.toFront( ) ); - return; - } - throw new ProgrammingException("Container " + cntr.getName() + " has no window parent"); - } - - /** - * return list of keys need by task - * @return non-null Collection - */ - public Collection requiredKeys( ) { - return Collections.emptyList(); - } - - /** - * required hash key name and type - */ - public static final class KeyInfo { - public final String name; - public final Class clzz; - /** - * @param name non null - * @param clzz non null - */ - protected KeyInfo(String name, Class clzz) { - this.name = name; - this.clzz = clzz; - Objects.requireNonNull(name); - Objects.requireNonNull(clzz); - } - } - - + /** + * Insert the method's description here. + * Creation date: (5/31/2004 7:18:33 PM) + * + * @return boolean + */ + private final boolean bSkipIfAbort; + private final boolean bSkipIfCancel; + private final int taskType; + private final String taskName; + private ClientTaskStatusSupport clientTaskStatusSupport = null; + private final boolean bShowProgressPopup; + //private AsynchClientTask[] followupTasks = null; + + /** + * defaults showPopup, skip if abort, skip if cancel to true + * + * @param name + * @param taskType + */ + public AsynchClientTask(String name, int taskType) { + this(name, taskType, true, true, true); + } + + /** + * defaults skip if abort, skip if cancel to true + * + * @param name + * @param taskType + * @param bShowPopup + */ + public AsynchClientTask(String name, int taskType, boolean bShowPopup) { + this(name, taskType, bShowPopup, true, true); + } + + /** + * defaults showPopup, skip if aborted and skip if canceled to true + * + * @param name + * @param taskType + * @param skipIfAbort + * @param skipIfCancel + */ + public AsynchClientTask(String name, int taskType, boolean skipIfAbort, boolean skipIfCancel) { + this(name, taskType, true, skipIfAbort, skipIfCancel); + } + + public AsynchClientTask(String name, int taskType, boolean bShowPopup, boolean skipIfAbort, boolean skipIfCancel) { + this.taskName = name; + this.taskType = taskType; + this.bShowProgressPopup = bShowPopup; + this.bSkipIfAbort = skipIfAbort; + this.bSkipIfCancel = skipIfCancel; + } + + public final boolean skipIfAbort() { + return this.bSkipIfAbort; + } + + public ClientTaskStatusSupport getClientTaskStatusSupport() { + return this.clientTaskStatusSupport; + } + + public boolean skipIfCancel(UserCancelException exc) { + return this.bSkipIfCancel; + } + + public final int getTaskType() { + return this.taskType; + } + + public final String getTaskName() { + return this.taskName; + } + + public abstract void run(Hashtable hashTable) throws Exception; + + public void setClientTaskStatusSupport(ClientTaskStatusSupport clientTaskStatusSupport) { + this.clientTaskStatusSupport = clientTaskStatusSupport; + } + + public boolean showProgressPopup() { + return this.bShowProgressPopup; + } + + /** + * set final window to be raised + * + * @param hashTable non null + * @param cw non null + * @throws ProgrammingException if more than one set in the same hash + */ + protected void setFinalWindow(Hashtable hashTable, ChildWindow cw) { + Objects.requireNonNull(cw); + ClientTaskDispatcher.setFinalWindow(hashTable, cw::toFront); + } + + /** + * set final window to be raised + * + * @param hashTable non null + * @param cntr non null + * @throws ProgrammingException if more than one set in the same hash + */ + protected void setFinalWindow(Hashtable hashTable, Container cntr) { + Objects.requireNonNull(cntr); + Window w = GuiUtils.getWindowForComponent(cntr); + if (w != null) { + ClientTaskDispatcher.setFinalWindow(hashTable, w::toFront); + return; + } + throw new ProgrammingException("Container " + cntr.getName() + " has no window parent"); + } + + /** + * return list of keys need by task + * + * @return non-null Collection + */ + public Collection requiredKeys() { + return Collections.emptyList(); + } + + /** + * required hash key name and type + */ + public static final class KeyInfo { + public final String name; + public final Class clzz; + + /** + * @param name non null + * @param clzz non null + */ + KeyInfo(String name, Class clzz) { + this.name = name; + this.clzz = clzz; + Objects.requireNonNull(name); + Objects.requireNonNull(clzz); + } + } } diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java new file mode 100644 index 0000000000..9783a121a6 --- /dev/null +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchTaskType.java @@ -0,0 +1,7 @@ +package cbit.vcell.client.task; + +public enum AsynchTaskType { + NON_SWING_BLOCKING, + SWING_BLOCKING, + SWING_NON_BLOCKING, +} diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 56edbf81b9..f7c21f2757 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -48,6 +48,7 @@ public class ClientTaskDispatcher { * used to count / generate thread names */ private static long serial = 0; + private static int entryCounter = 0; /** * set of all scheduled tasks; used to avoid calling System.exit() prematurely on Application exit */ @@ -58,7 +59,7 @@ public class ClientTaskDispatcher { private static final String FINAL_WINDOW = "finalWindowInterface"; static { - WeakHashMap whm = new WeakHashMap(); + WeakHashMap whm = new WeakHashMap<>(); allTasks = Collections.synchronizedSet(Collections.newSetFromMap(whm)); } @@ -92,8 +93,6 @@ public static void dispatch(final Component requester, final Hashtable 0; @@ -115,15 +114,12 @@ public void actionPerformed(ActionEvent e) { } } }); - private static final ProgressDialogListener cancelListener = new ProgressDialogListener() { - @Override - public void cancelButton_actionPerformed(EventObject newEvent) { - synchronized (allBlockingTimers) { - while (!allBlockingTimers.isEmpty()) { - allBlockingTimers.remove(0); - } - ppStop.restart(); + private static final ProgressDialogListener cancelListener = newEvent -> { + synchronized (allBlockingTimers) { + while (!allBlockingTimers.isEmpty()) { + allBlockingTimers.remove(0); } + ppStop.restart(); } }; @@ -408,6 +404,4 @@ static void setFinalWindow(Hashtable hash, FinalWindow fWindow) String n = ClassUtils.getShortClassName(fWindow, def); throw new ProgrammingException("duplicate final windows" + e + " and " + n); } - - } diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/SwingWorker.java index 86f6caff57..f8df2c5e18 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/SwingWorker.java @@ -21,20 +21,7 @@ */ public abstract class SwingWorker { private static final Logger lg = LogManager.getLogger(SwingWorker.class); - /** - * set {@link SwingWorker} thread name - * - * @param name may not be null - * @throws IllegalArgumentException if name is null - */ - public void setThreadName(String name) { - if (name == null) throw new IllegalArgumentException("name may not be null"); - try { - this.threadVar.thread.setName(name); - } catch (SecurityException e) { - lg.warn("setSwingWorkerName fail", e); - } - } + /** * Class to maintain reference to current worker thread @@ -60,6 +47,22 @@ synchronized void clear() { private Object value; // see getValue(), setValue() private final ThreadVar threadVar; + + /** + * set {@link SwingWorker} thread name + * + * @param name may not be null + * @throws IllegalArgumentException if name is null + */ + public void setThreadName(String name) { + if (name == null) throw new IllegalArgumentException("name may not be null"); + try { + this.threadVar.thread.setName(name); + } catch (SecurityException e) { + lg.warn("setSwingWorkerName fail", e); + } + } + /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. @@ -80,12 +83,6 @@ private synchronized void setValue(Object x) { */ public abstract Object construct(); - /** - * Called on the event dispatching thread (not on the worker thread) - * after the construct method has returned. - */ - public void finished() {} - /** * A new method that interrupts the worker thread. Call this method * to force the worker to stop what it's doing. @@ -139,6 +136,12 @@ public void run() { this.threadVar = new ThreadVar(t); } + /** + * Called on the event dispatching thread (not on the worker thread) + * after the construct method has returned. + */ + public void finished() {} + /** * Start the worker thread. */ diff --git a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java index aed308adab..e6de21237a 100644 --- a/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java +++ b/vcell-core/src/main/java/cbit/vcell/clientdb/ClientDocumentManager.java @@ -102,7 +102,7 @@ import cbit.vcell.xml.XmlParseException; import cbit.vcell.xml.XmlReader; -public class ClientDocumentManager implements DocumentManager{ +public class ClientDocumentManager implements DocumentManager { private static final Logger lg = LogManager.getLogger(ClientDocumentManager.class); // // From 02c2a12f0c4941925ab95c7982993fa0c50f471a Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Mon, 22 Jul 2024 16:04:31 -0400 Subject: [PATCH 26/48] Added missing parameters --- .../client/task/ClientTaskDispatcher.java | 2 +- .../swingthreads/StandardSwingWorker.java | 55 +++++++++---------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index f7c21f2757..3d25b7839a 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -282,7 +282,7 @@ public static void dispatch(final Component requester, final Hashtable taskList; private Hashtable resultsHash; - private boolean shouldShowProgressPopup; - private boolean shouldBlockInput; - private boolean shouldInformOfProgress; - private boolean shouldBeCancelable; - private String threadBaseName; - private ProgressDialog customProgressDialog; - private Component requestingComponent; - private ProgressDialogListener progressDialogListener; + private final boolean shouldShowProgressPopup; + private final boolean shouldBlockInput; + private final boolean shouldInformOfProgress; + private final boolean shouldBeCancelable; + private final String threadBaseName; + private final ProgressDialog customProgressDialog; + private final Component requestingComponent; + private final ProgressDialogListener progressDialogListener; - private ClientTaskDispatcher.StopStrategy stopStrategy; + private final ClientTaskDispatcher.StopStrategy stopStrategy; - public StandardSwingWorker(String threadBaseName, Component requestingComponent, - ClientTaskDispatcher.StopStrategy stopStrategy, boolean shouldInformOfProgress, - ProgressDialogListener progressDialogListener, boolean shouldShowProgressPopup, - ProgressDialog customProgressDialog, boolean shouldBlockInput, boolean shouldBeCancelable) { + public StandardSwingWorker(String threadBaseName, List taskList, Component requestingComponent, + ClientTaskDispatcher.StopStrategy stopStrategy, Hashtable resultsHash, + boolean shouldInformOfProgress, ProgressDialogListener progressDialogListener, + boolean shouldShowProgressPopup, ProgressDialog customProgressDialog, + boolean shouldBlockInput, boolean shouldBeCancelable) { super(); this.threadBaseName = threadBaseName; + this.taskList = taskList; this.requestingComponent = requestingComponent; this.stopStrategy = stopStrategy; + this.resultsHash = resultsHash; this.shouldInformOfProgress = shouldInformOfProgress; this.progressDialogListener = progressDialogListener; this.shouldShowProgressPopup = shouldShowProgressPopup; @@ -70,16 +73,10 @@ public StandardSwingWorker(String threadBaseName, Component requestingComponent, public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { if (lg.isDebugEnabled()) { String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); - if (lg.isDebugEnabled()) { - Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); - StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) { - msg += '\n' + StringUtils.join(ste, '\n'); - } - lg.debug(msg); - } else { - lg.debug(msg); - } + Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); + StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); + if (ste != null) msg += '\n' + StringUtils.join(ste, '\n'); + lg.debug(msg); } //check required elements present StringBuilder sb = null; @@ -90,12 +87,13 @@ public static void runTask(AsynchClientTask currentTask, Hashtable foundClass = obj.getClass(); - if (!requiredKey.clzz.isAssignableFrom(foundClass)) { - if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); - sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); - sb.append('\n'); - } + if (requiredKey.clzz.isAssignableFrom(foundClass)) continue; + + if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); + sb.append('\n'); } if (sb == null) { //no problems found @@ -103,6 +101,7 @@ public static void runTask(AsynchClientTask currentTask, Hashtable Date: Tue, 23 Jul 2024 14:40:24 -0400 Subject: [PATCH 27/48] class name changes --- ...ker.java => StandardVCellSwingWorker.java} | 158 +++++++++--------- ...SwingWorker.java => VCellSwingWorker.java} | 58 ++++--- 2 files changed, 114 insertions(+), 102 deletions(-) rename vcell-client/src/main/java/swingthreads/{StandardSwingWorker.java => StandardVCellSwingWorker.java} (65%) rename vcell-client/src/main/java/swingthreads/{SwingWorker.java => VCellSwingWorker.java} (70%) diff --git a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java similarity index 65% rename from vcell-client/src/main/java/swingthreads/StandardSwingWorker.java rename to vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java index f9a7f3664a..ebd30de5b4 100644 --- a/vcell-client/src/main/java/swingthreads/StandardSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java @@ -3,10 +3,7 @@ import cbit.vcell.client.ClientMDIManager; import cbit.vcell.client.DocumentWindowManager; import cbit.vcell.client.PopupGenerator; -import cbit.vcell.client.task.AsynchClientTask; -import cbit.vcell.client.task.ClientTaskDispatcher; -import cbit.vcell.client.task.CommonTask; -import cbit.vcell.client.task.ResultsHashUtils; +import cbit.vcell.client.task.*; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,39 +15,40 @@ import javax.swing.*; import java.awt.*; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.List; -public abstract class StandardSwingWorker extends SwingWorker { - private static final Logger lg = LogManager.getLogger(StandardSwingWorker.class); +public abstract class StandardVCellSwingWorker extends VCellSwingWorker { + private static final Logger lg = LogManager.getLogger(StandardVCellSwingWorker.class); - private AsynchProgressPopup pp = null; - private Window windowParent = null; - private Component focusOwner = null; + protected AsynchProgressPopup progressPopup = null; + protected Window windowParent = null; + protected Component focusOwner = null; - private List taskList; - private Hashtable resultsHash; + protected final List taskList; + protected final Hashtable resultsHash; - private final boolean shouldShowProgressPopup; - private final boolean shouldBlockInput; - private final boolean shouldInformOfProgress; - private final boolean shouldBeCancelable; - private final String threadBaseName; - private final ProgressDialog customProgressDialog; - private final Component requestingComponent; - private final ProgressDialogListener progressDialogListener; + protected final boolean shouldShowProgressPopup; + protected final boolean shouldBlockInput; + protected final boolean shouldInformOfProgress; + protected final boolean shouldBeCancelable; + protected final String threadBaseName; + protected final ProgressDialog customProgressDialog; + protected final Component requestingComponent; + protected final ProgressDialogListener progressDialogListener; - private final ClientTaskDispatcher.StopStrategy stopStrategy; + protected final ClientTaskDispatcher.StopStrategy stopStrategy; - public StandardSwingWorker(String threadBaseName, List taskList, Component requestingComponent, - ClientTaskDispatcher.StopStrategy stopStrategy, Hashtable resultsHash, - boolean shouldInformOfProgress, ProgressDialogListener progressDialogListener, - boolean shouldShowProgressPopup, ProgressDialog customProgressDialog, - boolean shouldBlockInput, boolean shouldBeCancelable) { + public StandardVCellSwingWorker(String threadBaseName, List taskList, Component requestingComponent, + ClientTaskDispatcher.StopStrategy stopStrategy, Hashtable resultsHash, + boolean shouldInformOfProgress, ProgressDialogListener progressDialogListener, + boolean shouldShowProgressPopup, ProgressDialog customProgressDialog, + boolean shouldBlockInput, boolean shouldBeCancelable) { super(); this.threadBaseName = threadBaseName; - this.taskList = taskList; + this.taskList = new ArrayList<>(taskList); this.requestingComponent = requestingComponent; this.stopStrategy = stopStrategy; this.resultsHash = resultsHash; @@ -68,7 +66,7 @@ public StandardSwingWorker(String threadBaseName, List taskLis * @param currentTask not null * @param hash not null * @param taskList current set of tasks being dispatched - * @throws Exception + * @throws Exception if an exception was generated by running the task */ public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { if (lg.isDebugEnabled()) { @@ -83,7 +81,7 @@ public static void runTask(AsynchClientTask currentTask, Hashtable foundClass = obj.getClass(); if (requiredKey.clzz.isAssignableFrom(foundClass)) continue; - if (sb == null) sb = StandardSwingWorker.initStringBuilder(currentTask); + if (sb == null) sb = StandardVCellSwingWorker.initStringBuilder(currentTask); sb.append("key ").append(requiredKey.name).append(" type ").append(foundClass.getName()).append(" not of required type ").append(requiredKey.clzz.getName()); sb.append('\n'); } - if (sb == null) { //no problems found - currentTask.run(hash); + if (sb == null) { // no problems found + currentTask.run(hash); // Run the AsyncClientTask the user provided...many layers ago. return; } @@ -113,18 +111,18 @@ public static void runTask(AsynchClientTask currentTask, Hashtable verifyAndRun() { if (this.shouldShowProgressPopup) { if (this.customProgressDialog == null) { - this.pp = new AsynchProgressPopup(this.requestingComponent, "WORKING...", "Initializing request", Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + this.progressPopup = new AsynchProgressPopup(this.requestingComponent, "WORKING...", "Initializing request", Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); } else { - this.pp = new AsynchProgressPopup(this.requestingComponent, this.customProgressDialog, Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); + this.progressPopup = new AsynchProgressPopup(this.requestingComponent, this.customProgressDialog, Thread.currentThread(), this.shouldBlockInput, this.shouldInformOfProgress, this.shouldBeCancelable, this.progressDialogListener); } - this.pp.setStopStrategy(this.stopStrategy); + this.progressPopup.setStopStrategy(this.stopStrategy); if (this.shouldBlockInput) { - this.pp.startKeepOnTop(); + this.progressPopup.startKeepOnTop(); } else { - this.pp.start(); + this.progressPopup.start(); } } if (this.requestingComponent != null) this.windowParent = GuiUtils.getWindowForComponent(this.requestingComponent); @@ -147,58 +145,67 @@ public Object construct() { // also skip selected tasks specified by conditionalSkip tag final AsynchClientTask currentTask = this.taskList.get(i); try { - currentTask.setClientTaskStatusSupport(this.pp); + currentTask.setClientTaskStatusSupport(this.progressPopup); this.setThreadName(this.threadBaseName + currentTask.getTaskName()); //System.out.println("DISPATCHING: "+currentTask.getTaskName()+" at "+ new Date(System.currentTimeMillis())); - if (this.pp != null) { - this.pp.setVisible(currentTask.showProgressPopup()); + if (this.progressPopup != null) { + this.progressPopup.setVisible(currentTask.shouldShowProgressPopup()); if (!this.shouldInformOfProgress) { - this.pp.setProgress(i * 100 / this.taskList.size()); // beginning of task + this.progressPopup.setProgress(i * 100 / this.taskList.size()); // beginning of task } - this.pp.setMessage(currentTask.getTaskName()); + this.progressPopup.setMessage(currentTask.getTaskName()); } - boolean shouldRun = !this.resultsHash.containsKey(TaskEventKeys.HASH_DATA_ERROR.toString()); + + // If the hash results have an error, don't run the task. + if (this.resultsHash.containsKey(TaskEventKeys.HASH_DATA_ERROR.toString())) continue; + + // If the task has an error, don't run it. if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) && currentTask.skipIfAbort()) { - shouldRun = false; + continue; } + + // If task is supposed to be skipped, don't run it. if (this.resultsHash.containsKey(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString())) { String[] toSkip = (String[]) this.resultsHash.get(TaskEventKeys.TASKS_TO_BE_SKIPPED.toString()); boolean taskShouldBeSkipped = ArrayUtils.arrayContains(toSkip, currentTask.getClass().getName()); - if (taskShouldBeSkipped) shouldRun = false; + if (taskShouldBeSkipped) continue; } - if (this.pp != null && this.pp.isInterrupted()) { + + // If the popup recorded an interruption, don't run it. + if (this.progressPopup != null && this.progressPopup.isInterrupted()) { ClientTaskDispatcher.recordException(UserCancelException.CANCEL_GENERIC, this.resultsHash); } + // If task was aborted, don't run it. if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { UserCancelException exc = (UserCancelException) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_USER.toString()); - if (currentTask.skipIfCancel(exc)) shouldRun = false; + if (currentTask.skipIfCancel(exc)) continue; } - if (shouldRun) { - try { - if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - SwingUtilities.invokeAndWait(() -> { - try { - StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); - } - }); - } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - SwingUtilities.invokeLater(() -> { - try { - StandardSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); - } - }); - } - } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); + + // All indicators, green; launch it! + try { + if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + SwingUtilities.invokeAndWait(() -> { + try { + StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); + } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + SwingUtilities.invokeLater(() -> { + try { + StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); + } + }); } + } catch (Exception exc) { + ClientTaskDispatcher.recordException(exc, this.resultsHash); } } finally { this.removeTaskFromDispatcher(currentTask); @@ -207,12 +214,11 @@ public Object construct() { return this.resultsHash; } - public void finished() { + public void performSwingPostProcessing() { this.announceTaskComplete(); - if (this.pp != null) { - this.pp.stop(); - } + if (this.progressPopup != null) this.progressPopup.stop(); + if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())) { // something went wrong StringBuilder allCausesErrorMessageSB = new StringBuilder(); @@ -241,7 +247,7 @@ public void finished() { (Throwable) this.resultsHash.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString())); } else if (this.resultsHash.containsKey(TaskEventKeys.TASK_ABORTED_BY_USER.toString())) { // depending on where user canceled we might want to automatically start a new job - StandardSwingWorker.dispatchFollowUp(this.resultsHash); + StandardVCellSwingWorker.dispatchFollowUp(this.resultsHash); } ClientTaskDispatcher.FinalWindow fw = ResultsHashUtils.fetch(this.resultsHash, TaskEventKeys.FINAL_WINDOW.toString(), ClientTaskDispatcher.FinalWindow.class, false); @@ -283,7 +289,7 @@ private static void dispatchFollowUp(Hashtable hash) { */ private static StringBuilder initStringBuilder(AsynchClientTask currentTask) { StringBuilder sb = new StringBuilder(); - sb.append("Data error for task " + currentTask.getTaskName() + '\n'); + sb.append("Data error for task ").append(currentTask.getTaskName()).append('\n'); return sb; } diff --git a/vcell-client/src/main/java/swingthreads/SwingWorker.java b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java similarity index 70% rename from vcell-client/src/main/java/swingthreads/SwingWorker.java rename to vcell-client/src/main/java/swingthreads/VCellSwingWorker.java index f8df2c5e18..f31f0c8690 100644 --- a/vcell-client/src/main/java/swingthreads/SwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java @@ -1,11 +1,13 @@ package swingthreads; -import cbit.vcell.client.task.ClientTaskDispatcher; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.swing.SwingUtilities; -import java.lang.reflect.Field; +import java.util.Hashtable; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; /** * This is the 3rd version of SwingWorker (also known as @@ -43,11 +45,6 @@ synchronized void clear() { } } - // Instance Variables - private Object value; // see getValue(), setValue() - private final ThreadVar threadVar; - - /** * set {@link SwingWorker} thread name * @@ -63,26 +60,25 @@ public void setThreadName(String name) { } } + // Instance Variables + private Hashtable value; // see getValue(), setValue() + private final ThreadVar threadVar; + /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ - protected synchronized Object getValue() { + protected synchronized Hashtable getValue() { return this.value; } /** * Set the value produced by worker thread */ - private synchronized void setValue(Object x) { + private synchronized void setValue(Hashtable x) { this.value = x; } - /** - * Compute the value to be returned by the get method. - */ - public abstract Object construct(); - /** * A new method that interrupts the worker thread. Call this method * to force the worker to stop what it's doing. @@ -100,10 +96,10 @@ public void interrupt() { * * @return the value created by the construct method */ - public Object get() { + public Hashtable get() { while (true) { Thread t = this.threadVar.get(); - if (t == null) return this.getValue(); + if (t == null) return this.getValue(); // thread finished! try { t.join(); @@ -119,36 +115,46 @@ public Object get() { * and then exit. */ public SwingWorker() { - final Runnable doFinished = SwingWorker.this::finished; - - Runnable doConstruct = new Runnable() { + Runnable doWork = new Runnable() { public void run() { try { - SwingWorker.this.setValue(SwingWorker.this.construct()); + SwingWorker.this.setValue(SwingWorker.this.verifyAndRun()); // Invoke now, on the current thread } finally { + // At the time this is called, the thread is running SwingWorker.this.threadVar.clear(); + // We do this to make sure we never accidentally re-run the same thread. + // We must ensure "one and done" threading. } - SwingUtilities.invokeLater(doFinished); + SwingUtilities.invokeLater(SwingWorker.this::performSwingPostProcessing); } }; - Thread t = new Thread(doConstruct); - this.threadVar = new ThreadVar(t); + this.threadVar = new ThreadVar(new Thread(doWork)); } + /** + * Compute the value to be returned by the get method. + */ + public abstract Hashtable verifyAndRun(); + /** * Called on the event dispatching thread (not on the worker thread) * after the construct method has returned. */ - public void finished() {} + public abstract void performSwingPostProcessing(); /** * Start the worker thread. */ - public void start() { + public Future> start() { Thread t = this.threadVar.get(); + FutureTask> ft = new FutureTask<>(t.start(), this.); if (t != null) { - t.start(); + ft.run(); + return ft; } + + // Generally, getting here means we've already run the thread. + return t.start(); } } \ No newline at end of file From a05615f4835ba351c09190ed7024ec99619c52a8 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 14:41:27 -0400 Subject: [PATCH 28/48] Change API logging to display certain info notices when debug is enabled --- .../org/vcell/api/client/VCellApiClient.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java index 1c7b284458..22ba2e0da3 100644 --- a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java +++ b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java @@ -202,13 +202,13 @@ public SimulationTaskRepresentation[] getSimTasks(SimTasksQuerySpec simTasksQuer HttpGet httpget = new HttpGet(getApiUrlPrefix() + "/simtask?" + simTasksQuerySpec.getQueryString()); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation tasks " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getSimTasks()", httpget), httpClientContext); String simTasksJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(simTasksJson)); } @@ -231,13 +231,13 @@ public BiomodelRepresentation[] getBioModels(BioModelsQuerySpec bioModelsQuerySp HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel?"+bioModelsQuerySpec.getQueryString()); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve biomodels " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getBioModels()", httpget), httpClientContext); String bimodelsJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(bimodelsJson)); } @@ -251,13 +251,13 @@ public EventWrapper[] getEvents(long beginTimestamp) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/events?beginTimestamp="+beginTimestamp); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve user events " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getEvents()", httpget), httpClientContext); String eventWrappersJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(eventWrappersJson)); } @@ -271,13 +271,13 @@ public BiomodelRepresentation getBioModel(String bmId) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve biomodel " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getBioModel()", httpget), httpClientContext); String bimodelsJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(bimodelsJson)); } @@ -291,7 +291,7 @@ public String getBioModelVCML(String bmId) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId+"/biomodel.vcml"); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve biomodel " + httpget.getRequestLine()); } @@ -306,13 +306,13 @@ public SimulationRepresentation getSimulation(String bmId, String simKey) throws HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getSimulation()", httpget), httpClientContext); String simulationJson = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(simulationJson)); } @@ -326,12 +326,12 @@ public String getOptRunJson(String optimizationId,boolean bStop) throws IOExcept HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/optimization/"+optimizationId+"?bStop="+bStop); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve optimization run " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getOptRunJson()", httpget), httpClientContext); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(responseBody)); } return responseBody; @@ -429,7 +429,7 @@ public SimulationTaskRepresentation[] startSimulation(String bmId, String simKey HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey+"/startSimulation"); httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation " + httppost.getRequestLine()); } @@ -453,13 +453,13 @@ public SimulationTaskRepresentation[] stopSimulation(String bmId, String simKey) HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey+"/stopSimulation"); httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve simulation " + httppost.getRequestLine()); } String responseBody = httpclient.execute(httppost, new VCellStringResponseHandler("stopSimulation()", httppost), httpClientContext); String simTaskReps = responseBody; - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("returned: "+toStringTruncated(simTaskReps)); } @@ -826,7 +826,7 @@ public String getServerSoftwareVersion() throws ClientProtocolException, IOExcep HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/swversion"); - if (lg.isInfoEnabled()) { + if (lg.isDebugEnabled()) { lg.info("Executing request to retrieve server software version " + httpget.getRequestLine()); } From da8a010d6293f7904ad6e5f08a9dbbf42f75fd09 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 15:59:26 -0400 Subject: [PATCH 29/48] More transition from magic strings to enums --- .../src/main/java/cbit/vcell/client/ClientRequestManager.java | 4 ++-- .../main/java/cbit/vcell/client/DatabaseWindowManager.java | 3 ++- .../main/java/cbit/vcell/client/DocumentWindowManager.java | 3 ++- .../src/main/java/cbit/vcell/client/data/PDEDataViewer.java | 4 ++-- .../src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java | 3 ++- .../java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java | 2 +- .../src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java | 4 ++-- .../java/cbit/vcell/mapping/gui/InitialConditionsPanel.java | 4 ++-- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index f8dd1b13d0..dccc7126e6 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -474,7 +474,7 @@ public boolean closeWindow(final java.lang.String windowID, final boolean exitIf @Override public void run(Hashtable hashTable) throws Exception { // if there is error saving the document, try to unblock the window - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) != null) { + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { getMdiManager().unBlockWindow(windowID); getMdiManager().showWindow(windowID); } else { @@ -3544,7 +3544,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { try { - Throwable exc = (Throwable) hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + Throwable exc = (Throwable) hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); if (exc == null) { boolean isSEDML = (boolean) hashTable.get("isSEDML"); if (isSEDML) { diff --git a/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java b/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java index e2228d5513..5340889359 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/DatabaseWindowManager.java @@ -40,6 +40,7 @@ import org.vcell.util.gui.GeneralGuiUtils; import org.vcell.util.gui.VCFileChooser; import org.vcell.util.gui.exporter.FileFilters; +import swingthreads.TaskEventKeys; import javax.swing.Timer; import javax.swing.*; @@ -541,7 +542,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { try { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null) { XmlTreeDiff xmlTreeDiff = (XmlTreeDiff) hashTable.get("xmlTreeDiff"); String baselineDesc = docInfo1.getVersion().getName() + ", " + docInfo1.getVersion().getDate(); String modifiedDesc = docInfo2.getVersion().getName() + ", " + docInfo2.getVersion().getDate(); diff --git a/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java b/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java index 47b0825404..881caab1c5 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/DocumentWindowManager.java @@ -37,6 +37,7 @@ import cbit.vcell.simdata.OutputContext; import cbit.vcell.solver.VCSimulationIdentifier; import cbit.xml.merge.XmlTreeDiff; +import swingthreads.TaskEventKeys; public abstract class DocumentWindowManager extends TopLevelWindowManager implements java.awt.event.ActionListener, DataViewerManager { @@ -119,7 +120,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { try { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) == null) { + if (hashTable.get(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) == null) { XmlTreeDiff xmlTreeDiff = (XmlTreeDiff)hashTable.get("xmlTreeDiff"); String baselineDesc = getVCDocument()+ ", " + (getVCDocument().getVersion() == null ? "not saved" : getVCDocument().getVersion().getDate()); String modifiedDesc = "Opened document instance"; diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java b/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java index 311550adf0..baff043ac0 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java @@ -3333,7 +3333,7 @@ private boolean errorAutoAllTimes(boolean bPPInfo,Boolean bVarMatch,boolean isFi // }; // AsynchClientTask task3 = new AsynchClientTask("Setting cursor", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { // public void run(Hashtable hashTable) throws Exception { -// Throwable exc = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); +// Throwable exc = (Throwable)hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); // if (exc == null) { // updateTimeTextField(getPdeDataContext().getTimePoint()); // } else { @@ -3404,7 +3404,7 @@ private boolean errorAutoAllTimes(boolean bPPInfo,Boolean bVarMatch,boolean isFi // // AsynchClientTask task3 = new AsynchClientTask("Setting cursor", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { // public void run(Hashtable hashTable) throws Exception { -// Throwable e = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); +// Throwable e = (Throwable)hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); // if (e != null) { // int index = -1; // if(getPdeDataContext() != null && getPdeDataContext().getDataIdentifier() != null){ diff --git a/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java b/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java index b9e264192f..6bb376a3a5 100644 --- a/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/field/gui/FieldDataGUIPanel.java @@ -80,6 +80,7 @@ import cbit.vcell.simdata.SimulationData; import cbit.vcell.solver.SimulationInfo; import cbit.vcell.solvers.CartesianMesh; +import swingthreads.TaskEventKeys; public class FieldDataGUIPanel extends JPanel{ @@ -1388,7 +1389,7 @@ public int compare(DataIdentifier o1, DataIdentifier o2) { getJTree1().expandPath(new TreePath(varNode.getPath())); } }catch(Throwable e){ - hash.put(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR,e); + hash.put(TaskEventKeys.TASK_ABORTED_BY_ERROR.toString(), e); } } }; diff --git a/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java b/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java index b6f69641ba..c944a4aa02 100644 --- a/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java +++ b/vcell-client/src/main/java/cbit/vcell/geometry/gui/ROIMultiPaintManager.java @@ -429,7 +429,7 @@ public void run(Hashtable hashTable) throws Exception { AsynchClientTask failTask = new AsynchClientTask("Check fail...",AsynchClientTask.TASKTYPE_SWING_BLOCKING,false,false,true) { @Override public void run(Hashtable hashTable) throws Exception { - Throwable throwable = (Throwable)hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + Throwable throwable = (Throwable)hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); if(throwable != null){ //cleanup ComboboxROIName[] comboboxROINames = overlayEditorPanelJAI.getAllCompositeROINamesAndColors(); diff --git a/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java b/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java index d6076e75ac..af0035b3c2 100644 --- a/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java +++ b/vcell-client/src/main/java/cbit/vcell/graph/gui/BioCartoonTool.java @@ -634,9 +634,9 @@ public void run(Hashtable hashTable)throws Exception { AsynchClientTask reshowInterface = new AsynchClientTask("Reshow interface...",AsynchClientTask.TASKTYPE_NONSWING_BLOCKING,false,true) { @Override public void run(Hashtable hashTable) throws Exception { - Object error = hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + Object error = hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); if(assignmentHelper.getAssignmentInterface() != null && error != null) { - hashTable.remove(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR); + hashTable.remove(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); //Reshow the interface if there was an error new Thread(new Runnable() { @Override diff --git a/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java b/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java index d08fa5dbf1..5a02858678 100644 --- a/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/mapping/gui/InitialConditionsPanel.java @@ -306,7 +306,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) != null) { + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { getSimulationContext().setUsingConcentration(false, true); updateTopScrollPanel(); } @@ -347,7 +347,7 @@ public void run(Hashtable hashTable) throws Exception { @Override public void run(Hashtable hashTable) throws Exception { - if (hashTable.get(ClientTaskDispatcher.TASK_ABORTED_BY_ERROR) != null) { + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { getSimulationContext().setUsingConcentration(true, true); updateTopScrollPanel(); } From 27ba0cc97752927286bd85e4924e8910347ea715 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 15:59:47 -0400 Subject: [PATCH 30/48] Changed name to match similar closures --- .../src/main/java/cbit/vcell/client/ClientSimManager.java | 2 +- .../cbit/vcell/client/desktop/biomodel/MathematicsPanel.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java index 0432bc61fc..eb42d8ef30 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientSimManager.java @@ -607,7 +607,7 @@ public void cancelButton_actionPerformed(EventObject newEvent) { } }; tasks.add(pv); - ClientTaskDispatcher.dispatchColl(documentWindowManager.getComponent(), new Hashtable(), tasks, false, true, null); + ClientTaskDispatcher.dispatch(documentWindowManager.getComponent(), new Hashtable(), tasks, false, true, null); } public void runQuickSimulation(final Simulation originalSimulation, ViewerType viewerType) { diff --git a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java index f35db026df..7b89a71edb 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/MathematicsPanel.java @@ -184,14 +184,14 @@ private javax.swing.JRadioButton getViewVCMDLRadioButton() { } private void refreshMath() { - ClientTaskDispatcher.dispatchColl(MathematicsPanel.this, new Hashtable(), ClientRequestManager.updateMath(this, simulationContext, true,NetworkGenerationRequirements.ComputeFullStandardTimeout), false); + ClientTaskDispatcher.dispatch(MathematicsPanel.this, new Hashtable(), ClientRequestManager.updateMath(this, simulationContext, true,NetworkGenerationRequirements.ComputeFullStandardTimeout), false); } private void createMathModel(final ActionEvent e) { // relays an action event with this as the source Collection tasks = ClientRequestManager.updateMath(this, simulationContext, true,NetworkGenerationRequirements.ComputeFullStandardTimeout); tasks.add(new AsynchClientTaskFunction(ht -> refireActionPerformed(e),"creating math model", AsynchClientTask.TASKTYPE_SWING_BLOCKING) ); - ClientTaskDispatcher.dispatchColl(this, new Hashtable(), tasks, false); + ClientTaskDispatcher.dispatch(this, new Hashtable(), tasks, false); } public synchronized void addActionListener(ActionListener l) { From fdf9f962b3f639d16f627e9c26be2eb035637f36 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Tue, 23 Jul 2024 16:01:01 -0400 Subject: [PATCH 31/48] Integrated Futures into newly named VCellSwingWorker system --- .../vcell/client/task/AsynchClientTask.java | 2 +- .../client/task/ClientTaskDispatcher.java | 152 ++++++++++++++---- .../StandardVCellSwingWorker.java | 2 +- .../java/swingthreads/VCellSwingWorker.java | 75 +++++---- 4 files changed, 165 insertions(+), 66 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java index eb86117b7c..1adb2c52da 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/AsynchClientTask.java @@ -116,7 +116,7 @@ public void setClientTaskStatusSupport(ClientTaskStatusSupport clientTaskStatusS this.clientTaskStatusSupport = clientTaskStatusSupport; } - public boolean showProgressPopup() { + public boolean shouldShowProgressPopup() { return this.bShowProgressPopup; } diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 3d25b7839a..264ea6c091 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -16,11 +16,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.EventObject; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.WeakHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import javax.swing.Timer; @@ -32,8 +35,8 @@ import org.vcell.util.gui.ProgressDialog; import cbit.vcell.simdata.PDEDataContext; -import swingthreads.StandardSwingWorker; -import swingthreads.SwingWorker; +import swingthreads.StandardVCellSwingWorker; +import swingthreads.VCellSwingWorker; import swingthreads.TaskEventKeys; /** @@ -44,6 +47,7 @@ */ public class ClientTaskDispatcher { private static final Logger lg = LogManager.getLogger(ClientTaskDispatcher.class); + private static final long DEFAULT_TIMEOUT = 5000;//ms /** * used to count / generate thread names */ @@ -74,25 +78,71 @@ public static void dispatch(Component requester, Hashtable hash, ClientTaskDispatcher.dispatch(requester, hash, tasks, false, false, false, null, false); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, false, false, false, null, false); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, false, false, false, null, false); + } + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, false, null, false); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, true, bKnowProgress, false, null, false); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, true, bKnowProgress, false, null, false); + } + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener) { ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, false); + } + public static void dispatch(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { ClientTaskDispatcher.dispatch(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } + public static Future> dispatchWithFuture(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchAndWait(Component requester, Hashtable hash, AsynchClientTask[] tasks, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, true, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { ClientTaskDispatcher.dispatch(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); } + public static Future> dispatchWithFuture(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + + public static void dispatchAndWait(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, null, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); + } + public static boolean isBusy() { // System.out.println("----------Busy----------"); return entryCounter > 0; @@ -250,11 +300,51 @@ public static void dispatch(final Component requester, final Hashtable> dispatchWithFuture(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking) { + return ClientTaskDispatcher.dispatchWithFuture(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, + bInputBlocking, StopStrategy.THREAD_INTERRUPT); + } + + public static void dispatchAndWait(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking) { + ClientTaskDispatcher.dispatchAndWait(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, + bInputBlocking, StopStrategy.THREAD_INTERRUPT); + } + public static void dispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking, final StopStrategy stopStrategy) { + ClientTaskDispatcher.masterDispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, + progressDialogListener, bInputBlocking, stopStrategy, false); + } + + public static Future> dispatchWithFuture(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy){ + return ClientTaskDispatcher.masterDispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, + progressDialogListener, bInputBlocking, stopStrategy, false); + } + + public static void dispatchAndWait(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy){ + ClientTaskDispatcher.masterDispatch(requester, hash, tasks, customDialog, bShowProgressPopup, bKnowProgress, cancelable, + progressDialogListener, bInputBlocking, stopStrategy, true); + } + + private static Future> masterDispatch(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, + final ProgressDialog customDialog, final boolean bShowProgressPopup, final boolean bKnowProgress, + final boolean cancelable, final ProgressDialogListener progressDialogListener, + final boolean bInputBlocking, final StopStrategy stopStrategy, final boolean blockUntilDone){ final String threadBaseName = "ClientTaskDispatcher " + (serial++) + ' '; final List taskList = new ArrayList<>(); @@ -281,8 +371,8 @@ public static void dispatch(final Component requester, final Hashtable> futureResult = worker.start(); + if (!blockUntilDone) return futureResult; + try { + futureResult.get(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + lg.error("Unexpected exception occurred during execution of {} : ", threadBaseName, e); + lg.error(e); + } catch (InterruptedException e) { + lg.error("Unexpected thread interruption of {}: ", threadBaseName); + lg.error(e); + } catch (TimeoutException e) { + lg.error("Unexpected timeout occurred during execution of {} : ", threadBaseName); + lg.error(e); + } + return futureResult; } /** @@ -308,8 +412,7 @@ public void announceTaskComplete() { * @return wrapper */ public static Runnable debugWrapper(Runnable r) { - return () -> - { + return () -> { lg.debug("calling " + r.getClass().getName() + ".run on " + r); r.run(); }; @@ -351,33 +454,16 @@ public static boolean hasOutstandingTasks() { } //updated API - public static void dispatchColl(Component requester, Hashtable hash, Collection coll) { - dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new)); - } - - public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { + // Extend if desired! + public static void dispatch(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress) { dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress); } - public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener) { + public static void dispatch(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, + boolean cancelable, ProgressDialogListener progressDialogListener) { dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener); } - public static void dispatchColl(Component requester, Hashtable hash, Collection coll, boolean bKnowProgress, - boolean cancelable, ProgressDialogListener progressDialogListener, boolean bInputBlocking) { - dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bKnowProgress, cancelable, progressDialogListener, bInputBlocking); - } - - public static void dispatchColl(final Component requester, final Hashtable hash, Collection coll, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - dispatch(requester, hash, coll.toArray(AsynchClientTask[]::new), bShowProgressPopup, bKnowProgress, cancelable, progressDialogListener, bInputBlocking); - } - - public static void dispatchColl(final Component requester, final Hashtable hash, final AsynchClientTask[] tasks, final ProgressDialog customDialog, - final boolean bShowProgressPopup, final boolean bKnowProgress, final boolean cancelable, final ProgressDialogListener progressDialogListener, final boolean bInputBlocking) { - } - //package public interface FinalWindow extends Runnable { @@ -404,4 +490,12 @@ static void setFinalWindow(Hashtable hash, FinalWindow fWindow) String n = ClassUtils.getShortClassName(fWindow, def); throw new ProgrammingException("duplicate final windows" + e + " and " + n); } + + private void removeTaskFromDispatcher(AsynchClientTask task) { + ClientTaskDispatcher.allTasks.remove(task); + } + + public void announceTaskComplete() { + ClientTaskDispatcher.entryCounter--; + } } diff --git a/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java index ebd30de5b4..002942e312 100644 --- a/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java @@ -192,7 +192,7 @@ public Hashtable verifyAndRun() { try { StandardVCellSwingWorker.runTask(currentTask, this.resultsHash, this.taskList); } catch (Exception exc) { - ClientTaskDispatcher.recordException(exc, this.resultsHash); + ClientTaskDispatcher.recordException(exc, StandardVCellSwingWorker.this.resultsHash); } }); } else if (currentTask.getTaskType() == AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { diff --git a/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java index f31f0c8690..16b7a40b5b 100644 --- a/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/VCellSwingWorker.java @@ -10,8 +10,11 @@ import java.util.concurrent.FutureTask; /** - * This is the 3rd version of SwingWorker (also known as - * SwingWorker 3), an abstract class that you subclass to + * This class is based upon the 3rd version of SwingWorker (also known as + * SwingWorker 3). Its job is to serve as a worker that dispatches tasks to the correct endpoints (swing or otherwise), + * based on the type of AsynchClientTask requested. + *

+ * SwingWorker 3 is an abstract class that you subclass to * perform GUI-related work in a dedicated thread. For * instructions on using this class, see: *

@@ -21,19 +24,21 @@ * You must now invoke start() on the SwingWorker after * creating it. */ -public abstract class SwingWorker { - private static final Logger lg = LogManager.getLogger(SwingWorker.class); +public abstract class VCellSwingWorker { + private static final Logger lg = LogManager.getLogger(VCellSwingWorker.class); /** * Class to maintain reference to current worker thread * under separate synchronization control. */ - private static class ThreadVar { + private static class TaskThread { private Thread thread; + private final FutureTask> futureTask; - ThreadVar(Thread t) { - this.thread = t; + TaskThread(Callable> callableTask) { + this.futureTask = new FutureTask<>(callableTask); + this.thread = new Thread(this.futureTask); } synchronized Thread get() { @@ -43,10 +48,16 @@ synchronized Thread get() { synchronized void clear() { this.thread = null; } + + Future> start(){ + if (this.thread == null) return this.futureTask; // do not rerun the task! It's already done. + this.thread.start(); + return this.futureTask; + } } /** - * set {@link SwingWorker} thread name + * set {@link VCellSwingWorker} thread name * * @param name may not be null * @throws IllegalArgumentException if name is null @@ -54,29 +65,29 @@ synchronized void clear() { public void setThreadName(String name) { if (name == null) throw new IllegalArgumentException("name may not be null"); try { - this.threadVar.thread.setName(name); + this.threadedTask.thread.setName(name); } catch (SecurityException e) { lg.warn("setSwingWorkerName fail", e); } } // Instance Variables - private Hashtable value; // see getValue(), setValue() - private final ThreadVar threadVar; + private Hashtable hashResults; // see getValue(), setValue() + private final TaskThread threadedTask; /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ - protected synchronized Hashtable getValue() { - return this.value; + protected synchronized Hashtable getHashResults() { + return this.hashResults; } /** * Set the value produced by worker thread */ - private synchronized void setValue(Hashtable x) { - this.value = x; + private synchronized void setHashResults(Hashtable x) { + this.hashResults = x; } /** @@ -84,9 +95,9 @@ private synchronized void setValue(Hashtable x) { * to force the worker to stop what it's doing. */ public void interrupt() { - Thread t = this.threadVar.get(); + Thread t = this.threadedTask.get(); if (t != null) t.interrupt(); - this.threadVar.clear(); + this.threadedTask.clear(); } /** @@ -98,8 +109,8 @@ public void interrupt() { */ public Hashtable get() { while (true) { - Thread t = this.threadVar.get(); - if (t == null) return this.getValue(); // thread finished! + Thread t = this.threadedTask.get(); + if (t == null) return this.getHashResults(); // thread finished! try { t.join(); @@ -114,22 +125,24 @@ public Hashtable get() { * Start a thread that will call the construct method * and then exit. */ - public SwingWorker() { - Runnable doWork = new Runnable() { - public void run() { + public VCellSwingWorker() { + Callable> doWork = new Callable<>() { + @Override + public Hashtable call() { try { - SwingWorker.this.setValue(SwingWorker.this.verifyAndRun()); // Invoke now, on the current thread + VCellSwingWorker.this.setHashResults(VCellSwingWorker.this.verifyAndRun()); // Invoke now, on the current thread } finally { // At the time this is called, the thread is running - SwingWorker.this.threadVar.clear(); + VCellSwingWorker.this.threadedTask.clear(); // We do this to make sure we never accidentally re-run the same thread. // We must ensure "one and done" threading. } - SwingUtilities.invokeLater(SwingWorker.this::performSwingPostProcessing); + SwingUtilities.invokeLater(VCellSwingWorker.this::performSwingPostProcessing); + return VCellSwingWorker.this.hashResults; } }; - this.threadVar = new ThreadVar(new Thread(doWork)); + this.threadedTask = new TaskThread(doWork); } /** @@ -147,14 +160,6 @@ public void run() { * Start the worker thread. */ public Future> start() { - Thread t = this.threadVar.get(); - FutureTask> ft = new FutureTask<>(t.start(), this.); - if (t != null) { - ft.run(); - return ft; - } - - // Generally, getting here means we've already run the thread. - return t.start(); + return this.threadedTask.start(); } } \ No newline at end of file From e342110cb329717d0001895e395c4e6b9ee51080 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 10:16:06 -0400 Subject: [PATCH 32/48] Changed to blocking call; currently negligible delay --- .../src/main/java/cbit/vcell/client/ClientRequestManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index dccc7126e6..746127fc9f 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -352,9 +352,8 @@ public void run(Hashtable hashTable) throws Exception { hashTable.put(IS_CHANGED_KEY, hasBeenChanged); } }; - ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[]{checkIfChanged}, + ClientTaskDispatcher.dispatchAndWait(null, hashtable, new AsynchClientTask[]{checkIfChanged}, false, false, null, true); - ClientTaskDispatcher.dispatch(null, hashtable, new AsynchClientTask[] {checkIfChanged}); if (hashtable.containsKey(IS_CHANGED_KEY)) isChanged = (Boolean)hashtable.get(IS_CHANGED_KEY); else if (hashtable.containsKey("clientTaskDispatcherStackTraceArray")){ @@ -463,6 +462,7 @@ public boolean closeWindow(final java.lang.String windowID, final boolean exitIf getMdiManager().showWindow(windowID); getMdiManager().blockWindow(windowID); CloseOption closeOption = checkBeforeClosing((DocumentWindowManager) windowManager); + lg.error("Yup, he's not dead Jim"); if (closeOption.equals(CloseOption.CANCEL_CLOSE)) { // user canceled getMdiManager().unBlockWindow(windowID); From 22adf127205ff619f0aff9c13b4ab43100aef595 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 11:19:24 -0400 Subject: [PATCH 33/48] changed to debug call --- .../vcell/client/desktop/biomodel/AnnotationsPanel.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java index 88c39fd626..5fd1d38c45 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/desktop/biomodel/AnnotationsPanel.java @@ -26,6 +26,8 @@ import cbit.vcell.model.*; import cbit.vcell.xml.gui.MiriamTreeModel; import cbit.vcell.xml.gui.MiriamTreeModel.LinkNode; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.vcell.model.rbm.MolecularType; import org.vcell.pathway.BioPaxObject; import org.vcell.sybil.models.AnnotationQualifiers; @@ -59,6 +61,8 @@ */ @SuppressWarnings("serial") public class AnnotationsPanel extends DocumentEditorSubPanel { + private static Logger lg = LogManager.getLogger(AnnotationsPanel.class); + private BioModel bioModel = null; private VCMetaData vcMetaData = null; MiriamTreeModel miriamTreeModel = null; @@ -517,7 +521,7 @@ public JComboBox getJComboBoxURI() { @Override public void actionPerformed(ActionEvent e) { VCMetaDataDataType mdt = (VCMetaDataDataType)jComboBoxURI.getSelectedItem(); - System.out.println("aici"); + lg.debug("aici"); if(mdt != null && mdt.isSearchable()) { getJButtonSearchRef().setEnabled(true); } else { From f307ae04c0a36c0eb0277978c6efb1c18a172deb Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 11:20:12 -0400 Subject: [PATCH 34/48] Removed object synchronization, and instead locked on the object; may need to synchronize on the specific manager, but not sure. --- .../client/server/AsynchMessageManager.java | 309 ++++++------------ 1 file changed, 98 insertions(+), 211 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index a7931d8085..a2d7ffbf61 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -54,22 +54,19 @@ public class AsynchMessageManager implements SimStatusListener, DataAccessExcept private static Logger lg = LogManager.getLogger(AsynchMessageManager.class); private EventListenerList listenerList = new EventListenerList(); - private ClientServerManager clientServerManager = null; + private ClientServerManager clientServerManager; private int failureCount = 0; private ScheduledExecutorService executorService = null; private long counter = 0; private long pollTime = BASE_POLL_SECONDS; - private AtomicBoolean bPoll = new AtomicBoolean(false); + private AtomicBoolean isPollingEnabled = new AtomicBoolean(false); private ScheduledFuture pollingHandle = null; /** * for {@link #schedule(long)} method */ private final ReentrantLock scheduleLock = new ReentrantLock(); + private final ReentrantLock connectionLock = new ReentrantLock(); -/** - * Insert the method's description here. - * Creation date: (6/9/2004 4:55:22 PM) - */ public AsynchMessageManager(ClientServerManager csm) { this.clientServerManager = csm; } @@ -78,19 +75,19 @@ public AsynchMessageManager(ClientServerManager csm) { * no-op if already called */ public synchronized void startPolling() { - if (!bPoll.get()) { - bPoll.set(true); - if (executorService == null) { - executorService = VCellExecutorService.get(); - DataAccessException.addListener(this); - } - schedule(pollTime); + if (isPollingEnabled.get()) return; + isPollingEnabled.set(true); + if (executorService == null) { + executorService = VCellExecutorService.get(); + DataAccessException.addListener(this); } + schedule(pollTime); + } public void stopPolling() { // lg.trace("stopping polling"); - bPoll.set(false); + isPollingEnabled.set(false); } @Override @@ -101,73 +98,57 @@ public void created(DataAccessException dae) { schedule(0); } private void poll( ) { - if (!bPoll.get()) { - if (lg.isDebugEnabled()){ - lg.debug("polling stopped"); - } + if (!isPollingEnabled.get()) { + lg.debug("polling stopped"); return; } - - if (lg.isDebugEnabled()){ - lg.debug("polling"); - } - boolean report = counter%50 == 0; + + lg.debug("polling"); + boolean shouldReport = counter % 50 == 0; long begin = 0; long end = 0; - // + // ask remote message listener (really should be "message producer") for any queued events. - // try { - MessageEvent[] queuedEvents = null; - if (report) { - // time the call - begin = System.currentTimeMillis(); - } - synchronized (this) { - if (!clientServerManager.isStatusConnected()) { - clientServerManager.attemptReconnect( ); - return; - } - pollTime = BASE_POLL_SECONDS; - queuedEvents = clientServerManager.getMessageEvents(); + MessageEvent[] queuedEvents; + if (shouldReport) begin = System.currentTimeMillis(); // time the call + + if (!clientServerManager.isStatusConnected()){ + connectionLock.lock(); + clientServerManager.attemptReconnect(); + return; } - if (report) { - end = System.currentTimeMillis(); - } + pollTime = BASE_POLL_SECONDS; + queuedEvents = clientServerManager.getMessageEvents(); + + if (shouldReport) end = System.currentTimeMillis(); + failureCount = 0; //this is skipped if the connection has failed:w // deal with events, if any - if (queuedEvents != null) { - for (MessageEvent messageEvent : queuedEvents){ - onMessageEvent(messageEvent); - } - } - // report polling call performance - if (report) { - double duration = ((double)(end - begin)) / 1000; - PerformanceMonitorEvent performanceMonitorEvent = new PerformanceMonitorEvent( - this, null, new PerformanceData( - "AsynchMessageManager.poll()", - MessageEvent.POLLING_STAT, - new PerformanceDataEntry[] {new PerformanceDataEntry("remote call duration", Double.toString(duration))} - ) - ); - } + if (queuedEvents != null) for (MessageEvent messageEvent : queuedEvents) onMessageEvent(messageEvent); + if (!shouldReport) return; + + // report polling call performance + double duration = ((double) (end - begin)) / 1000; + PerformanceMonitorEvent performanceMonitorEvent = new PerformanceMonitorEvent( + this, null, new PerformanceData( + "AsynchMessageManager.poll()", + MessageEvent.POLLING_STAT, + new PerformanceDataEntry[] {new PerformanceDataEntry("remote call duration", Double.toString(duration))} + ) + ); } catch (Exception exc) { - System.out.println(">> polling failure << " + exc.getMessage()); + lg.error(">> POLLING FAILURE <<", exc); pollTime = ATTEMPT_POLL_SECONDS; failureCount ++; if (failureCount % 3 == 0) { - bPoll.set(false); + isPollingEnabled.set(false); clientServerManager.setDisconnected(); } - } - finally { - if (lg.isDebugEnabled()) { - lg.debug(ExecutionTrace.justClassName(this) + " poll time " + pollTime + " seconds"); - } - if (bPoll.get()){ - schedule(pollTime); - } + } finally { + connectionLock.unlock(); + lg.debug(ExecutionTrace.justClassName(this) + " poll time " + pollTime + " seconds"); + if (isPollingEnabled.get()) schedule(pollTime); } } @@ -203,56 +184,39 @@ private void onMessageEvent(MessageEvent event) { } } -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void addDataJobListener(DataJobListener listener) { - listenerList.add(DataJobListener.class, listener); +public void addDataJobListener(DataJobListener listener) { + synchronized (listenerList){ + listenerList.add(DataJobListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void addExportListener(ExportListener listener) { - listenerList.add(ExportListener.class, listener); +public void addExportListener(ExportListener listener) { + synchronized (listenerList){ + listenerList.add(ExportListener.class, listener); + } } - -/** - * addSimulationStatusEventListener method comment. - */ -public synchronized void addSimStatusListener(SimStatusListener listener) { - listenerList.add(SimStatusListener.class, listener); +public void addSimStatusListener(SimStatusListener listener) { + synchronized (listenerList){ + listenerList.add(SimStatusListener.class, listener); + } } -/** - * addSimulationStatusEventListener method comment. - */ -public synchronized void addSimulationJobStatusListener(SimulationJobStatusListener listener) { - listenerList.add(SimulationJobStatusListener.class, listener); +public void addSimulationJobStatusListener(SimulationJobStatusListener listener) { + synchronized (listenerList){ + listenerList.add(SimulationJobStatusListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (6/19/2006 12:51:56 PM) - * @param listener cbit.vcell.desktop.controls.ExportListener - */ public void addVCellMessageEventListener(VCellMessageEventListener listener) { - listenerList.add(VCellMessageEventListener.class, listener); + synchronized (listenerList){ + listenerList.add(VCellMessageEventListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.ExportEvent - */ protected void fireDataJobEvent(DataJobEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -261,31 +225,15 @@ protected void fireDataJobEvent(DataJobEvent event) { // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==DataJobListener.class) { - fireDataJobEvent(event, (DataJobListener)listeners[i+1]); - } - } + if (listeners[i] != DataJobListener.class) continue; + fireDataJobEvent(event, (DataJobListener) listeners[i + 1]); + } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireDataJobEvent(final DataJobEvent event, final DataJobListener listener) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - listener.dataJobMessage(event); - } - }); + SwingUtilities.invokeLater(() -> listener.dataJobMessage(event)); } - -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.ExportEvent - */ protected void fireExportEvent(ExportEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -294,58 +242,31 @@ protected void fireExportEvent(ExportEvent event) { // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==ExportListener.class) { - fireExportEvent(event, (ExportListener)listeners[i+1]); - } - } + if (listeners[i] != ExportListener.class) continue; + fireExportEvent(event, (ExportListener) listeners[i + 1]); + } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireExportEvent(final ExportEvent event, final ExportListener listener) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - listener.exportMessage(event); - } - }); + SwingUtilities.invokeLater(() -> listener.exportMessage(event)); } -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.JobCompletedEvent - */ protected void fireSimStatusEvent(SimStatusEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==SimStatusListener.class) { - fireSimStatusEvent(event, (SimStatusListener)listeners[i+1]); - } + if (listeners[i] != SimStatusListener.class) continue; + fireSimStatusEvent(event, (SimStatusListener)listeners[i+1]); } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireSimStatusEvent(final SimStatusEvent event, final SimStatusListener listener) { listener.simStatusChanged(event); } - -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.JobCompletedEvent - */ protected void fireSimulationJobStatusEvent(SimulationJobStatusEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -354,27 +275,15 @@ protected void fireSimulationJobStatusEvent(SimulationJobStatusEvent event) { // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==SimulationJobStatusListener.class) { - fireSimulationJobStatusEvent(event, (SimulationJobStatusListener)listeners[i+1]); - } + if (listeners[i] != SimulationJobStatusListener.class) continue; + fireSimulationJobStatusEvent(event, (SimulationJobStatusListener)listeners[i+1]); } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireSimulationJobStatusEvent(final SimulationJobStatusEvent event, final SimulationJobStatusListener listener) { listener.simulationJobStatusChanged(event); } - -/** - * Insert the method's description here. - * Creation date: (11/17/2000 11:43:22 AM) - * @param event cbit.rmi.event.ExportEvent - */ protected void fireVCellMessageEvent(VCellMessageEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); @@ -389,71 +298,49 @@ protected void fireVCellMessageEvent(VCellMessageEvent event) { } } - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:49:15 PM) - */ private void fireVCellMessageEvent(final VCellMessageEvent event, final VCellMessageEventListener listener) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - listener.onVCellMessageEvent(event); - } - }); + SwingUtilities.invokeLater(() -> listener.onVCellMessageEvent(event)); } -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void removeDataJobListener(DataJobListener listener) { - listenerList.remove(DataJobListener.class, listener); +public void removeDataJobListener(DataJobListener listener) { + synchronized (listenerList){ + listenerList.remove(DataJobListener.class, listener); + } } - -/** - * Insert the method's description here. - * Creation date: (3/29/2001 5:18:16 PM) - * @param listener ExportListener - */ -public synchronized void removeExportListener(ExportListener listener) { - listenerList.remove(ExportListener.class, listener); +public void removeExportListener(ExportListener listener) { + synchronized (listenerList){ + listenerList.remove(ExportListener.class, listener); + } } /** * removeSimulationStatusEventListener method comment. */ -public synchronized void removeSimStatusListener(SimStatusListener listener) { - listenerList.remove(SimStatusListener.class, listener); +public void removeSimStatusListener(SimStatusListener listener) { + synchronized (listenerList){ + listenerList.remove(SimStatusListener.class, listener); + } } /** * removeSimulationStatusEventListener method comment. */ -public synchronized void removeSimulationJobStatusListener(SimulationJobStatusListener listener) { - listenerList.remove(SimulationJobStatusListener.class, listener); +public void removeSimulationJobStatusListener(SimulationJobStatusListener listener) { + synchronized (listenerList){ + listenerList.remove(SimulationJobStatusListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (6/19/2006 12:54:05 PM) - * @param listener cbit.vcell.desktop.controls.ExportListener - */ public void removeVCellMessageEventListener(VCellMessageEventListener listener) { - listenerList.remove(VCellMessageEventListener.class, listener); + synchronized (listenerList){ + listenerList.remove(VCellMessageEventListener.class, listener); + } } -/** - * Insert the method's description here. - * Creation date: (6/9/2004 2:27:28 PM) - * @param newJobStatus cbit.vcell.messaging.db.SimulationJobStatus - * @param progress java.lang.Double - * @param timePoint java.lang.Double - */ public void simStatusChanged(SimStatusEvent simStatusEvent) { // refire for swing fireSimStatusEvent(simStatusEvent); From 12d5e2a9a24ec6298a369c0ed99aab6caeb7c95e Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 15:13:10 -0400 Subject: [PATCH 35/48] Removed super useful logging. --- .../src/main/java/cbit/vcell/client/ClientRequestManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index 746127fc9f..2365ae79f9 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -462,7 +462,6 @@ public boolean closeWindow(final java.lang.String windowID, final boolean exitIf getMdiManager().showWindow(windowID); getMdiManager().blockWindow(windowID); CloseOption closeOption = checkBeforeClosing((DocumentWindowManager) windowManager); - lg.error("Yup, he's not dead Jim"); if (closeOption.equals(CloseOption.CANCEL_CLOSE)) { // user canceled getMdiManager().unBlockWindow(windowID); From 08f703911aa36cb3e1ba11955c28d42039a9305a Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 15:20:03 -0400 Subject: [PATCH 36/48] Changed to "tryLock()" to prevent uneccessary reconnect calls --- .../java/cbit/vcell/client/server/AsynchMessageManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index a2d7ffbf61..72200b7275 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -114,7 +114,7 @@ private void poll( ) { if (shouldReport) begin = System.currentTimeMillis(); // time the call if (!clientServerManager.isStatusConnected()){ - connectionLock.lock(); + if (!connectionLock.tryLock()) return; clientServerManager.attemptReconnect(); return; } From 19753af723885be12710d318f4d4380f762a76f5 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 15:20:19 -0400 Subject: [PATCH 37/48] Cleaned up ClientRequestManager --- .../vcell/client/ClientRequestManager.java | 9101 ++++++++--------- 1 file changed, 4533 insertions(+), 4568 deletions(-) diff --git a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java index 2365ae79f9..8afaf469ae 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java +++ b/vcell-client/src/main/java/cbit/vcell/client/ClientRequestManager.java @@ -130,897 +130,886 @@ import java.util.zip.GZIPInputStream; public class ClientRequestManager - implements RequestManager, PropertyChangeListener, ExportListener, VCellMessageEventListener { - private VCellClient vcellClient = null; - - private boolean bOpening = false; - private boolean bExiting = false; - - private static final Logger lg = LogManager.getLogger(ClientRequestManager.class); - - public ClientRequestManager(VCellClient vcellClient) { - setVcellClient(vcellClient); - // listen to connectionStatus events - getClientServerManager().addPropertyChangeListener(this); - getClientServerManager().getAsynchMessageManager().addExportListener(this); - getClientServerManager().getAsynchMessageManager().addVCellMessageEventListener(this); - - } - - private static final String GEOMETRY_KEY = "geometry"; - private static final String VERSIONINFO_KEY = "VERSIONINFO_KEY"; - - private AsynchClientTask createSelectDocTask(final TopLevelWindowManager requester) { - AsynchClientTask selectDocumentTypeTask = new AsynchClientTask("Select/Load geometry", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - String[][] docTypeoptions = new String[][] { { "BioModel names" }, { "MathModel names" } }; - VCDocumentType[] sourceDocumentTypes = new VCDocumentType[] { VCDocumentType.BIOMODEL_DOC, - VCDocumentType.MATHMODEL_DOC }; - VCAssert.assertTrue(docTypeoptions.length == sourceDocumentTypes.length, "Label and types mismatch"); - int[] geomType = DialogUtils.showComponentOKCancelTableList( - JOptionPane.getFrameForComponent(requester.getComponent()), "Select different Geometry", - new String[] { "Search by" }, docTypeoptions, ListSelectionModel.SINGLE_SELECTION); - final int selectedType = geomType[0]; - VCDocumentType sourceDocumentType = sourceDocumentTypes[selectedType]; - VersionInfo vcVersionInfo = null; - if (geomType[0] == 3) { - ImageDbTreePanel imageDbTreePanel = new ImageDbTreePanel(); - imageDbTreePanel.setDocumentManager(getDocumentManager()); - imageDbTreePanel.setPreferredSize(new java.awt.Dimension(200, 400)); - vcVersionInfo = DialogUtils.getDBTreePanelSelection(requester.getComponent(), imageDbTreePanel, - "OK", "Select Image:"); - } else { - if(hashTable.get(BioModelWindowManager.SELECT_GEOM_POPUP) != null && ((Boolean)hashTable.get(BioModelWindowManager.SELECT_GEOM_POPUP)).booleanValue()) { - if(getClientTaskStatusSupport() instanceof AsynchProgressPopup) { - ((AsynchProgressPopup)getClientTaskStatusSupport()).setVisible(false); - } - try { - Object obj = getMdiManager().getDatabaseWindowManager().selectDocument2(sourceDocumentType, - requester); - if (obj instanceof Geometry) {//user selected geometry directly using popup - hashTable.put(GEOMETRY_KEY, ((Geometry) obj)); - return; - } - vcVersionInfo = (VersionInfo) obj;//user selected VCDocument, list will be shown to select from - } finally { - if(getClientTaskStatusSupport() instanceof AsynchProgressPopup) { - ((AsynchProgressPopup)getClientTaskStatusSupport()).setVisible(true); - } - } - }else { - vcVersionInfo = selectDocumentFromType(sourceDocumentType, requester); - } - } - hashTable.put(VERSIONINFO_KEY, vcVersionInfo); - } - }; - return selectDocumentTypeTask; - } - - private AsynchClientTask createSelectLoadGeomTask(final TopLevelWindowManager requester) { - AsynchClientTask selectLoadGeomTask = new AsynchClientTask("Select/Load geometry...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - if(hashTable.get(GEOMETRY_KEY) != null) {//Already loaded from selection of BioModelDBTree from previous task - ((Geometry)hashTable.get(GEOMETRY_KEY)).precomputeAll(new GeometryThumbnailImageFactoryAWT()); - return; - } - VersionInfo vcVersionInfo = (VersionInfo) hashTable.get(VERSIONINFO_KEY); - Geometry geom = null; - if (vcVersionInfo instanceof VCDocumentInfo) { - geom = getGeometryFromDocumentSelection(requester.getComponent(), (VCDocumentInfo) vcVersionInfo, - false); - } else if (vcVersionInfo instanceof VCImageInfo) { - VCImage img = getDocumentManager().getImage((VCImageInfo) vcVersionInfo); - geom = new Geometry("createSelectLoadGeomTask", img); - } else { - throw new Exception("Unexpected versioninfo type."); - } - geom.precomputeAll(new GeometryThumbnailImageFactoryAWT());// pregenerate sampled image, cpu intensive - hashTable.put(GEOMETRY_KEY, geom); - } - }; - return selectLoadGeomTask; - } - - private void changeGeometry0(final TopLevelWindowManager requester, final SimulationContext simContext,Hashtable hashTable) { - - AsynchClientTask selectDocumentTypeTask = createSelectDocTask(requester); - - AsynchClientTask selectLoadGeomTask = createSelectLoadGeomTask(requester); - - AsynchClientTask processGeometryTask = new AsynchClientTask("Processing geometry...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry newGeometry = (Geometry) hashTable.get(GEOMETRY_KEY); - if (requester instanceof MathModelWindowManager) { - // User can cancel here - continueAfterMathModelGeomChangeWarning((MathModelWindowManager) requester, newGeometry); - } - if (newGeometry.getDimension() > 0 - && newGeometry.getGeometrySurfaceDescription().getGeometricRegions() == null) { - newGeometry.getGeometrySurfaceDescription().updateAll(); - } - } - }; - AsynchClientTask setNewGeometryTask = new AsynchClientTask("Setting new Geometry...", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry newGeometry = (Geometry) hashTable.get(GEOMETRY_KEY); - if (newGeometry != null) { - if (requester instanceof BioModelWindowManager) { - simContext.setGeometry(newGeometry); - } else if (requester instanceof MathModelWindowManager) { - MathModel mathModel = (MathModel) ((MathModelWindowManager) requester).getVCDocument(); - mathModel.getMathDescription().setGeometry(newGeometry); - } - } - } - }; - - ClientTaskDispatcher.dispatch(requester.getComponent(), hashTable, new AsynchClientTask[] { - selectDocumentTypeTask, selectLoadGeomTask, processGeometryTask, setNewGeometryTask }, false); - - } - - public void changeGeometry(DocumentWindowManager requester, SimulationContext simContext,Hashtable hashTable) { - changeGeometry0(requester, simContext,hashTable); - } - - public static void continueAfterMathModelGeomChangeWarning(MathModelWindowManager mathModelWindowManager, - Geometry newGeometry) throws UserCancelException { - - MathModel mathModel = mathModelWindowManager.getMathModel(); - if (mathModel != null && mathModel.getMathDescription() != null) { - Geometry oldGeometry = mathModel.getMathDescription().getGeometry(); - if (oldGeometry != null && oldGeometry.getDimension() == 0) { - return; - } - boolean bMeshResolutionChange = true; - if (oldGeometry == null) { - bMeshResolutionChange = false; - } - if (newGeometry != null && oldGeometry != null - && oldGeometry.getDimension() == newGeometry.getDimension()) { - bMeshResolutionChange = false; - } - boolean bHasSims = (mathModel.getSimulations() != null) && (mathModel.getSimulations().length > 0); - StringBuffer meshResolutionChangeSB = new StringBuffer(); - if (bHasSims && bMeshResolutionChange) { - ISize newGeomISize = MeshSpecification.calulateResetSamplingSize(newGeometry); - for (int i = 0; i < mathModel.getSimulations().length; i++) { - if (mathModel.getSimulations()[i].getMeshSpecification() != null) { - String simName = mathModel.getSimulations()[i].getName(); - ISize simMeshSize = mathModel.getSimulations()[i].getMeshSpecification().getSamplingSize(); - meshResolutionChangeSB.append((i != 0 ? "\n" : "") + "'" + simName + "' Mesh" + simMeshSize - + " will be reset to " + newGeomISize + ""); - } - } - } - - String result = DialogUtils.showWarningDialog( - JOptionPane.getFrameForComponent(mathModelWindowManager.getComponent()), - "After changing MathModel geometry please note:\n" - + " 1. Check Geometry subvolume names match MathModel compartment names." - + (bHasSims && bMeshResolutionChange ? "\n" - + " 2. All existing simulations mesh sizes will be reset" - + " because the new Geometry spatial dimension(" + newGeometry.getDimension() + "D)" - + " does not equal the current Geometry spatial dimension(" - + oldGeometry.getDimension() + "D)" + "\n" + meshResolutionChangeSB.toString() - : ""), - new String[] { "Continue", "Cancel" }, "Continue"); - if (result != null && result.equals("Continue")) { - return; - } - } else { - return; - } - - throw UserCancelException.CANCEL_GENERIC; - } - - enum CloseOption { - SAVE_AND_CLOSE, CLOSE_IN_ANY_CASE, CANCEL_CLOSE, - } - - public enum CallAction { - EXPORT, RUN, SAVE, SAVEASNEW, - } - - private CloseOption checkBeforeClosing(DocumentWindowManager windowManager) { - getMdiManager().showWindow(windowManager.getManagerID()); - // we need to check for changes and get user confirmation... - VCDocument vcDocument = windowManager.getVCDocument(); - if (vcDocument.getVersion() == null && !isDifferentFromBlank(vcDocument.getDocumentType(), vcDocument)) { - return CloseOption.CLOSE_IN_ANY_CASE; - } - boolean isChanged = true; - String IS_CHANGED_KEY = this.getClass().getName() + ".DocumentManager::isChanged"; - Hashtable hashtable = new Hashtable<>(); - try { - AsynchClientTask checkIfChanged = new AsynchClientTask( - "Checking if model has changed...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - boolean hasBeenChanged = ClientRequestManager.this.getDocumentManager().isChanged(vcDocument); + implements RequestManager, PropertyChangeListener, ExportListener, VCellMessageEventListener { + private VCellClient vcellClient = null; + + private boolean bOpening = false; + private boolean bExiting = false; + + private static final Logger lg = LogManager.getLogger(ClientRequestManager.class); + + public ClientRequestManager(VCellClient vcellClient) { + this.setVcellClient(vcellClient); + // listen to connectionStatus events + this.getClientServerManager().addPropertyChangeListener(this); + this.getClientServerManager().getAsynchMessageManager().addExportListener(this); + this.getClientServerManager().getAsynchMessageManager().addVCellMessageEventListener(this); + + } + + private static final String GEOMETRY_KEY = "geometry"; + private static final String VERSIONINFO_KEY = "VERSIONINFO_KEY"; + + private AsynchClientTask createSelectDocTask(final TopLevelWindowManager requester) { + AsynchClientTask selectDocumentTypeTask = new AsynchClientTask("Select/Load geometry", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + String[][] docTypeoptions = new String[][]{{"BioModel names"}, {"MathModel names"}}; + VCDocumentType[] sourceDocumentTypes = new VCDocumentType[]{VCDocumentType.BIOMODEL_DOC, + VCDocumentType.MATHMODEL_DOC}; + VCAssert.assertTrue(docTypeoptions.length == sourceDocumentTypes.length, "Label and types mismatch"); + int[] geomType = DialogUtils.showComponentOKCancelTableList( + JOptionPane.getFrameForComponent(requester.getComponent()), "Select different Geometry", + new String[]{"Search by"}, docTypeoptions, ListSelectionModel.SINGLE_SELECTION); + final int selectedType = geomType[0]; + VCDocumentType sourceDocumentType = sourceDocumentTypes[selectedType]; + VersionInfo vcVersionInfo = null; + if (geomType[0] == 3) { + ImageDbTreePanel imageDbTreePanel = new ImageDbTreePanel(); + imageDbTreePanel.setDocumentManager(ClientRequestManager.this.getDocumentManager()); + imageDbTreePanel.setPreferredSize(new java.awt.Dimension(200, 400)); + vcVersionInfo = DialogUtils.getDBTreePanelSelection(requester.getComponent(), imageDbTreePanel, + "OK", "Select Image:"); + } else { + if (hashTable.get(BioModelWindowManager.SELECT_GEOM_POPUP) != null && ((Boolean) hashTable.get(BioModelWindowManager.SELECT_GEOM_POPUP)).booleanValue()) { + if (this.getClientTaskStatusSupport() instanceof AsynchProgressPopup) { + ((AsynchProgressPopup) this.getClientTaskStatusSupport()).setVisible(false); + } + try { + Object obj = ClientRequestManager.this.getMdiManager().getDatabaseWindowManager().selectDocument2(sourceDocumentType, + requester); + if (obj instanceof Geometry) {//user selected geometry directly using popup + hashTable.put(GEOMETRY_KEY, obj); + return; + } + vcVersionInfo = (VersionInfo) obj;//user selected VCDocument, list will be shown to select from + } finally { + if (this.getClientTaskStatusSupport() instanceof AsynchProgressPopup) { + ((AsynchProgressPopup) this.getClientTaskStatusSupport()).setVisible(true); + } + } + } else { + vcVersionInfo = ClientRequestManager.this.selectDocumentFromType(sourceDocumentType, requester); + } + } + hashTable.put(VERSIONINFO_KEY, vcVersionInfo); + } + }; + return selectDocumentTypeTask; + } + + private AsynchClientTask createSelectLoadGeomTask(final TopLevelWindowManager requester) { + AsynchClientTask selectLoadGeomTask = new AsynchClientTask("Select/Load geometry...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + if (hashTable.get(GEOMETRY_KEY) != null) {//Already loaded from selection of BioModelDBTree from previous task + ((Geometry) hashTable.get(GEOMETRY_KEY)).precomputeAll(new GeometryThumbnailImageFactoryAWT()); + return; + } + VersionInfo vcVersionInfo = (VersionInfo) hashTable.get(VERSIONINFO_KEY); + Geometry geom = null; + if (vcVersionInfo instanceof VCDocumentInfo) { + geom = ClientRequestManager.this.getGeometryFromDocumentSelection(requester.getComponent(), (VCDocumentInfo) vcVersionInfo, + false); + } else if (vcVersionInfo instanceof VCImageInfo) { + VCImage img = ClientRequestManager.this.getDocumentManager().getImage((VCImageInfo) vcVersionInfo); + geom = new Geometry("createSelectLoadGeomTask", img); + } else { + throw new Exception("Unexpected versioninfo type."); + } + geom.precomputeAll(new GeometryThumbnailImageFactoryAWT());// pregenerate sampled image, cpu intensive + hashTable.put(GEOMETRY_KEY, geom); + } + }; + return selectLoadGeomTask; + } + + private void changeGeometry0(final TopLevelWindowManager requester, final SimulationContext simContext, Hashtable hashTable) { + + AsynchClientTask selectDocumentTypeTask = this.createSelectDocTask(requester); + + AsynchClientTask selectLoadGeomTask = this.createSelectLoadGeomTask(requester); + + AsynchClientTask processGeometryTask = new AsynchClientTask("Processing geometry...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry newGeometry = (Geometry) hashTable.get(GEOMETRY_KEY); + if (requester instanceof MathModelWindowManager) { + // User can cancel here + continueAfterMathModelGeomChangeWarning((MathModelWindowManager) requester, newGeometry); + } + if (newGeometry.getDimension() > 0 + && newGeometry.getGeometrySurfaceDescription().getGeometricRegions() == null) { + newGeometry.getGeometrySurfaceDescription().updateAll(); + } + } + }; + AsynchClientTask setNewGeometryTask = new AsynchClientTask("Setting new Geometry...", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry newGeometry = (Geometry) hashTable.get(GEOMETRY_KEY); + if (newGeometry != null) { + if (requester instanceof BioModelWindowManager) { + simContext.setGeometry(newGeometry); + } else if (requester instanceof MathModelWindowManager) { + MathModel mathModel = (MathModel) ((MathModelWindowManager) requester).getVCDocument(); + mathModel.getMathDescription().setGeometry(newGeometry); + } + } + } + }; + + ClientTaskDispatcher.dispatch(requester.getComponent(), hashTable, new AsynchClientTask[]{ + selectDocumentTypeTask, selectLoadGeomTask, processGeometryTask, setNewGeometryTask}, false); + + } + + public void changeGeometry(DocumentWindowManager requester, SimulationContext simContext, Hashtable hashTable) { + this.changeGeometry0(requester, simContext, hashTable); + } + + public static void continueAfterMathModelGeomChangeWarning(MathModelWindowManager mathModelWindowManager, + Geometry newGeometry) throws UserCancelException { + + MathModel mathModel = mathModelWindowManager.getMathModel(); + if (mathModel != null && mathModel.getMathDescription() != null) { + Geometry oldGeometry = mathModel.getMathDescription().getGeometry(); + if (oldGeometry != null && oldGeometry.getDimension() == 0) { + return; + } + boolean bMeshResolutionChange = oldGeometry != null; + if (newGeometry != null && oldGeometry != null + && oldGeometry.getDimension() == newGeometry.getDimension()) { + bMeshResolutionChange = false; + } + boolean bHasSims = (mathModel.getSimulations() != null) && (mathModel.getSimulations().length > 0); + StringBuffer meshResolutionChangeSB = new StringBuffer(); + if (bHasSims && bMeshResolutionChange) { + ISize newGeomISize = MeshSpecification.calulateResetSamplingSize(newGeometry); + for (int i = 0; i < mathModel.getSimulations().length; i++) { + if (mathModel.getSimulations()[i].getMeshSpecification() != null) { + String simName = mathModel.getSimulations()[i].getName(); + ISize simMeshSize = mathModel.getSimulations()[i].getMeshSpecification().getSamplingSize(); + meshResolutionChangeSB.append((i != 0 ? "\n" : "") + "'" + simName + "' Mesh" + simMeshSize + + " will be reset to " + newGeomISize); + } + } + } + + String result = DialogUtils.showWarningDialog( + JOptionPane.getFrameForComponent(mathModelWindowManager.getComponent()), + "After changing MathModel geometry please note:\n" + + " 1. Check Geometry subvolume names match MathModel compartment names." + + (bHasSims && bMeshResolutionChange ? "\n" + + " 2. All existing simulations mesh sizes will be reset" + + " because the new Geometry spatial dimension(" + newGeometry.getDimension() + "D)" + + " does not equal the current Geometry spatial dimension(" + + oldGeometry.getDimension() + "D)" + "\n" + meshResolutionChangeSB + : ""), + new String[]{"Continue", "Cancel"}, "Continue"); + if (result != null && result.equals("Continue")) { + return; + } + } else { + return; + } + + throw UserCancelException.CANCEL_GENERIC; + } + + enum CloseOption { + SAVE_AND_CLOSE, CLOSE_IN_ANY_CASE, CANCEL_CLOSE, + } + + public enum CallAction { + EXPORT, RUN, SAVE, SAVEASNEW, + } + + private CloseOption checkBeforeClosing(DocumentWindowManager windowManager) { + this.getMdiManager().showWindow(windowManager.getManagerID()); + // we need to check for changes and get user confirmation... + VCDocument vcDocument = windowManager.getVCDocument(); + if (vcDocument.getVersion() == null && !this.isDifferentFromBlank(vcDocument.getDocumentType(), vcDocument)) { + return CloseOption.CLOSE_IN_ANY_CASE; + } + boolean isChanged = true; + String IS_CHANGED_KEY = this.getClass().getName() + ".DocumentManager::isChanged"; + Hashtable hashtable = new Hashtable<>(); + try { + AsynchClientTask checkIfChanged = new AsynchClientTask( + "Checking if model has changed...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + boolean hasBeenChanged = ClientRequestManager.this.getDocumentManager().isChanged(vcDocument); hashTable.put(IS_CHANGED_KEY, hasBeenChanged); - } - }; - ClientTaskDispatcher.dispatchAndWait(null, hashtable, new AsynchClientTask[]{checkIfChanged}, - false, false, null, true); - if (hashtable.containsKey(IS_CHANGED_KEY)) - isChanged = (Boolean)hashtable.get(IS_CHANGED_KEY); - else if (hashtable.containsKey("clientTaskDispatcherStackTraceArray")){ - StringBuilder stackTrace = new StringBuilder(); - for (StackTraceElement elem : (StackTraceElement[]) hashtable.get("clientTaskDispatcherStackTraceArray")) - stackTrace.append(" \tat ").append(elem.toString()).append("\n"); + } + }; + ClientTaskDispatcher.dispatchAndWait(null, hashtable, new AsynchClientTask[]{checkIfChanged}, + false, false, null, true); + if (hashtable.containsKey(IS_CHANGED_KEY)) + isChanged = (Boolean) hashtable.get(IS_CHANGED_KEY); + else if (hashtable.containsKey("clientTaskDispatcherStackTraceArray")) { + StringBuilder stackTrace = new StringBuilder(); + for (StackTraceElement elem : (StackTraceElement[]) hashtable.get("clientTaskDispatcherStackTraceArray")) + stackTrace.append(" \tat ").append(elem.toString()).append("\n"); lg.error("Unknown error occurred during task 'Checking if model has changed'\n{}", stackTrace); - } - } catch (Exception exc) { - exc.printStackTrace(); - String choice = PopupGenerator.showWarningDialog(windowManager, getUserPreferences(), - UserMessage.warn_UnableToCheckForChanges, null); - if (choice.equals(UserMessage.OPTION_CANCEL)) { - // user canceled - return CloseOption.CANCEL_CLOSE; - } - } - // warn if necessary - if (isChanged) { - JDialog dialog = new JDialog(); - dialog.setAlwaysOnTop(true); - final String[] warnCloseArr = new String[] { UserMessage.OPTION_YES, "No", UserMessage.OPTION_CANCEL }; - int confirm = JOptionPane.showOptionDialog(dialog, UserMessage.warn_close.getMessage(null), - "Save warning...", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, warnCloseArr, - warnCloseArr[0]); + } + } catch (Exception exc) { + exc.printStackTrace(); + String choice = PopupGenerator.showWarningDialog(windowManager, this.getUserPreferences(), + UserMessage.warn_UnableToCheckForChanges, null); + if (choice.equals(UserMessage.OPTION_CANCEL)) { + // user canceled + return CloseOption.CANCEL_CLOSE; + } + } + // warn if necessary + if (isChanged) { + JDialog dialog = new JDialog(); + dialog.setAlwaysOnTop(true); + final String[] warnCloseArr = new String[]{UserMessage.OPTION_YES, "No", UserMessage.OPTION_CANCEL}; + int confirm = JOptionPane.showOptionDialog(dialog, UserMessage.warn_close.getMessage(null), + "Save warning...", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, warnCloseArr, + warnCloseArr[0]); // String choice = PopupGenerator.showWarningDialog(windowManager, getUserPreferences(), UserMessage.warn_close,null); - if (confirm != 0 && confirm != 1/* choice.equals(UserMessage.OPTION_CANCEL) */) { - // user canceled - return CloseOption.CANCEL_CLOSE; - } - if (confirm == 0/* choice.equals(UserMessage.OPTION_YES) */) { - return CloseOption.SAVE_AND_CLOSE; - } - } - // nothing changed, or user confirmed, close it - return CloseOption.CLOSE_IN_ANY_CASE; - } - - public boolean isDifferentFromBlank(VCDocumentType documentType, VCDocument vcDocument) { - // Handle Bio/Math models different from Geometry since createDefaultDoc for - // Geometry - // will bring up the NewGeometryEditor which is unnecessary. - // figure out if we come from a blank new document; if so, replace it inside - // same window - - if (documentType != vcDocument.getDocumentType()) { - // If the docType we are trying to open is not the same as the requesting - // windowmanager's docType - // we have to open the doc in a new window, hence return true; - return true; - } - VCDocument blank = null; - if (vcDocument.getDocumentType() != VCDocumentType.GEOMETRY_DOC) { - // BioModel/MathModel - blank = createDefaultDocument(vcDocument.getDocumentType()); - try { - blank.setName(vcDocument.getName()); - } catch (PropertyVetoException e) { - } // ignore. doesn't happen - return !blank.compareEqual(vcDocument); - } else { - // Geometry - blank = new Geometry(vcDocument.getName(), 1); - if (blank.compareEqual(vcDocument)) { - return false; - } - - blank = new Geometry(vcDocument.getName(), 2); - if (blank.compareEqual(vcDocument)) { - return false; - } - - blank = new Geometry(vcDocument.getName(), 3); - if (blank.compareEqual(vcDocument)) { - return false; - } - return true; - } - } - - @Override - public ClientServerInfo getClientServerInfo() { - return getVcellClient().getClientServerManager().getClientServerInfo(); - } - - private boolean closeAllWindows(boolean duringExit) { - // create copy to avoid ConcurrentModification exception caused by closing - // window - ArrayList modificationSafeCopy = new ArrayList<>(getMdiManager().getWindowManagers()); - for (TopLevelWindowManager windowManager : modificationSafeCopy) { - boolean closed = closeWindow(windowManager.getManagerID(), duringExit); - if (!closed) { - // user canceled, don't keep going... - return false; - } - } - return true; - } - - public boolean closeWindow(final java.lang.String windowID, final boolean exitIfLast) { - // called from DocumentWindow or from DatabaseWindow - final TopLevelWindowManager windowManager = getMdiManager().getWindowManager(windowID); - if (windowManager instanceof DocumentWindowManager) { - // we'll need to run some checks first - getMdiManager().showWindow(windowID); - getMdiManager().blockWindow(windowID); - CloseOption closeOption = checkBeforeClosing((DocumentWindowManager) windowManager); - if (closeOption.equals(CloseOption.CANCEL_CLOSE)) { - // user canceled - getMdiManager().unBlockWindow(windowID); - return false; - } else if (closeOption.equals(CloseOption.SAVE_AND_CLOSE)) { - AsynchClientTask closeTask = new AsynchClientTask("closing document", - AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { - - @Override - public void run(Hashtable hashTable) throws Exception { - // if there is error saving the document, try to unblock the window - if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { - getMdiManager().unBlockWindow(windowID); - getMdiManager().showWindow(windowID); - } else { - long openWindows = getMdiManager().closeWindow(windowManager.getManagerID()); - if (exitIfLast && (openWindows == 0)) { - setBExiting(true); - exitApplication(); - } - } - } - - @Override - public boolean skipIfCancel(UserCancelException exc) { - // if save as new edition, don't skip - if (exc == UserCancelException.CANCEL_DELETE_OLD - || exc == UserCancelException.CANCEL_NEW_NAME) { - return false; - } else { - return true; - } - } - }; - - if (((DocumentWindowManager) windowManager).getUser() == null - || User.isGuest(((DocumentWindowManager) windowManager).getUser().getName())) { - JDialog dialog = new JDialog(); - dialog.setAlwaysOnTop(true); - JOptionPane.showMessageDialog(dialog, User.createGuestErrorMessage("saveDocument"), "Error...", - JOptionPane.ERROR_MESSAGE, null); - return false; - } - - saveDocument((DocumentWindowManager) windowManager, true, closeTask); - return true; - } else { - long openWindows = getMdiManager().closeWindow(windowID); - if (exitIfLast && (openWindows == 0)) { - setBExiting(true); - exitApplication(); - } - return true; - } - } else if (windowManager instanceof DatabaseWindowManager) { - // nothing to check here, just close it - long openWindows = getMdiManager().closeWindow(windowID); - if (exitIfLast && (openWindows == 0)) { - setBExiting(true); - exitApplication(); - } - return true; - } else if (windowManager instanceof TestingFrameworkWindowManager) { - // nothing to check here, just close it - long openWindows = getMdiManager().closeWindow(windowID); - if (exitIfLast && (openWindows == 0)) { - setBExiting(true); - exitApplication(); - } - return true; - } else if (windowManager instanceof BNGWindowManager) { - // nothing to check here, just close it - long openWindows = getMdiManager().closeWindow(windowID); - if (exitIfLast && (openWindows == 0)) { - setBExiting(true); - exitApplication(); - } - return true; - } else if (windowManager instanceof FieldDataWindowManager) { - // nothing to check here, just close it - long openWindows = getMdiManager().closeWindow(windowID); - if (exitIfLast && (openWindows == 0)) { - setBExiting(true); - exitApplication(); - } - return true; - } else { - return false; - } - } - - private XmlTreeDiff compareDocuments(final VCDocument doc1, final VCDocument doc2, - DiffConfiguration comparisonSetting) throws Exception { - - VCellThreadChecker.checkCpuIntensiveInvocation(); - - if ((DiffConfiguration.COMPARE_DOCS_SAVED != comparisonSetting) - && (DiffConfiguration.COMPARE_DOCS_OTHER != comparisonSetting)) { - throw new RuntimeException("Unsupported comparison setting: " + comparisonSetting); - } - if (doc1.getDocumentType() != doc2.getDocumentType()) { - throw new RuntimeException("Only comparison of documents of the same type is currently supported"); - } - String doc1XML = null; - String doc2XML = null; - switch (doc1.getDocumentType()) { - case BIOMODEL_DOC: { - doc1XML = XmlHelper.bioModelToXML((BioModel) doc1); - doc2XML = XmlHelper.bioModelToXML((BioModel) doc2); - break; - } - case MATHMODEL_DOC: { - doc1XML = XmlHelper.mathModelToXML((MathModel) doc1); - doc2XML = XmlHelper.mathModelToXML((MathModel) doc2); - break; - } - case GEOMETRY_DOC: { - doc1XML = XmlHelper.geometryToXML((Geometry) doc1); - doc2XML = XmlHelper.geometryToXML((Geometry) doc2); - break; - } - } - final XmlTreeDiff diffTree = XmlHelper.compareMerge(doc1XML, doc2XML, comparisonSetting, true); - return diffTree; - } - - public XmlTreeDiff compareWithOther(final VCDocumentInfo docInfo1, final VCDocumentInfo docInfo2) { - - VCDocument document1, document2; - - try { - // get the VCDocument versions from documentManager - if (docInfo1 instanceof BioModelInfo && docInfo2 instanceof BioModelInfo) { - document1 = getDocumentManager().getBioModel((BioModelInfo) docInfo1); - document2 = getDocumentManager().getBioModel((BioModelInfo) docInfo2); - } else if (docInfo1 instanceof MathModelInfo && docInfo2 instanceof MathModelInfo) { - document1 = getDocumentManager().getMathModel((MathModelInfo) docInfo1); - document2 = getDocumentManager().getMathModel((MathModelInfo) docInfo2); - } else if (docInfo1 instanceof GeometryInfo && docInfo2 instanceof GeometryInfo) { - document1 = getDocumentManager().getGeometry((GeometryInfo) docInfo1); - document2 = getDocumentManager().getGeometry((GeometryInfo) docInfo2); - } else { - throw new IllegalArgumentException("The two documents are invalid or of different types."); - } - return compareDocuments(document1, document2, DiffConfiguration.COMPARE_DOCS_OTHER); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - } - - public XmlTreeDiff compareWithSaved(VCDocument document) { - - VCDocument savedVersion = null; - try { - if (document == null) { - throw new IllegalArgumentException("Invalid VC document: " + document); - } - // make the info and get saved version - switch (document.getDocumentType()) { - case BIOMODEL_DOC: { - BioModel bioModel = (BioModel) document; - savedVersion = getDocumentManager().getBioModel(bioModel.getVersion().getVersionKey()); - break; - } - case MATHMODEL_DOC: { - MathModel mathModel = (MathModel) document; - savedVersion = getDocumentManager().getMathModel(mathModel.getVersion().getVersionKey()); - break; - } - case GEOMETRY_DOC: { - Geometry geometry = (Geometry) document; - savedVersion = getDocumentManager().getGeometry(geometry.getKey()); - break; - } - } - return compareDocuments(savedVersion, document, DiffConfiguration.COMPARE_DOCS_SAVED); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - } - - public XmlTreeDiff compareApplications(BioModel bioModel, String appName1, String appName2) throws Exception { - - // clone BioModel as bioModel1 and remove all but appName1 - BioModel bioModel1 = (BioModel) BeanUtils.cloneSerializable(bioModel); - bioModel1.refreshDependencies(); - SimulationContext[] allSimContexts1 = bioModel1.getSimulationContexts(); - for (SimulationContext sc : allSimContexts1) { - if (!sc.getName().equals(appName1)) { - bioModel1.removeSimulationContext(sc); - } - } - - // clone BioModel as bioModel2 and remove all but appName2 - BioModel bioModel2 = (BioModel) BeanUtils.cloneSerializable(bioModel); - bioModel2.refreshDependencies(); - SimulationContext[] allSimContexts2 = bioModel2.getSimulationContexts(); - for (SimulationContext sc : allSimContexts2) { - if (!sc.getName().equals(appName2)) { - bioModel2.removeSimulationContext(sc); - } - } - - return compareDocuments(bioModel1, bioModel2, DiffConfiguration.COMPARE_DOCS_SAVED); - } - - public void connectToServer(TopLevelWindowManager requester, ClientServerInfo clientServerInfo) throws Exception { - getClientServerManager().connectNewServer(new VCellGuiInteractiveContext(requester), clientServerInfo); - } - - - public void logOut(final TopLevelWindowManager requester){ - JDialog dialog = new JDialog(); - dialog.setAlwaysOnTop(true); - StringBuilder dialogMessage = new StringBuilder(); - dialogMessage.append("You are about to log out of the VCell client.\n\n"); - if (requester instanceof DocumentWindowManager documentWindowManager){ - if(!User.isGuest(documentWindowManager.getUser().getName())){ - dialogMessage.append(""" + if (confirm != 0 && confirm != 1/* choice.equals(UserMessage.OPTION_CANCEL) */) { + // user canceled + return CloseOption.CANCEL_CLOSE; + } + if (confirm == 0/* choice.equals(UserMessage.OPTION_YES) */) { + return CloseOption.SAVE_AND_CLOSE; + } + } + // nothing changed, or user confirmed, close it + return CloseOption.CLOSE_IN_ANY_CASE; + } + + public boolean isDifferentFromBlank(VCDocumentType documentType, VCDocument vcDocument) { + // Handle Bio/Math models different from Geometry since createDefaultDoc for + // Geometry + // will bring up the NewGeometryEditor which is unnecessary. + // figure out if we come from a blank new document; if so, replace it inside + // same window + + if (documentType != vcDocument.getDocumentType()) { + // If the docType we are trying to open is not the same as the requesting + // windowmanager's docType + // we have to open the doc in a new window, hence return true; + return true; + } + VCDocument blank = null; + if (vcDocument.getDocumentType() != VCDocumentType.GEOMETRY_DOC) { + // BioModel/MathModel + blank = this.createDefaultDocument(vcDocument.getDocumentType()); + try { + blank.setName(vcDocument.getName()); + } catch (PropertyVetoException e) { + } // ignore. doesn't happen + return !blank.compareEqual(vcDocument); + } else { + // Geometry + blank = new Geometry(vcDocument.getName(), 1); + if (blank.compareEqual(vcDocument)) { + return false; + } + + blank = new Geometry(vcDocument.getName(), 2); + if (blank.compareEqual(vcDocument)) { + return false; + } + + blank = new Geometry(vcDocument.getName(), 3); + return !blank.compareEqual(vcDocument); + } + } + + @Override + public ClientServerInfo getClientServerInfo() { + return this.getVcellClient().getClientServerManager().getClientServerInfo(); + } + + private boolean closeAllWindows(boolean duringExit) { + // create copy to avoid ConcurrentModification exception caused by closing + // window + ArrayList modificationSafeCopy = new ArrayList<>(this.getMdiManager().getWindowManagers()); + for (TopLevelWindowManager windowManager : modificationSafeCopy) { + boolean closed = this.closeWindow(windowManager.getManagerID(), duringExit); + if (!closed) { + // user canceled, don't keep going... + return false; + } + } + return true; + } + + public boolean closeWindow(final java.lang.String windowID, final boolean exitIfLast) { + // called from DocumentWindow or from DatabaseWindow + final TopLevelWindowManager windowManager = this.getMdiManager().getWindowManager(windowID); + if (windowManager instanceof DocumentWindowManager) { + // we'll need to run some checks first + this.getMdiManager().showWindow(windowID); + this.getMdiManager().blockWindow(windowID); + CloseOption closeOption = this.checkBeforeClosing((DocumentWindowManager) windowManager); + if (closeOption.equals(CloseOption.CANCEL_CLOSE)) { + // user canceled + this.getMdiManager().unBlockWindow(windowID); + return false; + } else if (closeOption.equals(CloseOption.SAVE_AND_CLOSE)) { + AsynchClientTask closeTask = new AsynchClientTask("closing document", + AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false) { + + @Override + public void run(Hashtable hashTable) throws Exception { + // if there is error saving the document, try to unblock the window + if (hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()) != null) { + ClientRequestManager.this.getMdiManager().unBlockWindow(windowID); + ClientRequestManager.this.getMdiManager().showWindow(windowID); + } else { + long openWindows = ClientRequestManager.this.getMdiManager().closeWindow(windowManager.getManagerID()); + if (exitIfLast && (openWindows == 0)) { + ClientRequestManager.this.setBExiting(true); + ClientRequestManager.this.exitApplication(); + } + } + } + + @Override + public boolean skipIfCancel(UserCancelException exc) { + // if save as new edition, don't skip + return exc != UserCancelException.CANCEL_DELETE_OLD + && exc != UserCancelException.CANCEL_NEW_NAME; + } + }; + + if (((DocumentWindowManager) windowManager).getUser() == null + || User.isGuest(((DocumentWindowManager) windowManager).getUser().getName())) { + JDialog dialog = new JDialog(); + dialog.setAlwaysOnTop(true); + JOptionPane.showMessageDialog(dialog, User.createGuestErrorMessage("saveDocument"), "Error...", + JOptionPane.ERROR_MESSAGE, null); + return false; + } + + this.saveDocument((DocumentWindowManager) windowManager, true, closeTask); + return true; + } else { + long openWindows = this.getMdiManager().closeWindow(windowID); + if (exitIfLast && (openWindows == 0)) { + this.setBExiting(true); + this.exitApplication(); + } + return true; + } + } else if (windowManager instanceof DatabaseWindowManager) { + // nothing to check here, just close it + long openWindows = this.getMdiManager().closeWindow(windowID); + if (exitIfLast && (openWindows == 0)) { + this.setBExiting(true); + this.exitApplication(); + } + return true; + } else if (windowManager instanceof TestingFrameworkWindowManager) { + // nothing to check here, just close it + long openWindows = this.getMdiManager().closeWindow(windowID); + if (exitIfLast && (openWindows == 0)) { + this.setBExiting(true); + this.exitApplication(); + } + return true; + } else if (windowManager instanceof BNGWindowManager) { + // nothing to check here, just close it + long openWindows = this.getMdiManager().closeWindow(windowID); + if (exitIfLast && (openWindows == 0)) { + this.setBExiting(true); + this.exitApplication(); + } + return true; + } else if (windowManager instanceof FieldDataWindowManager) { + // nothing to check here, just close it + long openWindows = this.getMdiManager().closeWindow(windowID); + if (exitIfLast && (openWindows == 0)) { + this.setBExiting(true); + this.exitApplication(); + } + return true; + } else { + return false; + } + } + + private XmlTreeDiff compareDocuments(final VCDocument doc1, final VCDocument doc2, + DiffConfiguration comparisonSetting) throws Exception { + + VCellThreadChecker.checkCpuIntensiveInvocation(); + + if ((DiffConfiguration.COMPARE_DOCS_SAVED != comparisonSetting) + && (DiffConfiguration.COMPARE_DOCS_OTHER != comparisonSetting)) { + throw new RuntimeException("Unsupported comparison setting: " + comparisonSetting); + } + if (doc1.getDocumentType() != doc2.getDocumentType()) { + throw new RuntimeException("Only comparison of documents of the same type is currently supported"); + } + String doc1XML = null; + String doc2XML = null; + switch (doc1.getDocumentType()) { + case BIOMODEL_DOC: { + doc1XML = XmlHelper.bioModelToXML((BioModel) doc1); + doc2XML = XmlHelper.bioModelToXML((BioModel) doc2); + break; + } + case MATHMODEL_DOC: { + doc1XML = XmlHelper.mathModelToXML((MathModel) doc1); + doc2XML = XmlHelper.mathModelToXML((MathModel) doc2); + break; + } + case GEOMETRY_DOC: { + doc1XML = XmlHelper.geometryToXML((Geometry) doc1); + doc2XML = XmlHelper.geometryToXML((Geometry) doc2); + break; + } + } + final XmlTreeDiff diffTree = XmlHelper.compareMerge(doc1XML, doc2XML, comparisonSetting, true); + return diffTree; + } + + public XmlTreeDiff compareWithOther(final VCDocumentInfo docInfo1, final VCDocumentInfo docInfo2) { + + VCDocument document1, document2; + + try { + // get the VCDocument versions from documentManager + if (docInfo1 instanceof BioModelInfo && docInfo2 instanceof BioModelInfo) { + document1 = this.getDocumentManager().getBioModel((BioModelInfo) docInfo1); + document2 = this.getDocumentManager().getBioModel((BioModelInfo) docInfo2); + } else if (docInfo1 instanceof MathModelInfo && docInfo2 instanceof MathModelInfo) { + document1 = this.getDocumentManager().getMathModel((MathModelInfo) docInfo1); + document2 = this.getDocumentManager().getMathModel((MathModelInfo) docInfo2); + } else if (docInfo1 instanceof GeometryInfo && docInfo2 instanceof GeometryInfo) { + document1 = this.getDocumentManager().getGeometry((GeometryInfo) docInfo1); + document2 = this.getDocumentManager().getGeometry((GeometryInfo) docInfo2); + } else { + throw new IllegalArgumentException("The two documents are invalid or of different types."); + } + return this.compareDocuments(document1, document2, DiffConfiguration.COMPARE_DOCS_OTHER); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + public XmlTreeDiff compareWithSaved(VCDocument document) { + + VCDocument savedVersion = null; + try { + if (document == null) { + throw new IllegalArgumentException("Invalid VC document: " + document); + } + // make the info and get saved version + switch (document.getDocumentType()) { + case BIOMODEL_DOC: { + BioModel bioModel = (BioModel) document; + savedVersion = this.getDocumentManager().getBioModel(bioModel.getVersion().getVersionKey()); + break; + } + case MATHMODEL_DOC: { + MathModel mathModel = (MathModel) document; + savedVersion = this.getDocumentManager().getMathModel(mathModel.getVersion().getVersionKey()); + break; + } + case GEOMETRY_DOC: { + Geometry geometry = (Geometry) document; + savedVersion = this.getDocumentManager().getGeometry(geometry.getKey()); + break; + } + } + return this.compareDocuments(savedVersion, document, DiffConfiguration.COMPARE_DOCS_SAVED); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + public XmlTreeDiff compareApplications(BioModel bioModel, String appName1, String appName2) throws Exception { + + // clone BioModel as bioModel1 and remove all but appName1 + BioModel bioModel1 = (BioModel) BeanUtils.cloneSerializable(bioModel); + bioModel1.refreshDependencies(); + SimulationContext[] allSimContexts1 = bioModel1.getSimulationContexts(); + for (SimulationContext sc : allSimContexts1) { + if (!sc.getName().equals(appName1)) { + bioModel1.removeSimulationContext(sc); + } + } + + // clone BioModel as bioModel2 and remove all but appName2 + BioModel bioModel2 = (BioModel) BeanUtils.cloneSerializable(bioModel); + bioModel2.refreshDependencies(); + SimulationContext[] allSimContexts2 = bioModel2.getSimulationContexts(); + for (SimulationContext sc : allSimContexts2) { + if (!sc.getName().equals(appName2)) { + bioModel2.removeSimulationContext(sc); + } + } + + return this.compareDocuments(bioModel1, bioModel2, DiffConfiguration.COMPARE_DOCS_SAVED); + } + + public void connectToServer(TopLevelWindowManager requester, ClientServerInfo clientServerInfo) throws Exception { + this.getClientServerManager().connectNewServer(new VCellGuiInteractiveContext(requester), clientServerInfo); + } + + + public void logOut(final TopLevelWindowManager requester) { + JDialog dialog = new JDialog(); + dialog.setAlwaysOnTop(true); + StringBuilder dialogMessage = new StringBuilder(); + dialogMessage.append("You are about to log out of the VCell client.\n\n"); + if (requester instanceof DocumentWindowManager documentWindowManager) { + if (!User.isGuest(documentWindowManager.getUser().getName())) { + dialogMessage.append(""" Because VCell uses a browser-based login, you'll be redirected to a logout page to complete the logout process there. - + """); - } - } - dialogMessage.append("Do you wish to continue?"); - - int confirm = JOptionPane.showOptionDialog(dialog, dialogMessage.toString(), - "Logout", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, - new String[] { "Continue", "Cancel" }, "Continue"); - if (confirm == JOptionPane.OK_OPTION) { - closeAllWindows(false); - getClientServerManager().cleanup(); //set VCell connection to null - getClientServerManager().getAsynchMessageManager().stopPolling(); - - Hashtable hash = new Hashtable(); - - Auth0ConnectionUtils auth0ConnectionUtils = getClientServerManager().getAuth0ConnectionUtils(); - if (!getClientServerInfo().getUsername().equals(User.VCELL_GUEST_NAME)){ - auth0ConnectionUtils.logOut(); - } - Auth0ConnectionUtils.setShowLoginPopUp(true); - - AsynchClientTask waitTask = new AsynchClientTask("wait for window closing", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - // wait until all windows are closed. - long startTime = System.currentTimeMillis(); - while (true) { - long numOpenWindows = getMdiManager().closeWindow(ClientMDIManager.DATABASE_WINDOW_ID); - if (numOpenWindows == 0) { - break; - } - // if can't save all the documents, don't connect as thus throw exception. - if (System.currentTimeMillis() - startTime > 60000) { - throw UserCancelException.CANCEL_GENERIC; - } - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - }; - - - AsynchClientTask[] newTasks = newDocument(requester, - new VCDocument.DocumentCreationInfo(VCDocumentType.BIOMODEL_DOC, 0)); - AsynchClientTask task0 = new AsynchClientTask("preparing", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get("windowManager"); - if (windowManager != null) { - Frame frameParent = JOptionPane.getFrameForComponent(windowManager.getComponent()); - ClientMDIManager.blockWindow(frameParent); - frameParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - } - } - }; - - AsynchClientTask task1 = ClientLogin.popupLogin(); - AsynchClientTask task2 = ClientLogin.loginWithAuth0(auth0ConnectionUtils); - AsynchClientTask task3 = ClientLogin.connectToServer(auth0ConnectionUtils, getClientServerInfo()); - - AsynchClientTask refresh = new AsynchClientTask("Refresh", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, - false) { - @Override - public void run(Hashtable hashTable) throws Exception { - getMdiManager().refreshRecyclableWindows(); - DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get("windowManager"); - if (windowManager != null) { - Frame frameParent = JOptionPane.getFrameForComponent(windowManager.getComponent()); - ClientMDIManager.unBlockWindow(frameParent); - frameParent.setCursor(Cursor.getDefaultCursor()); - } - } - }; + } + } + dialogMessage.append("Do you wish to continue?"); + + int confirm = JOptionPane.showOptionDialog(dialog, dialogMessage.toString(), + "Logout", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, + new String[]{"Continue", "Cancel"}, "Continue"); + if (confirm == JOptionPane.OK_OPTION) { + this.closeAllWindows(false); + this.getClientServerManager().cleanup(); //set VCell connection to null + this.getClientServerManager().getAsynchMessageManager().stopPolling(); + + Hashtable hash = new Hashtable(); + + Auth0ConnectionUtils auth0ConnectionUtils = this.getClientServerManager().getAuth0ConnectionUtils(); + if (!this.getClientServerInfo().getUsername().equals(User.VCELL_GUEST_NAME)) { + auth0ConnectionUtils.logOut(); + } + Auth0ConnectionUtils.setShowLoginPopUp(true); + + AsynchClientTask waitTask = new AsynchClientTask("wait for window closing", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + // wait until all windows are closed. + long startTime = System.currentTimeMillis(); + while (true) { + long numOpenWindows = ClientRequestManager.this.getMdiManager().closeWindow(ClientMDIManager.DATABASE_WINDOW_ID); + if (numOpenWindows == 0) { + break; + } + // if can't save all the documents, don't connect as thus throw exception. + if (System.currentTimeMillis() - startTime > 60000) { + throw UserCancelException.CANCEL_GENERIC; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }; + + + AsynchClientTask[] newTasks = this.newDocument(requester, + new VCDocument.DocumentCreationInfo(VCDocumentType.BIOMODEL_DOC, 0)); + AsynchClientTask task0 = new AsynchClientTask("preparing", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get("windowManager"); + if (windowManager != null) { + Frame frameParent = JOptionPane.getFrameForComponent(windowManager.getComponent()); + ClientMDIManager.blockWindow(frameParent); + frameParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + } + } + }; + + AsynchClientTask task1 = ClientLogin.popupLogin(); + AsynchClientTask task2 = ClientLogin.loginWithAuth0(auth0ConnectionUtils); + AsynchClientTask task3 = ClientLogin.connectToServer(auth0ConnectionUtils, this.getClientServerInfo()); + + AsynchClientTask refresh = new AsynchClientTask("Refresh", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, + false) { + @Override + public void run(Hashtable hashTable) throws Exception { + ClientRequestManager.this.getMdiManager().refreshRecyclableWindows(); + DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get("windowManager"); + if (windowManager != null) { + Frame frameParent = JOptionPane.getFrameForComponent(windowManager.getComponent()); + ClientMDIManager.unBlockWindow(frameParent); + frameParent.setCursor(Cursor.getDefaultCursor()); + } + } + }; ArrayList tasks = new ArrayList<>(Arrays.stream(newTasks).toList()); - tasks.add(0, waitTask); - tasks.add(task0); - tasks.add(task1); - tasks.add(task2); - tasks.add(task3); - tasks.add(refresh); - - ClientTaskDispatcher.dispatch(null, hash, tasks.toArray(new AsynchClientTask[0])); - } - } - - VCDocument createDefaultDocument(VCDocumentType docType) { - VCDocument defaultDocument = null; - try { - switch (docType) { - case BIOMODEL_DOC: { - // blank - return createDefaultBioModelDocument(null); - } - case MATHMODEL_DOC: { - return createDefaultMathModelDocument(); - } - default: { - throw new RuntimeException("default document can only be BioModel or MathModel"); - } - } - } catch (Exception e) { - e.printStackTrace(System.out); - } - return defaultDocument; - } - - private MathModel createMathModel(String name, Geometry geometry) { - MathModel mathModel = new MathModel(null); - MathDescription mathDesc = mathModel.getMathDescription(); - try { - mathDesc.setGeometry(geometry); - if (geometry.getDimension() == 0) { - mathDesc.addSubDomain( - new CompartmentSubDomain("Compartment", CompartmentSubDomain.NON_SPATIAL_PRIORITY)); - } else { - try { - if (geometry.getDimension() > 0 - && geometry.getGeometrySurfaceDescription().getGeometricRegions() == null) { - geometry.getGeometrySurfaceDescription().updateAll(); - } - } catch (ImageException e) { - e.printStackTrace(System.out); - throw new RuntimeException("Geometric surface generation error: \n" + e.getMessage()); - } catch (GeometryException e) { - e.printStackTrace(System.out); - throw new RuntimeException("Geometric surface generation error: \n" + e.getMessage()); - } - - SubVolume subVolumes[] = geometry.getGeometrySpec().getSubVolumes(); - for (int i = 0; i < subVolumes.length; i++) { - mathDesc.addSubDomain(new CompartmentSubDomain(subVolumes[i].getName(), subVolumes[i].getHandle())); - } - // - // add only those MembraneSubDomains corresponding to surfaces that acutally - // exist in geometry. - // - GeometricRegion regions[] = geometry.getGeometrySurfaceDescription().getGeometricRegions(); - for (int i = 0; i < regions.length; i++) { - if (regions[i] instanceof SurfaceGeometricRegion) { - SurfaceGeometricRegion surfaceRegion = (SurfaceGeometricRegion) regions[i]; - SubVolume subVolume1 = ((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[0]) - .getSubVolume(); - SubVolume subVolume2 = ((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[1]) - .getSubVolume(); - CompartmentSubDomain compartment1 = mathDesc.getCompartmentSubDomain(subVolume1.getName()); - CompartmentSubDomain compartment2 = mathDesc.getCompartmentSubDomain(subVolume2.getName()); - MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compartment1, compartment2); - if (membraneSubDomain == null) { - SurfaceClass surfaceClass = geometry.getGeometrySurfaceDescription() - .getSurfaceClass(subVolume1, subVolume2); - membraneSubDomain = new MembraneSubDomain(compartment1, compartment2, - surfaceClass.getName()); - mathDesc.addSubDomain(membraneSubDomain); - } - } - } - } - mathDesc.isValid(); - mathModel.setName(name); - } catch (Exception e) { - e.printStackTrace(System.out); - } - return mathModel; - } - - public void createMathModelFromApplication(final BioModelWindowManager requester, final String name, - final SimulationContext simContext) { - if (simContext == null) { - PopupGenerator.showErrorDialog(requester, - "Selected Application is null, cannot generate corresponding math model"); - return; - } - - switch (simContext.getApplicationType()) { - case NETWORK_STOCHASTIC: - break; - case RULE_BASED_STOCHASTIC: - case NETWORK_DETERMINISTIC: - } - - AsynchClientTask task1 = new AsynchClientTask("Creating MathModel from BioModel Application", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - MathModel newMathModel = new MathModel(null); - // Get corresponding mathDesc to create new mathModel. - MathDescription mathDesc = simContext.getMathDescription(); - MathDescription newMathDesc = null; - newMathDesc = new MathDescription(name + "_" + (new java.util.Random()).nextInt()); - try { - if (mathDesc.getGeometry().getDimension() > 0 - && mathDesc.getGeometry().getGeometrySurfaceDescription().getGeometricRegions() == null) { - mathDesc.getGeometry().getGeometrySurfaceDescription().updateAll(); - } - - } catch (ImageException e) { - e.printStackTrace(System.out); - throw new RuntimeException("Geometric surface generation error:\n" + e.getMessage()); - } catch (GeometryException e) { - e.printStackTrace(System.out); - throw new RuntimeException("Geometric surface generation error:\n" + e.getMessage()); - } - newMathDesc.setGeometry(mathDesc.getGeometry()); - newMathDesc.read_database(new CommentStringTokenizer(mathDesc.getVCML_database())); - newMathDesc.isValid(); - - newMathModel.setName(name); - newMathModel.setMathDescription(newMathDesc); - hashTable.put("newMathModel", newMathModel); - } - }; - - AsynchClientTask task2 = new AsynchClientTask("Creating MathModel from BioModel Application", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - MathModel newMathModel = (MathModel) hashTable.get("newMathModel"); - DocumentWindowManager windowManager = createDocumentWindowManager(newMathModel); - if (simContext.getBioModel().getVersion() != null) { - ((MathModelWindowManager) windowManager).setCopyFromBioModelAppVersionableTypeVersion( - new VersionableTypeVersion(VersionableType.BioModelMetaData, - simContext.getBioModel().getVersion())); - } - DocumentWindow dw = getMdiManager().createNewDocumentWindow(windowManager); - setFinalWindow(hashTable, dw); - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), - new AsynchClientTask[] { task1, task2 }, false); - } - - public void createBioModelFromApplication(final BioModelWindowManager requester, final String name, - final SimulationContext simContext) { - if (simContext == null) { - PopupGenerator.showErrorDialog(requester, - "Selected Application is null, cannot generate corresponding bio model"); - return; - } - if (simContext.isRuleBased()) { - createRuleBasedBioModelFromApplication(requester, name, simContext); - return; - } - AsynchClientTask task1 = new AsynchClientTask("Creating BioModel from BioModel Application", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - - MathMapping transformedMathMapping = simContext.createNewMathMapping(); - - BioModel newBioModel = new BioModel(null); - SimulationContext transformedSimContext = transformedMathMapping - .getTransformation().transformedSimContext; - Model newModel = transformedSimContext.getModel(); - newBioModel.setModel(newModel); - - RbmModelContainer rbmmc = newModel.getRbmModelContainer(); - for (RbmObservable o : rbmmc.getObservableList()) { - rbmmc.removeObservable(o); - } - for (ReactionRule r : rbmmc.getReactionRuleList()) { - rbmmc.removeReactionRule(r); - } - for (ReactionStep rs : newModel.getReactionSteps()) { - String oldName = rs.getName(); - if (oldName.startsWith("_reverse_")) { - String newName = newModel.getReactionName("rev", oldName.substring("_reverse_".length())); - rs.setName(newName); - } - } - - hashTable.put("newBioModel", newBioModel); - } - }; - AsynchClientTask task2 = new AsynchClientTask("Creating BioModel from BioModel Application", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - BioModel newBioModel = (BioModel) hashTable.get("newBioModel"); - DocumentWindowManager windowManager = createDocumentWindowManager(newBioModel); + tasks.add(0, waitTask); + tasks.add(task0); + tasks.add(task1); + tasks.add(task2); + tasks.add(task3); + tasks.add(refresh); + + ClientTaskDispatcher.dispatch(null, hash, tasks.toArray(new AsynchClientTask[0])); + } + } + + VCDocument createDefaultDocument(VCDocumentType docType) { + VCDocument defaultDocument = null; + try { + switch (docType) { + case BIOMODEL_DOC: { + // blank + return this.createDefaultBioModelDocument(null); + } + case MATHMODEL_DOC: { + return this.createDefaultMathModelDocument(); + } + default: { + throw new RuntimeException("default document can only be BioModel or MathModel"); + } + } + } catch (Exception e) { + e.printStackTrace(System.out); + } + return defaultDocument; + } + + private MathModel createMathModel(String name, Geometry geometry) { + MathModel mathModel = new MathModel(null); + MathDescription mathDesc = mathModel.getMathDescription(); + try { + mathDesc.setGeometry(geometry); + if (geometry.getDimension() == 0) { + mathDesc.addSubDomain( + new CompartmentSubDomain("Compartment", CompartmentSubDomain.NON_SPATIAL_PRIORITY)); + } else { + try { + if (geometry.getDimension() > 0 + && geometry.getGeometrySurfaceDescription().getGeometricRegions() == null) { + geometry.getGeometrySurfaceDescription().updateAll(); + } + } catch (ImageException e) { + e.printStackTrace(System.out); + throw new RuntimeException("Geometric surface generation error: \n" + e.getMessage()); + } catch (GeometryException e) { + e.printStackTrace(System.out); + throw new RuntimeException("Geometric surface generation error: \n" + e.getMessage()); + } + + SubVolume[] subVolumes = geometry.getGeometrySpec().getSubVolumes(); + for (int i = 0; i < subVolumes.length; i++) { + mathDesc.addSubDomain(new CompartmentSubDomain(subVolumes[i].getName(), subVolumes[i].getHandle())); + } + // + // add only those MembraneSubDomains corresponding to surfaces that acutally + // exist in geometry. + // + GeometricRegion[] regions = geometry.getGeometrySurfaceDescription().getGeometricRegions(); + for (int i = 0; i < regions.length; i++) { + if (regions[i] instanceof SurfaceGeometricRegion surfaceRegion) { + SubVolume subVolume1 = ((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[0]) + .getSubVolume(); + SubVolume subVolume2 = ((VolumeGeometricRegion) surfaceRegion.getAdjacentGeometricRegions()[1]) + .getSubVolume(); + CompartmentSubDomain compartment1 = mathDesc.getCompartmentSubDomain(subVolume1.getName()); + CompartmentSubDomain compartment2 = mathDesc.getCompartmentSubDomain(subVolume2.getName()); + MembraneSubDomain membraneSubDomain = mathDesc.getMembraneSubDomain(compartment1, compartment2); + if (membraneSubDomain == null) { + SurfaceClass surfaceClass = geometry.getGeometrySurfaceDescription() + .getSurfaceClass(subVolume1, subVolume2); + membraneSubDomain = new MembraneSubDomain(compartment1, compartment2, + surfaceClass.getName()); + mathDesc.addSubDomain(membraneSubDomain); + } + } + } + } + mathDesc.isValid(); + mathModel.setName(name); + } catch (Exception e) { + e.printStackTrace(System.out); + } + return mathModel; + } + + public void createMathModelFromApplication(final BioModelWindowManager requester, final String name, + final SimulationContext simContext) { + if (simContext == null) { + PopupGenerator.showErrorDialog(requester, + "Selected Application is null, cannot generate corresponding math model"); + return; + } + + switch (simContext.getApplicationType()) { + case NETWORK_STOCHASTIC: + break; + case RULE_BASED_STOCHASTIC: + case NETWORK_DETERMINISTIC: + } + + AsynchClientTask task1 = new AsynchClientTask("Creating MathModel from BioModel Application", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + MathModel newMathModel = new MathModel(null); + // Get corresponding mathDesc to create new mathModel. + MathDescription mathDesc = simContext.getMathDescription(); + MathDescription newMathDesc = null; + newMathDesc = new MathDescription(name + "_" + (new java.util.Random()).nextInt()); + try { + if (mathDesc.getGeometry().getDimension() > 0 + && mathDesc.getGeometry().getGeometrySurfaceDescription().getGeometricRegions() == null) { + mathDesc.getGeometry().getGeometrySurfaceDescription().updateAll(); + } + + } catch (ImageException e) { + e.printStackTrace(System.out); + throw new RuntimeException("Geometric surface generation error:\n" + e.getMessage()); + } catch (GeometryException e) { + e.printStackTrace(System.out); + throw new RuntimeException("Geometric surface generation error:\n" + e.getMessage()); + } + newMathDesc.setGeometry(mathDesc.getGeometry()); + newMathDesc.read_database(new CommentStringTokenizer(mathDesc.getVCML_database())); + newMathDesc.isValid(); + + newMathModel.setName(name); + newMathModel.setMathDescription(newMathDesc); + hashTable.put("newMathModel", newMathModel); + } + }; + + AsynchClientTask task2 = new AsynchClientTask("Creating MathModel from BioModel Application", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + MathModel newMathModel = (MathModel) hashTable.get("newMathModel"); + DocumentWindowManager windowManager = ClientRequestManager.this.createDocumentWindowManager(newMathModel); + if (simContext.getBioModel().getVersion() != null) { + ((MathModelWindowManager) windowManager).setCopyFromBioModelAppVersionableTypeVersion( + new VersionableTypeVersion(VersionableType.BioModelMetaData, + simContext.getBioModel().getVersion())); + } + DocumentWindow dw = ClientRequestManager.this.getMdiManager().createNewDocumentWindow(windowManager); + this.setFinalWindow(hashTable, dw); + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), + new AsynchClientTask[]{task1, task2}, false); + } + + public void createBioModelFromApplication(final BioModelWindowManager requester, final String name, + final SimulationContext simContext) { + if (simContext == null) { + PopupGenerator.showErrorDialog(requester, + "Selected Application is null, cannot generate corresponding bio model"); + return; + } + if (simContext.isRuleBased()) { + this.createRuleBasedBioModelFromApplication(requester, name, simContext); + return; + } + AsynchClientTask task1 = new AsynchClientTask("Creating BioModel from BioModel Application", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + + MathMapping transformedMathMapping = simContext.createNewMathMapping(); + + BioModel newBioModel = new BioModel(null); + SimulationContext transformedSimContext = transformedMathMapping + .getTransformation().transformedSimContext; + Model newModel = transformedSimContext.getModel(); + newBioModel.setModel(newModel); + + RbmModelContainer rbmmc = newModel.getRbmModelContainer(); + for (RbmObservable o : rbmmc.getObservableList()) { + rbmmc.removeObservable(o); + } + for (ReactionRule r : rbmmc.getReactionRuleList()) { + rbmmc.removeReactionRule(r); + } + for (ReactionStep rs : newModel.getReactionSteps()) { + String oldName = rs.getName(); + if (oldName.startsWith("_reverse_")) { + String newName = newModel.getReactionName("rev", oldName.substring("_reverse_".length())); + rs.setName(newName); + } + } + + hashTable.put("newBioModel", newBioModel); + } + }; + AsynchClientTask task2 = new AsynchClientTask("Creating BioModel from BioModel Application", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + BioModel newBioModel = (BioModel) hashTable.get("newBioModel"); + DocumentWindowManager windowManager = ClientRequestManager.this.createDocumentWindowManager(newBioModel); // if(simContext.getBioModel().getVersion() != null){ // ((BioModelWindowManager)windowManager). setCopyFromBioModelAppVersionableTypeVersion( // new VersionableTypeVersion(VersionableType.BioModelMetaData, simContext.getBioModel().getVersion())); // } - getMdiManager().createNewDocumentWindow(windowManager); - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), - new AsynchClientTask[] { task1, task2 }, false); - } - - public void createRuleBasedBioModelFromApplication(final BioModelWindowManager requester, final String name, - final SimulationContext simContext) { - if (simContext == null) { - PopupGenerator.showErrorDialog(requester, - "Selected Application is null, cannot generate corresponding bio model"); - return; - } - AsynchClientTask task1 = new AsynchClientTask("Creating BioModel from BioModel Application", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - - MathMapping transformedMathMapping = simContext.createNewMathMapping(); - - BioModel newBioModel = new BioModel(null); - SimulationContext transformedSimContext = transformedMathMapping - .getTransformation().transformedSimContext; - Model model = transformedSimContext.getModel(); - - newBioModel.setModel(model); - - hashTable.put("newBioModel", newBioModel); - } - }; - AsynchClientTask task2 = new AsynchClientTask("Creating BioModel from BioModel Application", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - BioModel newBioModel = (BioModel) hashTable.get("newBioModel"); - DocumentWindowManager windowManager = createDocumentWindowManager(newBioModel); - getMdiManager().createNewDocumentWindow(windowManager); - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), - new AsynchClientTask[] { task1, task2 }, false); - } - -//public void createBioModelFromApplication(final BioModelWindowManager requester, final String name, final SimulationContext simContext) { + ClientRequestManager.this.getMdiManager().createNewDocumentWindow(windowManager); + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), + new AsynchClientTask[]{task1, task2}, false); + } + + public void createRuleBasedBioModelFromApplication(final BioModelWindowManager requester, final String name, + final SimulationContext simContext) { + if (simContext == null) { + PopupGenerator.showErrorDialog(requester, + "Selected Application is null, cannot generate corresponding bio model"); + return; + } + AsynchClientTask task1 = new AsynchClientTask("Creating BioModel from BioModel Application", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + + MathMapping transformedMathMapping = simContext.createNewMathMapping(); + + BioModel newBioModel = new BioModel(null); + SimulationContext transformedSimContext = transformedMathMapping + .getTransformation().transformedSimContext; + Model model = transformedSimContext.getModel(); + + newBioModel.setModel(model); + + hashTable.put("newBioModel", newBioModel); + } + }; + AsynchClientTask task2 = new AsynchClientTask("Creating BioModel from BioModel Application", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + BioModel newBioModel = (BioModel) hashTable.get("newBioModel"); + DocumentWindowManager windowManager = ClientRequestManager.this.createDocumentWindowManager(newBioModel); + ClientRequestManager.this.getMdiManager().createNewDocumentWindow(windowManager); + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), + new AsynchClientTask[]{task1, task2}, false); + } + + //public void createBioModelFromApplication(final BioModelWindowManager requester, final String name, final SimulationContext simContext) { // if (simContext == null) { // PopupGenerator.showErrorDialog(requester, "Selected Application is null, cannot generate corresponding bio model"); // return; @@ -1055,64 +1044,64 @@ public void run(Hashtable hashTable) throws Exception { // }; // ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), new AsynchClientTask[]{task1, task2}, false); //} -private BioModel createDefaultBioModelDocument(BngUnitSystem bngUnitSystem) throws Exception { - BioModel bioModel = new BioModel(null); - bioModel.setName("BioModel" + (getMdiManager().getNumCreatedDocumentWindows() + 1)); - - Model model; - if (bngUnitSystem == null) { - model = new Model("model"); - } else { - model = new Model("model", bngUnitSystem.createModelUnitSystem()); - } - bioModel.setModel(model); - - model.createFeature(); - return bioModel; -} - - private MathModel createDefaultMathModelDocument() throws Exception { - Geometry geometry = new Geometry("Untitled", 0); - MathModel mathModel = createMathModel("Untitled", geometry); - mathModel.setName("MathModel" + (getMdiManager().getNumCreatedDocumentWindows() + 1)); - return mathModel; - } - - public VCDocumentInfo selectDocumentFromType(VCDocumentType documentType, TopLevelWindowManager requester) - throws Exception, UserCancelException { - return getMdiManager().getDatabaseWindowManager().selectDocument(documentType, requester); - } - - public Geometry getGeometryFromDocumentSelection(Component parentComponent, VCDocumentInfo vcDocumentInfo, - boolean bClearVersion) throws Exception, UserCancelException { - Geometry geom = null; - if (vcDocumentInfo.getVersionType() - .equals(VersionableType.BioModelMetaData)/* documentType == VCDocument.BIOMODEL_DOC */) { - BioModelInfo bioModelInfo = getDocumentManager() - .getBioModelInfo(vcDocumentInfo.getVersion().getVersionKey()); - BioModelChildSummary bioModelChildSummary = bioModelInfo.getBioModelChildSummary(); - if (bioModelChildSummary != null && bioModelChildSummary.getSimulationContextNames() != null) { - Vector spatialV = new Vector(); - for (int i = 0; i < bioModelChildSummary.getSimulationContextNames().length; i++) { - if (bioModelChildSummary.getGeometryDimensions()[i] > 0) { - spatialV.add(i); - } - } - if (spatialV.size() > 0) { - String[] columnNames = new String[] { "Application", "Geometry", "Dimension" }; - String[][] rowData = new String[spatialV.size()][3]; - for (int i = 0; i < spatialV.size(); i++) { - rowData[i][0] = bioModelChildSummary.getSimulationContextNames()[spatialV.elementAt(i)]; - rowData[i][1] = bioModelChildSummary.getGeometryNames()[spatialV.elementAt(i)]; - rowData[i][2] = bioModelChildSummary.getGeometryDimensions()[spatialV.elementAt(i)] + ""; - } - int[] selection = DialogUtils.showComponentOKCancelTableList( - JOptionPane.getFrameForComponent(parentComponent), "Select Geometry", columnNames, rowData, - ListSelectionModel.SINGLE_SELECTION); - ModelGeometryOPResults modelGeometryOPResults = (ModelGeometryOPResults) getDocumentManager() - .getSessionManager().getUserMetaDbServer().doTestSuiteOP( - new ModelGeometryOP((BioModelInfo) vcDocumentInfo, rowData[selection[0]][0])); - geom = getDocumentManager().getGeometry(modelGeometryOPResults.getGeometryKey()); + private BioModel createDefaultBioModelDocument(BngUnitSystem bngUnitSystem) throws Exception { + BioModel bioModel = new BioModel(null); + bioModel.setName("BioModel" + (this.getMdiManager().getNumCreatedDocumentWindows() + 1)); + + Model model; + if (bngUnitSystem == null) { + model = new Model("model"); + } else { + model = new Model("model", bngUnitSystem.createModelUnitSystem()); + } + bioModel.setModel(model); + + model.createFeature(); + return bioModel; + } + + private MathModel createDefaultMathModelDocument() throws Exception { + Geometry geometry = new Geometry("Untitled", 0); + MathModel mathModel = this.createMathModel("Untitled", geometry); + mathModel.setName("MathModel" + (this.getMdiManager().getNumCreatedDocumentWindows() + 1)); + return mathModel; + } + + public VCDocumentInfo selectDocumentFromType(VCDocumentType documentType, TopLevelWindowManager requester) + throws Exception { + return this.getMdiManager().getDatabaseWindowManager().selectDocument(documentType, requester); + } + + public Geometry getGeometryFromDocumentSelection(Component parentComponent, VCDocumentInfo vcDocumentInfo, + boolean bClearVersion) throws Exception { + Geometry geom = null; + if (vcDocumentInfo.getVersionType() + .equals(VersionableType.BioModelMetaData)/* documentType == VCDocument.BIOMODEL_DOC */) { + BioModelInfo bioModelInfo = this.getDocumentManager() + .getBioModelInfo(vcDocumentInfo.getVersion().getVersionKey()); + BioModelChildSummary bioModelChildSummary = bioModelInfo.getBioModelChildSummary(); + if (bioModelChildSummary != null && bioModelChildSummary.getSimulationContextNames() != null) { + Vector spatialV = new Vector(); + for (int i = 0; i < bioModelChildSummary.getSimulationContextNames().length; i++) { + if (bioModelChildSummary.getGeometryDimensions()[i] > 0) { + spatialV.add(i); + } + } + if (spatialV.size() > 0) { + String[] columnNames = new String[]{"Application", "Geometry", "Dimension"}; + String[][] rowData = new String[spatialV.size()][3]; + for (int i = 0; i < spatialV.size(); i++) { + rowData[i][0] = bioModelChildSummary.getSimulationContextNames()[spatialV.elementAt(i)]; + rowData[i][1] = bioModelChildSummary.getGeometryNames()[spatialV.elementAt(i)]; + rowData[i][2] = bioModelChildSummary.getGeometryDimensions()[spatialV.elementAt(i)] + ""; + } + int[] selection = DialogUtils.showComponentOKCancelTableList( + JOptionPane.getFrameForComponent(parentComponent), "Select Geometry", columnNames, rowData, + ListSelectionModel.SINGLE_SELECTION); + ModelGeometryOPResults modelGeometryOPResults = (ModelGeometryOPResults) this.getDocumentManager() + .getSessionManager().getUserMetaDbServer().doTestSuiteOP( + new ModelGeometryOP((BioModelInfo) vcDocumentInfo, rowData[selection[0]][0])); + geom = this.getDocumentManager().getGeometry(modelGeometryOPResults.getGeometryKey()); // BioModel bioModel = getDocumentManager().getBioModel((BioModelInfo)vcDocumentInfo); // for (int i = 0; i < bioModel.getSimulationContexts().length; i++) { // if(bioModel.getSimulationContexts()[i].getName().equals(rowData[selection[0]][0])){ @@ -1120,679 +1109,679 @@ public Geometry getGeometryFromDocumentSelection(Component parentComponent, VCDo // break; // } // } - } else { - throw new Exception( - "BioModel '" + bioModelInfo.getVersion().getName() + "' contains no spatial geometries."); - } - } else { - throw new Exception( - "BioModel '" + bioModelInfo.getVersion().getName() + "' contains no spatial geometries."); - } - } else if (vcDocumentInfo.getVersionType() - .equals(VersionableType.MathModelMetaData)/* documentType == VCDocument.MATHMODEL_DOC */) { - MathModelInfo mathModelInfo = getDocumentManager() - .getMathModelInfo(vcDocumentInfo.getVersion().getVersionKey()); - MathModelChildSummary mathModelChildSummary = mathModelInfo.getMathModelChildSummary(); - if (mathModelChildSummary != null) { - if (mathModelChildSummary.getGeometryDimension() > 0) { - ModelGeometryOPResults modelGeometryOPResults = (ModelGeometryOPResults) getDocumentManager() - .getSessionManager().getUserMetaDbServer() - .doTestSuiteOP(new ModelGeometryOP((MathModelInfo) vcDocumentInfo)); - geom = getDocumentManager().getGeometry(modelGeometryOPResults.getGeometryKey()); + } else { + throw new Exception( + "BioModel '" + bioModelInfo.getVersion().getName() + "' contains no spatial geometries."); + } + } else { + throw new Exception( + "BioModel '" + bioModelInfo.getVersion().getName() + "' contains no spatial geometries."); + } + } else if (vcDocumentInfo.getVersionType() + .equals(VersionableType.MathModelMetaData)/* documentType == VCDocument.MATHMODEL_DOC */) { + MathModelInfo mathModelInfo = this.getDocumentManager() + .getMathModelInfo(vcDocumentInfo.getVersion().getVersionKey()); + MathModelChildSummary mathModelChildSummary = mathModelInfo.getMathModelChildSummary(); + if (mathModelChildSummary != null) { + if (mathModelChildSummary.getGeometryDimension() > 0) { + ModelGeometryOPResults modelGeometryOPResults = (ModelGeometryOPResults) this.getDocumentManager() + .getSessionManager().getUserMetaDbServer() + .doTestSuiteOP(new ModelGeometryOP((MathModelInfo) vcDocumentInfo)); + geom = this.getDocumentManager().getGeometry(modelGeometryOPResults.getGeometryKey()); // MathModel mathModel = getDocumentManager().getMathModel(mathModelInfo); // geom = mathModel.getMathDescription().getGeometry(); - } else { - throw new Exception( - "MathModel '" + mathModelInfo.getVersion().getName() + "' contains no spatial geometry."); - } - } else { - throw new Exception( - "MathModel '" + mathModelInfo.getVersion().getName() + "' contains no spatial geometry."); - } - } else if (vcDocumentInfo.getVersionType().equals(VersionableType.Geometry)) { - geom = getDocumentManager().getGeometry((GeometryInfo) vcDocumentInfo); - if (geom.getDimension() == 0) { - throw new Exception("Error, Only spatial geometries allowed (dimension > 0)."); - } - } else { - throw new IllegalArgumentException("Error selecting geometry from document type " - + vcDocumentInfo.getVersionType() + ". Must be BioModel,MathModel or Geometry."); - } - if (geom == null) { - throw new Exception("error selecting geometry"); - } - if (bClearVersion) { - geom.clearVersion(); - } - return geom; - } - - public static final String GUI_PARENT = "guiParent"; - - public static boolean isImportGeometryType(DocumentCreationInfo documentCreationInfo) { - return documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA - || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE - || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_SCRATCH - || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_ANALYTIC - || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_IMAGE + } else { + throw new Exception( + "MathModel '" + mathModelInfo.getVersion().getName() + "' contains no spatial geometry."); + } + } else { + throw new Exception( + "MathModel '" + mathModelInfo.getVersion().getName() + "' contains no spatial geometry."); + } + } else if (vcDocumentInfo.getVersionType().equals(VersionableType.Geometry)) { + geom = this.getDocumentManager().getGeometry((GeometryInfo) vcDocumentInfo); + if (geom.getDimension() == 0) { + throw new Exception("Error, Only spatial geometries allowed (dimension > 0)."); + } + } else { + throw new IllegalArgumentException("Error selecting geometry from document type " + + vcDocumentInfo.getVersionType() + ". Must be BioModel,MathModel or Geometry."); + } + if (geom == null) { + throw new Exception("error selecting geometry"); + } + if (bClearVersion) { + geom.clearVersion(); + } + return geom; + } + + public static final String GUI_PARENT = "guiParent"; + + public static boolean isImportGeometryType(DocumentCreationInfo documentCreationInfo) { + return documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA + || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE + || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_SCRATCH + || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_ANALYTIC + || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_IMAGE // || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIJI_IMAGEJ || // documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_BLENDER - ; - } - - private static void throwImportWholeDirectoryException(File invalidFile, String extraInfo) throws Exception { - throw new Exception("Import whole directory failed: directory '" + invalidFile.getAbsolutePath() + "' " - + "contains invalid file. Import from whole directory can contain only files for " - + "a single z-series, each file must be 2D, single time. " - + "All files must be the same size and have the same number color channels." - + (extraInfo == null ? "" : "\n" + extraInfo)); - - } - - private static FieldDataFileOperationSpec createFDOSFromVCImage(VCImage dbImage) throws ImageException { - int[] temp = new int[256]; - short[] templateShorts = new short[dbImage.getNumXYZ()]; - for (int i = 0; i < dbImage.getPixels().length; i++) { - templateShorts[i] = (short) (0x00FF & dbImage.getPixels()[i]); - temp[templateShorts[i]]++; - } - for (int j = 0; j < dbImage.getPixelClasses().length; j++) { - short tempshort = (short) (0x00FF & dbImage.getPixelClasses()[j].getPixel()); - } - FieldDataFileOperationSpec fdfos = null; - fdfos = new FieldDataFileOperationSpec(); - fdfos.origin = new Origin(0, 0, 0); - fdfos.extent = dbImage.getExtent(); - fdfos.isize = new ISize(dbImage.getNumX(), dbImage.getNumY(), dbImage.getNumZ()); - fdfos.shortSpecData = new short[][][] { { templateShorts } }; - return fdfos; - } - - public static SurfaceCollection createSurfaceCollectionFromSurfaceFile(File surfaceFile) throws Exception { - SurfaceCollection surfaceCollection = null; - if (ExtensionFilter.isMatchingExtension(surfaceFile, ".stl")) { - surfaceCollection = StlReader.readStl(surfaceFile); - } else if (ExtensionFilter.isMatchingExtension(surfaceFile, ".mesh")) {// NOT VCell mesh, salk Hughes Hoppe mesh - // convert to .stl and read - BufferedWriter stlBufferedWriter = null; - File tempstlFile = File.createTempFile("salk", ".stl"); - try { - try (BufferedReader salkBufferedReader = new BufferedReader(new FileReader(surfaceFile))) { - String line; - ArrayList vertList = new ArrayList(); - // read vertices - while ((line = salkBufferedReader.readLine()) != null) { - StringTokenizer st = new StringTokenizer(line, " "); - String firstToken = st.nextToken(); - int vertIndex = Integer.parseInt(st.nextToken()); - if (firstToken.equals("Vertex")) { - vertList.add(new double[] { Double.parseDouble(st.nextToken()), - Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken()) }); - if (vertList.size() != vertIndex) {// numbering starts at 1 - throw new Exception("Index not match position in list"); - } - } else if (firstToken.equals("Face")) { - break;// read all vertices - } else { - return null; - } - } - stlBufferedWriter = new BufferedWriter(new FileWriter(tempstlFile)); - stlBufferedWriter.write("solid VCell salk convert\n"); - // read faces - do { - stlBufferedWriter.write("facet normal 0 0 0\n"); - stlBufferedWriter.write("outer loop\n"); - StringTokenizer st = new StringTokenizer(line, " "); - String firstToken = st.nextToken(); - Integer.parseInt(st.nextToken());// ignore index token - if (firstToken.equals("Face")) { - for (int i = 0; i < 3; i++) { - int vertListIndex = Integer.parseInt(st.nextToken()) - 1; - double[] vertCoordinatges = vertList.get(vertListIndex); - stlBufferedWriter.write("vertex " + vertCoordinatges[0] + " " + vertCoordinatges[1] - + " " + vertCoordinatges[2] + "\n");// indexes start at 1, not 0 - } - } else { - throw new Exception("Expecting token 'Face' but got " + firstToken); - } - stlBufferedWriter.write("endloop\n"); - stlBufferedWriter.write("endfacet\n"); - } while ((line = salkBufferedReader.readLine()) != null); - stlBufferedWriter.write("endsolid VCell salk convert\n"); - - stlBufferedWriter.close(); - surfaceCollection = StlReader.readStl(tempstlFile); - } - } catch (Exception e) { - // we couldn't read this for some reason - e.printStackTrace(); - } finally { - if (stlBufferedWriter != null) { - try { - stlBufferedWriter.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - if (tempstlFile != null) { - tempstlFile.delete(); - } - } - } - return surfaceCollection; - } - - public static FieldDataFileOperationSpec createFDOSFromSurfaceFile(File surfaceFile) throws Exception { - SurfaceCollection surfaceCollection = createSurfaceCollectionFromSurfaceFile(surfaceFile); - if (surfaceCollection != null) { - Geometry geometry = RayCaster.createGeometryFromSTL(new GeometryThumbnailImageFactoryAWT(), - surfaceCollection, 1000000); - FieldDataFileOperationSpec fdfos = new FieldDataFileOperationSpec(); - fdfos.origin = geometry.getOrigin(); - fdfos.extent = geometry.getExtent(); - VCImage image = geometry.getGeometrySpec().getImage(); - if (image.getNumPixelClasses() == 1) { - throw new Exception("STL import failed during processing, pixelclass count=1"); - } - fdfos.isize = new ISize(image.getNumX(), image.getNumY(), image.getNumZ()); - byte[] pixels = image.getPixels(); - short[] dataToSegment = new short[image.getNumXYZ()]; - for (int i = 0; i < pixels.length; i++) { - dataToSegment[i] = pixels[i]; - } - fdfos.shortSpecData = new short[][][] { { dataToSegment } }; - return fdfos; - } - return null; - } - - public static final String GEOM_FROM_WORKSPACE = "GEOM_FROM_WORKSPACE"; - public static final String VCPIXELCLASSES = "VCPIXELCLASSES"; - - private enum NRRDTYPE { - DOUBLE, FLOAT, UNSIGNEDCHAR - }; - - private enum NRRDENCODING { - RAW, GZIP - }; - - public static final String IMPORT_SOURCE_NAME = "IMPORT_SOURCE_NAME"; - private static final String DIR_FILES = "DIR_FILES"; - public static final String ORIG_IMAGE_SIZE_INFO = "ORIG_IMAGE_SIZE_INFO"; - public static final String NEW_IMAGE_SIZE_INFO = "NEW_IMAGE_SIZE_INFO"; - private static final String INITIAL_ANNOTATION = "INITIAL_ANNOTATION"; - private static final String FD_MESH = "FD_MESH"; - private static final String FD_MESHISIZE = "FD_MESHISIZE"; - public static final String FDFOS = "FDFOS"; - private static final String IMAGE_FILE = "IMAGE_FILE"; - - public static AsynchClientTask getParseImageTask(final Component requesterComp,final VCDocument.DocumentCreationInfo documentCreationInfo,final MDIManager mdiManager) { - AsynchClientTask parseImageTask = new AsynchClientTask("read and parse image file",AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(final Hashtable hashTable) throws Exception { - - final Component guiParent = (Component) hashTable.get(ClientRequestManager.GUI_PARENT); - try { - FieldDataFileOperationSpec fdfos = null; - // if(documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIJI_IMAGEJ){ - // hashTable.put("imageFile",ImageJHelper.vcellWantImage(getClientTaskStatusSupport(),"Image for new VCell geometry")); - // } - // if(documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_BLENDER){ - // hashTable.put("imageFile",ImageJHelper.vcellWantSurface(getClientTaskStatusSupport(),"Image for new VCell geometry")); - // } - if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE - // || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIJI_IMAGEJ || - // documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_BLENDER - ) { - - File imageFile = (File) hashTable.get(IMAGE_FILE); - if (imageFile == null) { - throw new Exception("No file selected"); - } - if (ExtensionFilter.isMatchingExtension(imageFile, ".nrrd")) { - - DataInputStream dis = null; - try { - dis = new DataInputStream(new BufferedInputStream(new FileInputStream(imageFile))); - int xsize = 1; - int ysize = 1; - int zsize = 1; - double xspace = 1.0; - double yspace = 1.0; - double zspace = 1.0; - NRRDTYPE type = null; - NRRDENCODING encoding = null; - int dimension = -1; - // read header lines - while (true) { - @SuppressWarnings("deprecation") - String line = dis.readLine(); - if (line == null || line.length() == 0) { - break; - } - StringTokenizer stringTokenizer = new StringTokenizer(line, ": "); - String headerParam = stringTokenizer.nextToken(); - // System.out.println(headerParam); - if (headerParam.equals("sizes")) { - if (dimension != -1) { - xsize = Integer.parseInt(stringTokenizer.nextToken()); - if (dimension >= 2) { - ysize = Integer.parseInt(stringTokenizer.nextToken()); - } - if (dimension >= 3) { - zsize = Integer.parseInt(stringTokenizer.nextToken()); - } - for (int i = 4; i < dimension; i++) { - if (Integer.parseInt(stringTokenizer.nextToken()) != 1) { - throw new Exception("Dimensions > 3 not supported"); - } - } - } else { - throw new Exception("dimension expected to be set before reading sizes"); - } - } else if (headerParam.equals("spacings")) { - if (dimension != -1) { - xspace = Double.parseDouble(stringTokenizer.nextToken()); - if (dimension >= 2) { - yspace = Double.parseDouble(stringTokenizer.nextToken()); - } - if (dimension >= 3) { - zspace = Double.parseDouble(stringTokenizer.nextToken()); - } - // ignore other dimension spacings - } else { - throw new Exception("dimension expected to be set before reading spacings"); - } - } else if (headerParam.equals("type")) { - String nextToken = stringTokenizer.nextToken(); - if (nextToken.equalsIgnoreCase("double")) { - type = NRRDTYPE.DOUBLE; - } else if (nextToken.equalsIgnoreCase("float")) { - type = NRRDTYPE.FLOAT; - } else if (nextToken.equalsIgnoreCase("unsigned")) { - nextToken = stringTokenizer.nextToken(); - if (nextToken.equalsIgnoreCase("char")) { - type = NRRDTYPE.UNSIGNEDCHAR; - } else { - throw new Exception("Unknown nrrd data type=" + nextToken); - } - } else { - throw new Exception("Unknown nrrd data type=" + nextToken); - } - } else if (headerParam.equals("dimension")) { - dimension = Integer.parseInt(stringTokenizer.nextToken()); - if (dimension < 1) { - throw new Exception("unexpected dimension=" + dimension); - } - } else if (headerParam.equals("encoding")) { - encoding = NRRDENCODING.valueOf(stringTokenizer.nextToken().toUpperCase()); - } - } - BufferedInputStream bis = null; - if (encoding == NRRDENCODING.GZIP) { - dis.close(); - bis = new BufferedInputStream(new FileInputStream(imageFile)); - boolean bnewLine = false; - while (true) { - int currentChar = bis.read(); - if (currentChar == '\n') { - if (bnewLine) { - break;// 2 newlines end header - } - bnewLine = true; - } else { - bnewLine = false; - } - } - GZIPInputStream gzipInputStream = new GZIPInputStream(bis); - dis = new DataInputStream(gzipInputStream); - } - double[] data = new double[xsize * ysize * zsize]; - double minValue = Double.POSITIVE_INFINITY; - double maxValue = Double.NEGATIVE_INFINITY; - for (int i = 0; i < data.length; i++) { - if (i % 262144 == 0) { - if (getClientTaskStatusSupport() != null) { - getClientTaskStatusSupport().setMessage("Reading " + encoding + " " + type - + " NRRD data " + (((long) i * (long) 100) / (long) data.length) - + " % done."); - } - } - if (type == NRRDTYPE.DOUBLE) { - data[i] = dis.readDouble(); - } else if (type == NRRDTYPE.FLOAT) { - data[i] = dis.readFloat(); - } else if (type == NRRDTYPE.UNSIGNEDCHAR) { - data[i] = dis.readUnsignedByte(); - } else { - throw new Exception("Unexpected data type=" + type.toString()); - } - - minValue = Math.min(minValue, data[i]); - maxValue = Math.max(maxValue, data[i]); - } - dis.close(); - if (getClientTaskStatusSupport() != null) { - getClientTaskStatusSupport() - .setMessage("Scaling " + encoding + " " + type + " NRRD data."); - } - - short[] dataToSegment = new short[data.length]; - double scaleShort = Math.pow(2, Short.SIZE) - 1; - for (int i = 0; i < data.length; i++) { - dataToSegment[i] |= (int) ((data[i] - minValue) / (maxValue - minValue) - * scaleShort); - } - fdfos = new FieldDataFileOperationSpec(); - fdfos.origin = new Origin(0, 0, 0); - fdfos.extent = new Extent((xsize == 1 ? .5 : (xsize) * xspace), - (ysize == 1 ? .5 : (ysize) * yspace), (zsize == 1 ? .5 : (zsize) * zspace)); - fdfos.isize = new ISize(xsize, ysize, zsize); - fdfos.shortSpecData = new short[][][] { { dataToSegment } }; - } finally { - if (dis != null) { - try { - dis.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } else if ((fdfos = createFDOSFromSurfaceFile(imageFile)) != null) {// try surface file formats - // work already done at this point - } else { - File[] dirFiles = null; - ImageSizeInfo origImageSizeInfo = null; - ImageDatasetReaderService imageDatasetReaderServiceInstance = ImageDatasetReaderService - .getInstance(); - ImageDatasetReader imageDatasetReader = imageDatasetReaderServiceInstance - .getImageDatasetReader(); - if (imageFile.isDirectory()) { - dirFiles = imageFile.listFiles(new java.io.FileFilter() { - public boolean accept(File pathname) { - return pathname.isFile() && !pathname.isHidden();// exclude windows Thumbs.db - } - }); - if (dirFiles.length == 0) { - throw new Exception("No valid files in selected directory"); - } - String fileExt0 = null; - for (int i = 0; i < dirFiles.length; i++) { - int lastDot = dirFiles[i].getName().lastIndexOf('.'); - String fileExt = (lastDot != -1 ? dirFiles[i].getName().substring(lastDot) : null); - if (dirFiles[i].isDirectory()) { - fileExt = "dir"; - } - if (i == 0) { - fileExt0 = fileExt; - } else if (!Compare.isEqualOrNull(fileExt, fileExt0)) { - String result = DialogUtils.showWarningDialog(requesterComp, - "Files in '" + imageFile.getAbsolutePath() - + "' have different name extensions, continue?", - new String[] { "OK", "Cancel" }, "Cancel"); - if (!"OK".equals(result)) { - throw UserCancelException.CANCEL_FILE_SELECTION; - } - break; - } - - } - hashTable.put(IMPORT_SOURCE_NAME, "Directory: " + imageFile.getAbsolutePath()); - origImageSizeInfo = imageDatasetReader - .getImageSizeInfoForceZ(dirFiles[0].getAbsolutePath(), dirFiles.length); - if (dirFiles.length > 1) { - final String importZ = "Import Z-Sections"; - final String cancelOption = "Cancel"; - String result = DialogUtils.showWarningDialog(guiParent, - "Import all files in directory '" + imageFile.getAbsolutePath() - + "' as Z-Sections", - new String[] { importZ, cancelOption }, importZ); - if (result.equals(cancelOption)) { - throw UserCancelException.CANCEL_GENERIC; - } - } - hashTable.put(DIR_FILES, dirFiles); - } else { - origImageSizeInfo = imageDatasetReader - .getImageSizeInfoForceZ(imageFile.getAbsolutePath(), null); - hashTable.put(IMPORT_SOURCE_NAME, "File: " + imageFile.getAbsolutePath()); - } - hashTable.put(ORIG_IMAGE_SIZE_INFO, origImageSizeInfo); - return; - } - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA) { - getClientTaskStatusSupport().setMessage("Reading data from VCell server."); - VCDocument.GeomFromFieldDataCreationInfo docInfo = (VCDocument.GeomFromFieldDataCreationInfo) documentCreationInfo; - PDEDataContext pdeDataContext = mdiManager.getFieldDataWindowManager() - .getPDEDataContext(docInfo.getExternalDataID(), null); - ImageSizeInfo newImageSizeInfo = (ImageSizeInfo) hashTable.get(NEW_IMAGE_SIZE_INFO); - pdeDataContext.setVariableNameAndTime(docInfo.getVarName(), - newImageSizeInfo.getTimePoints()[newImageSizeInfo.getSelectedTimeIndex()]); - double[] data = pdeDataContext.getDataValues(); - hashTable.put(INITIAL_ANNOTATION, hashTable.get(IMPORT_SOURCE_NAME)); - CartesianMesh mesh = (CartesianMesh) hashTable.get(FD_MESH); - ISize meshISize = (ISize) hashTable.get(FD_MESHISIZE); - double minValue = Double.POSITIVE_INFINITY; - double maxValue = Double.NEGATIVE_INFINITY; - for (int i = 0; i < data.length; i++) { - minValue = Math.min(minValue, data[i]); - maxValue = Math.max(maxValue, data[i]); - } - short[] dataToSegment = new short[data.length]; - double scaleShort = Math.pow(2, Short.SIZE) - 1; - for (int i = 0; i < data.length; i++) { - dataToSegment[i] |= (int) ((data[i] - minValue) / (maxValue - minValue) * scaleShort); - } - fdfos = new FieldDataFileOperationSpec(); - fdfos.origin = mesh.getOrigin(); - fdfos.extent = mesh.getExtent(); - fdfos.isize = meshISize; - fdfos.shortSpecData = new short[][][] { { dataToSegment } }; - - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_SCRATCH) { - ISize isize = getISizeFromUser(guiParent, new ISize(256, 256, 8), - "Enter # of pixels for x,y,z (e.g. 3D{256,256,8}, 2D{256,256,1}, 1D{256,1,1})"); - fdfos = new FieldDataFileOperationSpec(); - fdfos.origin = new Origin(0, 0, 0); - fdfos.extent = new Extent(1, 1, 1); - fdfos.isize = isize; - hashTable.put(IMPORT_SOURCE_NAME, "Scratch: New Geometry"); - // final int SCRATCH_SIZE_LIMIT = 512*512*20; - // if(isize.getXYZ() > (SCRATCH_SIZE_LIMIT)){ - // throw new Exception("Total pixels (x*y*z) cannot be >"+SCRATCH_SIZE_LIMIT+"."); - // } - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_ANALYTIC) { - if (hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE) != null) { - Geometry workspaceGeom = (Geometry) hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE); - ISize defaultISize = workspaceGeom.getGeometrySpec().getDefaultSampledImageSize(); - ISize isize = getISizeFromUser(guiParent, defaultISize, - "Warning: converting analytic expression geometry into an image based geometry\nwill remove analytic expressions after new image is created.\n\n" - + "Enter size (x,y,z) for new geometry image (e.g. " + defaultISize.getX() - + "," + defaultISize.getY() + "," + defaultISize.getZ() + ")"); - hashTable.put(IMPORT_SOURCE_NAME, "Workspace from Analytic Geometry"); - VCImage img = workspaceGeom.getGeometrySpec().createSampledImage(isize); - Enumeration enumSubvolume = workspaceGeom.getGeometrySpec() - .getAnalyticOrCSGSubVolumes(); - ArrayList vcPixelClassArrList = new ArrayList(); - while (enumSubvolume.hasMoreElements()) { - SubVolume subVolume = enumSubvolume.nextElement(); - vcPixelClassArrList - .add(new VCPixelClass(null, subVolume.getName(), subVolume.getHandle())); - } - if (vcPixelClassArrList.size() > img.getPixelClasses().length) { - String result = DialogUtils.showOKCancelWarningDialog(requesterComp, null, - "Warning: sampling size is too small to include all subvolumes."); - if (result == null || !result.equals(SimpleUserMessage.OPTION_OK)) { - throw UserCancelException.CANCEL_GENERIC; - } - } - hashTable.put(VCPIXELCLASSES, vcPixelClassArrList.toArray(new VCPixelClass[0])); - fdfos = createFDOSFromVCImage(img); - } else { - throw new Exception("Expecting image source for GEOM_OPTION_FROM_WORKSPACE_ANALYTIC"); - } - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_IMAGE) { - if (hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE) != null) { - Geometry workspaceGeom = (Geometry) hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE); - hashTable.put(IMPORT_SOURCE_NAME, "Workspace Image"); - fdfos = createFDOSFromVCImage(workspaceGeom.getGeometrySpec().getImage()); - if (workspaceGeom.getGeometrySpec().getImage().getDescription() != null) { - hashTable.put(INITIAL_ANNOTATION, - workspaceGeom.getGeometrySpec().getImage().getDescription()); - } - GeometryClass[] myGeometryClasses = workspaceGeom.getGeometryClasses(); - VCPixelClass[] myPixelClasses = workspaceGeom.getGeometrySpec().getImage() - .getPixelClasses(); - VCPixelClass[] newPixelClasses = new VCPixelClass[myPixelClasses.length]; - for (int i = 0; i < myPixelClasses.length; i++) { - for (int j = 0; j < myGeometryClasses.length; j++) { - if (myGeometryClasses[j] instanceof ImageSubVolume && myPixelClasses[i] - .getPixel() == ((ImageSubVolume) myGeometryClasses[j]).getPixelValue()) { - newPixelClasses[i] = new VCPixelClass(null, myGeometryClasses[j].getName(), - myPixelClasses[i].getPixel()); - break; - } - } - } - hashTable.put(VCPIXELCLASSES, newPixelClasses); - } else { - throw new Exception("Expecting image source for GEOM_OPTION_FROM_WORKSPACE"); - } - } - hashTable.put(FDFOS, fdfos); - } catch (DataFormatException ex) { - throw new Exception("Cannot read image file.\n" + ex.getMessage()); - } - } - }; - return parseImageTask; - } - - // Get image from file - public static AsynchClientTask getSelectImageFileTask(final Component requesterComp,final UserPreferences userPreferences) { - AsynchClientTask selectImageFileTask = new AsynchClientTask("select image file", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - File imageFile = DatabaseWindowManager.showFileChooserDialog(requesterComp, null, userPreferences,JFileChooser.FILES_AND_DIRECTORIES); - hashTable.put(IMAGE_FILE, imageFile); - hashTable.put(IMPORT_SOURCE_NAME, "File: " + imageFile.getName()); - } - }; - return selectImageFileTask; - } - - public static AsynchClientTask getImportFileImageTask(final VCDocument.DocumentCreationInfo documentCreationInfo) { - AsynchClientTask importFileImageTask = new AsynchClientTask("Importing Image from File...",AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE && hashTable.get(FDFOS) == null) { - ImageSizeInfo origImageSizeInfo = (ImageSizeInfo) hashTable.get(ORIG_IMAGE_SIZE_INFO); - ImageSizeInfo newImageSizeInfo = (ImageSizeInfo) hashTable.get(NEW_IMAGE_SIZE_INFO); - File[] dirFiles = (File[]) hashTable.get(DIR_FILES); - File imageFile = (File) hashTable.get(IMAGE_FILE); - FieldDataFileOperationSpec fdfos = null; - boolean bMergeChannels = origImageSizeInfo.getNumChannels() != newImageSizeInfo.getNumChannels(); - ISize resize = (origImageSizeInfo.getiSize().compareEqual(newImageSizeInfo.getiSize()) ? null - : newImageSizeInfo.getiSize()); - if (dirFiles != null) { - Arrays.sort(dirFiles, new Comparator() { - public int compare(File o1, File o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }); - hashTable.put(INITIAL_ANNOTATION, dirFiles[0].getAbsolutePath() + "\n.\n.\n.\n" - + dirFiles[dirFiles.length - 1].getAbsolutePath()); - short[][] dataToSegment = null; - ISize isize = null; - Origin origin = null; - Extent extent = null; - int sizeXY = 0; - ISize firstImageISize = null; - for (int i = 0; i < dirFiles.length; i++) { - if (getClientTaskStatusSupport() != null) { - getClientTaskStatusSupport() - .setMessage("reading files " + (i + 1) + " of " + dirFiles.length); - } - ImageDataset[] imageDatasets = ImageDatasetReaderService.getInstance() - .getImageDatasetReader().readImageDatasetChannels(dirFiles[i].getAbsolutePath(), - getClientTaskStatusSupport(), bMergeChannels, null, resize); - for (int c = 0; c < imageDatasets.length; c++) { - if (imageDatasets[c].getSizeZ() != 1 || imageDatasets[c].getSizeT() != 1) { - throwImportWholeDirectoryException(imageFile, - dirFiles[i].getAbsolutePath() + " has Z=" + imageDatasets[c].getSizeZ() - + " T=" + imageDatasets[c].getSizeT()); - } - if (isize == null) { - firstImageISize = imageDatasets[c].getISize(); - sizeXY = imageDatasets[c].getISize().getX() * imageDatasets[c].getISize().getY(); - dataToSegment = new short[imageDatasets.length][sizeXY * dirFiles.length]; - isize = new ISize(imageDatasets[c].getISize().getX(), - imageDatasets[c].getISize().getY(), dirFiles.length); - origin = imageDatasets[c].getAllImages()[0].getOrigin(); - extent = imageDatasets[c].getExtent(); - } - if (!firstImageISize.compareEqual(imageDatasets[c].getISize())) { - throwImportWholeDirectoryException(imageFile, - dirFiles[0].getAbsolutePath() + " " + firstImageISize + " does not equal " - + dirFiles[i].getAbsolutePath() + " " - + imageDatasets[c].getISize()); - } - System.arraycopy(imageDatasets[c].getImage(0, 0, 0).getPixels(), 0, dataToSegment[c], - sizeXY * i, sizeXY); - - } - } - fdfos = new FieldDataFileOperationSpec(); - fdfos.origin = origin; - fdfos.extent = extent; - fdfos.isize = isize; - fdfos.shortSpecData = new short[][][] { dataToSegment }; - } else { - hashTable.put(INITIAL_ANNOTATION, imageFile.getAbsolutePath()); - Integer userPreferredTimeIndex = null; - if (origImageSizeInfo.getTimePoints().length > 1) { - userPreferredTimeIndex = newImageSizeInfo.getSelectedTimeIndex(); - } - if(getClientTaskStatusSupport() != null) { - getClientTaskStatusSupport().setMessage("Reading file..."); - } - ImageDataset[] imageDatasets = ImageDatasetReaderService.getInstance().getImageDatasetReader() - .readImageDatasetChannels(imageFile.getAbsolutePath(), getClientTaskStatusSupport(), - bMergeChannels, userPreferredTimeIndex, resize); - fdfos = ClientRequestManager.createFDOSWithChannels(imageDatasets, null); - } - hashTable.put(FDFOS, fdfos); - hashTable.remove(NEW_IMAGE_SIZE_INFO); - hashTable.remove(ORIG_IMAGE_SIZE_INFO); - hashTable.remove(DIR_FILES); - } - } - }; - return importFileImageTask; - } - - public static AsynchClientTask getResizeImageTask(final VCDocument.DocumentCreationInfo documentCreationInfo) { - AsynchClientTask resizeImageTask = new AsynchClientTask("Resizing Image...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - ImageSizeInfo newImageSizeInfo = (ImageSizeInfo) hashTable.get(NEW_IMAGE_SIZE_INFO); - FieldDataFileOperationSpec fdfos = (FieldDataFileOperationSpec) hashTable.get(FDFOS); - if (newImageSizeInfo != null && fdfos != null - && !fdfos.isize.compareEqual(newImageSizeInfo.getiSize())) { + ; + } + + private static void throwImportWholeDirectoryException(File invalidFile, String extraInfo) throws Exception { + throw new Exception("Import whole directory failed: directory '" + invalidFile.getAbsolutePath() + "' " + + "contains invalid file. Import from whole directory can contain only files for " + + "a single z-series, each file must be 2D, single time. " + + "All files must be the same size and have the same number color channels." + + (extraInfo == null ? "" : "\n" + extraInfo)); + + } + + private static FieldDataFileOperationSpec createFDOSFromVCImage(VCImage dbImage) throws ImageException { + int[] temp = new int[256]; + short[] templateShorts = new short[dbImage.getNumXYZ()]; + for (int i = 0; i < dbImage.getPixels().length; i++) { + templateShorts[i] = (short) (0x00FF & dbImage.getPixels()[i]); + temp[templateShorts[i]]++; + } + for (int j = 0; j < dbImage.getPixelClasses().length; j++) { + short tempshort = (short) (0x00FF & dbImage.getPixelClasses()[j].getPixel()); + } + FieldDataFileOperationSpec fdfos = null; + fdfos = new FieldDataFileOperationSpec(); + fdfos.origin = new Origin(0, 0, 0); + fdfos.extent = dbImage.getExtent(); + fdfos.isize = new ISize(dbImage.getNumX(), dbImage.getNumY(), dbImage.getNumZ()); + fdfos.shortSpecData = new short[][][]{{templateShorts}}; + return fdfos; + } + + public static SurfaceCollection createSurfaceCollectionFromSurfaceFile(File surfaceFile) throws Exception { + SurfaceCollection surfaceCollection = null; + if (ExtensionFilter.isMatchingExtension(surfaceFile, ".stl")) { + surfaceCollection = StlReader.readStl(surfaceFile); + } else if (ExtensionFilter.isMatchingExtension(surfaceFile, ".mesh")) {// NOT VCell mesh, salk Hughes Hoppe mesh + // convert to .stl and read + BufferedWriter stlBufferedWriter = null; + File tempstlFile = File.createTempFile("salk", ".stl"); + try { + try (BufferedReader salkBufferedReader = new BufferedReader(new FileReader(surfaceFile))) { + String line; + ArrayList vertList = new ArrayList(); + // read vertices + while ((line = salkBufferedReader.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line, " "); + String firstToken = st.nextToken(); + int vertIndex = Integer.parseInt(st.nextToken()); + if (firstToken.equals("Vertex")) { + vertList.add(new double[]{Double.parseDouble(st.nextToken()), + Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken())}); + if (vertList.size() != vertIndex) {// numbering starts at 1 + throw new Exception("Index not match position in list"); + } + } else if (firstToken.equals("Face")) { + break;// read all vertices + } else { + return null; + } + } + stlBufferedWriter = new BufferedWriter(new FileWriter(tempstlFile)); + stlBufferedWriter.write("solid VCell salk convert\n"); + // read faces + do { + stlBufferedWriter.write("facet normal 0 0 0\n"); + stlBufferedWriter.write("outer loop\n"); + StringTokenizer st = new StringTokenizer(line, " "); + String firstToken = st.nextToken(); + Integer.parseInt(st.nextToken());// ignore index token + if (firstToken.equals("Face")) { + for (int i = 0; i < 3; i++) { + int vertListIndex = Integer.parseInt(st.nextToken()) - 1; + double[] vertCoordinatges = vertList.get(vertListIndex); + stlBufferedWriter.write("vertex " + vertCoordinatges[0] + " " + vertCoordinatges[1] + + " " + vertCoordinatges[2] + "\n");// indexes start at 1, not 0 + } + } else { + throw new Exception("Expecting token 'Face' but got " + firstToken); + } + stlBufferedWriter.write("endloop\n"); + stlBufferedWriter.write("endfacet\n"); + } while ((line = salkBufferedReader.readLine()) != null); + stlBufferedWriter.write("endsolid VCell salk convert\n"); + + stlBufferedWriter.close(); + surfaceCollection = StlReader.readStl(tempstlFile); + } + } catch (Exception e) { + // we couldn't read this for some reason + e.printStackTrace(); + } finally { + if (stlBufferedWriter != null) { + try { + stlBufferedWriter.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (tempstlFile != null) { + tempstlFile.delete(); + } + } + } + return surfaceCollection; + } + + public static FieldDataFileOperationSpec createFDOSFromSurfaceFile(File surfaceFile) throws Exception { + SurfaceCollection surfaceCollection = createSurfaceCollectionFromSurfaceFile(surfaceFile); + if (surfaceCollection != null) { + Geometry geometry = RayCaster.createGeometryFromSTL(new GeometryThumbnailImageFactoryAWT(), + surfaceCollection, 1000000); + FieldDataFileOperationSpec fdfos = new FieldDataFileOperationSpec(); + fdfos.origin = geometry.getOrigin(); + fdfos.extent = geometry.getExtent(); + VCImage image = geometry.getGeometrySpec().getImage(); + if (image.getNumPixelClasses() == 1) { + throw new Exception("STL import failed during processing, pixelclass count=1"); + } + fdfos.isize = new ISize(image.getNumX(), image.getNumY(), image.getNumZ()); + byte[] pixels = image.getPixels(); + short[] dataToSegment = new short[image.getNumXYZ()]; + for (int i = 0; i < pixels.length; i++) { + dataToSegment[i] = pixels[i]; + } + fdfos.shortSpecData = new short[][][]{{dataToSegment}}; + return fdfos; + } + return null; + } + + public static final String GEOM_FROM_WORKSPACE = "GEOM_FROM_WORKSPACE"; + public static final String VCPIXELCLASSES = "VCPIXELCLASSES"; + + private enum NRRDTYPE { + DOUBLE, FLOAT, UNSIGNEDCHAR + } + + private enum NRRDENCODING { + RAW, GZIP + } + + public static final String IMPORT_SOURCE_NAME = "IMPORT_SOURCE_NAME"; + private static final String DIR_FILES = "DIR_FILES"; + public static final String ORIG_IMAGE_SIZE_INFO = "ORIG_IMAGE_SIZE_INFO"; + public static final String NEW_IMAGE_SIZE_INFO = "NEW_IMAGE_SIZE_INFO"; + private static final String INITIAL_ANNOTATION = "INITIAL_ANNOTATION"; + private static final String FD_MESH = "FD_MESH"; + private static final String FD_MESHISIZE = "FD_MESHISIZE"; + public static final String FDFOS = "FDFOS"; + private static final String IMAGE_FILE = "IMAGE_FILE"; + + public static AsynchClientTask getParseImageTask(final Component requesterComp, final VCDocument.DocumentCreationInfo documentCreationInfo, final MDIManager mdiManager) { + AsynchClientTask parseImageTask = new AsynchClientTask("read and parse image file", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(final Hashtable hashTable) throws Exception { + + final Component guiParent = (Component) hashTable.get(ClientRequestManager.GUI_PARENT); + try { + FieldDataFileOperationSpec fdfos = null; + // if(documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIJI_IMAGEJ){ + // hashTable.put("imageFile",ImageJHelper.vcellWantImage(getClientTaskStatusSupport(),"Image for new VCell geometry")); + // } + // if(documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_BLENDER){ + // hashTable.put("imageFile",ImageJHelper.vcellWantSurface(getClientTaskStatusSupport(),"Image for new VCell geometry")); + // } + if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE + // || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIJI_IMAGEJ || + // documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_BLENDER + ) { + + File imageFile = (File) hashTable.get(IMAGE_FILE); + if (imageFile == null) { + throw new Exception("No file selected"); + } + if (ExtensionFilter.isMatchingExtension(imageFile, ".nrrd")) { + + DataInputStream dis = null; + try { + dis = new DataInputStream(new BufferedInputStream(new FileInputStream(imageFile))); + int xsize = 1; + int ysize = 1; + int zsize = 1; + double xspace = 1.0; + double yspace = 1.0; + double zspace = 1.0; + NRRDTYPE type = null; + NRRDENCODING encoding = null; + int dimension = -1; + // read header lines + while (true) { + @SuppressWarnings("deprecation") + String line = dis.readLine(); + if (line == null || line.length() == 0) { + break; + } + StringTokenizer stringTokenizer = new StringTokenizer(line, ": "); + String headerParam = stringTokenizer.nextToken(); + // System.out.println(headerParam); + if (headerParam.equals("sizes")) { + if (dimension != -1) { + xsize = Integer.parseInt(stringTokenizer.nextToken()); + if (dimension >= 2) { + ysize = Integer.parseInt(stringTokenizer.nextToken()); + } + if (dimension >= 3) { + zsize = Integer.parseInt(stringTokenizer.nextToken()); + } + for (int i = 4; i < dimension; i++) { + if (Integer.parseInt(stringTokenizer.nextToken()) != 1) { + throw new Exception("Dimensions > 3 not supported"); + } + } + } else { + throw new Exception("dimension expected to be set before reading sizes"); + } + } else if (headerParam.equals("spacings")) { + if (dimension != -1) { + xspace = Double.parseDouble(stringTokenizer.nextToken()); + if (dimension >= 2) { + yspace = Double.parseDouble(stringTokenizer.nextToken()); + } + if (dimension >= 3) { + zspace = Double.parseDouble(stringTokenizer.nextToken()); + } + // ignore other dimension spacings + } else { + throw new Exception("dimension expected to be set before reading spacings"); + } + } else if (headerParam.equals("type")) { + String nextToken = stringTokenizer.nextToken(); + if (nextToken.equalsIgnoreCase("double")) { + type = NRRDTYPE.DOUBLE; + } else if (nextToken.equalsIgnoreCase("float")) { + type = NRRDTYPE.FLOAT; + } else if (nextToken.equalsIgnoreCase("unsigned")) { + nextToken = stringTokenizer.nextToken(); + if (nextToken.equalsIgnoreCase("char")) { + type = NRRDTYPE.UNSIGNEDCHAR; + } else { + throw new Exception("Unknown nrrd data type=" + nextToken); + } + } else { + throw new Exception("Unknown nrrd data type=" + nextToken); + } + } else if (headerParam.equals("dimension")) { + dimension = Integer.parseInt(stringTokenizer.nextToken()); + if (dimension < 1) { + throw new Exception("unexpected dimension=" + dimension); + } + } else if (headerParam.equals("encoding")) { + encoding = NRRDENCODING.valueOf(stringTokenizer.nextToken().toUpperCase()); + } + } + BufferedInputStream bis = null; + if (encoding == NRRDENCODING.GZIP) { + dis.close(); + bis = new BufferedInputStream(new FileInputStream(imageFile)); + boolean bnewLine = false; + while (true) { + int currentChar = bis.read(); + if (currentChar == '\n') { + if (bnewLine) { + break;// 2 newlines end header + } + bnewLine = true; + } else { + bnewLine = false; + } + } + GZIPInputStream gzipInputStream = new GZIPInputStream(bis); + dis = new DataInputStream(gzipInputStream); + } + double[] data = new double[xsize * ysize * zsize]; + double minValue = Double.POSITIVE_INFINITY; + double maxValue = Double.NEGATIVE_INFINITY; + for (int i = 0; i < data.length; i++) { + if (i % 262144 == 0) { + if (this.getClientTaskStatusSupport() != null) { + this.getClientTaskStatusSupport().setMessage("Reading " + encoding + " " + type + + " NRRD data " + (((long) i * (long) 100) / (long) data.length) + + " % done."); + } + } + if (type == NRRDTYPE.DOUBLE) { + data[i] = dis.readDouble(); + } else if (type == NRRDTYPE.FLOAT) { + data[i] = dis.readFloat(); + } else if (type == NRRDTYPE.UNSIGNEDCHAR) { + data[i] = dis.readUnsignedByte(); + } else { + throw new Exception("Unexpected data type=" + type.toString()); + } + + minValue = Math.min(minValue, data[i]); + maxValue = Math.max(maxValue, data[i]); + } + dis.close(); + if (this.getClientTaskStatusSupport() != null) { + this.getClientTaskStatusSupport() + .setMessage("Scaling " + encoding + " " + type + " NRRD data."); + } + + short[] dataToSegment = new short[data.length]; + double scaleShort = Math.pow(2, Short.SIZE) - 1; + for (int i = 0; i < data.length; i++) { + dataToSegment[i] |= (int) ((data[i] - minValue) / (maxValue - minValue) + * scaleShort); + } + fdfos = new FieldDataFileOperationSpec(); + fdfos.origin = new Origin(0, 0, 0); + fdfos.extent = new Extent((xsize == 1 ? .5 : (xsize) * xspace), + (ysize == 1 ? .5 : (ysize) * yspace), (zsize == 1 ? .5 : (zsize) * zspace)); + fdfos.isize = new ISize(xsize, ysize, zsize); + fdfos.shortSpecData = new short[][][]{{dataToSegment}}; + } finally { + if (dis != null) { + try { + dis.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } else if ((fdfos = createFDOSFromSurfaceFile(imageFile)) != null) {// try surface file formats + // work already done at this point + } else { + File[] dirFiles = null; + ImageSizeInfo origImageSizeInfo = null; + ImageDatasetReaderService imageDatasetReaderServiceInstance = ImageDatasetReaderService + .getInstance(); + ImageDatasetReader imageDatasetReader = imageDatasetReaderServiceInstance + .getImageDatasetReader(); + if (imageFile.isDirectory()) { + dirFiles = imageFile.listFiles(new java.io.FileFilter() { + public boolean accept(File pathname) { + return pathname.isFile() && !pathname.isHidden();// exclude windows Thumbs.db + } + }); + if (dirFiles.length == 0) { + throw new Exception("No valid files in selected directory"); + } + String fileExt0 = null; + for (int i = 0; i < dirFiles.length; i++) { + int lastDot = dirFiles[i].getName().lastIndexOf('.'); + String fileExt = (lastDot != -1 ? dirFiles[i].getName().substring(lastDot) : null); + if (dirFiles[i].isDirectory()) { + fileExt = "dir"; + } + if (i == 0) { + fileExt0 = fileExt; + } else if (!Compare.isEqualOrNull(fileExt, fileExt0)) { + String result = DialogUtils.showWarningDialog(requesterComp, + "Files in '" + imageFile.getAbsolutePath() + + "' have different name extensions, continue?", + new String[]{"OK", "Cancel"}, "Cancel"); + if (!"OK".equals(result)) { + throw UserCancelException.CANCEL_FILE_SELECTION; + } + break; + } + + } + hashTable.put(IMPORT_SOURCE_NAME, "Directory: " + imageFile.getAbsolutePath()); + origImageSizeInfo = imageDatasetReader + .getImageSizeInfoForceZ(dirFiles[0].getAbsolutePath(), dirFiles.length); + if (dirFiles.length > 1) { + final String importZ = "Import Z-Sections"; + final String cancelOption = "Cancel"; + String result = DialogUtils.showWarningDialog(guiParent, + "Import all files in directory '" + imageFile.getAbsolutePath() + + "' as Z-Sections", + new String[]{importZ, cancelOption}, importZ); + if (result.equals(cancelOption)) { + throw UserCancelException.CANCEL_GENERIC; + } + } + hashTable.put(DIR_FILES, dirFiles); + } else { + origImageSizeInfo = imageDatasetReader + .getImageSizeInfoForceZ(imageFile.getAbsolutePath(), null); + hashTable.put(IMPORT_SOURCE_NAME, "File: " + imageFile.getAbsolutePath()); + } + hashTable.put(ORIG_IMAGE_SIZE_INFO, origImageSizeInfo); + return; + } + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA) { + this.getClientTaskStatusSupport().setMessage("Reading data from VCell server."); + VCDocument.GeomFromFieldDataCreationInfo docInfo = (VCDocument.GeomFromFieldDataCreationInfo) documentCreationInfo; + PDEDataContext pdeDataContext = mdiManager.getFieldDataWindowManager() + .getPDEDataContext(docInfo.getExternalDataID(), null); + ImageSizeInfo newImageSizeInfo = (ImageSizeInfo) hashTable.get(NEW_IMAGE_SIZE_INFO); + pdeDataContext.setVariableNameAndTime(docInfo.getVarName(), + newImageSizeInfo.getTimePoints()[newImageSizeInfo.getSelectedTimeIndex()]); + double[] data = pdeDataContext.getDataValues(); + hashTable.put(INITIAL_ANNOTATION, hashTable.get(IMPORT_SOURCE_NAME)); + CartesianMesh mesh = (CartesianMesh) hashTable.get(FD_MESH); + ISize meshISize = (ISize) hashTable.get(FD_MESHISIZE); + double minValue = Double.POSITIVE_INFINITY; + double maxValue = Double.NEGATIVE_INFINITY; + for (int i = 0; i < data.length; i++) { + minValue = Math.min(minValue, data[i]); + maxValue = Math.max(maxValue, data[i]); + } + short[] dataToSegment = new short[data.length]; + double scaleShort = Math.pow(2, Short.SIZE) - 1; + for (int i = 0; i < data.length; i++) { + dataToSegment[i] |= (int) ((data[i] - minValue) / (maxValue - minValue) * scaleShort); + } + fdfos = new FieldDataFileOperationSpec(); + fdfos.origin = mesh.getOrigin(); + fdfos.extent = mesh.getExtent(); + fdfos.isize = meshISize; + fdfos.shortSpecData = new short[][][]{{dataToSegment}}; + + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_SCRATCH) { + ISize isize = getISizeFromUser(guiParent, new ISize(256, 256, 8), + "Enter # of pixels for x,y,z (e.g. 3D{256,256,8}, 2D{256,256,1}, 1D{256,1,1})"); + fdfos = new FieldDataFileOperationSpec(); + fdfos.origin = new Origin(0, 0, 0); + fdfos.extent = new Extent(1, 1, 1); + fdfos.isize = isize; + hashTable.put(IMPORT_SOURCE_NAME, "Scratch: New Geometry"); + // final int SCRATCH_SIZE_LIMIT = 512*512*20; + // if(isize.getXYZ() > (SCRATCH_SIZE_LIMIT)){ + // throw new Exception("Total pixels (x*y*z) cannot be >"+SCRATCH_SIZE_LIMIT+"."); + // } + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_ANALYTIC) { + if (hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE) != null) { + Geometry workspaceGeom = (Geometry) hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE); + ISize defaultISize = workspaceGeom.getGeometrySpec().getDefaultSampledImageSize(); + ISize isize = getISizeFromUser(guiParent, defaultISize, + "Warning: converting analytic expression geometry into an image based geometry\nwill remove analytic expressions after new image is created.\n\n" + + "Enter size (x,y,z) for new geometry image (e.g. " + defaultISize.getX() + + "," + defaultISize.getY() + "," + defaultISize.getZ() + ")"); + hashTable.put(IMPORT_SOURCE_NAME, "Workspace from Analytic Geometry"); + VCImage img = workspaceGeom.getGeometrySpec().createSampledImage(isize); + Enumeration enumSubvolume = workspaceGeom.getGeometrySpec() + .getAnalyticOrCSGSubVolumes(); + ArrayList vcPixelClassArrList = new ArrayList(); + while (enumSubvolume.hasMoreElements()) { + SubVolume subVolume = enumSubvolume.nextElement(); + vcPixelClassArrList + .add(new VCPixelClass(null, subVolume.getName(), subVolume.getHandle())); + } + if (vcPixelClassArrList.size() > img.getPixelClasses().length) { + String result = DialogUtils.showOKCancelWarningDialog(requesterComp, null, + "Warning: sampling size is too small to include all subvolumes."); + if (result == null || !result.equals(SimpleUserMessage.OPTION_OK)) { + throw UserCancelException.CANCEL_GENERIC; + } + } + hashTable.put(VCPIXELCLASSES, vcPixelClassArrList.toArray(new VCPixelClass[0])); + fdfos = createFDOSFromVCImage(img); + } else { + throw new Exception("Expecting image source for GEOM_OPTION_FROM_WORKSPACE_ANALYTIC"); + } + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_IMAGE) { + if (hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE) != null) { + Geometry workspaceGeom = (Geometry) hashTable.get(ClientRequestManager.GEOM_FROM_WORKSPACE); + hashTable.put(IMPORT_SOURCE_NAME, "Workspace Image"); + fdfos = createFDOSFromVCImage(workspaceGeom.getGeometrySpec().getImage()); + if (workspaceGeom.getGeometrySpec().getImage().getDescription() != null) { + hashTable.put(INITIAL_ANNOTATION, + workspaceGeom.getGeometrySpec().getImage().getDescription()); + } + GeometryClass[] myGeometryClasses = workspaceGeom.getGeometryClasses(); + VCPixelClass[] myPixelClasses = workspaceGeom.getGeometrySpec().getImage() + .getPixelClasses(); + VCPixelClass[] newPixelClasses = new VCPixelClass[myPixelClasses.length]; + for (int i = 0; i < myPixelClasses.length; i++) { + for (int j = 0; j < myGeometryClasses.length; j++) { + if (myGeometryClasses[j] instanceof ImageSubVolume && myPixelClasses[i] + .getPixel() == ((ImageSubVolume) myGeometryClasses[j]).getPixelValue()) { + newPixelClasses[i] = new VCPixelClass(null, myGeometryClasses[j].getName(), + myPixelClasses[i].getPixel()); + break; + } + } + } + hashTable.put(VCPIXELCLASSES, newPixelClasses); + } else { + throw new Exception("Expecting image source for GEOM_OPTION_FROM_WORKSPACE"); + } + } + hashTable.put(FDFOS, fdfos); + } catch (DataFormatException ex) { + throw new Exception("Cannot read image file.\n" + ex.getMessage()); + } + } + }; + return parseImageTask; + } + + // Get image from file + public static AsynchClientTask getSelectImageFileTask(final Component requesterComp, final UserPreferences userPreferences) { + AsynchClientTask selectImageFileTask = new AsynchClientTask("select image file", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + File imageFile = DatabaseWindowManager.showFileChooserDialog(requesterComp, null, userPreferences, JFileChooser.FILES_AND_DIRECTORIES); + hashTable.put(IMAGE_FILE, imageFile); + hashTable.put(IMPORT_SOURCE_NAME, "File: " + imageFile.getName()); + } + }; + return selectImageFileTask; + } + + public static AsynchClientTask getImportFileImageTask(final VCDocument.DocumentCreationInfo documentCreationInfo) { + AsynchClientTask importFileImageTask = new AsynchClientTask("Importing Image from File...", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE && hashTable.get(FDFOS) == null) { + ImageSizeInfo origImageSizeInfo = (ImageSizeInfo) hashTable.get(ORIG_IMAGE_SIZE_INFO); + ImageSizeInfo newImageSizeInfo = (ImageSizeInfo) hashTable.get(NEW_IMAGE_SIZE_INFO); + File[] dirFiles = (File[]) hashTable.get(DIR_FILES); + File imageFile = (File) hashTable.get(IMAGE_FILE); + FieldDataFileOperationSpec fdfos = null; + boolean bMergeChannels = origImageSizeInfo.getNumChannels() != newImageSizeInfo.getNumChannels(); + ISize resize = (origImageSizeInfo.getiSize().compareEqual(newImageSizeInfo.getiSize()) ? null + : newImageSizeInfo.getiSize()); + if (dirFiles != null) { + Arrays.sort(dirFiles, new Comparator() { + public int compare(File o1, File o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }); + hashTable.put(INITIAL_ANNOTATION, dirFiles[0].getAbsolutePath() + "\n.\n.\n.\n" + + dirFiles[dirFiles.length - 1].getAbsolutePath()); + short[][] dataToSegment = null; + ISize isize = null; + Origin origin = null; + Extent extent = null; + int sizeXY = 0; + ISize firstImageISize = null; + for (int i = 0; i < dirFiles.length; i++) { + if (this.getClientTaskStatusSupport() != null) { + this.getClientTaskStatusSupport() + .setMessage("reading files " + (i + 1) + " of " + dirFiles.length); + } + ImageDataset[] imageDatasets = ImageDatasetReaderService.getInstance() + .getImageDatasetReader().readImageDatasetChannels(dirFiles[i].getAbsolutePath(), + this.getClientTaskStatusSupport(), bMergeChannels, null, resize); + for (int c = 0; c < imageDatasets.length; c++) { + if (imageDatasets[c].getSizeZ() != 1 || imageDatasets[c].getSizeT() != 1) { + throwImportWholeDirectoryException(imageFile, + dirFiles[i].getAbsolutePath() + " has Z=" + imageDatasets[c].getSizeZ() + + " T=" + imageDatasets[c].getSizeT()); + } + if (isize == null) { + firstImageISize = imageDatasets[c].getISize(); + sizeXY = imageDatasets[c].getISize().getX() * imageDatasets[c].getISize().getY(); + dataToSegment = new short[imageDatasets.length][sizeXY * dirFiles.length]; + isize = new ISize(imageDatasets[c].getISize().getX(), + imageDatasets[c].getISize().getY(), dirFiles.length); + origin = imageDatasets[c].getAllImages()[0].getOrigin(); + extent = imageDatasets[c].getExtent(); + } + if (!firstImageISize.compareEqual(imageDatasets[c].getISize())) { + throwImportWholeDirectoryException(imageFile, + dirFiles[0].getAbsolutePath() + " " + firstImageISize + " does not equal " + + dirFiles[i].getAbsolutePath() + " " + + imageDatasets[c].getISize()); + } + System.arraycopy(imageDatasets[c].getImage(0, 0, 0).getPixels(), 0, dataToSegment[c], + sizeXY * i, sizeXY); + + } + } + fdfos = new FieldDataFileOperationSpec(); + fdfos.origin = origin; + fdfos.extent = extent; + fdfos.isize = isize; + fdfos.shortSpecData = new short[][][]{dataToSegment}; + } else { + hashTable.put(INITIAL_ANNOTATION, imageFile.getAbsolutePath()); + Integer userPreferredTimeIndex = null; + if (origImageSizeInfo.getTimePoints().length > 1) { + userPreferredTimeIndex = newImageSizeInfo.getSelectedTimeIndex(); + } + if (this.getClientTaskStatusSupport() != null) { + this.getClientTaskStatusSupport().setMessage("Reading file..."); + } + ImageDataset[] imageDatasets = ImageDatasetReaderService.getInstance().getImageDatasetReader() + .readImageDatasetChannels(imageFile.getAbsolutePath(), this.getClientTaskStatusSupport(), + bMergeChannels, userPreferredTimeIndex, resize); + fdfos = ClientRequestManager.createFDOSWithChannels(imageDatasets, null); + } + hashTable.put(FDFOS, fdfos); + hashTable.remove(NEW_IMAGE_SIZE_INFO); + hashTable.remove(ORIG_IMAGE_SIZE_INFO); + hashTable.remove(DIR_FILES); + } + } + }; + return importFileImageTask; + } + + public static AsynchClientTask getResizeImageTask(final VCDocument.DocumentCreationInfo documentCreationInfo) { + AsynchClientTask resizeImageTask = new AsynchClientTask("Resizing Image...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + ImageSizeInfo newImageSizeInfo = (ImageSizeInfo) hashTable.get(NEW_IMAGE_SIZE_INFO); + FieldDataFileOperationSpec fdfos = (FieldDataFileOperationSpec) hashTable.get(FDFOS); + if (newImageSizeInfo != null && fdfos != null + && !fdfos.isize.compareEqual(newImageSizeInfo.getiSize())) { // resizeImage((FieldDataFileOperationSpec) hashTable.get(FDFOS), newImageSizeInfo.getiSize(), // documentCreationInfo.getOption()); - resize0(hashTable); - } - } - }; - return resizeImageTask; - } - - private static void resize0(Hashtable hashTable/*ImageSizeInfo sourceSize,ImageSizeInfo newSize*/) { + resize0(hashTable); + } + } + }; + return resizeImageTask; + } + + private static void resize0(Hashtable hashTable/*ImageSizeInfo sourceSize,ImageSizeInfo newSize*/) { // OrigOrigin = new Origin // CartesianMesh origMesh = CartesianMesh.createSimpleCartesianMesh(orig, extent, size, regionImage); // ISize varISize = dataProcessingOutputInfo.getVariableISize(varName); @@ -1814,1323 +1803,1315 @@ private static void resize0(Hashtable hashTable/*ImageSizeInfo sourceSize,ImageS // varExtent, // varISize, regionImage); - CartesianMesh origMesh = (CartesianMesh) hashTable.get("sourceMesh"); - CartesianMesh resampleMesh = (CartesianMesh) hashTable.get("newMesh"); - FieldDataFileOperationSpec fdfos = (FieldDataFileOperationSpec) hashTable.get(FDFOS); - double[] origData = new double[fdfos.isize.getXYZ()]; - for(int i=0;i hashTable) throws Exception { - VCDocument.GeomFromFieldDataCreationInfo docInfo = (VCDocument.GeomFromFieldDataCreationInfo) documentCreationInfo; - PDEDataContext pdeDataContext = getMdiManager().getFieldDataWindowManager() - .getPDEDataContext(docInfo.getExternalDataID(), null); - CartesianMesh mesh = pdeDataContext.getCartesianMesh(); - ISize meshISize = new ISize(mesh.getSizeX(), mesh.getSizeY(), mesh.getSizeZ()); - double[] timePoints = pdeDataContext.getTimePoints(); - hashTable.put(FD_MESH, mesh); - hashTable.put(FD_MESHISIZE, meshISize); - hashTable.put(FD_TIMEPOINTS, timePoints); - } - }; - AsynchClientTask queryImageResizeTask = new AsynchClientTask("Query File Image Resize...", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - String importSourceName = (String) hashTable.get(IMPORT_SOURCE_NAME); - if ((ImageSizeInfo) hashTable.get(ORIG_IMAGE_SIZE_INFO) != null) {// from file - ImageSizeInfo newImagesiSizeInfo = queryImageResize(requester.getComponent(), - (ImageSizeInfo) hashTable.get(ORIG_IMAGE_SIZE_INFO), true); - hashTable.put(NEW_IMAGE_SIZE_INFO, newImagesiSizeInfo); - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA) {// from fielddata - VCDocument.GeomFromFieldDataCreationInfo docInfo = (VCDocument.GeomFromFieldDataCreationInfo) documentCreationInfo; - double[] fieldDataTimes = (double[]) hashTable.get(FD_TIMEPOINTS); - hashTable.remove(FD_TIMEPOINTS); - ISize fieldDataISize = (ISize) hashTable.get(FD_MESHISIZE); - ImageSizeInfo origImageSizeInfo = new ImageSizeInfo(importSourceName, fieldDataISize, 1, - fieldDataTimes, null); - ImageSizeInfo newImagesiSizeInfo = queryImageResize(requester.getComponent(), origImageSizeInfo, - true); - hashTable.put(NEW_IMAGE_SIZE_INFO, newImagesiSizeInfo); - hashTable.put(IMPORT_SOURCE_NAME, - "FieldData: " + docInfo.getExternalDataID().getName() + " varName=" + docInfo.getVarName() - + " timeIndex=" - + newImagesiSizeInfo.getTimePoints()[newImagesiSizeInfo.getSelectedTimeIndex()]); - } - } - }; - - AsynchClientTask importFileImageTask = getImportFileImageTask(documentCreationInfo); - - AsynchClientTask resizeImageTask = getResizeImageTask(documentCreationInfo); - - AsynchClientTask finishTask = new AsynchClientTask("Finishing...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(final Hashtable hashTable) throws Exception { - getClientTaskStatusSupport().setMessage("Initializing..."); - final ROIMultiPaintManager roiMultiPaintManager = new ROIMultiPaintManager(); - roiMultiPaintManager.setDocumentManager(ClientRequestManager.this.getDocumentManager()); - roiMultiPaintManager.initROIAndUnderlay((FieldDataFileOperationSpec) hashTable.get(FDFOS)); - final Geometry[] geomHolder = new Geometry[1]; - final VCPixelClass[] postProcessPixelClasses = (VCPixelClass[]) hashTable.get(VCPIXELCLASSES); - AsynchClientTask task1 = new AsynchClientTask("edit geometry", AsynchClientTask.TASKTYPE_SWING_BLOCKING, - false) { - - @Override - public void run(Hashtable hashTable) throws Exception { - geomHolder[0] = roiMultiPaintManager.showGUI(okButtonText, - (String) hashTable.get(IMPORT_SOURCE_NAME), (Component) hashTable.get(GUI_PARENT), - (String) hashTable.get(INITIAL_ANNOTATION), postProcessPixelClasses, - getUserPreferences(), - (hashTable.get(BioModelWindowManager.FIELD_DATA_FLAG)==null?false:((Boolean)hashTable.get(BioModelWindowManager.FIELD_DATA_FLAG)).booleanValue())); - } - }; - AsynchClientTask task2 = new AsynchClientTask("update geometry", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - // Create default name for image - String dateTimeString = BeanUtils.generateDateTimeString(); - geomHolder[0].getGeometrySpec().getImage().setName("img_" + dateTimeString); - geomHolder[0].setName("geom_" + dateTimeString); - // cause update in this thread so later swing threads won't be delayed - geomHolder[0].precomputeAll(new GeometryThumbnailImageFactoryAWT()); - hashTable.put("doc", geomHolder[0]); - } - }; - - AsynchClientTask[] finalTasks = afterTasks; - if (finalTasks == null) { - finalTasks = new AsynchClientTask[] { getSaveImageAndGeometryTask() }; - } - AsynchClientTask[] tasks = new AsynchClientTask[2 + finalTasks.length]; - tasks[0] = task1; - tasks[1] = task2; - System.arraycopy(finalTasks, 0, tasks, 2, finalTasks.length); - ClientTaskDispatcher.dispatch((Component) hashTable.get(GUI_PARENT), hashTable, tasks, false, false, - null, true); - } - }; - Vector tasksV = new Vector(); - if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_SCRATCH) { - tasksV.addAll(Arrays.asList(new AsynchClientTask[] { parseImageTask, finishTask })); - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_ANALYTIC) { - tasksV.addAll(Arrays.asList(new AsynchClientTask[] { parseImageTask, finishTask })); - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_IMAGE) { - tasksV.addAll(Arrays.asList(new AsynchClientTask[] { parseImageTask, resizeImageTask, finishTask })); - } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE) { - tasksV.addAll(Arrays.asList(new AsynchClientTask[] { selectImageFileTask, parseImageTask, - queryImageResizeTask, importFileImageTask/* resizes */, finishTask })); - } + } + + public AsynchClientTask[] createNewGeometryTasks(final TopLevelWindowManager requester, + final VCDocument.DocumentCreationInfo documentCreationInfo, final AsynchClientTask[] afterTasks, + final String okButtonText) { + + if (!isImportGeometryType(documentCreationInfo)) { + throw new IllegalArgumentException("Analytic geometry not implemented."); + + } + + AsynchClientTask selectImageFileTask = getSelectImageFileTask(requester.getComponent(), this.getUserPreferences()); + + final String INITIAL_ANNOTATION = "INITIAL_ANNOTATION"; + final String NEW_IMAGE_SIZE_INFO = "NEW_IMAGE_SIZE_INFO"; + final String FD_TIMEPOINTS = "FD_TIMEPOINTS"; + + AsynchClientTask parseImageTask = getParseImageTask(requester.getComponent(), documentCreationInfo, this.getMdiManager()); + + AsynchClientTask getFieldDataImageParams = new AsynchClientTask("Getting DB Image parameters...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + VCDocument.GeomFromFieldDataCreationInfo docInfo = (VCDocument.GeomFromFieldDataCreationInfo) documentCreationInfo; + PDEDataContext pdeDataContext = ClientRequestManager.this.getMdiManager().getFieldDataWindowManager() + .getPDEDataContext(docInfo.getExternalDataID(), null); + CartesianMesh mesh = pdeDataContext.getCartesianMesh(); + ISize meshISize = new ISize(mesh.getSizeX(), mesh.getSizeY(), mesh.getSizeZ()); + double[] timePoints = pdeDataContext.getTimePoints(); + hashTable.put(FD_MESH, mesh); + hashTable.put(FD_MESHISIZE, meshISize); + hashTable.put(FD_TIMEPOINTS, timePoints); + } + }; + AsynchClientTask queryImageResizeTask = new AsynchClientTask("Query File Image Resize...", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + String importSourceName = (String) hashTable.get(IMPORT_SOURCE_NAME); + if (hashTable.get(ORIG_IMAGE_SIZE_INFO) != null) {// from file + ImageSizeInfo newImagesiSizeInfo = queryImageResize(requester.getComponent(), + (ImageSizeInfo) hashTable.get(ORIG_IMAGE_SIZE_INFO), true); + hashTable.put(NEW_IMAGE_SIZE_INFO, newImagesiSizeInfo); + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA) {// from fielddata + VCDocument.GeomFromFieldDataCreationInfo docInfo = (VCDocument.GeomFromFieldDataCreationInfo) documentCreationInfo; + double[] fieldDataTimes = (double[]) hashTable.get(FD_TIMEPOINTS); + hashTable.remove(FD_TIMEPOINTS); + ISize fieldDataISize = (ISize) hashTable.get(FD_MESHISIZE); + ImageSizeInfo origImageSizeInfo = new ImageSizeInfo(importSourceName, fieldDataISize, 1, + fieldDataTimes, null); + ImageSizeInfo newImagesiSizeInfo = queryImageResize(requester.getComponent(), origImageSizeInfo, + true); + hashTable.put(NEW_IMAGE_SIZE_INFO, newImagesiSizeInfo); + hashTable.put(IMPORT_SOURCE_NAME, + "FieldData: " + docInfo.getExternalDataID().getName() + " varName=" + docInfo.getVarName() + + " timeIndex=" + + newImagesiSizeInfo.getTimePoints()[newImagesiSizeInfo.getSelectedTimeIndex()]); + } + } + }; + + AsynchClientTask importFileImageTask = getImportFileImageTask(documentCreationInfo); + + AsynchClientTask resizeImageTask = getResizeImageTask(documentCreationInfo); + + AsynchClientTask finishTask = new AsynchClientTask("Finishing...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(final Hashtable hashTable) throws Exception { + this.getClientTaskStatusSupport().setMessage("Initializing..."); + final ROIMultiPaintManager roiMultiPaintManager = new ROIMultiPaintManager(); + roiMultiPaintManager.setDocumentManager(ClientRequestManager.this.getDocumentManager()); + roiMultiPaintManager.initROIAndUnderlay((FieldDataFileOperationSpec) hashTable.get(FDFOS)); + final Geometry[] geomHolder = new Geometry[1]; + final VCPixelClass[] postProcessPixelClasses = (VCPixelClass[]) hashTable.get(VCPIXELCLASSES); + AsynchClientTask task1 = new AsynchClientTask("edit geometry", AsynchClientTask.TASKTYPE_SWING_BLOCKING, + false) { + + @Override + public void run(Hashtable hashTable) throws Exception { + geomHolder[0] = roiMultiPaintManager.showGUI(okButtonText, + (String) hashTable.get(IMPORT_SOURCE_NAME), (Component) hashTable.get(GUI_PARENT), + (String) hashTable.get(INITIAL_ANNOTATION), postProcessPixelClasses, + ClientRequestManager.this.getUserPreferences(), + (hashTable.get(BioModelWindowManager.FIELD_DATA_FLAG) != null && ((Boolean) hashTable.get(BioModelWindowManager.FIELD_DATA_FLAG)).booleanValue())); + } + }; + AsynchClientTask task2 = new AsynchClientTask("update geometry", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + // Create default name for image + String dateTimeString = BeanUtils.generateDateTimeString(); + geomHolder[0].getGeometrySpec().getImage().setName("img_" + dateTimeString); + geomHolder[0].setName("geom_" + dateTimeString); + // cause update in this thread so later swing threads won't be delayed + geomHolder[0].precomputeAll(new GeometryThumbnailImageFactoryAWT()); + hashTable.put("doc", geomHolder[0]); + } + }; + + AsynchClientTask[] finalTasks = afterTasks; + if (finalTasks == null) { + finalTasks = new AsynchClientTask[]{ClientRequestManager.this.getSaveImageAndGeometryTask()}; + } + AsynchClientTask[] tasks = new AsynchClientTask[2 + finalTasks.length]; + tasks[0] = task1; + tasks[1] = task2; + System.arraycopy(finalTasks, 0, tasks, 2, finalTasks.length); + ClientTaskDispatcher.dispatch((Component) hashTable.get(GUI_PARENT), hashTable, tasks, false, false, + null, true); + } + }; + Vector tasksV = new Vector(); + if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_SCRATCH) { + tasksV.addAll(Arrays.asList(parseImageTask, finishTask)); + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_ANALYTIC) { + tasksV.addAll(Arrays.asList(parseImageTask, finishTask)); + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FROM_WORKSPACE_IMAGE) { + tasksV.addAll(Arrays.asList(parseImageTask, resizeImageTask, finishTask)); + } else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FILE) { + tasksV.addAll(Arrays.asList(selectImageFileTask, parseImageTask, + queryImageResizeTask, importFileImageTask/* resizes */, finishTask)); + } // else if(documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIJI_IMAGEJ || documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_BLENDER){ // tasksV.addAll(Arrays.asList(new AsynchClientTask[] {parseImageTask,queryImageResizeTask,importFileImageTask/*resizes*/,finishTask})); // } - else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA) { - tasksV.addAll(Arrays.asList(new AsynchClientTask[] { getFieldDataImageParams, queryImageResizeTask, - parseImageTask, resizeImageTask, finishTask })); - } - return tasksV.toArray(new AsynchClientTask[0]); - } - - public static ISize getISizeFromUser(Component guiParent, ISize initISize, String textMessage) - throws UserCancelException { - Integer imageDimension = (initISize == null ? null - : (initISize.getX() != 1 ? 1 : 0) + (initISize.getY() != 1 ? 1 : 0) + (initISize.getZ() != 1 ? 1 : 0)); - if (imageDimension != null && (imageDimension < 1 || imageDimension > 3)) { - throw new IllegalArgumentException("Dimension must be 1, 2 or 3."); - } - try { - int xsize = (imageDimension == null ? -1 : initISize.getX()); - int ysize = (imageDimension == null ? -1 : initISize.getY()); - int zsize = (imageDimension == null ? -1 : initISize.getZ()); - do { - String result = (imageDimension == null ? "256,256,8" : xsize + "," + ysize + "," + zsize); - result = DialogUtils.showInputDialog0(guiParent, textMessage, result); - String tempResult = result; - try { - if (result == null || result.length() == 0) { - result = ""; - throw new Exception("No size values entered."); - } - xsize = Integer.parseInt(tempResult.substring(0, tempResult.indexOf(","))); - tempResult = tempResult.substring(tempResult.indexOf(",") + 1, tempResult.length()); - ysize = Integer.parseInt(tempResult.substring(0, tempResult.indexOf(","))); - tempResult = tempResult.substring(tempResult.indexOf(",") + 1, tempResult.length()); - zsize = Integer.parseInt(tempResult); - if (imageDimension != null) { - if (imageDimension == 2 && zsize != 1) { - throw new Exception("Dimension " + imageDimension + " must have z = 1."); - } else if (imageDimension == 1 && zsize != 1 && ysize != 1) { - throw new Exception("Dimension " + imageDimension + " must have z = 1 and y = 1."); - } - } - ISize isize = new ISize(xsize, ysize, zsize); - if (isize.getXYZ() <= 0) { - throw new Exception("Total pixels (" + xsize + "*" + ysize + "*" + zsize + ") cannot be <=0."); - } - return isize; - } catch (Exception e) { - DialogUtils.showErrorDialog(guiParent, "Error entering starting sizes\n" + e.getMessage(), e); - } - } while (true); - } catch (UtilCancelException e2) { - throw UserCancelException.CANCEL_GENERIC; - } - - } - - public static ImageSizeInfo queryImageResize(final Component requester, final ImageSizeInfo origImageSizeInfo, - boolean bFullMode) { - ImageResizePanel imageResizePanel = new ImageResizePanel(); - imageResizePanel.init(origImageSizeInfo, bFullMode); - imageResizePanel.setPreferredSize(new Dimension(400, 200)); - while (true) { - int flag = DialogUtils.showComponentOKCancelDialog(requester, imageResizePanel, - "Optionally convert imported images."); - if (flag != JOptionPane.OK_OPTION) { - throw UserCancelException.CANCEL_GENERIC; - } - try { - ImageSizeInfo imagesizeInfo = imageResizePanel.getNewImageSizeInfo(); - return imagesizeInfo; - } catch (Exception e) { - e.printStackTrace(); - DialogUtils.showErrorDialog(requester, "Error getting x,y,z: " + e.getMessage()); - } - } - } - - private static void resizeImage(FieldDataFileOperationSpec fdfos, ISize newImagesISize, int imageType) - throws Exception { - final int ORIG_XYSIZE = fdfos.isize.getX() * fdfos.isize.getY(); - try { - int xsize = newImagesISize.getX(); - int ysize = newImagesISize.getY(); - double scaleFactor = (double) newImagesISize.getX() / (double) fdfos.isize.getX(); - if (xsize != fdfos.isize.getX() || ysize != fdfos.isize.getY()) { - int numChannels = fdfos.shortSpecData[0].length;// this normally contains different variables but is - // used for channels here - // resize each z section to xsize,ysize - AffineTransform scaleAffineTransform = AffineTransform.getScaleInstance(scaleFactor, scaleFactor); - AffineTransformOp scaleAffineTransformOp = new AffineTransformOp(scaleAffineTransform, - AffineTransformOp.TYPE_NEAREST_NEIGHBOR); - short[][][] resizeData = new short[1][numChannels][fdfos.isize.getZ() * xsize * ysize]; - for (int c = 0; c < numChannels; c++) { - BufferedImage originalImage = new BufferedImage(fdfos.isize.getX(), fdfos.isize.getY(), - BufferedImage.TYPE_USHORT_GRAY); - BufferedImage scaledImage = new BufferedImage(xsize, ysize, BufferedImage.TYPE_USHORT_GRAY); - for (int z = 0; z < fdfos.isize.getZ(); z++) { - short[] originalImageBuffer = ((DataBufferUShort) (originalImage.getRaster().getDataBuffer())) - .getData(); - System.arraycopy(fdfos.shortSpecData[0][c], z * ORIG_XYSIZE, originalImageBuffer, 0, - ORIG_XYSIZE); - scaleAffineTransformOp.filter(originalImage, scaledImage); - short[] scaledImageBuffer = ((DataBufferUShort) (scaledImage.getRaster().getDataBuffer())) - .getData(); - System.arraycopy(scaledImageBuffer, 0, resizeData[0][c], z * xsize * ysize, xsize * ysize); - } - } - fdfos.isize = new ISize(xsize, ysize, fdfos.isize.getZ()); - fdfos.shortSpecData = resizeData; - } - } catch (Exception e) { - throw new Exception("Error scaling imported image:\n" + e.getMessage()); - } - } - - public AsynchClientTask[] createNewDocument(final TopLevelWindowManager requester, - final VCDocument.DocumentCreationInfo documentCreationInfo) {// throws UserCancelException, Exception { - /* asynchronous and not blocking any window */ - AsynchClientTask[] taskArray = null; - - final int createOption = documentCreationInfo.getOption(); - switch (documentCreationInfo.getDocumentType()) { - case BIOMODEL_DOC: { - AsynchClientTask task1 = new AsynchClientTask("creating biomodel", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - BioModel bioModel = createDefaultBioModelDocument(null); - hashTable.put("doc", bioModel); - } - }; - taskArray = new AsynchClientTask[] { task1 }; - break; - } - case MATHMODEL_DOC: { - if ((createOption == VCDocument.MATH_OPTION_NONSPATIAL) - || (createOption == VCDocument.MATH_OPTION_SPATIAL_EXISTS)) { - AsynchClientTask task2 = new AsynchClientTask("creating mathmodel", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry geometry = null; - if (createOption == VCDocument.MATH_OPTION_NONSPATIAL) { - geometry = new Geometry("Untitled", 0); - } else { - geometry = (Geometry) hashTable.get(GEOMETRY_KEY); - } - MathModel mathModel = createMathModel("Untitled", geometry); - mathModel.setName("MathModel" + (getMdiManager().getNumCreatedDocumentWindows() + 1)); - hashTable.put("doc", mathModel); - } - }; - if (createOption == VCDocument.MATH_OPTION_SPATIAL_EXISTS) { - AsynchClientTask task1 = createSelectDocTask(requester); - AsynchClientTask task1b = createSelectLoadGeomTask(requester); - taskArray = new AsynchClientTask[] { task1, task1b, task2 }; - } else { - taskArray = new AsynchClientTask[] { task2 }; - } - break; - } else if (createOption == VCDocument.MATH_OPTION_FROMBIOMODELAPP) { - - AsynchClientTask task1 = new AsynchClientTask("select biomodel application", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - // spatial or non-spatial - BioModelInfo bioModelInfo = (BioModelInfo) DialogUtils.getDBTreePanelSelection( - requester.getComponent(), - getMdiManager().getDatabaseWindowManager().getBioModelDbTreePanel(), "Open", - "Select BioModel"); - if (bioModelInfo != null) { // may throw UserCancelException - hashTable.put("bioModelInfo", bioModelInfo); - } - } - }; - AsynchClientTask task2 = new AsynchClientTask("find sim contexts in biomodel application", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - // spatial or non-spatial - // Get the simContexts in the corresponding BioModel - BioModelInfo bioModelInfo = (BioModelInfo) hashTable.get("bioModelInfo"); - SimulationContext[] simContexts = getDocumentManager().getBioModel(bioModelInfo) - .getSimulationContexts(); - if (simContexts != null) { // may throw UserCancelException - hashTable.put("simContexts", simContexts); - } - } - }; - AsynchClientTask task3 = new AsynchClientTask("create math model from biomodel application", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - SimulationContext[] simContexts = (SimulationContext[]) hashTable.get("simContexts"); - String[] simContextNames = new String[simContexts.length]; - - if (simContextNames.length == 0) { - throw new RuntimeException("no application is available"); - } else { - for (int i = 0; i < simContexts.length; i++) { - simContextNames[i] = simContexts[i].getName(); - } - Component component = requester.getComponent(); - // Get the simContext names, so that user can choose which simContext math to - // import - String simContextChoice = (String) PopupGenerator.showListDialog(component, simContextNames, - "Please select Application"); - if (simContextChoice == null) { - throw UserCancelException.CANCEL_DB_SELECTION; - } - SimulationContext chosenSimContext = null; - for (int i = 0; i < simContexts.length; i++) { - if (simContexts[i].getName().equals(simContextChoice)) { - chosenSimContext = simContexts[i]; - break; - } - } - Objects.requireNonNull(chosenSimContext); - - BioModelInfo bioModelInfo = (BioModelInfo) hashTable.get("bioModelInfo"); - // Get corresponding mathDesc to create new mathModel and return. - String newName = bioModelInfo.getVersion().getName() + "_" + chosenSimContext.getName(); - MathDescription bioMathDesc = chosenSimContext.getMathDescription(); - MathDescription newMathDesc = null; - newMathDesc = new MathDescription(newName + "_" + (new Random()).nextInt()); - - newMathDesc.setGeometry(bioMathDesc.getGeometry()); - newMathDesc.read_database(new CommentStringTokenizer(bioMathDesc.getVCML_database())); - newMathDesc.isValid(); - - MathModel newMathModel = new MathModel(null); - newMathModel.setName(newName); - newMathModel.setMathDescription(newMathDesc); - hashTable.put("doc", newMathModel); - } - } - }; - taskArray = new AsynchClientTask[] { task1, task2, task3 }; - break; - } else { - throw new RuntimeException( - "Unknown MathModel Document creation option value=" + documentCreationInfo.getOption()); - } - } - case GEOMETRY_DOC: { - if (createOption == VCDocument.GEOM_OPTION_1D || createOption == VCDocument.GEOM_OPTION_2D - || createOption == VCDocument.GEOM_OPTION_3D) { - // analytic - AsynchClientTask task1 = new AsynchClientTask("creating analytic geometry", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry geometry = new Geometry( - "Geometry" + (getMdiManager().getNumCreatedDocumentWindows() + 1), - documentCreationInfo.getOption()); - geometry.getGeometrySpec() - .addSubVolume(new AnalyticSubVolume("subdomain0", new Expression(1.0))); - geometry.precomputeAll(new GeometryThumbnailImageFactoryAWT()); - hashTable.put("doc", geometry); - } - }; - taskArray = new AsynchClientTask[] { task1 }; - break; - } - if (createOption == VCDocument.GEOM_OPTION_CSGEOMETRY_3D) { - // constructed solid geometry - AsynchClientTask task1 = new AsynchClientTask("creating constructed solid geometry", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry geometry = new Geometry( - "Geometry" + (getMdiManager().getNumCreatedDocumentWindows() + 1), 3); - Extent extent = geometry.getExtent(); - if (extent != null) { - // create a CSGPrimitive of type cube and scale it to the 'extent' components. - // Use this as the default or background CSGObject (subdomain). - // This can be considered as the equivalent of subdomain (with expression) 1.0 - // for analyticSubvolume. - // basic cube - CSGPrimitive cube = new CSGPrimitive("cube", CSGPrimitive.PrimitiveType.CUBE); - // scaled cube - double x = extent.getX(); - double y = extent.getY(); - double z = extent.getZ(); - CSGScale scaledCube = new CSGScale("scale", new Vect3d(x / 2.0, y / 2.0, z / 2.0)); - scaledCube.setChild(cube); - // translated scaled cube - CSGTranslation translatedScaledCube = new CSGTranslation("translation", - new Vect3d(x / 2, y / 2, z / 2)); - translatedScaledCube.setChild(scaledCube); - CSGObject csgObject = new CSGObject(null, "subdomain0", 0); - csgObject.setRoot(translatedScaledCube); - geometry.getGeometrySpec().addSubVolume(csgObject, false); - geometry.precomputeAll(new GeometryThumbnailImageFactoryAWT()); - hashTable.put("doc", geometry); - } - } - }; - taskArray = new AsynchClientTask[] { task1 }; - break; - } else { - throw new RuntimeException( - "Unknown Geometry Document creation option value=" + documentCreationInfo.getOption()); - } - } - default: { - throw new RuntimeException("Unknown default document type: " + documentCreationInfo.getDocumentType()); - } - } - return taskArray; - } - - private static final int MAX_NUMBER_OF_COLORS_IMPORTED_FILE = 256; - - public static VCImage createVCImageFromUnsignedShorts(short[] dataToSegment, Extent extent, ISize isize, - BitSet uniquePixelBS) throws Exception { - // auto segment - - int minVal = dataToSegment[0] & 0x0000FFFF; - int maxVal = minVal; - for (int i = 0; i < dataToSegment.length; i++) { - int usIntVal = (int) (dataToSegment[i] & 0x0000FFFF); - minVal = Math.min(usIntVal, minVal); - maxVal = Math.max(usIntVal, maxVal); - } - byte[] byteData = new byte[dataToSegment.length]; - - if (maxVal >= MAX_NUMBER_OF_COLORS_IMPORTED_FILE) { - if (uniquePixelBS.cardinality() <= MAX_NUMBER_OF_COLORS_IMPORTED_FILE) { - int index = 0; - int[] indexRef = new int[(int) Math.pow(2, Short.SIZE)]; - Arrays.fill(indexRef, -1); - for (int i = 0; i < indexRef.length; i++) { - if (uniquePixelBS.get(i)) { - indexRef[i] = index; - index++; - } - } - for (int i = 0; i < dataToSegment.length; i++) { - byteData[i] = (byte) indexRef[(int) (dataToSegment[i] & 0x0000FFFF)]; - } - } else { - for (int i = 0; i < dataToSegment.length; i++) { - byteData[i] = (byte) (0xFF & (int) ((double) (dataToSegment[i] - minVal) - / (double) (maxVal - minVal) * (MAX_NUMBER_OF_COLORS_IMPORTED_FILE - 1))); - } - } - } else { - for (int i = 0; i < byteData.length; i++) { - byteData[i] = (byte) (dataToSegment[i] & 0xFF); - } - } - VCImage autoSegmentVCImage = new VCImageUncompressed(null, byteData, extent, isize.getX(), isize.getY(), - isize.getZ()); - return autoSegmentVCImage; - - } - - public void curateDocument(final VCDocumentInfo documentInfo, final int curateType, - final TopLevelWindowManager requester) { - - if (documentInfo != null) { - // see if we have this open - String documentID = documentInfo.getVersion().getVersionKey().toString(); - if (getMdiManager().haveWindow(documentID)) { - // already open, refuse - PopupGenerator.showErrorDialog(requester, - "Selected edition is open, cannot " + CurateSpec.CURATE_TYPE_NAMES[curateType]); - return; - } else { - // don't have it open, try to CURATE it - int confirm = PopupGenerator.showComponentOKCancelDialog(requester.getComponent(), - new JTextArea(CurateSpec.CURATE_TYPE_ACTIONS[curateType] - + " cannot be undone without VCELL administrative assistance.\n" - + CurateSpec.CURATE_TYPE_STATES[curateType] - + " versions of documents cannot be deleted without VCELL administrative assistance.\n" - + (curateType == CurateSpec.PUBLISH ? CurateSpec.CURATE_TYPE_STATES[curateType] - + " versions of documents MUST remain publically accessible to other VCELL users.\n" - : "") - + "Do you want to " + CurateSpec.CURATE_TYPE_NAMES[curateType] + " document '" - + documentInfo.getVersion().getName() + "'" + "\nwith version date '" - + documentInfo.getVersion().getDate().toString() + "'?"), - "WARNING -- " + CurateSpec.CURATE_TYPE_ACTIONS[curateType] + " operation cannot be undone"); - if (confirm == JOptionPane.OK_OPTION) { - AsynchClientTask task1 = new AsynchClientTask( - CurateSpec.CURATE_TYPE_ACTIONS[curateType] + " document...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - if (documentInfo instanceof BioModelInfo) { - getDocumentManager().curate(new CurateSpec((BioModelInfo) documentInfo, curateType)); - } else if (documentInfo instanceof MathModelInfo) { - getDocumentManager().curate(new CurateSpec((MathModelInfo) documentInfo, curateType)); - } else { - throw new RuntimeException(CurateSpec.CURATE_TYPE_ACTIONS[curateType] - + " not supported for VCDocumentInfo type " - + documentInfo.getClass().getName()); - } - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), - new AsynchClientTask[] { task1 }, false); - } else { - // user canceled - return; - } - } - } else { - // nothing selected - return; - } - } - - public void deleteDocument(final VCDocumentInfo documentInfo, final TopLevelWindowManager requester) { - deleteDocument(documentInfo, requester, false); - } - - public void deleteDocument(final VCDocumentInfo documentInfo, final TopLevelWindowManager requester, - boolean bDontAsk) { - if (documentInfo != null) { - // see if we have this open - String documentID = documentInfo.getVersion().getVersionKey().toString(); - if (getMdiManager().haveWindow(documentID)) { - // already open, refuse - PopupGenerator.showErrorDialog(requester, "Selected edition is open, cannot delete"); - return; - } else { - // don't have it open, try to delete it - String confirm = UserMessage.OPTION_CANCEL; - if (bDontAsk) { - confirm = UserMessage.OPTION_DELETE; - } else { - SimpleDateFormat sdf = new SimpleDateFormat(BeanUtils.vcDateFormat); - confirm = PopupGenerator.showWarningDialog(requester, getUserPreferences(), - UserMessage.warn_deleteDocument, documentInfo.getVersion().getName() + " " - + sdf.format(documentInfo.getVersion().getDate())); - } - if (confirm.equals(UserMessage.OPTION_DELETE)) { - AsynchClientTask task1 = new AsynchClientTask("Deleting document...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - if (documentInfo instanceof BioModelInfo) { - getDocumentManager().delete((BioModelInfo) documentInfo); - } else if (documentInfo instanceof MathModelInfo) { - getDocumentManager().delete((MathModelInfo) documentInfo); - } else if (documentInfo instanceof GeometryInfo) { - getDocumentManager().delete((GeometryInfo) documentInfo); - } else { - throw new RuntimeException("delete not supported for VCDocumentInfo type " - + documentInfo.getClass().getName()); - } - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), - new AsynchClientTask[] { task1 }, false); - } else { - // user canceled - return; - } - } - } else { - // nothing selected - return; - } - } - - /** - * hashtable key for data bytes of file - */ - private final static String BYTES_KEY = "bytes"; - - /** - * Comment - */ - public static void downloadExportedData(final Component requester, final UserPreferences userPrefs, - final ExportEvent evt) { - TreeSet exportsRecord = getExportsRecord(); - if (exportsRecord.contains(evt.getJobID() + "")) { - return; - } - if (evt.getLocation().toLowerCase().endsWith("." + N5Specs.n5Suffix)){ - return; - } - AsynchClientTask task1 = new AsynchClientTask("Retrieving data from '" + evt.getLocation() + "'", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - final Exception[] excArr = new Exception[] { null }; - final boolean[] bFlagArr = new boolean[] { false }; - final ByteArrayOutputStream[] baosArr = new ByteArrayOutputStream[1]; - final HttpGet[] httpGetArr = new HttpGet[1]; - // Start download of exported file in separate thread that is interruptible - // (apache HTTPClient) - Thread interruptible = new Thread(new Runnable() { - @Override - public void run() { - if (getClientTaskStatusSupport() != null) { - getClientTaskStatusSupport().setMessage("downloading data..."); - } - CloseableHttpClient httpclient = HttpClients.createDefault(); - httpGetArr[0] = new HttpGet(evt.getLocation()); - CloseableHttpResponse response = null; - try { - response = httpclient.execute(httpGetArr[0]); - if (response.getStatusLine() != null - && (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)) { - throw new Exception( - evt.getLocation() + " " + response.getStatusLine().getReasonPhrase()); - } - HttpEntity entity = response.getEntity(); - if (entity != null) { - long size = entity.getContentLength(); - InputStream instream = entity.getContent(); - try { - if (size > 0) { - baosArr[0] = new ByteArrayOutputStream((int) size); - } else { - baosArr[0] = new ByteArrayOutputStream(); - } - IOUtils.copy(instream, baosArr[0]); - } finally { - instream.close(); - } - } - - } catch (Exception e) { - excArr[0] = e; - } finally { - if (response != null) { - try { - response.close(); - } catch (Exception e) { - } - } - if (httpclient != null) { - try { - httpclient.close(); - } catch (Exception e) { - } - } - bFlagArr[0] = true; - } - } - }); - interruptible.start(); - // Wait for download to 1-finish, 2-fail or 3-be cancelled by user - while (!bFlagArr[0]) { - if (getClientTaskStatusSupport() != null && getClientTaskStatusSupport().isInterrupted()) {// user - // cancelled - if (httpGetArr[0] != null) { - httpGetArr[0].abort(); - } - throw UserCancelException.CANCEL_GENERIC; - } - try { - Thread.sleep(500); - } catch (InterruptedException e) {// caused by pressing 'cancel' button on progresspopup - if (httpGetArr[0] != null) { - httpGetArr[0].abort(); - } - if (getClientTaskStatusSupport() != null && getClientTaskStatusSupport().isInterrupted()) { - throw UserCancelException.CANCEL_GENERIC; - } - } - } - if (excArr[0] != null) {// download failed - throw excArr[0]; - } - // - // finished downloading, either save to file or send to ImageJ directly - // - if (evt.getFormat() == null || !evt.getFormat().equals("IMAGEJ")) { - // save for file save operations - hashTable.put(BYTES_KEY, baosArr[0].toByteArray()); - } - } - }; - AsynchClientTask task2 = new AsynchClientTask("selecting file to save", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - // user pref could be null if trying local export - String defaultPath = getPreferredPath(userPrefs); - final VCFileChooser fileChooser = new VCFileChooser(defaultPath); - fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.setMultiSelectionEnabled(false); - String name = evt.getDataIdString(); - String suffix = null; - if (evt.getLocation().toLowerCase().endsWith(".mov")) { - fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_MOV); - fileChooser.setFileFilter(FileFilters.FILE_FILTER_MOV); - - suffix = "_exported.mov"; - } else if (evt.getLocation().toLowerCase().endsWith(".gif")) { - fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_GIF); - fileChooser.setFileFilter(FileFilters.FILE_FILTER_GIF); - - suffix = "_exported.gif"; - } else if (evt.getLocation().toLowerCase().endsWith(".jpeg")) { - fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_JPEG); - fileChooser.setFileFilter(FileFilters.FILE_FILTER_JPEG); - - suffix = "_exported.jpeg"; - } else if (evt.getLocation().toLowerCase().endsWith(".hdf5")) { - fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_HDF5); - fileChooser.setFileFilter(FileFilters.FILE_FILTER_HDF5); - - suffix = "_exported.hdf5"; - } else { - fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_ZIP); - fileChooser.setFileFilter(FileFilters.FILE_FILTER_ZIP); - - suffix = "_exported.zip"; - } - File file = new File(name + suffix); - if (file.exists()) { - int count = 0; - do { - file = new File(name + "_" + count + suffix); - count++; - } while (file.exists()); - } - - fileChooser.setSelectedFile(file); - fileChooser.setDialogTitle("Save exported dataset..."); - int approve = fileChooser.showSaveDialog(requester); - if (approve == JFileChooser.APPROVE_OPTION) { - hashTable.put("selectedFile", fileChooser.getSelectedFile()); - } else { - fileChooser.setSelectedFile(null); - } - } - }; - AsynchClientTask task3 = new AsynchClientTask("saving to file", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - addExportRecord(evt.getJobID() + ""); - - File selectedFile = (File) hashTable.get("selectedFile"); - if (selectedFile == null) { - return; - } - setPreferredPath(userPrefs, selectedFile); + else if (documentCreationInfo.getOption() == VCDocument.GEOM_OPTION_FIELDDATA) { + tasksV.addAll(Arrays.asList(getFieldDataImageParams, queryImageResizeTask, + parseImageTask, resizeImageTask, finishTask)); + } + return tasksV.toArray(new AsynchClientTask[0]); + } + + public static ISize getISizeFromUser(Component guiParent, ISize initISize, String textMessage) + throws UserCancelException { + Integer imageDimension = (initISize == null ? null + : (initISize.getX() != 1 ? 1 : 0) + (initISize.getY() != 1 ? 1 : 0) + (initISize.getZ() != 1 ? 1 : 0)); + if (imageDimension != null && (imageDimension < 1 || imageDimension > 3)) { + throw new IllegalArgumentException("Dimension must be 1, 2 or 3."); + } + try { + int xsize = (imageDimension == null ? -1 : initISize.getX()); + int ysize = (imageDimension == null ? -1 : initISize.getY()); + int zsize = (imageDimension == null ? -1 : initISize.getZ()); + do { + String result = (imageDimension == null ? "256,256,8" : xsize + "," + ysize + "," + zsize); + result = DialogUtils.showInputDialog0(guiParent, textMessage, result); + String tempResult = result; + try { + if (result == null || result.length() == 0) { + result = ""; + throw new Exception("No size values entered."); + } + xsize = Integer.parseInt(tempResult.substring(0, tempResult.indexOf(","))); + tempResult = tempResult.substring(tempResult.indexOf(",") + 1); + ysize = Integer.parseInt(tempResult.substring(0, tempResult.indexOf(","))); + tempResult = tempResult.substring(tempResult.indexOf(",") + 1); + zsize = Integer.parseInt(tempResult); + if (imageDimension != null) { + if (imageDimension == 2 && zsize != 1) { + throw new Exception("Dimension " + imageDimension + " must have z = 1."); + } else if (imageDimension == 1 && zsize != 1 && ysize != 1) { + throw new Exception("Dimension " + imageDimension + " must have z = 1 and y = 1."); + } + } + ISize isize = new ISize(xsize, ysize, zsize); + if (isize.getXYZ() <= 0) { + throw new Exception("Total pixels (" + xsize + "*" + ysize + "*" + zsize + ") cannot be <=0."); + } + return isize; + } catch (Exception e) { + DialogUtils.showErrorDialog(guiParent, "Error entering starting sizes\n" + e.getMessage(), e); + } + } while (true); + } catch (UtilCancelException e2) { + throw UserCancelException.CANCEL_GENERIC; + } + + } + + public static ImageSizeInfo queryImageResize(final Component requester, final ImageSizeInfo origImageSizeInfo, + boolean bFullMode) { + ImageResizePanel imageResizePanel = new ImageResizePanel(); + imageResizePanel.init(origImageSizeInfo, bFullMode); + imageResizePanel.setPreferredSize(new Dimension(400, 200)); + while (true) { + int flag = DialogUtils.showComponentOKCancelDialog(requester, imageResizePanel, + "Optionally convert imported images."); + if (flag != JOptionPane.OK_OPTION) { + throw UserCancelException.CANCEL_GENERIC; + } + try { + ImageSizeInfo imagesizeInfo = imageResizePanel.getNewImageSizeInfo(); + return imagesizeInfo; + } catch (Exception e) { + e.printStackTrace(); + DialogUtils.showErrorDialog(requester, "Error getting x,y,z: " + e.getMessage()); + } + } + } + + private static void resizeImage(FieldDataFileOperationSpec fdfos, ISize newImagesISize, int imageType) + throws Exception { + final int ORIG_XYSIZE = fdfos.isize.getX() * fdfos.isize.getY(); + try { + int xsize = newImagesISize.getX(); + int ysize = newImagesISize.getY(); + double scaleFactor = (double) newImagesISize.getX() / (double) fdfos.isize.getX(); + if (xsize != fdfos.isize.getX() || ysize != fdfos.isize.getY()) { + int numChannels = fdfos.shortSpecData[0].length;// this normally contains different variables but is + // used for channels here + // resize each z section to xsize,ysize + AffineTransform scaleAffineTransform = AffineTransform.getScaleInstance(scaleFactor, scaleFactor); + AffineTransformOp scaleAffineTransformOp = new AffineTransformOp(scaleAffineTransform, + AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + short[][][] resizeData = new short[1][numChannels][fdfos.isize.getZ() * xsize * ysize]; + for (int c = 0; c < numChannels; c++) { + BufferedImage originalImage = new BufferedImage(fdfos.isize.getX(), fdfos.isize.getY(), + BufferedImage.TYPE_USHORT_GRAY); + BufferedImage scaledImage = new BufferedImage(xsize, ysize, BufferedImage.TYPE_USHORT_GRAY); + for (int z = 0; z < fdfos.isize.getZ(); z++) { + short[] originalImageBuffer = ((DataBufferUShort) (originalImage.getRaster().getDataBuffer())) + .getData(); + System.arraycopy(fdfos.shortSpecData[0][c], z * ORIG_XYSIZE, originalImageBuffer, 0, + ORIG_XYSIZE); + scaleAffineTransformOp.filter(originalImage, scaledImage); + short[] scaledImageBuffer = ((DataBufferUShort) (scaledImage.getRaster().getDataBuffer())) + .getData(); + System.arraycopy(scaledImageBuffer, 0, resizeData[0][c], z * xsize * ysize, xsize * ysize); + } + } + fdfos.isize = new ISize(xsize, ysize, fdfos.isize.getZ()); + fdfos.shortSpecData = resizeData; + } + } catch (Exception e) { + throw new Exception("Error scaling imported image:\n" + e.getMessage()); + } + } + + public AsynchClientTask[] createNewDocument(final TopLevelWindowManager requester, + final VCDocument.DocumentCreationInfo documentCreationInfo) {// throws UserCancelException, Exception { + /* asynchronous and not blocking any window */ + AsynchClientTask[] taskArray = null; + + final int createOption = documentCreationInfo.getOption(); + switch (documentCreationInfo.getDocumentType()) { + case BIOMODEL_DOC: { + AsynchClientTask task1 = new AsynchClientTask("creating biomodel", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + BioModel bioModel = ClientRequestManager.this.createDefaultBioModelDocument(null); + hashTable.put("doc", bioModel); + } + }; + taskArray = new AsynchClientTask[]{task1}; + break; + } + case MATHMODEL_DOC: { + if ((createOption == VCDocument.MATH_OPTION_NONSPATIAL) + || (createOption == VCDocument.MATH_OPTION_SPATIAL_EXISTS)) { + AsynchClientTask task2 = new AsynchClientTask("creating mathmodel", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry geometry = null; + if (createOption == VCDocument.MATH_OPTION_NONSPATIAL) { + geometry = new Geometry("Untitled", 0); + } else { + geometry = (Geometry) hashTable.get(GEOMETRY_KEY); + } + MathModel mathModel = ClientRequestManager.this.createMathModel("Untitled", geometry); + mathModel.setName("MathModel" + (ClientRequestManager.this.getMdiManager().getNumCreatedDocumentWindows() + 1)); + hashTable.put("doc", mathModel); + } + }; + if (createOption == VCDocument.MATH_OPTION_SPATIAL_EXISTS) { + AsynchClientTask task1 = this.createSelectDocTask(requester); + AsynchClientTask task1b = this.createSelectLoadGeomTask(requester); + taskArray = new AsynchClientTask[]{task1, task1b, task2}; + } else { + taskArray = new AsynchClientTask[]{task2}; + } + break; + } else if (createOption == VCDocument.MATH_OPTION_FROMBIOMODELAPP) { + + AsynchClientTask task1 = new AsynchClientTask("select biomodel application", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + // spatial or non-spatial + BioModelInfo bioModelInfo = (BioModelInfo) DialogUtils.getDBTreePanelSelection( + requester.getComponent(), + ClientRequestManager.this.getMdiManager().getDatabaseWindowManager().getBioModelDbTreePanel(), "Open", + "Select BioModel"); + if (bioModelInfo != null) { // may throw UserCancelException + hashTable.put("bioModelInfo", bioModelInfo); + } + } + }; + AsynchClientTask task2 = new AsynchClientTask("find sim contexts in biomodel application", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + // spatial or non-spatial + // Get the simContexts in the corresponding BioModel + BioModelInfo bioModelInfo = (BioModelInfo) hashTable.get("bioModelInfo"); + SimulationContext[] simContexts = ClientRequestManager.this.getDocumentManager().getBioModel(bioModelInfo) + .getSimulationContexts(); + if (simContexts != null) { // may throw UserCancelException + hashTable.put("simContexts", simContexts); + } + } + }; + AsynchClientTask task3 = new AsynchClientTask("create math model from biomodel application", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + SimulationContext[] simContexts = (SimulationContext[]) hashTable.get("simContexts"); + String[] simContextNames = new String[simContexts.length]; + + if (simContextNames.length == 0) { + throw new RuntimeException("no application is available"); + } else { + for (int i = 0; i < simContexts.length; i++) { + simContextNames[i] = simContexts[i].getName(); + } + Component component = requester.getComponent(); + // Get the simContext names, so that user can choose which simContext math to + // import + String simContextChoice = (String) PopupGenerator.showListDialog(component, simContextNames, + "Please select Application"); + if (simContextChoice == null) { + throw UserCancelException.CANCEL_DB_SELECTION; + } + SimulationContext chosenSimContext = null; + for (int i = 0; i < simContexts.length; i++) { + if (simContexts[i].getName().equals(simContextChoice)) { + chosenSimContext = simContexts[i]; + break; + } + } + Objects.requireNonNull(chosenSimContext); + + BioModelInfo bioModelInfo = (BioModelInfo) hashTable.get("bioModelInfo"); + // Get corresponding mathDesc to create new mathModel and return. + String newName = bioModelInfo.getVersion().getName() + "_" + chosenSimContext.getName(); + MathDescription bioMathDesc = chosenSimContext.getMathDescription(); + MathDescription newMathDesc = null; + newMathDesc = new MathDescription(newName + "_" + (new Random()).nextInt()); + + newMathDesc.setGeometry(bioMathDesc.getGeometry()); + newMathDesc.read_database(new CommentStringTokenizer(bioMathDesc.getVCML_database())); + newMathDesc.isValid(); + + MathModel newMathModel = new MathModel(null); + newMathModel.setName(newName); + newMathModel.setMathDescription(newMathDesc); + hashTable.put("doc", newMathModel); + } + } + }; + taskArray = new AsynchClientTask[]{task1, task2, task3}; + break; + } else { + throw new RuntimeException( + "Unknown MathModel Document creation option value=" + documentCreationInfo.getOption()); + } + } + case GEOMETRY_DOC: { + if (createOption == VCDocument.GEOM_OPTION_1D || createOption == VCDocument.GEOM_OPTION_2D + || createOption == VCDocument.GEOM_OPTION_3D) { + // analytic + AsynchClientTask task1 = new AsynchClientTask("creating analytic geometry", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry geometry = new Geometry( + "Geometry" + (ClientRequestManager.this.getMdiManager().getNumCreatedDocumentWindows() + 1), + documentCreationInfo.getOption()); + geometry.getGeometrySpec() + .addSubVolume(new AnalyticSubVolume("subdomain0", new Expression(1.0))); + geometry.precomputeAll(new GeometryThumbnailImageFactoryAWT()); + hashTable.put("doc", geometry); + } + }; + taskArray = new AsynchClientTask[]{task1}; + break; + } + if (createOption == VCDocument.GEOM_OPTION_CSGEOMETRY_3D) { + // constructed solid geometry + AsynchClientTask task1 = new AsynchClientTask("creating constructed solid geometry", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry geometry = new Geometry( + "Geometry" + (ClientRequestManager.this.getMdiManager().getNumCreatedDocumentWindows() + 1), 3); + Extent extent = geometry.getExtent(); + if (extent != null) { + // create a CSGPrimitive of type cube and scale it to the 'extent' components. + // Use this as the default or background CSGObject (subdomain). + // This can be considered as the equivalent of subdomain (with expression) 1.0 + // for analyticSubvolume. + // basic cube + CSGPrimitive cube = new CSGPrimitive("cube", CSGPrimitive.PrimitiveType.CUBE); + // scaled cube + double x = extent.getX(); + double y = extent.getY(); + double z = extent.getZ(); + CSGScale scaledCube = new CSGScale("scale", new Vect3d(x / 2.0, y / 2.0, z / 2.0)); + scaledCube.setChild(cube); + // translated scaled cube + CSGTranslation translatedScaledCube = new CSGTranslation("translation", + new Vect3d(x / 2, y / 2, z / 2)); + translatedScaledCube.setChild(scaledCube); + CSGObject csgObject = new CSGObject(null, "subdomain0", 0); + csgObject.setRoot(translatedScaledCube); + geometry.getGeometrySpec().addSubVolume(csgObject, false); + geometry.precomputeAll(new GeometryThumbnailImageFactoryAWT()); + hashTable.put("doc", geometry); + } + } + }; + taskArray = new AsynchClientTask[]{task1}; + break; + } else { + throw new RuntimeException( + "Unknown Geometry Document creation option value=" + documentCreationInfo.getOption()); + } + } + default: { + throw new RuntimeException("Unknown default document type: " + documentCreationInfo.getDocumentType()); + } + } + return taskArray; + } + + private static final int MAX_NUMBER_OF_COLORS_IMPORTED_FILE = 256; + + public static VCImage createVCImageFromUnsignedShorts(short[] dataToSegment, Extent extent, ISize isize, + BitSet uniquePixelBS) throws Exception { + // auto segment + + int minVal = dataToSegment[0] & 0x0000FFFF; + int maxVal = minVal; + for (int i = 0; i < dataToSegment.length; i++) { + int usIntVal = dataToSegment[i] & 0x0000FFFF; + minVal = Math.min(usIntVal, minVal); + maxVal = Math.max(usIntVal, maxVal); + } + byte[] byteData = new byte[dataToSegment.length]; + + if (maxVal >= MAX_NUMBER_OF_COLORS_IMPORTED_FILE) { + if (uniquePixelBS.cardinality() <= MAX_NUMBER_OF_COLORS_IMPORTED_FILE) { + int index = 0; + int[] indexRef = new int[(int) Math.pow(2, Short.SIZE)]; + Arrays.fill(indexRef, -1); + for (int i = 0; i < indexRef.length; i++) { + if (uniquePixelBS.get(i)) { + indexRef[i] = index; + index++; + } + } + for (int i = 0; i < dataToSegment.length; i++) { + byteData[i] = (byte) indexRef[dataToSegment[i] & 0x0000FFFF]; + } + } else { + for (int i = 0; i < dataToSegment.length; i++) { + byteData[i] = (byte) (0xFF & (int) ((double) (dataToSegment[i] - minVal) + / (double) (maxVal - minVal) * (MAX_NUMBER_OF_COLORS_IMPORTED_FILE - 1))); + } + } + } else { + for (int i = 0; i < byteData.length; i++) { + byteData[i] = (byte) (dataToSegment[i] & 0xFF); + } + } + VCImage autoSegmentVCImage = new VCImageUncompressed(null, byteData, extent, isize.getX(), isize.getY(), + isize.getZ()); + return autoSegmentVCImage; + + } + + public void curateDocument(final VCDocumentInfo documentInfo, final int curateType, + final TopLevelWindowManager requester) { + + if (documentInfo != null) { + // see if we have this open + String documentID = documentInfo.getVersion().getVersionKey().toString(); + if (this.getMdiManager().haveWindow(documentID)) { + // already open, refuse + PopupGenerator.showErrorDialog(requester, + "Selected edition is open, cannot " + CurateSpec.CURATE_TYPE_NAMES[curateType]); + } else { + // don't have it open, try to CURATE it + int confirm = PopupGenerator.showComponentOKCancelDialog(requester.getComponent(), + new JTextArea(CurateSpec.CURATE_TYPE_ACTIONS[curateType] + + " cannot be undone without VCELL administrative assistance.\n" + + CurateSpec.CURATE_TYPE_STATES[curateType] + + " versions of documents cannot be deleted without VCELL administrative assistance.\n" + + (curateType == CurateSpec.PUBLISH ? CurateSpec.CURATE_TYPE_STATES[curateType] + + " versions of documents MUST remain publically accessible to other VCELL users.\n" + : "") + + "Do you want to " + CurateSpec.CURATE_TYPE_NAMES[curateType] + " document '" + + documentInfo.getVersion().getName() + "'" + "\nwith version date '" + + documentInfo.getVersion().getDate().toString() + "'?"), + "WARNING -- " + CurateSpec.CURATE_TYPE_ACTIONS[curateType] + " operation cannot be undone"); + if (confirm == JOptionPane.OK_OPTION) { + AsynchClientTask task1 = new AsynchClientTask( + CurateSpec.CURATE_TYPE_ACTIONS[curateType] + " document...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + if (documentInfo instanceof BioModelInfo) { + ClientRequestManager.this.getDocumentManager().curate(new CurateSpec((BioModelInfo) documentInfo, curateType)); + } else if (documentInfo instanceof MathModelInfo) { + ClientRequestManager.this.getDocumentManager().curate(new CurateSpec((MathModelInfo) documentInfo, curateType)); + } else { + throw new RuntimeException(CurateSpec.CURATE_TYPE_ACTIONS[curateType] + + " not supported for VCDocumentInfo type " + + documentInfo.getClass().getName()); + } + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), + new AsynchClientTask[]{task1}, false); + } else { + // user canceled + } + } + } else { + // nothing selected + } + } + + public void deleteDocument(final VCDocumentInfo documentInfo, final TopLevelWindowManager requester) { + this.deleteDocument(documentInfo, requester, false); + } + + public void deleteDocument(final VCDocumentInfo documentInfo, final TopLevelWindowManager requester, + boolean bDontAsk) { + if (documentInfo != null) { + // see if we have this open + String documentID = documentInfo.getVersion().getVersionKey().toString(); + if (this.getMdiManager().haveWindow(documentID)) { + // already open, refuse + PopupGenerator.showErrorDialog(requester, "Selected edition is open, cannot delete"); + } else { + // don't have it open, try to delete it + String confirm = UserMessage.OPTION_CANCEL; + if (bDontAsk) { + confirm = UserMessage.OPTION_DELETE; + } else { + SimpleDateFormat sdf = new SimpleDateFormat(BeanUtils.vcDateFormat); + confirm = PopupGenerator.showWarningDialog(requester, this.getUserPreferences(), + UserMessage.warn_deleteDocument, documentInfo.getVersion().getName() + " " + + sdf.format(documentInfo.getVersion().getDate())); + } + if (confirm.equals(UserMessage.OPTION_DELETE)) { + AsynchClientTask task1 = new AsynchClientTask("Deleting document...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + if (documentInfo instanceof BioModelInfo) { + ClientRequestManager.this.getDocumentManager().delete((BioModelInfo) documentInfo); + } else if (documentInfo instanceof MathModelInfo) { + ClientRequestManager.this.getDocumentManager().delete((MathModelInfo) documentInfo); + } else if (documentInfo instanceof GeometryInfo) { + ClientRequestManager.this.getDocumentManager().delete((GeometryInfo) documentInfo); + } else { + throw new RuntimeException("delete not supported for VCDocumentInfo type " + + documentInfo.getClass().getName()); + } + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), + new AsynchClientTask[]{task1}, false); + } else { + // user canceled + } + } + } else { + // nothing selected + } + } + + /** + * hashtable key for data bytes of file + */ + private final static String BYTES_KEY = "bytes"; + + /** + * Comment + */ + public static void downloadExportedData(final Component requester, final UserPreferences userPrefs, + final ExportEvent evt) { + TreeSet exportsRecord = getExportsRecord(); + if (exportsRecord.contains(evt.getJobID() + "")) { + return; + } + if (evt.getLocation().toLowerCase().endsWith("." + N5Specs.n5Suffix)) { + return; + } + AsynchClientTask task1 = new AsynchClientTask("Retrieving data from '" + evt.getLocation() + "'", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + final Exception[] excArr = new Exception[]{null}; + final boolean[] bFlagArr = new boolean[]{false}; + final ByteArrayOutputStream[] baosArr = new ByteArrayOutputStream[1]; + final HttpGet[] httpGetArr = new HttpGet[1]; + // Start download of exported file in separate thread that is interruptible + // (apache HTTPClient) + Thread interruptible = new Thread(new Runnable() { + @Override + public void run() { + if (getClientTaskStatusSupport() != null) { + getClientTaskStatusSupport().setMessage("downloading data..."); + } + CloseableHttpClient httpclient = HttpClients.createDefault(); + httpGetArr[0] = new HttpGet(evt.getLocation()); + CloseableHttpResponse response = null; + try { + response = httpclient.execute(httpGetArr[0]); + if (response.getStatusLine() != null + && (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)) { + throw new Exception( + evt.getLocation() + " " + response.getStatusLine().getReasonPhrase()); + } + HttpEntity entity = response.getEntity(); + if (entity != null) { + long size = entity.getContentLength(); + InputStream instream = entity.getContent(); + try { + if (size > 0) { + baosArr[0] = new ByteArrayOutputStream((int) size); + } else { + baosArr[0] = new ByteArrayOutputStream(); + } + IOUtils.copy(instream, baosArr[0]); + } finally { + instream.close(); + } + } + + } catch (Exception e) { + excArr[0] = e; + } finally { + if (response != null) { + try { + response.close(); + } catch (Exception e) { + } + } + if (httpclient != null) { + try { + httpclient.close(); + } catch (Exception e) { + } + } + bFlagArr[0] = true; + } + } + }); + interruptible.start(); + // Wait for download to 1-finish, 2-fail or 3-be cancelled by user + while (!bFlagArr[0]) { + if (this.getClientTaskStatusSupport() != null && this.getClientTaskStatusSupport().isInterrupted()) {// user + // cancelled + if (httpGetArr[0] != null) { + httpGetArr[0].abort(); + } + throw UserCancelException.CANCEL_GENERIC; + } + try { + Thread.sleep(500); + } catch (InterruptedException e) {// caused by pressing 'cancel' button on progresspopup + if (httpGetArr[0] != null) { + httpGetArr[0].abort(); + } + if (this.getClientTaskStatusSupport() != null && this.getClientTaskStatusSupport().isInterrupted()) { + throw UserCancelException.CANCEL_GENERIC; + } + } + } + if (excArr[0] != null) {// download failed + throw excArr[0]; + } + // + // finished downloading, either save to file or send to ImageJ directly + // + if (evt.getFormat() == null || !evt.getFormat().equals("IMAGEJ")) { + // save for file save operations + hashTable.put(BYTES_KEY, baosArr[0].toByteArray()); + } + } + }; + AsynchClientTask task2 = new AsynchClientTask("selecting file to save", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + // user pref could be null if trying local export + String defaultPath = getPreferredPath(userPrefs); + final VCFileChooser fileChooser = new VCFileChooser(defaultPath); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setMultiSelectionEnabled(false); + String name = evt.getDataIdString(); + String suffix = null; + if (evt.getLocation().toLowerCase().endsWith(".mov")) { + fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_MOV); + fileChooser.setFileFilter(FileFilters.FILE_FILTER_MOV); + + suffix = "_exported.mov"; + } else if (evt.getLocation().toLowerCase().endsWith(".gif")) { + fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_GIF); + fileChooser.setFileFilter(FileFilters.FILE_FILTER_GIF); + + suffix = "_exported.gif"; + } else if (evt.getLocation().toLowerCase().endsWith(".jpeg")) { + fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_JPEG); + fileChooser.setFileFilter(FileFilters.FILE_FILTER_JPEG); + + suffix = "_exported.jpeg"; + } else if (evt.getLocation().toLowerCase().endsWith(".hdf5")) { + fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_HDF5); + fileChooser.setFileFilter(FileFilters.FILE_FILTER_HDF5); + + suffix = "_exported.hdf5"; + } else { + fileChooser.addChoosableFileFilter(FileFilters.FILE_FILTER_ZIP); + fileChooser.setFileFilter(FileFilters.FILE_FILTER_ZIP); + + suffix = "_exported.zip"; + } + File file = new File(name + suffix); + if (file.exists()) { + int count = 0; + do { + file = new File(name + "_" + count + suffix); + count++; + } while (file.exists()); + } + + fileChooser.setSelectedFile(file); + fileChooser.setDialogTitle("Save exported dataset..."); + int approve = fileChooser.showSaveDialog(requester); + if (approve == JFileChooser.APPROVE_OPTION) { + hashTable.put("selectedFile", fileChooser.getSelectedFile()); + } else { + fileChooser.setSelectedFile(null); + } + } + }; + AsynchClientTask task3 = new AsynchClientTask("saving to file", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + addExportRecord(evt.getJobID() + ""); + + File selectedFile = (File) hashTable.get("selectedFile"); + if (selectedFile == null) { + return; + } + setPreferredPath(userPrefs, selectedFile); // System.out.println("New preferred file path: " + newPath + ", Old preferred file path: " + defaultPath); - if (selectedFile.exists()) { - String question = null; - if (userPrefs != null) { - question = PopupGenerator.showWarningDialog(requester, userPrefs, - UserMessage.warn_OverwriteFile, selectedFile.getAbsolutePath()); - } else { - question = DialogUtils.showWarningDialog(requester, "Overwrite File?", - "Overwrite file '" + selectedFile.getAbsolutePath() + "'?", - new String[] { UserMessage.OPTION_OVERWRITE_FILE, UserMessage.OPTION_CANCEL }, - UserMessage.OPTION_OVERWRITE_FILE); - } - if (question != null && question.equals(UserMessage.OPTION_CANCEL)) { - return; - } - } - byte[] bytes = (byte[]) hashTable.get(BYTES_KEY); - FileOutputStream fo = new FileOutputStream(selectedFile); - fo.write(bytes); - fo.close(); - } - }; - ClientTaskDispatcher.dispatch(requester, new Hashtable(), - new AsynchClientTask[] { task1, task2, task3 }, false, true, null); - } - - private static String EXPORT_RECORD_FILE_NAME = "exportRecords"; - - private static TreeSet getExportsRecord() { - try { - if (ResourceUtil.getVcellHome() != null) { - File exportRecordsFile = new File(ResourceUtil.getVcellHome(), EXPORT_RECORD_FILE_NAME); - if (exportRecordsFile.exists()) { - List exportRecordsList = Files.readAllLines(exportRecordsFile.toPath()); - return new TreeSet(exportRecordsList); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return new TreeSet(); - } - - private static void addExportRecord(String exportRecord) { - try { - if (ResourceUtil.getVcellHome() != null) { - File exportRecordsFile = new File(ResourceUtil.getVcellHome(), EXPORT_RECORD_FILE_NAME); - Files.write(exportRecordsFile.toPath(), (exportRecord + System.lineSeparator()).getBytes(), - StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.APPEND); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static String EXPORT_METADATA_FILENAME = "exportMetaData.json"; - - private static void updateExportMetaData(final ExportEvent exportEvent){ - try{ - if(ResourceUtil.getVcellHome() != null){ - - String stringJobID = String.valueOf(exportEvent.getJobID()); - String exportFormat = exportEvent.getFormat(); - if(stringJobID == null) { - throw new RuntimeException("stringJobID is null"); - } - if(exportFormat == null) { - throw new RuntimeException("exportFormat is null"); - } - String globalID = stringJobID + "," + exportFormat; - - ExportDataRepresentation exportDataRepresentation = new ExportDataRepresentation(new Stack<>(), new HashMap<>()); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - // put lock - File jsonFile = new File(ResourceUtil.getVcellHome(), EXPORT_METADATA_FILENAME); - - HumanReadableExportData humanReadableExportData = exportEvent.getHumanReadableData(); - DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); - double[] exportTimes = exportEvent.getTimeSpecs().getAllTimes(); - - - if (jsonFile.exists()){ - String stringJSON = new String(Files.readAllBytes(jsonFile.toPath())); - exportDataRepresentation = stringJSON.isEmpty() ? - exportDataRepresentation : gson.fromJson(stringJSON, ExportDataRepresentation.class); - } - - int sizeOfList = exportDataRepresentation.globalJobIDs.size(); - int startOfSearch = sizeOfList > 200 ? sizeOfList - 200 : 0; - // only write new data, checking the last 200 elements in the stack - if (!exportDataRepresentation.globalJobIDs.subList(startOfSearch, sizeOfList).contains(globalID)){ - ExportDataRepresentation.FormatExportDataRepresentation formatData = exportDataRepresentation.formatData.containsKey(exportFormat) ? - exportDataRepresentation.formatData.get(exportFormat) : new ExportDataRepresentation.FormatExportDataRepresentation(new HashMap<>(), new ArrayList<>()); - - - ExportDataRepresentation.SimulationExportDataRepresentation simulationExportDataRepresentation = new ExportDataRepresentation.SimulationExportDataRepresentation( - dateFormat.format(new Date()), - exportEvent.getLocation(), - stringJobID, - exportEvent.getDataIdString(), - humanReadableExportData.simulationName, - humanReadableExportData.applicationName, - humanReadableExportData.biomodelName, + if (selectedFile.exists()) { + String question = null; + if (userPrefs != null) { + question = PopupGenerator.showWarningDialog(requester, userPrefs, + UserMessage.warn_OverwriteFile, selectedFile.getAbsolutePath()); + } else { + question = DialogUtils.showWarningDialog(requester, "Overwrite File?", + "Overwrite file '" + selectedFile.getAbsolutePath() + "'?", + new String[]{UserMessage.OPTION_OVERWRITE_FILE, UserMessage.OPTION_CANCEL}, + UserMessage.OPTION_OVERWRITE_FILE); + } + if (question != null && question.equals(UserMessage.OPTION_CANCEL)) { + return; + } + } + byte[] bytes = (byte[]) hashTable.get(BYTES_KEY); + FileOutputStream fo = new FileOutputStream(selectedFile); + fo.write(bytes); + fo.close(); + } + }; + ClientTaskDispatcher.dispatch(requester, new Hashtable(), + new AsynchClientTask[]{task1, task2, task3}, false, true, null); + } + + private static final String EXPORT_RECORD_FILE_NAME = "exportRecords"; + + private static TreeSet getExportsRecord() { + try { + if (ResourceUtil.getVcellHome() != null) { + File exportRecordsFile = new File(ResourceUtil.getVcellHome(), EXPORT_RECORD_FILE_NAME); + if (exportRecordsFile.exists()) { + List exportRecordsList = Files.readAllLines(exportRecordsFile.toPath()); + return new TreeSet(exportRecordsList); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return new TreeSet(); + } + + private static void addExportRecord(String exportRecord) { + try { + if (ResourceUtil.getVcellHome() != null) { + File exportRecordsFile = new File(ResourceUtil.getVcellHome(), EXPORT_RECORD_FILE_NAME); + Files.write(exportRecordsFile.toPath(), (exportRecord + System.lineSeparator()).getBytes(), + StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.APPEND); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static String EXPORT_METADATA_FILENAME = "exportMetaData.json"; + + private static void updateExportMetaData(final ExportEvent exportEvent) { + try { + if (ResourceUtil.getVcellHome() != null) { + + String stringJobID = String.valueOf(exportEvent.getJobID()); + String exportFormat = exportEvent.getFormat(); + if (stringJobID == null) { + throw new RuntimeException("stringJobID is null"); + } + if (exportFormat == null) { + throw new RuntimeException("exportFormat is null"); + } + String globalID = stringJobID + "," + exportFormat; + + ExportDataRepresentation exportDataRepresentation = new ExportDataRepresentation(new Stack<>(), new HashMap<>()); + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + // put lock + File jsonFile = new File(ResourceUtil.getVcellHome(), EXPORT_METADATA_FILENAME); + + HumanReadableExportData humanReadableExportData = exportEvent.getHumanReadableData(); + DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + double[] exportTimes = exportEvent.getTimeSpecs().getAllTimes(); + + + if (jsonFile.exists()) { + String stringJSON = new String(Files.readAllBytes(jsonFile.toPath())); + exportDataRepresentation = stringJSON.isEmpty() ? + exportDataRepresentation : gson.fromJson(stringJSON, ExportDataRepresentation.class); + } + + int sizeOfList = exportDataRepresentation.globalJobIDs.size(); + int startOfSearch = sizeOfList > 200 ? sizeOfList - 200 : 0; + // only write new data, checking the last 200 elements in the stack + if (!exportDataRepresentation.globalJobIDs.subList(startOfSearch, sizeOfList).contains(globalID)) { + ExportDataRepresentation.FormatExportDataRepresentation formatData = exportDataRepresentation.formatData.containsKey(exportFormat) ? + exportDataRepresentation.formatData.get(exportFormat) : new ExportDataRepresentation.FormatExportDataRepresentation(new HashMap<>(), new ArrayList<>()); + + + ExportDataRepresentation.SimulationExportDataRepresentation simulationExportDataRepresentation = new ExportDataRepresentation.SimulationExportDataRepresentation( + dateFormat.format(new Date()), + exportEvent.getLocation(), + stringJobID, + exportEvent.getDataIdString(), + humanReadableExportData.simulationName, + humanReadableExportData.applicationName, + humanReadableExportData.biomodelName, Arrays.toString(exportEvent.getVariableSpecs().getVariableNames()), - exportTimes[exportEvent.getTimeSpecs().getBeginTimeIndex()] + "/" + exportTimes[exportEvent.getTimeSpecs().getEndTimeIndex()], - humanReadableExportData.differentParameterValues, - humanReadableExportData.serverSavedFileName, - humanReadableExportData.applicationType, - humanReadableExportData.nonSpatial - ); - - formatData.simulationDataMap.put(stringJobID, simulationExportDataRepresentation); - formatData.formatJobIDs.add(stringJobID); - - exportDataRepresentation.formatData.put(exportFormat, formatData); - exportDataRepresentation.globalJobIDs.add(globalID); - - - String json = gson.toJson(exportDataRepresentation, ExportDataRepresentation.class); - FileWriter jsonFileWriter = new FileWriter(jsonFile); - jsonFileWriter.write(json); - - jsonFileWriter.close(); - } - } - } - catch (Exception e){ - lg.error("Failed Update Export Metadata", e); - } - } - - public void exitApplication(boolean loggingOut) { - try (VCellThreadChecker.SuppressIntensive si = new VCellThreadChecker.SuppressIntensive()) { - if (!bExiting) { - // close all windows - this will run checks - boolean closedAllWindows = closeAllWindows(true); - if (!closedAllWindows) { - // user bailed out at some point, we're not gonna exit - return; - } - } - // ready to exit - if (!ClientTaskDispatcher.hasOutstandingTasks()) { - // simply exit in this case - if (loggingOut) { - Auth0ConnectionUtils.setShowLoginPopUp(true); - if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - try { - Desktop.getDesktop().browse(new URI("https://vcell-stage.cam.uchc.edu/login_success")); - } catch (IOException | URISyntaxException e) { - throw new RuntimeException(e); - } - } - } - System.exit(0); - } - new Timer(1000, evt -> checkTasksDone()).start(); - } - } - - public void exitApplication(){ - exitApplication(false); - } - - /** - * see if there are outstanding tasks ... if not, exit the application - */ - private void checkTasksDone() { - Collection ot = ClientTaskDispatcher.outstandingTasks(); - if (ot.isEmpty()) { - // ready to exit now - System.exit(0); - } - System.out.println("waiting for " + ot.toString()); - } - - /** - * Comment - */ - public void exportDocument(TopLevelWindowManager manager, FileFilter forceFilefilter) { - /* block window */ - JFrame currentWindow = getMdiManager().blockWindow(manager.getManagerID()); - /* prepare hashtable for tasks */ - Hashtable hash = new Hashtable(); - hash.put("mdiManager", getMdiManager()); - hash.put(DocumentManager.IDENT, getDocumentManager()); - hash.put("topLevelWindowManager", manager); - hash.put("currentWindow", currentWindow); - hash.put("userPreferences", getUserPreferences()); - if (forceFilefilter != null) { - hash.put(ChooseFile.FORCE_FILE_FILTER, forceFilefilter); - } - - hash.put("CallAction", CallAction.EXPORT); - hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, manager); - hash.put("currentDocumentWindow", currentWindow); - - /* create tasks */ - AsynchClientTask documentValid = new DocumentValidTask(); - AsynchClientTask setMathDescription = new SetMathDescription(); - - // get document to be exported - AsynchClientTask documentToExport = new DocumentToExport(); - // get file - AsynchClientTask chooseFile = new ChooseFile(); - // export it - AsynchClientTask exportDocument = new ExportDocument(); - // clean-up - AsynchClientTask finishExport = new FinishExport(); - // assemble array - AsynchClientTask[] tasks = null; - tasks = new AsynchClientTask[] { documentToExport, chooseFile, documentValid, setMathDescription, exportDocument, finishExport }; - /* run tasks */ - ClientTaskDispatcher.dispatch(currentWindow, hash, tasks, false); - } - - public void exportMessage(ExportEvent event) { - if (event.getEventTypeID() == ExportEvent.EXPORT_COMPLETE) { - // try to download the thing - if(!Objects.equals(event.getFormat(), ExportFormat.N5.name())){ - downloadExportedData(getMdiManager().getFocusedWindowManager().getComponent(), getUserPreferences(), event); - } - // create export metadata - updateExportMetaData(event); - } - } - - public AsynchMessageManager getAsynchMessageManager() { - return getClientServerManager().getAsynchMessageManager(); - } - - private ClientServerManager getClientServerManager() { - // shorthand - return getVcellClient().getClientServerManager(); - } - - public ConnectionStatus getConnectionStatus() { - return getClientServerManager().getConnectionStatus(); - } - - public DataManager getDataManager(OutputContext outputContext, VCDataIdentifier vcDataId, boolean isSpatial) - throws DataAccessException { - // - // Create ODE or PDE or Merged Datamanager depending on ODE or PDE or Merged - // data. - // - DataManager dataManager = null; - VCDataManager vcDataManager = getClientServerManager().getVCDataManager(); - if (isSpatial) { - dataManager = new PDEDataManager(outputContext, vcDataManager, vcDataId); - } else { - dataManager = new ODEDataManager(outputContext, vcDataManager, vcDataId); - } + exportTimes[exportEvent.getTimeSpecs().getBeginTimeIndex()] + "/" + exportTimes[exportEvent.getTimeSpecs().getEndTimeIndex()], + humanReadableExportData.differentParameterValues, + humanReadableExportData.serverSavedFileName, + humanReadableExportData.applicationType, + humanReadableExportData.nonSpatial + ); + + formatData.simulationDataMap.put(stringJobID, simulationExportDataRepresentation); + formatData.formatJobIDs.add(stringJobID); + + exportDataRepresentation.formatData.put(exportFormat, formatData); + exportDataRepresentation.globalJobIDs.add(globalID); + + + String json = gson.toJson(exportDataRepresentation, ExportDataRepresentation.class); + FileWriter jsonFileWriter = new FileWriter(jsonFile); + jsonFileWriter.write(json); + + jsonFileWriter.close(); + } + } + } catch (Exception e) { + lg.error("Failed Update Export Metadata", e); + } + } + + public void exitApplication(boolean loggingOut) { + try (VCellThreadChecker.SuppressIntensive si = new VCellThreadChecker.SuppressIntensive()) { + if (!this.bExiting) { + // close all windows - this will run checks + boolean closedAllWindows = this.closeAllWindows(true); + if (!closedAllWindows) { + // user bailed out at some point, we're not gonna exit + return; + } + } + // ready to exit + if (!ClientTaskDispatcher.hasOutstandingTasks()) { + // simply exit in this case + if (loggingOut) { + Auth0ConnectionUtils.setShowLoginPopUp(true); + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(new URI("https://vcell-stage.cam.uchc.edu/login_success")); + } catch (IOException | URISyntaxException e) { + throw new RuntimeException(e); + } + } + } + System.exit(0); + } + new Timer(1000, evt -> this.checkTasksDone()).start(); + } + } + + public void exitApplication() { + this.exitApplication(false); + } + + /** + * see if there are outstanding tasks ... if not, exit the application + */ + private void checkTasksDone() { + Collection ot = ClientTaskDispatcher.outstandingTasks(); + if (ot.isEmpty()) { + // ready to exit now + System.exit(0); + } + System.out.println("waiting for " + ot); + } + + /** + * Comment + */ + public void exportDocument(TopLevelWindowManager manager, FileFilter forceFilefilter) { + /* block window */ + JFrame currentWindow = this.getMdiManager().blockWindow(manager.getManagerID()); + /* prepare hashtable for tasks */ + Hashtable hash = new Hashtable(); + hash.put("mdiManager", this.getMdiManager()); + hash.put(DocumentManager.IDENT, this.getDocumentManager()); + hash.put("topLevelWindowManager", manager); + hash.put("currentWindow", currentWindow); + hash.put("userPreferences", this.getUserPreferences()); + if (forceFilefilter != null) { + hash.put(ChooseFile.FORCE_FILE_FILTER, forceFilefilter); + } + + hash.put("CallAction", CallAction.EXPORT); + hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, manager); + hash.put("currentDocumentWindow", currentWindow); + + /* create tasks */ + AsynchClientTask documentValid = new DocumentValidTask(); + AsynchClientTask setMathDescription = new SetMathDescription(); + + // get document to be exported + AsynchClientTask documentToExport = new DocumentToExport(); + // get file + AsynchClientTask chooseFile = new ChooseFile(); + // export it + AsynchClientTask exportDocument = new ExportDocument(); + // clean-up + AsynchClientTask finishExport = new FinishExport(); + // assemble array + AsynchClientTask[] tasks = null; + tasks = new AsynchClientTask[]{documentToExport, chooseFile, documentValid, setMathDescription, exportDocument, finishExport}; + /* run tasks */ + ClientTaskDispatcher.dispatch(currentWindow, hash, tasks, false); + } + + public void exportMessage(ExportEvent event) { + if (event.getEventTypeID() == ExportEvent.EXPORT_COMPLETE) { + // try to download the thing + if (!Objects.equals(event.getFormat(), ExportFormat.N5.name())) { + downloadExportedData(this.getMdiManager().getFocusedWindowManager().getComponent(), this.getUserPreferences(), event); + } + // create export metadata + updateExportMetaData(event); + } + } + + public AsynchMessageManager getAsynchMessageManager() { + return this.getClientServerManager().getAsynchMessageManager(); + } + + private ClientServerManager getClientServerManager() { + // shorthand + return this.getVcellClient().getClientServerManager(); + } + + public ConnectionStatus getConnectionStatus() { + return this.getClientServerManager().getConnectionStatus(); + } + + public DataManager getDataManager(OutputContext outputContext, VCDataIdentifier vcDataId, boolean isSpatial) + throws DataAccessException { + // + // Create ODE or PDE or Merged Datamanager depending on ODE or PDE or Merged + // data. + // + DataManager dataManager = null; + VCDataManager vcDataManager = this.getClientServerManager().getVCDataManager(); + if (isSpatial) { + dataManager = new PDEDataManager(outputContext, vcDataManager, vcDataId); + } else { + dataManager = new ODEDataManager(outputContext, vcDataManager, vcDataId); + } // dataManager.connect(); - return dataManager; - } - - @Override - public VtkManager getVtkManager(OutputContext outputContext, VCDataIdentifier vcDataID) throws DataAccessException { - VCDataManager vcDataManager = getClientServerManager().getVCDataManager(); - return new VtkManager(outputContext, vcDataManager, vcDataID); - } - - public DocumentManager getDocumentManager() { - // this should not be exposed here, but needs many changes outside project in - // order to live without it... - // will eliminate when finishing up new client - return getVcellClient().getClientServerManager().getDocumentManager(); - } - - public MergedDatasetViewerController getMergedDatasetViewerController(OutputContext outputContext, - VCDataIdentifier vcdId, boolean expectODEData) throws DataAccessException { - if (vcdId instanceof MergedDataInfo) { - DataManager dataManager = getDataManager(outputContext, vcdId, !expectODEData); - return new MergedDatasetViewerController(dataManager); - } else { - return null; - } - } - - public DataViewerController getDataViewerController(OutputContext outputContext, Simulation simulation, - int jobIndex) throws DataAccessException { - VCSimulationIdentifier vcSimulationIdentifier = simulation.getSimulationInfo() - .getAuthoritativeVCSimulationIdentifier(); - final VCDataIdentifier vcdataIdentifier = new VCSimulationDataIdentifier(vcSimulationIdentifier, jobIndex); - boolean isSpatialData = simulation.isSpatial() - && simulation.getSolverTaskDescription().getLangevinSimulationOptions() == null; - DataManager dataManager = getDataManager(outputContext, vcdataIdentifier, isSpatialData); - return new SimResultsViewerController(dataManager, simulation); - } - - // utility method - private VCDocumentInfo getMatchingDocumentInfo(VCDocument vcDoc) throws DataAccessException { - - VCDocumentInfo vcDocInfo = null; - - switch (vcDoc.getDocumentType()) { - case BIOMODEL_DOC: { - BioModel bm = ((BioModel) vcDoc); - vcDocInfo = getDocumentManager().getBioModelInfo(bm.getVersion().getVersionKey()); - break; - } - case MATHMODEL_DOC: { - MathModel mm = ((MathModel) vcDoc); - vcDocInfo = getDocumentManager().getMathModelInfo(mm.getVersion().getVersionKey()); - break; - } - case GEOMETRY_DOC: { - Geometry geom = ((Geometry) vcDoc); - vcDocInfo = getDocumentManager().getGeometryInfo(geom.getKey()); - break; - } - default: { - throw new IllegalArgumentException("Invalid VC document: " + vcDoc.getDocumentType()); - } - } - - return vcDocInfo; - } - - private MDIManager getMdiManager() { - // shorthand - return getVcellClient().getMdiManager(); - } - - public SimulationStatus getServerSimulationStatus(SimulationInfo simInfo) { - - SimulationStatus simStatus = null; - if (simInfo == null) { - // unsaved simulation ... won't have simulation status - return null; - } - try { - VCSimulationIdentifier vcSimulationIdentifier = simInfo.getAuthoritativeVCSimulationIdentifier(); - simStatus = getClientServerManager().getJobManager().getServerSimulationStatus(vcSimulationIdentifier); - } catch (Throwable exc) { - exc.printStackTrace(System.out); - } - return simStatus; - } - - public UserPreferences getUserPreferences() { - return getVcellClient().getClientServerManager().getUserPreferences(); - } - - private VCellClient getVcellClient() { - return vcellClient; - } - - /** - * - * @return false - */ - @Deprecated - public boolean isApplet() { - return false; - } - - public void managerIDchanged(java.lang.String oldID, java.lang.String newID) { - if (oldID != null) { - getMdiManager().updateDocumentID(oldID, newID); - } - } - - public AsynchClientTask[] newDocument(TopLevelWindowManager requester, - final VCDocument.DocumentCreationInfo documentCreationInfo) { - // gcwtodo - - AsynchClientTask createNewDocumentTask = new AsynchClientTask("Creating New Document", - AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - VCDocument doc = (VCDocument) hashTable.get("doc"); - DocumentWindowManager windowManager = createDocumentWindowManager(doc); - DocumentWindow dw = getMdiManager().createNewDocumentWindow(windowManager); - if (windowManager != null) { - hashTable.put("windowManager", windowManager); - } - setFinalWindow(hashTable, dw); - } - }; - - if (documentCreationInfo.getDocumentType() == VCDocumentType.MATHMODEL_DOC - && documentCreationInfo.getOption() == VCDocument.MATH_OPTION_SPATIAL_NEW) { - final AsynchClientTask createSpatialMathModelTask = new AsynchClientTask("creating mathmodel", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry geometry = null; - geometry = (Geometry) hashTable.get("doc"); - MathModel mathModel = createMathModel("Untitled", geometry); - mathModel.setName("MathModel" + (getMdiManager().getNumCreatedDocumentWindows() + 1)); - hashTable.put("doc", mathModel); - } - }; - - requester.createGeometry(null, new AsynchClientTask[] { createSpatialMathModelTask, createNewDocumentTask }, - "Choose geometry type to start MathModel creation", "Create MathModel", null); - return null; - } - - /* asynchronous and not blocking any window */ - AsynchClientTask[] taskArray = null; - if (documentCreationInfo.getPreCreatedDocument() == null) { - AsynchClientTask[] taskArray1 = createNewDocument(requester, documentCreationInfo); - taskArray = new AsynchClientTask[taskArray1.length + 1]; - System.arraycopy(taskArray1, 0, taskArray, 0, taskArray1.length); - } else { - taskArray = new AsynchClientTask[2]; - taskArray[0] = new AsynchClientTask("Setting document...", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - hashTable.put("doc", documentCreationInfo.getPreCreatedDocument()); - } - }; - } - - taskArray[taskArray.length - 1] = createNewDocumentTask; - return taskArray; - } - - private static VCImage saveImageAutoName(RequestManager requestManager, VCImage vcImage) throws Exception { - VCImageInfo[] imageInfos = null; - try { - imageInfos = requestManager.getDocumentManager().getImageInfos(); - } catch (DataAccessException e) { - e.printStackTrace(System.out); - } - String newName = null; - boolean bNameIsGood = false; + return dataManager; + } + + @Override + public VtkManager getVtkManager(OutputContext outputContext, VCDataIdentifier vcDataID) throws DataAccessException { + VCDataManager vcDataManager = this.getClientServerManager().getVCDataManager(); + return new VtkManager(outputContext, vcDataManager, vcDataID); + } + + public DocumentManager getDocumentManager() { + // this should not be exposed here, but needs many changes outside project in + // order to live without it... + // will eliminate when finishing up new client + return this.getVcellClient().getClientServerManager().getDocumentManager(); + } + + public MergedDatasetViewerController getMergedDatasetViewerController(OutputContext outputContext, + VCDataIdentifier vcdId, boolean expectODEData) throws DataAccessException { + if (vcdId instanceof MergedDataInfo) { + DataManager dataManager = this.getDataManager(outputContext, vcdId, !expectODEData); + return new MergedDatasetViewerController(dataManager); + } else { + return null; + } + } + + public DataViewerController getDataViewerController(OutputContext outputContext, Simulation simulation, + int jobIndex) throws DataAccessException { + VCSimulationIdentifier vcSimulationIdentifier = simulation.getSimulationInfo() + .getAuthoritativeVCSimulationIdentifier(); + final VCDataIdentifier vcdataIdentifier = new VCSimulationDataIdentifier(vcSimulationIdentifier, jobIndex); + boolean isSpatialData = simulation.isSpatial() + && simulation.getSolverTaskDescription().getLangevinSimulationOptions() == null; + DataManager dataManager = this.getDataManager(outputContext, vcdataIdentifier, isSpatialData); + return new SimResultsViewerController(dataManager, simulation); + } + + // utility method + private VCDocumentInfo getMatchingDocumentInfo(VCDocument vcDoc) throws DataAccessException { + + VCDocumentInfo vcDocInfo = null; + + switch (vcDoc.getDocumentType()) { + case BIOMODEL_DOC: { + BioModel bm = ((BioModel) vcDoc); + vcDocInfo = this.getDocumentManager().getBioModelInfo(bm.getVersion().getVersionKey()); + break; + } + case MATHMODEL_DOC: { + MathModel mm = ((MathModel) vcDoc); + vcDocInfo = this.getDocumentManager().getMathModelInfo(mm.getVersion().getVersionKey()); + break; + } + case GEOMETRY_DOC: { + Geometry geom = ((Geometry) vcDoc); + vcDocInfo = this.getDocumentManager().getGeometryInfo(geom.getKey()); + break; + } + default: { + throw new IllegalArgumentException("Invalid VC document: " + vcDoc.getDocumentType()); + } + } + + return vcDocInfo; + } + + private MDIManager getMdiManager() { + // shorthand + return this.getVcellClient().getMdiManager(); + } + + public SimulationStatus getServerSimulationStatus(SimulationInfo simInfo) { + + SimulationStatus simStatus = null; + if (simInfo == null) { + // unsaved simulation ... won't have simulation status + return null; + } + try { + VCSimulationIdentifier vcSimulationIdentifier = simInfo.getAuthoritativeVCSimulationIdentifier(); + simStatus = this.getClientServerManager().getJobManager().getServerSimulationStatus(vcSimulationIdentifier); + } catch (Throwable exc) { + exc.printStackTrace(System.out); + } + return simStatus; + } + + public UserPreferences getUserPreferences() { + return this.getVcellClient().getClientServerManager().getUserPreferences(); + } + + private VCellClient getVcellClient() { + return this.vcellClient; + } + + /** + * @return false + */ + @Deprecated + public boolean isApplet() { + return false; + } + + public void managerIDchanged(java.lang.String oldID, java.lang.String newID) { + if (oldID != null) { + this.getMdiManager().updateDocumentID(oldID, newID); + } + } + + public AsynchClientTask[] newDocument(TopLevelWindowManager requester, + final VCDocument.DocumentCreationInfo documentCreationInfo) { + // gcwtodo + + AsynchClientTask createNewDocumentTask = new AsynchClientTask("Creating New Document", + AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + VCDocument doc = (VCDocument) hashTable.get("doc"); + DocumentWindowManager windowManager = ClientRequestManager.this.createDocumentWindowManager(doc); + DocumentWindow dw = ClientRequestManager.this.getMdiManager().createNewDocumentWindow(windowManager); + if (windowManager != null) { + hashTable.put("windowManager", windowManager); + } + this.setFinalWindow(hashTable, dw); + } + }; + + if (documentCreationInfo.getDocumentType() == VCDocumentType.MATHMODEL_DOC + && documentCreationInfo.getOption() == VCDocument.MATH_OPTION_SPATIAL_NEW) { + final AsynchClientTask createSpatialMathModelTask = new AsynchClientTask("creating mathmodel", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry geometry = null; + geometry = (Geometry) hashTable.get("doc"); + MathModel mathModel = ClientRequestManager.this.createMathModel("Untitled", geometry); + mathModel.setName("MathModel" + (ClientRequestManager.this.getMdiManager().getNumCreatedDocumentWindows() + 1)); + hashTable.put("doc", mathModel); + } + }; + + requester.createGeometry(null, new AsynchClientTask[]{createSpatialMathModelTask, createNewDocumentTask}, + "Choose geometry type to start MathModel creation", "Create MathModel", null); + return null; + } + + /* asynchronous and not blocking any window */ + AsynchClientTask[] taskArray = null; + if (documentCreationInfo.getPreCreatedDocument() == null) { + AsynchClientTask[] taskArray1 = this.createNewDocument(requester, documentCreationInfo); + taskArray = new AsynchClientTask[taskArray1.length + 1]; + System.arraycopy(taskArray1, 0, taskArray, 0, taskArray1.length); + } else { + taskArray = new AsynchClientTask[2]; + taskArray[0] = new AsynchClientTask("Setting document...", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + hashTable.put("doc", documentCreationInfo.getPreCreatedDocument()); + } + }; + } + + taskArray[taskArray.length - 1] = createNewDocumentTask; + return taskArray; + } + + private static VCImage saveImageAutoName(RequestManager requestManager, VCImage vcImage) throws Exception { + VCImageInfo[] imageInfos = null; + try { + imageInfos = requestManager.getDocumentManager().getImageInfos(); + } catch (DataAccessException e) { + e.printStackTrace(System.out); + } + String newName = null; + boolean bNameIsGood = false; // Calendar calendar = Calendar.getInstance(); - newName = "image_" + BeanUtils.generateDateTimeString(); - while (!bNameIsGood) { - if (imageInfos == null) { - bNameIsGood = true; // if no image information assume image name is good - } else { - boolean bNameExists = false; - for (int i = 0; i < imageInfos.length; i++) { - if (imageInfos[i].getVersion().getName().equals(newName)) { - bNameExists = true; - break; - } - } - if (!bNameExists) { - bNameIsGood = true; - } - } - if (!bNameIsGood) { - newName = TokenMangler.getNextEnumeratedToken(newName); - } - } - - return requestManager.getDocumentManager().saveAsNew(vcImage, newName); - - } - - private AsynchClientTask getSaveImageAndGeometryTask() { - - final AsynchClientTask saveImageAndGeometryTask = new AsynchClientTask("creating geometry", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - getClientTaskStatusSupport().setMessage("Getting new Geometry name..."); - String newGeometryName = null; - while (true) { - newGeometryName = ClientRequestManager.this.getMdiManager().getDatabaseWindowManager() - .showSaveDialog(((Geometry) hashTable.get("doc")).getDocumentType(), - (Component) hashTable.get(ClientRequestManager.GUI_PARENT), - (newGeometryName == null ? "NewGeometry" : newGeometryName)); - if (newGeometryName == null || newGeometryName.trim().length() == 0) { - newGeometryName = null; - DialogUtils.showWarningDialog((Component) hashTable.get(ClientRequestManager.GUI_PARENT), - "New Geometry name cannot be empty."); - continue; - } - // Check name conflict - GeometryInfo[] geometryInfos = ClientRequestManager.this.getDocumentManager().getGeometryInfos(); - boolean bNameConflict = false; - for (int i = 0; i < geometryInfos.length; i++) { - if (geometryInfos[i].getVersion().getOwner() - .equals(ClientRequestManager.this.getDocumentManager().getUser())) { - if (geometryInfos[i].getVersion().getName().equals(newGeometryName)) { - bNameConflict = true; - break; - } - } - } - if (bNameConflict) { - DialogUtils.showWarningDialog((Component) hashTable.get(ClientRequestManager.GUI_PARENT), - "A Geometry with name " + newGeometryName - + " already exists. Choose a different name."); - continue; - } else { - break; - } - } - getClientTaskStatusSupport().setMessage("Saving image portion of Geometry..."); - saveImageAutoName(ClientRequestManager.this, - ((Geometry) hashTable.get("doc")).getGeometrySpec().getImage()); - getClientTaskStatusSupport().setMessage("Saving final Geometry..."); - ClientRequestManager.this.getDocumentManager().saveAsNew((Geometry) hashTable.get("doc"), - newGeometryName); - } - }; - - return saveImageAndGeometryTask; - } - - /** - * onVCellMessageEvent method comment. - */ - public void onVCellMessageEvent(final VCellMessageEvent event) { - if (event.getEventTypeID() == VCellMessageEvent.VCELL_MESSAGEEVENT_TYPE_BROADCAST) { - DialogUtils.showInfoDialog(getMdiManager().getFocusedWindowManager().getComponent(),"Message for All VCell Users", - event.getMessageData().getData().toString()); - } - } + newName = "image_" + BeanUtils.generateDateTimeString(); + while (!bNameIsGood) { + if (imageInfos == null) { + bNameIsGood = true; // if no image information assume image name is good + } else { + boolean bNameExists = false; + for (int i = 0; i < imageInfos.length; i++) { + if (imageInfos[i].getVersion().getName().equals(newName)) { + bNameExists = true; + break; + } + } + if (!bNameExists) { + bNameIsGood = true; + } + } + if (!bNameIsGood) { + newName = TokenMangler.getNextEnumeratedToken(newName); + } + } + + return requestManager.getDocumentManager().saveAsNew(vcImage, newName); + + } + + private AsynchClientTask getSaveImageAndGeometryTask() { + + final AsynchClientTask saveImageAndGeometryTask = new AsynchClientTask("creating geometry", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + this.getClientTaskStatusSupport().setMessage("Getting new Geometry name..."); + String newGeometryName = null; + while (true) { + newGeometryName = ClientRequestManager.this.getMdiManager().getDatabaseWindowManager() + .showSaveDialog(((Geometry) hashTable.get("doc")).getDocumentType(), + (Component) hashTable.get(ClientRequestManager.GUI_PARENT), + (newGeometryName == null ? "NewGeometry" : newGeometryName)); + if (newGeometryName == null || newGeometryName.trim().length() == 0) { + newGeometryName = null; + DialogUtils.showWarningDialog((Component) hashTable.get(ClientRequestManager.GUI_PARENT), + "New Geometry name cannot be empty."); + continue; + } + // Check name conflict + GeometryInfo[] geometryInfos = ClientRequestManager.this.getDocumentManager().getGeometryInfos(); + boolean bNameConflict = false; + for (int i = 0; i < geometryInfos.length; i++) { + if (geometryInfos[i].getVersion().getOwner() + .equals(ClientRequestManager.this.getDocumentManager().getUser())) { + if (geometryInfos[i].getVersion().getName().equals(newGeometryName)) { + bNameConflict = true; + break; + } + } + } + if (bNameConflict) { + DialogUtils.showWarningDialog((Component) hashTable.get(ClientRequestManager.GUI_PARENT), + "A Geometry with name " + newGeometryName + + " already exists. Choose a different name."); + continue; + } else { + break; + } + } + this.getClientTaskStatusSupport().setMessage("Saving image portion of Geometry..."); + saveImageAutoName(ClientRequestManager.this, + ((Geometry) hashTable.get("doc")).getGeometrySpec().getImage()); + this.getClientTaskStatusSupport().setMessage("Saving final Geometry..."); + ClientRequestManager.this.getDocumentManager().saveAsNew((Geometry) hashTable.get("doc"), + newGeometryName); + } + }; + + return saveImageAndGeometryTask; + } + + /** + * onVCellMessageEvent method comment. + */ + public void onVCellMessageEvent(final VCellMessageEvent event) { + if (event.getEventTypeID() == VCellMessageEvent.VCELL_MESSAGEEVENT_TYPE_BROADCAST) { + DialogUtils.showInfoDialog(this.getMdiManager().getFocusedWindowManager().getComponent(), "Message for All VCell Users", + event.getMessageData().getData().toString()); + } + } //private void openBnglDebugger() { //try { @@ -3153,283 +3134,278 @@ public void onVCellMessageEvent(final VCellMessageEvent event) { //} //} - /** - * DocumentWindowManager hash table key - */ - private final static String WIN_MGR_KEY = "WIN_MGR_KY"; - - private void openAfterChecking(VCDocumentInfo documentInfo, final TopLevelWindowManager requester, - final boolean inNewWindow) { - - final String DOCUMENT_INFO = "documentInfo"; - final String SEDML_TASK = "SedMLTask"; - final String SEDML_MODELS = "SedMLModels"; - final String BNG_UNIT_SYSTEM = "bngUnitSystem"; - final String BMDB_DEFAULT_APPLICATION = "Deterministic"; - /* asynchronous and not blocking any window */ - bOpening = true; - Hashtable hashTable = new Hashtable(); - - // may want to insert corrected VCDocumentInfo later if our import debugger - // corrects it (BNGL Debugger). - hashTable.put(DOCUMENT_INFO, documentInfo); - hashTable.put("isBMDB", false); - hashTable.put("isSEDML", false); - - - // start a thread that gets it and updates the GUI by creating a new document - // desktop - String taskName = null; - if (documentInfo instanceof ExternalDocInfo) { - taskName = "Importing document"; - ExternalDocInfo externalDocInfo = (ExternalDocInfo) documentInfo; - - File file = externalDocInfo.getFile(); - if (file != null && !file.getName().isEmpty() && file.getName().endsWith("bngl")) { - - BngUnitSystem bngUnitSystem = new BngUnitSystem(BngUnitOrigin.DEFAULT); - String fileText; - String originalFileText; - try { - fileText = BeanUtils.readBytesFromFile(file, null); - originalFileText = new String(fileText); - } catch (IOException e1) { - e1.printStackTrace(); - DialogUtils.showErrorDialog(requester.getComponent(), - "Error reading file " + file.getPath() + ""); - return; - } - Reader reader = externalDocInfo.getReader(); - boolean bException = true; - while (bException) { - try { - BioModel bioModel = createDefaultBioModelDocument(bngUnitSystem); - boolean bStochastic = true; - boolean bRuleBased = true; - SimulationContext ruleBasedSimContext = bioModel.addNewSimulationContext("temp NFSim app", - SimulationContext.Application.RULE_BASED_STOCHASTIC); - List appList = new ArrayList(); - appList.add(ruleBasedSimContext); - - RbmModelContainer rbmModelContainer = bioModel.getModel().getRbmModelContainer(); - RbmUtils.reactionRuleLabelIndex = 0; - RbmUtils.reactionRuleNames.clear(); - ASTModel astModel = RbmUtils.importBnglFile(reader); - // TODO: if we imported a unit system from the bngl file, update bngUnitSystem - // at this point - // for now, hasUnitSystem() always returns false - if (astModel.hasUnitSystem()) { - bngUnitSystem = astModel.getUnitSystem(); - } - if (astModel.hasCompartments()) { - Structure struct = bioModel.getModel().getStructure(0); - if (struct != null) { - bioModel.getModel().removeStructure(struct, true); - } - } - BnglObjectConstructionVisitor constructionVisitor = null; - if (!astModel.hasMolecularDefinitions()) { - System.out.println("Molecular Definition Block missing."); - constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, - bngUnitSystem, false); - } else { - constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, - bngUnitSystem, true); - } - astModel.jjtAccept(constructionVisitor, rbmModelContainer); - bException = false; - } catch (final Exception e) { - e.printStackTrace(System.out); - BNGLDebuggerPanel panel = new BNGLDebuggerPanel(fileText, e); - int oKCancel = DialogUtils.showComponentOKCancelDialog(requester.getComponent(), panel, - "Bngl Debugger: " + file.getName()); - if (oKCancel == JOptionPane.CANCEL_OPTION || oKCancel == JOptionPane.DEFAULT_OPTION) { - throw new UserCancelException("Canceling Import"); - } - - // inserting corrected DocumentInfo - fileText = panel.getText(); - externalDocInfo = new ExternalDocInfo(panel.getText()); - reader = externalDocInfo.getReader(); - hashTable.put(DOCUMENT_INFO, externalDocInfo); - } - } - - if (!originalFileText.equals(fileText)) { // file has been modified - String message = "Importing " + file.getName() - + " into vCell.
Overwrite the file on the disk?
"; - message = "" + message + ""; - Object[] options = { "Overwrite and Import", "Import Only", "Cancel" }; - int returnCode = JOptionPane.showOptionDialog(requester.getComponent(), message, "Bngl Debugger", - JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2]); - if (returnCode == JOptionPane.YES_OPTION) { - try { - FileWriter fw = new FileWriter(file); - fw.write(fileText); - fw.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } else if (returnCode == JOptionPane.CANCEL_OPTION || returnCode == JOptionPane.CLOSED_OPTION) { - return; - } - } - - if (!(bngUnitSystem.getOrigin() == BngUnitOrigin.PARSER)) { - BNGLUnitsPanel panel = new BNGLUnitsPanel(bngUnitSystem); - int oKCancel = DialogUtils.showComponentOKCancelDialog(requester.getComponent(), panel, - " Bngl Units Selector", null, false); - if (oKCancel == JOptionPane.CANCEL_OPTION || oKCancel == JOptionPane.DEFAULT_OPTION) { - return; // TODO: or do nothing and continue with default values? - } else { - bngUnitSystem = panel.getUnits(); - } - } - hashTable.put(BNG_UNIT_SYSTEM, bngUnitSystem); - } else if (file != null && !file.getName().isEmpty() && (file.getName().toLowerCase().endsWith(".sedx") - || file.getName().toLowerCase().endsWith(".omex"))) { - try { - ArchiveComponents ac = null; - ac = Libsedml.readSEDMLArchive(new FileInputStream(file)); - List docs = ac.getSedmlDocuments(); - if (docs.isEmpty()) { - throw new RuntimeException("Did not find any supported SEDML files in archive " + file.getName()); - } - List sedmls = new ArrayList<>(); - for (SEDMLDocument doc : docs) { - SedML sedml =doc.getSedMLModel(); - if (sedml == null) { - throw new RuntimeException("Failed importing " + file.getName()); - } - if (sedml.getModels().isEmpty()) { - throw new RuntimeException("Unable to find any model in " + file.getName()); - } - sedmls.add(sedml); - } - hashTable.put(SEDML_MODELS, sedmls); - - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("failed to read archive: " + e.getMessage(), e); - } - } - } else { - taskName = "Loading document '" + documentInfo.getVersion().getName() + "' from database"; - } - - AsynchClientTask task0 = new AsynchClientTask(taskName, AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - public void run(Hashtable hashTable) throws Exception { - if (!inNewWindow) { - // request was to replace the document in an existing window - getMdiManager().blockWindow(requester.getManagerID()); - } - } - }; - AsynchClientTask task1 = new AsynchClientTask(taskName, AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - VCDocument doc = null; - List docs = new ArrayList<>(); - boolean isBMDB = false; - boolean isSEDML = false; - VCDocumentInfo documentInfo = (VCDocumentInfo) hashTable.get(DOCUMENT_INFO); - if (documentInfo instanceof BioModelInfo) { - BioModelInfo bmi = (BioModelInfo) documentInfo; - doc = getDocumentManager().getBioModel(bmi); - } else if (documentInfo instanceof MathModelInfo) { - MathModelInfo mmi = (MathModelInfo) documentInfo; - doc = getDocumentManager().getMathModel(mmi); - } else if (documentInfo instanceof GeometryInfo) { - GeometryInfo gmi = (GeometryInfo) documentInfo; - doc = getDocumentManager().getGeometry(gmi); - } else if (documentInfo instanceof ExternalDocInfo) { - ExternalDocInfo externalDocInfo = (ExternalDocInfo) documentInfo; - File file = externalDocInfo.getFile(); - if (file != null && !file.getName().isEmpty() && (file.getName().toLowerCase().endsWith(".sedx") - || file.getName().toLowerCase().endsWith(".omex"))) { - TranslationLogger transLogger = new TranslationLogger(requester); - // iterate through one or more SEDML objects - List sedmls = (List) hashTable.get(SEDML_MODELS); - for (SedML sedml : sedmls) { - // default to import all tasks - List vcdocs = XmlHelper.importSEDML(transLogger, externalDocInfo, sedml, false); - for (VCDocument vcdoc : vcdocs) { - docs.add(vcdoc); - } - } - isSEDML = true; // treat the same since OMEX is just and archive with SED-ML file(s) - } else if (!externalDocInfo.isXML()) { - if (hashTable.containsKey(BNG_UNIT_SYSTEM)) { // not XML, look for BNGL etc. - // we use the BngUnitSystem already created during the 1st pass - BngUnitSystem bngUnitSystem = (BngUnitSystem) hashTable.get(BNG_UNIT_SYSTEM); - BioModel bioModel = createDefaultBioModelDocument(bngUnitSystem); - - SimulationContext ruleBasedSimContext = bioModel.addNewSimulationContext("NFSim app", - SimulationContext.Application.RULE_BASED_STOCHASTIC); - SimulationContext odeSimContext = bioModel.addNewSimulationContext("BioNetGen app", - SimulationContext.Application.NETWORK_DETERMINISTIC); - List appList = new ArrayList(); - appList.add(ruleBasedSimContext); - appList.add(odeSimContext); - // set convention for initial conditions in generated application for seed - // species (concentration or count) - ruleBasedSimContext.setUsingConcentration(bngUnitSystem.isConcentration(), false); - odeSimContext.setUsingConcentration(bngUnitSystem.isConcentration(), false); - - RbmModelContainer rbmModelContainer = bioModel.getModel().getRbmModelContainer(); - RbmUtils.reactionRuleLabelIndex = 0; - RbmUtils.reactionRuleNames.clear(); - Reader reader = externalDocInfo.getReader(); - ASTModel astModel = RbmUtils.importBnglFile(reader); - if (bioModel.getModel() != null && bioModel.getModel().getVcMetaData() != null) { - VCMetaData vcMetaData = bioModel.getModel().getVcMetaData(); - vcMetaData.setFreeTextAnnotation(bioModel, astModel.getProlog()); - } - if (astModel.hasCompartments()) { - Structure struct = bioModel.getModel().getStructure(0); - if (struct != null) { - bioModel.getModel().removeStructure(struct, true); - } - } - - BnglObjectConstructionVisitor constructionVisitor = null; - if (!astModel.hasMolecularDefinitions()) { - System.out.println( - "Molecular Definition Block missing. Extracting it from Species, Reactions, Obserbables."); - constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, - bngUnitSystem, false); - } else { - constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, - bngUnitSystem, true); - } - // we'll convert the kinetic parameters to BngUnitSystem inside the - // visit(ASTKineticsParameter...) - astModel.jjtAccept(constructionVisitor, rbmModelContainer); - - // set the volume in the newly created application to - // BngUnitSystem.bnglModelVolume - // TODO: set the right values if we import compartments from the bngl file! + /** + * DocumentWindowManager hash table key + */ + private final static String WIN_MGR_KEY = "WIN_MGR_KY"; + + private void openAfterChecking(VCDocumentInfo documentInfo, final TopLevelWindowManager requester, + final boolean inNewWindow) { + + final String DOCUMENT_INFO = "documentInfo"; + final String SEDML_TASK = "SedMLTask"; + final String SEDML_MODELS = "SedMLModels"; + final String BNG_UNIT_SYSTEM = "bngUnitSystem"; + final String BMDB_DEFAULT_APPLICATION = "Deterministic"; + /* asynchronous and not blocking any window */ + this.bOpening = true; + Hashtable hashTable = new Hashtable(); + + // may want to insert corrected VCDocumentInfo later if our import debugger + // corrects it (BNGL Debugger). + hashTable.put(DOCUMENT_INFO, documentInfo); + hashTable.put("isBMDB", false); + hashTable.put("isSEDML", false); + + + // start a thread that gets it and updates the GUI by creating a new document + // desktop + String taskName = null; + if (documentInfo instanceof ExternalDocInfo externalDocInfo) { + taskName = "Importing document"; + + File file = externalDocInfo.getFile(); + if (file != null && !file.getName().isEmpty() && file.getName().endsWith("bngl")) { + + BngUnitSystem bngUnitSystem = new BngUnitSystem(BngUnitOrigin.DEFAULT); + String fileText; + String originalFileText; + try { + fileText = BeanUtils.readBytesFromFile(file, null); + originalFileText = fileText; + } catch (IOException e1) { + e1.printStackTrace(); + DialogUtils.showErrorDialog(requester.getComponent(), + "Error reading file " + file.getPath() + ""); + return; + } + Reader reader = externalDocInfo.getReader(); + boolean bException = true; + while (bException) { + try { + BioModel bioModel = this.createDefaultBioModelDocument(bngUnitSystem); + boolean bStochastic = true; + boolean bRuleBased = true; + SimulationContext ruleBasedSimContext = bioModel.addNewSimulationContext("temp NFSim app", + SimulationContext.Application.RULE_BASED_STOCHASTIC); + List appList = new ArrayList(); + appList.add(ruleBasedSimContext); + + RbmModelContainer rbmModelContainer = bioModel.getModel().getRbmModelContainer(); + RbmUtils.reactionRuleLabelIndex = 0; + RbmUtils.reactionRuleNames.clear(); + ASTModel astModel = RbmUtils.importBnglFile(reader); + // TODO: if we imported a unit system from the bngl file, update bngUnitSystem + // at this point + // for now, hasUnitSystem() always returns false + if (astModel.hasUnitSystem()) { + bngUnitSystem = astModel.getUnitSystem(); + } + if (astModel.hasCompartments()) { + Structure struct = bioModel.getModel().getStructure(0); + if (struct != null) { + bioModel.getModel().removeStructure(struct, true); + } + } + BnglObjectConstructionVisitor constructionVisitor = null; + if (!astModel.hasMolecularDefinitions()) { + System.out.println("Molecular Definition Block missing."); + constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, + bngUnitSystem, false); + } else { + constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, + bngUnitSystem, true); + } + astModel.jjtAccept(constructionVisitor, rbmModelContainer); + bException = false; + } catch (final Exception e) { + e.printStackTrace(System.out); + BNGLDebuggerPanel panel = new BNGLDebuggerPanel(fileText, e); + int oKCancel = DialogUtils.showComponentOKCancelDialog(requester.getComponent(), panel, + "Bngl Debugger: " + file.getName()); + if (oKCancel == JOptionPane.CANCEL_OPTION || oKCancel == JOptionPane.DEFAULT_OPTION) { + throw new UserCancelException("Canceling Import"); + } + + // inserting corrected DocumentInfo + fileText = panel.getText(); + externalDocInfo = new ExternalDocInfo(panel.getText()); + reader = externalDocInfo.getReader(); + hashTable.put(DOCUMENT_INFO, externalDocInfo); + } + } + + if (!originalFileText.equals(fileText)) { // file has been modified + String message = "Importing " + file.getName() + + " into vCell.
Overwrite the file on the disk?
"; + message = "" + message + ""; + Object[] options = {"Overwrite and Import", "Import Only", "Cancel"}; + int returnCode = JOptionPane.showOptionDialog(requester.getComponent(), message, "Bngl Debugger", + JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2]); + if (returnCode == JOptionPane.YES_OPTION) { + try { + FileWriter fw = new FileWriter(file); + fw.write(fileText); + fw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else if (returnCode == JOptionPane.CANCEL_OPTION || returnCode == JOptionPane.CLOSED_OPTION) { + return; + } + } + + if (!(bngUnitSystem.getOrigin() == BngUnitOrigin.PARSER)) { + BNGLUnitsPanel panel = new BNGLUnitsPanel(bngUnitSystem); + int oKCancel = DialogUtils.showComponentOKCancelDialog(requester.getComponent(), panel, + " Bngl Units Selector", null, false); + if (oKCancel == JOptionPane.CANCEL_OPTION || oKCancel == JOptionPane.DEFAULT_OPTION) { + return; // TODO: or do nothing and continue with default values? + } else { + bngUnitSystem = panel.getUnits(); + } + } + hashTable.put(BNG_UNIT_SYSTEM, bngUnitSystem); + } else if (file != null && !file.getName().isEmpty() && (file.getName().toLowerCase().endsWith(".sedx") + || file.getName().toLowerCase().endsWith(".omex"))) { + try { + ArchiveComponents ac = null; + ac = Libsedml.readSEDMLArchive(new FileInputStream(file)); + List docs = ac.getSedmlDocuments(); + if (docs.isEmpty()) { + throw new RuntimeException("Did not find any supported SEDML files in archive " + file.getName()); + } + List sedmls = new ArrayList<>(); + for (SEDMLDocument doc : docs) { + SedML sedml = doc.getSedMLModel(); + if (sedml == null) { + throw new RuntimeException("Failed importing " + file.getName()); + } + if (sedml.getModels().isEmpty()) { + throw new RuntimeException("Unable to find any model in " + file.getName()); + } + sedmls.add(sedml); + } + hashTable.put(SEDML_MODELS, sedmls); + + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("failed to read archive: " + e.getMessage(), e); + } + } + } else { + taskName = "Loading document '" + documentInfo.getVersion().getName() + "' from database"; + } + + AsynchClientTask task0 = new AsynchClientTask(taskName, AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + public void run(Hashtable hashTable) throws Exception { + if (!inNewWindow) { + // request was to replace the document in an existing window + ClientRequestManager.this.getMdiManager().blockWindow(requester.getManagerID()); + } + } + }; + AsynchClientTask task1 = new AsynchClientTask(taskName, AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + VCDocument doc = null; + List docs = new ArrayList<>(); + boolean isBMDB = false; + boolean isSEDML = false; + VCDocumentInfo documentInfo = (VCDocumentInfo) hashTable.get(DOCUMENT_INFO); + if (documentInfo instanceof BioModelInfo bmi) { + doc = ClientRequestManager.this.getDocumentManager().getBioModel(bmi); + } else if (documentInfo instanceof MathModelInfo mmi) { + doc = ClientRequestManager.this.getDocumentManager().getMathModel(mmi); + } else if (documentInfo instanceof GeometryInfo gmi) { + doc = ClientRequestManager.this.getDocumentManager().getGeometry(gmi); + } else if (documentInfo instanceof ExternalDocInfo externalDocInfo) { + File file = externalDocInfo.getFile(); + if (file != null && !file.getName().isEmpty() && (file.getName().toLowerCase().endsWith(".sedx") + || file.getName().toLowerCase().endsWith(".omex"))) { + TranslationLogger transLogger = new TranslationLogger(requester); + // iterate through one or more SEDML objects + List sedmls = (List) hashTable.get(SEDML_MODELS); + for (SedML sedml : sedmls) { + // default to import all tasks + List vcdocs = XmlHelper.importSEDML(transLogger, externalDocInfo, sedml, false); + for (VCDocument vcdoc : vcdocs) { + docs.add(vcdoc); + } + } + isSEDML = true; // treat the same since OMEX is just and archive with SED-ML file(s) + } else if (!externalDocInfo.isXML()) { + if (hashTable.containsKey(BNG_UNIT_SYSTEM)) { // not XML, look for BNGL etc. + // we use the BngUnitSystem already created during the 1st pass + BngUnitSystem bngUnitSystem = (BngUnitSystem) hashTable.get(BNG_UNIT_SYSTEM); + BioModel bioModel = ClientRequestManager.this.createDefaultBioModelDocument(bngUnitSystem); + + SimulationContext ruleBasedSimContext = bioModel.addNewSimulationContext("NFSim app", + SimulationContext.Application.RULE_BASED_STOCHASTIC); + SimulationContext odeSimContext = bioModel.addNewSimulationContext("BioNetGen app", + SimulationContext.Application.NETWORK_DETERMINISTIC); + List appList = new ArrayList(); + appList.add(ruleBasedSimContext); + appList.add(odeSimContext); + // set convention for initial conditions in generated application for seed + // species (concentration or count) + ruleBasedSimContext.setUsingConcentration(bngUnitSystem.isConcentration(), false); + odeSimContext.setUsingConcentration(bngUnitSystem.isConcentration(), false); + + RbmModelContainer rbmModelContainer = bioModel.getModel().getRbmModelContainer(); + RbmUtils.reactionRuleLabelIndex = 0; + RbmUtils.reactionRuleNames.clear(); + Reader reader = externalDocInfo.getReader(); + ASTModel astModel = RbmUtils.importBnglFile(reader); + if (bioModel.getModel() != null && bioModel.getModel().getVcMetaData() != null) { + VCMetaData vcMetaData = bioModel.getModel().getVcMetaData(); + vcMetaData.setFreeTextAnnotation(bioModel, astModel.getProlog()); + } + if (astModel.hasCompartments()) { + Structure struct = bioModel.getModel().getStructure(0); + if (struct != null) { + bioModel.getModel().removeStructure(struct, true); + } + } + + BnglObjectConstructionVisitor constructionVisitor = null; + if (!astModel.hasMolecularDefinitions()) { + System.out.println( + "Molecular Definition Block missing. Extracting it from Species, Reactions, Obserbables."); + constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, + bngUnitSystem, false); + } else { + constructionVisitor = new BnglObjectConstructionVisitor(bioModel.getModel(), appList, + bngUnitSystem, true); + } + // we'll convert the kinetic parameters to BngUnitSystem inside the + // visit(ASTKineticsParameter...) + astModel.jjtAccept(constructionVisitor, rbmModelContainer); + + // set the volume in the newly created application to + // BngUnitSystem.bnglModelVolume + // TODO: set the right values if we import compartments from the bngl file! // if(!bngUnitSystem.isConcentration()) { - Expression sizeExpression = new Expression(bngUnitSystem.getVolume()); - ruleBasedSimContext.getGeometryContext().getStructureMapping(0).getSizeParameter() - .setExpression(sizeExpression); - odeSimContext.getGeometryContext().getStructureMapping(0).getSizeParameter() - .setExpression(sizeExpression); + Expression sizeExpression = new Expression(bngUnitSystem.getVolume()); + ruleBasedSimContext.getGeometryContext().getStructureMapping(0).getSizeParameter() + .setExpression(sizeExpression); + odeSimContext.getGeometryContext().getStructureMapping(0).getSizeParameter() + .setExpression(sizeExpression); // } - // we remove the NFSim application if any seed species is clamped because NFSim - // doesn't know what to do with it - boolean bClamped = false; - for (SpeciesContextSpec scs : ruleBasedSimContext.getReactionContext() - .getSpeciesContextSpecs()) { - if (scs.isConstant()) { - bClamped = true; - break; - } - } - if (bClamped) { - bioModel.removeSimulationContext(ruleBasedSimContext); - } + // we remove the NFSim application if any seed species is clamped because NFSim + // doesn't know what to do with it + boolean bClamped = false; + for (SpeciesContextSpec scs : ruleBasedSimContext.getReactionContext() + .getSpeciesContextSpecs()) { + if (scs.isConstant()) { + bClamped = true; + break; + } + } + if (bClamped) { + bioModel.removeSimulationContext(ruleBasedSimContext); + } // // TODO: DON'T delete this code // // the code below is needed if we also want to create simulations, example for 1 rule based simulation @@ -3439,1143 +3415,1132 @@ public void run(Hashtable hashTable) throws Exception { // ruleBasedSimContext.refreshMathDescription(callback,networkGenerationRequirements); // Simulation sim = ruleBasedSimContext.addNewSimulation(SimulationOwner.DEFAULT_SIM_NAME_PREFIX,callback,networkGenerationRequirements); - doc = bioModel; - } - } else { // is XML - try (TranslationLogger transLogger = new TranslationLogger(requester)) { - XMLSource xmlSource = externalDocInfo.createXMLSource(); - org.jdom.Element rootElement = xmlSource.getXmlDoc().getRootElement(); - String xmlType = rootElement.getName(); - String modelXmlType = null; - if (xmlType.equals(XMLTags.VcmlRootNodeTag)) { - // For now, assuming that element has only one child (biomodel, mathmodel - // or geometry). - // Will deal with multiple children of Element when we get to model - // composition. - @SuppressWarnings("unchecked") - List childElementList = rootElement.getChildren(); - Element modelElement = childElementList.get(0); // assuming first child is the biomodel, - // mathmodel or geometry. - modelXmlType = modelElement.getName(); - } - if (xmlType.equals(XMLTags.BioModelTag) || (xmlType.equals(XMLTags.VcmlRootNodeTag) - && modelXmlType.equals(XMLTags.BioModelTag))) { - doc = XmlHelper.XMLToBioModel(xmlSource); - } else if (xmlType.equals(XMLTags.MathModelTag) || (xmlType.equals(XMLTags.VcmlRootNodeTag) - && modelXmlType.equals(XMLTags.MathModelTag))) { - doc = XmlHelper.XMLToMathModel(xmlSource); - } else if (xmlType.equals(XMLTags.GeometryTag) || (xmlType.equals(XMLTags.VcmlRootNodeTag) - && modelXmlType.equals(XMLTags.GeometryTag))) { - doc = XmlHelper.XMLToGeometry(xmlSource); - } else if (xmlType.equals(XMLTags.SbmlRootNodeTag)) { - Namespace namespace = rootElement.getNamespace(XMLTags.SBML_SPATIAL_NS_PREFIX); - isBMDB = externalDocInfo.isBioModelsNet(); - boolean bIsSpatial = (namespace == null) ? false : true; - doc = XmlHelper.importSBML(transLogger, xmlSource, bIsSpatial); - } else if (xmlType.equals(XMLTags.CellmlRootNodeTag)) { - if (requester instanceof BioModelWindowManager) { - doc = XmlHelper.importBioCellML(transLogger, xmlSource); - } else { - doc = XmlHelper.importMathCellML(transLogger, xmlSource); - } - } else if (xmlType.equals(MicroscopyXMLTags.FRAPStudyTag)) { - doc = VFrapXmlHelper.VFRAPToBioModel(hashTable, xmlSource, getDocumentManager(), - requester); - } else if (xmlType.equals(XMLTags.SedMLTypeTag)) { - File sedmlFile = xmlSource.getXmlFile(); - SedML sedml = Libsedml.readDocument(sedmlFile).getSedMLModel(); - if (sedml == null) { - throw new RuntimeException("Failed importing " + file.getName()); - } - if (sedml.getModels().isEmpty()) { - throw new RuntimeException("Unable to find any model in " + file.getName()); - } - List sedmls = new ArrayList<>(); - sedmls.add(sedml); - hashTable.put(SEDML_MODELS, sedmls); - - // default to import all tasks - List vcdocs = XmlHelper.importSEDML(transLogger, externalDocInfo, sedml, false); - for (VCDocument vcdoc : vcdocs) { - docs.add(vcdoc); - } - - isSEDML = true; - } else { // unknown XML format - throw new RuntimeException( - "unsupported XML format, first element tag is <" + rootElement.getName() + ">"); - } - if (externalDocInfo.getDefaultName() != null) { - doc.setName(externalDocInfo.getDefaultName()); - } - } - } - if (doc == null && docs == null) { - File f = externalDocInfo.getFile(); - if (f != null) { - throw new RuntimeException("Unable to determine type of file " + f.getCanonicalPath()); - } - throw new ProgrammingException(); - } - } - // create biopax objects using annotation - if (doc instanceof BioModel) { - BioModel bioModel = (BioModel) doc; - try { - bioModel.getVCMetaData().createBioPaxObjects(bioModel); - } catch (Exception e) { - e.printStackTrace(); - } - } - requester.prepareDocumentToLoad(doc, inNewWindow); - hashTable.put("isBMDB", isBMDB); - hashTable.put("isSEDML", isSEDML); - if (!isSEDML) { - hashTable.put("doc", doc); - } else { - hashTable.put("docs", docs); - } - } - }; - - AsynchClientTask task2 = new AsynchClientTask("Showing document", AsynchClientTask.TASKTYPE_SWING_BLOCKING, - false, false) { - @Override - public void run(Hashtable hashTable) throws Exception { - try { - Throwable exc = (Throwable) hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); - if (exc == null) { - boolean isSEDML = (boolean) hashTable.get("isSEDML"); - if (isSEDML) { - List docs = (List) hashTable.get("docs"); - List windowManagers = new ArrayList(); - for (VCDocument doc : docs) { - DocumentWindowManager windowManager = createDocumentWindowManager(doc); - getMdiManager().createNewDocumentWindow(windowManager); - windowManagers.add(windowManager); - } - hashTable.put("managers", windowManagers); - hashTable.put("docs", docs); - } else { - VCDocument doc = (VCDocument) hashTable.get("doc"); - DocumentWindowManager windowManager = null; - if (inNewWindow) { - windowManager = createDocumentWindowManager(doc); - // request was to create a new top-level window with this doc - getMdiManager().createNewDocumentWindow(windowManager); - - } else { - // request was to replace the document in an existing window - windowManager = (DocumentWindowManager) requester; - getMdiManager().setCanonicalTitle(requester.getManagerID()); - windowManager.resetDocument(doc); - } - hashTable.put(WIN_MGR_KEY, windowManager); - hashTable.put("doc", doc); - } - } - } catch(Exception ex) { - ex.printStackTrace(); - // TODO: check why getMdiManager().createNewDocumentWindow(windowManager) fails sometimes - } finally { - if (!inNewWindow) { - getMdiManager().unBlockWindow(requester.getManagerID()); - } - bOpening = false; - } - } - }; - AsynchClientTask task3 = new AsynchClientTask("Special Layout", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, - false) { - @Override - public void run(Hashtable hashTable) throws Exception { - if (documentInfo instanceof ExternalDocInfo) { - ExternalDocInfo externalDocInfo = (ExternalDocInfo) documentInfo; - boolean isSEDML = (boolean) hashTable.get("isSEDML"); - if (externalDocInfo.isBioModelsNet() || externalDocInfo.isFromXmlFile() || (!isSEDML && !externalDocInfo.isFromVcmlFile())) { - DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get(WIN_MGR_KEY); - if (windowManager instanceof BioModelWindowManager) { - ((BioModelWindowManager) windowManager).specialLayout(); - } - } - if (isSEDML) { - List windowManagers = (List) hashTable.get("managers"); - if(windowManagers != null) { - for (DocumentWindowManager manager : windowManagers) { - ((BioModelWindowManager) manager).specialLayout(); - } - } - } - } - } - }; - AsynchClientTask task4 = new AsynchClientTaskFunction(ClientRequestManager::setWindowFocus, "Set window focus", - AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false); - - AsynchClientTask task6 = new AsynchClientTask("Renaming, please wait...", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING, false, false) { // TASKTYPE_NONSWING_BLOCKING - @Override - public void run(Hashtable hashTable) throws Exception { - VCDocument doc = (VCDocument) hashTable.get("doc"); - if(!(doc instanceof BioModel)) { - return; - } - boolean isBMDB = (boolean) hashTable.get("isBMDB"); - if (documentInfo instanceof ExternalDocInfo) { - if (isBMDB) { - idToNameConversion(doc); - } - } - if (isBMDB) { - BioModel bioModel = (BioModel) doc; - SimulationContext simulationContext = bioModel.getSimulationContext(0); - simulationContext.setName(BMDB_DEFAULT_APPLICATION); - try { - simulationContext.updateAll(false); - MathDescription mathDesc = simulationContext.getMathDescription(); - - Simulation sim = new Simulation(mathDesc, simulationContext); - sim.setName(simulationContext.getBioModel().getFreeSimulationName()); - simulationContext.addSimulation(sim); - bioModel.refreshDependencies(); - - } catch (MappingException e1) { - e1.printStackTrace(); - } - hashTable.put("doc", doc); - } - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), hashTable, - new AsynchClientTask[] { task0, task1, task6, task2, task3, task4 }, false); - } - - private static boolean isRestrictedXYZT(String name, BioModel vcBioModel) { - - ReservedSymbol rs = vcBioModel.getModel().getReservedSymbolByName(name); - if (rs == null) { - return false; - } - if (rs.isX() || rs.isY() || rs.isZ() || rs.isTime()) { - return true; - } - return false; - } - - public static void idToNameConversion(VCDocument vcDoc) { - if (!(vcDoc instanceof BioModel)) { - return; - } - BioModel vcBioModel = (BioModel) vcDoc; - vcBioModel.getSimulationContext(0).setbIgnoreEvents(true); - Map entitiesToRename = new LinkedHashMap<>(); - - for (SpeciesContext sc : vcBioModel.getModel().getSpeciesContexts()) { - String id = sc.getName(); - String name = sc.getSbmlName(); - if (name == null || name.isEmpty()) { - continue; - } - if(id.equals(name)) { - continue; - } - if (isRestrictedXYZT(name, vcBioModel)) { - continue; - } - name = TokenMangler.fixTokenStrict(name, 60); - while (true) { - if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { - break; - } - name = TokenMangler.getNextEnumeratedToken(name); - } - if (id.equals(name)) { - continue; - } - try { - System.out.println(name + " <-- " + id); - sc.setName(name); - } catch (PropertyVetoException e) { - e.printStackTrace(); // we just keep the id rather than abort - } - entitiesToRename.put(id, name); - } - - for (ModelParameter mp : vcBioModel.getModel().getModelParameters()) { - String id = mp.getName(); - String name = mp.getSbmlName(); - if (name == null || name.isEmpty()) { - continue; - } - if(id.equals(name)) { - continue; - } - if (isRestrictedXYZT(name, vcBioModel)) { - continue; - } - name = TokenMangler.fixTokenStrict(name, 60); - while (true) { - if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { - break; - } - name = TokenMangler.getNextEnumeratedToken(name); - } - if (id.equals(name)) { - continue; - } - try { - System.out.println(name + " <-- " + id); - mp.setName(name); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - entitiesToRename.put(id, name); - } - for(Structure struct : vcBioModel.getModel().getStructures()) { - String id = struct.getName(); - String name = struct.getSbmlName(); - if(name == null || name.isEmpty()) { - continue; - } - if(id.equals(name)) { - continue; - } - if(isRestrictedXYZT(name, vcBioModel)) { - continue; - } - name = TokenMangler.fixTokenStrict(name, 60); - while (true) { - if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { - break; - } - name = TokenMangler.getNextEnumeratedToken(name); - } - if(id.equals(name)) { - continue; - } - try { - System.out.println(name + " <-- " + id); - struct.setName(name, true); - } catch(PropertyVetoException e) { - e.printStackTrace(); - } - entitiesToRename.put(id, name); - } - vcBioModel.getSimulationContext(0).substituteChangedNamesInExpressions(entitiesToRename); - - for (ReactionStep rs : vcBioModel.getModel().getReactionSteps()) { - String id = rs.getName(); - String name = rs.getSbmlName(); - if (name == null || name.isEmpty()) { - continue; - } - if(id.equals(name)) { - continue; - } - if (isRestrictedXYZT(name, vcBioModel)) { - continue; - } + doc = bioModel; + } + } else { // is XML + try (TranslationLogger transLogger = new TranslationLogger(requester)) { + XMLSource xmlSource = externalDocInfo.createXMLSource(); + org.jdom.Element rootElement = xmlSource.getXmlDoc().getRootElement(); + String xmlType = rootElement.getName(); + String modelXmlType = null; + if (xmlType.equals(XMLTags.VcmlRootNodeTag)) { + // For now, assuming that element has only one child (biomodel, mathmodel + // or geometry). + // Will deal with multiple children of Element when we get to model + // composition. + @SuppressWarnings("unchecked") + List childElementList = rootElement.getChildren(); + Element modelElement = childElementList.get(0); // assuming first child is the biomodel, + // mathmodel or geometry. + modelXmlType = modelElement.getName(); + } + if (xmlType.equals(XMLTags.BioModelTag) || (xmlType.equals(XMLTags.VcmlRootNodeTag) + && modelXmlType.equals(XMLTags.BioModelTag))) { + doc = XmlHelper.XMLToBioModel(xmlSource); + } else if (xmlType.equals(XMLTags.MathModelTag) || (xmlType.equals(XMLTags.VcmlRootNodeTag) + && modelXmlType.equals(XMLTags.MathModelTag))) { + doc = XmlHelper.XMLToMathModel(xmlSource); + } else if (xmlType.equals(XMLTags.GeometryTag) || (xmlType.equals(XMLTags.VcmlRootNodeTag) + && modelXmlType.equals(XMLTags.GeometryTag))) { + doc = XmlHelper.XMLToGeometry(xmlSource); + } else if (xmlType.equals(XMLTags.SbmlRootNodeTag)) { + Namespace namespace = rootElement.getNamespace(XMLTags.SBML_SPATIAL_NS_PREFIX); + isBMDB = externalDocInfo.isBioModelsNet(); + boolean bIsSpatial = namespace != null; + doc = XmlHelper.importSBML(transLogger, xmlSource, bIsSpatial); + } else if (xmlType.equals(XMLTags.CellmlRootNodeTag)) { + if (requester instanceof BioModelWindowManager) { + doc = XmlHelper.importBioCellML(transLogger, xmlSource); + } else { + doc = XmlHelper.importMathCellML(transLogger, xmlSource); + } + } else if (xmlType.equals(MicroscopyXMLTags.FRAPStudyTag)) { + doc = VFrapXmlHelper.VFRAPToBioModel(hashTable, xmlSource, ClientRequestManager.this.getDocumentManager(), + requester); + } else if (xmlType.equals(XMLTags.SedMLTypeTag)) { + File sedmlFile = xmlSource.getXmlFile(); + SedML sedml = Libsedml.readDocument(sedmlFile).getSedMLModel(); + if (sedml == null) { + throw new RuntimeException("Failed importing " + file.getName()); + } + if (sedml.getModels().isEmpty()) { + throw new RuntimeException("Unable to find any model in " + file.getName()); + } + List sedmls = new ArrayList<>(); + sedmls.add(sedml); + hashTable.put(SEDML_MODELS, sedmls); + + // default to import all tasks + List vcdocs = XmlHelper.importSEDML(transLogger, externalDocInfo, sedml, false); + for (VCDocument vcdoc : vcdocs) { + docs.add(vcdoc); + } + + isSEDML = true; + } else { // unknown XML format + throw new RuntimeException( + "unsupported XML format, first element tag is <" + rootElement.getName() + ">"); + } + if (externalDocInfo.getDefaultName() != null) { + doc.setName(externalDocInfo.getDefaultName()); + } + } + } + if (doc == null && docs == null) { + File f = externalDocInfo.getFile(); + if (f != null) { + throw new RuntimeException("Unable to determine type of file " + f.getCanonicalPath()); + } + throw new ProgrammingException(); + } + } + // create biopax objects using annotation + if (doc instanceof BioModel bioModel) { + try { + bioModel.getVCMetaData().createBioPaxObjects(bioModel); + } catch (Exception e) { + e.printStackTrace(); + } + } + requester.prepareDocumentToLoad(doc, inNewWindow); + hashTable.put("isBMDB", isBMDB); + hashTable.put("isSEDML", isSEDML); + if (!isSEDML) { + hashTable.put("doc", doc); + } else { + hashTable.put("docs", docs); + } + } + }; + + AsynchClientTask task2 = new AsynchClientTask("Showing document", AsynchClientTask.TASKTYPE_SWING_BLOCKING, + false, false) { + @Override + public void run(Hashtable hashTable) throws Exception { + try { + Throwable exc = (Throwable) hashTable.get(swingthreads.TaskEventKeys.TASK_ABORTED_BY_ERROR.toString()); + if (exc == null) { + boolean isSEDML = (boolean) hashTable.get("isSEDML"); + if (isSEDML) { + List docs = (List) hashTable.get("docs"); + List windowManagers = new ArrayList(); + for (VCDocument doc : docs) { + DocumentWindowManager windowManager = ClientRequestManager.this.createDocumentWindowManager(doc); + ClientRequestManager.this.getMdiManager().createNewDocumentWindow(windowManager); + windowManagers.add(windowManager); + } + hashTable.put("managers", windowManagers); + hashTable.put("docs", docs); + } else { + VCDocument doc = (VCDocument) hashTable.get("doc"); + DocumentWindowManager windowManager = null; + if (inNewWindow) { + windowManager = ClientRequestManager.this.createDocumentWindowManager(doc); + // request was to create a new top-level window with this doc + ClientRequestManager.this.getMdiManager().createNewDocumentWindow(windowManager); + + } else { + // request was to replace the document in an existing window + windowManager = (DocumentWindowManager) requester; + ClientRequestManager.this.getMdiManager().setCanonicalTitle(requester.getManagerID()); + windowManager.resetDocument(doc); + } + hashTable.put(WIN_MGR_KEY, windowManager); + hashTable.put("doc", doc); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + // TODO: check why getMdiManager().createNewDocumentWindow(windowManager) fails sometimes + } finally { + if (!inNewWindow) { + ClientRequestManager.this.getMdiManager().unBlockWindow(requester.getManagerID()); + } + ClientRequestManager.this.bOpening = false; + } + } + }; + AsynchClientTask task3 = new AsynchClientTask("Special Layout", AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, + false) { + @Override + public void run(Hashtable hashTable) throws Exception { + if (documentInfo instanceof ExternalDocInfo externalDocInfo) { + boolean isSEDML = (boolean) hashTable.get("isSEDML"); + if (externalDocInfo.isBioModelsNet() || externalDocInfo.isFromXmlFile() || (!isSEDML && !externalDocInfo.isFromVcmlFile())) { + DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get(WIN_MGR_KEY); + if (windowManager instanceof BioModelWindowManager) { + ((BioModelWindowManager) windowManager).specialLayout(); + } + } + if (isSEDML) { + List windowManagers = (List) hashTable.get("managers"); + if (windowManagers != null) { + for (DocumentWindowManager manager : windowManagers) { + ((BioModelWindowManager) manager).specialLayout(); + } + } + } + } + } + }; + AsynchClientTask task4 = new AsynchClientTaskFunction(ClientRequestManager::setWindowFocus, "Set window focus", + AsynchClientTask.TASKTYPE_SWING_BLOCKING, false, false); + + AsynchClientTask task6 = new AsynchClientTask("Renaming, please wait...", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING, false, false) { // TASKTYPE_NONSWING_BLOCKING + @Override + public void run(Hashtable hashTable) throws Exception { + VCDocument doc = (VCDocument) hashTable.get("doc"); + if (!(doc instanceof BioModel)) { + return; + } + boolean isBMDB = (boolean) hashTable.get("isBMDB"); + if (documentInfo instanceof ExternalDocInfo) { + if (isBMDB) { + idToNameConversion(doc); + } + } + if (isBMDB) { + BioModel bioModel = (BioModel) doc; + SimulationContext simulationContext = bioModel.getSimulationContext(0); + simulationContext.setName(BMDB_DEFAULT_APPLICATION); + try { + simulationContext.updateAll(false); + MathDescription mathDesc = simulationContext.getMathDescription(); + + Simulation sim = new Simulation(mathDesc, simulationContext); + sim.setName(simulationContext.getBioModel().getFreeSimulationName()); + simulationContext.addSimulation(sim); + bioModel.refreshDependencies(); + + } catch (MappingException e1) { + e1.printStackTrace(); + } + hashTable.put("doc", doc); + } + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), hashTable, + new AsynchClientTask[]{task0, task1, task6, task2, task3, task4}, false); + } + + private static boolean isRestrictedXYZT(String name, BioModel vcBioModel) { + + ReservedSymbol rs = vcBioModel.getModel().getReservedSymbolByName(name); + if (rs == null) { + return false; + } + return rs.isX() || rs.isY() || rs.isZ() || rs.isTime(); + } + + public static void idToNameConversion(VCDocument vcDoc) { + if (!(vcDoc instanceof BioModel vcBioModel)) { + return; + } + vcBioModel.getSimulationContext(0).setbIgnoreEvents(true); + Map entitiesToRename = new LinkedHashMap<>(); + + for (SpeciesContext sc : vcBioModel.getModel().getSpeciesContexts()) { + String id = sc.getName(); + String name = sc.getSbmlName(); + if (name == null || name.isEmpty()) { + continue; + } + if (id.equals(name)) { + continue; + } + if (isRestrictedXYZT(name, vcBioModel)) { + continue; + } + name = TokenMangler.fixTokenStrict(name, 60); + while (true) { + if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { + break; + } + name = TokenMangler.getNextEnumeratedToken(name); + } + if (id.equals(name)) { + continue; + } + try { + System.out.println(name + " <-- " + id); + sc.setName(name); + } catch (PropertyVetoException e) { + e.printStackTrace(); // we just keep the id rather than abort + } + entitiesToRename.put(id, name); + } + + for (ModelParameter mp : vcBioModel.getModel().getModelParameters()) { + String id = mp.getName(); + String name = mp.getSbmlName(); + if (name == null || name.isEmpty()) { + continue; + } + if (id.equals(name)) { + continue; + } + if (isRestrictedXYZT(name, vcBioModel)) { + continue; + } + name = TokenMangler.fixTokenStrict(name, 60); + while (true) { + if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { + break; + } + name = TokenMangler.getNextEnumeratedToken(name); + } + if (id.equals(name)) { + continue; + } + try { + System.out.println(name + " <-- " + id); + mp.setName(name); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + entitiesToRename.put(id, name); + } + for (Structure struct : vcBioModel.getModel().getStructures()) { + String id = struct.getName(); + String name = struct.getSbmlName(); + if (name == null || name.isEmpty()) { + continue; + } + if (id.equals(name)) { + continue; + } + if (isRestrictedXYZT(name, vcBioModel)) { + continue; + } + name = TokenMangler.fixTokenStrict(name, 60); + while (true) { + if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { + break; + } + name = TokenMangler.getNextEnumeratedToken(name); + } + if (id.equals(name)) { + continue; + } + try { + System.out.println(name + " <-- " + id); + struct.setName(name, true); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + entitiesToRename.put(id, name); + } + vcBioModel.getSimulationContext(0).substituteChangedNamesInExpressions(entitiesToRename); + + for (ReactionStep rs : vcBioModel.getModel().getReactionSteps()) { + String id = rs.getName(); + String name = rs.getSbmlName(); + if (name == null || name.isEmpty()) { + continue; + } + if (id.equals(name)) { + continue; + } + if (isRestrictedXYZT(name, vcBioModel)) { + continue; + } // name = TokenMangler.fixTokenStrict(name, 60); - while (true) { - if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { - break; - } - name = TokenMangler.getNextEnumeratedToken(name); - } - if (id.equals(name)) { - continue; - } - try { - System.out.println(name + " <-- " + id); - rs.setName(name); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - } - vcBioModel.getSimulationContext(0).setbIgnoreEvents(false); - } - - /** - * raise issue tab if error is present - * - * @param hashTable - * @throws Exception - */ - private static void setWindowFocus(Hashtable hashTable) throws Exception { - DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get(WIN_MGR_KEY); - if (windowManager != null) { - DocumentEditor de = windowManager.getDocumentEditor(); - if (de != null) { - de.setWindowFocus(); - } - } - } - - private DocumentWindowManager createDocumentWindowManager(final VCDocument doc) { - JPanel newJPanel = new JPanel(); - if (doc instanceof BioModel) { - return new BioModelWindowManager(newJPanel, ClientRequestManager.this, (BioModel) doc); - } else if (doc instanceof MathModel) { - return new MathModelWindowManager(newJPanel, ClientRequestManager.this, (MathModel) doc); - } else if (doc instanceof Geometry) { - return new GeometryWindowManager(newJPanel, ClientRequestManager.this, (Geometry) doc); - } - throw new RuntimeException("Unknown VCDocument type " + doc); - } - - public void openDocument(VCDocumentType documentType, DocumentWindowManager requester) { - /* trying to open from database; called by DocumentWindow */ - // get an info first - VCDocumentInfo documentInfo = null; - try { - documentInfo = getMdiManager().getDatabaseWindowManager().selectDocument(documentType, requester); - // check whether request comes from a blank, unchanged document window; if so, - // open in same window, otherwise in a new window - boolean inNewWindow = isDifferentFromBlank(documentType, requester.getVCDocument()); - openDocument(documentInfo, requester, inNewWindow); - } catch (UserCancelException uexc) { - System.out.println(uexc); - return; - } catch (Exception exc) { - exc.printStackTrace(System.out); - PopupGenerator.showErrorDialog(requester, "Open document failed\n" + exc.getMessage(), exc); - } - } - - public void openDocument(VCDocumentInfo documentInfo, TopLevelWindowManager requester, boolean inNewWindow) { - // called directly from DatabaseWindow or after invoking an open dialog (see - // openDocument(int, Component)) - // need to check whether we opened this before and we still have it open - if (documentInfo == null) { - return; - } - String documentID = null; - if (documentInfo.getVersion() != null && documentInfo.getVersion().getVersionKey() != null) { // CLEAN UP BOGUS - // VERSION in - // XmlInfo !!! - documentID = documentInfo.getVersion().getVersionKey().toString(); - } - - // see if we have this open - if (documentID != null && getMdiManager().haveWindow(documentID)) { - // already open, block it - getMdiManager().blockWindow(documentID); - // check for changes - VCDocument openedDoc = ((DocumentWindowManager) getMdiManager().getWindowManager(documentID)) - .getVCDocument(); - boolean isChanged = true; - try { - isChanged = getDocumentManager().isChanged(openedDoc); - } catch (DataAccessException exc) { - // *maybe* something wrong trying to go to database, may not be able to load in - // the end, but warn anyway and try - String choice = PopupGenerator.showWarningDialog(requester, getUserPreferences(), - UserMessage.warn_UnableToCheckForChanges, null); - if (choice.equals(UserMessage.OPTION_CANCEL)) { - // user canceled, just show existing document - getMdiManager().unBlockWindow(documentID); - getMdiManager().showWindow(documentID); - return; - } - } - // we managed to check - if (isChanged) { - // it changed, warn the user - String choice = PopupGenerator.showWarningDialog(requester, getUserPreferences(), - UserMessage.choice_AlreadyOpened, null); - if (choice.equals(UserMessage.OPTION_CANCEL)) { - // user canceled, just show existing document - getMdiManager().unBlockWindow(documentID); - getMdiManager().showWindow(documentID); - return; - } else { - // user confirmed, close existing window first - getMdiManager().closeWindow(documentID); - // we are ready to try to get the new document - } - } else { - // nothing changed, just show that window - getMdiManager().unBlockWindow(documentID); - getMdiManager().showWindow(documentID); - return; - } - } - openAfterChecking(documentInfo, requester, inNewWindow); - } - - public void openPathway(DocumentWindowManager windowManager, PathwayImportOption pathwayImportOption) { - if (windowManager instanceof BioModelWindowManager) { - BioModelWindowManager bioModelWindowManager = (BioModelWindowManager) windowManager; - bioModelWindowManager.importPathway(pathwayImportOption); - } else { - DialogUtils.showErrorDialog(windowManager.getComponent(), - "Pathways can only be imported into a BioModel. " - + "To import a pathway, switch to a BioModel window or open a new" - + "one by opening a biomodel. This option should not even be available otherwise."); - } - } - - public void processComparisonResult(TMLPanel comparePanel, TopLevelWindowManager requester) { - // this is called from the EventDispatchQueue, so take care with threading... - - if (comparePanel == null || requester == null) { - throw new IllegalArgumentException("Invalid params: " + comparePanel + " " + requester); - } - try { - final VCDocument vcDoc = comparePanel.processComparisonResult(); - if (requester instanceof DatabaseWindowManager) { - final DatabaseWindowManager dataWinManager = (DatabaseWindowManager) requester; - final VCDocumentInfo vcDocInfo = getMatchingDocumentInfo(vcDoc); - this.openDocument(vcDocInfo, dataWinManager, true); - Thread waiter = new Thread() { - public void run() { - try { - GeneralGuiUtils.setCursorThroughout((Container) dataWinManager.getComponent(), - Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - while (bOpening) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - } - } - String ID = vcDocInfo.getVersion().getVersionKey().toString(); - DocumentWindowManager dwm = (DocumentWindowManager) ClientRequestManager.this - .getMdiManager().getWindowManager(ID); - dwm.resetDocument(vcDoc); - } finally { - GeneralGuiUtils.setCursorThroughout((Container) dataWinManager.getComponent(), - Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - }; - waiter.start(); - } else if (requester instanceof DocumentWindowManager) { - DocumentWindowManager docWinManager = (DocumentWindowManager) requester; - docWinManager.resetDocument(vcDoc); - } else { - throw new IllegalArgumentException( - "Invalid TopLevelWindowManager instance: " + requester.getClass().getName()); - } - System.out.println("Processing new model ..." + vcDoc.getVersion().getName()); - } catch (Exception e) { - e.printStackTrace(System.out); - throw new RuntimeException(e.getMessage()); - } - } - - /** - * This method gets called when a bound property is changed. - * - * @param evt A PropertyChangeEvent object describing the event source and the - * property that has changed. - */ - public void propertyChange(final PropertyChangeEvent evt) { - if (evt.getSource() == getVcellClient().getClientServerManager() - && evt.getPropertyName().equals("connectionStatus")) { - // update status display - updateStatusNow(); // this is already thread-safe - // other updates - AsynchGuiUpdater updater = new AsynchGuiUpdater() { - public void guiToDo() { - } - - public void guiToDo(Object params) { - // so far just update the DatabaseWindow - // need logic to deal with disconnection, different credentials etc. - - // only when NOT initializing - if (((ConnectionStatus) evt.getNewValue()).getStatus() != ConnectionStatus.INITIALIZING) { - getMdiManager().getDatabaseWindowManager().initializeAll(); - if (getMdiManager().getTestingFrameworkWindowManager() != null) { - getMdiManager().getTestingFrameworkWindowManager().initializeAllPanels(); - } - } - } - }; - updater.updateNow("some arg needed..."); - } - } - - public void reconnect(final TopLevelWindowManager requester) { - // asynch & nothing to do on Swing queue (updates handled by events) - AsynchClientTask task1 = new AsynchClientTask("reconnect", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - getClientServerManager().reconnect(new VCellGuiInteractiveContext(requester)); - - } - }; - ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), - new AsynchClientTask[] { task1 }); - } - - public void revertToSaved(DocumentWindowManager documentWindowManager) { - // make the info - VCDocument document = documentWindowManager.getVCDocument(); - VCDocumentInfo info = null; - try { - KeyValue versionKey = document.getVersion().getVersionKey(); - switch (document.getDocumentType()) { - case BIOMODEL_DOC: { - info = getDocumentManager().getBioModelInfo(versionKey); - break; - } - case MATHMODEL_DOC: { - info = getDocumentManager().getMathModelInfo(versionKey); - break; - } - case GEOMETRY_DOC: { - info = getDocumentManager().getGeometryInfo(versionKey); - break; - } - } - } catch (DataAccessException e) { - e.printStackTrace(System.out); - throw new RuntimeException(e.getMessage()); - } - // reload and reset into same window - openAfterChecking(info, documentWindowManager, false); - } - - public SimulationStatus runSimulation(final SimulationInfo simInfo, int numSimulationScanJobs) - throws DataAccessException { - - SimulationStatus simStatus = getClientServerManager().getJobManager() - .startSimulation(simInfo.getAuthoritativeVCSimulationIdentifier(), numSimulationScanJobs); - return simStatus; - } - - public void runSimulations(final ClientSimManager clientSimManager, final Simulation[] simulations) { - runSimulations(clientSimManager, simulations, null); - } - - public void runSimulations(final ClientSimManager clientSimManager, final Simulation[] simulations,AsynchClientTask[] endTasks) { - DocumentWindowManager documentWindowManager = clientSimManager.getDocumentWindowManager(); - if (documentWindowManager.getUser() == null || User.isGuest(documentWindowManager.getUser().getName())) { - DialogUtils.showErrorDialog(documentWindowManager.getComponent(), - User.createGuestErrorMessage("runVCellServerSimulations")); - return; - } - - /* run some quick checks to see if we need to do a SaveAs */ - boolean needSaveAs = false; - if (documentWindowManager.getVCDocument().getVersion() == null) { - // never saved - needSaveAs = true; - } else if (!documentWindowManager.getVCDocument().getVersion().getOwner() - .compareEqual(getDocumentManager().getUser())) { - // not the owner - // keep the user informed this time - String choice = PopupGenerator.showWarningDialog(documentWindowManager, getUserPreferences(), - UserMessage.warn_SaveNotOwner, null); - if (choice.equals(UserMessage.OPTION_SAVE_AS_NEW)) { - needSaveAs = true; - } else { - // user canceled, just show existing document - getMdiManager().showWindow(documentWindowManager.getManagerID()); - throw new UserCancelException("user canceled"); - } - } - - // Before running the simulation, check if all the sizes of structures are set - if (simulations != null && simulations.length > 0) { - VCDocument vcd = documentWindowManager.getVCDocument(); - if (vcd instanceof BioModel) { - String stochChkMsg = null; - // we want to check when there is stochastic application if the rate laws set in - // model can be automatically transformed. - for (int i = 0; i < simulations.length; i++) { - if (simulations[i].getMathDescription().isNonSpatialStoch() - || simulations[i].getMathDescription().isSpatialStoch() - || simulations[i].getMathDescription().isSpatialHybrid()) { - if (stochChkMsg == null) { - stochChkMsg = ((BioModel) vcd).getModel().isValidForStochApp(); - } - if (!(stochChkMsg.equals(""))) { - DialogUtils.showErrorDialog(documentWindowManager.getComponent(), - "Problem in simulation: " + simulations[i].getName() + ".\n" + stochChkMsg); - throw new RuntimeException( - "Problem in simulation: " + simulations[i].getName() + "\n" + stochChkMsg); - } - } - } - } - } - // - // when we run simulations, we want to force these exact editions to be run (not - // their older "equivalent" simulations). - // - // rather than trying to update immutable objects (e.g. directly clear parent - // references), we can do two things: - // - // 1) if simulation already points back to a previous "equivalent" edition, - // clear the version to force a clean save with no equivalency relationship - // 2) and, to prevent a simulation save from creating a new equivalency - // relationship, - // send the list of simulations to be run to force independence (see - // SaveDocument). - // - for (int i = 0; simulations != null && i < simulations.length; i++) { - if (simulations[i].getSimulationVersion() != null - && simulations[i].getSimulationVersion().getParentSimulationReference() != null) { - simulations[i].clearVersion(); - } - } - /* now start the dirty work */ - - /* block document window */ - JFrame currentDocumentWindow = getMdiManager().blockWindow(documentWindowManager.getManagerID()); - /* prepare hashtable for tasks */ - Hashtable hash = new Hashtable(); - hash.put("mdiManager", getMdiManager()); - hash.put(DocumentManager.IDENT, getDocumentManager()); - hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, documentWindowManager); - hash.put("currentDocumentWindow", currentDocumentWindow); - hash.put("clientSimManager", clientSimManager); - hash.put("simulations", simulations); - hash.put("jobManager", getClientServerManager().getJobManager()); - hash.put("requestManager", this); - hash.put("CallAction", CallAction.RUN); - - /* create tasks */ - AsynchClientTask[] tasks = null; - if (needSaveAs) { - // check document consistency first - AsynchClientTask documentValid = new DocumentValidTask(); - AsynchClientTask setMathDescription = new SetMathDescription(); - // get a new name - AsynchClientTask newName = new NewName(); - // save it - AsynchClientTask saveDocument = new SaveDocument(true); - // clean up - AsynchClientTask finishSave = new FinishSave(); - // run the simulations - AsynchClientTask runSims = new RunSims(); - // assemble array - tasks = new AsynchClientTask[] { documentValid, setMathDescription, newName, saveDocument, finishSave, - runSims }; - } else { - // check document consistency first - AsynchClientTask documentValid = new DocumentValidTask(); - AsynchClientTask setMathDescription = new SetMathDescription(); - // check if unchanged document - AsynchClientTask checkUnchanged = new CheckUnchanged(true); - // save it - AsynchClientTask saveDocument = new SaveDocument(false); - // check for lost results - AsynchClientTask checkBeforeDelete = new CheckBeforeDelete(); - // delete old document - AsynchClientTask deleteOldDocument = new DeleteOldDocument(); - // clean up - AsynchClientTask finishSave = new FinishSave(); - // run the simulations - AsynchClientTask runSims = new RunSims(); - // assemble array - tasks = new AsynchClientTask[] { documentValid, setMathDescription, checkUnchanged, saveDocument, - checkBeforeDelete, CheckBeforeDelete.getLowPrecisionConstantsNewNameTask(), - CheckBeforeDelete.getLowPrecisionConstantsSaveTask(), deleteOldDocument, finishSave, + while (true) { + if (cbit.vcell.model.Model.isNameUnused(name, vcBioModel.getModel())) { + break; + } + name = TokenMangler.getNextEnumeratedToken(name); + } + if (id.equals(name)) { + continue; + } + try { + System.out.println(name + " <-- " + id); + rs.setName(name); + } catch (PropertyVetoException e) { + e.printStackTrace(); + } + } + vcBioModel.getSimulationContext(0).setbIgnoreEvents(false); + } + + /** + * raise issue tab if error is present + * + * @param hashTable + * @throws Exception + */ + private static void setWindowFocus(Hashtable hashTable) throws Exception { + DocumentWindowManager windowManager = (DocumentWindowManager) hashTable.get(WIN_MGR_KEY); + if (windowManager != null) { + DocumentEditor de = windowManager.getDocumentEditor(); + if (de != null) { + de.setWindowFocus(); + } + } + } + + private DocumentWindowManager createDocumentWindowManager(final VCDocument doc) { + JPanel newJPanel = new JPanel(); + if (doc instanceof BioModel) { + return new BioModelWindowManager(newJPanel, ClientRequestManager.this, (BioModel) doc); + } else if (doc instanceof MathModel) { + return new MathModelWindowManager(newJPanel, ClientRequestManager.this, (MathModel) doc); + } else if (doc instanceof Geometry) { + return new GeometryWindowManager(newJPanel, ClientRequestManager.this, (Geometry) doc); + } + throw new RuntimeException("Unknown VCDocument type " + doc); + } + + public void openDocument(VCDocumentType documentType, DocumentWindowManager requester) { + /* trying to open from database; called by DocumentWindow */ + // get an info first + VCDocumentInfo documentInfo = null; + try { + documentInfo = this.getMdiManager().getDatabaseWindowManager().selectDocument(documentType, requester); + // check whether request comes from a blank, unchanged document window; if so, + // open in same window, otherwise in a new window + boolean inNewWindow = this.isDifferentFromBlank(documentType, requester.getVCDocument()); + this.openDocument(documentInfo, requester, inNewWindow); + } catch (UserCancelException uexc) { + System.out.println(uexc); + } catch (Exception exc) { + exc.printStackTrace(System.out); + PopupGenerator.showErrorDialog(requester, "Open document failed\n" + exc.getMessage(), exc); + } + } + + public void openDocument(VCDocumentInfo documentInfo, TopLevelWindowManager requester, boolean inNewWindow) { + // called directly from DatabaseWindow or after invoking an open dialog (see + // openDocument(int, Component)) + // need to check whether we opened this before and we still have it open + if (documentInfo == null) { + return; + } + String documentID = null; + if (documentInfo.getVersion() != null && documentInfo.getVersion().getVersionKey() != null) { // CLEAN UP BOGUS + // VERSION in + // XmlInfo !!! + documentID = documentInfo.getVersion().getVersionKey().toString(); + } + + // see if we have this open + if (documentID != null && this.getMdiManager().haveWindow(documentID)) { + // already open, block it + this.getMdiManager().blockWindow(documentID); + // check for changes + VCDocument openedDoc = ((DocumentWindowManager) this.getMdiManager().getWindowManager(documentID)) + .getVCDocument(); + boolean isChanged = true; + try { + isChanged = this.getDocumentManager().isChanged(openedDoc); + } catch (DataAccessException exc) { + // *maybe* something wrong trying to go to database, may not be able to load in + // the end, but warn anyway and try + String choice = PopupGenerator.showWarningDialog(requester, this.getUserPreferences(), + UserMessage.warn_UnableToCheckForChanges, null); + if (choice.equals(UserMessage.OPTION_CANCEL)) { + // user canceled, just show existing document + this.getMdiManager().unBlockWindow(documentID); + this.getMdiManager().showWindow(documentID); + return; + } + } + // we managed to check + if (isChanged) { + // it changed, warn the user + String choice = PopupGenerator.showWarningDialog(requester, this.getUserPreferences(), + UserMessage.choice_AlreadyOpened, null); + if (choice.equals(UserMessage.OPTION_CANCEL)) { + // user canceled, just show existing document + this.getMdiManager().unBlockWindow(documentID); + this.getMdiManager().showWindow(documentID); + return; + } else { + // user confirmed, close existing window first + this.getMdiManager().closeWindow(documentID); + // we are ready to try to get the new document + } + } else { + // nothing changed, just show that window + this.getMdiManager().unBlockWindow(documentID); + this.getMdiManager().showWindow(documentID); + return; + } + } + this.openAfterChecking(documentInfo, requester, inNewWindow); + } + + public void openPathway(DocumentWindowManager windowManager, PathwayImportOption pathwayImportOption) { + if (windowManager instanceof BioModelWindowManager bioModelWindowManager) { + bioModelWindowManager.importPathway(pathwayImportOption); + } else { + DialogUtils.showErrorDialog(windowManager.getComponent(), + "Pathways can only be imported into a BioModel. " + + "To import a pathway, switch to a BioModel window or open a new" + + "one by opening a biomodel. This option should not even be available otherwise."); + } + } + + public void processComparisonResult(TMLPanel comparePanel, TopLevelWindowManager requester) { + // this is called from the EventDispatchQueue, so take care with threading... + + if (comparePanel == null || requester == null) { + throw new IllegalArgumentException("Invalid params: " + comparePanel + " " + requester); + } + try { + final VCDocument vcDoc = comparePanel.processComparisonResult(); + if (requester instanceof DatabaseWindowManager dataWinManager) { + final VCDocumentInfo vcDocInfo = this.getMatchingDocumentInfo(vcDoc); + this.openDocument(vcDocInfo, dataWinManager, true); + Thread waiter = new Thread() { + public void run() { + try { + GeneralGuiUtils.setCursorThroughout((Container) dataWinManager.getComponent(), + Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + while (ClientRequestManager.this.bOpening) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + String ID = vcDocInfo.getVersion().getVersionKey().toString(); + DocumentWindowManager dwm = (DocumentWindowManager) ClientRequestManager.this + .getMdiManager().getWindowManager(ID); + dwm.resetDocument(vcDoc); + } finally { + GeneralGuiUtils.setCursorThroughout((Container) dataWinManager.getComponent(), + Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + }; + waiter.start(); + } else if (requester instanceof DocumentWindowManager docWinManager) { + docWinManager.resetDocument(vcDoc); + } else { + throw new IllegalArgumentException( + "Invalid TopLevelWindowManager instance: " + requester.getClass().getName()); + } + System.out.println("Processing new model ..." + vcDoc.getVersion().getName()); + } catch (Exception e) { + e.printStackTrace(System.out); + throw new RuntimeException(e.getMessage()); + } + } + + /** + * This method gets called when a bound property is changed. + * + * @param evt A PropertyChangeEvent object describing the event source and the + * property that has changed. + */ + public void propertyChange(final PropertyChangeEvent evt) { + if (evt.getSource() == this.getVcellClient().getClientServerManager() + && evt.getPropertyName().equals("connectionStatus")) { + // update status display + this.updateStatusNow(); // this is already thread-safe + // other updates + AsynchGuiUpdater updater = new AsynchGuiUpdater() { + public void guiToDo() { + } + + public void guiToDo(Object params) { + // so far just update the DatabaseWindow + // need logic to deal with disconnection, different credentials etc. + + // only when NOT initializing + if (((ConnectionStatus) evt.getNewValue()).getStatus() != ConnectionStatus.INITIALIZING) { + ClientRequestManager.this.getMdiManager().getDatabaseWindowManager().initializeAll(); + if (ClientRequestManager.this.getMdiManager().getTestingFrameworkWindowManager() != null) { + ClientRequestManager.this.getMdiManager().getTestingFrameworkWindowManager().initializeAllPanels(); + } + } + } + }; + updater.updateNow("some arg needed..."); + } + } + + public void reconnect(final TopLevelWindowManager requester) { + // asynch & nothing to do on Swing queue (updates handled by events) + AsynchClientTask task1 = new AsynchClientTask("reconnect", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + ClientRequestManager.this.getClientServerManager().reconnect(new VCellGuiInteractiveContext(requester)); + + } + }; + ClientTaskDispatcher.dispatch(requester.getComponent(), new Hashtable(), + new AsynchClientTask[]{task1}); + } + + public void revertToSaved(DocumentWindowManager documentWindowManager) { + // make the info + VCDocument document = documentWindowManager.getVCDocument(); + VCDocumentInfo info = null; + try { + KeyValue versionKey = document.getVersion().getVersionKey(); + switch (document.getDocumentType()) { + case BIOMODEL_DOC: { + info = this.getDocumentManager().getBioModelInfo(versionKey); + break; + } + case MATHMODEL_DOC: { + info = this.getDocumentManager().getMathModelInfo(versionKey); + break; + } + case GEOMETRY_DOC: { + info = this.getDocumentManager().getGeometryInfo(versionKey); + break; + } + } + } catch (DataAccessException e) { + e.printStackTrace(System.out); + throw new RuntimeException(e.getMessage()); + } + // reload and reset into same window + this.openAfterChecking(info, documentWindowManager, false); + } + + public SimulationStatus runSimulation(final SimulationInfo simInfo, int numSimulationScanJobs) + throws DataAccessException { + + SimulationStatus simStatus = this.getClientServerManager().getJobManager() + .startSimulation(simInfo.getAuthoritativeVCSimulationIdentifier(), numSimulationScanJobs); + return simStatus; + } + + public void runSimulations(final ClientSimManager clientSimManager, final Simulation[] simulations) { + this.runSimulations(clientSimManager, simulations, null); + } + + public void runSimulations(final ClientSimManager clientSimManager, final Simulation[] simulations, AsynchClientTask[] endTasks) { + DocumentWindowManager documentWindowManager = clientSimManager.getDocumentWindowManager(); + if (documentWindowManager.getUser() == null || User.isGuest(documentWindowManager.getUser().getName())) { + DialogUtils.showErrorDialog(documentWindowManager.getComponent(), + User.createGuestErrorMessage("runVCellServerSimulations")); + return; + } + + /* run some quick checks to see if we need to do a SaveAs */ + boolean needSaveAs = false; + if (documentWindowManager.getVCDocument().getVersion() == null) { + // never saved + needSaveAs = true; + } else if (!documentWindowManager.getVCDocument().getVersion().getOwner() + .compareEqual(this.getDocumentManager().getUser())) { + // not the owner + // keep the user informed this time + String choice = PopupGenerator.showWarningDialog(documentWindowManager, this.getUserPreferences(), + UserMessage.warn_SaveNotOwner, null); + if (choice.equals(UserMessage.OPTION_SAVE_AS_NEW)) { + needSaveAs = true; + } else { + // user canceled, just show existing document + this.getMdiManager().showWindow(documentWindowManager.getManagerID()); + throw new UserCancelException("user canceled"); + } + } + + // Before running the simulation, check if all the sizes of structures are set + if (simulations != null && simulations.length > 0) { + VCDocument vcd = documentWindowManager.getVCDocument(); + if (vcd instanceof BioModel) { + String stochChkMsg = null; + // we want to check when there is stochastic application if the rate laws set in + // model can be automatically transformed. + for (int i = 0; i < simulations.length; i++) { + if (simulations[i].getMathDescription().isNonSpatialStoch() + || simulations[i].getMathDescription().isSpatialStoch() + || simulations[i].getMathDescription().isSpatialHybrid()) { + if (stochChkMsg == null) { + stochChkMsg = ((BioModel) vcd).getModel().isValidForStochApp(); + } + if (!(stochChkMsg.equals(""))) { + DialogUtils.showErrorDialog(documentWindowManager.getComponent(), + "Problem in simulation: " + simulations[i].getName() + ".\n" + stochChkMsg); + throw new RuntimeException( + "Problem in simulation: " + simulations[i].getName() + "\n" + stochChkMsg); + } + } + } + } + } + // + // when we run simulations, we want to force these exact editions to be run (not + // their older "equivalent" simulations). + // + // rather than trying to update immutable objects (e.g. directly clear parent + // references), we can do two things: + // + // 1) if simulation already points back to a previous "equivalent" edition, + // clear the version to force a clean save with no equivalency relationship + // 2) and, to prevent a simulation save from creating a new equivalency + // relationship, + // send the list of simulations to be run to force independence (see + // SaveDocument). + // + for (int i = 0; simulations != null && i < simulations.length; i++) { + if (simulations[i].getSimulationVersion() != null + && simulations[i].getSimulationVersion().getParentSimulationReference() != null) { + simulations[i].clearVersion(); + } + } + /* now start the dirty work */ + + /* block document window */ + JFrame currentDocumentWindow = this.getMdiManager().blockWindow(documentWindowManager.getManagerID()); + /* prepare hashtable for tasks */ + Hashtable hash = new Hashtable(); + hash.put("mdiManager", this.getMdiManager()); + hash.put(DocumentManager.IDENT, this.getDocumentManager()); + hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, documentWindowManager); + hash.put("currentDocumentWindow", currentDocumentWindow); + hash.put("clientSimManager", clientSimManager); + hash.put("simulations", simulations); + hash.put("jobManager", this.getClientServerManager().getJobManager()); + hash.put("requestManager", this); + hash.put("CallAction", CallAction.RUN); + + /* create tasks */ + AsynchClientTask[] tasks = null; + if (needSaveAs) { + // check document consistency first + AsynchClientTask documentValid = new DocumentValidTask(); + AsynchClientTask setMathDescription = new SetMathDescription(); + // get a new name + AsynchClientTask newName = new NewName(); + // save it + AsynchClientTask saveDocument = new SaveDocument(true); + // clean up + AsynchClientTask finishSave = new FinishSave(); + // run the simulations + AsynchClientTask runSims = new RunSims(); + // assemble array + tasks = new AsynchClientTask[]{documentValid, setMathDescription, newName, saveDocument, finishSave, + runSims}; + } else { + // check document consistency first + AsynchClientTask documentValid = new DocumentValidTask(); + AsynchClientTask setMathDescription = new SetMathDescription(); + // check if unchanged document + AsynchClientTask checkUnchanged = new CheckUnchanged(true); + // save it + AsynchClientTask saveDocument = new SaveDocument(false); + // check for lost results + AsynchClientTask checkBeforeDelete = new CheckBeforeDelete(); + // delete old document + AsynchClientTask deleteOldDocument = new DeleteOldDocument(); + // clean up + AsynchClientTask finishSave = new FinishSave(); + // run the simulations + AsynchClientTask runSims = new RunSims(); + // assemble array + tasks = new AsynchClientTask[]{documentValid, setMathDescription, checkUnchanged, saveDocument, + checkBeforeDelete, CheckBeforeDelete.getLowPrecisionConstantsNewNameTask(), + CheckBeforeDelete.getLowPrecisionConstantsSaveTask(), deleteOldDocument, finishSave, // lowPrecisionConstantsWaitSave, - runSims }; - if(endTasks != null && endTasks.length > 0) { - AsynchClientTask[] temp = Arrays.copyOf(tasks, tasks.length+endTasks.length); - System.arraycopy(endTasks, 0, temp, tasks.length, endTasks.length); - tasks = temp; - } - } - /* run the tasks */ - ClientTaskDispatcher.dispatch(currentDocumentWindow, hash, tasks, true); - } - - public void saveDocument(DocumentWindowManager documentWindowManager, boolean replace) { - saveDocument(documentWindowManager, replace, null); - } - - public void saveDocument(final DocumentWindowManager documentWindowManager, boolean replace, - AsynchClientTask closeWindowTask) { - if (documentWindowManager.getUser() == null || User.isGuest(documentWindowManager.getUser().getName())) { - DialogUtils.showErrorDialog(documentWindowManager.getComponent(), - User.createGuestErrorMessage("saveDocument")); - return; - } - - /* run some quick checks first to validate request to save or save edition */ - if (documentWindowManager.getVCDocument().getVersion() == null) { - // it can never see this happening before, but check anyway and default to save - // as - // but since we can allow user to save during closing, now it can happen - // (save/save edition buttons should have not been enabled upon document window - // creation) - System.out.println( - "\nIGNORED ERROR: should not have been able to use save/save edition on doc with no version key\n"); - saveDocumentAsNew(documentWindowManager, closeWindowTask); - return; - } - if (!documentWindowManager.getVCDocument().getVersion().getOwner() - .compareEqual(getDocumentManager().getUser())) { - // not the owner - this should also not happen, but check anyway... - // keep the user informed this time - System.out.println( - "\nIGNORED ERROR: should not have been able to use save/save edition on doc with different owner\n"); - String choice = PopupGenerator.showWarningDialog(documentWindowManager, getUserPreferences(), - UserMessage.warn_SaveNotOwner, null); - if (choice.equals(UserMessage.OPTION_SAVE_AS_NEW)) { - // user chose to Save As - saveDocumentAsNew(documentWindowManager, closeWindowTask); - return; - } else { - if (closeWindowTask == null) { - // user canceled, just show existing document - getMdiManager().showWindow(documentWindowManager.getManagerID()); - return; - } else { - ClientTaskDispatcher.dispatch(documentWindowManager.getComponent(), new Hashtable(), - new AsynchClientTask[] { closeWindowTask }, false); - } - } - } - - /* request is valid, go ahead with save */ - - /* block document window */ - JFrame currentDocumentWindow = getMdiManager().blockWindow(documentWindowManager.getManagerID()); - /* prepare hashtable for tasks */ - Hashtable hash = new Hashtable(); - hash.put("mdiManager", getMdiManager()); - hash.put(DocumentManager.IDENT, getDocumentManager()); - hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, documentWindowManager); - hash.put("currentDocumentWindow", currentDocumentWindow); - hash.put("requestManager", this); - hash.put("CallAction", CallAction.RUN); - - /* create tasks */ - // check document consistency first - AsynchClientTask documentValid = new DocumentValidTask(); - AsynchClientTask setMathDescription = new SetMathDescription(); - // check if unchanged document - AsynchClientTask checkUnchanged = new CheckUnchanged(false); - // clean up - AsynchClientTask finishSave = new FinishSave(); - // assemble array - AsynchClientTask[] tasks = null; - if (replace) { - // save it - AsynchClientTask saveDocument = new SaveDocument(false); - // check for lost results - AsynchClientTask checkBeforeDelete = new CheckBeforeDelete(); - // delete old document - AsynchClientTask deleteOldDocument = new DeleteOldDocument(); - tasks = new AsynchClientTask[] { documentValid, setMathDescription, checkUnchanged, saveDocument, - checkBeforeDelete, CheckBeforeDelete.getLowPrecisionConstantsNewNameTask(), - CheckBeforeDelete.getLowPrecisionConstantsSaveTask(), deleteOldDocument, finishSave }; - } else { - // save it - AsynchClientTask saveDocument = new SaveDocument(true); - tasks = new AsynchClientTask[] { documentValid, setMathDescription, checkUnchanged, saveDocument, - finishSave }; - } - if (closeWindowTask != null) { - // replace finishSave - tasks[tasks.length - 1] = closeWindowTask; - } - /* run tasks */ - ClientTaskDispatcher.dispatch(currentDocumentWindow, hash, tasks, false); - } - - public void saveDocumentAsNew(DocumentWindowManager documentWindowManager) { - saveDocumentAsNew(documentWindowManager, null); - } - - public void saveDocumentAsNew(DocumentWindowManager documentWindowManager, AsynchClientTask closeWindowTask) { - if (documentWindowManager.getUser() == null || User.isGuest(documentWindowManager.getUser().getName())) { - DialogUtils.showErrorDialog(documentWindowManager.getComponent(), - User.createGuestErrorMessage("saveDocument")); - return; - } - - /* block document window */ - JFrame currentDocumentWindow = getMdiManager().blockWindow(documentWindowManager.getManagerID()); - /* prepare hashtable for tasks */ - Hashtable hash = new Hashtable(); - hash.put("mdiManager", getMdiManager()); - hash.put(DocumentManager.IDENT, getDocumentManager()); - hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, documentWindowManager); - hash.put("currentDocumentWindow", currentDocumentWindow); - hash.put("requestManager", this); - hash.put("CallAction", CallAction.SAVEASNEW); - - - /* create tasks */ - // check document consistency first - AsynchClientTask documentValid = new DocumentValidTask(); - AsynchClientTask setMathDescription = new SetMathDescription(); - // get a new name - AsynchClientTask newName = new NewName(); - // save it - AsynchClientTask saveDocument = new SaveDocument(true); - // clean up - AsynchClientTask finishSave = new FinishSave(); - // assemble array - AsynchClientTask[] tasks = new AsynchClientTask[] { documentValid, setMathDescription, newName, saveDocument, - finishSave }; - - if (closeWindowTask != null) { - // replace finishSave - tasks[tasks.length - 1] = closeWindowTask; - } - /* run tasks */ - ClientTaskDispatcher.dispatch(currentDocumentWindow, hash, tasks, false); - } - - public BioModelInfo selectBioModelInfo(TopLevelWindowManager requester) { - VCDocumentInfo documentInfo = null; - try { - documentInfo = getMdiManager().getDatabaseWindowManager().selectDocument(VCDocumentType.BIOMODEL_DOC, - requester); - } catch (UserCancelException uexc) { - System.out.println(uexc); - return null; - } catch (Exception exc) { - exc.printStackTrace(System.out); - PopupGenerator.showErrorDialog(requester, "Selection of BioModel failed\n" + exc.getMessage(), exc); - } - return (BioModelInfo) documentInfo; - } - - public MathModelInfo selectMathModelInfo(TopLevelWindowManager requester) { - VCDocumentInfo documentInfo = null; - try { - documentInfo = getMdiManager().getDatabaseWindowManager().selectDocument(VCDocumentType.MATHMODEL_DOC, - requester); - } catch (UserCancelException uexc) { - System.out.println(uexc); - return null; - } catch (Exception exc) { - exc.printStackTrace(System.out); - PopupGenerator.showErrorDialog(requester, "Selection of MathModel failed\n" + exc.getMessage(), exc); - } - return (MathModelInfo) documentInfo; - } - - private void setBExiting(boolean newBExiting) { - bExiting = newBExiting; - } - - private void setVcellClient(VCellClient newVcellClient) { - vcellClient = newVcellClient; - } - - public void showFieldDataWindow(FieldDataWindowManager.DataSymbolCallBack dataSymbolCallBack) { - FieldDataWindowManager fdwm = (FieldDataWindowManager) getMdiManager() - .getWindowManager(ClientMDIManager.FIELDDATA_WINDOW_ID); - fdwm.getFieldDataGUIPanel().setCreateDataSymbolCallBack(dataSymbolCallBack); - Window win = (Window) GeneralGuiUtils.findTypeParentOfComponent(fdwm.getFieldDataGUIPanel(), Window.class); - if (win != null) { - win.setVisible(false); - } - getMdiManager().showWindow(ClientMDIManager.FIELDDATA_WINDOW_ID); - - } - - public void showTestingFrameworkWindow() { - getMdiManager().showWindow(ClientMDIManager.TESTING_FRAMEWORK_WINDOW_ID); - } - - public void startExport(final OutputContext outputContext, Component requester, final ExportSpecs exportSpecs) { - // start a thread to get it; not blocking any window/frame - AsynchClientTask task1 = new AsynchClientTask("starting exporting", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - getClientServerManager().getJobManager().startExport(outputContext, exportSpecs); - } - }; - ClientTaskDispatcher.dispatch(requester, new Hashtable(), new AsynchClientTask[] { task1 }); - } - - public void stopSimulations(final ClientSimManager clientSimManager, final Simulation[] simulations) { - // stop is single step operation, don't bother with tasks, thread inline - AsynchClientTask task1 = new AsynchClientTask("stopping simulations", - AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - Hashtable failures = new Hashtable(); - if (simulations != null && simulations.length > 0) { - for (int i = 0; i < simulations.length; i++) { - try { - SimulationInfo simInfo = simulations[i].getSimulationInfo(); - if (simInfo != null) { - // check for running once more... directly from job status - SimulationStatus serverSimulationStatus = getServerSimulationStatus(simInfo); - if (serverSimulationStatus != null - && serverSimulationStatus.numberOfJobsDone() < simulations[i].getScanCount()) { - SimulationStatus simStatus = getClientServerManager().getJobManager() - .stopSimulation(simInfo.getAuthoritativeVCSimulationIdentifier()); - // updateStatus - clientSimManager.updateStatusFromStopRequest(simulations[i], simStatus); - } - } else { - // this should really not happen... - throw new RuntimeException(">>>>>>>>>> trying to stop an unsaved simulation..."); - } - } catch (Throwable exc) { - exc.printStackTrace(System.out); - failures.put(simulations[i], exc); - } - } - hashTable.put("failures", failures); - } - } - }; - - AsynchClientTask task2 = new AsynchClientTask("stopping simulations", AsynchClientTask.TASKTYPE_SWING_BLOCKING, - false, false) { - - @Override - public void run(Hashtable hashTable) throws Exception { - @SuppressWarnings("unchecked") - Hashtable failures = (Hashtable) hashTable - .get("failures"); - if (failures != null && !failures.isEmpty()) { - Enumeration en = failures.keys(); - while (en.hasMoreElements()) { - Simulation sim = (Simulation) en.nextElement(); - Throwable exc = (Throwable) failures.get(sim); - // notify user - PopupGenerator.showErrorDialog(clientSimManager.getDocumentWindowManager(), - "Failed to dispatch stop request for simulation'" + sim.getName() + "'\n" - + exc.getMessage(), - exc); - } - } - } - }; - ClientTaskDispatcher.dispatch(clientSimManager.getDocumentWindowManager().getComponent(), - new Hashtable(), new AsynchClientTask[] { task1, task2 }); - } - - public void updateStatusNow() { - // thread safe update of gui - AsynchClientTask task1 = new AsynchClientTask("updateStatusNow", AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { - @Override - public void run(Hashtable hashTable) throws Exception { - getVcellClient().getStatusUpdater() - .updateNow(getVcellClient().getClientServerManager().getConnectionStatus()); - - } - }; - ClientTaskDispatcher.dispatch(null, new Hashtable(), new AsynchClientTask[] { task1 }); - } - - public OpenModelInfoHolder[] getOpenDesktopDocumentInfos(boolean bIncludeSimulations) throws DataAccessException { - Vector simInfoHolderV = new Vector(); - for (TopLevelWindowManager tlwm : getMdiManager().getWindowManagers()) { - if (tlwm instanceof DocumentWindowManager) { - DocumentWindowManager dwm = (DocumentWindowManager) tlwm; - VCDocument vcDoc = dwm.getVCDocument(); - // if(vcDoc.getVersion() != null){ - if (vcDoc.getDocumentType() == VCDocumentType.BIOMODEL_DOC) { - BioModel bioModel = (BioModel) vcDoc; - // getDocumentManager().getBioModel(vcDoc.getVersion().getVersionKey()); - SimulationContext[] simContexts = bioModel.getSimulationContexts(); - for (int i = 0; i < simContexts.length; i += 1) { - if (bIncludeSimulations) { - if (simContexts[i].getGeometry() == null) { - throw new DataAccessException( - "Error gathering document info (isCompartmental check failed):\nOpen BioModel document " - + bioModel.getName() + " has no Geometry"); - } - Simulation[] sims = simContexts[i].getSimulations(); - for (int j = 0; j < sims.length; j += 1) { - for (int k = 0; k < sims[j].getScanCount(); k += 1) { - FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimBioModelInfo( - sims[j].getName(), bioModel.getVersion(), simContexts[i], - sims[j].getSimulationInfo(), k, - // !sims[j].getSolverTaskDescription().getSolverDescription().hasVariableTimestep(), - simContexts[i].getGeometry().getDimension() == 0); - simInfoHolderV.add(simInfoHolder); - } - } - } else { - FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimBioModelInfo( - null, bioModel.getVersion(), simContexts[i], null, -1, - simContexts[i].getGeometry().getDimension() == 0); - simInfoHolderV.add(simInfoHolder); - } - } - } else if (vcDoc.getDocumentType() == VCDocumentType.MATHMODEL_DOC) { - MathModel mathModel = (MathModel) vcDoc; - // getDocumentManager().getMathModel(vcDoc.getVersion().getVersionKey()); - if (bIncludeSimulations) { - if (mathModel.getMathDescription() == null - || mathModel.getMathDescription().getGeometry() == null) { - throw new DataAccessException( - "Error gathering document info (isCompartmental check failed):\nOpen MathModel document " - + mathModel.getName() + " has either no MathDescription or no Geometry"); - } - Simulation[] sims = mathModel.getSimulations(); - for (int i = 0; i < sims.length; i += 1) { - for (int k = 0; k < sims[i].getScanCount(); k += 1) { - FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimMathModelInfo( - sims[i].getName(), mathModel.getVersion(), mathModel.getMathDescription(), - sims[i].getSimulationInfo(), k, - // !sims[i].getSolverTaskDescription().getSolverDescription().hasVariableTimestep(), - mathModel.getMathDescription().getGeometry().getDimension() == 0); - simInfoHolderV.add(simInfoHolder); - } - } - } else { - FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimMathModelInfo( - null, mathModel.getVersion(), mathModel.getMathDescription(), null, -1, - mathModel.getMathDescription().getGeometry().getDimension() == 0); - simInfoHolderV.add(simInfoHolder); - } - } - // } - } - - } - OpenModelInfoHolder[] simInfoHolderArr = new OpenModelInfoHolder[simInfoHolderV.size()]; - simInfoHolderV.copyInto(simInfoHolderArr); - return simInfoHolderArr; - } - - public void showComparisonResults(TopLevelWindowManager requester, XmlTreeDiff diffTree, String baselineDesc, - String modifiedDesc) { - TMLPanel comparePanel = new TMLPanel(); - comparePanel.setXmlTreeDiff(diffTree); - comparePanel.setBaselineVersionDescription(baselineDesc); - comparePanel.setModifiedVersionDescription(modifiedDesc); - - JOptionPane comparePane = new JOptionPane(null, JOptionPane.PLAIN_MESSAGE, 0, null, - new Object[] { /* "Apply Changes", */"Close" }); - comparePane.setMessage(comparePanel); - JDialog compareDialog = comparePane.createDialog(requester.getComponent(), "Compare Models"); - compareDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - compareDialog.setResizable(true); - compareDialog.pack(); - compareDialog.setVisible(true); - // ZEnforcer.showModalDialogOnTop(compareDialog,JOptionPane.getFrameForComponent(requester.getComponent())); - if ("Apply Changes".equals(comparePane.getValue())) { - if (!comparePanel.tagsResolved()) { - DialogUtils.showErrorDialog(comparePanel, - "Please resolve all tagged elements/attributes before proceeding."); - } else { - GeneralGuiUtils.setCursorThroughout((Container) requester.getComponent(), - Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - try { - processComparisonResult(comparePanel, requester); - } catch (RuntimeException e) { - throw e; - } finally { - GeneralGuiUtils.setCursorThroughout((Container) requester.getComponent(), - Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - } - } + runSims}; + if (endTasks != null && endTasks.length > 0) { + AsynchClientTask[] temp = Arrays.copyOf(tasks, tasks.length + endTasks.length); + System.arraycopy(endTasks, 0, temp, tasks.length, endTasks.length); + tasks = temp; + } + } + /* run the tasks */ + ClientTaskDispatcher.dispatch(currentDocumentWindow, hash, tasks, true); + } + + public void saveDocument(DocumentWindowManager documentWindowManager, boolean replace) { + this.saveDocument(documentWindowManager, replace, null); + } + + public void saveDocument(final DocumentWindowManager documentWindowManager, boolean replace, + AsynchClientTask closeWindowTask) { + if (documentWindowManager.getUser() == null || User.isGuest(documentWindowManager.getUser().getName())) { + DialogUtils.showErrorDialog(documentWindowManager.getComponent(), + User.createGuestErrorMessage("saveDocument")); + return; + } + + /* run some quick checks first to validate request to save or save edition */ + if (documentWindowManager.getVCDocument().getVersion() == null) { + // it can never see this happening before, but check anyway and default to save + // as + // but since we can allow user to save during closing, now it can happen + // (save/save edition buttons should have not been enabled upon document window + // creation) + System.out.println( + "\nIGNORED ERROR: should not have been able to use save/save edition on doc with no version key\n"); + this.saveDocumentAsNew(documentWindowManager, closeWindowTask); + return; + } + if (!documentWindowManager.getVCDocument().getVersion().getOwner() + .compareEqual(this.getDocumentManager().getUser())) { + // not the owner - this should also not happen, but check anyway... + // keep the user informed this time + System.out.println( + "\nIGNORED ERROR: should not have been able to use save/save edition on doc with different owner\n"); + String choice = PopupGenerator.showWarningDialog(documentWindowManager, this.getUserPreferences(), + UserMessage.warn_SaveNotOwner, null); + if (choice.equals(UserMessage.OPTION_SAVE_AS_NEW)) { + // user chose to Save As + this.saveDocumentAsNew(documentWindowManager, closeWindowTask); + return; + } else { + if (closeWindowTask == null) { + // user canceled, just show existing document + this.getMdiManager().showWindow(documentWindowManager.getManagerID()); + return; + } else { + ClientTaskDispatcher.dispatch(documentWindowManager.getComponent(), new Hashtable(), + new AsynchClientTask[]{closeWindowTask}, false); + } + } + } + + /* request is valid, go ahead with save */ + + /* block document window */ + JFrame currentDocumentWindow = this.getMdiManager().blockWindow(documentWindowManager.getManagerID()); + /* prepare hashtable for tasks */ + Hashtable hash = new Hashtable(); + hash.put("mdiManager", this.getMdiManager()); + hash.put(DocumentManager.IDENT, this.getDocumentManager()); + hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, documentWindowManager); + hash.put("currentDocumentWindow", currentDocumentWindow); + hash.put("requestManager", this); + hash.put("CallAction", CallAction.RUN); + + /* create tasks */ + // check document consistency first + AsynchClientTask documentValid = new DocumentValidTask(); + AsynchClientTask setMathDescription = new SetMathDescription(); + // check if unchanged document + AsynchClientTask checkUnchanged = new CheckUnchanged(false); + // clean up + AsynchClientTask finishSave = new FinishSave(); + // assemble array + AsynchClientTask[] tasks = null; + if (replace) { + // save it + AsynchClientTask saveDocument = new SaveDocument(false); + // check for lost results + AsynchClientTask checkBeforeDelete = new CheckBeforeDelete(); + // delete old document + AsynchClientTask deleteOldDocument = new DeleteOldDocument(); + tasks = new AsynchClientTask[]{documentValid, setMathDescription, checkUnchanged, saveDocument, + checkBeforeDelete, CheckBeforeDelete.getLowPrecisionConstantsNewNameTask(), + CheckBeforeDelete.getLowPrecisionConstantsSaveTask(), deleteOldDocument, finishSave}; + } else { + // save it + AsynchClientTask saveDocument = new SaveDocument(true); + tasks = new AsynchClientTask[]{documentValid, setMathDescription, checkUnchanged, saveDocument, + finishSave}; + } + if (closeWindowTask != null) { + // replace finishSave + tasks[tasks.length - 1] = closeWindowTask; + } + /* run tasks */ + ClientTaskDispatcher.dispatch(currentDocumentWindow, hash, tasks, false); + } + + public void saveDocumentAsNew(DocumentWindowManager documentWindowManager) { + this.saveDocumentAsNew(documentWindowManager, null); + } + + public void saveDocumentAsNew(DocumentWindowManager documentWindowManager, AsynchClientTask closeWindowTask) { + if (documentWindowManager.getUser() == null || User.isGuest(documentWindowManager.getUser().getName())) { + DialogUtils.showErrorDialog(documentWindowManager.getComponent(), + User.createGuestErrorMessage("saveDocument")); + return; + } + + /* block document window */ + JFrame currentDocumentWindow = this.getMdiManager().blockWindow(documentWindowManager.getManagerID()); + /* prepare hashtable for tasks */ + Hashtable hash = new Hashtable(); + hash.put("mdiManager", this.getMdiManager()); + hash.put(DocumentManager.IDENT, this.getDocumentManager()); + hash.put(CommonTask.DOCUMENT_WINDOW_MANAGER.name, documentWindowManager); + hash.put("currentDocumentWindow", currentDocumentWindow); + hash.put("requestManager", this); + hash.put("CallAction", CallAction.SAVEASNEW); + + + /* create tasks */ + // check document consistency first + AsynchClientTask documentValid = new DocumentValidTask(); + AsynchClientTask setMathDescription = new SetMathDescription(); + // get a new name + AsynchClientTask newName = new NewName(); + // save it + AsynchClientTask saveDocument = new SaveDocument(true); + // clean up + AsynchClientTask finishSave = new FinishSave(); + // assemble array + AsynchClientTask[] tasks = new AsynchClientTask[]{documentValid, setMathDescription, newName, saveDocument, + finishSave}; + + if (closeWindowTask != null) { + // replace finishSave + tasks[tasks.length - 1] = closeWindowTask; + } + /* run tasks */ + ClientTaskDispatcher.dispatch(currentDocumentWindow, hash, tasks, false); + } + + public BioModelInfo selectBioModelInfo(TopLevelWindowManager requester) { + VCDocumentInfo documentInfo = null; + try { + documentInfo = this.getMdiManager().getDatabaseWindowManager().selectDocument(VCDocumentType.BIOMODEL_DOC, + requester); + } catch (UserCancelException uexc) { + System.out.println(uexc); + return null; + } catch (Exception exc) { + exc.printStackTrace(System.out); + PopupGenerator.showErrorDialog(requester, "Selection of BioModel failed\n" + exc.getMessage(), exc); + } + return (BioModelInfo) documentInfo; + } + + public MathModelInfo selectMathModelInfo(TopLevelWindowManager requester) { + VCDocumentInfo documentInfo = null; + try { + documentInfo = this.getMdiManager().getDatabaseWindowManager().selectDocument(VCDocumentType.MATHMODEL_DOC, + requester); + } catch (UserCancelException uexc) { + System.out.println(uexc); + return null; + } catch (Exception exc) { + exc.printStackTrace(System.out); + PopupGenerator.showErrorDialog(requester, "Selection of MathModel failed\n" + exc.getMessage(), exc); + } + return (MathModelInfo) documentInfo; + } + + private void setBExiting(boolean newBExiting) { + this.bExiting = newBExiting; + } + + private void setVcellClient(VCellClient newVcellClient) { + this.vcellClient = newVcellClient; + } + + public void showFieldDataWindow(FieldDataWindowManager.DataSymbolCallBack dataSymbolCallBack) { + FieldDataWindowManager fdwm = (FieldDataWindowManager) this.getMdiManager() + .getWindowManager(ClientMDIManager.FIELDDATA_WINDOW_ID); + fdwm.getFieldDataGUIPanel().setCreateDataSymbolCallBack(dataSymbolCallBack); + Window win = (Window) GeneralGuiUtils.findTypeParentOfComponent(fdwm.getFieldDataGUIPanel(), Window.class); + if (win != null) { + win.setVisible(false); + } + this.getMdiManager().showWindow(ClientMDIManager.FIELDDATA_WINDOW_ID); + + } + + public void showTestingFrameworkWindow() { + this.getMdiManager().showWindow(ClientMDIManager.TESTING_FRAMEWORK_WINDOW_ID); + } + + public void startExport(final OutputContext outputContext, Component requester, final ExportSpecs exportSpecs) { + // start a thread to get it; not blocking any window/frame + AsynchClientTask task1 = new AsynchClientTask("starting exporting", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + ClientRequestManager.this.getClientServerManager().getJobManager().startExport(outputContext, exportSpecs); + } + }; + ClientTaskDispatcher.dispatch(requester, new Hashtable(), new AsynchClientTask[]{task1}); + } + + public void stopSimulations(final ClientSimManager clientSimManager, final Simulation[] simulations) { + // stop is single step operation, don't bother with tasks, thread inline + AsynchClientTask task1 = new AsynchClientTask("stopping simulations", + AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + Hashtable failures = new Hashtable(); + if (simulations != null && simulations.length > 0) { + for (int i = 0; i < simulations.length; i++) { + try { + SimulationInfo simInfo = simulations[i].getSimulationInfo(); + if (simInfo != null) { + // check for running once more... directly from job status + SimulationStatus serverSimulationStatus = ClientRequestManager.this.getServerSimulationStatus(simInfo); + if (serverSimulationStatus != null + && serverSimulationStatus.numberOfJobsDone() < simulations[i].getScanCount()) { + SimulationStatus simStatus = ClientRequestManager.this.getClientServerManager().getJobManager() + .stopSimulation(simInfo.getAuthoritativeVCSimulationIdentifier()); + // updateStatus + clientSimManager.updateStatusFromStopRequest(simulations[i], simStatus); + } + } else { + // this should really not happen... + throw new RuntimeException(">>>>>>>>>> trying to stop an unsaved simulation..."); + } + } catch (Throwable exc) { + exc.printStackTrace(System.out); + failures.put(simulations[i], exc); + } + } + hashTable.put("failures", failures); + } + } + }; + + AsynchClientTask task2 = new AsynchClientTask("stopping simulations", AsynchClientTask.TASKTYPE_SWING_BLOCKING, + false, false) { + + @Override + public void run(Hashtable hashTable) throws Exception { + @SuppressWarnings("unchecked") + Hashtable failures = (Hashtable) hashTable + .get("failures"); + if (failures != null && !failures.isEmpty()) { + Enumeration en = failures.keys(); + while (en.hasMoreElements()) { + Simulation sim = en.nextElement(); + Throwable exc = failures.get(sim); + // notify user + PopupGenerator.showErrorDialog(clientSimManager.getDocumentWindowManager(), + "Failed to dispatch stop request for simulation'" + sim.getName() + "'\n" + + exc.getMessage(), + exc); + } + } + } + }; + ClientTaskDispatcher.dispatch(clientSimManager.getDocumentWindowManager().getComponent(), + new Hashtable(), new AsynchClientTask[]{task1, task2}); + } + + public void updateStatusNow() { + // thread safe update of gui + AsynchClientTask task1 = new AsynchClientTask("updateStatusNow", AsynchClientTask.TASKTYPE_SWING_NONBLOCKING) { + @Override + public void run(Hashtable hashTable) throws Exception { + ClientRequestManager.this.getVcellClient().getStatusUpdater() + .updateNow(ClientRequestManager.this.getVcellClient().getClientServerManager().getConnectionStatus()); + + } + }; + ClientTaskDispatcher.dispatch(null, new Hashtable(), new AsynchClientTask[]{task1}); + } + + public OpenModelInfoHolder[] getOpenDesktopDocumentInfos(boolean bIncludeSimulations) throws DataAccessException { + Vector simInfoHolderV = new Vector(); + for (TopLevelWindowManager tlwm : this.getMdiManager().getWindowManagers()) { + if (tlwm instanceof DocumentWindowManager dwm) { + VCDocument vcDoc = dwm.getVCDocument(); + // if(vcDoc.getVersion() != null){ + if (vcDoc.getDocumentType() == VCDocumentType.BIOMODEL_DOC) { + BioModel bioModel = (BioModel) vcDoc; + // getDocumentManager().getBioModel(vcDoc.getVersion().getVersionKey()); + SimulationContext[] simContexts = bioModel.getSimulationContexts(); + for (int i = 0; i < simContexts.length; i += 1) { + if (bIncludeSimulations) { + if (simContexts[i].getGeometry() == null) { + throw new DataAccessException( + "Error gathering document info (isCompartmental check failed):\nOpen BioModel document " + + bioModel.getName() + " has no Geometry"); + } + Simulation[] sims = simContexts[i].getSimulations(); + for (int j = 0; j < sims.length; j += 1) { + for (int k = 0; k < sims[j].getScanCount(); k += 1) { + FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimBioModelInfo( + sims[j].getName(), bioModel.getVersion(), simContexts[i], + sims[j].getSimulationInfo(), k, + // !sims[j].getSolverTaskDescription().getSolverDescription().hasVariableTimestep(), + simContexts[i].getGeometry().getDimension() == 0); + simInfoHolderV.add(simInfoHolder); + } + } + } else { + FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimBioModelInfo( + null, bioModel.getVersion(), simContexts[i], null, -1, + simContexts[i].getGeometry().getDimension() == 0); + simInfoHolderV.add(simInfoHolder); + } + } + } else if (vcDoc.getDocumentType() == VCDocumentType.MATHMODEL_DOC) { + MathModel mathModel = (MathModel) vcDoc; + // getDocumentManager().getMathModel(vcDoc.getVersion().getVersionKey()); + if (bIncludeSimulations) { + if (mathModel.getMathDescription() == null + || mathModel.getMathDescription().getGeometry() == null) { + throw new DataAccessException( + "Error gathering document info (isCompartmental check failed):\nOpen MathModel document " + + mathModel.getName() + " has either no MathDescription or no Geometry"); + } + Simulation[] sims = mathModel.getSimulations(); + for (int i = 0; i < sims.length; i += 1) { + for (int k = 0; k < sims[i].getScanCount(); k += 1) { + FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimMathModelInfo( + sims[i].getName(), mathModel.getVersion(), mathModel.getMathDescription(), + sims[i].getSimulationInfo(), k, + // !sims[i].getSolverTaskDescription().getSolverDescription().hasVariableTimestep(), + mathModel.getMathDescription().getGeometry().getDimension() == 0); + simInfoHolderV.add(simInfoHolder); + } + } + } else { + FieldDataWindowManager.OpenModelInfoHolder simInfoHolder = new FieldDataWindowManager.FDSimMathModelInfo( + null, mathModel.getVersion(), mathModel.getMathDescription(), null, -1, + mathModel.getMathDescription().getGeometry().getDimension() == 0); + simInfoHolderV.add(simInfoHolder); + } + } + // } + } + + } + OpenModelInfoHolder[] simInfoHolderArr = new OpenModelInfoHolder[simInfoHolderV.size()]; + simInfoHolderV.copyInto(simInfoHolderArr); + return simInfoHolderArr; + } + + public void showComparisonResults(TopLevelWindowManager requester, XmlTreeDiff diffTree, String baselineDesc, + String modifiedDesc) { + TMLPanel comparePanel = new TMLPanel(); + comparePanel.setXmlTreeDiff(diffTree); + comparePanel.setBaselineVersionDescription(baselineDesc); + comparePanel.setModifiedVersionDescription(modifiedDesc); + + JOptionPane comparePane = new JOptionPane(null, JOptionPane.PLAIN_MESSAGE, 0, null, + new Object[]{ /* "Apply Changes", */"Close"}); + comparePane.setMessage(comparePanel); + JDialog compareDialog = comparePane.createDialog(requester.getComponent(), "Compare Models"); + compareDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + compareDialog.setResizable(true); + compareDialog.pack(); + compareDialog.setVisible(true); + // ZEnforcer.showModalDialogOnTop(compareDialog,JOptionPane.getFrameForComponent(requester.getComponent())); + if ("Apply Changes".equals(comparePane.getValue())) { + if (!comparePanel.tagsResolved()) { + DialogUtils.showErrorDialog(comparePanel, + "Please resolve all tagged elements/attributes before proceeding."); + } else { + GeneralGuiUtils.setCursorThroughout((Container) requester.getComponent(), + Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + try { + this.processComparisonResult(comparePanel, requester); + } catch (RuntimeException e) { + throw e; + } finally { + GeneralGuiUtils.setCursorThroughout((Container) requester.getComponent(), + Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + } + } //public void prepareDocumentToLoad(VCDocument doc) throws Exception { // Simulation[] simulations = null; @@ -4603,254 +4568,254 @@ public void showComparisonResults(TopLevelWindowManager requester, XmlTreeDiff d // } //} - public static FieldDataFileOperationSpec createFDOSFromImageFile(File imageFile, boolean bCropOutBlack, - Integer saveOnlyThisTimePointIndex) throws DataFormatException, ImageException { - try { - ImageDatasetReader imageDatasetReader = ImageDatasetReaderService.getInstance().getImageDatasetReader(); - ImageDataset[] imagedataSets = imageDatasetReader.readImageDatasetChannels(imageFile.getAbsolutePath(), - null, false, saveOnlyThisTimePointIndex, null); - if (imagedataSets != null && bCropOutBlack) { - for (int i = 0; i < imagedataSets.length; i++) { - Rectangle nonZeroRect = imagedataSets[i].getNonzeroBoundingRectangle(); - if (nonZeroRect != null) { - imagedataSets[i] = imagedataSets[i].crop(nonZeroRect); - } - } - } - return createFDOSWithChannels(imagedataSets, null); - } catch (Exception e) { - e.printStackTrace(System.out); - throw new DataFormatException(e.getMessage()); - } - } - - public static FieldDataFileOperationSpec createFDOSWithChannels(ImageDataset[] imagedataSets, - Integer saveOnlyThisTimePointIndex) { - final FieldDataFileOperationSpec fdos = new FieldDataFileOperationSpec(); - - // [time][var][data] - int numXY = imagedataSets[0].getISize().getX() * imagedataSets[0].getISize().getY(); - int numXYZ = imagedataSets[0].getSizeZ() * numXY; - fdos.variableTypes = new VariableType[imagedataSets.length]; - fdos.varNames = new String[imagedataSets.length]; - short[][][] shortData = new short[(saveOnlyThisTimePointIndex != null ? 1 - : imagedataSets[0].getSizeT())][imagedataSets.length][numXYZ]; - for (int c = 0; c < imagedataSets.length; c += 1) { - fdos.variableTypes[c] = VariableType.VOLUME; - fdos.varNames[c] = "Channel" + c; - for (int t = 0; t < imagedataSets[c].getSizeT(); t += 1) { - if (saveOnlyThisTimePointIndex != null && saveOnlyThisTimePointIndex.intValue() != t) { - continue; - } - int zOffset = 0; - for (int z = 0; z < imagedataSets[c].getSizeZ(); z += 1) { - UShortImage ushortImage = imagedataSets[c].getImage(z, 0, t); - System.arraycopy(ushortImage.getPixels(), 0, - shortData[(saveOnlyThisTimePointIndex != null ? 0 : t)][c], zOffset, numXY); + public static FieldDataFileOperationSpec createFDOSFromImageFile(File imageFile, boolean bCropOutBlack, + Integer saveOnlyThisTimePointIndex) throws DataFormatException, ImageException { + try { + ImageDatasetReader imageDatasetReader = ImageDatasetReaderService.getInstance().getImageDatasetReader(); + ImageDataset[] imagedataSets = imageDatasetReader.readImageDatasetChannels(imageFile.getAbsolutePath(), + null, false, saveOnlyThisTimePointIndex, null); + if (imagedataSets != null && bCropOutBlack) { + for (int i = 0; i < imagedataSets.length; i++) { + Rectangle nonZeroRect = imagedataSets[i].getNonzeroBoundingRectangle(); + if (nonZeroRect != null) { + imagedataSets[i] = imagedataSets[i].crop(nonZeroRect); + } + } + } + return createFDOSWithChannels(imagedataSets, null); + } catch (Exception e) { + e.printStackTrace(System.out); + throw new DataFormatException(e.getMessage()); + } + } + + public static FieldDataFileOperationSpec createFDOSWithChannels(ImageDataset[] imagedataSets, + Integer saveOnlyThisTimePointIndex) { + final FieldDataFileOperationSpec fdos = new FieldDataFileOperationSpec(); + + // [time][var][data] + int numXY = imagedataSets[0].getISize().getX() * imagedataSets[0].getISize().getY(); + int numXYZ = imagedataSets[0].getSizeZ() * numXY; + fdos.variableTypes = new VariableType[imagedataSets.length]; + fdos.varNames = new String[imagedataSets.length]; + short[][][] shortData = new short[(saveOnlyThisTimePointIndex != null ? 1 + : imagedataSets[0].getSizeT())][imagedataSets.length][numXYZ]; + for (int c = 0; c < imagedataSets.length; c += 1) { + fdos.variableTypes[c] = VariableType.VOLUME; + fdos.varNames[c] = "Channel" + c; + for (int t = 0; t < imagedataSets[c].getSizeT(); t += 1) { + if (saveOnlyThisTimePointIndex != null && saveOnlyThisTimePointIndex.intValue() != t) { + continue; + } + int zOffset = 0; + for (int z = 0; z < imagedataSets[c].getSizeZ(); z += 1) { + UShortImage ushortImage = imagedataSets[c].getImage(z, 0, t); + System.arraycopy(ushortImage.getPixels(), 0, + shortData[(saveOnlyThisTimePointIndex != null ? 0 : t)][c], zOffset, numXY); // shortData[t][c] = ushortImage.getPixels(); - zOffset += numXY; - } - } - } - fdos.shortSpecData = shortData; - fdos.times = imagedataSets[0].getImageTimeStamps(); - if (fdos.times == null) { - fdos.times = new double[imagedataSets[0].getSizeT()]; - for (int i = 0; i < fdos.times.length; i += 1) { - fdos.times[i] = i; - } - } - - fdos.origin = (imagedataSets[0].getAllImages()[0].getOrigin() != null - ? imagedataSets[0].getAllImages()[0].getOrigin() - : new Origin(0, 0, 0)); - fdos.extent = (imagedataSets[0].getExtent() != null) ? (imagedataSets[0].getExtent()) : (new Extent(1, 1, 1)); - fdos.isize = imagedataSets[0].getISize(); - - return fdos; - - } - - public void accessPermissions(Component requester, VCDocument vcDoc) { - VersionInfo selectedVersionInfo = null; - switch (vcDoc.getDocumentType()) { - case BIOMODEL_DOC: - BioModelInfo[] bioModelInfos = getDocumentManager().getBioModelInfos(); - for (BioModelInfo bioModelInfo : bioModelInfos) { - if (bioModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { - selectedVersionInfo = bioModelInfo; - break; - } - } - break; - case MATHMODEL_DOC: - MathModelInfo[] mathModelInfos = getDocumentManager().getMathModelInfos(); - for (MathModelInfo mathModelInfo : mathModelInfos) { - if (mathModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { - selectedVersionInfo = mathModelInfo; - break; - } - } - break; - case GEOMETRY_DOC: - GeometryInfo[] geoInfos = getDocumentManager().getGeometryInfos(); - for (GeometryInfo geoInfo : geoInfos) { - if (geoInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { - selectedVersionInfo = geoInfo; - break; - } - } - break; - } - getMdiManager().getDatabaseWindowManager().accessPermissions(requester, selectedVersionInfo, false); - - } - - public void accessPermissionsEx(Component requester, VCDocument vcDoc, boolean bGrantSupportPermissions) { - VersionInfo selectedVersionInfo = null; - switch (vcDoc.getDocumentType()) { - case BIOMODEL_DOC: - BioModelInfo[] bioModelInfos = getDocumentManager().getBioModelInfos(); - for (BioModelInfo bioModelInfo : bioModelInfos) { - if (bioModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { - selectedVersionInfo = bioModelInfo; - break; - } - } - break; - case MATHMODEL_DOC: - MathModelInfo[] mathModelInfos = getDocumentManager().getMathModelInfos(); - for (MathModelInfo mathModelInfo : mathModelInfos) { - if (mathModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { - selectedVersionInfo = mathModelInfo; - break; - } - } - break; - case GEOMETRY_DOC: - GeometryInfo[] geoInfos = getDocumentManager().getGeometryInfos(); - for (GeometryInfo geoInfo : geoInfos) { - if (geoInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { - selectedVersionInfo = geoInfo; - break; - } - } - break; - } - getMdiManager().getDatabaseWindowManager().accessPermissions(requester, selectedVersionInfo, true); - - } - - public static Collection updateMath(final Component requester, - final SimulationContext simulationContext, final boolean bShowWarning, - final NetworkGenerationRequirements networkGenerationRequirements) { - ArrayList rval = new ArrayList<>(); - AsynchClientTask task1 = new AsynchClientTask("generating math", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - Geometry geometry = simulationContext.getGeometry(); - if (geometry.getDimension() > 0 - && geometry.getGeometrySurfaceDescription().getGeometricRegions() == null) { - geometry.getGeometrySurfaceDescription().updateAll(); - } - // Use differnt mathmapping for different applications (stoch or non-stoch) - simulationContext.checkValidity(); - MathMappingCallback callback = new MathMappingCallbackTaskAdapter(getClientTaskStatusSupport()); - - MathMapping mathMapping = simulationContext.createNewMathMapping(callback, - networkGenerationRequirements); - MathDescription mathDesc = mathMapping.getMathDescription(callback); - callback.setProgressFraction(1.0f / 3.0f * 2.0f); - hashTable.put("mathMapping", mathMapping); - hashTable.put("mathDesc", mathDesc); - } - }; - rval.add(task1); - - AsynchClientTask task2 = new AsynchClientTask("formating math", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - MathDescription mathDesc = (MathDescription) hashTable.get("mathDesc"); - if (mathDesc != null) { - simulationContext.setMathDescription(mathDesc); - } - } - }; - rval.add(task2); - - if (bShowWarning) { - AsynchClientTask task3 = new AsynchClientTask("showing issues", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { - - @Override - public void run(Hashtable hashTable) throws Exception { - MathMapping mathMapping = (MathMapping) hashTable.get("mathMapping"); - MathDescription mathDesc = (MathDescription) hashTable.get("mathDesc"); - if (mathDesc != null) { - // - // inform user if any issues - // - Issue issues[] = mathMapping.getIssues(); - if (issues != null && issues.length > 0) { - StringBuffer messageBuffer = new StringBuffer( - "Errors encountered during Math Generation:\n"); - int issueCount = 0; - for (int i = 0; i < issues.length; i++) { - if (issues[i].getSeverity() == Issue.Severity.ERROR) { - messageBuffer.append(issues[i].getCategory() + " " + issues[i].getSeverityName() - + " : " + issues[i].getMessage() + "\n"); - issueCount++; - } - } - if (issueCount > 0) { - PopupGenerator.showWarningDialog(requester, messageBuffer.toString(), - new String[] { "OK" }, "OK"); - } - } - } - } - }; - rval.add(task3); - } - return rval; - } - - public static String getPreferredPath(final UserPreferences userPrefs) { - String defaultPath = null; - if (userPrefs == null) { - defaultPath = ResourceUtil.getLastUserLocalDir(); - if (defaultPath == null || defaultPath.length() == 0) { - defaultPath = ResourceUtil.getUserHomeDir().getAbsolutePath(); - } - } else { - defaultPath = userPrefs.getCurrentDialogPath().getAbsolutePath(); - } - if (defaultPath == null || ResourceUtil.getVCellInstall().getAbsolutePath().contains(defaultPath)) { - defaultPath = ResourceUtil.getUserHomeDir().getAbsolutePath(); - } - return defaultPath; - } - - public static void setPreferredPath(final UserPreferences userPrefs, File selectedFile) { - File defaultPath = null; - File newPath = null; - - if (userPrefs != null) { - defaultPath = userPrefs.getCurrentDialogPath(); - newPath = selectedFile.getParentFile(); - if (!newPath.equals(defaultPath)) { - userPrefs.setCurrentDialogPath(newPath); - } - } else { - // if export is local export, userPrefs = null - defaultPath = (ResourceUtil.getLastUserLocalDir() == null ? null - : new File(ResourceUtil.getLastUserLocalDir())); - newPath = selectedFile.getParentFile(); - if (!newPath.equals(defaultPath)) { - ResourceUtil.setLastUserLocalDir(newPath.getAbsolutePath()); - } - } - } + zOffset += numXY; + } + } + } + fdos.shortSpecData = shortData; + fdos.times = imagedataSets[0].getImageTimeStamps(); + if (fdos.times == null) { + fdos.times = new double[imagedataSets[0].getSizeT()]; + for (int i = 0; i < fdos.times.length; i += 1) { + fdos.times[i] = i; + } + } + + fdos.origin = (imagedataSets[0].getAllImages()[0].getOrigin() != null + ? imagedataSets[0].getAllImages()[0].getOrigin() + : new Origin(0, 0, 0)); + fdos.extent = (imagedataSets[0].getExtent() != null) ? (imagedataSets[0].getExtent()) : (new Extent(1, 1, 1)); + fdos.isize = imagedataSets[0].getISize(); + + return fdos; + + } + + public void accessPermissions(Component requester, VCDocument vcDoc) { + VersionInfo selectedVersionInfo = null; + switch (vcDoc.getDocumentType()) { + case BIOMODEL_DOC: + BioModelInfo[] bioModelInfos = this.getDocumentManager().getBioModelInfos(); + for (BioModelInfo bioModelInfo : bioModelInfos) { + if (bioModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { + selectedVersionInfo = bioModelInfo; + break; + } + } + break; + case MATHMODEL_DOC: + MathModelInfo[] mathModelInfos = this.getDocumentManager().getMathModelInfos(); + for (MathModelInfo mathModelInfo : mathModelInfos) { + if (mathModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { + selectedVersionInfo = mathModelInfo; + break; + } + } + break; + case GEOMETRY_DOC: + GeometryInfo[] geoInfos = this.getDocumentManager().getGeometryInfos(); + for (GeometryInfo geoInfo : geoInfos) { + if (geoInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { + selectedVersionInfo = geoInfo; + break; + } + } + break; + } + this.getMdiManager().getDatabaseWindowManager().accessPermissions(requester, selectedVersionInfo, false); + + } + + public void accessPermissionsEx(Component requester, VCDocument vcDoc, boolean bGrantSupportPermissions) { + VersionInfo selectedVersionInfo = null; + switch (vcDoc.getDocumentType()) { + case BIOMODEL_DOC: + BioModelInfo[] bioModelInfos = this.getDocumentManager().getBioModelInfos(); + for (BioModelInfo bioModelInfo : bioModelInfos) { + if (bioModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { + selectedVersionInfo = bioModelInfo; + break; + } + } + break; + case MATHMODEL_DOC: + MathModelInfo[] mathModelInfos = this.getDocumentManager().getMathModelInfos(); + for (MathModelInfo mathModelInfo : mathModelInfos) { + if (mathModelInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { + selectedVersionInfo = mathModelInfo; + break; + } + } + break; + case GEOMETRY_DOC: + GeometryInfo[] geoInfos = this.getDocumentManager().getGeometryInfos(); + for (GeometryInfo geoInfo : geoInfos) { + if (geoInfo.getVersion().getVersionKey().equals(vcDoc.getVersion().getVersionKey())) { + selectedVersionInfo = geoInfo; + break; + } + } + break; + } + this.getMdiManager().getDatabaseWindowManager().accessPermissions(requester, selectedVersionInfo, true); + + } + + public static Collection updateMath(final Component requester, + final SimulationContext simulationContext, final boolean bShowWarning, + final NetworkGenerationRequirements networkGenerationRequirements) { + ArrayList rval = new ArrayList<>(); + AsynchClientTask task1 = new AsynchClientTask("generating math", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + Geometry geometry = simulationContext.getGeometry(); + if (geometry.getDimension() > 0 + && geometry.getGeometrySurfaceDescription().getGeometricRegions() == null) { + geometry.getGeometrySurfaceDescription().updateAll(); + } + // Use differnt mathmapping for different applications (stoch or non-stoch) + simulationContext.checkValidity(); + MathMappingCallback callback = new MathMappingCallbackTaskAdapter(this.getClientTaskStatusSupport()); + + MathMapping mathMapping = simulationContext.createNewMathMapping(callback, + networkGenerationRequirements); + MathDescription mathDesc = mathMapping.getMathDescription(callback); + callback.setProgressFraction(1.0f / 3.0f * 2.0f); + hashTable.put("mathMapping", mathMapping); + hashTable.put("mathDesc", mathDesc); + } + }; + rval.add(task1); + + AsynchClientTask task2 = new AsynchClientTask("formating math", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + MathDescription mathDesc = (MathDescription) hashTable.get("mathDesc"); + if (mathDesc != null) { + simulationContext.setMathDescription(mathDesc); + } + } + }; + rval.add(task2); + + if (bShowWarning) { + AsynchClientTask task3 = new AsynchClientTask("showing issues", AsynchClientTask.TASKTYPE_SWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + MathMapping mathMapping = (MathMapping) hashTable.get("mathMapping"); + MathDescription mathDesc = (MathDescription) hashTable.get("mathDesc"); + if (mathDesc != null) { + // + // inform user if any issues + // + Issue[] issues = mathMapping.getIssues(); + if (issues != null && issues.length > 0) { + StringBuffer messageBuffer = new StringBuffer( + "Errors encountered during Math Generation:\n"); + int issueCount = 0; + for (int i = 0; i < issues.length; i++) { + if (issues[i].getSeverity() == Issue.Severity.ERROR) { + messageBuffer.append(issues[i].getCategory() + " " + issues[i].getSeverityName() + + " : " + issues[i].getMessage() + "\n"); + issueCount++; + } + } + if (issueCount > 0) { + PopupGenerator.showWarningDialog(requester, messageBuffer.toString(), + new String[]{"OK"}, "OK"); + } + } + } + } + }; + rval.add(task3); + } + return rval; + } + + public static String getPreferredPath(final UserPreferences userPrefs) { + String defaultPath = null; + if (userPrefs == null) { + defaultPath = ResourceUtil.getLastUserLocalDir(); + if (defaultPath == null || defaultPath.length() == 0) { + defaultPath = ResourceUtil.getUserHomeDir().getAbsolutePath(); + } + } else { + defaultPath = userPrefs.getCurrentDialogPath().getAbsolutePath(); + } + if (defaultPath == null || ResourceUtil.getVCellInstall().getAbsolutePath().contains(defaultPath)) { + defaultPath = ResourceUtil.getUserHomeDir().getAbsolutePath(); + } + return defaultPath; + } + + public static void setPreferredPath(final UserPreferences userPrefs, File selectedFile) { + File defaultPath = null; + File newPath = null; + + if (userPrefs != null) { + defaultPath = userPrefs.getCurrentDialogPath(); + newPath = selectedFile.getParentFile(); + if (!newPath.equals(defaultPath)) { + userPrefs.setCurrentDialogPath(newPath); + } + } else { + // if export is local export, userPrefs = null + defaultPath = (ResourceUtil.getLastUserLocalDir() == null ? null + : new File(ResourceUtil.getLastUserLocalDir())); + newPath = selectedFile.getParentFile(); + if (!newPath.equals(defaultPath)) { + ResourceUtil.setLastUserLocalDir(newPath.getAbsolutePath()); + } + } + } } From 3c95fbe98673144a686c4b8626461231e8187172 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 16:31:11 -0400 Subject: [PATCH 38/48] Clean up class --- .../client/server/AsynchMessageManager.java | 501 +++++++++--------- 1 file changed, 252 insertions(+), 249 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index 72200b7275..c947a8bd65 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -9,6 +9,7 @@ */ package cbit.vcell.client.server; + import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -48,302 +49,304 @@ * {@link AsynchMessageManager} also listens to {@link ClientJobManager} if user stops the simulation, then it will notify TopLevelWindowManager * to update the status. */ -public class AsynchMessageManager implements SimStatusListener, DataAccessException.Listener,DataJobListenerHolder { +public class AsynchMessageManager implements SimStatusListener, DataAccessException.Listener, DataJobListenerHolder { private static final long BASE_POLL_SECONDS = 3; private static final long ATTEMPT_POLL_SECONDS = 3; - private static Logger lg = LogManager.getLogger(AsynchMessageManager.class); + private static final Logger lg = LogManager.getLogger(AsynchMessageManager.class); - private EventListenerList listenerList = new EventListenerList(); - private ClientServerManager clientServerManager; + private final EventListenerList listenerList = new EventListenerList(); + private final ClientServerManager clientServerManager; private int failureCount = 0; private ScheduledExecutorService executorService = null; - private long counter = 0; + private final long counter = 0; private long pollTime = BASE_POLL_SECONDS; - private AtomicBoolean isPollingEnabled = new AtomicBoolean(false); - private ScheduledFuture pollingHandle = null; - /** - * for {@link #schedule(long)} method - */ - private final ReentrantLock scheduleLock = new ReentrantLock(); - private final ReentrantLock connectionLock = new ReentrantLock(); - -public AsynchMessageManager(ClientServerManager csm) { - this.clientServerManager = csm; -} -/** - * start polling for connection. Should be called after connect - * no-op if already called - */ -public synchronized void startPolling() { - if (isPollingEnabled.get()) return; - isPollingEnabled.set(true); - if (executorService == null) { - executorService = VCellExecutorService.get(); - DataAccessException.addListener(this); - } - schedule(pollTime); + private final AtomicBoolean isPollingEnabled = new AtomicBoolean(false); + private ScheduledFuture pollingHandle = null; + /** + * for {@link #schedule(long)} method + */ + private final ReentrantLock scheduleLock = new ReentrantLock(); + private final ReentrantLock connectionLock = new ReentrantLock(); + + public AsynchMessageManager(ClientServerManager csm) { + this.clientServerManager = csm; + } -} + /** + * start polling for connection. Should be called after connect + * no-op if already called + */ + public synchronized void startPolling() { + if (this.isPollingEnabled.get()) return; + this.isPollingEnabled.set(true); + if (this.executorService == null) { + this.executorService = VCellExecutorService.get(); + DataAccessException.addListener(this); + } + this.schedule(this.pollTime); + + } -public void stopPolling() { + public void stopPolling() { // lg.trace("stopping polling"); - isPollingEnabled.set(false); -} + this.isPollingEnabled.set(false); + } -@Override -public void created(DataAccessException dae) { + @Override + public void created(DataAccessException dae) { // if (lg.isTraceEnabled()) { // lg.trace("scheduling now due to " + dae.getMessage()); // } - schedule(0); -} -private void poll( ) { - if (!isPollingEnabled.get()) { - lg.debug("polling stopped"); - return; - } - - lg.debug("polling"); - boolean shouldReport = counter % 50 == 0; - long begin = 0; - long end = 0; - - // ask remote message listener (really should be "message producer") for any queued events. - try { - MessageEvent[] queuedEvents; - if (shouldReport) begin = System.currentTimeMillis(); // time the call - - if (!clientServerManager.isStatusConnected()){ - if (!connectionLock.tryLock()) return; - clientServerManager.attemptReconnect(); - return; - } - pollTime = BASE_POLL_SECONDS; - queuedEvents = clientServerManager.getMessageEvents(); - - if (shouldReport) end = System.currentTimeMillis(); - - failureCount = 0; //this is skipped if the connection has failed:w - // deal with events, if any - if (queuedEvents != null) for (MessageEvent messageEvent : queuedEvents) onMessageEvent(messageEvent); - if (!shouldReport) return; - - // report polling call performance - double duration = ((double) (end - begin)) / 1000; - PerformanceMonitorEvent performanceMonitorEvent = new PerformanceMonitorEvent( - this, null, new PerformanceData( - "AsynchMessageManager.poll()", - MessageEvent.POLLING_STAT, - new PerformanceDataEntry[] {new PerformanceDataEntry("remote call duration", Double.toString(duration))} + this.schedule(0); + } + + private void poll() { + if (!this.isPollingEnabled.get()) { + lg.debug("polling stopped"); + return; + } + + lg.debug("polling"); + boolean shouldReport = this.counter % 50 == 0; + long begin = 0; + long end = 0; + + // ask remote message listener (really should be "message producer") for any queued events. + try { + MessageEvent[] queuedEvents; + if (shouldReport) begin = System.currentTimeMillis(); // time the call + + if (!this.clientServerManager.isStatusConnected()) { + if (!this.connectionLock.tryLock()) return; + this.clientServerManager.attemptReconnect(); + return; + } + this.pollTime = BASE_POLL_SECONDS; + queuedEvents = this.clientServerManager.getMessageEvents(); + + if (shouldReport) end = System.currentTimeMillis(); + + this.failureCount = 0; //this is skipped if the connection has failed:w + // deal with events, if any + if (queuedEvents != null) for (MessageEvent messageEvent : queuedEvents) this.onMessageEvent(messageEvent); + if (!shouldReport) return; + + // report polling call performance + double duration = ((double) (end - begin)) / 1000; + PerformanceMonitorEvent performanceMonitorEvent = new PerformanceMonitorEvent( + this, null, new PerformanceData( + "AsynchMessageManager.poll()", + MessageEvent.POLLING_STAT, + new PerformanceDataEntry[]{new PerformanceDataEntry("remote call duration", Double.toString(duration))} ) - ); - } catch (Exception exc) { - lg.error(">> POLLING FAILURE <<", exc); - pollTime = ATTEMPT_POLL_SECONDS; - failureCount ++; - if (failureCount % 3 == 0) { - isPollingEnabled.set(false); - clientServerManager.setDisconnected(); - } - } finally { - connectionLock.unlock(); - lg.debug(ExecutionTrace.justClassName(this) + " poll time " + pollTime + " seconds"); - if (isPollingEnabled.get()) schedule(pollTime); + ); + } catch (Exception exc) { + lg.error(">> POLLING FAILURE <<", exc); + this.pollTime = ATTEMPT_POLL_SECONDS; + this.failureCount++; + if (this.failureCount % 3 == 0) { + this.isPollingEnabled.set(false); + this.clientServerManager.setDisconnected(); + } + } finally { + this.connectionLock.unlock(); + lg.debug(ExecutionTrace.justClassName(this) + " poll time " + this.pollTime + " seconds"); + if (this.isPollingEnabled.get()) this.schedule(this.pollTime); + } } -} -/** - * schedule poll, replacing previously scheduled instance, if any - * @param delay - */ -private void schedule(long delay) { - scheduleLock.lock(); - try { - if (pollingHandle != null && !pollingHandle.isDone()) { - pollingHandle.cancel(true); - } - pollingHandle = executorService.schedule(this::poll, delay,TimeUnit.SECONDS); - } - finally { - scheduleLock.unlock(); - } -} + /** + * schedule poll, replacing previously scheduled instance, if any + * + * @param delay + */ + private void schedule(long delay) { + this.scheduleLock.lock(); + try { + if (this.pollingHandle != null && !this.pollingHandle.isDone()) { + this.pollingHandle.cancel(true); + } + this.pollingHandle = this.executorService.schedule(this::poll, delay, TimeUnit.SECONDS); + } finally { + this.scheduleLock.unlock(); + } + } -private void onMessageEvent(MessageEvent event) { - if (event instanceof SimulationJobStatusEvent) { - fireSimulationJobStatusEvent((SimulationJobStatusEvent)event); - } else if (event instanceof ExportEvent) { - fireExportEvent((ExportEvent)event); - } else if (event instanceof DataJobEvent) { - fireDataJobEvent((DataJobEvent)event); - } else if (event instanceof VCellMessageEvent) { - fireVCellMessageEvent((VCellMessageEvent)event); - } else { - System.err.println("AsynchMessageManager.onMessageEvent() : unknown message event " + event); - } -} + private void onMessageEvent(MessageEvent event) { + if (event instanceof SimulationJobStatusEvent) { + this.fireSimulationJobStatusEvent((SimulationJobStatusEvent) event); + } else if (event instanceof ExportEvent) { + this.fireExportEvent((ExportEvent) event); + } else if (event instanceof DataJobEvent) { + this.fireDataJobEvent((DataJobEvent) event); + } else if (event instanceof VCellMessageEvent) { + this.fireVCellMessageEvent((VCellMessageEvent) event); + } else { + System.err.println("AsynchMessageManager.onMessageEvent() : unknown message event " + event); + } + } -public void addDataJobListener(DataJobListener listener) { - synchronized (listenerList){ - listenerList.add(DataJobListener.class, listener); - } -} + public void addDataJobListener(DataJobListener listener) { + synchronized (this.listenerList) { + this.listenerList.add(DataJobListener.class, listener); + } + } -public void addExportListener(ExportListener listener) { - synchronized (listenerList){ - listenerList.add(ExportListener.class, listener); - } -} + public void addExportListener(ExportListener listener) { + synchronized (this.listenerList) { + this.listenerList.add(ExportListener.class, listener); + } + } -public void addSimStatusListener(SimStatusListener listener) { - synchronized (listenerList){ - listenerList.add(SimStatusListener.class, listener); - } -} + public void addSimStatusListener(SimStatusListener listener) { + synchronized (this.listenerList) { + this.listenerList.add(SimStatusListener.class, listener); + } + } -public void addSimulationJobStatusListener(SimulationJobStatusListener listener) { - synchronized (listenerList){ - listenerList.add(SimulationJobStatusListener.class, listener); - } -} + public void addSimulationJobStatusListener(SimulationJobStatusListener listener) { + synchronized (this.listenerList) { + this.listenerList.add(SimulationJobStatusListener.class, listener); + } + } -public void addVCellMessageEventListener(VCellMessageEventListener listener) { - synchronized (listenerList){ - listenerList.add(VCellMessageEventListener.class, listener); - } -} + public void addVCellMessageEventListener(VCellMessageEventListener listener) { + synchronized (this.listenerList) { + this.listenerList.add(VCellMessageEventListener.class, listener); + } + } -protected void fireDataJobEvent(DataJobEvent event) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Reset the source to allow proper wiring - event.setSource(this); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i] != DataJobListener.class) continue; - fireDataJobEvent(event, (DataJobListener) listeners[i + 1]); + protected void fireDataJobEvent(DataJobEvent event) { + // Guaranteed to return a non-null array + Object[] listeners = this.listenerList.getListenerList(); + // Reset the source to allow proper wiring + event.setSource(this); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] != DataJobListener.class) continue; + this.fireDataJobEvent(event, (DataJobListener) listeners[i + 1]); + } } -} -private void fireDataJobEvent(final DataJobEvent event, final DataJobListener listener) { - SwingUtilities.invokeLater(() -> listener.dataJobMessage(event)); -} + private void fireDataJobEvent(final DataJobEvent event, final DataJobListener listener) { + SwingUtilities.invokeLater(() -> listener.dataJobMessage(event)); + } -protected void fireExportEvent(ExportEvent event) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Reset the source to allow proper wiring - event.setSource(this); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i] != ExportListener.class) continue; - fireExportEvent(event, (ExportListener) listeners[i + 1]); + protected void fireExportEvent(ExportEvent event) { + // Guaranteed to return a non-null array + Object[] listeners = this.listenerList.getListenerList(); + // Reset the source to allow proper wiring + event.setSource(this); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] != ExportListener.class) continue; + this.fireExportEvent(event, (ExportListener) listeners[i + 1]); + } } -} -private void fireExportEvent(final ExportEvent event, final ExportListener listener) { - SwingUtilities.invokeLater(() -> listener.exportMessage(event)); -} + private void fireExportEvent(final ExportEvent event, final ExportListener listener) { + SwingUtilities.invokeLater(() -> listener.exportMessage(event)); + } -protected void fireSimStatusEvent(SimStatusEvent event) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i] != SimStatusListener.class) continue; - fireSimStatusEvent(event, (SimStatusListener)listeners[i+1]); - } -} + protected void fireSimStatusEvent(SimStatusEvent event) { + // Guaranteed to return a non-null array + Object[] listeners = this.listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] != SimStatusListener.class) continue; + this.fireSimStatusEvent(event, (SimStatusListener) listeners[i + 1]); + } + } -private void fireSimStatusEvent(final SimStatusEvent event, final SimStatusListener listener) { - listener.simStatusChanged(event); -} + private void fireSimStatusEvent(final SimStatusEvent event, final SimStatusListener listener) { + listener.simStatusChanged(event); + } -protected void fireSimulationJobStatusEvent(SimulationJobStatusEvent event) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Reset the source to allow proper wiring - event.setSource(this); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i] != SimulationJobStatusListener.class) continue; - fireSimulationJobStatusEvent(event, (SimulationJobStatusListener)listeners[i+1]); - } -} + protected void fireSimulationJobStatusEvent(SimulationJobStatusEvent event) { + // Guaranteed to return a non-null array + Object[] listeners = this.listenerList.getListenerList(); + // Reset the source to allow proper wiring + event.setSource(this); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] != SimulationJobStatusListener.class) continue; + this.fireSimulationJobStatusEvent(event, (SimulationJobStatusListener) listeners[i + 1]); + } + } -private void fireSimulationJobStatusEvent(final SimulationJobStatusEvent event, final SimulationJobStatusListener listener) { - listener.simulationJobStatusChanged(event); -} + private void fireSimulationJobStatusEvent(final SimulationJobStatusEvent event, final SimulationJobStatusListener listener) { + listener.simulationJobStatusChanged(event); + } -protected void fireVCellMessageEvent(VCellMessageEvent event) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Reset the source to allow proper wiring - event.setSource(this); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length-2; i>=0; i-=2) { - if (listeners[i]==VCellMessageEventListener.class) { - fireVCellMessageEvent(event, (VCellMessageEventListener)listeners[i+1]); - } - } -} + protected void fireVCellMessageEvent(VCellMessageEvent event) { + // Guaranteed to return a non-null array + Object[] listeners = this.listenerList.getListenerList(); + // Reset the source to allow proper wiring + event.setSource(this); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == VCellMessageEventListener.class) { + this.fireVCellMessageEvent(event, (VCellMessageEventListener) listeners[i + 1]); + } + } + } -private void fireVCellMessageEvent(final VCellMessageEvent event, final VCellMessageEventListener listener) { - SwingUtilities.invokeLater(() -> listener.onVCellMessageEvent(event)); -} + private void fireVCellMessageEvent(final VCellMessageEvent event, final VCellMessageEventListener listener) { + SwingUtilities.invokeLater(() -> listener.onVCellMessageEvent(event)); + } -public void removeDataJobListener(DataJobListener listener) { - synchronized (listenerList){ - listenerList.remove(DataJobListener.class, listener); - } -} + public void removeDataJobListener(DataJobListener listener) { + synchronized (this.listenerList) { + this.listenerList.remove(DataJobListener.class, listener); + } + } -public void removeExportListener(ExportListener listener) { - synchronized (listenerList){ - listenerList.remove(ExportListener.class, listener); - } -} + public void removeExportListener(ExportListener listener) { + synchronized (this.listenerList) { + this.listenerList.remove(ExportListener.class, listener); + } + } -/** - * removeSimulationStatusEventListener method comment. - */ -public void removeSimStatusListener(SimStatusListener listener) { - synchronized (listenerList){ - listenerList.remove(SimStatusListener.class, listener); - } -} + /** + * removeSimulationStatusEventListener method comment. + */ + public void removeSimStatusListener(SimStatusListener listener) { + synchronized (this.listenerList) { + this.listenerList.remove(SimStatusListener.class, listener); + } + } -/** - * removeSimulationStatusEventListener method comment. - */ -public void removeSimulationJobStatusListener(SimulationJobStatusListener listener) { - synchronized (listenerList){ - listenerList.remove(SimulationJobStatusListener.class, listener); - } -} + /** + * removeSimulationStatusEventListener method comment. + */ + public void removeSimulationJobStatusListener(SimulationJobStatusListener listener) { + synchronized (this.listenerList) { + this.listenerList.remove(SimulationJobStatusListener.class, listener); + } + } -public void removeVCellMessageEventListener(VCellMessageEventListener listener) { - synchronized (listenerList){ - listenerList.remove(VCellMessageEventListener.class, listener); - } -} + public void removeVCellMessageEventListener(VCellMessageEventListener listener) { + synchronized (this.listenerList) { + this.listenerList.remove(VCellMessageEventListener.class, listener); + } + } -public void simStatusChanged(SimStatusEvent simStatusEvent) { - // refire for swing - fireSimStatusEvent(simStatusEvent); -} + public void simStatusChanged(SimStatusEvent simStatusEvent) { + // refire for swing + this.fireSimStatusEvent(simStatusEvent); + } } From 2f40a4429ab92c78a434db1e6a376f0bb7dba4e2 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Wed, 24 Jul 2024 16:31:39 -0400 Subject: [PATCH 39/48] Commented out unused class (will delete once confirmed not useful) --- .../client/server/ClientServerManager.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java index 7cc0fee463..4612ac2f6c 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java @@ -354,22 +354,22 @@ public void reconnect(InteractiveContext requester) { } } -public void connectAs(InteractiveContext requester, String user) { - reconnectStat = ReconnectStatus.NOT; - switch (getClientServerInfo().getServerType()) { - case SERVER_LOCAL: { - clientServerInfo = ClientServerInfo.createLocalServerInfo(user); - break; - } - case SERVER_REMOTE: { - clientServerInfo = ClientServerInfo.createRemoteServerInfo( - getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), getClientServerInfo().getPathPrefix_v0(), - user); - break; - } - } - connect(requester); -} +//public void connectAs(InteractiveContext requester, String user) { +// reconnectStat = ReconnectStatus.NOT; +// switch (getClientServerInfo().getServerType()) { +// case SERVER_LOCAL: { +// clientServerInfo = ClientServerInfo.createLocalServerInfo(user); +// break; +// } +// case SERVER_REMOTE: { +// clientServerInfo = ClientServerInfo.createRemoteServerInfo( +// getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), getClientServerInfo().getPathPrefix_v0(), +// user); +// break; +// } +// } +// connect(requester); +//} /** From f9ed66b92a71700bd9a2a2800346c5736f01dab6 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 09:41:22 -0400 Subject: [PATCH 40/48] Restored logging to polling --- .../java/cbit/vcell/client/server/AsynchMessageManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index c947a8bd65..62625eca67 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -78,18 +78,19 @@ public AsynchMessageManager(ClientServerManager csm) { */ public synchronized void startPolling() { if (this.isPollingEnabled.get()) return; + lg.debug("Asynch Polling initiated"); this.isPollingEnabled.set(true); if (this.executorService == null) { this.executorService = VCellExecutorService.get(); DataAccessException.addListener(this); } this.schedule(this.pollTime); - + lg.debug("Asynch Polling active"); } public void stopPolling() { -// lg.trace("stopping polling"); this.isPollingEnabled.set(false); + lg.debug("Asynch Polling disabled, stopping polling"); } @Override From 883b484d1dc73af04d52d4cefdec43155ae4c258 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 14:57:29 -0400 Subject: [PATCH 41/48] Changed debug_log4j2 to actually use debug levels --- debug_log4j2.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/debug_log4j2.xml b/debug_log4j2.xml index 4bd5910c55..eb49757805 100644 --- a/debug_log4j2.xml +++ b/debug_log4j2.xml @@ -10,13 +10,13 @@ - + - + - + @@ -28,7 +28,7 @@ - + From 0f750e3b4e0e99fec654021bed1c385f726a28de Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 15:15:52 -0400 Subject: [PATCH 42/48] Logging Improvements for clarity, organization, and efficiency --- .../org/vcell/api/client/VCellApiClient.java | 40 +++++++++++-------- .../java/cbit/gui/graph/gui/CartoonTool.java | 6 ++- .../client/task/ClientTaskDispatcher.java | 9 +++-- .../cbit/vcell/graph/gui/LargeShapePanel.java | 7 +++- .../graph/gui/ReactionCartoonEditorPanel.java | 16 ++++---- .../vcell/util/gui/ButtonGroupCivilized.java | 6 ++- .../StandardVCellSwingWorker.java | 20 ++++++---- .../client/server/AsynchMessageManager.java | 14 +++---- .../cbit/vcell/client/server/Reconnector.java | 13 +++--- .../vcell/graph/ReactionCartoonMolecule.java | 18 ++++----- .../cbit/vcell/graph/ReactionCartoonRule.java | 18 ++++----- 11 files changed, 94 insertions(+), 73 deletions(-) diff --git a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java index 22ba2e0da3..cf666ee6e2 100644 --- a/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java +++ b/vcell-apiclient/src/main/java/org/vcell/api/client/VCellApiClient.java @@ -61,6 +61,12 @@ public class VCellApiClient implements AutoCloseable { private static final Logger lg = LogManager.getLogger(VCellApiClient.class); + private static final boolean activeLogLevelIsSensitiveEnough; + + static { + activeLogLevelIsSensitiveEnough = lg.isTraceEnabled(); + } + private final HttpHost httpHost; private final String pathPrefix_v0; private final String clientID; @@ -202,13 +208,13 @@ public SimulationTaskRepresentation[] getSimTasks(SimTasksQuerySpec simTasksQuer HttpGet httpget = new HttpGet(getApiUrlPrefix() + "/simtask?" + simTasksQuerySpec.getQueryString()); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve simulation tasks " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getSimTasks()", httpget), httpClientContext); String simTasksJson = responseBody; - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(simTasksJson)); } @@ -231,13 +237,13 @@ public BiomodelRepresentation[] getBioModels(BioModelsQuerySpec bioModelsQuerySp HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel?"+bioModelsQuerySpec.getQueryString()); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve biomodels " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getBioModels()", httpget), httpClientContext); String bimodelsJson = responseBody; - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(bimodelsJson)); } @@ -251,13 +257,13 @@ public EventWrapper[] getEvents(long beginTimestamp) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/events?beginTimestamp="+beginTimestamp); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (lg.isTraceEnabled()) { lg.info("Executing request to retrieve user events " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getEvents()", httpget), httpClientContext); String eventWrappersJson = responseBody; - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(eventWrappersJson)); } @@ -271,13 +277,13 @@ public BiomodelRepresentation getBioModel(String bmId) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve biomodel " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getBioModel()", httpget), httpClientContext); String bimodelsJson = responseBody; - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(bimodelsJson)); } @@ -291,7 +297,7 @@ public String getBioModelVCML(String bmId) throws IOException { HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId+"/biomodel.vcml"); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve biomodel " + httpget.getRequestLine()); } @@ -306,13 +312,13 @@ public SimulationRepresentation getSimulation(String bmId, String simKey) throws HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve simulation " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getSimulation()", httpget), httpClientContext); String simulationJson = responseBody; - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(simulationJson)); } @@ -326,12 +332,12 @@ public String getOptRunJson(String optimizationId,boolean bStop) throws IOExcept HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/optimization/"+optimizationId+"?bStop="+bStop); httpget.addHeader("Authorization","Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve optimization run " + httpget.getRequestLine()); } String responseBody = httpclient.execute(httpget, new VCellStringResponseHandler("getOptRunJson()", httpget), httpClientContext); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(responseBody)); } return responseBody; @@ -429,7 +435,7 @@ public SimulationTaskRepresentation[] startSimulation(String bmId, String simKey HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey+"/startSimulation"); httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve simulation " + httppost.getRequestLine()); } @@ -453,13 +459,13 @@ public SimulationTaskRepresentation[] stopSimulation(String bmId, String simKey) HttpPost httppost = new HttpPost(getApiUrlPrefix()+"/biomodel/"+bmId+"/simulation/"+simKey+"/stopSimulation"); httppost.addHeader("Authorization", "Bearer "+httpClientContext.getUserToken(String.class)); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve simulation " + httppost.getRequestLine()); } String responseBody = httpclient.execute(httppost, new VCellStringResponseHandler("stopSimulation()", httppost), httpClientContext); String simTaskReps = responseBody; - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("returned: "+toStringTruncated(simTaskReps)); } @@ -826,7 +832,7 @@ public String getServerSoftwareVersion() throws ClientProtocolException, IOExcep HttpGet httpget = new HttpGet(getApiUrlPrefix()+"/swversion"); - if (lg.isDebugEnabled()) { + if (activeLogLevelIsSensitiveEnough) { lg.info("Executing request to retrieve server software version " + httpget.getRequestLine()); } diff --git a/vcell-client/src/main/java/cbit/gui/graph/gui/CartoonTool.java b/vcell-client/src/main/java/cbit/gui/graph/gui/CartoonTool.java index 9a617e89ea..e725e35d15 100644 --- a/vcell-client/src/main/java/cbit/gui/graph/gui/CartoonTool.java +++ b/vcell-client/src/main/java/cbit/gui/graph/gui/CartoonTool.java @@ -48,11 +48,13 @@ import cbit.gui.graph.actions.CartoonToolSaveAsImageActions; import cbit.gui.graph.actions.GraphViewAction; import cbit.gui.graph.groups.VCGroupManager; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.vcell.util.gui.GeneralGuiUtils; public abstract class CartoonTool implements GraphView, MouseListener, MouseMotionListener, ActionListener, KeyListener { - + private static final Logger lg = LogManager.getLogger(CartoonTool.class); public static final boolean GROUPS_ARE_ENABLED = false; private GraphPane graphPane = null; @@ -359,7 +361,7 @@ public final void updateButtonGroup(ButtonGroup buttonGroup, return; } } - System.out.println("ERROR: button with actionCommand " + actionCommand + " not found"); + lg.warn("ERROR: button with actionCommand {} not found", actionCommand); return; } diff --git a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java index 264ea6c091..06dffe4f87 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java +++ b/vcell-client/src/main/java/cbit/vcell/client/task/ClientTaskDispatcher.java @@ -350,7 +350,8 @@ private static Future> masterDispatch(final Component // check tasks - swing non-blocking can be only at the end ClientTaskDispatcher.entryCounter++; - if (ClientTaskDispatcher.entryCounter > 1) lg.debug("Reentrant: {}", ClientTaskDispatcher.entryCounter); + if (ClientTaskDispatcher.entryCounter > 1 && lg.isTraceEnabled()) + lg.debug("Reentrant: {}", ClientTaskDispatcher.entryCounter); // if (bInProgress) { // Thread.dumpStack(); @@ -359,8 +360,8 @@ private static Future> masterDispatch(final Component hash.put(TaskEventKeys.STACK_TRACE_ARRAY.toString(), Thread.currentThread().getStackTrace()); if (bShowProgressPopup && requester == null) { - System.out.println("ClientTaskDispatcher.dispatch(), requester is null, dialog has no parent, please try best to fix it!!!"); - Thread.dumpStack(); + if (lg.isDebugEnabled()) lg.warn("ClientTaskDispatcher.dispatch(), requester is null, " + + "dialog has no parent, please try best to fix it!!!"); } for (AsynchClientTask task : tasks) { @@ -368,7 +369,7 @@ private static Future> masterDispatch(final Component throw new RuntimeException("SWING_NONBLOCKING task only permitted as last task"); } taskList.add(task); - lg.debug("added task name {}", task.getTaskName()); + if (lg.isTraceEnabled()) lg.debug("added task name {}", task.getTaskName()); } // dispatch tasks to a new worker (note that there is handling for non-swing and swing tasks in the same place) diff --git a/vcell-client/src/main/java/cbit/vcell/graph/gui/LargeShapePanel.java b/vcell-client/src/main/java/cbit/vcell/graph/gui/LargeShapePanel.java index 86faf7a602..20547c5bdf 100644 --- a/vcell-client/src/main/java/cbit/vcell/graph/gui/LargeShapePanel.java +++ b/vcell-client/src/main/java/cbit/vcell/graph/gui/LargeShapePanel.java @@ -2,6 +2,8 @@ import javax.swing.JPanel; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.vcell.model.rbm.ComponentStateDefinition; import org.vcell.model.rbm.ComponentStatePattern; import org.vcell.model.rbm.MolecularComponent; @@ -17,6 +19,7 @@ @SuppressWarnings("serial") public abstract class LargeShapePanel extends JPanel implements LargeShapeCanvas, ShapeModeInterface { + private static final Logger lg = LogManager.getLogger(LargeShapePanel.class); private boolean showDifferencesOnly = false; private boolean bShowMoleculeColor = false; @@ -138,10 +141,10 @@ public boolean zoomSmaller() { // returns false when lower limit was reached zoomFactor--; if(zoomFactor <= SmallestZoomFactor) { zoomFactor = SmallestZoomFactor; - System.out.println("MIN. Factor is " + zoomFactor); + lg.debug("MIN. Factor is " + zoomFactor); return false; } else { - System.out.println("Down. Factor is " + zoomFactor); + lg.debug("Down. Factor is " + zoomFactor); return true; } } diff --git a/vcell-client/src/main/java/cbit/vcell/graph/gui/ReactionCartoonEditorPanel.java b/vcell-client/src/main/java/cbit/vcell/graph/gui/ReactionCartoonEditorPanel.java index 27b5483e45..95127e4479 100644 --- a/vcell-client/src/main/java/cbit/vcell/graph/gui/ReactionCartoonEditorPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/graph/gui/ReactionCartoonEditorPanel.java @@ -35,6 +35,8 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.vcell.util.graphlayout.ExpandCanvasLayouter; import org.vcell.util.graphlayout.GenericLogicGraphLayouter; import org.vcell.util.graphlayout.RandomLayouter; @@ -57,6 +59,8 @@ @SuppressWarnings("serial") public class ReactionCartoonEditorPanel extends JPanel implements ActionListener { + private static final Logger lg = LogManager.getLogger(ReactionCartoonEditorPanel.class); + public static final Dimension TOOL_BAR_SEPARATOR_SIZE = new Dimension(10,0); public static final Dimension NARROW_SEPARATOR_SIZE = new Dimension(2,0); public static final Dimension WIDE_SEPARATOR_SIZE = new Dimension(15,0); @@ -169,7 +173,7 @@ public void run() { }); } else if (source == getGlgLayoutJButton()) -// System.out.println("GLG Layout has been removed"); +// lg.debug("GLG Layout has been removed"); getReactionCartoonTool().layout(GenericLogicGraphLayouter.LAYOUT_NAME); else if (source == getShrinkCanvasButton()) getReactionCartoonTool().layout(ShrinkCanvasLayouter.LAYOUT_NAME); @@ -700,8 +704,7 @@ private JToolBarToggleButton getSizeByLengthButton() { // TODO centralize exception handling private void handleException(Throwable exception) { - System.out.println("--------- UNCAUGHT EXCEPTION --------- in CartoonPanel"); - exception.printStackTrace(System.out); + lg.error("--------- UNCAUGHT EXCEPTION ---------", exception); } private void initConnections() throws Exception { @@ -830,7 +833,7 @@ private JToolBarToggleButton getUngroupButton() { return ungroupButton; } private void setViewMode(String command) { - System.out.println("ReactionCartoonEditorPanel, setViewMode"); + lg.trace("ReactionCartoonEditorPanel, setViewMode"); if(command.equalsIgnoreCase(Mode.GROUPMOLECULE.getActionCommand())) { // group participants by signature currentReactionCartoon = reactionCartoonMolecule; getReactionCartoonTool().setReactionCartoon(currentReactionCartoon); @@ -853,7 +856,7 @@ private void setViewMode(String command) { } private void setSizeMode(String command) { - System.out.println("ReactionCartoonEditorPanel, setSizeMode"); + lg.trace("ReactionCartoonEditorPanel, setSizeMode"); if(command.equalsIgnoreCase(Mode.EQUALSIZE.getActionCommand())) { currentReactionCartoon.setSizeMode(ReactionCartoon.SpeciesSizeOptions.normal); } else if(command.equalsIgnoreCase(Mode.SIZEBYWEIGHT.getActionCommand())) { @@ -934,8 +937,7 @@ public void specialLayout(){ try{ getReactionCartoonTool().layout(GenericLogicGraphLayouter.LAYOUT_NAME, false); }catch(Exception e){ - System.out.println("Error: "+this.getClass().getName()+" setStructureSuite(...)->reactioncartoontool.layout(...)"); - e.printStackTrace(); + lg.error("Error: "+this.getClass().getName()+" setStructureSuite(...)->reactioncartoontool.layout(...)", e); } //} } diff --git a/vcell-client/src/main/java/org/vcell/util/gui/ButtonGroupCivilized.java b/vcell-client/src/main/java/org/vcell/util/gui/ButtonGroupCivilized.java index f00c1928a8..7c9282e47b 100644 --- a/vcell-client/src/main/java/org/vcell/util/gui/ButtonGroupCivilized.java +++ b/vcell-client/src/main/java/org/vcell/util/gui/ButtonGroupCivilized.java @@ -10,6 +10,9 @@ package org.vcell.util.gui; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.util.Enumeration; import javax.swing.AbstractButton; @@ -21,6 +24,7 @@ */ @SuppressWarnings("serial") public class ButtonGroupCivilized extends PropertyChangeButtonGroup { + private static final Logger lg = LogManager.getLogger(ButtonGroupCivilized.class); /** * ButtonGroupCivilized constructor comment. */ @@ -67,7 +71,7 @@ public void setSelection(String actionCommand) { // if we get this far and there actually were some buttons in the group... // if (buttonModel != null) { - System.out.println("ERROR: button with actionCommand " + actionCommand + " not found"); + lg.warn("ERROR: button with actionCommand {} not found", actionCommand); } } /** diff --git a/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java index 002942e312..cc9ab0420f 100644 --- a/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java +++ b/vcell-client/src/main/java/swingthreads/StandardVCellSwingWorker.java @@ -15,9 +15,7 @@ import javax.swing.*; import java.awt.*; import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Hashtable; +import java.util.*; import java.util.List; public abstract class StandardVCellSwingWorker extends VCellSwingWorker { @@ -69,13 +67,17 @@ public StandardVCellSwingWorker(String threadBaseName, List ta * @throws Exception if an exception was generated by running the task */ public static void runTask(AsynchClientTask currentTask, Hashtable hash, Collection taskList) throws Exception { - if (lg.isDebugEnabled()) { - String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); + String msg = "Thread " + Thread.currentThread().getName() + " calling task " + currentTask.getTaskName(); + if (lg.isTraceEnabled()){ Object obj = hash.get(TaskEventKeys.STACK_TRACE_ARRAY.toString()); StackTraceElement[] ste = CastingUtils.downcast(StackTraceElement[].class, obj); - if (ste != null) msg += '\n' + StringUtils.join(ste, '\n'); - lg.debug(msg); + String[] steStrings; + if (ste == null) steStrings = new String[0]; + else steStrings = Arrays.stream(ste).map(StackTraceElement::toString).toArray(String[]::new); + msg += "\n" + String.join("\n\t", steStrings); } + lg.debug(msg); + //check required elements present StringBuilder sb = null; for (AsynchClientTask.KeyInfo requiredKey : currentTask.requiredKeys()) { @@ -265,12 +267,14 @@ public void performSwingPostProcessing() { lg.debug("FinalWindow built from {} and {}", this.windowParent.toString(), this.focusOwner.toString()); } } + + if (!lg.isTraceEnabled()) return; if (fw != null) { lg.debug("scheduling {}.run on {}", fw.getClass().getName(), fw); Runnable runnable = lg.isDebugEnabled() ? ClientTaskDispatcher.debugWrapper(fw) : fw; SwingUtilities.invokeLater(runnable); } else { - lg.debug("no Final Window"); + lg.debug("scheduling run with no final window"); } } diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index 62625eca67..6b23a7d382 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -84,18 +84,18 @@ public synchronized void startPolling() { this.executorService = VCellExecutorService.get(); DataAccessException.addListener(this); } - this.schedule(this.pollTime); - lg.debug("Asynch Polling active"); + this.schedule(AsynchMessageManager.BASE_POLL_SECONDS); + lg.debug("Asynch polling active"); } public void stopPolling() { this.isPollingEnabled.set(false); - lg.debug("Asynch Polling disabled, stopping polling"); + lg.debug("Asynch polling disabled, stopping polling"); } @Override public void created(DataAccessException dae) { -// if (lg.isTraceEnabled()) { + lg.debug("scheduling now due to " + dae.getMessage()); // lg.trace("scheduling now due to " + dae.getMessage()); // } this.schedule(0); @@ -103,12 +103,12 @@ public void created(DataAccessException dae) { private void poll() { if (!this.isPollingEnabled.get()) { - lg.debug("polling stopped"); + lg.debug("polling is not currently enabled"); return; } - lg.debug("polling"); - boolean shouldReport = this.counter % 50 == 0; + if (lg.isTraceEnabled()) lg.debug("Attempting a single poll..."); + boolean shouldReport = this.counter++ % 50 == 0; long begin = 0; long end = 0; diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/Reconnector.java b/vcell-core/src/main/java/cbit/vcell/client/server/Reconnector.java index 9cf5af172e..de7ca764e0 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/Reconnector.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/Reconnector.java @@ -90,8 +90,8 @@ public boolean isActive( ) { * @param p */ void notificationPause(boolean p) { - if (lg.isDebugEnabled()) { - lg.debug("set paused to " + p); + if (lg.isTraceEnabled()) { + lg.debug("set paused to {}", p); } paused.set(p); } @@ -110,14 +110,13 @@ public void addListener(ReconnectListener rl) { */ private void countdown( ) { try { - lg.debug("countdown"); + lg.trace("countdown"); if (!active.get( ) || paused.get()) { return; } --remaining; - if (lg.isDebugEnabled()) { - lg.debug(remaining + " seconds remaining, " + listeners.size() + " listening"); - } + lg.debug("Reconnecting: {} seconds remaining, {} listening", remaining, listeners.size()); + Runnable r = () -> listeners.stream().forEach((rl) -> rl.refactorCountdown(remaining)); SwingUtilities.invokeLater( r ); @@ -128,7 +127,7 @@ private void countdown( ) { waitTime = Math.min(MAX_WAIT_SECONDS, ++reconnectTries * 10) ; } remaining = waitTime; - if (lg.isDebugEnabled()) { + if (lg.isTraceEnabled()) { lg.debug("new time " + remaining); } } diff --git a/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonMolecule.java b/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonMolecule.java index 57df25beb7..e48aabe8fc 100644 --- a/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonMolecule.java +++ b/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonMolecule.java @@ -65,7 +65,7 @@ public void rebindAll(Diagram diagram) { } } } else if(node.nodeType == NodeReference.RULE_PARTICIPANT_SIGNATURE_FULL_NODE) { - System.out.println("ReactionCartoonMolecule, rebindAll(), wrong NodeReference type RULE_PARTICIPANT_SIGNATURE_FULL_NODE"); + lg.warn("ReactionCartoonMolecule, rebindAll(), wrong NodeReference type RULE_PARTICIPANT_SIGNATURE_FULL_NODE"); } } } @@ -105,7 +105,7 @@ public void applyDefaults(Diagram diagram) { obj = getModel().getRbmModelContainer().getReactionRule(node.name); break; case NodeReference.RULE_PARTICIPANT_SIGNATURE_FULL_NODE: // obj is a RuleParticipantSignature - System.out.println("ReactionCartoonMolecule, RULE_PARTICIPANT_SIGNATURE_FULL_NODE detected"); + lg.warn("ReactionCartoonMolecule, RULE_PARTICIPANT_SIGNATURE_FULL_NODE detected"); for(RuleParticipantSignature signature : ruleParticipantSignatures) { if (signature instanceof RuleParticipantLongSignature && signature.getStructure() == struct && signature.compareByCriteria(node.getName(), GroupingCriteria.full)){ obj = signature; @@ -172,7 +172,7 @@ public void setPositionsFromReactionCartoon(Diagram diagram) { ((SpeciesContext) shape.getModelObject()).getName(), shape.getSpaceManager().getRelPos())); } else if (shape instanceof RuleParticipantSignatureFullDiagramShape) { - System.out.println("ReactionCartoonMolecule, Invalid shape type 'RuleParticipantSignatureFullDiagramShape'"); + lg.warn("ReactionCartoonMolecule, Invalid shape type 'RuleParticipantSignatureFullDiagramShape'"); RuleParticipantSignature ruleParticipantSignature = (RuleParticipantSignature) shape.getModelObject(); if (ruleParticipantSignature.getStructure() == diagram.getStructure()){ String spAsString = ruleParticipantSignature.getFirstSpeciesPatternAsString(); @@ -199,7 +199,7 @@ protected void refreshAll(boolean reallocateShapes) { if (getModel() == null || getStructureSuite() == null) { return; } - System.out.println("ReactionCartoonMolecule, RefreshAll()"); + lg.trace("ReactionCartoonMolecule, RefreshAll()"); for(Structure structure : structureSuite.getStructures()) { Diagram diagram = getModel().getDiagram(structure); if (diagram != null) { @@ -362,7 +362,7 @@ protected void refreshAll(boolean reallocateShapes) { RuleParticipantShortSignature ruleParticipantShortSignature = null; for (RuleParticipantSignature signature : ruleParticipantSignatures) { if (signature instanceof RuleParticipantLongSignature && signature.getStructure() == participant.getStructure()) { - System.out.println("ReactionCartoonMolecule, refreshAll(), RuleParticipantLongSignature"); + lg.trace("ReactionCartoonMolecule, refreshAll(), RuleParticipantLongSignature"); break; } } @@ -440,21 +440,21 @@ protected void refreshAll(boolean reallocateShapes) { //TODO: uncomment the following block to track the instances of participants and signatures during transitions // String msg1 = transitioning ? "transitioning to " : "staying "; // msg1 += ruleParticipantGroupingCriteria == RuleParticipantSignature.Criteria.full ? "full" : "short"; -// System.out.println(" --------------------------------- " + msg1 + " ------------------------"); +// lg.debug(" --------------------------------- " + msg1 + " ------------------------"); // for (RuleParticipantSignature signature : ruleParticipantSignatures) { // String sSign = RbmUtils.toBnglString(signature.getSpeciesPattern(), null, CompartmentMode.hide, 0); // String msg2 = "sign "; // msg2 += signature instanceof RuleParticipantLongSignature ? "full: " : "short: "; // String hashSignature = System.identityHashCode(signature) + ""; // String hashSP = System.identityHashCode(signature.getSpeciesPattern()) + ""; -// System.out.println(msg2 + sSign + ", sp hash: " + hashSP + ", signature hash: " + hashSignature); +// lg.debug(msg2 + sSign + ", sp hash: " + hashSP + ", signature hash: " + hashSignature); // } // for(ReactionRule rr : getModel().getRbmModelContainer().getReactionRuleList()) { // for(ReactionRuleParticipant participant : rr.getReactionRuleParticipants()) { // String hashParticipant = System.identityHashCode(participant) + ""; // String hashSP = System.identityHashCode(participant.getSpeciesPattern()) + ""; // String sPart = RbmUtils.toBnglString(participant.getSpeciesPattern(), null, CompartmentMode.hide, 0); -// System.out.println("part: " + sPart + ", sp hash: " + hashSP + ", participant hash: " + hashParticipant); +// lg.debug("part: " + sPart + ", sp hash: " + hashSP + ", participant hash: " + hashParticipant); // } // } @@ -465,7 +465,7 @@ protected void refreshAll(boolean reallocateShapes) { if(getStructureSuite().areReactionsShownFor(structure)) { ReactionContainerShape reactionContainerShape = (ReactionContainerShape) getShapeFromModelObject(structure); if(reactionContainerShape == null) { - System.out.println("Reaction container shape is null for structure " + structure + + lg.debug("Reaction container shape is null for structure " + structure + " for reaction step " + reactionStep); } ReactionStepShape reactionStepShape = (ReactionStepShape) getShapeFromModelObject(reactionStep); diff --git a/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonRule.java b/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonRule.java index 5063f03f3d..c80a228e57 100644 --- a/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonRule.java +++ b/vcell-core/src/main/java/cbit/vcell/graph/ReactionCartoonRule.java @@ -57,7 +57,7 @@ public void rebindAll(Diagram diagram) { // } // } // } else if(node.nodeType == NodeReference.RULE_PARTICIPANT_SIGNATURE_FULL_NODE) { -// System.out.println("ReactionCartoonRule, rebindAll(), wrong NodeReference type RULE_PARTICIPANT_SIGNATURE_FULL_NODE"); +// lg.trace("ReactionCartoonRule, rebindAll(), wrong NodeReference type RULE_PARTICIPANT_SIGNATURE_FULL_NODE"); // } // } } @@ -98,7 +98,7 @@ public void applyDefaults(Diagram diagram) { obj = getModel().getRbmModelContainer().getReactionRule(node.name); break; case NodeReference.RULE_PARTICIPANT_SIGNATURE_FULL_NODE: // obj is a RuleParticipantSignature - System.out.println("ReactionCartoonRule, RULE_PARTICIPANT_SIGNATURE_FULL_NODE detected"); + lg.warn("ReactionCartoonRule, RULE_PARTICIPANT_SIGNATURE_FULL_NODE detected"); for(RuleParticipantSignature signature : ruleParticipantSignatures) { if (signature instanceof RuleParticipantLongSignature && signature.getStructure() == struct && signature.compareByCriteria(node.getName(), GroupingCriteria.full)){ obj = signature; @@ -172,7 +172,7 @@ public void setPositionsFromReactionCartoon(Diagram diagram) { ((SpeciesContext) shape.getModelObject()).getName(), shape.getSpaceManager().getRelPos())); } else if (shape instanceof RuleParticipantSignatureFullDiagramShape) { - System.out.println("ReactionCartoonRule, Invalid shape type 'RuleParticipantSignatureFullDiagramShape'"); + lg.warn("ReactionCartoonRule, Invalid shape type 'RuleParticipantSignatureFullDiagramShape'"); RuleParticipantSignature ruleParticipantSignature = (RuleParticipantSignature) shape.getModelObject(); if (ruleParticipantSignature.getStructure() == diagram.getStructure()) { String spAsString = ruleParticipantSignature.getFirstSpeciesPatternAsString(); @@ -199,7 +199,7 @@ protected void refreshAll(boolean reallocateShapes) { if (getModel() == null || getStructureSuite() == null) { return; } - System.out.println("ReactionCartoonRule, RefreshAll()"); + lg.trace("ReactionCartoonRule, RefreshAll()"); for(Structure structure : structureSuite.getStructures()) { Diagram diagram = getModel().getDiagram(structure); if (diagram != null) { @@ -351,7 +351,7 @@ protected void refreshAll(boolean reallocateShapes) { // RuleParticipantShortSignature ruleParticipantShortSignature = null; // for (RuleParticipantSignature signature : ruleParticipantSignatures) { // if (signature instanceof RuleParticipantLongSignature && signature.getStructure() == participant.getStructure()) { -// System.out.println("ReactionCartoonMolecule, refreshAll(), RuleParticipantLongSignature"); +// lg.trace("ReactionCartoonMolecule, refreshAll(), RuleParticipantLongSignature"); // break; // } // } @@ -430,21 +430,21 @@ protected void refreshAll(boolean reallocateShapes) { // //TODO: uncomment the following block to track the instances of participants and signatures during transitions //// String msg1 = transitioning ? "transitioning to " : "staying "; //// msg1 += ruleParticipantGroupingCriteria == RuleParticipantSignature.Criteria.full ? "full" : "short"; -//// System.out.println(" --------------------------------- " + msg1 + " ------------------------"); +//// lg.debug(" --------------------------------- " + msg1 + " ------------------------"); //// for (RuleParticipantSignature signature : ruleParticipantSignatures) { //// String sSign = RbmUtils.toBnglString(signature.getSpeciesPattern(), null, CompartmentMode.hide, 0); //// String msg2 = "sign "; //// msg2 += signature instanceof RuleParticipantLongSignature ? "full: " : "short: "; //// String hashSignature = System.identityHashCode(signature) + ""; //// String hashSP = System.identityHashCode(signature.getSpeciesPattern()) + ""; -//// System.out.println(msg2 + sSign + ", sp hash: " + hashSP + ", signature hash: " + hashSignature); +//// lg.debug(msg2 + sSign + ", sp hash: " + hashSP + ", signature hash: " + hashSignature); //// } //// for(ReactionRule rr : getModel().getRbmModelContainer().getReactionRuleList()) { //// for(ReactionRuleParticipant participant : rr.getReactionRuleParticipants()) { //// String hashParticipant = System.identityHashCode(participant) + ""; //// String hashSP = System.identityHashCode(participant.getSpeciesPattern()) + ""; //// String sPart = RbmUtils.toBnglString(participant.getSpeciesPattern(), null, CompartmentMode.hide, 0); -//// System.out.println("part: " + sPart + ", sp hash: " + hashSP + ", participant hash: " + hashParticipant); +//// lg.debug("part: " + sPart + ", sp hash: " + hashSP + ", participant hash: " + hashParticipant); //// } //// } // @@ -455,7 +455,7 @@ protected void refreshAll(boolean reallocateShapes) { // if(getStructureSuite().areReactionsShownFor(structure)) { // ReactionContainerShape reactionContainerShape = (ReactionContainerShape) getShapeFromModelObject(structure); // if(reactionContainerShape == null) { -// System.out.println("Reaction container shape is null for structure " + structure + +// lg.debug("Reaction container shape is null for structure " + structure + // " for reaction step " + reactionStep); // } // ReactionStepShape reactionStepShape = (ReactionStepShape) getShapeFromModelObject(reactionStep); From 3a3b1bb7211f573fc26eb1171aa285937ce615d2 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 15:16:20 -0400 Subject: [PATCH 43/48] Fixed pop-up window's message when VCell is opened without internet --- .../src/main/java/cbit/vcell/server/Auth0ConnectionUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vcell-core/src/main/java/cbit/vcell/server/Auth0ConnectionUtils.java b/vcell-core/src/main/java/cbit/vcell/server/Auth0ConnectionUtils.java index 1ce17174ef..7c4714fa7b 100644 --- a/vcell-core/src/main/java/cbit/vcell/server/Auth0ConnectionUtils.java +++ b/vcell-core/src/main/java/cbit/vcell/server/Auth0ConnectionUtils.java @@ -9,6 +9,7 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.net.UnknownHostException; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -30,6 +31,9 @@ public void auth0SignIn(boolean isGuest) throws ApiException { boolean ignoreSSLCertProblems = bIgnoreCertProblems || bIgnoreHostMismatch; if (!isGuest) vcellApiClient.authenticate(ignoreSSLCertProblems); else vcellApiClient.createDefaultQuarkusClient(ignoreSSLCertProblems); + } catch (UnknownHostException e) { + throw new RuntimeException("VCell can not attempt to login:\n\n" + + "VCell was unable to connect to the internet while trying to connect to '" + e.getMessage() + "'\n\n", e); } catch (ApiException | URISyntaxException | IOException | ParseException e){ throw new RuntimeException(e); } From 7a262a3543d69a596cca5f020651ee16655880ea Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 15:16:28 -0400 Subject: [PATCH 44/48] Fixed NPE exception --- .../main/java/org/vcell/client/logicalwindow/LWNamespace.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcell-client/src/main/java/org/vcell/client/logicalwindow/LWNamespace.java b/vcell-client/src/main/java/org/vcell/client/logicalwindow/LWNamespace.java index 425729a527..7e4b45bd60 100644 --- a/vcell-client/src/main/java/org/vcell/client/logicalwindow/LWNamespace.java +++ b/vcell-client/src/main/java/org/vcell/client/logicalwindow/LWNamespace.java @@ -126,7 +126,7 @@ public static T findOwnerOfType(Class clzz, Component swingPare lg.debug(ExecutionTrace.justClassName(swingParent) + " does not implement " + ExecutionTrace.justClassName(clzz)); } - Container up = swingParent.getParent(); + Container up = swingParent == null ? null : swingParent.getParent(); if (up == null) { lg.error("top level object " + ExecutionTrace.justClassName(swingParent) + " does not implement " + ExecutionTrace.justClassName(clzz)); return null; From 297fca19cc044927331e66ddf85ebf0ce498dd88 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 15:19:07 -0400 Subject: [PATCH 45/48] Added timeout to message call to drastically improve disconnect response --- .../vcell/client/server/AsynchMessageManager.java | 7 ++++--- .../vcell/client/server/ClientServerManager.java | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index 6b23a7d382..dfb7315a62 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -52,13 +52,14 @@ public class AsynchMessageManager implements SimStatusListener, DataAccessException.Listener, DataJobListenerHolder { private static final long BASE_POLL_SECONDS = 3; private static final long ATTEMPT_POLL_SECONDS = 3; + private static final long DEFAULT_TIMEOUT_MS = 1500; private static final Logger lg = LogManager.getLogger(AsynchMessageManager.class); private final EventListenerList listenerList = new EventListenerList(); private final ClientServerManager clientServerManager; private int failureCount = 0; private ScheduledExecutorService executorService = null; - private final long counter = 0; + private long counter = 0; private long pollTime = BASE_POLL_SECONDS; private final AtomicBoolean isPollingEnabled = new AtomicBoolean(false); private ScheduledFuture pollingHandle = null; @@ -122,8 +123,8 @@ private void poll() { this.clientServerManager.attemptReconnect(); return; } - this.pollTime = BASE_POLL_SECONDS; - queuedEvents = this.clientServerManager.getMessageEvents(); + + queuedEvents = this.clientServerManager.getMessageEvents(AsynchMessageManager.DEFAULT_TIMEOUT_MS); if (shouldReport) end = System.currentTimeMillis(); diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java index 4612ac2f6c..584d1a7fad 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.net.URL; +import java.util.concurrent.*; /** * Insert the type's description here. @@ -279,6 +280,18 @@ public MessageEvent[] getMessageEvents() throws RemoteProxyException, IOExceptio } } + public MessageEvent[] getMessageEvents(long timeoutMs) throws RemoteProxyException, IOException, TimeoutException { + Callable getMessageEventsCallable = this::getMessageEvents; + FutureTask futureTask = new FutureTask<>(getMessageEventsCallable); + Thread messageFetchThread = new Thread(futureTask); + messageFetchThread.start(); + try { + return futureTask.get(timeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException("Error Attempting to get message events:", e); + } + } + private void checkClientServerSoftwareVersion(InteractiveContext requester, ClientServerInfo clientServerInfo) { String clientSoftwareVersion = System.getProperty(PropertyLoader.vcellSoftwareVersion); if (clientSoftwareVersion != null && clientSoftwareVersion.toLowerCase().contains("devel") ) { From 8d8fa351e324973a4a8e77c6a2d45f311d658299 Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 15:20:17 -0400 Subject: [PATCH 46/48] eliminated unnecessary instance variable and further improved responsiveness --- .../client/server/AsynchMessageManager.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java index dfb7315a62..33f0fc744a 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/AsynchMessageManager.java @@ -38,7 +38,6 @@ import cbit.rmi.event.VCellMessageEventListener; import cbit.vcell.resource.VCellExecutorService; import cbit.vcell.server.VCellConnection; -import edu.uchc.connjur.wb.ExecutionTrace; /** * {@link AsynchMessageManager} polls from {@link VCellConnection} to get remote messages. Remote Messages include the following: @@ -51,7 +50,7 @@ */ public class AsynchMessageManager implements SimStatusListener, DataAccessException.Listener, DataJobListenerHolder { private static final long BASE_POLL_SECONDS = 3; - private static final long ATTEMPT_POLL_SECONDS = 3; + private static final long RETRY_POLL_SECONDS = 1; private static final long DEFAULT_TIMEOUT_MS = 1500; private static final Logger lg = LogManager.getLogger(AsynchMessageManager.class); @@ -60,7 +59,6 @@ public class AsynchMessageManager implements SimStatusListener, DataAccessExcept private int failureCount = 0; private ScheduledExecutorService executorService = null; private long counter = 0; - private long pollTime = BASE_POLL_SECONDS; private final AtomicBoolean isPollingEnabled = new AtomicBoolean(false); private ScheduledFuture pollingHandle = null; /** @@ -97,8 +95,6 @@ public void stopPolling() { @Override public void created(DataAccessException dae) { lg.debug("scheduling now due to " + dae.getMessage()); -// lg.trace("scheduling now due to " + dae.getMessage()); -// } this.schedule(0); } @@ -144,16 +140,18 @@ this, null, new PerformanceData( ); } catch (Exception exc) { lg.error(">> POLLING FAILURE <<", exc); - this.pollTime = ATTEMPT_POLL_SECONDS; this.failureCount++; if (this.failureCount % 3 == 0) { this.isPollingEnabled.set(false); this.clientServerManager.setDisconnected(); } } finally { - this.connectionLock.unlock(); - lg.debug(ExecutionTrace.justClassName(this) + " poll time " + this.pollTime + " seconds"); - if (this.isPollingEnabled.get()) this.schedule(this.pollTime); + long retryTime = this.failureCount > 0 ? + AsynchMessageManager.RETRY_POLL_SECONDS : AsynchMessageManager.BASE_POLL_SECONDS; + if (lg.isTraceEnabled()) + lg.debug("Poll concluded; Next poll in " + retryTime + " seconds"); + if (this.connectionLock.isHeldByCurrentThread()) this.connectionLock.unlock(); + if (this.isPollingEnabled.get()) this.schedule(retryTime); } } From da0f3b204b81135228eab2908b063a7565b47b0a Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 15:42:49 -0400 Subject: [PATCH 47/48] Used Collatz Conjecture to check timeout feature. --- .../client/ClientTaskDispatcherTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/vcell-admin/src/test/java/cbit/vcell/client/ClientTaskDispatcherTest.java b/vcell-admin/src/test/java/cbit/vcell/client/ClientTaskDispatcherTest.java index 2da574253d..75c8e0c72d 100644 --- a/vcell-admin/src/test/java/cbit/vcell/client/ClientTaskDispatcherTest.java +++ b/vcell-admin/src/test/java/cbit/vcell/client/ClientTaskDispatcherTest.java @@ -10,6 +10,9 @@ import java.awt.*; import java.util.Hashtable; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import static cbit.vcell.client.task.AsynchClientTask.*; @@ -40,6 +43,37 @@ public void sbNotLast( ) { test(TASKTYPE_NONSWING_BLOCKING,TASKTYPE_NONSWING_BLOCKING, TASKTYPE_SWING_NONBLOCKING, TASKTYPE_NONSWING_BLOCKING); }); } + + @Test void blockingCheck(){ + AsynchClientTask collatzConjecture = new AsynchClientTask( + "Collatz Conjecture", AsynchClientTask.TASKTYPE_NONSWING_BLOCKING) { + + @Override + public void run(Hashtable hashTable) throws Exception { + for (long startingNum = 1; startingNum < Long.MAX_VALUE; startingNum++) { + long currentNum = startingNum; + long counter = 0; + while(true){ + if (currentNum == 1 || currentNum == 2 || currentNum == 4) { + // We won't waste storage space + System.out.print(counter + ", "); + break; + } + counter++; + if (currentNum % 2 == 0) currentNum /= 2; // Even case + if (currentNum %2 == 1) currentNum = (3 * currentNum) + 1; + } + } + } + } ; + Assertions.assertThrows(TimeoutException.class, () -> { + Hashtable hashTable = new Hashtable<>(); + Future terribleFuture = ClientTaskDispatcher.dispatchWithFuture(null, hashTable, + new AsynchClientTask[]{collatzConjecture}); + terribleFuture.get(2, TimeUnit.SECONDS); // Not expensive but significant timeout + }); + + } private AsynchClientTask[] create(int ... types) { AsynchClientTask[] rval = new AsynchClientTask[types.length]; From 3a02aeb7e58681f5538550a558c9be7f3098c42b Mon Sep 17 00:00:00 2001 From: Logan Drescher Date: Fri, 26 Jul 2024 16:02:24 -0400 Subject: [PATCH 48/48] Cleaned up class --- .../client/server/ClientServerManager.java | 1520 +++++++++-------- 1 file changed, 770 insertions(+), 750 deletions(-) diff --git a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java index 584d1a7fad..1cc8c1a61f 100644 --- a/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java +++ b/vcell-core/src/main/java/cbit/vcell/client/server/ClientServerManager.java @@ -38,334 +38,337 @@ /** * Insert the type's description here. * Creation date: (5/12/2004 4:31:18 PM) + * * @author: Ion Moraru */ -public class ClientServerManager implements SessionManager,DataSetControllerProvider { - private final static Logger lg = LogManager.getLogger(ClientServerManager.class); - private final VCellConnectionFactory vcellConnectionFactory; - - public interface InteractiveContext { - void showErrorDialog(String errorMessage); - - void showWarningDialog(String warningMessage); - - void clearConnectWarning(); - - void showConnectWarning(String message); - } - - public interface InteractiveContextDefaultProvider { - InteractiveContext getInteractiveContext(); - } - - public static final String PROPERTY_NAME_CONNECTION_STATUS = "connectionStatus"; - private class ClientConnectionStatus implements ConnectionStatus { - // actual status info - private String apihost = null; - private Integer apiport = null; - private String userName = null; - private int status = NOT_CONNECTED; - - private ClientConnectionStatus(String userName, String apihost, Integer apiport, int status) { - switch (status) { - case NOT_CONNECTED: { - setUserName(null); - setApihost(null); - setApiport(null); - break; - } - case INITIALIZING: - case CONNECTED: - case DISCONNECTED: { - if (userName == null) throw new RuntimeException("userName should be non-null unless NOT_CONNECTED"); - setUserName(userName); - setApihost(apihost); - setApiport(apiport); - break; - } - default: { - throw new RuntimeException("unknown connection status: " + status); - } - } - setStatus(status); - } - - - public String getApihost() { - return apihost; - } - - public Integer getApiport() { - return apiport; - } - - public int getStatus() { - return status; - } - - public java.lang.String getUserName() { - return userName; - } - - - private void setApihost(java.lang.String newApihost) { - this.apihost = newApihost; - } - - private void setApiport(Integer newApiport) { - this.apiport = newApiport; - } - - - private void setStatus(int newStatus) { - status = newStatus; - } - - private void setUserName(java.lang.String newUserName) { - userName = newUserName; - } - - public String toString() { - return "status " + getStatus() + " apihost " + getApihost() + " apiport " + getApiport() + " user " + getUserName(); - } - - - - @Override - public Reconnector getReconnector() { - return ClientServerManager.this.getReconnector(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((apihost == null) ? 0 : apihost.hashCode()); - result = prime * result + ((apiport == null) ? 0 : apiport.hashCode()); - result = prime * result + status; - result = prime * result + ((userName == null) ? 0 : userName.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ClientConnectionStatus) { - return false; - } - ClientConnectionStatus other = (ClientConnectionStatus) obj; - if (!Compare.isEqualOrNull(apihost, other.apihost)) { - return false; - } - if (!Compare.isEqualOrNull(apiport, other.apiport)) { - return false; - } - if (status != other.status) { - return false; - } - if (!Compare.isEqualOrNull(userName, other.userName)) { - return false; - } - return true; - } - - } - private enum ReconnectStatus { - NOT("Not reconnecting"), - FIRST("First reconnection attempt"), - SUBSEQUENT("Subsequent reconnect attempt"); - - private String label; - - private ReconnectStatus(String label) { - this.label = label; - } - @Override - public String toString( ) { - return label; - } - } - private ClientServerInfo clientServerInfo = null; - // - // remote references - // - private VCellConnection vcellConnection = null; - private SimulationController simulationController = null; - private UserMetaDbServer userMetaDbServer = null; - private DataSetController dataSetController = null; - // gotten from call to vcellConnection - private User user = null; - - private DocumentManager documentManager = new ClientDocumentManager(this, 10000000L);; - private JobManager jobManager = null; - private ExportController exportController = null; - private AsynchMessageManager asynchMessageManager = null; - private VCDataManager vcDataManager = null; - private UserPreferences userPreferences = new UserPreferences(this); - protected transient java.beans.PropertyChangeSupport propertyChange; - private ClientConnectionStatus fieldConnectionStatus = new ClientConnectionStatus(null, null, null, ConnectionStatus.NOT_CONNECTED); - private ReconnectStatus reconnectStat = ReconnectStatus.NOT; - private final InteractiveContextDefaultProvider defaultInteractiveContextProvider; - /** - * modeless window to warn about lost connection - */ - private Reconnector reconnector = null; +public class ClientServerManager implements SessionManager, DataSetControllerProvider { + private final static Logger lg = LogManager.getLogger(ClientServerManager.class); + private final VCellConnectionFactory vcellConnectionFactory; + + public interface InteractiveContext { + void showErrorDialog(String errorMessage); + + void showWarningDialog(String warningMessage); + + void clearConnectWarning(); + + void showConnectWarning(String message); + } + + public interface InteractiveContextDefaultProvider { + InteractiveContext getInteractiveContext(); + } + + public static final String PROPERTY_NAME_CONNECTION_STATUS = "connectionStatus"; + + private class ClientConnectionStatus implements ConnectionStatus { + // actual status info + private String apihost = null; + private Integer apiport = null; + private String userName = null; + private int status = NOT_CONNECTED; + + private ClientConnectionStatus(String userName, String apihost, Integer apiport, int status) { + switch (status) { + case NOT_CONNECTED: { + this.setUserName(null); + this.setApihost(null); + this.setApiport(null); + break; + } + case INITIALIZING: + case CONNECTED: + case DISCONNECTED: { + if (userName == null) + throw new RuntimeException("userName should be non-null unless NOT_CONNECTED"); + this.setUserName(userName); + this.setApihost(apihost); + this.setApiport(apiport); + break; + } + default: { + throw new RuntimeException("unknown connection status: " + status); + } + } + this.setStatus(status); + } -/** - * The addPropertyChangeListener method was generated to support the propertyChange field. - */ -public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener listener) { - getPropertyChange().addPropertyChangeListener(listener); -} -public ClientServerManager(VCellConnectionFactory vcellConnectionFactory, ClientServerInfo clientServerInfo, InteractiveContextDefaultProvider defaultInteractiveContextProvider) { - this.vcellConnectionFactory = vcellConnectionFactory; - this.clientServerInfo = clientServerInfo; - this.defaultInteractiveContextProvider = defaultInteractiveContextProvider; -} + public String getApihost() { + return this.apihost; + } - public Auth0ConnectionUtils getAuth0ConnectionUtils() { - return vcellConnectionFactory.getAuth0ConnectionUtils(); - } + public Integer getApiport() { + return this.apiport; + } -/** - * Insert the method's description here. - * Creation date: (5/12/2004 4:48:13 PM) - */ -private void changeConnection(InteractiveContext requester, VCellConnection newVCellConnection) { - VCellThreadChecker.checkRemoteInvocation(); - - VCellConnection lastVCellConnection = getVcellConnection(); - setVcellConnection(newVCellConnection); - if (getVcellConnection() != null) { - try { - /* new credentials; need full init */ - // throw it away; doesn't properly support full reinits - // preload the document manager cache - ((ClientDocumentManager)getDocumentManager()).initAllDatabaseInfos(); - - // load user preferences - getUserPreferences().resetFromSaved(getDocumentManager().getPreferences()); - - setConnectionStatus(new ClientConnectionStatus(getClientServerInfo().getUsername(), getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), ConnectionStatus.CONNECTED)); - } catch (DataAccessException exc) { - // unlikely, since we just connected, but it looks like we did loose the connection... - lastVCellConnection = getVcellConnection(); - setVcellConnection(null); - setConnectionStatus(new ClientConnectionStatus(getClientServerInfo().getUsername(), getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); - lg.error("Server connection failed", exc); - requester.showErrorDialog("Server connection failed:\n\n" + exc.getMessage()); - } - } else if(lastVCellConnection != null) { - setConnectionStatus(new ClientConnectionStatus(getClientServerInfo().getUsername(), getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); - } else { - setConnectionStatus(new ClientConnectionStatus(null, null, null, ConnectionStatus.NOT_CONNECTED)); - } -} + public int getStatus() { + return this.status; + } -/** - * Insert the method's description here. - * Creation date: (5/25/2004 2:03:47 AM) - * @return int - */ -public void cleanup() { - setVcellConnection(null); - setConnectionStatus(new ClientConnectionStatus(null, null, null, ConnectionStatus.NOT_CONNECTED)); -} + public java.lang.String getUserName() { + return this.userName; + } -public MessageEvent[] getMessageEvents() throws RemoteProxyException, IOException{ - if (vcellConnection!=null && isStatusConnected()){ - return vcellConnection.getMessageEvents(); - } else { - return null; - } -} - public MessageEvent[] getMessageEvents(long timeoutMs) throws RemoteProxyException, IOException, TimeoutException { - Callable getMessageEventsCallable = this::getMessageEvents; - FutureTask futureTask = new FutureTask<>(getMessageEventsCallable); - Thread messageFetchThread = new Thread(futureTask); - messageFetchThread.start(); - try { - return futureTask.get(timeoutMs, TimeUnit.MILLISECONDS); - } catch (ExecutionException | InterruptedException e) { - throw new RuntimeException("Error Attempting to get message events:", e); + private void setApihost(java.lang.String newApihost) { + this.apihost = newApihost; } - } - -private void checkClientServerSoftwareVersion(InteractiveContext requester, ClientServerInfo clientServerInfo) { - String clientSoftwareVersion = System.getProperty(PropertyLoader.vcellSoftwareVersion); - if (clientSoftwareVersion != null && clientSoftwareVersion.toLowerCase().contains("devel") ) { - return; - } - if (clientServerInfo.getServerType() == ServerType.SERVER_REMOTE) { - String apihost = clientServerInfo.getApihost(); - Integer apiport = clientServerInfo.getApiport(); - String pathPrefixV0 = clientServerInfo.getPathPrefix_v0(); - String serverSoftwareVersion = RemoteProxyVCellConnectionFactory.getVCellSoftwareVersion(apihost,apiport,pathPrefixV0); - if (serverSoftwareVersion != null && !serverSoftwareVersion.equals(clientSoftwareVersion)) { - VCellSoftwareVersion clientVersion = VCellSoftwareVersion.fromString(clientSoftwareVersion); - VCellSoftwareVersion serverVersion = VCellSoftwareVersion.fromString(serverSoftwareVersion); - if (clientVersion.getSite()==VCellSite.beta) { - requester.showWarningDialog("VCell Public Beta program has been discontinued - please use our Release VCell version\n\n" - + "We have adopted a Release Early, Release Often software development approach\n\n" - + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); - } - if (clientVersion.getMajorVersion()!=serverVersion.getMajorVersion() || - clientVersion.getMinorVersion()!=serverVersion.getMinorVersion() || - clientVersion.getPatchVersion()!=serverVersion.getPatchVersion()) { - requester.showWarningDialog("software version mismatch between client and server:\n" - + "client VCell version : " + clientSoftwareVersion + "\n" - + "server VCell version : " + serverSoftwareVersion + "\n" - + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); - } - } - } -} + private void setApiport(Integer newApiport) { + this.apiport = newApiport; + } -public void connectNewServer(InteractiveContext requester, ClientServerInfo csi) { - clientServerInfo = csi; - connect(requester); -} -/** - * Insert the method's description here. - * Creation date: (5/17/2004 6:26:14 PM) - */ -public void connect(InteractiveContext requester) { - asynchMessageManager.stopPolling(); - reconnectStat = ReconnectStatus.NOT; - checkClientServerSoftwareVersion(requester,clientServerInfo); - - // get new server connection - VCellConnection newVCellConnection = connectToServer(requester,true); - // update managers, status, etc. - changeConnection(requester, newVCellConnection); - if (fieldConnectionStatus.getStatus() == ConnectionStatus.CONNECTED) { - //start polling if haven't already - asynchMessageManager.startPolling(); - } -} + private void setStatus(int newStatus) { + this.status = newStatus; + } -/** - * same as {@link #connect(InteractiveContext)} but pause {@link Reconnector} - * @param requester - */ -public void reconnect(InteractiveContext requester) { - Reconnector rc = getReconnector(); - try { - rc.start(); - rc.notificationPause(true); - connect(requester); - if (fieldConnectionStatus.getStatus() == ConnectionStatus.CONNECTED) { - rc.stop( ); - asynchMessageManager.startPolling(); - } - } - finally { - rc.notificationPause(false); - } -} + private void setUserName(java.lang.String newUserName) { + this.userName = newUserName; + } + + public String toString() { + return "status " + this.getStatus() + " apihost " + this.getApihost() + " apiport " + this.getApiport() + " user " + this.getUserName(); + } + + + @Override + public Reconnector getReconnector() { + return ClientServerManager.this.getReconnector(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((this.apihost == null) ? 0 : this.apihost.hashCode()); + result = prime * result + ((this.apiport == null) ? 0 : this.apiport.hashCode()); + result = prime * result + this.status; + result = prime * result + ((this.userName == null) ? 0 : this.userName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ClientConnectionStatus) { + return false; + } + ClientConnectionStatus other = (ClientConnectionStatus) obj; + if (!Compare.isEqualOrNull(this.apihost, other.apihost)) { + return false; + } + if (!Compare.isEqualOrNull(this.apiport, other.apiport)) { + return false; + } + if (this.status != other.status) { + return false; + } + return Compare.isEqualOrNull(this.userName, other.userName); + } + + } + + private enum ReconnectStatus { + NOT("Not reconnecting"), + FIRST("First reconnection attempt"), + SUBSEQUENT("Subsequent reconnect attempt"); + + private final String label; + + ReconnectStatus(String label) { + this.label = label; + } + + @Override + public String toString() { + return this.label; + } + } + + private ClientServerInfo clientServerInfo = null; + // + // remote references + // + private VCellConnection vcellConnection = null; + private SimulationController simulationController = null; + private UserMetaDbServer userMetaDbServer = null; + private DataSetController dataSetController = null; + // gotten from call to vcellConnection + private User user = null; + + private final DocumentManager documentManager = new ClientDocumentManager(this, 10000000L); + private JobManager jobManager = null; + private ExportController exportController = null; + private AsynchMessageManager asynchMessageManager = null; + private VCDataManager vcDataManager = null; + private final UserPreferences userPreferences = new UserPreferences(this); + protected transient java.beans.PropertyChangeSupport propertyChange; + private ClientConnectionStatus fieldConnectionStatus = new ClientConnectionStatus(null, null, null, ConnectionStatus.NOT_CONNECTED); + private ReconnectStatus reconnectStat = ReconnectStatus.NOT; + private final InteractiveContextDefaultProvider defaultInteractiveContextProvider; + /** + * modeless window to warn about lost connection + */ + private Reconnector reconnector = null; + + /** + * The addPropertyChangeListener method was generated to support the propertyChange field. + */ + public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener listener) { + this.getPropertyChange().addPropertyChangeListener(listener); + } + + public ClientServerManager(VCellConnectionFactory vcellConnectionFactory, ClientServerInfo clientServerInfo, InteractiveContextDefaultProvider defaultInteractiveContextProvider) { + this.vcellConnectionFactory = vcellConnectionFactory; + this.clientServerInfo = clientServerInfo; + this.defaultInteractiveContextProvider = defaultInteractiveContextProvider; + } + + public Auth0ConnectionUtils getAuth0ConnectionUtils() { + return this.vcellConnectionFactory.getAuth0ConnectionUtils(); + } + + /** + * Insert the method's description here. + * Creation date: (5/12/2004 4:48:13 PM) + */ + private void changeConnection(InteractiveContext requester, VCellConnection newVCellConnection) { + VCellThreadChecker.checkRemoteInvocation(); + + VCellConnection lastVCellConnection = this.getVcellConnection(); + this.setVcellConnection(newVCellConnection); + if (this.getVcellConnection() != null) { + try { + /* new credentials; need full init */ + // throw it away; doesn't properly support full reinits + // preload the document manager cache + ((ClientDocumentManager) this.getDocumentManager()).initAllDatabaseInfos(); + + // load user preferences + this.getUserPreferences().resetFromSaved(this.getDocumentManager().getPreferences()); + + this.setConnectionStatus(new ClientConnectionStatus(this.getClientServerInfo().getUsername(), this.getClientServerInfo().getApihost(), this.getClientServerInfo().getApiport(), ConnectionStatus.CONNECTED)); + } catch (DataAccessException exc) { + // unlikely, since we just connected, but it looks like we did loose the connection... + lastVCellConnection = this.getVcellConnection(); + this.setVcellConnection(null); + this.setConnectionStatus(new ClientConnectionStatus(this.getClientServerInfo().getUsername(), this.getClientServerInfo().getApihost(), this.getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); + lg.error("Server connection failed", exc); + requester.showErrorDialog("Server connection failed:\n\n" + exc.getMessage()); + } + } else if (lastVCellConnection != null) { + this.setConnectionStatus(new ClientConnectionStatus(this.getClientServerInfo().getUsername(), this.getClientServerInfo().getApihost(), this.getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); + } else { + this.setConnectionStatus(new ClientConnectionStatus(null, null, null, ConnectionStatus.NOT_CONNECTED)); + } + } + + /** + * Insert the method's description here. + * Creation date: (5/25/2004 2:03:47 AM) + * + * @return int + */ + public void cleanup() { + this.setVcellConnection(null); + this.setConnectionStatus(new ClientConnectionStatus(null, null, null, ConnectionStatus.NOT_CONNECTED)); + } + + public MessageEvent[] getMessageEvents() throws RemoteProxyException, IOException { + if (this.vcellConnection != null && this.isStatusConnected()) { + return this.vcellConnection.getMessageEvents(); + } else { + return null; + } + } + + public MessageEvent[] getMessageEvents(long timeoutMs) throws RemoteProxyException, IOException, TimeoutException { + Callable getMessageEventsCallable = this::getMessageEvents; + FutureTask futureTask = new FutureTask<>(getMessageEventsCallable); + Thread messageFetchThread = new Thread(futureTask); + messageFetchThread.start(); + try { + return futureTask.get(timeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException("Error Attempting to get message events:", e); + } + } + + private void checkClientServerSoftwareVersion(InteractiveContext requester, ClientServerInfo clientServerInfo) { + String clientSoftwareVersion = System.getProperty(PropertyLoader.vcellSoftwareVersion); + if (clientSoftwareVersion != null && clientSoftwareVersion.toLowerCase().contains("devel")) { + return; + } + if (clientServerInfo.getServerType() == ServerType.SERVER_REMOTE) { + String apihost = clientServerInfo.getApihost(); + Integer apiport = clientServerInfo.getApiport(); + String pathPrefixV0 = clientServerInfo.getPathPrefix_v0(); + String serverSoftwareVersion = RemoteProxyVCellConnectionFactory.getVCellSoftwareVersion(apihost, apiport, pathPrefixV0); + if (serverSoftwareVersion != null && !serverSoftwareVersion.equals(clientSoftwareVersion)) { + VCellSoftwareVersion clientVersion = VCellSoftwareVersion.fromString(clientSoftwareVersion); + VCellSoftwareVersion serverVersion = VCellSoftwareVersion.fromString(serverSoftwareVersion); + if (clientVersion.getSite() == VCellSite.beta) { + requester.showWarningDialog("VCell Public Beta program has been discontinued - please use our Release VCell version\n\n" + + "We have adopted a Release Early, Release Often software development approach\n\n" + + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); + } + if (clientVersion.getMajorVersion() != serverVersion.getMajorVersion() || + clientVersion.getMinorVersion() != serverVersion.getMinorVersion() || + clientVersion.getPatchVersion() != serverVersion.getPatchVersion()) { + requester.showWarningDialog("software version mismatch between client and server:\n" + + "client VCell version : " + clientSoftwareVersion + "\n" + + "server VCell version : " + serverSoftwareVersion + "\n" + + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); + } + } + } + } + + + public void connectNewServer(InteractiveContext requester, ClientServerInfo csi) { + this.clientServerInfo = csi; + this.connect(requester); + } + + /** + * Insert the method's description here. + * Creation date: (5/17/2004 6:26:14 PM) + */ + public void connect(InteractiveContext requester) { + this.asynchMessageManager.stopPolling(); + this.reconnectStat = ReconnectStatus.NOT; + this.checkClientServerSoftwareVersion(requester, this.clientServerInfo); + + // get new server connection + VCellConnection newVCellConnection = this.connectToServer(requester, true); + // update managers, status, etc. + this.changeConnection(requester, newVCellConnection); + if (this.fieldConnectionStatus.getStatus() == ConnectionStatus.CONNECTED) { + //start polling if haven't already + this.asynchMessageManager.startPolling(); + } + } + + /** + * same as {@link #connect(InteractiveContext)} but pause {@link Reconnector} + * + * @param requester + */ + public void reconnect(InteractiveContext requester) { + Reconnector rc = this.getReconnector(); + try { + rc.start(); + rc.notificationPause(true); + this.connect(requester); + if (this.fieldConnectionStatus.getStatus() == ConnectionStatus.CONNECTED) { + rc.stop(); + this.asynchMessageManager.startPolling(); + } + } finally { + rc.notificationPause(false); + } + } //public void connectAs(InteractiveContext requester, String user) { // reconnectStat = ReconnectStatus.NOT; @@ -385,393 +388,406 @@ public void reconnect(InteractiveContext requester) { //} -/** - * Insert the method's description here. - * Creation date: (5/12/2004 4:48:13 PM) - */ -private VCellConnection connectToServer(InteractiveContext requester,boolean bShowErrors) { - try { - // see static-files-config ConfigMap for definitions of dynamic properties as deployed - String url_path = PropertyLoader.getProperty(PropertyLoader.DYNAMIC_PROPERTIES_URL_PATH, "/vcell_dynamic_properties.csv"); - boolean isHTTP = PropertyLoader.getBooleanProperty(PropertyLoader.isHTTP, false); - String webapp_base_url = isHTTP ? "http://" : "https://" + getClientServerInfo().getApihost() + ":" + getClientServerInfo().getApiport(); - URL vcell_dynamic_client_properties_url = new URL(webapp_base_url + url_path); - DynamicClientProperties.updateDynamicClientProperties(vcell_dynamic_client_properties_url); - } catch (Exception e) { - lg.error(e.getMessage(), e); - } - VCellThreadChecker.checkRemoteInvocation(); - - VCellConnection newVCellConnection = null; - String badConnStr = ""; - try { - try { - String apihost = getClientServerInfo().getApihost(); - Integer apiport = getClientServerInfo().getApiport(); - Auth0ConnectionUtils auth0ConnectionUtils = vcellConnectionFactory.getAuth0ConnectionUtils(); - String username = User.isGuest(getClientServerInfo().getUsername()) ? getClientServerInfo().getUsername() : auth0ConnectionUtils.getAuth0MappedUser(); - setConnectionStatus(new ClientConnectionStatus(username, apihost, apiport, ConnectionStatus.INITIALIZING)); - newVCellConnection = vcellConnectionFactory.createVCellConnection(getClientServerInfo().getUserLoginInfo()); - requester.clearConnectWarning(); - reconnectStat = ReconnectStatus.NOT; - }catch(Exception e) { - lg.error(e.getMessage(), e); - if(bShowErrors) { - throw e; - } - } - } catch (ConnectionException cexc) { - String msg = badConnectMessage(badConnStr) + "\n" + cexc.getMessage(); - lg.error(cexc); - ErrorUtils.sendRemoteLogMessage(getClientServerInfo().getUserLoginInfo(),msg); - if (reconnectStat != ReconnectStatus.SUBSEQUENT) { - requester.showConnectWarning(msg); - } - } catch (Exception exc) { - lg.error(exc.getMessage(), exc); - String msg = "Exception: "+exc.getMessage() + "\n\n" + badConnectMessage(badConnStr); - ErrorUtils.sendRemoteLogMessage(getClientServerInfo().getUserLoginInfo(),msg); - requester.showErrorDialog(msg); - } - - return newVCellConnection; -} - -private String badConnectMessage(String badConnStr) { - String ctype = reconnectStat == ReconnectStatus.NOT ? "connect" : "reconnect"; - return VCellErrorMessages.getErrorMessage(VCellErrorMessages.BAD_CONNECTION_MESSAGE, ctype, badConnStr); -} - - -public FieldDataFileOperationResults fieldDataFileOperation(FieldDataFileOperationSpec fieldDataFielOperationSpec) throws DataAccessException{ - return getVCDataManager().fieldDataFileOperation(fieldDataFielOperationSpec); -} - -/** - * The firePropertyChange method was generated to support the propertyChange field. - */ -public void firePropertyChange(java.beans.PropertyChangeEvent evt) { - getPropertyChange().firePropertyChange(evt); -} - - -/** - * The firePropertyChange method was generated to support the propertyChange field. - */ -public void firePropertyChange(java.lang.String propertyName, int oldValue, int newValue) { - getPropertyChange().firePropertyChange(propertyName, oldValue, newValue); -} - - -/** - * The firePropertyChange method was generated to support the propertyChange field. - */ -public void firePropertyChange(java.lang.String propertyName, java.lang.Object oldValue, java.lang.Object newValue) { - getPropertyChange().firePropertyChange(propertyName, oldValue, newValue); -} - - -/** - * The firePropertyChange method was generated to support the propertyChange field. - */ -public void firePropertyChange(java.lang.String propertyName, boolean oldValue, boolean newValue) { - getPropertyChange().firePropertyChange(propertyName, oldValue, newValue); -} - - -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:21:46 PM) - * @return cbit.vcell.client.AsynchMessageManager - */ -public AsynchMessageManager getAsynchMessageManager() { - if (asynchMessageManager == null) { - asynchMessageManager = new AsynchMessageManager(this); - } - return asynchMessageManager; -} - - -/** - * Insert the method's description here. - * Creation date: (5/12/2004 4:45:19 PM) - * @return cbit.vcell.client.server.ClientServerInfo - */ -public ClientServerInfo getClientServerInfo() { - return clientServerInfo; -} - - -/** - * Gets the connectionStatus property (cbit.vcell.client.server.ConnectionStatus) value. - * @return The connectionStatus property value. - * @see #setConnectionStatus - */ -public ConnectionStatus getConnectionStatus() { - return fieldConnectionStatus; -} - -public boolean isStatusConnected(){ - return (fieldConnectionStatus.getStatus() == ConnectionStatus.CONNECTED); -} - -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - * @return UserMetaDbServer - */ -public synchronized DataSetController getDataSetController() throws DataAccessException { - VCellThreadChecker.checkRemoteInvocation(); - if (dataSetController!=null){ - return dataSetController; - }else if (getVcellConnection()==null){ - throw new RuntimeException("cannot get Simulation Data Server, no VCell Connection\ntry Server->Reconnect"); - }else{ - try { - dataSetController = getVcellConnection().getDataSetController(); - return dataSetController; - } catch (RemoteProxyException rexc) { - lg.error(rexc); - try { - // one more time before we fail../ - dataSetController = getVcellConnection().getDataSetController(); - return dataSetController; - } catch (RemoteProxyException rexc2) { - throw new DataAccessException("RemoteProxyException: "+rexc2.getMessage(), rexc2); - } - } - } -} - - -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - * @return cbit.vcell.clientdb.DocumentManager - */ -public DocumentManager getDocumentManager() { - return documentManager; -} - - -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - */ -public ExportController getExportController() { - if (exportController == null) { - exportController = new ClientExportController(this); - } - return exportController; -} - - -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - * @return cbit.vcell.clientdb.JobManager - */ -public JobManager getJobManager() { - if (jobManager == null) { - jobManager = new ClientJobManager(this); - getAsynchMessageManager().addSimulationJobStatusListener(jobManager); - jobManager.addSimStatusListener(getAsynchMessageManager()); - } - return jobManager; -} - - -/** - * Accessor for the propertyChange field. - */ -protected java.beans.PropertyChangeSupport getPropertyChange() { - if (propertyChange == null) { - propertyChange = new java.beans.PropertyChangeSupport(this); - }; - return propertyChange; -} + /** + * Insert the method's description here. + * Creation date: (5/12/2004 4:48:13 PM) + */ + private VCellConnection connectToServer(InteractiveContext requester, boolean bShowErrors) { + try { + // see static-files-config ConfigMap for definitions of dynamic properties as deployed + String url_path = PropertyLoader.getProperty(PropertyLoader.DYNAMIC_PROPERTIES_URL_PATH, "/vcell_dynamic_properties.csv"); + boolean isHTTP = PropertyLoader.getBooleanProperty(PropertyLoader.isHTTP, false); + String webapp_base_url = isHTTP ? "http://" : "https://" + this.getClientServerInfo().getApihost() + ":" + this.getClientServerInfo().getApiport(); + URL vcell_dynamic_client_properties_url = new URL(webapp_base_url + url_path); + DynamicClientProperties.updateDynamicClientProperties(vcell_dynamic_client_properties_url); + } catch (Exception e) { + lg.error(e.getMessage(), e); + } + VCellThreadChecker.checkRemoteInvocation(); + + VCellConnection newVCellConnection = null; + String badConnStr = ""; + try { + try { + String apihost = this.getClientServerInfo().getApihost(); + Integer apiport = this.getClientServerInfo().getApiport(); + Auth0ConnectionUtils auth0ConnectionUtils = this.vcellConnectionFactory.getAuth0ConnectionUtils(); + String username = User.isGuest(this.getClientServerInfo().getUsername()) ? this.getClientServerInfo().getUsername() : auth0ConnectionUtils.getAuth0MappedUser(); + this.setConnectionStatus(new ClientConnectionStatus(username, apihost, apiport, ConnectionStatus.INITIALIZING)); + newVCellConnection = this.vcellConnectionFactory.createVCellConnection(this.getClientServerInfo().getUserLoginInfo()); + requester.clearConnectWarning(); + this.reconnectStat = ReconnectStatus.NOT; + } catch (Exception e) { + lg.error(e.getMessage(), e); + if (bShowErrors) { + throw e; + } + } + } catch (ConnectionException cexc) { + String msg = this.badConnectMessage(badConnStr) + "\n" + cexc.getMessage(); + lg.error(cexc); + ErrorUtils.sendRemoteLogMessage(this.getClientServerInfo().getUserLoginInfo(), msg); + if (this.reconnectStat != ReconnectStatus.SUBSEQUENT) { + requester.showConnectWarning(msg); + } + } catch (Exception exc) { + lg.error(exc.getMessage(), exc); + String msg = "Exception: " + exc.getMessage() + "\n\n" + this.badConnectMessage(badConnStr); + ErrorUtils.sendRemoteLogMessage(this.getClientServerInfo().getUserLoginInfo(), msg); + requester.showErrorDialog(msg); + } -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - * @return UserMetaDbServer - */ -public synchronized SimulationController getSimulationController() { - VCellThreadChecker.checkRemoteInvocation(); - if (simulationController!=null){ - return simulationController; - }else if (getVcellConnection()==null){ - throw new RuntimeException("cannot get Simulation Server, no VCell Connection\ntry Server->Reconnect"); - }else{ - try { - simulationController = getVcellConnection().getSimulationController(); - return simulationController; - } catch (RemoteProxyException rexc) { - lg.error(rexc); - try { - // one more time before we fail../ - simulationController = getVcellConnection().getSimulationController(); - return simulationController; - } catch (RemoteProxyException rexc2) { - throw new RuntimeException("RemoteProxyException: "+rexc2.getMessage(), rexc2); - } - } - } -} + return newVCellConnection; + } + private String badConnectMessage(String badConnStr) { + String ctype = this.reconnectStat == ReconnectStatus.NOT ? "connect" : "reconnect"; + return VCellErrorMessages.getErrorMessage(VCellErrorMessages.BAD_CONNECTION_MESSAGE, ctype, badConnStr); + } -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - * @return cbit.vcell.server.URLFinder - */ -public synchronized User getUser() { - if (user!=null){ - return user; - }else if (getVcellConnection()==null){ - return null; - }else{ - VCellThreadChecker.checkRemoteInvocation(); - try { - user = getVcellConnection().getUserLoginInfo().getUser(); - return user; - } catch (RemoteProxyException rexc) { - throw new RuntimeException("RemoteProxyException: "+rexc.getMessage(), rexc); - } - } -} + public FieldDataFileOperationResults fieldDataFileOperation(FieldDataFileOperationSpec fieldDataFielOperationSpec) throws DataAccessException { + return this.getVCDataManager().fieldDataFileOperation(fieldDataFielOperationSpec); + } -/** - * Insert the method's description here. - * Creation date: (5/13/2004 1:54:04 PM) - * @return UserMetaDbServer - */ -public synchronized UserMetaDbServer getUserMetaDbServer() throws DataAccessException { - VCellThreadChecker.checkRemoteInvocation(); - if (userMetaDbServer != null) return userMetaDbServer; - - if (getVcellConnection()==null){ - throw new RuntimeException("cannot get Database Server, no VCell Connection\ntry Server->Reconnect"); - }else{ - try { - userMetaDbServer = getVcellConnection().getUserMetaDbServer(); - return userMetaDbServer; - } catch (RemoteProxyException rexc) { - lg.error(rexc); - try { - // one more time before we fail../ - userMetaDbServer = getVcellConnection().getUserMetaDbServer(); - return userMetaDbServer; - } catch (RemoteProxyException rexc2) { - throw new DataAccessException("RemoteProxyException: "+rexc2.getMessage(), rexc2); - } - } - } -} + /** + * The firePropertyChange method was generated to support the propertyChange field. + */ + public void firePropertyChange(java.beans.PropertyChangeEvent evt) { + this.getPropertyChange().firePropertyChange(evt); + } -/** - * Insert the method's description here. - * Creation date: (5/24/2004 8:19:36 PM) - * @return cbit.vcell.client.UserPreferences - */ -public UserPreferences getUserPreferences() { - return userPreferences; -} + /** + * The firePropertyChange method was generated to support the propertyChange field. + */ + public void firePropertyChange(java.lang.String propertyName, int oldValue, int newValue) { + this.getPropertyChange().firePropertyChange(propertyName, oldValue, newValue); + } -/** - * Insert the method's description here. - * Creation date: (6/9/2004 3:21:46 PM) - * @return cbit.vcell.client.VCDataManager - */ -public VCDataManager getVCDataManager() { - if (vcDataManager == null) { - vcDataManager = new VCDataManager(this); - } - return vcDataManager; -} + /** + * The firePropertyChange method was generated to support the propertyChange field. + */ + public void firePropertyChange(java.lang.String propertyName, java.lang.Object oldValue, java.lang.Object newValue) { + this.getPropertyChange().firePropertyChange(propertyName, oldValue, newValue); + } -/** - * Insert the method's description here. - * Creation date: (5/13/2004 12:26:57 PM) - * @return VCellConnection - */ -private VCellConnection getVcellConnection() { - return vcellConnection; -} + /** + * The firePropertyChange method was generated to support the propertyChange field. + */ + public void firePropertyChange(java.lang.String propertyName, boolean oldValue, boolean newValue) { + this.getPropertyChange().firePropertyChange(propertyName, oldValue, newValue); + } -/** - * The hasListeners method was generated to support the propertyChange field. - */ -public synchronized boolean hasListeners(java.lang.String propertyName) { - return getPropertyChange().hasListeners(propertyName); -} -/** - * @return lazily created {@link Reconnector } - */ -private Reconnector getReconnector( ) { - if (reconnector == null) { - reconnector = new Reconnector(this); - } - return reconnector; -} + /** + * Insert the method's description here. + * Creation date: (6/9/2004 3:21:46 PM) + * + * @return cbit.vcell.client.AsynchMessageManager + */ + public AsynchMessageManager getAsynchMessageManager() { + if (this.asynchMessageManager == null) { + this.asynchMessageManager = new AsynchMessageManager(this); + } + return this.asynchMessageManager; + } + + + /** + * Insert the method's description here. + * Creation date: (5/12/2004 4:45:19 PM) + * + * @return cbit.vcell.client.server.ClientServerInfo + */ + public ClientServerInfo getClientServerInfo() { + return this.clientServerInfo; + } + + + /** + * Gets the connectionStatus property (cbit.vcell.client.server.ConnectionStatus) value. + * + * @return The connectionStatus property value. + * @see #setConnectionStatus + */ + public ConnectionStatus getConnectionStatus() { + return this.fieldConnectionStatus; + } + + public boolean isStatusConnected() { + return (this.fieldConnectionStatus.getStatus() == ConnectionStatus.CONNECTED); + } + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + * + * @return UserMetaDbServer + */ + public synchronized DataSetController getDataSetController() throws DataAccessException { + VCellThreadChecker.checkRemoteInvocation(); + if (this.dataSetController != null) { + return this.dataSetController; + } else if (this.getVcellConnection() == null) { + throw new RuntimeException("cannot get Simulation Data Server, no VCell Connection\ntry Server->Reconnect"); + } else { + try { + this.dataSetController = this.getVcellConnection().getDataSetController(); + return this.dataSetController; + } catch (RemoteProxyException rexc) { + lg.error(rexc); + try { + // one more time before we fail../ + this.dataSetController = this.getVcellConnection().getDataSetController(); + return this.dataSetController; + } catch (RemoteProxyException rexc2) { + throw new DataAccessException("RemoteProxyException: " + rexc2.getMessage(), rexc2); + } + } + } + } + + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + * + * @return cbit.vcell.clientdb.DocumentManager + */ + public DocumentManager getDocumentManager() { + return this.documentManager; + } + + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + */ + public ExportController getExportController() { + if (this.exportController == null) { + this.exportController = new ClientExportController(this); + } + return this.exportController; + } + + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + * + * @return cbit.vcell.clientdb.JobManager + */ + public JobManager getJobManager() { + if (this.jobManager == null) { + this.jobManager = new ClientJobManager(this); + this.getAsynchMessageManager().addSimulationJobStatusListener(this.jobManager); + this.jobManager.addSimStatusListener(this.getAsynchMessageManager()); + } + return this.jobManager; + } -/** - * commence automatic reconnect attempts - */ -void attemptReconnect( ) { - getReconnector( ).start(); -} -/** - * attempt reconnect now - */ -void reconnect() { - Reconnector rc = getReconnector(); - rc.notificationPause(true); - try { - switch (reconnectStat) { - case NOT: - reconnectStat = ReconnectStatus.FIRST; - break; - case FIRST: - reconnectStat = ReconnectStatus.SUBSEQUENT; - break; - default: - } - InteractiveContext requester = defaultInteractiveContextProvider.getInteractiveContext(); - VCellConnection connection = connectToServer(requester,false); - if (connection != null) { //success - changeConnection(requester,connection); - rc.stop(); - asynchMessageManager.startPolling(); - return; - } - setConnectionStatus(new ClientConnectionStatus(getClientServerInfo().getUsername(), getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); - } finally { - rc.notificationPause(false); - } -} + /** + * Accessor for the propertyChange field. + */ + protected java.beans.PropertyChangeSupport getPropertyChange() { + if (this.propertyChange == null) { + this.propertyChange = new java.beans.PropertyChangeSupport(this); + } + return this.propertyChange; + } + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + * + * @return UserMetaDbServer + */ + public synchronized SimulationController getSimulationController() { + VCellThreadChecker.checkRemoteInvocation(); + if (this.simulationController != null) { + return this.simulationController; + } else if (this.getVcellConnection() == null) { + throw new RuntimeException("cannot get Simulation Server, no VCell Connection\ntry Server->Reconnect"); + } else { + try { + this.simulationController = this.getVcellConnection().getSimulationController(); + return this.simulationController; + } catch (RemoteProxyException rexc) { + lg.error(rexc); + try { + // one more time before we fail../ + this.simulationController = this.getVcellConnection().getSimulationController(); + return this.simulationController; + } catch (RemoteProxyException rexc2) { + throw new RuntimeException("RemoteProxyException: " + rexc2.getMessage(), rexc2); + } + } + } + } + + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + * + * @return cbit.vcell.server.URLFinder + */ + public synchronized User getUser() { + if (this.user != null) { + return this.user; + } else if (this.getVcellConnection() == null) { + return null; + } else { + VCellThreadChecker.checkRemoteInvocation(); + try { + this.user = this.getVcellConnection().getUserLoginInfo().getUser(); + return this.user; + } catch (RemoteProxyException rexc) { + throw new RuntimeException("RemoteProxyException: " + rexc.getMessage(), rexc); + } + } + } + + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 1:54:04 PM) + * + * @return UserMetaDbServer + */ + public synchronized UserMetaDbServer getUserMetaDbServer() throws DataAccessException { + VCellThreadChecker.checkRemoteInvocation(); + if (this.userMetaDbServer != null) return this.userMetaDbServer; + + if (this.getVcellConnection() == null) { + throw new RuntimeException("cannot get Database Server, no VCell Connection\ntry Server->Reconnect"); + } else { + try { + this.userMetaDbServer = this.getVcellConnection().getUserMetaDbServer(); + return this.userMetaDbServer; + } catch (RemoteProxyException rexc) { + lg.error(rexc); + try { + // one more time before we fail../ + this.userMetaDbServer = this.getVcellConnection().getUserMetaDbServer(); + return this.userMetaDbServer; + } catch (RemoteProxyException rexc2) { + throw new DataAccessException("RemoteProxyException: " + rexc2.getMessage(), rexc2); + } + } + } + } + + + /** + * Insert the method's description here. + * Creation date: (5/24/2004 8:19:36 PM) + * + * @return cbit.vcell.client.UserPreferences + */ + public UserPreferences getUserPreferences() { + return this.userPreferences; + } + + + /** + * Insert the method's description here. + * Creation date: (6/9/2004 3:21:46 PM) + * + * @return cbit.vcell.client.VCDataManager + */ + public VCDataManager getVCDataManager() { + if (this.vcDataManager == null) { + this.vcDataManager = new VCDataManager(this); + } + return this.vcDataManager; + } + + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 12:26:57 PM) + * + * @return VCellConnection + */ + private VCellConnection getVcellConnection() { + return this.vcellConnection; + } + + + /** + * The hasListeners method was generated to support the propertyChange field. + */ + public synchronized boolean hasListeners(java.lang.String propertyName) { + return this.getPropertyChange().hasListeners(propertyName); + } + + /** + * @return lazily created {@link Reconnector } + */ + private Reconnector getReconnector() { + if (this.reconnector == null) { + this.reconnector = new Reconnector(this); + } + return this.reconnector; + } + + /** + * commence automatic reconnect attempts + */ + void attemptReconnect() { + this.getReconnector().start(); + } + + /** + * attempt reconnect now + */ + void reconnect() { + Reconnector rc = this.getReconnector(); + rc.notificationPause(true); + try { + switch (this.reconnectStat) { + case NOT: + this.reconnectStat = ReconnectStatus.FIRST; + break; + case FIRST: + this.reconnectStat = ReconnectStatus.SUBSEQUENT; + break; + default: + } + InteractiveContext requester = this.defaultInteractiveContextProvider.getInteractiveContext(); + VCellConnection connection = this.connectToServer(requester, false); + if (connection != null) { //success + this.changeConnection(requester, connection); + rc.stop(); + this.asynchMessageManager.startPolling(); + return; + } + this.setConnectionStatus(new ClientConnectionStatus(this.getClientServerInfo().getUsername(), this.getClientServerInfo().getApihost(), this.getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); + } finally { + rc.notificationPause(false); + } + } -/** - * The removePropertyChangeListener method was generated to support the propertyChange field. - */ -public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener listener) { - getPropertyChange().removePropertyChangeListener(listener); -} + /** + * The removePropertyChangeListener method was generated to support the propertyChange field. + */ + public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener listener) { + this.getPropertyChange().removePropertyChangeListener(listener); + } -/** - * The removePropertyChangeListener method was generated to support the propertyChange field. - */ -public synchronized void removePropertyChangeListener(java.lang.String propertyName, java.beans.PropertyChangeListener listener) { - getPropertyChange().removePropertyChangeListener(propertyName, listener); -} + /** + * The removePropertyChangeListener method was generated to support the propertyChange field. + */ + public synchronized void removePropertyChangeListener(java.lang.String propertyName, java.beans.PropertyChangeListener listener) { + this.getPropertyChange().removePropertyChangeListener(propertyName, listener); + } /** @@ -784,72 +800,76 @@ public synchronized void removePropertyChangeListener(java.lang.String propertyN //} -/** - * Sets the connectionStatus property (cbit.vcell.client.server.ConnectionStatus) value. - * @param connectionStatus The new value for the property. - * @see #getConnectionStatus - */ -private void setConnectionStatus(ClientConnectionStatus connectionStatus) { - ConnectionStatus oldValue = fieldConnectionStatus; - fieldConnectionStatus = connectionStatus; - firePropertyChange(PROPERTY_NAME_CONNECTION_STATUS, oldValue, connectionStatus); -} - -/** - * Insert the method's description here. - * Creation date: (5/13/2004 12:26:57 PM) - * @param newVcellConnection VCellConnection - * @throws DataAccessException - */ -private void setVcellConnection(VCellConnection newVcellConnection) { - vcellConnection = newVcellConnection; - user = null; - simulationController = null; - dataSetController = null; - userMetaDbServer = null; - - if (vcellConnection == null) { - return; - } - try { - getUser(); - getSimulationController(); - getDataSetController(); - getUserMetaDbServer(); - } catch (DataAccessException ex) { - throw new RuntimeException("DataAccessException: "+ex.getMessage(), ex); - } -} - - -/** - * calls {@link #sendErrorReport(Throwable, cbit.vcell.server.VCellConnection.ExtraContext)} with null ExtraContext - * @param exception - */ -public void sendErrorReport(Throwable exception ) { - sendErrorReport(exception, null); -} -/** - * @param exception - * @param extraContext may be null - */ -public void sendErrorReport(Throwable exception, VCellConnection.ExtraContext extraContext) { - try { - getVcellConnection().sendErrorReport(exception, extraContext); - } catch (Exception ex) { - lg.error(ex.getMessage(), ex); - } -} - -/** - * start {@link Reconnector}, set status to {@link ConnectionStatus#DISCONNECTED} - */ -void setDisconnected() { - getReconnector().start(); - setConnectionStatus(new ClientConnectionStatus(getClientServerInfo().getUsername(), getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); -} - -public RegistrationService getRegistrationProvider() { - return new VCellConnectionRegistrationProvider(this.vcellConnection); -} + /** + * Sets the connectionStatus property (cbit.vcell.client.server.ConnectionStatus) value. + * + * @param connectionStatus The new value for the property. + * @see #getConnectionStatus + */ + private void setConnectionStatus(ClientConnectionStatus connectionStatus) { + ConnectionStatus oldValue = this.fieldConnectionStatus; + this.fieldConnectionStatus = connectionStatus; + this.firePropertyChange(PROPERTY_NAME_CONNECTION_STATUS, oldValue, connectionStatus); + } + + /** + * Insert the method's description here. + * Creation date: (5/13/2004 12:26:57 PM) + * + * @param newVcellConnection VCellConnection + * @throws DataAccessException + */ + private void setVcellConnection(VCellConnection newVcellConnection) { + this.vcellConnection = newVcellConnection; + this.user = null; + this.simulationController = null; + this.dataSetController = null; + this.userMetaDbServer = null; + + if (this.vcellConnection == null) { + return; + } + try { + this.getUser(); + this.getSimulationController(); + this.getDataSetController(); + this.getUserMetaDbServer(); + } catch (DataAccessException ex) { + throw new RuntimeException("DataAccessException: " + ex.getMessage(), ex); + } + } + + + /** + * calls {@link #sendErrorReport(Throwable, cbit.vcell.server.VCellConnection.ExtraContext)} with null ExtraContext + * + * @param exception + */ + public void sendErrorReport(Throwable exception) { + this.sendErrorReport(exception, null); + } + + /** + * @param exception + * @param extraContext may be null + */ + public void sendErrorReport(Throwable exception, VCellConnection.ExtraContext extraContext) { + try { + this.getVcellConnection().sendErrorReport(exception, extraContext); + } catch (Exception ex) { + lg.error(ex.getMessage(), ex); + } + } + + /** + * start {@link Reconnector}, set status to {@link ConnectionStatus#DISCONNECTED} + */ + void setDisconnected() { + this.getReconnector().start(); + this.setConnectionStatus(new ClientConnectionStatus(this.getClientServerInfo().getUsername(), this.getClientServerInfo().getApihost(), this.getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); + } + + public RegistrationService getRegistrationProvider() { + return new VCellConnectionRegistrationProvider(this.vcellConnection); + } }