Issue #1442 Changes to update display when Simulated Time is changed. Corrections to pqact.conf.template.
Changes based on code review and added listener to GridManager and unit test. Change-Id: Ida593a7e3cc7d4fd9bd6f44a4455145114484650 Former-commit-id:1cd076671c
[formerly 7f70c2f65453db6bf3097ae8157511c38a36b136] Former-commit-id:1e492b81ff
This commit is contained in:
parent
e8d8dcc795
commit
f10521f861
13 changed files with 442 additions and 117 deletions
|
@ -45,6 +45,7 @@ import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 3, 2007 chammack Initial Creation.
|
||||
* Jan 14, 2013 1442 rferrel Added method searchTreeUsingContraints.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -279,7 +280,41 @@ public class DecisionTree<T> {
|
|||
insertCriteria(searchCriteria, item, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the tree by calling RequestConstraint.evaluate with the map values
|
||||
* for each level of the tree.
|
||||
*
|
||||
* @param searchCriteria
|
||||
* @return
|
||||
*/
|
||||
public List<T> searchTree(Map<String, Object> searchCriteria) {
|
||||
return searchTree(searchCriteria, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the tree to find entries that were put into the tree using the
|
||||
* exact same criteria as searchCriteria.
|
||||
*
|
||||
* @param searchCriteria
|
||||
* @return
|
||||
*/
|
||||
public List<T> searchTreeUsingContraints(
|
||||
Map<String, RequestConstraint> searchCriteria) {
|
||||
return searchTree(searchCriteria, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal search method
|
||||
*
|
||||
* @param searchCriteria
|
||||
* @param evaluateConstraints
|
||||
* true if the map values should be passed to
|
||||
* RequestConstraint.evaluate, false if they chould be passed to
|
||||
* RequestConstraint.equals
|
||||
* @return
|
||||
*/
|
||||
private List<T> searchTree(Map<String, ?> searchCriteria,
|
||||
boolean evaluateConstraints) {
|
||||
synchronized (this) {
|
||||
List<T> lst = new ArrayList<T>();
|
||||
if (head == null) {
|
||||
|
@ -288,13 +323,13 @@ public class DecisionTree<T> {
|
|||
|
||||
Node curNode = head;
|
||||
|
||||
searchTree(curNode, searchCriteria, lst, 0);
|
||||
searchTree(curNode, searchCriteria, lst, 0, evaluateConstraints);
|
||||
return lst;
|
||||
}
|
||||
}
|
||||
|
||||
private void searchTree(Node curNode, Map<String, Object> searchCriteria,
|
||||
List<T> resultList, int lvl) {
|
||||
private void searchTree(Node curNode, Map<String, ?> searchCriteria,
|
||||
List<T> resultList, int lvl, boolean evaluatedConstraint) {
|
||||
|
||||
if (curNode == null) {
|
||||
return;
|
||||
|
@ -312,20 +347,39 @@ public class DecisionTree<T> {
|
|||
Object parsedValue = searchCriteria.get(curNode.decisionAttribute);
|
||||
|
||||
boolean foundSomething = false;
|
||||
// Evaluate through the values: First search for an exact match
|
||||
// of non-null values
|
||||
for (Node n : curNode.nodeChildren) {
|
||||
RequestConstraint c = n.decision;
|
||||
if (c == null
|
||||
|| (c == RequestConstraint.WILDCARD || parsedValue == null || c
|
||||
.evaluate(parsedValue))) {
|
||||
// for (int k = 0; k < lvl; k++) {
|
||||
// System.out.print(" ");
|
||||
// }
|
||||
foundSomething = true;
|
||||
// System.out.println("visit: " + curNode.decisionAttribute
|
||||
// + ":: " + c);
|
||||
searchTree(n, searchCriteria, resultList, lvl + 1);
|
||||
if (evaluatedConstraint) {
|
||||
// Evaluate through the values: First search for an exact match
|
||||
// of non-null values
|
||||
for (Node n : curNode.nodeChildren) {
|
||||
RequestConstraint c = n.decision;
|
||||
if (c == null
|
||||
|| (c == RequestConstraint.WILDCARD
|
||||
|| parsedValue == null || c
|
||||
.evaluate(parsedValue))) {
|
||||
// for (int k = 0; k < lvl; k++) {
|
||||
// System.out.print(" ");
|
||||
// }
|
||||
foundSomething = true;
|
||||
// System.out.println("visit: " + curNode.decisionAttribute
|
||||
// + ":: " + c);
|
||||
searchTree(n, searchCriteria, resultList, lvl + 1,
|
||||
evaluatedConstraint);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Evaluate using existing constraints.
|
||||
for (Node n : curNode.nodeChildren) {
|
||||
RequestConstraint c = n.decision;
|
||||
if (parsedValue.equals(c)) {
|
||||
// for (int k = 0; k < lvl; k++) {
|
||||
// System.out.print(" ");
|
||||
// }
|
||||
foundSomething = true;
|
||||
// System.out.println("visit: " + curNode.decisionAttribute
|
||||
// + ":: " + c);
|
||||
searchTree(n, searchCriteria, resultList, lvl + 1,
|
||||
evaluatedConstraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ import com.raytheon.uf.viz.core.rsc.URICatalog.IURIRefreshCallback;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 12, 2007 chammack Initial Creation.
|
||||
* Jan 14, 2013 1442 rferrel Added query method.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -70,6 +71,8 @@ public class URICatalog extends DecisionTree<List<IURIRefreshCallback>> {
|
|||
|
||||
protected Map<Map<String, RequestConstraint>, List<IURIRefreshCallback>> queuedRCMap = new HashMap<Map<String, RequestConstraint>, List<IURIRefreshCallback>>();
|
||||
|
||||
private Map<Map<String, RequestConstraint>, List<IURIRefreshCallback>> queryRCMap = new HashMap<Map<String, RequestConstraint>, List<IURIRefreshCallback>>();
|
||||
|
||||
/**
|
||||
* Singleton accessor
|
||||
*
|
||||
|
@ -193,14 +196,29 @@ public class URICatalog extends DecisionTree<List<IURIRefreshCallback>> {
|
|||
do {
|
||||
workingTime = time;
|
||||
Map<Map<String, RequestConstraint>, List<IURIRefreshCallback>> runRCList = null;
|
||||
Map<Map<String, RequestConstraint>, List<IURIRefreshCallback>> runQueryList = null;
|
||||
synchronized (URICatalog.this) {
|
||||
runRCList = queuedRCMap;
|
||||
queuedRCMap = new HashMap<Map<String, RequestConstraint>, List<IURIRefreshCallback>>();
|
||||
}
|
||||
if (queuedRCMap.size() > 0) {
|
||||
runRCList = queuedRCMap;
|
||||
queuedRCMap = new HashMap<Map<String, RequestConstraint>, List<IURIRefreshCallback>>();
|
||||
}
|
||||
|
||||
catalogAndQueryDataURIsInternal(runRCList, monitor);
|
||||
if (queryRCMap.size() > 0) {
|
||||
runQueryList = queryRCMap;
|
||||
queryRCMap = new HashMap<Map<String, RequestConstraint>, List<IURIRefreshCallback>>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (runRCList != null) {
|
||||
catalogAndQueryDataURIsInternal(runRCList, monitor);
|
||||
}
|
||||
|
||||
if (runQueryList != null) {
|
||||
doQuery(runQueryList, monitor);
|
||||
}
|
||||
} while (!monitor.isCanceled() && workingTime != time
|
||||
&& queuedRCMap.size() > 0);
|
||||
&& (queuedRCMap.size() > 0 || queryRCMap.size() > 0));
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
}
|
||||
|
@ -245,40 +263,24 @@ public class URICatalog extends DecisionTree<List<IURIRefreshCallback>> {
|
|||
try {
|
||||
for (Map.Entry<Map<String, RequestConstraint>, List<IURIRefreshCallback>> entry : rcMap
|
||||
.entrySet()) {
|
||||
Map<String, RequestConstraint> map = entry.getKey();
|
||||
List<IURIRefreshCallback> runnable = entry.getValue();
|
||||
if (monitor.isCanceled()) {
|
||||
// If we are cancelled add our runnables back into the queue
|
||||
// instead of requesting times
|
||||
synchronized (this) {
|
||||
List<IURIRefreshCallback> runnables = queuedRCMap
|
||||
.get(entry.getKey());
|
||||
.get(map);
|
||||
if (runnables == null) {
|
||||
queuedRCMap.put(entry.getKey(), entry.getValue());
|
||||
queuedRCMap.put(map, runnable);
|
||||
} else {
|
||||
runnables.addAll(entry.getValue());
|
||||
runnables.addAll(runnable);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Map<String, RequestConstraint> map = entry.getKey();
|
||||
DataTime[] dt = DataCubeContainer.performTimeQuery(map, true);
|
||||
DataTime newDataTime = null;
|
||||
if (dt != null && dt.length > 0) {
|
||||
newDataTime = dt[dt.length - 1];
|
||||
}
|
||||
doCallbacks(map, runnable);
|
||||
|
||||
List<IURIRefreshCallback> runnable = entry.getValue();
|
||||
|
||||
final DataTime dataTime = newDataTime;
|
||||
if (runnable != null) {
|
||||
|
||||
Iterator<IURIRefreshCallback> iterator = runnable
|
||||
.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
final IURIRefreshCallback r = iterator.next();
|
||||
r.updateTime(dataTime);
|
||||
}
|
||||
}
|
||||
for (Map<String, RequestConstraint> updateMap : DataCubeContainer
|
||||
.getBaseUpdateConstraints(map)) {
|
||||
insert(updateMap, rcMap.get(map));
|
||||
|
@ -297,6 +299,76 @@ public class URICatalog extends DecisionTree<List<IURIRefreshCallback>> {
|
|||
|
||||
}
|
||||
|
||||
private void doCallbacks(Map<String, RequestConstraint> map,
|
||||
List<IURIRefreshCallback> runnable) throws VizException {
|
||||
DataTime[] dt = DataCubeContainer.performTimeQuery(map, true);
|
||||
DataTime newDataTime = null;
|
||||
if (dt != null && dt.length > 0) {
|
||||
newDataTime = dt[dt.length - 1];
|
||||
}
|
||||
|
||||
final DataTime dataTime = newDataTime;
|
||||
if (runnable != null) {
|
||||
|
||||
Iterator<IURIRefreshCallback> iterator = runnable.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
final IURIRefreshCallback r = iterator.next();
|
||||
r.updateTime(dataTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform query using the existing constraints in map.
|
||||
*
|
||||
* @param map
|
||||
*/
|
||||
public void query(Map<String, RequestConstraint> map) {
|
||||
synchronized (this) {
|
||||
List<List<IURIRefreshCallback>> runableList = searchTreeUsingContraints(map);
|
||||
List<IURIRefreshCallback> runnables = queryRCMap.get(map);
|
||||
if (runnables == null) {
|
||||
runnables = new ArrayList<URICatalog.IURIRefreshCallback>();
|
||||
queryRCMap.put(map, runnables);
|
||||
}
|
||||
|
||||
for (List<IURIRefreshCallback> runnable : runableList) {
|
||||
runnables.addAll(runnable);
|
||||
}
|
||||
rebuildSchedulerJob.schedule();
|
||||
}
|
||||
}
|
||||
|
||||
private void doQuery(
|
||||
Map<Map<String, RequestConstraint>, List<IURIRefreshCallback>> queryMap,
|
||||
IProgressMonitor monitor) {
|
||||
try {
|
||||
for (Map.Entry<Map<String, RequestConstraint>, List<IURIRefreshCallback>> entry : queryMap
|
||||
.entrySet()) {
|
||||
Map<String, RequestConstraint> map = entry.getKey();
|
||||
List<IURIRefreshCallback> runnable = entry.getValue();
|
||||
if (monitor.isCanceled()) {
|
||||
// If we are cancelled add our runnables back into the queue
|
||||
// instead of requesting times
|
||||
synchronized (this) {
|
||||
List<IURIRefreshCallback> runnables = queryRCMap
|
||||
.get(map);
|
||||
if (runnables == null) {
|
||||
queryRCMap.put(map, runnable);
|
||||
} else {
|
||||
runnables.addAll(runnable);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
doCallbacks(map, runnable);
|
||||
}
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void insert(Map<String, RequestConstraint> map,
|
||||
List<IURIRefreshCallback> runnables) throws VizException {
|
||||
insertCriteria(map, runnables, false);
|
||||
|
@ -306,7 +378,5 @@ public class URICatalog extends DecisionTree<List<IURIRefreshCallback>> {
|
|||
|
||||
/** check and update most recent time */
|
||||
public abstract void updateTime(DataTime time);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ import com.raytheon.uf.common.status.UFStatus;
|
|||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.BinOffset;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.ISimulatedTimeChangeListener;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.viz.core.VariableSubstitutionUtil;
|
||||
import com.raytheon.uf.viz.core.VizApp;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
@ -84,6 +86,7 @@ import com.raytheon.viz.ui.editor.AbstractEditor;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 12, 2009 chammack Initial creation
|
||||
* Jan 14, 2013 1442 rferrel Add Simulated Time Change Listener.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -127,6 +130,12 @@ public class BundleContributionItem extends ContributionItem {
|
|||
|
||||
protected boolean performQuery = true;
|
||||
|
||||
/**
|
||||
* A flag to indicate simulated time has changed and item's values needs to
|
||||
* be refreshed the next time it is displayed.
|
||||
*/
|
||||
private boolean timeChangeUpdate = false;
|
||||
|
||||
public BundleContributionItem(CommonBundleMenuContribution contribution,
|
||||
VariableSubstitution[] includeSubstitutions) throws VizException {
|
||||
super(VariableSubstitutionUtil.processVariables(contribution.id,
|
||||
|
@ -165,6 +174,25 @@ public class BundleContributionItem extends ContributionItem {
|
|||
this.substitutions);
|
||||
}
|
||||
}
|
||||
|
||||
// The bundle persists for the life of CAVE; no need to remove the
|
||||
// listener.
|
||||
ISimulatedTimeChangeListener stcl = new ISimulatedTimeChangeListener() {
|
||||
|
||||
@Override
|
||||
public void timechanged() {
|
||||
// Updating the value here will generate a flood of requests for
|
||||
// all bundles.
|
||||
//
|
||||
// This will force the update of the item's value the next time
|
||||
// it is displayed.
|
||||
//
|
||||
// Any open widget using the bundle will need to handle the
|
||||
// update.
|
||||
timeChangeUpdate = true;
|
||||
}
|
||||
};
|
||||
SimulatedTime.getSystemTime().addSimulatedTimeChangeListener(stcl);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -212,6 +240,22 @@ public class BundleContributionItem extends ContributionItem {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows a widget such as an open dialog to force the bundle to query
|
||||
* for new values based on Simulated Time. Allows a widget to refresh its
|
||||
* display after a user has modified Simulated Time.
|
||||
*/
|
||||
public void refreshText() {
|
||||
lastUsedTime = null;
|
||||
if (pdoMapList != null && pdoMapList.size() > 0) {
|
||||
URICatalog cat = URICatalog.getInstance();
|
||||
for (BundleDataItem d : pdoMapList) {
|
||||
cat.query(d.metadata);
|
||||
}
|
||||
}
|
||||
timeChangeUpdate = false;
|
||||
}
|
||||
|
||||
protected synchronized void updateMenuText() {
|
||||
if (widget == null)
|
||||
return;
|
||||
|
@ -325,6 +369,11 @@ public class BundleContributionItem extends ContributionItem {
|
|||
*
|
||||
*/
|
||||
protected void onShow() {
|
||||
if (timeChangeUpdate) {
|
||||
refreshText();
|
||||
return;
|
||||
}
|
||||
|
||||
if (performQuery) {
|
||||
if (!shownBefore) {
|
||||
shownBefore = true;
|
||||
|
@ -438,7 +487,6 @@ public class BundleContributionItem extends ContributionItem {
|
|||
URICatalog.getInstance().catalogAndQueryDataURI(d.metadata,
|
||||
new BundleRefreshCallback(d.offset));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,10 @@ import org.eclipse.swt.widgets.Shell;
|
|||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.services.IServiceLocator;
|
||||
|
||||
import com.raytheon.uf.common.time.ISimulatedTimeChangeListener;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.viz.core.ContextManager;
|
||||
import com.raytheon.uf.viz.ui.menus.widgets.BundleContributionItem;
|
||||
import com.raytheon.viz.ui.VizWorkbenchManager;
|
||||
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
||||
|
||||
|
@ -49,6 +52,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Sep 14, 2011 mnash Initial creation
|
||||
* Jan 09, 2013 1442 rferrel Add Simulated Time Change Listener.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -64,6 +68,12 @@ public class TearOffMenuDialog extends CaveSWTDialog {
|
|||
|
||||
private Composite fullComp;
|
||||
|
||||
/**
|
||||
* Listener to force the dialog's items' display to be updated when user
|
||||
* changes Simulated time.
|
||||
*/
|
||||
ISimulatedTimeChangeListener stcl;
|
||||
|
||||
/**
|
||||
* @param parentShell
|
||||
*/
|
||||
|
@ -170,14 +180,36 @@ public class TearOffMenuDialog extends CaveSWTDialog {
|
|||
addListener(SWT.Close, deactivate);
|
||||
|
||||
activate.handleEvent(new Event());
|
||||
|
||||
stcl = new ISimulatedTimeChangeListener() {
|
||||
|
||||
@Override
|
||||
public void timechanged() {
|
||||
updateItems();
|
||||
}
|
||||
};
|
||||
SimulatedTime.getSystemTime().addSimulatedTimeChangeListener(stcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disposed() {
|
||||
SimulatedTime.getSystemTime().removeSimulatedTimeChangeListener(stcl);
|
||||
for (Control control : fullComp.getChildren()) {
|
||||
control.dispose();
|
||||
}
|
||||
super.disposed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force update of item's display.
|
||||
*/
|
||||
private void updateItems() {
|
||||
// items[0] is the tear off object and is not in the dialog's display.
|
||||
for (int index = 1; index < items.length; ++index) {
|
||||
MenuItem item = items[index];
|
||||
if (item.getData() instanceof BundleContributionItem) {
|
||||
((BundleContributionItem) item.getData()).refreshText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ import com.raytheon.edex.msg.PracticeDataURINotificationMessage;
|
|||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.viz.core.RecordFactory;
|
||||
import com.raytheon.uf.viz.core.alerts.AlertMessage;
|
||||
import com.raytheon.uf.viz.core.exception.NoPluginException;
|
||||
|
@ -65,6 +67,7 @@ import com.raytheon.viz.core.mode.CAVEMode;
|
|||
* 02/28/08 966 chammack Refactored to support generalized listeners
|
||||
* 05/08/08 1127 randerso Changed to implement INotificationObserver
|
||||
* 10/06/08 1433 chammack Updated to use VizStatus
|
||||
* 01/14/2013 1442 rferrel Filter out simulated time "future" alerts.
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
|
@ -233,6 +236,27 @@ public class ProductAlertObserver implements INotificationObserver {
|
|||
// collection for future messages
|
||||
Collection<AlertMessage> messagesToProc = messages;
|
||||
messages = new ConcurrentLinkedQueue<AlertMessage>();
|
||||
SimulatedTime time = SimulatedTime.getSystemTime();
|
||||
if (!time.isRealTime()) {
|
||||
// Filter out any "future" alerts.
|
||||
long simTime = time.getTime().getTime();
|
||||
Iterator<AlertMessage> iter = messagesToProc.iterator();
|
||||
while (iter.hasNext()) {
|
||||
AlertMessage message = iter.next();
|
||||
Map<String, Object> attribs = new HashMap<String, Object>(
|
||||
message.decodedAlert);
|
||||
DataTime messageTime = (DataTime) attribs
|
||||
.get("dataTime");
|
||||
if (messageTime != null
|
||||
&& (simTime < messageTime.getRefTime()
|
||||
.getTime())) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
if (messagesToProc.isEmpty()) {
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
observer.alertArrived(messagesToProc);
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.eclipse.ui.PlatformUI;
|
|||
import org.eclipse.ui.commands.ICommandService;
|
||||
import org.eclipse.ui.progress.UIJob;
|
||||
|
||||
import com.raytheon.uf.common.time.ISimulatedTimeChangeListener;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.viz.core.VizApp;
|
||||
|
@ -68,6 +69,7 @@ import com.raytheon.viz.gfe.temporaleditor.TemporalEditor;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 7, 2009 randerso Redesigned
|
||||
* May 18, 2009 2159 rjpeter Added temporal editor.
|
||||
* Jan 14, 2013 1442 rferrel Add SimulatedTimeChangeListener.
|
||||
* </pre>
|
||||
*
|
||||
* @author randerso
|
||||
|
@ -151,11 +153,13 @@ public class GridManager implements IGridManager,
|
|||
/**
|
||||
* Job to update the time display
|
||||
*/
|
||||
private static class UpdateJob extends UIJob {
|
||||
private static class UpdateJob extends UIJob implements
|
||||
ISimulatedTimeChangeListener {
|
||||
|
||||
public UpdateJob() {
|
||||
super("GridManagerUpdate");
|
||||
this.setSystem(true);
|
||||
SimulatedTime.getSystemTime().addSimulatedTimeChangeListener(this);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -178,6 +182,18 @@ public class GridManager implements IGridManager,
|
|||
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.time.ISimulatedTimeChangeListener#timechanged
|
||||
* ()
|
||||
*/
|
||||
@Override
|
||||
public void timechanged() {
|
||||
wakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -86,6 +86,7 @@ import com.raytheon.viz.core.units.UnitRegistrar;
|
|||
* Oct 02, 2012 #1236 dgilling Allow SimulatedTime to be set from
|
||||
* the command line even if practice
|
||||
* mode is off.
|
||||
* Jan 09, 2013 #1442 rferrel Changes to notify SimultedTime listeners.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -319,11 +320,13 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
}
|
||||
|
||||
SimulatedTime systemTime = SimulatedTime.getSystemTime();
|
||||
systemTime.notifyListeners(false);
|
||||
systemTime.setRealTime();
|
||||
systemTime.setFrozen(isFrozen);
|
||||
if (timeValue != 0) {
|
||||
systemTime.setTime(new Date(timeValue));
|
||||
}
|
||||
systemTime.notifyListeners(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,7 @@ import com.raytheon.viz.ui.VizWorkbenchManager;
|
|||
* May 21, 2008 1122 ebabin Updated to use new StatusBarDisplay.
|
||||
* 09JUL2008 1234 ebabin Updates for color, and display issues.
|
||||
* Oct 17, 2012 1229 rferrel Made dialog non-blocking.
|
||||
* Jan 09, 2013 1442 rferrel Changes to notify Simulated Time listeners
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -338,8 +339,9 @@ public class SetTimeDialog extends CaveSWTDialog {
|
|||
}
|
||||
|
||||
private void setVizTime() {
|
||||
SimulatedTime systemTime = SimulatedTime.getSystemTime();
|
||||
if (useCurrentTimeRdo.getSelection()) {
|
||||
SimulatedTime.getSystemTime().setRealTime();
|
||||
systemTime.setRealTime();
|
||||
} else if (setTimeRdo.getSelection()) {
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
cal.clear();
|
||||
|
@ -348,9 +350,10 @@ public class SetTimeDialog extends CaveSWTDialog {
|
|||
this.daySpnr.getSelection(), this.hourSpnr.getSelection(),
|
||||
this.minuteSpnr.getSelection(),
|
||||
this.secondSpnr.getSelection());
|
||||
SimulatedTime.getSystemTime().setFrozen(
|
||||
freezeTimeChk.getSelection());
|
||||
SimulatedTime.getSystemTime().setTime(cal.getTime());
|
||||
systemTime.notifyListeners(false);
|
||||
systemTime.setFrozen(freezeTimeChk.getSelection());
|
||||
systemTime.setTime(cal.getTime());
|
||||
systemTime.notifyListeners(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.eclipse.ui.progress.UIJob;
|
|||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.ISimulatedTimeChangeListener;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.viz.core.mode.CAVEMode;
|
||||
import com.raytheon.viz.ui.actions.ShowTimeDialog;
|
||||
|
@ -62,6 +63,7 @@ import com.raytheon.viz.ui.actions.ShowTimeDialog;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Nov 30,2007 461 bphillip Initial Creation
|
||||
* 09JUL2008 1234 ebabin Updates for color, and display issues.
|
||||
* Jan 09, 2013 1442 rferrel Added Simulated Time Change listener.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -140,6 +142,8 @@ public class TimeDisplay extends ContributionItem {
|
|||
// workaround for the random tooltip following the cursor
|
||||
private boolean displayTooltip = true;
|
||||
|
||||
private ISimulatedTimeChangeListener timeChangeListener;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -150,6 +154,15 @@ public class TimeDisplay extends ContributionItem {
|
|||
gmtFormatter.setTimeZone(GMT);
|
||||
|
||||
localFormatter = new SimpleDateFormat(localPattern);
|
||||
timeChangeListener = new ISimulatedTimeChangeListener() {
|
||||
|
||||
@Override
|
||||
public void timechanged() {
|
||||
update();
|
||||
}
|
||||
};
|
||||
SimulatedTime.getSystemTime().addSimulatedTimeChangeListener(
|
||||
timeChangeListener);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -160,6 +173,8 @@ public class TimeDisplay extends ContributionItem {
|
|||
@Override
|
||||
public void dispose() {
|
||||
activeList.remove(this);
|
||||
SimulatedTime.getSystemTime().removeSimulatedTimeChangeListener(
|
||||
timeChangeListener);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.time;
|
||||
|
||||
/**
|
||||
* Interface for hooks to send notification when simulated time is modified.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 09, 2013 1442 rferrel Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author rferrel
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface ISimulatedTimeChangeListener {
|
||||
|
||||
/**
|
||||
* Method called with simulated time is modified.
|
||||
*/
|
||||
public void timechanged();
|
||||
}
|
|
@ -19,10 +19,9 @@
|
|||
**/
|
||||
package com.raytheon.uf.common.time;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Simulated time clock with offset and scale capabilities.
|
||||
|
@ -38,6 +37,8 @@ import java.util.TimeZone;
|
|||
* Jul 16, 2008 randerso Initial creation
|
||||
* Aug 24, 2012 0743 djohnson Add option to use milliseconds for operations, change to singleton.
|
||||
* Nov 02, 2012 1302 djohnson Change mistakenly public constructor to private.
|
||||
* Jan 07, 2013 1442 rferrel Changes to add/remove/notify Simulated Time Change Listeners.
|
||||
* Use SimulatedTimeTest for unit testing.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -51,6 +52,10 @@ public final class SimulatedTime {
|
|||
*/
|
||||
private static final SimulatedTime systemTime = new SimulatedTime();
|
||||
|
||||
private List<ISimulatedTimeChangeListener> listeners;
|
||||
|
||||
private boolean doNotify;
|
||||
|
||||
/**
|
||||
* Retrieve the system global simulate time instance
|
||||
*
|
||||
|
@ -99,41 +104,19 @@ public final class SimulatedTime {
|
|||
*
|
||||
*/
|
||||
private SimulatedTime() {
|
||||
this.listeners = new ArrayList<ISimulatedTimeChangeListener>();
|
||||
this.doNotify = true;
|
||||
setRealTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a simulated time starting at the specified time with
|
||||
* acceleration/deceleration, optionally frozen.
|
||||
*
|
||||
* @param date
|
||||
* starting time
|
||||
* @param scale
|
||||
* 1.0 for normal time rate, >1.0 for accelerated time < 1.0 for
|
||||
* decelerated time. If negative time will run backward.
|
||||
* @param isFrozen
|
||||
* true to freeze time
|
||||
*/
|
||||
private SimulatedTime(Date date, double scale, boolean isFrozen) {
|
||||
this(date.getTime(), scale, isFrozen);
|
||||
public synchronized void addSimulatedTimeChangeListener(
|
||||
ISimulatedTimeChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a simulated time starting at the specified time with
|
||||
* acceleration/deceleration, optionally frozen.
|
||||
*
|
||||
* @param millis
|
||||
* starting time in milliseconds
|
||||
* @param scale
|
||||
* 1.0 for normal time rate, >1.0 for accelerated time < 1.0 for
|
||||
* decelerated time. If negative time will run backward.
|
||||
* @param isFrozen
|
||||
* true to freeze time
|
||||
*/
|
||||
private SimulatedTime(long millis, double scale, boolean isFrozen) {
|
||||
setTime(millis);
|
||||
this.scale = scale;
|
||||
this.isFrozen = isFrozen;
|
||||
public synchronized void removeSimulatedTimeChangeListener(
|
||||
ISimulatedTimeChangeListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,6 +136,7 @@ public final class SimulatedTime {
|
|||
offset = 0;
|
||||
scale = 1.0;
|
||||
isFrozen = false;
|
||||
fireTimeChangeListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,6 +177,7 @@ public final class SimulatedTime {
|
|||
baseTime = now();
|
||||
offset = millis - baseTime;
|
||||
}
|
||||
fireTimeChangeListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,7 +198,10 @@ public final class SimulatedTime {
|
|||
* decelerated time. If negative time will run backward.
|
||||
*/
|
||||
public void setScale(double scale) {
|
||||
this.scale = scale;
|
||||
if (this.scale != scale) {
|
||||
this.scale = scale;
|
||||
fireTimeChangeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,42 +231,34 @@ public final class SimulatedTime {
|
|||
offset = frozenTime - baseTime;
|
||||
}
|
||||
this.isFrozen = isFrozen;
|
||||
fireTimeChangeListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test routine
|
||||
* Allows turning off notification of listeners when making several updates
|
||||
* at the same time. Changing to false turns off notification. Changing to
|
||||
* true allows notification and triggers a notification.
|
||||
*
|
||||
* @param args
|
||||
* N/A
|
||||
* @param doNotify
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
String timeFormat = "HH:mm:ss z dd-MMM-yyyy";
|
||||
TimeZone GMT = TimeZone.getTimeZone("GMT");
|
||||
public void notifyListeners(boolean doNotify) {
|
||||
if (this.doNotify != doNotify) {
|
||||
this.doNotify = doNotify;
|
||||
fireTimeChangeListeners();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleDateFormat gmtFormatter = new SimpleDateFormat(timeFormat);
|
||||
gmtFormatter.setTimeZone(GMT);
|
||||
|
||||
SimpleDateFormat local = new SimpleDateFormat(timeFormat);
|
||||
|
||||
Calendar cal = Calendar.getInstance(GMT);
|
||||
cal.clear();
|
||||
cal.set(1960, 5, 5, 0, 0, 0);
|
||||
|
||||
SimulatedTime simTime = new SimulatedTime(cal.getTime(), 2.0, false);
|
||||
for (int i = 0; i < 15; i++) {
|
||||
Date date = simTime.getTime();
|
||||
System.out.println(gmtFormatter.format(date) + ", "
|
||||
+ local.format(date)
|
||||
+ (simTime.isFrozen() ? " frozen" : ""));
|
||||
simTime.setFrozen(i >= 5 && i < 10);
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
/**
|
||||
* Notify listeners of time change.
|
||||
*/
|
||||
private void fireTimeChangeListeners() {
|
||||
if (doNotify) {
|
||||
// Copy to make thread safe.
|
||||
List<ISimulatedTimeChangeListener> list = new ArrayList<ISimulatedTimeChangeListener>(
|
||||
listeners);
|
||||
for (ISimulatedTimeChangeListener listener : list) {
|
||||
listener.timechanged();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,8 +153,8 @@ HDS ^(O.[JMNQ].{1,3}) KWBJ (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)
|
|||
# OTLA88 KWBI 010000 /mSST !grib/ncep/SST/#235/201102010000/F000/TMP/sfc/
|
||||
#HDS ^(O.L.{1,3}) KWBI (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/(F[0-9]{3})/([^/]*)
|
||||
# FILE -overwrite -log -close -edex /data_store/\5/(\2:yyyy)(\2:mm)\2/\3/\6/GRID\7/\9Z_\(10)_\(11)-\1_KWBI_\2\3\4_(seq).\5.%Y%m%d%H
|
||||
#!MAINT! Combined the above two patterns into one. The only difference was KWBM vs KWBI
|
||||
HDS ^(O.N.{1,3}) (KWBM|KWBI) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/(F[0-9]{3})/([^/]*)
|
||||
#!MAINT! Combined the above two patterns into one. The only difference was KWBM vs KWBI and the O.L or O.N in \1
|
||||
HDS ^(O.[LN].{1,3}) (KWBM|KWBI) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/(F[0-9]{3})/([^/]*)
|
||||
FILE -overwrite -log -close -edex /data_store/\6/(\3:yyyy)(\3:mm)\3/\4/\7/GRID\8/\(10)Z_\(11)_\(12)-\1_\2_\3\4\5_(seq).\6.%Y%m%d%H
|
||||
|
||||
# AWIPS1: GRID ^OEBA88.*KNWC /Grid/SBN/Raw
|
||||
|
@ -335,6 +335,14 @@ HDS ^(ZETA98) (KTUA|PACR|KSTR|KRSA|KORN|KRHA|KKRF|KMSR|KTAR|KPTR|KTIR|KALR|KFWR)
|
|||
ANY ^(ZDIA98) (....) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/(F[0-9]{3})
|
||||
FILE -overwrite -log -close -edex /data_store/\6/(\3:yyyy)(\3:mm)\3/\4/\7/GRID\8/\(10)Z_\(11)-\1_\2_\3\4\5_(seq).\6.%Y%m%d%H
|
||||
|
||||
# Restore from build 12.12 with new grib storage convention.
|
||||
HRS ^(YA)([WX])(A..) (KKCI) (..)(..)(..).*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/(F[0-9]{3})
|
||||
FILE -overwrite -log -close -edex /data_store/\8/(\5:yyyy)(\5:mm)\5/\6/\9/GRID\(10)/\(12)Z_\(13)-\1\2\3_\4_5\6\7_(seq).\8.%Y%m%d%H
|
||||
|
||||
HRS ^(ZV)(W)([ADGJM]..) (KKCI) (..)(..)(..).*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/(F[0-9]{3})
|
||||
FILE -overwrite -log -close -edex /data_store/\8/(\5:yyyy)(\5:mm)\5/\6/\9/GRID\(10)/\(12)Z_\(13)-\1\2\3_\4_5\6\7_(seq).\8.%Y%m%d%H
|
||||
|
||||
|
||||
# AWIPS1: POINT .*IUPT(0[1-4]).*|.*IUPT40.* /ispan/bufr/profiler
|
||||
# IUPT01 KBOU 020300
|
||||
# AWIPS1: POINT ^IUAK01.* /ispan/bufr/profiler
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Date;
|
|||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.raytheon.uf.common.util.TestUtil;
|
||||
|
||||
|
@ -38,6 +39,7 @@ import com.raytheon.uf.common.util.TestUtil;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 24, 2012 djohnson Initial creation
|
||||
* Jan 15, 2013 1442 rferrel Added tests for notify Time changes.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -73,4 +75,29 @@ public class SimulatedTimeTest {
|
|||
|
||||
TestUtil.assertNotEquals(start, end);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerNotifiedOnTimeChanges() throws Exception {
|
||||
SimulatedTime simulatedTime = SimulatedTime.getSystemTime();
|
||||
ISimulatedTimeChangeListener listener = Mockito
|
||||
.mock(ISimulatedTimeChangeListener.class);
|
||||
simulatedTime.addSimulatedTimeChangeListener(listener);
|
||||
try {
|
||||
simulatedTime.setFrozen(true);
|
||||
Mockito.verify(listener).timechanged();
|
||||
} finally {
|
||||
simulatedTime.removeSimulatedTimeChangeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovedListenerNotNotifiedOnTimeChanges() throws Exception {
|
||||
SimulatedTime simulatedTime = SimulatedTime.getSystemTime();
|
||||
ISimulatedTimeChangeListener listener = Mockito
|
||||
.mock(ISimulatedTimeChangeListener.class);
|
||||
simulatedTime.addSimulatedTimeChangeListener(listener);
|
||||
simulatedTime.removeSimulatedTimeChangeListener(listener);
|
||||
simulatedTime.setFrozen(true);
|
||||
Mockito.verify(listener, Mockito.never()).timechanged();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue