Merge branch 'omaha_13.5.1' (omaha_13.5.1-3) into development
Conflicts: edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java Change-Id: Idbf62886d6dbb4a4feeedb6ac17e8978cad2d59c Former-commit-id:4d67472f05
[formerlycf29af8d65
] [formerlyad353c34f9
] [formerlyad353c34f9
[formerlyd262c02612
]] [formerlyb007d4a302
[formerlyad353c34f9
[formerlyd262c02612
] [formerlyb007d4a302
[formerly 98e25be1049113faf4b2cde1eea38ce7e432b6de]]]] Former-commit-id:b007d4a302
Former-commit-id: ad8fce32fddfcc3c0b9c81e8f7f20bf4773ffb2c [formerly e422f5095871dd256779ff7c9c2a352c6ebe88ac] [formerlye03283ad4a
[formerlyaf1099b3fb
]] Former-commit-id:e03283ad4a
Former-commit-id:bf6e4c1f71
This commit is contained in:
commit
8af18ae802
240 changed files with 6008 additions and 2922 deletions
|
@ -7,6 +7,7 @@ Bundle-Activator: com.raytheon.uf.viz.archive.Activator
|
|||
Bundle-Vendor: RAYTHEON
|
||||
Require-Bundle: org.eclipse.ui;bundle-version="3.8.2",
|
||||
org.eclipse.core.runtime,
|
||||
org.apache.commons.lang;bundle-version="2.3.0",
|
||||
com.raytheon.viz.ui;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
|
||||
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
|
||||
|
|
|
@ -183,7 +183,7 @@ public class SizeJob extends Job {
|
|||
|
||||
displayData.setSize(size);
|
||||
|
||||
List<SizeJobRequest> list = new ArrayList<SizeJobRequest>();
|
||||
List<SizeJobRequest> list = new ArrayList<SizeJobRequest>(1);
|
||||
list.add(dirInfo);
|
||||
for (IUpdateListener listener : listeners) {
|
||||
listener.update(list);
|
||||
|
|
|
@ -253,8 +253,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
|
|||
}
|
||||
});
|
||||
|
||||
ArchiveConfigManager.getInstance().reset();
|
||||
|
||||
return comboComp;
|
||||
}
|
||||
|
||||
|
@ -266,17 +264,17 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
|
|||
@Override
|
||||
protected void preOpened() {
|
||||
super.preOpened();
|
||||
setCursorBusy(true);
|
||||
|
||||
// Setup to display blank dialog with busy cursor while getting data.
|
||||
Job job = new Job("setup") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
initInfo();
|
||||
VizApp.runAsync(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
setCursorBusy(true);
|
||||
initInfo();
|
||||
populateComboBoxes();
|
||||
updateTableComp();
|
||||
}
|
||||
|
@ -362,10 +360,12 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
|
|||
}
|
||||
|
||||
/**
|
||||
* Populates the archive/category combo boxes and obtains the display data.
|
||||
* Get information from manager for populating combo boxes and set up to get
|
||||
* selected entries sizes. Intended for use on a non-UI thread.
|
||||
*/
|
||||
private void initInfo() {
|
||||
ArchiveConfigManager manager = ArchiveConfigManager.getInstance();
|
||||
manager.reset();
|
||||
Calendar startCal = getStart();
|
||||
Calendar endCal = getEnd();
|
||||
String[] archiveNames = manager.getArchiveDataNamesList();
|
||||
|
@ -495,4 +495,29 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset modification flag.
|
||||
*/
|
||||
protected void clearModified() {
|
||||
tableComp.clearModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listener to inform when modification flag is set.
|
||||
*
|
||||
* @param iModifyListener
|
||||
*/
|
||||
protected void addModifiedListener(IModifyListener iModifyListener) {
|
||||
tableComp.addModifiedListener(iModifyListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove modification listener.
|
||||
*
|
||||
* @param iModifyListener
|
||||
*/
|
||||
protected void removeModifiedListener(IModifyListener iModifyListener) {
|
||||
tableComp.removeModifiedListener(iModifyListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.util.List;
|
|||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.events.ShellAdapter;
|
||||
import org.eclipse.swt.events.ShellEvent;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
|
@ -32,6 +34,7 @@ import org.eclipse.swt.widgets.Combo;
|
|||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Layout;
|
||||
import org.eclipse.swt.widgets.MessageBox;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Spinner;
|
||||
|
||||
|
@ -39,6 +42,7 @@ import com.raytheon.uf.common.archive.config.ArchiveConfigManager;
|
|||
import com.raytheon.uf.common.archive.config.DisplayData;
|
||||
import com.raytheon.uf.viz.archive.data.IArchiveTotals;
|
||||
import com.raytheon.uf.viz.archive.ui.ArchiveTableComp.TableType;
|
||||
import com.raytheon.uf.viz.core.VizApp;
|
||||
|
||||
/**
|
||||
* Archive retention dialog.
|
||||
|
@ -59,7 +63,7 @@ import com.raytheon.uf.viz.archive.ui.ArchiveTableComp.TableType;
|
|||
* @version 1.0
|
||||
*/
|
||||
public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
||||
IArchiveTotals {
|
||||
IArchiveTotals, IModifyListener {
|
||||
|
||||
/** Current Archive/Category selection's minimum retention hours. */
|
||||
private RetentionHours minRetention;
|
||||
|
@ -73,8 +77,11 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
/** Displays the total size of selected items. */
|
||||
private Label totalSizeLbl;
|
||||
|
||||
// TODO in the future, get this value from a user text box
|
||||
protected static final String ARCHIVE_DIR = "/archive_dir";
|
||||
/** Performs save action button. */
|
||||
private Button saveBtn;
|
||||
|
||||
/** Flag set when user wants to close with unsaved modifications. */
|
||||
boolean closeFlag = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -89,6 +96,11 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
this.tableType = TableType.Retention;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#constructShellLayout()
|
||||
*/
|
||||
@Override
|
||||
protected Layout constructShellLayout() {
|
||||
// Create the main layout for the shell.
|
||||
|
@ -98,6 +110,13 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
return mainLayout;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#initializeComponents(org
|
||||
* .eclipse.swt.widgets.Shell)
|
||||
*/
|
||||
@Override
|
||||
protected void initializeComponents(Shell shell) {
|
||||
setText("Archive Retention");
|
||||
|
@ -162,11 +181,13 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
minRetention = new RetentionHours(1, minRetentionSpnr, minRetentionCbo) {
|
||||
|
||||
@Override
|
||||
protected void handleTimeSelection() {
|
||||
super.handleTimeSelection();
|
||||
protected boolean handleTimeSelection() {
|
||||
boolean state = super.handleTimeSelection();
|
||||
getSelectedArchive().setRetentionHours(getHours());
|
||||
return state;
|
||||
}
|
||||
};
|
||||
minRetention.addModifyListener(this);
|
||||
|
||||
/*
|
||||
* Bottom row of controls.
|
||||
|
@ -190,11 +211,13 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
extRetention = new RetentionHours(1, extRetentionSpnr, extRetentionCbo) {
|
||||
|
||||
@Override
|
||||
protected void handleTimeSelection() {
|
||||
super.handleTimeSelection();
|
||||
protected boolean handleTimeSelection() {
|
||||
boolean state = super.handleTimeSelection();
|
||||
getSelectedCategory().setRetentionHours(getHours());
|
||||
return state;
|
||||
}
|
||||
};
|
||||
extRetention.addModifyListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,7 +243,7 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
// }
|
||||
// });
|
||||
|
||||
Button saveBtn = new Button(actionControlComp, SWT.PUSH);
|
||||
saveBtn = new Button(actionControlComp, SWT.PUSH);
|
||||
saveBtn.setText(" Save ");
|
||||
saveBtn.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
|
@ -228,8 +251,11 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
ArchiveConfigManager manager = ArchiveConfigManager
|
||||
.getInstance();
|
||||
manager.save();
|
||||
saveBtn.setEnabled(false);
|
||||
clearModified();
|
||||
}
|
||||
});
|
||||
saveBtn.setEnabled(false);
|
||||
|
||||
gd = new GridData(SWT.RIGHT, SWT.DEFAULT, true, false);
|
||||
Button closeBtn = new Button(actionControlComp, SWT.PUSH);
|
||||
|
@ -238,11 +264,33 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
closeBtn.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
close();
|
||||
if (verifyClose()) {
|
||||
close();
|
||||
} else {
|
||||
e.doit = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* When unsaved modifications this asks the user to verify the close.
|
||||
*
|
||||
* @return true when okay to close.
|
||||
*/
|
||||
private boolean verifyClose() {
|
||||
boolean state = true;
|
||||
if (isModified()) {
|
||||
MessageBox box = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK
|
||||
| SWT.CANCEL);
|
||||
box.setText("Close Retention");
|
||||
box.setMessage("Unsave changes.\nSelect OK to continue.");
|
||||
state = box.open() == SWT.OK;
|
||||
}
|
||||
closeFlag = state;
|
||||
return state;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -334,4 +382,80 @@ public class ArchiveRetentionDlg extends AbstractArchiveDlg implements
|
|||
super.categoryComboSelection();
|
||||
extRetention.setHours(getSelectedCategory().getRetentionHours());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.archive.ui.IModifyListener#modified()
|
||||
*/
|
||||
@Override
|
||||
public void modified() {
|
||||
saveBtn.setEnabled(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#clearModified()
|
||||
*/
|
||||
@Override
|
||||
public void clearModified() {
|
||||
super.clearModified();
|
||||
minRetention.clearModified();
|
||||
extRetention.clearModified();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#preOpened()
|
||||
*/
|
||||
@Override
|
||||
protected void preOpened() {
|
||||
super.preOpened();
|
||||
addModifiedListener(this);
|
||||
shell.addShellListener(new ShellAdapter() {
|
||||
|
||||
@Override
|
||||
public void shellClosed(ShellEvent e) {
|
||||
if (closeFlag || !isModified()) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.doit = false;
|
||||
VizApp.runAsync(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (verifyClose()) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.uf.viz.archive.ui.AbstractArchiveDlg#disposed()
|
||||
*/
|
||||
@Override
|
||||
protected void disposed() {
|
||||
minRetention.removeModifyListener(this);
|
||||
extRetention.removeModifyListener(this);
|
||||
removeModifiedListener(this);
|
||||
super.disposed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate unsaved user changes.
|
||||
*
|
||||
* @return modified
|
||||
*/
|
||||
private boolean isModified() {
|
||||
return (saveBtn != null) && !saveBtn.isDisposed()
|
||||
&& saveBtn.isEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.archive.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.MouseAdapter;
|
||||
import org.eclipse.swt.events.MouseEvent;
|
||||
|
@ -31,7 +33,9 @@ import org.eclipse.swt.layout.GridData;
|
|||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.Menu;
|
||||
import org.eclipse.swt.widgets.MenuItem;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
|
@ -60,8 +64,11 @@ import com.raytheon.uf.viz.archive.data.IArchiveTotals;
|
|||
*/
|
||||
public class ArchiveTableComp extends Composite {
|
||||
|
||||
/** Key for getting Display Data. */
|
||||
private final String DISPLAY_DATA_KEY = "displayData";
|
||||
/** Column to display label information. */
|
||||
private final int LABEL_COL_INDEX = 0;
|
||||
|
||||
/** Column to display size information,. */
|
||||
private final int SIZE_COL_INDEX = 1;
|
||||
|
||||
/** Table control. */
|
||||
private Table table;
|
||||
|
@ -86,6 +93,19 @@ public class ArchiveTableComp extends Composite {
|
|||
/** Allows the parent dialog log to update other total displays. */
|
||||
private final IArchiveTotals iArchiveTotals;
|
||||
|
||||
/** Data for the currently display table */
|
||||
private DisplayData[] tableData;
|
||||
|
||||
/**
|
||||
* Modification state set to true only when user performs a modification.
|
||||
*/
|
||||
private boolean modifiedState = false;
|
||||
|
||||
/**
|
||||
* Listeners to inform when user changes the modification state.
|
||||
*/
|
||||
private final List<IModifyListener> modifiedListeners = new CopyOnWriteArrayList<IModifyListener>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
@ -129,13 +149,25 @@ public class ArchiveTableComp extends Composite {
|
|||
GridData gd = null;
|
||||
|
||||
table = new Table(this, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL
|
||||
| SWT.H_SCROLL | SWT.MULTI);
|
||||
| SWT.H_SCROLL | SWT.MULTI | SWT.VIRTUAL);
|
||||
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, true);
|
||||
gd.widthHint = 730;
|
||||
gd.heightHint = 270;
|
||||
table.setLayoutData(gd);
|
||||
table.setHeaderVisible(true);
|
||||
table.setLinesVisible(true);
|
||||
table.addListener(SWT.SetData, new Listener() {
|
||||
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
TableItem item = (TableItem) event.item;
|
||||
int index = table.indexOf(item);
|
||||
DisplayData displayData = tableData[index];
|
||||
item.setText(new String[] { displayData.getDisplayLabel(),
|
||||
displayData.getSizeLabel() });
|
||||
item.setChecked(displayData.isSelected());
|
||||
}
|
||||
});
|
||||
|
||||
TableColumn pathColumn = new TableColumn(table, SWT.LEFT);
|
||||
pathColumn.setText("Label");
|
||||
|
@ -164,9 +196,21 @@ public class ArchiveTableComp extends Composite {
|
|||
public void widgetSelected(SelectionEvent e) {
|
||||
if (e.detail == SWT.CHECK) {
|
||||
updateSelectionLabels();
|
||||
setModified();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Listener sortListener = new Listener() {
|
||||
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
sortColumn(event);
|
||||
}
|
||||
};
|
||||
|
||||
pathColumn.addListener(SWT.Selection, sortListener);
|
||||
sizeColumn.addListener(SWT.Selection, sortListener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,20 +232,58 @@ public class ArchiveTableComp extends Composite {
|
|||
sizeLbl.setLayoutData(gd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort table roles by desired column and direction.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
private void sortColumn(Event e) {
|
||||
TableColumn sortColumn = table.getSortColumn();
|
||||
TableColumn eventColumn = (TableColumn) e.widget;
|
||||
|
||||
int sortDir = table.getSortDirection();
|
||||
int index = eventColumn == table.getColumn(LABEL_COL_INDEX) ? LABEL_COL_INDEX
|
||||
: SIZE_COL_INDEX;
|
||||
|
||||
if (sortColumn == eventColumn) {
|
||||
sortDir = ((sortDir == SWT.UP) ? SWT.DOWN : SWT.UP);
|
||||
} else {
|
||||
table.setSortColumn(eventColumn);
|
||||
sortDir = SWT.UP;
|
||||
}
|
||||
|
||||
switch (index) {
|
||||
case LABEL_COL_INDEX:
|
||||
Arrays.sort(tableData, DisplayData.LABEL_ORDER);
|
||||
if (sortDir == SWT.DOWN) {
|
||||
ArrayUtils.reverse(tableData);
|
||||
}
|
||||
break;
|
||||
case SIZE_COL_INDEX:
|
||||
Arrays.sort(tableData, DisplayData.SIZE_ORDER);
|
||||
if (sortDir == SWT.DOWN) {
|
||||
ArrayUtils.reverse(tableData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Programmer error should never get here.
|
||||
throw new IndexOutOfBoundsException("Unknown column index.");
|
||||
}
|
||||
table.setSortDirection(sortDir);
|
||||
table.clearAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the selection items labels.
|
||||
*/
|
||||
private void updateSelectionLabels() {
|
||||
TableItem[] itemArray = table.getItems();
|
||||
int count = 0;
|
||||
long tableTotalSize = 0;
|
||||
List<DisplayData> displayDatas = new ArrayList<DisplayData>(
|
||||
itemArray.length);
|
||||
|
||||
for (TableItem ti : itemArray) {
|
||||
DisplayData displayData = (DisplayData) ti
|
||||
.getData(DISPLAY_DATA_KEY);
|
||||
if (ti.getChecked()) {
|
||||
for (int index = 0; index < tableData.length; ++index) {
|
||||
DisplayData displayData = tableData[index];
|
||||
TableItem item = table.getItem(index);
|
||||
if (item.getChecked()) {
|
||||
++count;
|
||||
displayData.setSelected(true);
|
||||
if (tableTotalSize >= 0) {
|
||||
|
@ -215,8 +297,8 @@ public class ArchiveTableComp extends Composite {
|
|||
} else {
|
||||
displayData.setSelected(false);
|
||||
}
|
||||
displayDatas.add(displayData);
|
||||
}
|
||||
List<DisplayData> displayDatas = Arrays.asList(tableData);
|
||||
|
||||
if (selectedLbl != null) {
|
||||
selectedLbl.setText("Table Selected Items: " + count);
|
||||
|
@ -312,59 +394,86 @@ public class ArchiveTableComp extends Composite {
|
|||
for (TableItem ti : itemArray) {
|
||||
ti.setChecked(check);
|
||||
}
|
||||
setModified();
|
||||
|
||||
updateSelectionLabels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the current table to see if the size of any entries needs to be
|
||||
* updated.
|
||||
*
|
||||
* @param displayDatas
|
||||
*/
|
||||
public void updateSize(List<DisplayData> displayDatas) {
|
||||
TableItem[] itemArray = table.getItems();
|
||||
|
||||
for (DisplayData displayData : displayDatas) {
|
||||
for (TableItem ti : itemArray) {
|
||||
if (displayData.equals(ti.getData(DISPLAY_DATA_KEY))) {
|
||||
setItemSize(ti);
|
||||
if (tableData != null && tableData.length > 0) {
|
||||
for (DisplayData displayData : displayDatas) {
|
||||
for (int index = 0; index < tableData.length; ++index) {
|
||||
if (displayData.equals(tableData[index])) {
|
||||
table.getItem(index)
|
||||
.setText(displayData.getSizeLabel());
|
||||
table.clear(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
updateSelectionLabels();
|
||||
}
|
||||
|
||||
updateSelectionLabels();
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO : this is just for display purposes. This will go away when the
|
||||
* functionality is implemented.
|
||||
/**
|
||||
* Set up table with values in the list.
|
||||
*
|
||||
* @param displayDatas
|
||||
*/
|
||||
protected void populateTable(List<DisplayData> displayDataArray) {
|
||||
protected void populateTable(List<DisplayData> displayDatas) {
|
||||
tableData = displayDatas.toArray(new DisplayData[0]);
|
||||
table.removeAll();
|
||||
for (DisplayData displayData : displayDataArray) {
|
||||
TableItem item = new TableItem(table, SWT.NONE);
|
||||
item.setData(DISPLAY_DATA_KEY, displayData);
|
||||
item.setChecked(displayData.isSelected());
|
||||
item.setText(0, displayData.getDisplayLabel());
|
||||
table.setItemCount(tableData.length);
|
||||
|
||||
item.setChecked(displayData.isSelected());
|
||||
setItemSize(item);
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
table.getColumn(i).setResizable(false);
|
||||
table.getColumn(i).setMoveable(false);
|
||||
table.getColumn(i).pack();
|
||||
}
|
||||
table.getColumn(0).setWidth(600);
|
||||
updateSelectionLabels();
|
||||
table.setSortColumn(table.getColumn(LABEL_COL_INDEX));
|
||||
table.setSortDirection(SWT.UP);
|
||||
table.clearAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update table items size column.
|
||||
*
|
||||
* @param item
|
||||
* Check the modified state and inform listeners when it changes.
|
||||
*/
|
||||
private void setItemSize(TableItem item) {
|
||||
long size = ((DisplayData) item.getData(DISPLAY_DATA_KEY)).getSize();
|
||||
if (size < 0L) {
|
||||
item.setText(1, DisplayData.UNKNOWN_SIZE_LABEL);
|
||||
} else {
|
||||
item.setText(1, SizeUtil.prettyByteSize(size));
|
||||
private void setModified() {
|
||||
if (!modifiedState) {
|
||||
modifiedState = true;
|
||||
for (IModifyListener iModifyListener : modifiedListeners) {
|
||||
iModifyListener.modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the modified state.
|
||||
*/
|
||||
public void clearModified() {
|
||||
modifiedState = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listener that wants to be informed when the modified state is
|
||||
* changed.
|
||||
*
|
||||
* @param iModifyListener
|
||||
*/
|
||||
public void addModifiedListener(IModifyListener iModifyListener) {
|
||||
modifiedListeners.add(iModifyListener);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the listener.
|
||||
*/
|
||||
public void removeModifiedListener(IModifyListener iModifyListener) {
|
||||
modifiedListeners.remove(iModifyListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -417,7 +417,7 @@ public class GenerateCaseDlg extends CaveSWTDialog {
|
|||
destination.mkdirs();
|
||||
FileUtil.copyDirectory(source, destination);
|
||||
} else {
|
||||
File destParent = caseDir.getParentFile();
|
||||
File destParent = destination.getParentFile();
|
||||
destParent.mkdirs();
|
||||
FileUtil.copyFile(source, destination);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* 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.viz.archive.ui;
|
||||
|
||||
/**
|
||||
* A Listner to inform when class is modified.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 18, 2013 1966 rferrel Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author rferrel
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public interface IModifyListener {
|
||||
/*
|
||||
* Method called to notify listener that a modification has happened.
|
||||
*/
|
||||
public void modified();
|
||||
}
|
|
@ -19,6 +19,9 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.archive.ui;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
|
@ -57,6 +60,21 @@ public class RetentionHours {
|
|||
/** Combo box assume to determine use of Hours or Days. */
|
||||
private Combo timeUnitCombo;
|
||||
|
||||
/**
|
||||
* Keep track of previous time unit so recalculation only done when changed.
|
||||
*/
|
||||
private int prevTimeUnitSelected = 0;
|
||||
|
||||
/**
|
||||
* Set when user modified values.
|
||||
*/
|
||||
private boolean modifyState = false;
|
||||
|
||||
/**
|
||||
* Listeners to inform when user performs a modification.
|
||||
*/
|
||||
private final List<IModifyListener> listeners = new CopyOnWriteArrayList<IModifyListener>();
|
||||
|
||||
/**
|
||||
* Constructor with default 7 day retention.
|
||||
*/
|
||||
|
@ -76,26 +94,46 @@ public class RetentionHours {
|
|||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
handleTimeSelection();
|
||||
updateAndCheckTimeSelection();
|
||||
}
|
||||
});
|
||||
|
||||
timeUnitCombo.removeAll();
|
||||
timeUnitCombo.add("Hours");
|
||||
timeUnitCombo.add("Days");
|
||||
timeUnitCombo.select(0);
|
||||
timeUnitCombo.select(prevTimeUnitSelected);
|
||||
|
||||
timeUnitCombo.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
handleTimeUnitSelection();
|
||||
handleTimeSelection();
|
||||
if (prevTimeUnitSelected != timeUnitCombo.getSelectionIndex()) {
|
||||
prevTimeUnitSelected = timeUnitCombo.getSelectionIndex();
|
||||
handleTimeUnitSelection();
|
||||
updateAndCheckTimeSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
timeUnitCombo.setData(timeUnitCombo.getItem(timeUnitCombo
|
||||
.getSelectionIndex()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the retention hours and determine if modification listeners should
|
||||
* be notified.
|
||||
*/
|
||||
private void updateAndCheckTimeSelection() {
|
||||
// Make sure this is called so retention hours is updated properly.
|
||||
boolean modified = handleTimeSelection();
|
||||
|
||||
// Do notification when state becomes true.
|
||||
if (!modifyState && modified) {
|
||||
modifyState = true;
|
||||
for (IModifyListener iModifyListener : listeners) {
|
||||
iModifyListener.modified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get retention in hours.
|
||||
*
|
||||
|
@ -120,11 +158,14 @@ public class RetentionHours {
|
|||
if (timeUnitCombo.getItem(timeUnitCombo.getSelectionIndex()).equals(
|
||||
"Days")) {
|
||||
time /= TimeUtil.HOURS_PER_DAY;
|
||||
if (time < minUnit) {
|
||||
time = minUnit;
|
||||
}
|
||||
}
|
||||
|
||||
timeSpnr.setSelection(time);
|
||||
|
||||
// Based on the time unit retentionHours and GUI may need updating.
|
||||
// Based on the time unit retentionHours may need updating.
|
||||
handleTimeSelection();
|
||||
}
|
||||
|
||||
|
@ -177,12 +218,41 @@ public class RetentionHours {
|
|||
/**
|
||||
* Adjust retention hours based on combo boxes current values.
|
||||
*/
|
||||
protected void handleTimeSelection() {
|
||||
protected boolean handleTimeSelection() {
|
||||
int time = timeSpnr.getSelection();
|
||||
boolean modified = false;
|
||||
if (timeUnitCombo.getItem(timeUnitCombo.getSelectionIndex()).equals(
|
||||
"Days")) {
|
||||
time *= TimeUtil.HOURS_PER_DAY;
|
||||
}
|
||||
retentionHours = time;
|
||||
|
||||
if (retentionHours != time) {
|
||||
retentionHours = time;
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the modify state.
|
||||
*/
|
||||
public void clearModified() {
|
||||
modifyState = false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param iModifyListener
|
||||
*/
|
||||
public void addModifyListener(IModifyListener iModifyListener) {
|
||||
listeners.add(iModifyListener);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param iModifyListener
|
||||
*/
|
||||
public void removeModifyListener(IModifyListener iModifyListener) {
|
||||
listeners.remove(iModifyListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
* Aug 20, 2007 njensen Added listColorMaps().
|
||||
* Aug 20, 2008 dglazesk JiBX to JaXB
|
||||
* Aug 20, 2008 dglazesk Updated for new ColorMap interface
|
||||
* Jun 10, 2013 2075 njensen Added listColorMapFiles(subdirectory)
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -62,6 +63,10 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
|
||||
public class ColorMapLoader {
|
||||
|
||||
private static final String EXTENSION = ".cmap";
|
||||
|
||||
private static final String DIR_NAME = "colormaps";
|
||||
|
||||
private static final String sharedMutex = "";
|
||||
|
||||
/* This class is used to cache the color maps and update them upon changes */
|
||||
|
@ -132,8 +137,8 @@ public class ColorMapLoader {
|
|||
try {
|
||||
LocalizationFile f = PathManagerFactory.getPathManager()
|
||||
.getStaticLocalizationFile(
|
||||
"colormaps" + IPathManager.SEPARATOR + name
|
||||
+ ".cmap");
|
||||
DIR_NAME + IPathManager.SEPARATOR + name
|
||||
+ EXTENSION);
|
||||
if (f == null || !f.exists()) {
|
||||
// If the file was not found check to see if the
|
||||
// localization context is encoded as part of the path.
|
||||
|
@ -146,9 +151,8 @@ public class ColorMapLoader {
|
|||
f = PathManagerFactory.getPathManager()
|
||||
.getLocalizationFile(
|
||||
context,
|
||||
"colormaps"
|
||||
+ IPathManager.SEPARATOR
|
||||
+ split[2] + ".cmap");
|
||||
DIR_NAME + IPathManager.SEPARATOR
|
||||
+ split[2] + EXTENSION);
|
||||
if (f == null) {
|
||||
return loadColorMap(split[2]);
|
||||
}
|
||||
|
@ -170,7 +174,15 @@ public class ColorMapLoader {
|
|||
return cm;
|
||||
}
|
||||
|
||||
public static LocalizationFile[] listColorMapFiles() {
|
||||
/**
|
||||
* Recursively searches for the colormaps that are in the specified
|
||||
* directory
|
||||
*
|
||||
* @param dir
|
||||
* the directory to search recursively
|
||||
* @return the localization files of the colormaps that are found
|
||||
*/
|
||||
private static LocalizationFile[] internalListColorMapFiles(String dir) {
|
||||
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
Set<LocalizationContext> searchContexts = new HashSet<LocalizationContext>();
|
||||
|
@ -195,15 +207,38 @@ public class ColorMapLoader {
|
|||
}
|
||||
|
||||
LocalizationFile[] files = pm.listFiles(searchContexts
|
||||
.toArray(new LocalizationContext[searchContexts.size()]),
|
||||
"colormaps", new String[] { ".cmap" }, true, true);
|
||||
.toArray(new LocalizationContext[searchContexts.size()]), dir,
|
||||
new String[] { EXTENSION }, true, true);
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the colormaps in the specified subdirectory. For example, if
|
||||
* subdirectory is "ffmp", it will recursively walk down the colormaps/ffmp
|
||||
* directory
|
||||
*
|
||||
* @param subDirectory
|
||||
* the subdirectory of the colormaps dir to search
|
||||
* @return
|
||||
*/
|
||||
public static LocalizationFile[] listColorMapFiles(String subDirectory) {
|
||||
return internalListColorMapFiles(DIR_NAME + IPathManager.SEPARATOR
|
||||
+ subDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the colormaps found in the system
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static LocalizationFile[] listColorMapFiles() {
|
||||
return internalListColorMapFiles(DIR_NAME);
|
||||
}
|
||||
|
||||
public static String shortenName(LocalizationFile file) {
|
||||
String name = file.getName()
|
||||
.replace("colormaps" + IPathManager.SEPARATOR, "")
|
||||
.replace(".cmap", "");
|
||||
.replace(DIR_NAME + IPathManager.SEPARATOR, "")
|
||||
.replace(EXTENSION, "");
|
||||
if (!file.getContext().getLocalizationLevel()
|
||||
.equals(LocalizationLevel.BASE)) {
|
||||
String level = file.getContext().getLocalizationLevel().name();
|
||||
|
@ -234,9 +269,8 @@ public class ColorMapLoader {
|
|||
private static IColorMap loadColorMap(String name,
|
||||
LocalizationFile colorMapFile) throws SerializationException {
|
||||
if (colorMapFile != null) {
|
||||
ColorMap cm = (ColorMap) SerializationUtil
|
||||
.jaxbUnmarshalFromXmlFile(colorMapFile.getFile()
|
||||
.getAbsolutePath());
|
||||
ColorMap cm = SerializationUtil.jaxbUnmarshalFromXmlFile(
|
||||
ColorMap.class, colorMapFile.getFile().getAbsolutePath());
|
||||
cm.setName(name);
|
||||
cm.setChanged(false);
|
||||
return cm;
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.util.ArrayList;
|
|||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -20,6 +19,7 @@ import java.util.TreeSet;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentNavigableMap;
|
||||
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
|
@ -44,7 +44,6 @@ import com.raytheon.uf.common.monitor.config.FFFGDataMgr;
|
|||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPTemplateConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.DomainXML;
|
||||
import com.raytheon.uf.common.monitor.xml.FFMPRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductRunXML;
|
||||
|
@ -71,10 +70,7 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpBasinTableDlg;
|
|||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfig;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.IFFMPResourceListener;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader.LOADER_TYPE;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResource;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResourceData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTimeWindow;
|
||||
import com.raytheon.uf.viz.monitor.listeners.IMonitorListener;
|
||||
|
||||
|
@ -95,10 +91,12 @@ import com.raytheon.uf.viz.monitor.listeners.IMonitorListener;
|
|||
* 02/01/13 1627 D. Hladky removed unused(useless) db load method
|
||||
* 02/19/13 1639 njensen Replaced ConcurrentHashMaps with data structures
|
||||
* 02/20/13 1635 D. Hladky Fixed multi guidance sources
|
||||
* Mar 6, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Apr 9, 2013 1890 dhladky Fixed the broken cache file load
|
||||
* Mar 06, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Apr 09, 2013 1890 dhladky Fixed the broken cache file load
|
||||
* Apr 16, 2013 1912 bsteffen Initial bulk hdf5 access for ffmp
|
||||
* Apr 26, 2013 1954 bsteffen Minor code cleanup throughout FFMP.
|
||||
* Jun 06, 2013 2075 njensen No longer starts loading threads, resourceData does that
|
||||
* Jun 07, 2013 2075 njensen Extracted FFMPProcessUris to separate class
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -107,7 +105,6 @@ import com.raytheon.uf.viz.monitor.listeners.IMonitorListener;
|
|||
*/
|
||||
|
||||
public class FFMPMonitor extends ResourceMonitor {
|
||||
private static long SECONDS_PER_HOUR = 60 * 60;
|
||||
|
||||
/** Singleton instance of this class */
|
||||
private static FFMPMonitor monitor = null;
|
||||
|
@ -143,8 +140,8 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
|
||||
private FFMPTimeWindow qpeWindow = null;
|
||||
|
||||
/** The infamous templates **/
|
||||
private FFMPTemplates templates = null;
|
||||
/** The infamous templates, now volatile! **/
|
||||
private volatile FFMPTemplates templates = null;
|
||||
|
||||
private FFMPRunConfigurationManager frcm = null;
|
||||
|
||||
|
@ -168,12 +165,6 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
if (res.basinTableDlg != null) {
|
||||
closeDialog(res);
|
||||
}
|
||||
|
||||
// will kill any loaders running
|
||||
if (res.getResourceData().floader != null) {
|
||||
res.getResourceData().floader.kill();
|
||||
res.getResourceData().floader = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +238,6 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
* @return
|
||||
*/
|
||||
public static boolean isRunning() {
|
||||
|
||||
if (monitor == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -301,7 +291,7 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
* @param phuc
|
||||
* @return
|
||||
*/
|
||||
private List<String> getLoadedUris(String siteKey, String source,
|
||||
protected List<String> getLoadedUris(String siteKey, String source,
|
||||
String phuc) {
|
||||
FFMPSiteData siteData = siteDataMap.get(siteKey);
|
||||
FFMPSourceData sourceData = siteData.getSourceData(source);
|
||||
|
@ -338,8 +328,8 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
|| !getLoadedUris(siteKey, source, phuc)
|
||||
.contains(uri)) {
|
||||
try {
|
||||
populateFFMPRecord(siteKey,
|
||||
new FFMPRecord(uri), source, phuc);
|
||||
populateFFMPRecord(siteKey, new FFMPRecord(
|
||||
uri), source, phuc);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"FFMP Can't retrieve FFMP URI, "
|
||||
|
@ -435,11 +425,10 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
* @param phuc
|
||||
* @throws Exception
|
||||
*/
|
||||
public void populateFFMPRecord(String siteKey,
|
||||
FFMPRecord ffmpRec, String source, String phuc) throws Exception {
|
||||
public void populateFFMPRecord(String siteKey, FFMPRecord ffmpRec,
|
||||
String source, String phuc) throws Exception {
|
||||
|
||||
FFMPLoadRecord flr = new FFMPLoadRecord(siteKey,
|
||||
ffmpRec, source, phuc);
|
||||
FFMPLoadRecord flr = new FFMPLoadRecord(siteKey, ffmpRec, source, phuc);
|
||||
flr.run();
|
||||
}
|
||||
|
||||
|
@ -469,9 +458,9 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
if (sourceXML.getSourceType().equals(
|
||||
SOURCE_TYPE.GAGE.getSourceType())
|
||||
&& phuc.equals(FFMPRecord.ALL)) {
|
||||
ffmpRec.retrieveVirtualBasinFromDataStore(loc,
|
||||
dataUri, getTemplates(siteKey), ffmpRec
|
||||
.getDataTime().getRefTime(), basin);
|
||||
ffmpRec.retrieveVirtualBasinFromDataStore(loc, dataUri,
|
||||
getTemplates(siteKey), ffmpRec.getDataTime()
|
||||
.getRefTime(), basin);
|
||||
} else {
|
||||
ffmpRec.retrieveBasinFromDataStore(dataStore, dataUri,
|
||||
getTemplates(siteKey), phuc, ffmpRec
|
||||
|
@ -509,7 +498,7 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
|
||||
return uris;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform a single database request to populate the availableUris for
|
||||
* multiple sources. After preloading the uris the uris for each source can
|
||||
|
@ -790,13 +779,13 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
retrieveNew);
|
||||
}
|
||||
} else {
|
||||
populateFFMPRecord(siteKey, dataKey,
|
||||
sourceName, ptime, phuc, retrieveNew);
|
||||
populateFFMPRecord(siteKey, dataKey, sourceName,
|
||||
ptime, phuc, retrieveNew);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
populateFFMPRecord(siteKey, dataKey, sourceName,
|
||||
ptime, phuc, retrieveNew);
|
||||
populateFFMPRecord(siteKey, dataKey, sourceName, ptime,
|
||||
phuc, retrieveNew);
|
||||
}
|
||||
} else {
|
||||
// special case where FFG is the primary source
|
||||
|
@ -858,39 +847,6 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start secondary and tertiary data loads
|
||||
*
|
||||
* @param startTime
|
||||
* @param loadType
|
||||
* @throws VizException
|
||||
*/
|
||||
public void startLoad(FFMPResource resource, Date startTime,
|
||||
LOADER_TYPE loadType) throws VizException {
|
||||
Date timeBack = null;
|
||||
FFMPTemplateConfigurationManager ftcm = FFMPTemplateConfigurationManager
|
||||
.getInstance();
|
||||
ArrayList<String> hucsToLoad = ftcm.getHucLevels();
|
||||
FFMPResourceData frd = resource.getResourceData();
|
||||
|
||||
if (loadType == LOADER_TYPE.SECONDARY) {
|
||||
timeBack = new Date(resource.getMostRecentTime().getTime()
|
||||
- (6 * TimeUtil.MILLIS_PER_HOUR));
|
||||
frd.timeBack = timeBack;
|
||||
} else if (loadType == LOADER_TYPE.TERTIARY) {
|
||||
hucsToLoad.clear();
|
||||
hucsToLoad.add(FFMPRecord.ALL);
|
||||
timeBack = new Date(resource.getMostRecentTime().getTime()
|
||||
- (TimeUtil.MILLIS_PER_HOUR * 24));
|
||||
}
|
||||
|
||||
frd.floader = new FFMPDataLoader(frd, timeBack, startTime, loadType,
|
||||
hucsToLoad);
|
||||
frd.floader.addListener(resource);
|
||||
frd.floader.start();
|
||||
|
||||
}
|
||||
|
||||
public void launchSplash(final String siteKey) {
|
||||
VizApp.runAsync(new Runnable() {
|
||||
@Override
|
||||
|
@ -985,7 +941,7 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void splashDisposeAndDataLoad(FFMPResource resource) {
|
||||
public synchronized void splashDispose(FFMPResource resource) {
|
||||
if (ffmpSplash != null) {
|
||||
ffmpSplash.close();
|
||||
ffmpSplash = null;
|
||||
|
@ -993,15 +949,6 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
if (resource.isFirst) {
|
||||
updateDialog(resource);
|
||||
}
|
||||
|
||||
// start secondary data load
|
||||
try {
|
||||
startLoad(resource, resource.getResourceData().timeBack,
|
||||
LOADER_TYPE.SECONDARY);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Secondary Data Load failure", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1044,10 +991,6 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
|
||||
if (listener instanceof FFMPResource) {
|
||||
FFMPResource res = (FFMPResource) listener;
|
||||
if (res.getResourceData().floader != null) {
|
||||
res.getResourceData().floader.kill();
|
||||
}
|
||||
res.getResourceData().floader = null;
|
||||
int val = siteCount.get(res.getSiteKey());
|
||||
|
||||
if ((val == 1) && (siteCount.size() > 1)) {
|
||||
|
@ -1684,12 +1627,12 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
* @param barrierTime
|
||||
* @param phuc
|
||||
*/
|
||||
public void processUri(String uri, String siteKey,
|
||||
String sourceName, Date barrierTime, String phuc) {
|
||||
public void processUri(String uri, String siteKey, String sourceName,
|
||||
Date barrierTime, String phuc) {
|
||||
if (uri != null) {
|
||||
try {
|
||||
FFMPRecord record = populateFFMPRecord(uri,
|
||||
siteKey, sourceName, phuc);
|
||||
FFMPRecord record = populateFFMPRecord(uri, siteKey,
|
||||
sourceName, phuc);
|
||||
if (record != null) {
|
||||
record.getBasinData(phuc).loadNow();
|
||||
SourceXML source = getSourceConfig().getSource(sourceName);
|
||||
|
@ -1713,10 +1656,11 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
* @param sourceName
|
||||
*/
|
||||
public void processUris(NavigableMap<Date, List<String>> uriMap,
|
||||
String siteKey, String sourceName, Date barrierTime, String phuc) {
|
||||
FFMPProcessUris processor = new FFMPProcessUris(uriMap,
|
||||
siteKey, sourceName, barrierTime, phuc);
|
||||
processor.run();
|
||||
String siteKey, String sourceName, Date barrierTime, String phuc,
|
||||
SubMonitor smonitor) {
|
||||
FFMPProcessUris processor = new FFMPProcessUris(this, uriMap, siteKey,
|
||||
sourceName, barrierTime, phuc);
|
||||
processor.run(smonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1732,17 +1676,25 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
*/
|
||||
public FFMPTemplates getTemplates(String siteKey) {
|
||||
if (templates == null) {
|
||||
FFMPRunXML runner = getRunConfig().getRunner(wfo);
|
||||
this.templates = FFMPTemplates.getInstance(
|
||||
runner.getPrimaryDomain(), siteKey, MODE.CAVE);
|
||||
// backup domains
|
||||
if (runner.getBackupDomains() != null) {
|
||||
for (DomainXML backup : runner.getBackupDomains()) {
|
||||
templates.addDomain(siteKey, backup);
|
||||
long t0 = System.currentTimeMillis();
|
||||
synchronized (this) {
|
||||
if (templates == null) {
|
||||
FFMPRunXML runner = getRunConfig().getRunner(wfo);
|
||||
this.templates = FFMPTemplates.getInstance(
|
||||
runner.getPrimaryDomain(), siteKey, MODE.CAVE);
|
||||
|
||||
// backup domains
|
||||
if (runner.getBackupDomains() != null) {
|
||||
for (DomainXML backup : runner.getBackupDomains()) {
|
||||
templates.addDomain(siteKey, backup);
|
||||
}
|
||||
} else {
|
||||
templates.done = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
templates.done = true;
|
||||
}
|
||||
System.out.println("Time spent initializing templates: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
}
|
||||
|
||||
if (!templates.isSiteLoaded(siteKey)) {
|
||||
|
@ -1962,7 +1914,7 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
.getTime()) / 1000;
|
||||
if (((Integer) data1Dur.get(i)[2]) > 1000) {
|
||||
dur = ((Integer) data1Dur.get(i)[2] - 1000)
|
||||
* SECONDS_PER_HOUR;
|
||||
* TimeUtil.SECONDS_PER_HOUR;
|
||||
} else {
|
||||
dur = ((Integer) data1Dur.get(i)[2]) * 1000;
|
||||
}
|
||||
|
@ -2241,11 +2193,6 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
dataUri, getTemplates(fsiteKey), refTime,
|
||||
fffmpRec.getSourceName());
|
||||
} else {
|
||||
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
|
||||
statusHandler.handle(Priority.DEBUG,
|
||||
"Retrieving and Populating URI: , "
|
||||
+ dataUri);
|
||||
}
|
||||
curRecord.retrieveMapFromDataStore(loc, dataUri,
|
||||
getTemplates(fffmpRec.getSiteKey()), fhuc,
|
||||
refTime, fffmpRec.getSourceName());
|
||||
|
@ -2260,80 +2207,4 @@ public class FFMPMonitor extends ResourceMonitor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The uri processing
|
||||
*
|
||||
* @author dhladky
|
||||
*
|
||||
*/
|
||||
private class FFMPProcessUris implements Runnable {
|
||||
|
||||
final NavigableMap<Date, List<String>> furiMap;
|
||||
|
||||
|
||||
final String fsiteKey;
|
||||
|
||||
final String fsourceName;
|
||||
|
||||
final Date fbarrierTime;
|
||||
|
||||
final String fhuc;
|
||||
|
||||
public FFMPProcessUris(NavigableMap<Date, List<String>> uriMap,
|
||||
String siteKey, String sourceName, Date barrierTime, String phuc) {
|
||||
this.furiMap = uriMap;
|
||||
this.fsiteKey = siteKey;
|
||||
this.fbarrierTime = barrierTime;
|
||||
this.fsourceName = sourceName;
|
||||
this.fhuc = phuc;
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (furiMap != null) {
|
||||
SourceXML source = getSourceConfig().getSource(fsourceName);
|
||||
boolean isGuidance = false;
|
||||
if (source != null
|
||||
&& source.getSourceType().equals(
|
||||
SOURCE_TYPE.GUIDANCE.getSourceType())) {
|
||||
isGuidance = true;
|
||||
}
|
||||
List<String> loadedUris = getLoadedUris(fsiteKey, fsourceName,
|
||||
fhuc);
|
||||
Set<FFMPRecord> populatedRecords = new HashSet<FFMPRecord>();
|
||||
for (List<String> uris : furiMap.descendingMap().values()) {
|
||||
for (String uri : uris) {
|
||||
if (uri == null || loadedUris.contains(uri)) {
|
||||
continue;
|
||||
}
|
||||
FFMPRecord record = new FFMPRecord(uri);
|
||||
if (record.getDataTime().getRefTime()
|
||||
.after(fbarrierTime)
|
||||
|| isGuidance) {
|
||||
try {
|
||||
record = populateFFMPRecord(uri, fsiteKey,
|
||||
fsourceName, fhuc);
|
||||
if (record != null) {
|
||||
populatedRecords.add(record);
|
||||
if (source != null) {
|
||||
record.setExpiration(source
|
||||
.getExpirationMinutes(fsiteKey));
|
||||
record.setRate(source.isRate());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"FFMP Can't retrieve FFMP URI, " + uri,
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (FFMPRecord record : populatedRecords) {
|
||||
record.getBasinData(fhuc).loadNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE;
|
||||
import com.raytheon.uf.common.monitor.xml.SourceXML;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
||||
/**
|
||||
* Processes the FFMP URIs. Extracted from FFMPMonitor.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 7, 2013 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class FFMPProcessUris {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FFMPProcessUris.class);
|
||||
|
||||
private final NavigableMap<Date, List<String>> furiMap;
|
||||
|
||||
private final String fsiteKey;
|
||||
|
||||
private final String fsourceName;
|
||||
|
||||
private final Date fbarrierTime;
|
||||
|
||||
private final String fhuc;
|
||||
|
||||
private final FFMPMonitor ffmpMonitor;
|
||||
|
||||
public FFMPProcessUris(FFMPMonitor ffmpMonitor,
|
||||
NavigableMap<Date, List<String>> uriMap, String siteKey,
|
||||
String sourceName, Date barrierTime, String phuc) {
|
||||
this.furiMap = uriMap;
|
||||
this.fsiteKey = siteKey;
|
||||
this.fbarrierTime = barrierTime;
|
||||
this.fsourceName = sourceName;
|
||||
this.fhuc = phuc;
|
||||
this.ffmpMonitor = ffmpMonitor;
|
||||
}
|
||||
|
||||
public void run(IProgressMonitor monitor) {
|
||||
if (furiMap != null) {
|
||||
SourceXML source = ffmpMonitor.getSourceConfig().getSource(
|
||||
fsourceName);
|
||||
boolean isGuidance = false;
|
||||
if (source != null
|
||||
&& source.getSourceType().equals(
|
||||
SOURCE_TYPE.GUIDANCE.getSourceType())) {
|
||||
isGuidance = true;
|
||||
}
|
||||
List<String> loadedUris = ffmpMonitor.getLoadedUris(fsiteKey,
|
||||
fsourceName, fhuc);
|
||||
Set<FFMPRecord> populatedRecords = new HashSet<FFMPRecord>();
|
||||
for (List<String> uris : furiMap.descendingMap().values()) {
|
||||
for (String uri : uris) {
|
||||
if (uri == null || loadedUris.contains(uri)) {
|
||||
continue;
|
||||
}
|
||||
FFMPRecord record = new FFMPRecord(uri);
|
||||
if (record.getDataTime().getRefTime().after(fbarrierTime)
|
||||
|| isGuidance) {
|
||||
try {
|
||||
record = ffmpMonitor.populateFFMPRecord(uri,
|
||||
fsiteKey, fsourceName, fhuc);
|
||||
if (record != null) {
|
||||
populatedRecords.add(record);
|
||||
if (source != null) {
|
||||
record.setExpiration(source
|
||||
.getExpirationMinutes(fsiteKey));
|
||||
record.setRate(source.isRate());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"FFMP Can't retrieve FFMP URI, " + uri, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
monitor.beginTask(null, populatedRecords.size());
|
||||
for (FFMPRecord record : populatedRecords) {
|
||||
record.getBasinData(fhuc).loadNow();
|
||||
monitor.worked(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -73,6 +73,7 @@ import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML;
|
|||
* the table column images. This is to fix the Windows
|
||||
* issue on the images being blank and throwing errors.
|
||||
* Also cleaned up some code.
|
||||
* Jun 11, 2013 2075 njensen Optimized createTableItems()
|
||||
* </pre>
|
||||
*
|
||||
* @author lvenable
|
||||
|
@ -289,7 +290,6 @@ public abstract class FFMPTable extends Composite {
|
|||
item.setBackground(j, cellData[j].getBackgroungColor());
|
||||
}
|
||||
}
|
||||
|
||||
table.getColumn(0).setWidth(extent.x + 10);
|
||||
table.redraw();
|
||||
}
|
||||
|
@ -402,7 +402,9 @@ public abstract class FFMPTable extends Composite {
|
|||
ArrayList<FFMPTableColumnXML> ffmpTableCols = ffmpCfgBasin
|
||||
.getTableColumnData();
|
||||
|
||||
if (!sortedColumnName.equalsIgnoreCase(NAME)) {
|
||||
boolean sortedColumnIsName = sortedColumnName.equalsIgnoreCase(NAME);
|
||||
|
||||
if (!sortedColumnIsName) {
|
||||
for (ThreshColNames threshColName : ThreshColNames.values()) {
|
||||
if (sortedColumnName.contains(threshColName.name())) {
|
||||
sortedThreshCol = threshColName;
|
||||
|
@ -437,6 +439,7 @@ public abstract class FFMPTable extends Composite {
|
|||
indexArray.clear();
|
||||
FFMPTableRowData rowData;
|
||||
ArrayList<FFMPTableRowData> rowArray = tableData.getTableRows();
|
||||
indexArray.ensureCapacity(rowArray.size());
|
||||
|
||||
GC gc = new GC(table);
|
||||
gc.setFont(tiFont);
|
||||
|
@ -452,7 +455,7 @@ public abstract class FFMPTable extends Composite {
|
|||
/*
|
||||
* Check if the data value is Not A Number.
|
||||
*/
|
||||
if (!sortedColumnName.equalsIgnoreCase(NAME)) {
|
||||
if (!sortedColumnIsName) {
|
||||
float dataVal = cellData[sortColIndex].getValueAsFloat();
|
||||
|
||||
// DR 14250 fix: any value not a number will be omitted
|
||||
|
|
|
@ -36,9 +36,10 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig.ThreshColNames;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 6, 2009 lvenable Initial creation
|
||||
* Apr 12, 2013 1902 mpduff Optimized the color assignments.
|
||||
* May 7, 2013 1986 njensen Optimized sortBy
|
||||
* Apr 06, 2009 lvenable Initial creation
|
||||
* Apr 12, 2013 1902 mpduff Optimized the color assignments.
|
||||
* May 07, 2013 1986 njensen Optimized sortBy
|
||||
* Jun 10, 2013 2085 njensen Generate color on demand
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -120,8 +121,6 @@ public class FFMPTableCellData {
|
|||
colorValue = Float.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
this.generateCellColor();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,21 +178,21 @@ public class FFMPTableCellData {
|
|||
/**
|
||||
* Set the RGB which is the cell background color.
|
||||
*/
|
||||
public void generateCellColor() {
|
||||
private Color generateCellColor() {
|
||||
Color retVal = null;
|
||||
if ((columnName == FIELDS.GUIDANCE) && this.guidForcedFlag) {
|
||||
if (this.value.isNaN()) {
|
||||
backgroundColor = ffmpCfg.getCellColor(TableCellColor.Default);
|
||||
retVal = ffmpCfg.getCellColor(TableCellColor.Default);
|
||||
} else {
|
||||
backgroundColor = ffmpCfg
|
||||
.getCellColor(TableCellColor.ForcedFFG);
|
||||
retVal = ffmpCfg.getCellColor(TableCellColor.ForcedFFG);
|
||||
}
|
||||
} else if (columnName == FIELDS.GUIDANCE) {
|
||||
backgroundColor = ffmpCfg.getThresholdColor(
|
||||
ThreshColNames.GUID.name(), colorValue);
|
||||
} else {
|
||||
backgroundColor = ffmpCfg.getThresholdColor(columnName.name(),
|
||||
retVal = ffmpCfg.getThresholdColor(ThreshColNames.GUID.name(),
|
||||
colorValue);
|
||||
} else {
|
||||
retVal = ffmpCfg.getThresholdColor(columnName.name(), colorValue);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,6 +248,19 @@ public class FFMPTableCellData {
|
|||
* @return The cell background RGB.
|
||||
*/
|
||||
public Color getBackgroungColor() {
|
||||
if (backgroundColor == null) {
|
||||
synchronized (this) {
|
||||
if (backgroundColor == null) {
|
||||
backgroundColor = generateCellColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public void clearColor() {
|
||||
synchronized (this) {
|
||||
backgroundColor = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ public class FFMPTableComp extends FFMPTable {
|
|||
|
||||
private String siteKey;
|
||||
|
||||
public FFMPTableComp(Composite parent, FFMPTableData data, ITableSelection tableSelectionCB, String siteKey) {
|
||||
public FFMPTableComp(Composite parent, FFMPTableData data,
|
||||
ITableSelection tableSelectionCB, String siteKey) {
|
||||
super(parent, data, siteKey);
|
||||
|
||||
this.siteKey = siteKey;
|
||||
|
@ -67,12 +68,14 @@ public class FFMPTableComp extends FFMPTable {
|
|||
|
||||
@Override
|
||||
protected ColumnAttribData getColumnAttributeData(String colName) {
|
||||
return tableConfig.getTableConfigData(siteKey).getTableColumnAttr(colName);
|
||||
return tableConfig.getTableConfigData(siteKey).getTableColumnAttr(
|
||||
colName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getColumnIndex(String sortCol) {
|
||||
return tableConfig.getTableConfigData(siteKey).getTableColumnIndex(sortCol);
|
||||
return tableConfig.getTableConfigData(siteKey).getTableColumnIndex(
|
||||
sortCol);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,7 +151,7 @@ public class FFMPTableComp extends FFMPTable {
|
|||
ArrayList<FFMPTableRowData> rowData = tableData.getTableRows();
|
||||
for (int i = 0; i < rowData.size(); i++) {
|
||||
rowData.get(i).getTableCellData(threshColumn.getColIndex())
|
||||
.generateCellColor();
|
||||
.clearColor();
|
||||
}
|
||||
|
||||
sortTableUsingConfig();
|
||||
|
|
|
@ -21,7 +21,6 @@ package com.raytheon.uf.viz.monitor.ffmp.ui.dialogs;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
|
||||
|
@ -61,33 +60,30 @@ public class FFMPTableData implements ISortColumn {
|
|||
*/
|
||||
private int currentSortDirection = SWT.DOWN;
|
||||
|
||||
private HashMap<String, Object> pfafMap;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public FFMPTableData() {
|
||||
tableRows = new ArrayList<FFMPTableRowData>();
|
||||
pfafMap = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or replace a row of cell data to the table rows collection. A row is
|
||||
* replaced if the area Id already exists.
|
||||
* Constructor.
|
||||
*/
|
||||
public FFMPTableData(int initialCapacity) {
|
||||
tableRows = new ArrayList<FFMPTableRowData>(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a row of cell data to the table rows collection.
|
||||
*
|
||||
* @param data
|
||||
* Table row data.
|
||||
*/
|
||||
public void addDataRow(FFMPTableRowData data) {
|
||||
pfafMap.put(data.getPfaf().toString(), null);
|
||||
data.setSortCallback(this);
|
||||
public synchronized void addDataRow(FFMPTableRowData data) {
|
||||
tableRows.add(data);
|
||||
}
|
||||
|
||||
public boolean containsPfaf(String pfaf) {
|
||||
return pfafMap.containsKey(pfaf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the data in a table cell.
|
||||
*
|
||||
|
|
|
@ -84,9 +84,7 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPScreenCenterEvent;
|
|||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPStreamTraceEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPTimeChangeEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPWorstCaseEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader.LOADER_TYPE;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPGraphData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPLoaderStatus;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResource;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTableDataLoader;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPTableDataUpdate;
|
||||
|
@ -121,6 +119,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* Apr 15, 2013 1904 mpduff Remove calls to reset FFMPConfig.
|
||||
* Apr 25, 2013 1902 mpduff Fixed Thresholds dialog on multiple opens, needed an isDisposed check.
|
||||
* Jun 04, 2013 #1984 lvenable removed unnecessary code.
|
||||
* Jun 06, 2013 2075 njensen Removed loading labels
|
||||
* </pre>
|
||||
*
|
||||
* @author lvenable
|
||||
|
@ -274,8 +273,6 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements
|
|||
*/
|
||||
private String previousHuc;
|
||||
|
||||
private FFMPLoaderStatus loadStatus;
|
||||
|
||||
public FfmpBasinTableDlg(Shell parent, FFMPTableData tData,
|
||||
FFMPResource resource) {
|
||||
super(parent, SWT.DIALOG_TRIM | SWT.RESIZE, CAVE.INDEPENDENT_SHELL
|
||||
|
@ -2096,47 +2093,6 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements
|
|||
allowNewTableUpdate = true;
|
||||
}
|
||||
|
||||
public void updateLoadingLabel(FFMPLoaderStatus status) {
|
||||
this.loadStatus = status;
|
||||
if (dataLoadComp == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GridData gd = (GridData) dataLoadComp.getLayoutData();
|
||||
|
||||
if (gd.exclude == true) {
|
||||
((GridData) dataLoadComp.getLayoutData()).exclude = false;
|
||||
dataLoadComp.setVisible(true);
|
||||
shell.pack();
|
||||
}
|
||||
|
||||
String prefix = null;
|
||||
|
||||
if (status.getLoaderType() == LOADER_TYPE.SECONDARY) {
|
||||
prefix = " Secondary Data Load: ";
|
||||
} else if (status.getLoaderType() == LOADER_TYPE.TERTIARY) {
|
||||
prefix = " Tertiary Data Load: ";
|
||||
} else if (status.getLoaderType() == LOADER_TYPE.GENERAL) {
|
||||
prefix = " General Data Load: ";
|
||||
} else {
|
||||
prefix = " Tertiary Data Load: ";
|
||||
}
|
||||
|
||||
if (status.isDone() == false) {
|
||||
dataLoadingLbl.setText(prefix + status.getMessage());
|
||||
dataLoadingLbl.setBackground(getDisplay().getSystemColor(
|
||||
SWT.COLOR_CYAN));
|
||||
} else {
|
||||
dataLoadingLbl.setText("");
|
||||
dataLoadingLbl.setBackground(getDisplay().getSystemColor(
|
||||
SWT.COLOR_WIDGET_BACKGROUND));
|
||||
|
||||
((GridData) dataLoadComp.getLayoutData()).exclude = true;
|
||||
dataLoadComp.setVisible(false);
|
||||
shell.pack();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
@ -2240,11 +2196,6 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements
|
|||
updateGapValueLabel(fupdateData.getGapValueLabel());
|
||||
|
||||
resetCursor();
|
||||
|
||||
// start tertiary loader if not run yet
|
||||
if (loadStatus != null) {
|
||||
resource.manageLoaders(loadStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -118,9 +118,6 @@ public class TimeDurScaleComp extends Composite {
|
|||
*/
|
||||
private double[] displayNumbers;
|
||||
|
||||
// = new double[] { 0.00, 3.00, 6.00, 9.00, 12.00, 15.00, 18.00,
|
||||
// 21.00, 24.00 };
|
||||
|
||||
/**
|
||||
* Thumb pixel index array.
|
||||
*/
|
||||
|
@ -635,8 +632,6 @@ public class TimeDurScaleComp extends Composite {
|
|||
private void setTimeDurationScale(double hourVal) {
|
||||
for (int key : indexSelHrsMap.keySet()) {
|
||||
|
||||
// TODO : remove print statements
|
||||
|
||||
if (hourVal == indexSelHrsMap.get(key)) {
|
||||
// Find an 'X' coordinate for the thumb slider.
|
||||
|
||||
|
@ -687,18 +682,8 @@ public class TimeDurScaleComp extends Composite {
|
|||
}
|
||||
|
||||
private void calcDisplayNumbers() {
|
||||
// displayNumbers = new double[] { 0.00, 3.00, 6.00, 9.00, 12.00, 15.00,
|
||||
// 18.00,
|
||||
// 21.00, 24.00 };
|
||||
|
||||
// displayNumbers = new double[] { 0.00, 3.00, 6.00, 9.00, 12.00, 15.00,
|
||||
// 18.00,
|
||||
// 23.00 };
|
||||
|
||||
double hours = validateHours(upperHourRangeVal);
|
||||
|
||||
int divisor = getDivisor(hours);
|
||||
|
||||
int hourLbls = (int) (hours / divisor);
|
||||
|
||||
// Account for the 0.00 hour label
|
||||
|
@ -717,10 +702,6 @@ public class TimeDurScaleComp extends Composite {
|
|||
displayNumbers[i] = (i * divisor);
|
||||
}
|
||||
}
|
||||
|
||||
for (double d : displayNumbers) {
|
||||
System.out.println("d = " + d);
|
||||
}
|
||||
}
|
||||
|
||||
private double validateHours(double hours) {
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package com.raytheon.uf.viz.monitor.ffmp.ui.listeners;
|
||||
|
||||
|
||||
public interface FFMPLoadListener {
|
||||
|
||||
public void loadStatus(FFMPLoaderEvent event);
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package com.raytheon.uf.viz.monitor.ffmp.ui.listeners;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPLoaderStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
* FFMP loader event updates
|
||||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* May 31, 2011 8661 dhladky Initial creation
|
||||
* </pre>
|
||||
*
|
||||
* @author dhladky
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
|
||||
public class FFMPLoaderEvent extends EventObject {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 135784L;
|
||||
|
||||
public FFMPLoaderEvent(FFMPLoaderStatus status) {
|
||||
super(status);
|
||||
}
|
||||
}
|
|
@ -44,6 +44,7 @@ import com.raytheon.uf.common.monitor.xml.SourceXML;
|
|||
* 04/15/13 1890 dhladky Changed COUNTY to use constant
|
||||
* 05/10/13 1919 mpduff If there are forced pfafs then the aggregate is forced.
|
||||
* 05/22/13 1902 mpduff Added methods to get forced values.
|
||||
* 06/17/13 2085 njensen Made forceIt() more thread safe
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -52,16 +53,9 @@ import com.raytheon.uf.common.monitor.xml.SourceXML;
|
|||
*/
|
||||
|
||||
public class FFFGForceUtil {
|
||||
private boolean forced = false;
|
||||
|
||||
private List<Long> forcedPfafList = new ArrayList<Long>();
|
||||
|
||||
private List<Long> pfafList = new ArrayList<Long>();
|
||||
|
||||
private final FFMPResource resource;
|
||||
|
||||
private String domain = "NA";
|
||||
|
||||
private SourceXML sourceXML1 = null;
|
||||
|
||||
private SourceXML sourceXML2 = null;
|
||||
|
@ -114,21 +108,24 @@ public class FFFGForceUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public void calculateForcings(String domain, FFMPTemplates ft,
|
||||
public ForceUtilResult calculateForcings(String domain, FFMPTemplates ft,
|
||||
FFMPBasin cBasin) {
|
||||
this.domain = domain;
|
||||
forceIt(ft, cBasin);
|
||||
return forceIt(ft, cBasin, null, domain);
|
||||
}
|
||||
|
||||
public void calculateForcings(List<Long> pfafList, FFMPTemplates ft,
|
||||
FFMPBasin cBasin) {
|
||||
this.pfafList = pfafList;
|
||||
forceIt(ft, cBasin);
|
||||
public ForceUtilResult calculateForcings(List<Long> pfafList,
|
||||
FFMPTemplates ft, FFMPBasin cBasin) {
|
||||
return forceIt(ft, cBasin, pfafList, "NA");
|
||||
}
|
||||
|
||||
private void forceIt(FFMPTemplates ft, FFMPBasin cBasin) {
|
||||
private ForceUtilResult forceIt(FFMPTemplates ft, FFMPBasin cBasin,
|
||||
List<Long> pfafList, String domain) {
|
||||
boolean forced = false;
|
||||
List<Long> forcedPfafList = new ArrayList<Long>();
|
||||
ForceUtilResult retVal = new ForceUtilResult(forced, pfafList,
|
||||
forcedPfafList);
|
||||
if (interp == null) {
|
||||
return;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
if (domain == null) {
|
||||
|
@ -215,6 +212,11 @@ public class FFFGForceUtil {
|
|||
forced = true;
|
||||
}
|
||||
}
|
||||
|
||||
retVal.forced = forced;
|
||||
retVal.pfafList = pfafList;
|
||||
retVal.forcedPfafList = forcedPfafList;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private ArrayList<Long> getForcedBasins(String source,
|
||||
|
@ -312,43 +314,6 @@ public class FFFGForceUtil {
|
|||
return Float.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the forced
|
||||
*/
|
||||
public boolean isForced() {
|
||||
return forced;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forced
|
||||
* the forced to set
|
||||
*/
|
||||
public void setForced(boolean forced) {
|
||||
this.forced = forced;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the forcedPfafList
|
||||
*/
|
||||
public List<Long> getForcedPfafList() {
|
||||
return forcedPfafList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forcedPfafList
|
||||
* the forcedPfafList to set
|
||||
*/
|
||||
public void setForcedPfafList(ArrayList<Long> forcedPfafList) {
|
||||
this.forcedPfafList = forcedPfafList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pfafList
|
||||
*/
|
||||
public List<Long> getPfafList() {
|
||||
return pfafList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sliderTime
|
||||
* the sliderTime to set
|
||||
|
|
|
@ -52,6 +52,7 @@ import com.raytheon.viz.core.style.image.ImagePreferences;
|
|||
* 08/29/09 2152 D. Hladky Initial release
|
||||
* 05/21/12 DR 14833 G. Zhang Error handling for invalid cmap
|
||||
* Apr 26, 2013 1954 bsteffen Minor code cleanup throughout FFMP.
|
||||
* Jun 10, 2013 2075 njensen Improved init time
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -69,16 +70,14 @@ public class FFMPColorUtils {
|
|||
|
||||
private double time = 0.0;
|
||||
|
||||
private ArrayList<String> fileArray = new ArrayList<String>();
|
||||
private TreeMap<Double, String> hourColorMapMap = new TreeMap<Double, String>();
|
||||
|
||||
private TreeMap<Double, String> hourColorMapMap = new TreeMap<Double, String>();
|
||||
|
||||
// DR 14833: replacing the one in the constructor
|
||||
private StyleRule sr = null;
|
||||
|
||||
|
||||
// DR 14833: used when no colormap found
|
||||
private static final String DEFAULT_COLORMAP = "ffmp/qpe";
|
||||
|
||||
private static final String DEFAULT_COLORMAP = "ffmp/qpe";
|
||||
|
||||
// DR 14833: used when paramname not matching colormap name found
|
||||
private static final String DEFAULT_PARAMNAME = "qpe";
|
||||
|
||||
|
@ -96,18 +95,7 @@ public class FFMPColorUtils {
|
|||
this.tableLoad = tableLoad;
|
||||
this.colormapparams = null;
|
||||
|
||||
// LocalizationFile[] files = ColorMapLoader.listColorMapFiles();
|
||||
// for (LocalizationFile file : files) {
|
||||
// String fn = file.getName();
|
||||
// if (fn.startsWith("colormaps/ffmp/qpe"))
|
||||
// {
|
||||
// System.out.println(file.getName());
|
||||
// String hour = fn.s
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
// StyleRule sr = null;// DR 14833 replaced by a instance field
|
||||
// StyleRule sr = null;// DR 14833 replaced by a instance field
|
||||
try {
|
||||
sr = StyleManager.getInstance().getStyleRule(
|
||||
StyleManager.StyleType.IMAGERY, getMatchCriteria());
|
||||
|
@ -125,7 +113,8 @@ public class FFMPColorUtils {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if(cxml == null) cxml = getDefaultColorMap(); // DR 14833: load the default map
|
||||
if (cxml == null)
|
||||
cxml = getDefaultColorMap(); // DR 14833: load the default map
|
||||
ColorMap colorMap = new ColorMap(colormapfile, (ColorMap) cxml);
|
||||
colormapparams = new ColorMapParameters();
|
||||
colormapparams.setColorMap(colorMap);
|
||||
|
@ -188,16 +177,15 @@ public class FFMPColorUtils {
|
|||
|
||||
double value = (Math.round(valueArg * 100.0)) / 100.0;
|
||||
|
||||
|
||||
if (field == FIELDS.DIFF) {
|
||||
Color color = colormapparams.getColorByValue((float) value);
|
||||
rgb = convert(color);
|
||||
return rgb;
|
||||
|
||||
} else if (value >= 0.005) {
|
||||
Color color = colormapparams.getColorByValue((float) value);
|
||||
rgb = convert(color);
|
||||
return rgb;
|
||||
Color color = colormapparams.getColorByValue((float) value);
|
||||
rgb = convert(color);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
List<Color> colors = getColorMap().getColors();
|
||||
|
@ -255,14 +243,13 @@ public class FFMPColorUtils {
|
|||
}
|
||||
|
||||
private String determineQpeToUse(double time) {
|
||||
getQpeColorMapFiles();
|
||||
parseFileNames();
|
||||
parseFileNames(getQpeColorMapFiles());
|
||||
String qpeHourToUse = determineColorMap(time);
|
||||
|
||||
return qpeHourToUse;
|
||||
}
|
||||
|
||||
private void parseFileNames() {
|
||||
private void parseFileNames(List<String> fileArray) {
|
||||
double hour = 0.0;
|
||||
for (String fn : fileArray) {
|
||||
hour = 0.0;
|
||||
|
@ -327,80 +314,89 @@ public class FFMPColorUtils {
|
|||
return qpeHourToUse;
|
||||
}
|
||||
|
||||
private void getQpeColorMapFiles() {
|
||||
LocalizationFile[] files = ColorMapLoader.listColorMapFiles();
|
||||
private List<String> getQpeColorMapFiles() {
|
||||
List<String> colormaps = new ArrayList<String>();
|
||||
LocalizationFile[] files = ColorMapLoader.listColorMapFiles("ffmp");
|
||||
for (LocalizationFile file : files) {
|
||||
String fn = file.getName();
|
||||
if (fn.indexOf("ffmp/qpe") > 0) {
|
||||
fileArray.add(fn);
|
||||
if (fn.indexOf("qpe") > 0) {
|
||||
colormaps.add(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return colormaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* DR 14833: Error handling for the following:
|
||||
* when a user modified the ffmpImageryStyleRules.xml file
|
||||
* without adding the related qpeX.cmap and for a user made
|
||||
* error like: qpe6/qpe4.cmap then default qpe/qpe.cmap used.
|
||||
* DR 14833: Error handling for the following: when a user modified the
|
||||
* ffmpImageryStyleRules.xml file without adding the related qpeX.cmap and
|
||||
* for a user made error like: qpe6/qpe4.cmap then default qpe/qpe.cmap
|
||||
* used.
|
||||
*
|
||||
*/
|
||||
public IColorMap getDefaultColorMap(){
|
||||
IColorMap cxml = null;
|
||||
|
||||
/*see parseFileNames(): colormap_name is "0.0" or qpe+key+".cmap"
|
||||
double hour = hourColorMapMap.firstKey();
|
||||
String cmapHour = ( hour==0.0 ? "" : String.valueOf(hour) );
|
||||
System.out.println("FFMPColorUtils.getDefaultColorMap() cmapHour: "+cmapHour );*/
|
||||
*/
|
||||
public IColorMap getDefaultColorMap() {
|
||||
IColorMap cxml = null;
|
||||
|
||||
/* Loop through all StyleRules to get the default.
|
||||
* In StyleManager.loadRules(StyleType), all levels(not only USER)
|
||||
* StyleRule loaded. So it is guaranteed the default can be loaded.
|
||||
*/
|
||||
|
||||
com.raytheon.uf.viz.core.style.StyleRuleset srs =
|
||||
StyleManager.getInstance().getStyleRuleSet(StyleManager.StyleType.IMAGERY);
|
||||
|
||||
for(StyleRule srl : srs.getStyleRules()){
|
||||
String pn="", cm="";
|
||||
try{
|
||||
pn = ((ParamLevelMatchCriteria)srl.getMatchCriteria()).getParameterNames().get(0);
|
||||
cm = ((ImagePreferences)srl.getPreferences()).getDefaultColormap();
|
||||
}catch(Exception e){ continue; }
|
||||
|
||||
if(DEFAULT_PARAMNAME.equalsIgnoreCase(pn) && DEFAULT_COLORMAP.equalsIgnoreCase(cm)){
|
||||
sr = srl;
|
||||
System.out.println("FFMPColorUtils.getDefaultColorMap(): StyleRule pn-cm value: "+pn+"-"+cm);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
if(sr == null){
|
||||
//get the MatchCriteria
|
||||
ParamLevelMatchCriteria match = new ParamLevelMatchCriteria();
|
||||
ArrayList<String> paramList = new ArrayList<String>();
|
||||
paramList.add( FIELDS.QPE.getFieldName()+cmapHour );
|
||||
match.setParameterName(paramList);
|
||||
|
||||
//get the StyleRule
|
||||
try {
|
||||
sr=StyleManager.getInstance().getStyleRule(StyleManager.StyleType.IMAGERY, match);
|
||||
} catch (VizStyleException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
*/
|
||||
//get the colormapfile name
|
||||
String colormapfile = ((ImagePreferences) sr.getPreferences()).getDefaultColormap();
|
||||
/*
|
||||
* see parseFileNames(): colormap_name is "0.0" or qpe+key+".cmap"
|
||||
* double hour = hourColorMapMap.firstKey(); String cmapHour = (
|
||||
* hour==0.0 ? "" : String.valueOf(hour) );
|
||||
* System.out.println("FFMPColorUtils.getDefaultColorMap() cmapHour: "
|
||||
* +cmapHour );
|
||||
*/
|
||||
|
||||
//load the colormap
|
||||
/*
|
||||
* Loop through all StyleRules to get the default. In
|
||||
* StyleManager.loadRules(StyleType), all levels(not only USER)
|
||||
* StyleRule loaded. So it is guaranteed the default can be loaded.
|
||||
*/
|
||||
|
||||
com.raytheon.uf.viz.core.style.StyleRuleset srs = StyleManager
|
||||
.getInstance().getStyleRuleSet(StyleManager.StyleType.IMAGERY);
|
||||
|
||||
for (StyleRule srl : srs.getStyleRules()) {
|
||||
String pn = "", cm = "";
|
||||
try {
|
||||
pn = ((ParamLevelMatchCriteria) srl.getMatchCriteria())
|
||||
.getParameterNames().get(0);
|
||||
cm = ((ImagePreferences) srl.getPreferences())
|
||||
.getDefaultColormap();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DEFAULT_PARAMNAME.equalsIgnoreCase(pn)
|
||||
&& DEFAULT_COLORMAP.equalsIgnoreCase(cm)) {
|
||||
sr = srl;
|
||||
System.out
|
||||
.println("FFMPColorUtils.getDefaultColorMap(): StyleRule pn-cm value: "
|
||||
+ pn + "-" + cm);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* if(sr == null){ //get the MatchCriteria ParamLevelMatchCriteria match
|
||||
* = new ParamLevelMatchCriteria(); ArrayList<String> paramList = new
|
||||
* ArrayList<String>(); paramList.add(
|
||||
* FIELDS.QPE.getFieldName()+cmapHour );
|
||||
* match.setParameterName(paramList);
|
||||
*
|
||||
* //get the StyleRule try {
|
||||
* sr=StyleManager.getInstance().getStyleRule(StyleManager
|
||||
* .StyleType.IMAGERY, match); } catch (VizStyleException e) {
|
||||
* e.printStackTrace(); } }
|
||||
*/
|
||||
// get the colormapfile name
|
||||
String colormapfile = ((ImagePreferences) sr.getPreferences())
|
||||
.getDefaultColormap();
|
||||
|
||||
// load the colormap
|
||||
try {
|
||||
cxml = ColorMapLoader.loadColorMap(colormapfile);
|
||||
} catch (VizException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return cxml;
|
||||
|
||||
return cxml;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,24 +19,20 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.monitor.ffmp.ui.rsc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasin;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinData;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinMetaData;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPGuidanceBasin;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPGuidanceInterpolation;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord.FIELDS;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPTemplates;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPUtils;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPVirtualGageBasin;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPVirtualGageBasinMetaData;
|
||||
import com.raytheon.uf.common.monitor.config.FFFGDataMgr;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.DomainXML;
|
||||
|
@ -48,11 +44,10 @@ import com.raytheon.uf.common.status.UFStatus;
|
|||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.jobs.JobPool;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.FFMPMonitor;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableCellData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableRowData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfig;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData;
|
||||
|
||||
|
@ -80,6 +75,8 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData;
|
|||
* May 07, 2013 1986 njensen Removed unnecessary sort
|
||||
* May 10, 2013 1919 mpduff Fixed problem with VGBs
|
||||
* May 22, 2013 1902 mpduff Code cleanup.
|
||||
* Jun 11, 2013 2085 njensen Extracted row creation to FFMPRowGenerator and
|
||||
* multi-threaded row creation.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -93,51 +90,50 @@ public class FFMPDataGenerator {
|
|||
private static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FFMPDataGenerator.class);
|
||||
|
||||
private static final String ALL = FFMPRecord.ALL;
|
||||
protected final String siteKey;
|
||||
|
||||
private static final String NA = "NA";
|
||||
protected final Date paintRefTime;
|
||||
|
||||
private final String siteKey;
|
||||
protected final Object centeredAggregationKey;
|
||||
|
||||
private final Date paintRefTime;
|
||||
protected final String huc;
|
||||
|
||||
private final Object centeredAggregationKey;
|
||||
protected final double sliderTime;
|
||||
|
||||
private final String huc;
|
||||
protected boolean isWorstCase = false;
|
||||
|
||||
private final double sliderTime;
|
||||
protected FFMPTemplates ft = null;
|
||||
|
||||
private boolean isWorstCase = false;
|
||||
protected FFMPResource resource = null;
|
||||
|
||||
private FFMPTemplates ft = null;
|
||||
protected FFMPMonitor monitor = null;
|
||||
|
||||
private FFMPResource resource = null;
|
||||
protected FFMPBasinData qpeBasin = null;
|
||||
|
||||
private FFMPMonitor monitor = null;
|
||||
protected FFMPBasinData qpfBasin = null;
|
||||
|
||||
private FFMPBasinData qpeBasin = null;
|
||||
protected FFMPBasinData rateBasin = null;
|
||||
|
||||
private FFMPBasinData qpfBasin = null;
|
||||
protected Map<String, FFMPBasinData> guidBasins = null;
|
||||
|
||||
private FFMPBasinData rateBasin = null;
|
||||
protected FFMPBasinData virtualBasin = null;
|
||||
|
||||
private Map<String, FFMPBasinData> guidBasins = null;
|
||||
protected Map<String, FFMPRecord> guidRecords = null;
|
||||
|
||||
private FFMPBasinData virtualBasin = null;
|
||||
protected FFMPRecord baseRec = null;
|
||||
|
||||
private Map<String, FFMPRecord> guidRecords = null;
|
||||
protected boolean isRate = false;
|
||||
|
||||
private FFMPRecord baseRec = null;
|
||||
protected long expirationTime = 0l;
|
||||
|
||||
private boolean isRate = false;
|
||||
protected String[] cwaArr = null;
|
||||
|
||||
private long expirationTime = 0l;
|
||||
protected Map<String, FFFGForceUtil> forceUtils = null;
|
||||
|
||||
private String[] cwaArr = null;
|
||||
protected FfmpTableConfigData ffmpTableCfgData = null;
|
||||
|
||||
private Map<String, FFFGForceUtil> forceUtils = null;
|
||||
|
||||
private FfmpTableConfigData ffmpTableCfgData = null;
|
||||
private JobPool jobPool = new JobPool("Table Data Generation", 3, true,
|
||||
Job.INTERACTIVE);
|
||||
|
||||
public FFMPDataGenerator(FFMPMonitor monitor, FFMPResource resource) {
|
||||
siteKey = resource.getSiteKey();
|
||||
|
@ -171,7 +167,6 @@ public class FFMPDataGenerator {
|
|||
|
||||
// update the FFFGDataManager
|
||||
FFFGDataMgr.getUpdatedInstance();
|
||||
tData = new FFMPTableData();
|
||||
|
||||
try {
|
||||
FIELDS field = getBaseField();
|
||||
|
@ -181,18 +176,20 @@ public class FFMPDataGenerator {
|
|||
}
|
||||
FFMPBasinData fbd = null;
|
||||
if (centeredAggregationKey != null) {
|
||||
fbd = baseRec.getBasinData(ALL);
|
||||
fbd = baseRec.getBasinData(FFMPRecord.ALL);
|
||||
} else {
|
||||
fbd = baseRec.getBasinData(huc);
|
||||
}
|
||||
|
||||
tData = new FFMPTableData(fbd.getBasins().size());
|
||||
List<DomainXML> domains = resource.getDomains();
|
||||
if (!fbd.getBasins().isEmpty()) {
|
||||
if ((centeredAggregationKey == null) || huc.equals(ALL)) {
|
||||
if ((centeredAggregationKey == null)
|
||||
|| huc.equals(FFMPRecord.ALL)) {
|
||||
// System.out.println(fbd.getBasins().keySet().size()
|
||||
// + " rows in the table");
|
||||
for (Long key : fbd.getBasins().keySet()) {
|
||||
if (huc.equals(ALL)) {
|
||||
if (huc.equals(FFMPRecord.ALL)) {
|
||||
FFMPBasinMetaData fmdb = ft.getBasin(siteKey, key);
|
||||
if (fmdb == null) {
|
||||
continue;
|
||||
|
@ -307,689 +304,20 @@ public class FFMPDataGenerator {
|
|||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Failed to load FFMP table data!", e);
|
||||
}
|
||||
|
||||
// wait for all the rows to finish being created before continuing on
|
||||
long t0 = System.currentTimeMillis();
|
||||
jobPool.join();
|
||||
System.out.println("Waited on FFMP job pool for: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
return tData;
|
||||
}
|
||||
|
||||
private void setFFMPRow(FFMPBasin cBasin, FFMPTableData tData,
|
||||
boolean isVGB, String domain) {
|
||||
try {
|
||||
String pfafToTest = null;
|
||||
if (cBasin instanceof FFMPVirtualGageBasin) {
|
||||
pfafToTest = ((FFMPVirtualGageBasin) cBasin).getLid();
|
||||
} else {
|
||||
pfafToTest = cBasin.getPfaf().toString();
|
||||
}
|
||||
if (tData.containsPfaf(pfafToTest)) {
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
|
||||
String displayName = "";
|
||||
String mouseOverText = "";
|
||||
|
||||
FFMPTableRowData trd = new FFMPTableRowData(
|
||||
ffmpTableCfgData.getTableColumnKeys().length);
|
||||
|
||||
Float guidance = Float.NaN;
|
||||
Float qpe = Float.NaN;
|
||||
Float rate = Float.NaN;
|
||||
Float qpf = Float.NaN;
|
||||
FIELDS rowField = FIELDS.NAME;
|
||||
|
||||
if (isVGB) {
|
||||
rowField = FIELDS.VIRTUAL;
|
||||
}
|
||||
|
||||
if (cBasin instanceof FFMPVirtualGageBasin) {
|
||||
rowField = FIELDS.VIRTUAL;
|
||||
|
||||
FFMPVirtualGageBasin vgBasin = (FFMPVirtualGageBasin) cBasin;
|
||||
|
||||
String lid = vgBasin.getLid();
|
||||
|
||||
if (lid != null) {
|
||||
StringBuilder sb = new StringBuilder(lid);
|
||||
// in this special case it is actually the LID
|
||||
trd.setPfaf(lid);
|
||||
FFMPVirtualGageBasinMetaData fvgmbd = ft
|
||||
.getVirtualGageBasinMetaData(siteKey, lid);
|
||||
FFMPBasinMetaData metabasin = ft.getBasin(siteKey,
|
||||
fvgmbd.getParentPfaf());
|
||||
Long parentBasinPfaf = fvgmbd.getParentPfaf();
|
||||
|
||||
mouseOverText = metabasin.getBasinId() + "\n" + lid + "-"
|
||||
+ fvgmbd.getName();
|
||||
|
||||
if (!huc.equals(ALL)) {
|
||||
sb.append("-").append(fvgmbd.getName());
|
||||
}
|
||||
|
||||
trd.setTableCellData(0,
|
||||
new FFMPTableCellData(rowField, sb.toString(),
|
||||
mouseOverText));
|
||||
|
||||
if (!isWorstCase || huc.equals(ALL)
|
||||
|| (centeredAggregationKey != null)) {
|
||||
|
||||
if (!cBasin.getValues().isEmpty()) {
|
||||
rate = vgBasin.getValue(paintRefTime);
|
||||
if (sliderTime > 0.00) {
|
||||
FFMPTimeWindow window = monitor.getQpeWindow();
|
||||
qpe = cBasin.getAccumValue(window.getAfterTime(),
|
||||
window.getBeforeTime(), expirationTime,
|
||||
isRate);
|
||||
} else {
|
||||
qpe = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(1, new FFMPTableCellData(FIELDS.RATE,
|
||||
rate));
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE,
|
||||
qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
FFMPBasin basin = qpfBasin.get(parentBasinPfaf);
|
||||
if (basin != null) {
|
||||
FFMPTimeWindow window = monitor.getQpfWindow();
|
||||
qpf = basin.getAverageValue(window.getAfterTime(),
|
||||
window.getBeforeTime());
|
||||
}
|
||||
}
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF,
|
||||
qpf));
|
||||
|
||||
// run over each guidance type
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
|
||||
FFMPTableCellData guidCellData = getGuidanceCellData(
|
||||
cBasin, domain, guidType, parentBasinPfaf);
|
||||
if (guidCellData == null) {
|
||||
// check for forcing even if no data are available
|
||||
guidance = getForcedAvg(domain, cBasin, guidType);
|
||||
boolean forced = !guidance.isNaN();
|
||||
guidCellData = new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced);
|
||||
} else {
|
||||
guidance = guidCellData.getValueAsFloat();
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, guidCellData);
|
||||
|
||||
float ratioValue = Float.NaN;
|
||||
float diffValue = Float.NaN;
|
||||
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
|
||||
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, diffValue));
|
||||
i += 3;
|
||||
}
|
||||
} else {
|
||||
trd = getMaxValue(trd, cBasin);
|
||||
}
|
||||
|
||||
tData.addDataRow(trd);
|
||||
}
|
||||
} else {
|
||||
displayName = getDisplayName(cBasin);
|
||||
if (displayName != null) {
|
||||
long cBasinPfaf = cBasin.getPfaf();
|
||||
String cBasinPfafStr = Long.toString(cBasinPfaf);
|
||||
StringBuilder sb = new StringBuilder(cBasinPfafStr);
|
||||
sb.append("\n").append(displayName);
|
||||
trd.setPfaf(cBasinPfafStr);
|
||||
trd.setTableCellData(0, new FFMPTableCellData(rowField,
|
||||
displayName, sb.toString()));
|
||||
|
||||
if (!isWorstCase || huc.equals(ALL)
|
||||
|| (centeredAggregationKey != null)) {
|
||||
if (rateBasin != null) {
|
||||
FFMPBasin basin = rateBasin.get(cBasinPfaf);
|
||||
if (basin != null) {
|
||||
rate = basin.getValue(paintRefTime);
|
||||
}
|
||||
}
|
||||
trd.setTableCellData(1, new FFMPTableCellData(FIELDS.RATE,
|
||||
rate));
|
||||
|
||||
if (qpeBasin != null) {
|
||||
FFMPBasin basin = qpeBasin.get(cBasinPfaf);
|
||||
if (basin != null) {
|
||||
FFMPTimeWindow window = monitor.getQpeWindow();
|
||||
qpe = basin.getAccumValue(window.getAfterTime(),
|
||||
window.getBeforeTime(), expirationTime,
|
||||
isRate);
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE,
|
||||
qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
FFMPBasin basin = qpfBasin.get(cBasinPfaf);
|
||||
if (basin != null) {
|
||||
FFMPTimeWindow window = monitor.getQpfWindow();
|
||||
qpf = basin.getAverageValue(window.getAfterTime(),
|
||||
window.getBeforeTime());
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF,
|
||||
qpf));
|
||||
|
||||
// run over each guidance type
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
FFMPTableCellData guidCellData = getGuidanceCellData(
|
||||
cBasin, domain, guidType, cBasinPfaf);
|
||||
if (guidCellData == null) {
|
||||
// check for forcing even if no data are available
|
||||
guidance = getForcedAvg(domain, cBasin, guidType);
|
||||
boolean forced = !guidance.isNaN();
|
||||
guidCellData = new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced);
|
||||
} else {
|
||||
guidance = guidCellData.getValueAsFloat();
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, guidCellData);
|
||||
|
||||
float ratioValue = Float.NaN;
|
||||
float diffValue = Float.NaN;
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
|
||||
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, diffValue));
|
||||
|
||||
i += 3;
|
||||
}
|
||||
} else {
|
||||
trd = getMaxValue(trd, cBasin);
|
||||
}
|
||||
|
||||
tData.addDataRow(trd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FFMPTableCellData getGuidanceCellData(FFMPBasin cBasin,
|
||||
String domain, String guidType, Long parentBasinPfaf) {
|
||||
long cBasinPfaf = cBasin.getPfaf();
|
||||
|
||||
FFMPBasinData guidBasin = guidBasins.get(guidType);
|
||||
|
||||
FFMPGuidanceBasin ffmpGuidBasin = null;
|
||||
if (guidBasin != null) {
|
||||
ffmpGuidBasin = (FFMPGuidanceBasin) guidBasin.get(cBasinPfaf);
|
||||
}
|
||||
|
||||
if (ffmpGuidBasin == null) {
|
||||
return null;
|
||||
}
|
||||
List<Long> pfafList = Collections.emptyList();
|
||||
List<Long> forcedPfafs = Collections.emptyList();
|
||||
boolean forced = false;
|
||||
Float guidance = Float.NaN;
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
// If aggregate, get basins within the aggregate
|
||||
if (cBasin.getAggregated()) {
|
||||
if (domain == null) {
|
||||
pfafList = ft.getAggregatePfafs(cBasinPfaf, siteKey, huc);
|
||||
} else if (!domain.equals(NA)) {
|
||||
if (!huc.equals(ALL)) {
|
||||
pfafList = ft.getAggregatePfafsByDomain(parentBasinPfaf,
|
||||
siteKey, domain, huc);
|
||||
}
|
||||
} else {
|
||||
pfafList = ft.getAggregatePfafsByDomain(parentBasinPfaf,
|
||||
siteKey, domain, huc);
|
||||
pfafList.add(ft.getAggregatedPfaf(cBasinPfaf, siteKey, huc));
|
||||
}
|
||||
} else {
|
||||
pfafList = new ArrayList<Long>();
|
||||
pfafList.add(cBasinPfaf);
|
||||
}
|
||||
|
||||
if (FFFGDataMgr.getInstance().isForcingConfigured()) {
|
||||
FFMPBasin parentBasin = cBasin;
|
||||
if (cBasinPfaf != parentBasinPfaf.longValue()) {
|
||||
parentBasin = baseRec.getBasinData(ALL).get(parentBasinPfaf);
|
||||
}
|
||||
forceUtil.calculateForcings(domain, ft, parentBasin);
|
||||
forcedPfafs = forceUtil.getForcedPfafList();
|
||||
forced = forceUtil.isForced();
|
||||
}
|
||||
|
||||
if (!forcedPfafs.isEmpty() || forced || !pfafList.isEmpty()) {
|
||||
// Recalculate guidance using the forced value(s)
|
||||
guidance = guidRecords
|
||||
.get(guidType)
|
||||
.getBasinData(ALL)
|
||||
.getAverageGuidanceValue(pfafList,
|
||||
resource.getGuidanceInterpolators().get(guidType),
|
||||
guidance, forcedPfafs,
|
||||
resource.getGuidSourceExpiration(guidType));
|
||||
} else {
|
||||
if (ffmpGuidBasin != null) {
|
||||
guidance = resource.getGuidanceValue(ffmpGuidBasin,
|
||||
paintRefTime, guidType);
|
||||
|
||||
if (guidance < 0.0f) {
|
||||
guidance = Float.NaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new FFMPTableCellData(FIELDS.GUIDANCE, guidance, forced);
|
||||
}
|
||||
|
||||
private float getForcedAvg(String domain, FFMPBasin cBasin, String guidType) {
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
FFFGDataMgr fdm = FFFGDataMgr.getInstance();
|
||||
List<Long> forcedPfafs;
|
||||
List<Long> pfafList = new ArrayList<Long>();
|
||||
float guidance = Float.NaN;
|
||||
|
||||
boolean forced = false;
|
||||
if (fdm.isForcingConfigured()) {
|
||||
forceUtil.calculateForcings(domain, ft, cBasin);
|
||||
forcedPfafs = forceUtil.getForcedPfafList();
|
||||
forced = forceUtil.isForced();
|
||||
if (!forced) {
|
||||
return Float.NaN;
|
||||
}
|
||||
} else {
|
||||
return Float.NaN;
|
||||
}
|
||||
|
||||
if (cBasin.getAggregated()) {
|
||||
if (domain == null) {
|
||||
pfafList = ft.getAggregatePfafs(cBasin.getPfaf(), siteKey, huc);
|
||||
} else if (!domain.equals(NA)) {
|
||||
if (!huc.equals(ALL)) {
|
||||
pfafList = ft.getAggregatePfafsByDomain(cBasin.getPfaf(),
|
||||
siteKey, domain, huc);
|
||||
}
|
||||
} else {
|
||||
pfafList = ft.getAggregatePfafsByDomain(cBasin.getPfaf(),
|
||||
siteKey, domain, huc);
|
||||
pfafList.add(ft.getAggregatedPfaf(cBasin.getPfaf(), siteKey,
|
||||
huc));
|
||||
}
|
||||
}
|
||||
|
||||
if (!isWorstCase || huc.equals(ALL) || (centeredAggregationKey != null)) {
|
||||
if (((forcedPfafs.size() > 1)) || forced) {
|
||||
// Calculate an average
|
||||
guidance = forceUtil.getAvgForcedValue(pfafList, forcedPfafs,
|
||||
resource.getGuidanceInterpolators().get(guidType),
|
||||
resource.getGuidSourceExpiration(guidType), ft);
|
||||
}
|
||||
} else {
|
||||
// TODO Calculate a max value
|
||||
|
||||
}
|
||||
|
||||
return guidance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regular basin display name
|
||||
*
|
||||
* @param basin
|
||||
* @return
|
||||
*/
|
||||
private String getDisplayName(FFMPBasin basin) {
|
||||
String name = null;
|
||||
|
||||
try {
|
||||
if (huc.equals(ALL) || (centeredAggregationKey != null)) {
|
||||
name = ft.getBasin(siteKey, basin.getPfaf()).getStreamName();
|
||||
}
|
||||
// aggregations
|
||||
else {
|
||||
|
||||
ArrayList<Long> pfafs = ft.getAggregatePfafs(basin.getPfaf(),
|
||||
siteKey, huc);
|
||||
if (!pfafs.isEmpty()) {
|
||||
if (huc.equals(FFMPRecord.COUNTY)) {
|
||||
name = ft.getCountyStateName(siteKey, basin.getPfaf());
|
||||
} else {
|
||||
for (int i = 0; i < pfafs.size(); i++) {
|
||||
if (ft.getBasin(siteKey, pfafs.get(0)).getHucName() != null) {
|
||||
name = ft.getBasin(siteKey, pfafs.get(0))
|
||||
.getHucName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.WARN, "No display name for basin.."
|
||||
+ basin.getPfaf());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private FFMPTableRowData getMaxValue(FFMPTableRowData trd, FFMPBasin cBasin) {
|
||||
ArrayList<DomainXML> domainList = FFMPRunConfigurationManager
|
||||
.getInstance().getDomains();
|
||||
ArrayList<DomainXML> activeDomains = new ArrayList<DomainXML>();
|
||||
for (DomainXML domainXml : domainList) {
|
||||
for (String cwa : cwaArr) {
|
||||
if (domainXml.getCwa().equalsIgnoreCase(cwa)) {
|
||||
activeDomains.add(domainXml);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Long> pfafs = ft.getAggregatePfafs(cBasin.getPfaf(), siteKey,
|
||||
huc, activeDomains);
|
||||
trd.setPfaf(cBasin.getPfaf().toString());
|
||||
Float qpe = Float.NaN;
|
||||
Float guidance = Float.NaN;
|
||||
Float rate = Float.NaN;
|
||||
Float qpf = Float.NaN;
|
||||
Float ratioValue = Float.NaN;
|
||||
Float diffValue = Float.NaN;
|
||||
|
||||
if (cBasin instanceof FFMPVirtualGageBasin) {
|
||||
if (!pfafs.isEmpty()) {
|
||||
if (virtualBasin != null) {
|
||||
rate = virtualBasin.get(cBasin.getPfaf()).getValue(
|
||||
paintRefTime);
|
||||
|
||||
if (sliderTime > 0.00) {
|
||||
qpe = virtualBasin.get(cBasin.getPfaf()).getAccumValue(
|
||||
monitor.getQpeWindow().getAfterTime(),
|
||||
monitor.getQpeWindow().getBeforeTime(),
|
||||
expirationTime, isRate);
|
||||
} else {
|
||||
qpe = 0.0f;
|
||||
}
|
||||
}
|
||||
trd.setTableCellData(1,
|
||||
new FFMPTableCellData(FIELDS.RATE, rate));
|
||||
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
qpf = new Float(qpfBasin.get(cBasin.getPfaf()).getMaxValue(
|
||||
monitor.getQpfWindow().getAfterTime(),
|
||||
monitor.getQpfWindow().getBeforeTime()))
|
||||
.floatValue();
|
||||
}
|
||||
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF, qpf));
|
||||
|
||||
processGuidance(trd, cBasin, pfafs, qpe);
|
||||
}
|
||||
} else {
|
||||
// Not Virtual
|
||||
if (!pfafs.isEmpty()) {
|
||||
if (rateBasin != null) {
|
||||
rate = rateBasin.getMaxValue(pfafs, paintRefTime);
|
||||
}
|
||||
trd.setTableCellData(1,
|
||||
new FFMPTableCellData(FIELDS.RATE, rate));
|
||||
|
||||
if (qpeBasin != null) {
|
||||
qpe = qpeBasin.getAccumMaxValue(pfafs, monitor
|
||||
.getQpeWindow().getBeforeTime(), monitor
|
||||
.getQpeWindow().getAfterTime(), expirationTime,
|
||||
isRate);
|
||||
}
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
qpf = qpfBasin.getAverageMaxValue(pfafs, monitor
|
||||
.getQpfWindow().getAfterTime(), monitor
|
||||
.getQpfWindow().getBeforeTime());
|
||||
|
||||
// qpf = getQPFValue(true, new Long(0l), pfafs);/* DR13839
|
||||
// */
|
||||
}
|
||||
trd.setTableCellData(3,
|
||||
new FFMPTableCellData(FIELDS.QPF, qpf.floatValue()));
|
||||
|
||||
// run over each guidance type
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
diffValue = Float.NaN;
|
||||
ratioValue = Float.NaN;
|
||||
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
FFMPBasinData guidBasin = guidBasins.get(guidType);
|
||||
|
||||
List<Long> pfafList = new ArrayList<Long>();
|
||||
if (cBasin.getAggregated()) {
|
||||
pfafList = ft.getAggregatePfafs(cBasin.getPfaf(),
|
||||
siteKey, huc);
|
||||
pfafList.add(ft.getAggregatedPfaf(cBasin.getPfaf(),
|
||||
siteKey, huc));
|
||||
}
|
||||
|
||||
boolean forced = false;
|
||||
List<Long> forcedPfafs = new ArrayList<Long>();
|
||||
FFFGDataMgr fdm = FFFGDataMgr.getInstance();
|
||||
|
||||
if (fdm.isForcingConfigured()) {
|
||||
forceUtil.calculateForcings(pfafList, ft, cBasin);
|
||||
forcedPfafs = forceUtil.getForcedPfafList();
|
||||
forced = forceUtil.isForced();
|
||||
}
|
||||
|
||||
if (!forced) {
|
||||
if ((forcedPfafs != null) && (!forcedPfafs.isEmpty())) {
|
||||
forced = true;
|
||||
}
|
||||
}
|
||||
if ((guidBasin != null)
|
||||
&& (!guidBasin.getBasins().isEmpty())) {
|
||||
|
||||
if (isWorstCase) {
|
||||
guidance = guidRecords
|
||||
.get(guidType)
|
||||
.getBasinData(ALL)
|
||||
.getMaxGuidanceValue(
|
||||
pfafs,
|
||||
resource.getGuidanceInterpolators()
|
||||
.get(guidType),
|
||||
resource.getGuidSourceExpiration(guidType),
|
||||
cBasin.getPfaf());
|
||||
} else {
|
||||
FFMPGuidanceBasin basin = (FFMPGuidanceBasin) guidRecords
|
||||
.get(guidType).getBasinData(huc)
|
||||
.get(cBasin.getPfaf());
|
||||
guidance = resource.getGuidanceValue(basin, monitor
|
||||
.getQpeWindow().getBeforeTime(), guidType);
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced));
|
||||
} else {
|
||||
if (forced) {
|
||||
// Recalculate guidance using the forced value(s)
|
||||
guidance = forceUtil.getMaxForcedValue(
|
||||
pfafList,
|
||||
forcedPfafs,
|
||||
resource.getGuidanceInterpolators().get(
|
||||
guidType), resource
|
||||
.getGuidSourceExpiration(guidType),
|
||||
ft);
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced));
|
||||
}
|
||||
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
|
||||
List<Float> qpes = qpeBasin.getAccumValues(pfafs,
|
||||
monitor.getQpeWindow().getAfterTime(), monitor
|
||||
.getQpeWindow().getBeforeTime(),
|
||||
expirationTime, isRate);
|
||||
List<Float> guids = null;
|
||||
if (guidBasin != null) {
|
||||
guids = guidBasin.getGuidanceValues(pfafs, resource
|
||||
.getGuidanceInterpolators().get(guidType),
|
||||
resource.getGuidSourceExpiration(guidType));
|
||||
} else if (forced) {
|
||||
guids = forceUtil.getForcedGuidValues(
|
||||
pfafList,
|
||||
forcedPfafs,
|
||||
resource.getGuidanceInterpolators().get(
|
||||
guidType), resource
|
||||
.getGuidSourceExpiration(guidType),
|
||||
ft);
|
||||
}
|
||||
|
||||
if ((!qpes.isEmpty())
|
||||
&& ((guids != null) && (!guids.isEmpty()))) {
|
||||
ratioValue = FFMPUtils
|
||||
.getMaxRatioValue(qpes, guids);
|
||||
diffValue = FFMPUtils.getMaxDiffValue(qpes, guids);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, diffValue));
|
||||
} else {
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, Float.NaN));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, Float.NaN));
|
||||
}
|
||||
|
||||
i += 3;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((rateBasin != null)
|
||||
&& (rateBasin.get(cBasin.getPfaf()) != null)) {
|
||||
rate = rateBasin.get(cBasin.getPfaf()).getValue(
|
||||
paintRefTime);
|
||||
}
|
||||
trd.setTableCellData(1,
|
||||
new FFMPTableCellData(FIELDS.RATE, rate));
|
||||
|
||||
if ((qpeBasin != null)
|
||||
&& (qpeBasin.get(cBasin.getPfaf()) != null)) {
|
||||
qpe = qpeBasin.get(cBasin.getPfaf()).getAccumValue(
|
||||
monitor.getQpeWindow().getAfterTime(),
|
||||
monitor.getQpeWindow().getBeforeTime(),
|
||||
expirationTime, isRate);
|
||||
}
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe));
|
||||
|
||||
if ((qpfBasin != null)
|
||||
&& (qpfBasin.get(cBasin.getPfaf()) != null)) {
|
||||
qpf = new Float(qpfBasin.get(cBasin.getPfaf()).getMaxValue(
|
||||
monitor.getQpfWindow().getAfterTime(),
|
||||
monitor.getQpfWindow().getBeforeTime()))
|
||||
.floatValue();
|
||||
}
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF, qpf));
|
||||
|
||||
processGuidance(trd, cBasin, pfafs, qpe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return trd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trd
|
||||
* @param cBasin
|
||||
* @param pfafs
|
||||
* @param qpe
|
||||
*/
|
||||
private void processGuidance(FFMPTableRowData trd, FFMPBasin cBasin,
|
||||
ArrayList<Long> pfafs, Float qpe) {
|
||||
Float guidance;
|
||||
Float ratioValue;
|
||||
Float diffValue;
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
diffValue = Float.NaN;
|
||||
ratioValue = Float.NaN;
|
||||
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
FFMPBasinData guidBasin = guidBasins.get(guidType);
|
||||
|
||||
if (guidBasin != null) {
|
||||
|
||||
FFMPGuidanceBasin basin = ((FFMPGuidanceBasin) guidBasin
|
||||
.get(cBasin.getPfaf()));
|
||||
guidance = resource.getGuidanceValue(basin, monitor
|
||||
.getQpeWindow().getBeforeTime(), guidType);
|
||||
|
||||
if (guidance < 0.0f) {
|
||||
guidance = Float.NaN;
|
||||
}
|
||||
|
||||
forceUtil.calculateForcings(pfafs, ft, cBasin);
|
||||
|
||||
List<Long> forcedPfafs = forceUtil.getForcedPfafList();
|
||||
boolean forced = forceUtil.isForced();
|
||||
|
||||
if (!forced) {
|
||||
if ((forcedPfafs != null) && (!forcedPfafs.isEmpty())) {
|
||||
forced = true;
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced));
|
||||
} else {
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, Float.NaN));
|
||||
}
|
||||
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
|
||||
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(FIELDS.RATIO,
|
||||
ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(FIELDS.DIFF,
|
||||
diffValue));
|
||||
|
||||
i += 3;
|
||||
}
|
||||
FFMPRowGenerator rowTask = new FFMPRowGenerator(this, cBasin, tData,
|
||||
isVGB, domain);
|
||||
jobPool.schedule(rowTask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1032,7 +360,7 @@ public class FFMPDataGenerator {
|
|||
|
||||
if (isWorstCase || (centeredAggregationKey != null)) {
|
||||
// make sure that "ALL" is loaded
|
||||
localHuc = ALL;
|
||||
localHuc = FFMPRecord.ALL;
|
||||
} else {
|
||||
localHuc = huc;
|
||||
}
|
||||
|
@ -1046,7 +374,7 @@ public class FFMPDataGenerator {
|
|||
guidRecords = monitor.getGuidanceRecords(product, siteKey, tableTime,
|
||||
localHuc, true);
|
||||
FFMPRecord virtualRecord = null;
|
||||
if (localHuc.equals(ALL)) {
|
||||
if (localHuc.equals(FFMPRecord.ALL)) {
|
||||
virtualRecord = monitor.getVirtualRecord(product, siteKey, dataKey,
|
||||
product.getVirtual(), tableTime, localHuc, true);
|
||||
}
|
||||
|
|
|
@ -1,533 +0,0 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.rsc;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPAggregateRecord;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPUtils;
|
||||
import com.raytheon.uf.common.datastorage.DataStoreFactory;
|
||||
import com.raytheon.uf.common.datastorage.IDataStore;
|
||||
import com.raytheon.uf.common.datastorage.Request;
|
||||
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
|
||||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.FFMPRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductXML;
|
||||
import com.raytheon.uf.common.monitor.xml.SourceXML;
|
||||
import com.raytheon.uf.common.serialization.SerializationUtil;
|
||||
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.viz.monitor.ffmp.FFMPMonitor;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPLoadListener;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPLoaderEvent;
|
||||
|
||||
/**
|
||||
* Place holder more or less for a ResourceData Object This dosen't do anything
|
||||
* currently.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 28 Feb, 2011 7587 dhladky Initial creation
|
||||
* 25 Jan, 2012 DR13839 gzhang Handle Uris and Huc processing
|
||||
* 01/27/13 1478 D. Hladky revamped the cache file format to help NAS overloading
|
||||
* 02/01/13 1569 D. Hladky Changed to reading aggregate records from pypies
|
||||
* Feb 28, 2013 1729 dhladky Changed the way status messages are sent to the FFMP Dialog.
|
||||
* Mar 6, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Apr 9, 2013 1890 dhladky removed loading of phantom Virtual template and cache file processing.
|
||||
* Apr 18, 2013 1912 bsteffen Increase bulk requests to pypies.
|
||||
* Apr 26, 2013 1954 bsteffen Minor code cleanup throughout FFMP.
|
||||
* May 22, 2013 1902 mpduff Check for null times.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dhladky
|
||||
* @version 1.0
|
||||
*/
|
||||
public class FFMPDataLoader extends Thread {
|
||||
|
||||
private static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FFMPDataLoader.class);
|
||||
|
||||
private ProductXML product = null;
|
||||
|
||||
private FFMPRunXML runner = null;
|
||||
|
||||
private Date timeBack = null;
|
||||
|
||||
private Date mostRecentTime = null;
|
||||
|
||||
public LOADER_TYPE loadType = null;
|
||||
|
||||
private String siteKey = null;
|
||||
|
||||
private String dataKey = null;
|
||||
|
||||
private List<String> hucsToLoad = null;
|
||||
|
||||
private String wfo = null;
|
||||
|
||||
private FFMPResourceData resourceData = null;
|
||||
|
||||
private FFMPConfig config = null;
|
||||
|
||||
private final ArrayList<FFMPLoadListener> loadListeners = new ArrayList<FFMPLoadListener>();
|
||||
|
||||
private final CountDownLatch latch;
|
||||
|
||||
public FFMPDataLoader(FFMPResourceData resourceData, Date timeBack,
|
||||
Date mostRecentTime, LOADER_TYPE loadType, List<String> hucsToLoad) {
|
||||
|
||||
this.product = resourceData.getProduct();
|
||||
this.siteKey = resourceData.siteKey;
|
||||
this.dataKey = resourceData.dataKey;
|
||||
this.timeBack = timeBack;
|
||||
this.mostRecentTime = mostRecentTime;
|
||||
this.loadType = loadType;
|
||||
this.hucsToLoad = hucsToLoad;
|
||||
this.wfo = resourceData.wfo;
|
||||
this.resourceData = resourceData;
|
||||
this.runner = FFMPRunConfigurationManager.getInstance().getRunner(wfo);
|
||||
this.config = FFMPConfig.getInstance();
|
||||
this.latch = new CountDownLatch(1);
|
||||
|
||||
if ((loadType == LOADER_TYPE.INITIAL)
|
||||
|| (loadType == LOADER_TYPE.GENERAL)) {
|
||||
this.setPriority(MAX_PRIORITY);
|
||||
} else {
|
||||
this.setPriority(MIN_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
public void waitFor() throws InterruptedException {
|
||||
latch.await();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listener
|
||||
*
|
||||
* @param fl
|
||||
*/
|
||||
public synchronized void addListener(FFMPLoadListener fl) {
|
||||
loadListeners.add(fl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove listener
|
||||
*
|
||||
* @param fl
|
||||
*/
|
||||
public synchronized void removeListener(FFMPLoadListener fl) {
|
||||
loadListeners.remove(fl);
|
||||
}
|
||||
|
||||
// kills the loader
|
||||
public void kill() {
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
resourceData.setLoader(loadType);
|
||||
FFMPMonitor monitor = getMonitor();
|
||||
FFMPSourceConfigurationManager sourceConfig = monitor
|
||||
.getSourceConfig();
|
||||
|
||||
ProductRunXML productRun = runner.getProduct(siteKey);
|
||||
List<SourceXML> qpfSources = new ArrayList<SourceXML>();
|
||||
String layer = config.getFFMPConfigData().getLayer();
|
||||
String rateURI = null;
|
||||
|
||||
if (loadType != LOADER_TYPE.GENERAL) {
|
||||
// preload all the uris except guidance. Guidance loads data
|
||||
// much further back and it is not efficient to group with the
|
||||
// rest.
|
||||
Set<String> sources = new HashSet<String>();
|
||||
sources.add(product.getRate());
|
||||
sources.add(product.getQpe());
|
||||
sources.add(product.getVirtual());
|
||||
for (String qpfType : productRun.getQpfTypes(product)) {
|
||||
for (SourceXML qpfSource : productRun.getQpfSources(
|
||||
product, qpfType)) {
|
||||
sources.add(qpfSource.getSourceName());
|
||||
}
|
||||
}
|
||||
monitor.preloadAvailableUris(siteKey, dataKey, sources,
|
||||
timeBack);
|
||||
}
|
||||
if ((loadType == LOADER_TYPE.INITIAL || loadType == LOADER_TYPE.GENERAL)
|
||||
&& !product.getRate().equals(product.getQpe())) {
|
||||
Map<Date, List<String>> rateURIs = monitor.getAvailableUris(
|
||||
siteKey, dataKey, product.getRate(), mostRecentTime);
|
||||
if (rateURIs.containsKey(mostRecentTime)) {
|
||||
rateURI = rateURIs.get(mostRecentTime).get(0);
|
||||
}
|
||||
}
|
||||
|
||||
NavigableMap<Date, List<String>> qpeURIs = monitor
|
||||
.getAvailableUris(siteKey, dataKey, product.getQpe(),
|
||||
timeBack);
|
||||
|
||||
ArrayList<NavigableMap<Date, List<String>>> qpfs = new ArrayList<NavigableMap<Date, List<String>>>();
|
||||
|
||||
for (String qpfType : productRun.getQpfTypes(product)) {
|
||||
for (SourceXML qpfSource : productRun.getQpfSources(product,
|
||||
qpfType)) {
|
||||
|
||||
NavigableMap<Date, List<String>> qpfURIs = null;
|
||||
Date qpfTime = timeBack;
|
||||
|
||||
if (loadType == LOADER_TYPE.GENERAL) {
|
||||
qpfTime = monitor.getPreviousQueryTime(siteKey,
|
||||
qpfSource.getSourceName());
|
||||
}
|
||||
|
||||
qpfURIs = monitor.getAvailableUris(siteKey, dataKey,
|
||||
qpfSource.getSourceName(), qpfTime);
|
||||
|
||||
if (qpfURIs != null && !qpfURIs.isEmpty()) {
|
||||
qpfs.add(qpfURIs);
|
||||
qpfSources.add(qpfSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NavigableMap<Date, List<String>> virtualURIs = monitor
|
||||
.getAvailableUris(siteKey, dataKey, product.getVirtual(),
|
||||
timeBack);
|
||||
|
||||
HashMap<String, NavigableMap<Date, List<String>>> guids = new HashMap<String, NavigableMap<Date, List<String>>>();
|
||||
|
||||
for (String type : productRun.getGuidanceTypes(product)) {
|
||||
for (SourceXML guidSource : productRun.getGuidanceSources(
|
||||
product, type)) {
|
||||
|
||||
NavigableMap<Date, List<String>> iguidURIs = null;
|
||||
Date guidTime = timeBack;
|
||||
if (loadType == LOADER_TYPE.GENERAL) {
|
||||
guidTime = monitor.getPreviousQueryTime(siteKey,
|
||||
guidSource.getSourceName());
|
||||
}
|
||||
if (guidTime == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
iguidURIs = monitor.getAvailableUris(siteKey, dataKey,
|
||||
guidSource.getSourceName(), guidTime);
|
||||
|
||||
if (iguidURIs != null && !iguidURIs.isEmpty()) {
|
||||
guids.put(guidSource.getSourceName(), iguidURIs);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We only load all for long range data, all + layer for medium
|
||||
// range
|
||||
if (loadType == LOADER_TYPE.TERTIARY) {
|
||||
hucsToLoad.clear();
|
||||
hucsToLoad.add(FFMPRecord.ALL);
|
||||
} else {
|
||||
// Only used as place holder name, No data is linked to it, uses
|
||||
// ALL
|
||||
hucsToLoad.remove(FFMPRecord.VIRTUAL);
|
||||
}
|
||||
|
||||
if (isDone()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// rate
|
||||
if (rateURI != null) {
|
||||
fireLoaderEvent(loadType, "Processing " + product.getRate(),
|
||||
isDone());
|
||||
for (String phuc : hucsToLoad) {
|
||||
monitor.processUri(rateURI, siteKey, product.getRate(),
|
||||
timeBack, phuc);
|
||||
}
|
||||
fireLoaderEvent(loadType, product.getRate(), isDone());
|
||||
}
|
||||
|
||||
// qpes
|
||||
fireLoaderEvent(loadType, "Processing " + product.getQpe(),
|
||||
isDone());
|
||||
FFMPAggregateRecord qpeCache = null;
|
||||
|
||||
if (loadType == LOADER_TYPE.INITIAL) {
|
||||
|
||||
SourceXML source = sourceConfig.getSource(product.getQpe());
|
||||
|
||||
qpeCache = readAggregateRecord(source, dataKey, wfo);
|
||||
|
||||
if (qpeCache != null) {
|
||||
monitor.insertFFMPData(qpeCache, qpeURIs, siteKey,
|
||||
product.getQpe());
|
||||
}
|
||||
}
|
||||
|
||||
// Use this method of QPE data retrieval if you don't have cache
|
||||
// files
|
||||
if (!qpeURIs.isEmpty()) {
|
||||
for (String phuc : hucsToLoad) {
|
||||
if (phuc.equals(layer) || phuc.equals(FFMPRecord.ALL)) {
|
||||
monitor.processUris(qpeURIs, siteKey, product.getQpe(),
|
||||
timeBack, phuc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fireLoaderEvent(loadType, product.getQpe(), isDone());
|
||||
|
||||
int i = 0;
|
||||
for (NavigableMap<Date, List<String>> qpfURIs : qpfs) {
|
||||
// qpf
|
||||
fireLoaderEvent(loadType, "Processing " + product.getQpf(i),
|
||||
isDone());
|
||||
FFMPAggregateRecord qpfCache = null;
|
||||
|
||||
if (loadType == LOADER_TYPE.INITIAL) {
|
||||
|
||||
SourceXML source = qpfSources.get(i);
|
||||
|
||||
String pdataKey = findQPFHomeDataKey(source);
|
||||
qpfCache = readAggregateRecord(source, pdataKey, wfo);
|
||||
|
||||
if (qpfCache != null) {
|
||||
monitor.insertFFMPData(qpfCache, qpfURIs, siteKey,
|
||||
source.getSourceName());
|
||||
}
|
||||
}
|
||||
|
||||
// Use this method of QPF data retrieval if you don't have cache
|
||||
// files
|
||||
if (!qpfURIs.isEmpty()) {
|
||||
for (String phuc : hucsToLoad) {
|
||||
if (phuc.equals(layer) || phuc.equals(FFMPRecord.ALL)) { // old
|
||||
monitor.processUris(qpfURIs, siteKey,
|
||||
product.getQpf(i), timeBack, phuc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fireLoaderEvent(loadType, product.getQpf(i), isDone());
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
fireLoaderEvent(loadType, "Processing " + product.getVirtual(),
|
||||
isDone());
|
||||
// process virtual all for all only, never uses cache files
|
||||
if (!virtualURIs.isEmpty()) {
|
||||
monitor.processUris(virtualURIs, siteKey, product.getVirtual(),
|
||||
timeBack, FFMPRecord.ALL);
|
||||
}
|
||||
|
||||
fireLoaderEvent(loadType, product.getVirtual(), isDone());
|
||||
|
||||
// process guidance all for all only, never uses cache files
|
||||
for (String type : productRun.getGuidanceTypes(product)) {
|
||||
|
||||
ArrayList<SourceXML> guidSources = productRun
|
||||
.getGuidanceSources(product, type);
|
||||
for (SourceXML guidSource : guidSources) {
|
||||
|
||||
NavigableMap<Date, List<String>> iguidURIs = guids
|
||||
.get(guidSource.getSourceName());
|
||||
|
||||
fireLoaderEvent(loadType,
|
||||
"Processing " + guidSource.getSourceName(),
|
||||
isDone());
|
||||
|
||||
monitor.processUris(iguidURIs, siteKey,
|
||||
guidSource.getSourceName(), timeBack,
|
||||
FFMPRecord.ALL);
|
||||
|
||||
fireLoaderEvent(loadType, guidSource.getSourceName(),
|
||||
isDone());
|
||||
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"General Problem in Loading FFMP Data", e);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
synchronized (this) {
|
||||
this.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
String message = null;
|
||||
if (loadType == LOADER_TYPE.INITIAL) {
|
||||
message = "Finished Initial Load";
|
||||
} else {
|
||||
message = "Finished General Data Load";
|
||||
}
|
||||
|
||||
long endTime = (System.currentTimeMillis()) - time;
|
||||
System.out.println(loadType.loaderType + " Loader took: " + endTime
|
||||
/ 1000 + " seconds");
|
||||
fireLoaderEvent(loadType, message, isDone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire loader updates to the front end displays
|
||||
*
|
||||
* @param FFMPLoaderStatus
|
||||
**/
|
||||
public void fireLoaderEvent(LOADER_TYPE ltype, String lmessage,
|
||||
boolean lstatus) {
|
||||
|
||||
FFMPLoaderStatus sstatus = new FFMPLoaderStatus(ltype, lmessage,
|
||||
lstatus);
|
||||
|
||||
FFMPLoaderEvent fle = new FFMPLoaderEvent(sstatus);
|
||||
Iterator<FFMPLoadListener> iter = loadListeners.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
FFMPLoadListener listener = iter.next();
|
||||
listener.loadStatus(fle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private FFMPMonitor getMonitor() {
|
||||
if (FFMPMonitor.isRunning()) {
|
||||
return FFMPMonitor.getInstance();
|
||||
} else {
|
||||
latch.countDown();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum LOADER_TYPE {
|
||||
|
||||
INITIAL("Initial"), GENERAL("General"), SECONDARY("Secondary"), TERTIARY(
|
||||
"Tertiary");
|
||||
|
||||
private final String loaderType;
|
||||
|
||||
private LOADER_TYPE(String name) {
|
||||
loaderType = name;
|
||||
}
|
||||
|
||||
public String getLoaderType() {
|
||||
return loaderType;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the Cache files
|
||||
*
|
||||
* @param sourceName
|
||||
* @param huc
|
||||
* @param wfo
|
||||
* @return
|
||||
*/
|
||||
private FFMPAggregateRecord readAggregateRecord(SourceXML source,
|
||||
String pdataKey, String wfo) throws Exception {
|
||||
|
||||
FFMPAggregateRecord record = null;
|
||||
String sourceSiteDataKey = getSourceSiteDataKey(source, pdataKey);
|
||||
|
||||
try {
|
||||
|
||||
File hdf5File = FFMPUtils.getHdf5File(wfo, sourceSiteDataKey);
|
||||
IDataStore dataStore = DataStoreFactory.getDataStore(hdf5File);
|
||||
IDataRecord rec = dataStore.retrieve(wfo, sourceSiteDataKey,
|
||||
Request.ALL);
|
||||
byte[] bytes = ((ByteDataRecord) rec).getByteData();
|
||||
record = SerializationUtil.transformFromThrift(
|
||||
FFMPAggregateRecord.class, bytes);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.WARN,
|
||||
"Couldn't read Aggregate Record" + sourceSiteDataKey);
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the home datakey identifier for QPF sources
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private String findQPFHomeDataKey(SourceXML source) {
|
||||
|
||||
FFMPRunConfigurationManager runManager = FFMPRunConfigurationManager
|
||||
.getInstance();
|
||||
|
||||
for (ProductRunXML product : runManager.getProducts()) {
|
||||
|
||||
try {
|
||||
// we are just checking if it exists or not
|
||||
String pdataKey = product.getProductKey();
|
||||
String sourceSiteDataKey = getSourceSiteDataKey(source,
|
||||
pdataKey);
|
||||
File hdf5File = FFMPUtils.getHdf5File(wfo, sourceSiteDataKey);
|
||||
DataStoreFactory.getDataStore(hdf5File);
|
||||
|
||||
return pdataKey;
|
||||
} catch (Exception e) {
|
||||
// not the right key, doesn't exist
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return siteKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sourceSiteDataKey for this piece of data
|
||||
*
|
||||
* @param source
|
||||
* @param pdataKey
|
||||
* @return
|
||||
*/
|
||||
private String getSourceSiteDataKey(SourceXML source, String pdataKey) {
|
||||
return source.getSourceName() + "-" + siteKey + "-" + pdataKey;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return latch.getCount() == 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package com.raytheon.uf.viz.monitor.ffmp.ui.rsc;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader.LOADER_TYPE;
|
||||
|
||||
/**
|
||||
* Loader status for FFMP
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 04/23/10 4494 D. Hladky Initial release
|
||||
* 02/01/13 1569 D. Hladky Added constants
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dhladky
|
||||
* @version 1
|
||||
*/
|
||||
|
||||
public class FFMPLoaderStatus {
|
||||
|
||||
private LOADER_TYPE loaderType = null;
|
||||
|
||||
private String message = null;
|
||||
|
||||
private boolean isDone = false;
|
||||
|
||||
public FFMPLoaderStatus(LOADER_TYPE loaderType, String message,
|
||||
boolean isDone) {
|
||||
this.loaderType = loaderType;
|
||||
this.message = message;
|
||||
this.isDone = isDone;
|
||||
}
|
||||
|
||||
public LOADER_TYPE getLoaderType() {
|
||||
return loaderType;
|
||||
}
|
||||
|
||||
public void setLoaderName(LOADER_TYPE loaderType) {
|
||||
this.loaderType = loaderType;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return isDone;
|
||||
}
|
||||
|
||||
public void isDone(boolean isDone) {
|
||||
this.isDone = isDone;
|
||||
}
|
||||
|
||||
}
|
|
@ -38,7 +38,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
@ -123,8 +125,6 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPCWAChangeEvent;
|
|||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPFieldChangeEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPHUCChangeEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPListener;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPLoadListener;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPLoaderEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPMaintainLayerEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPParentBasinEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPScreenCenterEvent;
|
||||
|
@ -132,7 +132,7 @@ import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPStreamTraceEvent;
|
|||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPTimeChangeEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.FFMPWorstCaseEvent;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.listeners.IFFMPResourceListener;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader.LOADER_TYPE;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.thread.UpdateLoadJob;
|
||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler.PointStyle;
|
||||
import com.raytheon.viz.ui.input.EditableManager;
|
||||
|
@ -148,25 +148,27 @@ import com.vividsolutions.jts.geom.Point;
|
|||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 29 June, 2009 2521 dhladky Initial creation
|
||||
* 11 Apr. 2012 DR 14522 gzhang Fixing invalid thread error.
|
||||
* 31 July 2012 14517 mpduff Fix for blanking map on update.
|
||||
* 14 Sep 2012 1048 njensen Code cleanup
|
||||
* 07 Dec 2012 1353 rferrel Changes for non-blocking FFMPSplash dialog.
|
||||
* 10 Jan 2013 1475 dhladky Some cleanup
|
||||
* 27 Jan 2013 1478 dhladky Changed gap collection to a generic list instead of Arraylist
|
||||
* 02/01/13 1569 D. Hladky Added constants
|
||||
* 10 Feb 2013 1584 mpduff Add performance logging.
|
||||
* Feb 19, 2013 1639 njensen Replaced FFMPCacheRecord with FFMPRecord
|
||||
* Feb 20, 2013 1635 dhladky Fixed multiple guidance display
|
||||
* Feb 28, 2013 1729 dhladky Changed the way the loaders are managed via the status updates.
|
||||
* Mar 6, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Apr 9, 2013 1890 dhladky General cleanup.
|
||||
* Apr 10, 2013 1896 bsteffen Make FFMPResource work better with D2D
|
||||
* time matcher.
|
||||
* Apr 25, 2013 1954 bsteffen Skip extent checking for FFMP shape
|
||||
* generation.
|
||||
* Apr 26, 2013 1954 bsteffen Minor code cleanup throughout FFMP.
|
||||
* 29 June, 2009 2521 dhladky Initial creation
|
||||
* 11 Apr. 2012 DR 14522 gzhang Fixing invalid thread error.
|
||||
* 31 July 2012 14517 mpduff Fix for blanking map on update.
|
||||
* 14 Sep 2012 1048 njensen Code cleanup
|
||||
* 07 Dec 2012 1353 rferrel Changes for non-blocking FFMPSplash dialog.
|
||||
* 10 Jan 2013 1475 dhladky Some cleanup
|
||||
* 27 Jan 2013 1478 dhladky Changed gap collection to a generic list instead of Arraylist
|
||||
* 02/01/13 1569 D. Hladky Added constants
|
||||
* 10 Feb 2013 1584 mpduff Add performance logging.
|
||||
* Feb 19, 2013 1639 njensen Replaced FFMPCacheRecord with FFMPRecord
|
||||
* Feb 20, 2013 1635 dhladky Fixed multiple guidance display
|
||||
* Feb 28, 2013 1729 dhladky Changed the way the loaders are managed via the status updates.
|
||||
* Mar 6, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Apr 9, 2013 1890 dhladky General cleanup.
|
||||
* Apr 10, 2013 1896 bsteffen Make FFMPResource work better with D2D
|
||||
* time matcher.
|
||||
* Apr 25, 2013 1954 bsteffen Skip extent checking for FFMP shape
|
||||
* generation.
|
||||
* Apr 26, 2013 1954 bsteffen Minor code cleanup throughout FFMP.
|
||||
* Jun 06, 2013 2075 njensen No longer schedules load threads,
|
||||
* refactored updates
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -176,8 +178,7 @@ import com.vividsolutions.jts.geom.Point;
|
|||
|
||||
public class FFMPResource extends
|
||||
AbstractVizResource<FFMPResourceData, MapDescriptor> implements
|
||||
IResourceDataChanged, IFFMPResourceListener, FFMPListener,
|
||||
FFMPLoadListener {
|
||||
IResourceDataChanged, IFFMPResourceListener, FFMPListener {
|
||||
|
||||
/** Status handler */
|
||||
private static final IUFStatusHandler statusHandler = UFStatus
|
||||
|
@ -356,9 +357,6 @@ public class FFMPResource extends
|
|||
*/
|
||||
public FfmpBasinTableDlg basinTableDlg;
|
||||
|
||||
/** data loader **/
|
||||
private FFMPDataLoader loader = null;
|
||||
|
||||
/** Guidance Interpolation Map **/
|
||||
public HashMap<String, FFMPGuidanceInterpolation> interpolationMap;
|
||||
|
||||
|
@ -437,19 +435,16 @@ public class FFMPResource extends
|
|||
*/
|
||||
@Override
|
||||
public void resourceChanged(ChangeType type, Object object) {
|
||||
ITimer timer = TimeUtil.getTimer();
|
||||
timer.start();
|
||||
if (type.equals(ChangeType.DATA_UPDATE)) {
|
||||
FFFGDataMgr.getUpdatedInstance();
|
||||
PluginDataObject[] pdos = (PluginDataObject[]) object;
|
||||
FFMPRecord ffmpRec = (FFMPRecord) pdos[pdos.length - 1];
|
||||
// an update clears everything
|
||||
clear();
|
||||
// only care about the most recent one
|
||||
try {
|
||||
|
||||
if (ffmpRec.getSourceName()
|
||||
.equals(getResourceData().sourceName)) {
|
||||
// an update clears everything
|
||||
clear();
|
||||
|
||||
// go back an extra time step
|
||||
Date previousMostRecentTime = null;
|
||||
List<Date> tok = getTimeOrderedKeys();
|
||||
|
@ -458,66 +453,58 @@ public class FFMPResource extends
|
|||
} else {
|
||||
previousMostRecentTime = tok.get(0);
|
||||
}
|
||||
Date refTime = ffmpRec.getDataTime().getRefTime();
|
||||
|
||||
final Date refTime = ffmpRec.getDataTime().getRefTime();
|
||||
updateTimeOrderedkeys(refTime);
|
||||
|
||||
if (getResourceData().tableLoad) {
|
||||
setTableTime();
|
||||
}
|
||||
|
||||
resourceData.populateRecord(ffmpRec);
|
||||
|
||||
statusHandler.handle(Priority.INFO, "Updating : Previous: "
|
||||
+ previousMostRecentTime + " New: "
|
||||
+ ffmpRec.getDataTime().getRefTime());
|
||||
|
||||
if (getResourceData().tableLoad) {
|
||||
|
||||
if (loader == null) {
|
||||
startLoader(previousMostRecentTime, refTime,
|
||||
LOADER_TYPE.GENERAL);
|
||||
} else {
|
||||
try {
|
||||
loader.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
startLoader(previousMostRecentTime, refTime,
|
||||
LOADER_TYPE.GENERAL);
|
||||
try {
|
||||
loader.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
List<String> hucsToLoad = new ArrayList<String>();
|
||||
hucsToLoad.add(FFMPRecord.ALL);
|
||||
String currentHuc = getHuc();
|
||||
if (!currentHuc.equals(FFMPRecord.ALL)) {
|
||||
hucsToLoad.add(currentHuc);
|
||||
}
|
||||
|
||||
purge(refTime);
|
||||
UpdateLoadJob updateJob = new UpdateLoadJob(
|
||||
resourceData, previousMostRecentTime, refTime,
|
||||
hucsToLoad);
|
||||
updateJob.addJobChangeListener(new JobChangeAdapter() {
|
||||
@Override
|
||||
public void done(IJobChangeEvent event) {
|
||||
purge(refTime);
|
||||
finishUpdate();
|
||||
}
|
||||
});
|
||||
updateJob.schedule();
|
||||
} else {
|
||||
finishUpdate();
|
||||
}
|
||||
|
||||
resetRecords();
|
||||
}
|
||||
|
||||
} catch (VizException ve) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Error updating record",
|
||||
ve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the last actions triggered by an update. Should run after the
|
||||
* data is loaded if the update triggered a data load.
|
||||
*/
|
||||
private void finishUpdate() {
|
||||
resetRecords();
|
||||
if (getResourceData().tableLoad) {
|
||||
allowNewTableUpdate();
|
||||
isFirst = true;
|
||||
}
|
||||
|
||||
refresh();
|
||||
|
||||
if (type.equals(ChangeType.DATA_UPDATE)) {
|
||||
timer.stop();
|
||||
perfLog.logDuration("Load Time", timer.getElapsedTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -707,7 +694,8 @@ public class FFMPResource extends
|
|||
long fips = monitor.getTemplates(getSiteKey())
|
||||
.getCountyFipsByPfaf(pfafs.get(0));
|
||||
|
||||
value = getGuidanceRecord().getBasinData(FFMPRecord.ALL)
|
||||
value = getGuidanceRecord()
|
||||
.getBasinData(FFMPRecord.ALL)
|
||||
.getMaxGuidanceValue(pfafs,
|
||||
getGuidanceInterpolation(getFFGName()),
|
||||
getGuidSourceExpiration(getFFGName()), fips);
|
||||
|
@ -814,12 +802,12 @@ public class FFMPResource extends
|
|||
forceUtil.setSliderTime(this.getTime());
|
||||
|
||||
if (pfafs != null) {
|
||||
forceUtil.calculateForcings(pfafs,
|
||||
ForceUtilResult forceResult = forceUtil.calculateForcings(pfafs,
|
||||
monitor.getTemplates(getSiteKey()), basin);
|
||||
|
||||
List<Long> forcedPfafs = forceUtil.getForcedPfafList();
|
||||
List<Long> pfafList = forceUtil.getPfafList();
|
||||
boolean forced = forceUtil.isForced();
|
||||
List<Long> forcedPfafs = forceResult.getForcedPfafList();
|
||||
List<Long> pfafList = forceResult.getPfafList();
|
||||
boolean forced = forceResult.isForced();
|
||||
if ((forcedPfafs.size() > 0) && forced) {
|
||||
// Recalculate the guidance using the forced value(s)
|
||||
value = guidRecord.getBasinData(FFMPRecord.ALL)
|
||||
|
@ -1077,13 +1065,6 @@ public class FFMPResource extends
|
|||
}
|
||||
|
||||
if (this.getName().indexOf("Table Display") > -1) {
|
||||
|
||||
if (resourceData.floader != null) {
|
||||
resourceData.floader.removeListener(this);
|
||||
resourceData.floader.kill();
|
||||
resourceData.floader = null;
|
||||
}
|
||||
|
||||
if (basinTableDlg != null) {
|
||||
closeDialog();
|
||||
if (smallBasinOverlayShape != null) {
|
||||
|
@ -1210,10 +1191,6 @@ public class FFMPResource extends
|
|||
FFMPDrawable drawable = null;
|
||||
|
||||
if (paintTime != null) {
|
||||
if (loader != null && !loader.isDone()
|
||||
&& loader.loadType == LOADER_TYPE.GENERAL) {
|
||||
return;
|
||||
}
|
||||
if (!drawables.containsKey(paintTime)) {
|
||||
|
||||
drawable = new FFMPDrawable(getDomains());
|
||||
|
@ -2316,8 +2293,7 @@ public class FFMPResource extends
|
|||
requestQueue.poll();
|
||||
}
|
||||
|
||||
Request req = new Request(target, drawable,
|
||||
time);
|
||||
Request req = new Request(target, drawable, time);
|
||||
requestQueue.add(req);
|
||||
this.schedule();
|
||||
}
|
||||
|
@ -2332,7 +2308,6 @@ public class FFMPResource extends
|
|||
@SuppressWarnings({ "unchecked" })
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor progMonitor) {
|
||||
|
||||
VizApp.runSync(new Runnable() {
|
||||
|
||||
@Override
|
||||
|
@ -2414,8 +2389,7 @@ public class FFMPResource extends
|
|||
centeredAggr = templates
|
||||
.findAggregatedVGB(
|
||||
(String) centeredAggregationKey,
|
||||
siteKey,
|
||||
phuc);
|
||||
siteKey, phuc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2429,8 +2403,7 @@ public class FFMPResource extends
|
|||
centeredAggr = templates
|
||||
.getAggregatedPfaf(
|
||||
(Long) centeredAggregationKey,
|
||||
siteKey,
|
||||
phuc);
|
||||
siteKey, phuc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2463,7 +2436,6 @@ public class FFMPResource extends
|
|||
String shadedHuc = null;
|
||||
|
||||
if (!isAllPhuc) {
|
||||
|
||||
Map<Long, Geometry> geomMap = hucGeomFactory
|
||||
.getGeometries(templates, siteKey,
|
||||
cwa, phuc);
|
||||
|
@ -2482,8 +2454,8 @@ public class FFMPResource extends
|
|||
.keySet();
|
||||
} else {
|
||||
allPfafs = (List<Long>) (templates
|
||||
.getMap(siteKey,
|
||||
cwa, phuc)
|
||||
.getMap(siteKey, cwa,
|
||||
phuc)
|
||||
.get(centeredAggr));
|
||||
}
|
||||
|
||||
|
@ -2491,8 +2463,7 @@ public class FFMPResource extends
|
|||
Map<Long, Geometry> allGeomMap = hucGeomFactory
|
||||
.getGeometries(
|
||||
templates,
|
||||
siteKey,
|
||||
cwa,
|
||||
siteKey, cwa,
|
||||
FFMPRecord.ALL);
|
||||
IColormapShadedShape shape = shadedShapes
|
||||
.getShape(cwa,
|
||||
|
@ -2521,12 +2492,10 @@ public class FFMPResource extends
|
|||
.keySet();
|
||||
|
||||
if (allPfafs != null) {
|
||||
|
||||
Map<Long, Geometry> allGeomMap = hucGeomFactory
|
||||
.getGeometries(
|
||||
templates,
|
||||
siteKey,
|
||||
cwa,
|
||||
siteKey, cwa,
|
||||
FFMPRecord.ALL);
|
||||
|
||||
IColormapShadedShape shape = shadedShapes
|
||||
|
@ -2655,7 +2624,7 @@ public class FFMPResource extends
|
|||
fshell.setCursor(null);
|
||||
|
||||
// check whether or not the dialog needs to be dumped
|
||||
monitor.splashDisposeAndDataLoad(getResource());
|
||||
monitor.splashDispose(getResource());
|
||||
|
||||
if (getResourceData().tableLoad && isFirst) {
|
||||
isFirst = false;
|
||||
|
@ -2756,7 +2725,6 @@ public class FFMPResource extends
|
|||
try {
|
||||
for (DomainXML domains : templates.getDomains()) {
|
||||
String cwa = domains.getCwa();
|
||||
|
||||
Map<Long, Geometry> geomMap = hucGeomFactory
|
||||
.getGeometries(templates, getSiteKey(), cwa,
|
||||
FFMPRecord.ALL);
|
||||
|
@ -3212,7 +3180,8 @@ public class FFMPResource extends
|
|||
for (SourceXML ffgSource : getProduct().getGuidanceSourcesByType(
|
||||
ffgGraphType)) {
|
||||
if (guidBasin.getValue(ffgSource.getSourceName(),
|
||||
guidanceInterpolator, getGuidSourceExpiration(ffgGraphType)) != null) {
|
||||
guidanceInterpolator,
|
||||
getGuidSourceExpiration(ffgGraphType)) != null) {
|
||||
|
||||
double time = FFMPGuiUtils.getTimeDiff(mostRecentRefTime,
|
||||
FFMPGuiUtils.getHourDisplacement(mostRecentRefTime,
|
||||
|
@ -3948,32 +3917,6 @@ public class FFMPResource extends
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadStatus(FFMPLoaderEvent event) {
|
||||
|
||||
if (basinTableDlg != null) {
|
||||
// call to update the basin table dialog
|
||||
if (event.getSource() instanceof FFMPLoaderStatus) {
|
||||
final FFMPLoaderStatus status = (FFMPLoaderStatus) event
|
||||
.getSource();
|
||||
VizApp.runAsync(new Runnable() {
|
||||
public void run() {
|
||||
if (basinTableDlg != null
|
||||
&& !basinTableDlg.isDisposed()) {
|
||||
basinTableDlg.updateLoadingLabel(status);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (event.getSource() instanceof FFMPLoaderStatus) {
|
||||
FFMPLoaderStatus status = (FFMPLoaderStatus) event.getSource();
|
||||
if (status.isDone()) {
|
||||
issueRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FFG used
|
||||
*
|
||||
|
@ -4060,52 +4003,6 @@ public class FFMPResource extends
|
|||
refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start up a loader
|
||||
*
|
||||
* @param startDate
|
||||
* @param endDate
|
||||
* @param type
|
||||
*/
|
||||
private void startLoader(Date startDate, Date endDate, LOADER_TYPE type) {
|
||||
|
||||
ArrayList<String> hucsToLoad = new ArrayList<String>();
|
||||
|
||||
if (isWorstCase) {
|
||||
hucsToLoad.add(FFMPRecord.ALL);
|
||||
}
|
||||
|
||||
// tertiary loader only loads ALL
|
||||
if (type != LOADER_TYPE.TERTIARY) {
|
||||
if (!hucsToLoad.contains(getHuc())) {
|
||||
hucsToLoad.add(getHuc());
|
||||
}
|
||||
} else {
|
||||
if (!hucsToLoad.contains(FFMPRecord.ALL)) {
|
||||
hucsToLoad.add(FFMPRecord.ALL);
|
||||
}
|
||||
}
|
||||
// destroy any old loader
|
||||
if (loader != null) {
|
||||
loader = null;
|
||||
}
|
||||
|
||||
loader = new FFMPDataLoader(getResourceData(), endDate, startDate,
|
||||
type, hucsToLoad);
|
||||
|
||||
loader.addListener(this);
|
||||
|
||||
try {
|
||||
if (!loader.isAlive()) {
|
||||
loader.start();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM, "FFMP " + type
|
||||
+ " Data update failed", e);
|
||||
loader.removeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the purge file time
|
||||
*/
|
||||
|
@ -4137,30 +4034,6 @@ public class FFMPResource extends
|
|||
return 24 * TimeUtil.MILLIS_PER_HOUR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks off additional loaders that need to be fired off
|
||||
*
|
||||
* @param loader
|
||||
* @param isDone
|
||||
*/
|
||||
public void manageLoaders(FFMPLoaderStatus status) {
|
||||
|
||||
if (status.getLoaderType() == LOADER_TYPE.SECONDARY) {
|
||||
if (status.isDone() && !this.getResourceData().isTertiaryLoad) {
|
||||
try {
|
||||
Date startDate = new Date(getMostRecentTime().getTime()
|
||||
- (6 * TimeUtil.MILLIS_PER_HOUR));
|
||||
FFMPMonitor.getInstance().startLoad(this, startDate,
|
||||
LOADER_TYPE.TERTIARY);
|
||||
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Secondary Data Load failure", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTime[] getDataTimes() {
|
||||
List<Date> dates = getTimeOrderedKeys();
|
||||
|
|
|
@ -30,6 +30,11 @@ import javax.xml.bind.annotation.XmlAttribute;
|
|||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord.FIELDS;
|
||||
|
@ -37,15 +42,13 @@ import com.raytheon.uf.common.dataplugin.ffmp.FFMPTemplates;
|
|||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager.SOURCE_TYPE;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPTemplateConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.DomainXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductXML;
|
||||
import com.raytheon.uf.common.monitor.xml.SourceXML;
|
||||
import com.raytheon.uf.common.status.IPerformanceStatusHandler;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.PerformanceStatus;
|
||||
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.util.TimeUtil;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
|
@ -57,24 +60,27 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
|||
import com.raytheon.uf.viz.monitor.ffmp.FFMPMonitor;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPConfig;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfig;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPDataLoader.LOADER_TYPE;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.thread.BackgroundLoadJob;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.thread.InitHucLevelGeomsJob;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.thread.InitialLoadJob;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML;
|
||||
|
||||
/**
|
||||
* Place holder more or less for a ResourceData Object This dosen't do anything
|
||||
* currently.
|
||||
* Resource data for an FFMPResource. Schedules all of the loading jobs except
|
||||
* for jobs triggered by updates.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 29 June, 2009 2521 dhladky Initial creation
|
||||
* 02/01/13 1569 D. Hladky Added constants
|
||||
* Feb 10, 2013 1584 mpduff Add performance logging.
|
||||
* Feb 28, 2013 1729 dhladky Got rid of thread sleeps
|
||||
* Mar 6, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Jun 29, 2009 2521 dhladky Initial creation
|
||||
* Feb 01, 2013 1569 D. Hladky Added constants
|
||||
* Feb 10, 2013 1584 mpduff Add performance logging.
|
||||
* Feb 28, 2013 1729 dhladky Got rid of thread sleeps
|
||||
* Mar 06, 2013 1769 dhladky Changed threading to use count down latch.
|
||||
* Apr 26, 2013 1954 bsteffen Minor code cleanup throughout FFMP.
|
||||
* Jun 06, 2013 2075 njensen Use new load jobs
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -84,11 +90,9 @@ import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPConfigBasinXML;
|
|||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
@XmlType(name = "ffmpResourceData")
|
||||
public class FFMPResourceData extends AbstractRequestableResourceData {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FFMPResourceData.class);
|
||||
|
||||
/** Performance log entry prefix */
|
||||
private final String prefix = "FFMP ResourceData:";
|
||||
private static final String prefix = "FFMP ResourceData:";
|
||||
|
||||
/** Performance logger */
|
||||
private final IPerformanceStatusHandler perfLog = PerformanceStatus
|
||||
|
@ -139,20 +143,6 @@ public class FFMPResourceData extends AbstractRequestableResourceData {
|
|||
/** Field default **/
|
||||
protected FIELDS field = FIELDS.QPE;
|
||||
|
||||
public Date timeBack = null;
|
||||
|
||||
/** active loader **/
|
||||
public FFMPDataLoader floader = null;
|
||||
|
||||
/** mark whether or not the tertiary load has run or not **/
|
||||
public boolean isTertiaryLoad = false;
|
||||
|
||||
/** mark whether or not the secondary load has run or not **/
|
||||
public boolean isSecondaryLoad = false;
|
||||
|
||||
/** mark whether or not the initial load has run or not **/
|
||||
public boolean isInitialLoad = false;
|
||||
|
||||
public FFMPResourceData() {
|
||||
|
||||
super();
|
||||
|
@ -185,33 +175,12 @@ public class FFMPResourceData extends AbstractRequestableResourceData {
|
|||
|
||||
DataTime[] availableTimes = this.getAvailableTimes();
|
||||
// no data available;
|
||||
FFMPTemplates templates = null;
|
||||
if (availableTimes.length != 0) {
|
||||
product = monitor.getProductXML(sourceName);
|
||||
if (product != null) {
|
||||
monitor.launchSplash(siteKey);
|
||||
FFMPTemplates templates = monitor.getTemplates(siteKey);
|
||||
|
||||
// wait for templates to finish load
|
||||
int i = 0;
|
||||
while (!templates.done) {
|
||||
try {
|
||||
if (i > 5) {
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
"Failed to read template in allotted time");
|
||||
break;
|
||||
}
|
||||
if (floader != null) {
|
||||
synchronized (floader) {
|
||||
floader.wait(1000);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} catch (InterruptedException e) {
|
||||
statusHandler.handle(Priority.INFO,
|
||||
"Data Loader thread interrupted, dying!", e);
|
||||
}
|
||||
}
|
||||
|
||||
templates = monitor.getTemplates(siteKey);
|
||||
tableLoad = true;
|
||||
}
|
||||
|
||||
|
@ -242,18 +211,80 @@ public class FFMPResourceData extends AbstractRequestableResourceData {
|
|||
|
||||
this.domains = defaults;
|
||||
|
||||
Date mostRecentTime = availableTimes[availableTimes.length - 1]
|
||||
final Date mostRecentTime = availableTimes[availableTimes.length - 1]
|
||||
.getRefTime();
|
||||
this.timeBack = new Date(
|
||||
(long) (mostRecentTime.getTime() - (cfgBasinXML
|
||||
.getTimeFrame() * TimeUtil.MILLIS_PER_HOUR)));
|
||||
List<String> hucsToLoad = monitor.getTemplates(siteKey)
|
||||
.getTemplateMgr().getHucLevels();
|
||||
// goes back X hours and pre populates the Data Hashes
|
||||
FFMPDataLoader loader = new FFMPDataLoader(this, timeBack,
|
||||
mostRecentTime, LOADER_TYPE.INITIAL,
|
||||
hucsToLoad);
|
||||
loader.run();
|
||||
final double configTimeFrame = cfgBasinXML.getTimeFrame();
|
||||
final Date timeBack = new Date(
|
||||
(long) (mostRecentTime.getTime() - (configTimeFrame * TimeUtil.MILLIS_PER_HOUR)));
|
||||
final List<String> initialHucs = new ArrayList<String>();
|
||||
initialHucs.add(FFMPRecord.ALL);
|
||||
final String defaultLayer = monitor.getConfig()
|
||||
.getFFMPConfigData().getLayer();
|
||||
if (!defaultLayer.equals(FFMPRecord.ALL)) {
|
||||
initialHucs.add(defaultLayer);
|
||||
}
|
||||
InitialLoadJob initialJob = new InitialLoadJob(this, timeBack,
|
||||
mostRecentTime, initialHucs);
|
||||
|
||||
// schedule the secondary load to start as soon as the initial
|
||||
// completes
|
||||
// secondary load will be the same time period as initial with
|
||||
// the hucs that the initial job did not do
|
||||
initialJob.addJobChangeListener(new JobChangeAdapter() {
|
||||
@Override
|
||||
public void done(IJobChangeEvent event) {
|
||||
Date secondStartTime = timeBack;
|
||||
List<String> secondaryHucs = FFMPTemplateConfigurationManager
|
||||
.getInstance().getHucLevels();
|
||||
secondaryHucs.removeAll(initialHucs);
|
||||
|
||||
BackgroundLoadJob secondaryJob = new BackgroundLoadJob(
|
||||
"Secondary FFMP Load", FFMPResourceData.this,
|
||||
secondStartTime, mostRecentTime, secondaryHucs);
|
||||
secondaryJob.setPriority(Job.SHORT);
|
||||
// schedule the tertiary load as soon as the
|
||||
// secondary completes
|
||||
// tertiary load will do 24 hours back of the
|
||||
// same hucs as the initial load
|
||||
secondaryJob
|
||||
.addJobChangeListener(new JobChangeAdapter() {
|
||||
@Override
|
||||
public void done(IJobChangeEvent event) {
|
||||
List<String> tertiaryHucs = new ArrayList<String>();
|
||||
tertiaryHucs.add(FFMPRecord.ALL);
|
||||
Date tertiaryStartTime = new Date(
|
||||
mostRecentTime.getTime()
|
||||
- (24 * TimeUtil.MILLIS_PER_HOUR));
|
||||
BackgroundLoadJob tertiaryJob = new BackgroundLoadJob(
|
||||
"Tertiary FFMP Load",
|
||||
FFMPResourceData.this,
|
||||
tertiaryStartTime, timeBack,
|
||||
tertiaryHucs);
|
||||
tertiaryJob
|
||||
.setPreloadAvailableUris(true);
|
||||
tertiaryJob.schedule();
|
||||
}
|
||||
});
|
||||
secondaryJob.schedule();
|
||||
}
|
||||
});
|
||||
initialJob.schedule();
|
||||
|
||||
// schedule this huc geometries job to run in the
|
||||
// background so the first paints of the resource
|
||||
// will be faster
|
||||
List<String> earlyLoadHucs = new ArrayList<String>();
|
||||
earlyLoadHucs.addAll(initialHucs);
|
||||
for (String otherHuc : FFMPTemplateConfigurationManager
|
||||
.getInstance().getHucLevels()) {
|
||||
if (!earlyLoadHucs.contains(otherHuc)) {
|
||||
earlyLoadHucs.add(otherHuc);
|
||||
}
|
||||
}
|
||||
earlyLoadHucs.remove(FFMPRecord.VIRTUAL);
|
||||
InitHucLevelGeomsJob hucGeomsJob = new InitHucLevelGeomsJob(
|
||||
this.siteKey, templates, earlyLoadHucs);
|
||||
hucGeomsJob.schedule();
|
||||
} else {
|
||||
/*
|
||||
* This appears completely un-orthodox for anything in D2D. But
|
||||
|
@ -292,8 +323,9 @@ public class FFMPResourceData extends AbstractRequestableResourceData {
|
|||
NavigableMap<Date, List<String>> sourceURIs = getMonitor()
|
||||
.getAvailableUris(siteKey, dataKey, sourceName,
|
||||
standAloneTime);
|
||||
monitor.processUris(sourceURIs, siteKey,
|
||||
sourceName, standAloneTime, FFMPRecord.ALL);
|
||||
monitor.processUris(sourceURIs, siteKey, sourceName,
|
||||
standAloneTime, FFMPRecord.ALL,
|
||||
SubMonitor.convert(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -392,8 +424,7 @@ public class FFMPResourceData extends AbstractRequestableResourceData {
|
|||
*
|
||||
* @param record
|
||||
*/
|
||||
public void populateRecord(FFMPRecord precord)
|
||||
throws VizException {
|
||||
public void populateRecord(FFMPRecord precord) throws VizException {
|
||||
try {
|
||||
getMonitor().populateFFMPRecord(siteKey, precord,
|
||||
precord.getSourceName(), huc);
|
||||
|
@ -538,19 +569,4 @@ public class FFMPResourceData extends AbstractRequestableResourceData {
|
|||
return sourceNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set them as done
|
||||
*
|
||||
* @param type
|
||||
*/
|
||||
public void setLoader(LOADER_TYPE type) {
|
||||
if (type == LOADER_TYPE.INITIAL) {
|
||||
isInitialLoad = true;
|
||||
} else if (type == LOADER_TYPE.SECONDARY) {
|
||||
isSecondaryLoad = true;
|
||||
} else if (type == LOADER_TYPE.TERTIARY) {
|
||||
isTertiaryLoad = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,841 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.rsc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasin;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinData;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPBasinMetaData;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPGuidanceBasin;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord.FIELDS;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPTemplates;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPUtils;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPVirtualGageBasin;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPVirtualGageBasinMetaData;
|
||||
import com.raytheon.uf.common.monitor.config.FFFGDataMgr;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.DomainXML;
|
||||
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.viz.monitor.ffmp.FFMPMonitor;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableCellData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FFMPTableRowData;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.dialogs.FfmpTableConfigData;
|
||||
|
||||
/**
|
||||
* Generates an FFMPTableRowData for the parameters specified and adds them to
|
||||
* the table data. This class was created by separating out some of the logic of
|
||||
* FFMPDataGenerator.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 11, 2013 2085 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class FFMPRowGenerator implements Runnable {
|
||||
|
||||
private static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FFMPRowGenerator.class);
|
||||
|
||||
private static final String NA = "NA";
|
||||
|
||||
// values specific to this row
|
||||
private FFMPBasin cBasin;
|
||||
|
||||
private FFMPTableData tData;
|
||||
|
||||
private boolean isVGB;
|
||||
|
||||
private String domain;
|
||||
|
||||
// values shared between all rows
|
||||
private final String siteKey;
|
||||
|
||||
private final Date paintRefTime;
|
||||
|
||||
private final Object centeredAggregationKey;
|
||||
|
||||
private final String huc;
|
||||
|
||||
private final double sliderTime;
|
||||
|
||||
private boolean isWorstCase = false;
|
||||
|
||||
private FFMPTemplates ft = null;
|
||||
|
||||
private FFMPResource resource = null;
|
||||
|
||||
private FFMPMonitor monitor = null;
|
||||
|
||||
private FFMPBasinData qpeBasin = null;
|
||||
|
||||
private FFMPBasinData qpfBasin = null;
|
||||
|
||||
private FFMPBasinData rateBasin = null;
|
||||
|
||||
private Map<String, FFMPBasinData> guidBasins = null;
|
||||
|
||||
private FFMPBasinData virtualBasin = null;
|
||||
|
||||
private Map<String, FFMPRecord> guidRecords = null;
|
||||
|
||||
protected FFMPRecord baseRec = null;
|
||||
|
||||
private boolean isRate = false;
|
||||
|
||||
private long expirationTime = 0l;
|
||||
|
||||
private String[] cwaArr = null;
|
||||
|
||||
private Map<String, FFFGForceUtil> forceUtils = null;
|
||||
|
||||
private FfmpTableConfigData ffmpTableCfgData = null;
|
||||
|
||||
public FFMPRowGenerator(FFMPDataGenerator parent, FFMPBasin cBasin,
|
||||
FFMPTableData tData, boolean isVGB, String domain) {
|
||||
// these are the values related to this specific row
|
||||
this.cBasin = cBasin;
|
||||
this.tData = tData;
|
||||
this.isVGB = isVGB;
|
||||
this.domain = domain;
|
||||
|
||||
// these are the values shared between all rows
|
||||
this.siteKey = parent.siteKey;
|
||||
this.paintRefTime = parent.paintRefTime;
|
||||
this.centeredAggregationKey = parent.centeredAggregationKey;
|
||||
this.huc = parent.huc;
|
||||
this.sliderTime = parent.sliderTime;
|
||||
this.isWorstCase = parent.isWorstCase;
|
||||
this.ft = parent.ft;
|
||||
this.resource = parent.resource;
|
||||
this.monitor = parent.monitor;
|
||||
this.qpeBasin = parent.qpeBasin;
|
||||
this.qpfBasin = parent.qpfBasin;
|
||||
this.rateBasin = parent.rateBasin;
|
||||
this.guidBasins = parent.guidBasins;
|
||||
this.virtualBasin = parent.virtualBasin;
|
||||
this.guidRecords = parent.guidRecords;
|
||||
this.baseRec = parent.baseRec;
|
||||
this.isRate = parent.isRate;
|
||||
this.expirationTime = parent.expirationTime;
|
||||
this.cwaArr = parent.cwaArr;
|
||||
this.forceUtils = parent.forceUtils;
|
||||
this.ffmpTableCfgData = parent.ffmpTableCfgData;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
String displayName = "";
|
||||
String mouseOverText = "";
|
||||
|
||||
FFMPTableRowData trd = new FFMPTableRowData(
|
||||
ffmpTableCfgData.getTableColumnKeys().length);
|
||||
|
||||
Float guidance = Float.NaN;
|
||||
Float qpe = Float.NaN;
|
||||
Float rate = Float.NaN;
|
||||
Float qpf = Float.NaN;
|
||||
FIELDS rowField = FIELDS.NAME;
|
||||
|
||||
if (isVGB) {
|
||||
rowField = FIELDS.VIRTUAL;
|
||||
}
|
||||
|
||||
if (cBasin instanceof FFMPVirtualGageBasin) {
|
||||
rowField = FIELDS.VIRTUAL;
|
||||
|
||||
FFMPVirtualGageBasin vgBasin = (FFMPVirtualGageBasin) cBasin;
|
||||
|
||||
String lid = vgBasin.getLid();
|
||||
|
||||
if (lid != null) {
|
||||
StringBuilder sb = new StringBuilder(lid);
|
||||
// in this special case it is actually the LID
|
||||
trd.setPfaf(lid);
|
||||
FFMPVirtualGageBasinMetaData fvgmbd = ft
|
||||
.getVirtualGageBasinMetaData(siteKey, lid);
|
||||
FFMPBasinMetaData metabasin = ft.getBasin(siteKey,
|
||||
fvgmbd.getParentPfaf());
|
||||
Long parentBasinPfaf = fvgmbd.getParentPfaf();
|
||||
|
||||
mouseOverText = metabasin.getBasinId() + "\n" + lid + "-"
|
||||
+ fvgmbd.getName();
|
||||
|
||||
if (!huc.equals(FFMPRecord.ALL)) {
|
||||
sb.append("-").append(fvgmbd.getName());
|
||||
}
|
||||
|
||||
trd.setTableCellData(0,
|
||||
new FFMPTableCellData(rowField, sb.toString(),
|
||||
mouseOverText));
|
||||
|
||||
if (!isWorstCase || huc.equals(FFMPRecord.ALL)
|
||||
|| (centeredAggregationKey != null)) {
|
||||
|
||||
if (!cBasin.getValues().isEmpty()) {
|
||||
rate = vgBasin.getValue(paintRefTime);
|
||||
if (sliderTime > 0.00) {
|
||||
FFMPTimeWindow window = monitor.getQpeWindow();
|
||||
qpe = cBasin.getAccumValue(window.getAfterTime(),
|
||||
window.getBeforeTime(), expirationTime,
|
||||
isRate);
|
||||
} else {
|
||||
qpe = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(1, new FFMPTableCellData(FIELDS.RATE,
|
||||
rate));
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE,
|
||||
qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
FFMPBasin basin = qpfBasin.get(parentBasinPfaf);
|
||||
if (basin != null) {
|
||||
FFMPTimeWindow window = monitor.getQpfWindow();
|
||||
qpf = basin.getAverageValue(window.getAfterTime(),
|
||||
window.getBeforeTime());
|
||||
}
|
||||
}
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF,
|
||||
qpf));
|
||||
|
||||
// run over each guidance type
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
|
||||
FFMPTableCellData guidCellData = getGuidanceCellData(
|
||||
cBasin, domain, guidType, parentBasinPfaf);
|
||||
if (guidCellData == null) {
|
||||
// check for forcing even if no data are available
|
||||
guidance = getForcedAvg(domain, cBasin, guidType);
|
||||
boolean forced = !guidance.isNaN();
|
||||
guidCellData = new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced);
|
||||
} else {
|
||||
guidance = guidCellData.getValueAsFloat();
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, guidCellData);
|
||||
|
||||
float ratioValue = Float.NaN;
|
||||
float diffValue = Float.NaN;
|
||||
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
|
||||
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, diffValue));
|
||||
i += 3;
|
||||
}
|
||||
} else {
|
||||
trd = getMaxValue(trd, cBasin);
|
||||
}
|
||||
|
||||
trd.setSortCallback(tData);
|
||||
tData.addDataRow(trd);
|
||||
}
|
||||
} else {
|
||||
displayName = getDisplayName(cBasin);
|
||||
if (displayName != null) {
|
||||
long cBasinPfaf = cBasin.getPfaf();
|
||||
String cBasinPfafStr = Long.toString(cBasinPfaf);
|
||||
StringBuilder sb = new StringBuilder(cBasinPfafStr);
|
||||
sb.append("\n").append(displayName);
|
||||
trd.setPfaf(cBasinPfafStr);
|
||||
trd.setTableCellData(0, new FFMPTableCellData(rowField,
|
||||
displayName, sb.toString()));
|
||||
|
||||
if (!isWorstCase || huc.equals(FFMPRecord.ALL)
|
||||
|| (centeredAggregationKey != null)) {
|
||||
if (rateBasin != null) {
|
||||
FFMPBasin basin = rateBasin.get(cBasinPfaf);
|
||||
if (basin != null) {
|
||||
rate = basin.getValue(paintRefTime);
|
||||
}
|
||||
}
|
||||
trd.setTableCellData(1, new FFMPTableCellData(FIELDS.RATE,
|
||||
rate));
|
||||
|
||||
if (qpeBasin != null) {
|
||||
FFMPBasin basin = qpeBasin.get(cBasinPfaf);
|
||||
if (basin != null) {
|
||||
FFMPTimeWindow window = monitor.getQpeWindow();
|
||||
qpe = basin.getAccumValue(window.getAfterTime(),
|
||||
window.getBeforeTime(), expirationTime,
|
||||
isRate);
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE,
|
||||
qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
FFMPBasin basin = qpfBasin.get(cBasinPfaf);
|
||||
if (basin != null) {
|
||||
FFMPTimeWindow window = monitor.getQpfWindow();
|
||||
qpf = basin.getAverageValue(window.getAfterTime(),
|
||||
window.getBeforeTime());
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF,
|
||||
qpf));
|
||||
|
||||
// run over each guidance type
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
FFMPTableCellData guidCellData = getGuidanceCellData(
|
||||
cBasin, domain, guidType, cBasinPfaf);
|
||||
if (guidCellData == null) {
|
||||
// check for forcing even if no data are available
|
||||
guidance = getForcedAvg(domain, cBasin, guidType);
|
||||
boolean forced = !guidance.isNaN();
|
||||
guidCellData = new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced);
|
||||
} else {
|
||||
guidance = guidCellData.getValueAsFloat();
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, guidCellData);
|
||||
|
||||
float ratioValue = Float.NaN;
|
||||
float diffValue = Float.NaN;
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
|
||||
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, diffValue));
|
||||
|
||||
i += 3;
|
||||
}
|
||||
} else {
|
||||
trd = getMaxValue(trd, cBasin);
|
||||
}
|
||||
|
||||
trd.setSortCallback(tData);
|
||||
tData.addDataRow(trd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Regular basin display name
|
||||
*
|
||||
* @param basin
|
||||
* @return
|
||||
*/
|
||||
private String getDisplayName(FFMPBasin basin) {
|
||||
String name = null;
|
||||
|
||||
try {
|
||||
if (huc.equals(FFMPRecord.ALL) || (centeredAggregationKey != null)) {
|
||||
name = ft.getBasin(siteKey, basin.getPfaf()).getStreamName();
|
||||
}
|
||||
// aggregations
|
||||
else {
|
||||
|
||||
ArrayList<Long> pfafs = ft.getAggregatePfafs(basin.getPfaf(),
|
||||
siteKey, huc);
|
||||
if (!pfafs.isEmpty()) {
|
||||
if (huc.equals(FFMPRecord.COUNTY)) {
|
||||
name = ft.getCountyStateName(siteKey, basin.getPfaf());
|
||||
} else {
|
||||
for (int i = 0; i < pfafs.size(); i++) {
|
||||
if (ft.getBasin(siteKey, pfafs.get(0)).getHucName() != null) {
|
||||
name = ft.getBasin(siteKey, pfafs.get(0))
|
||||
.getHucName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.WARN, "No display name for basin.."
|
||||
+ basin.getPfaf());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private FFMPTableRowData getMaxValue(FFMPTableRowData trd, FFMPBasin cBasin) {
|
||||
ArrayList<DomainXML> domainList = FFMPRunConfigurationManager
|
||||
.getInstance().getDomains();
|
||||
ArrayList<DomainXML> activeDomains = new ArrayList<DomainXML>();
|
||||
for (DomainXML domainXml : domainList) {
|
||||
for (String cwa : cwaArr) {
|
||||
if (domainXml.getCwa().equalsIgnoreCase(cwa)) {
|
||||
activeDomains.add(domainXml);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Long> pfafs = ft.getAggregatePfafs(cBasin.getPfaf(), siteKey,
|
||||
huc, activeDomains);
|
||||
trd.setPfaf(cBasin.getPfaf().toString());
|
||||
Float qpe = Float.NaN;
|
||||
Float guidance = Float.NaN;
|
||||
Float rate = Float.NaN;
|
||||
Float qpf = Float.NaN;
|
||||
Float ratioValue = Float.NaN;
|
||||
Float diffValue = Float.NaN;
|
||||
|
||||
if (cBasin instanceof FFMPVirtualGageBasin) {
|
||||
if (!pfafs.isEmpty()) {
|
||||
if (virtualBasin != null) {
|
||||
rate = virtualBasin.get(cBasin.getPfaf()).getValue(
|
||||
paintRefTime);
|
||||
|
||||
if (sliderTime > 0.00) {
|
||||
qpe = virtualBasin.get(cBasin.getPfaf()).getAccumValue(
|
||||
monitor.getQpeWindow().getAfterTime(),
|
||||
monitor.getQpeWindow().getBeforeTime(),
|
||||
expirationTime, isRate);
|
||||
} else {
|
||||
qpe = 0.0f;
|
||||
}
|
||||
}
|
||||
trd.setTableCellData(1,
|
||||
new FFMPTableCellData(FIELDS.RATE, rate));
|
||||
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
qpf = new Float(qpfBasin.get(cBasin.getPfaf()).getMaxValue(
|
||||
monitor.getQpfWindow().getAfterTime(),
|
||||
monitor.getQpfWindow().getBeforeTime()))
|
||||
.floatValue();
|
||||
}
|
||||
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF, qpf));
|
||||
|
||||
processGuidance(trd, cBasin, pfafs, qpe);
|
||||
}
|
||||
} else {
|
||||
// Not Virtual
|
||||
if (!pfafs.isEmpty()) {
|
||||
if (rateBasin != null) {
|
||||
rate = rateBasin.getMaxValue(pfafs, paintRefTime);
|
||||
}
|
||||
trd.setTableCellData(1,
|
||||
new FFMPTableCellData(FIELDS.RATE, rate));
|
||||
|
||||
if (qpeBasin != null) {
|
||||
qpe = qpeBasin.getAccumMaxValue(pfafs, monitor
|
||||
.getQpeWindow().getBeforeTime(), monitor
|
||||
.getQpeWindow().getAfterTime(), expirationTime,
|
||||
isRate);
|
||||
}
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe));
|
||||
|
||||
if (qpfBasin != null) {
|
||||
qpf = qpfBasin.getAverageMaxValue(pfafs, monitor
|
||||
.getQpfWindow().getAfterTime(), monitor
|
||||
.getQpfWindow().getBeforeTime());
|
||||
|
||||
// qpf = getQPFValue(true, new Long(0l), pfafs);/* DR13839
|
||||
// */
|
||||
}
|
||||
trd.setTableCellData(3,
|
||||
new FFMPTableCellData(FIELDS.QPF, qpf.floatValue()));
|
||||
|
||||
// run over each guidance type
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
diffValue = Float.NaN;
|
||||
ratioValue = Float.NaN;
|
||||
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
FFMPBasinData guidBasin = guidBasins.get(guidType);
|
||||
|
||||
List<Long> pfafList = new ArrayList<Long>();
|
||||
if (cBasin.getAggregated()) {
|
||||
pfafList = ft.getAggregatePfafs(cBasin.getPfaf(),
|
||||
siteKey, huc);
|
||||
pfafList.add(ft.getAggregatedPfaf(cBasin.getPfaf(),
|
||||
siteKey, huc));
|
||||
}
|
||||
|
||||
boolean forced = false;
|
||||
List<Long> forcedPfafs = new ArrayList<Long>();
|
||||
FFFGDataMgr fdm = FFFGDataMgr.getInstance();
|
||||
|
||||
if (fdm.isForcingConfigured()) {
|
||||
ForceUtilResult forceResult = forceUtil
|
||||
.calculateForcings(pfafList, ft, cBasin);
|
||||
forcedPfafs = forceResult.getForcedPfafList();
|
||||
forced = forceResult.isForced();
|
||||
}
|
||||
|
||||
if (!forced) {
|
||||
if ((forcedPfafs != null) && (!forcedPfafs.isEmpty())) {
|
||||
forced = true;
|
||||
}
|
||||
}
|
||||
if ((guidBasin != null)
|
||||
&& (!guidBasin.getBasins().isEmpty())) {
|
||||
|
||||
if (isWorstCase) {
|
||||
guidance = guidRecords
|
||||
.get(guidType)
|
||||
.getBasinData(FFMPRecord.ALL)
|
||||
.getMaxGuidanceValue(
|
||||
pfafs,
|
||||
resource.getGuidanceInterpolators()
|
||||
.get(guidType),
|
||||
resource.getGuidSourceExpiration(guidType),
|
||||
cBasin.getPfaf());
|
||||
} else {
|
||||
FFMPGuidanceBasin basin = (FFMPGuidanceBasin) guidRecords
|
||||
.get(guidType).getBasinData(huc)
|
||||
.get(cBasin.getPfaf());
|
||||
guidance = resource.getGuidanceValue(basin, monitor
|
||||
.getQpeWindow().getBeforeTime(), guidType);
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced));
|
||||
} else {
|
||||
if (forced) {
|
||||
// Recalculate guidance using the forced value(s)
|
||||
guidance = forceUtil.getMaxForcedValue(
|
||||
pfafList,
|
||||
forcedPfafs,
|
||||
resource.getGuidanceInterpolators().get(
|
||||
guidType), resource
|
||||
.getGuidSourceExpiration(guidType),
|
||||
ft);
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced));
|
||||
}
|
||||
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
|
||||
List<Float> qpes = qpeBasin.getAccumValues(pfafs,
|
||||
monitor.getQpeWindow().getAfterTime(), monitor
|
||||
.getQpeWindow().getBeforeTime(),
|
||||
expirationTime, isRate);
|
||||
List<Float> guids = null;
|
||||
if (guidBasin != null) {
|
||||
guids = guidBasin.getGuidanceValues(pfafs, resource
|
||||
.getGuidanceInterpolators().get(guidType),
|
||||
resource.getGuidSourceExpiration(guidType));
|
||||
} else if (forced) {
|
||||
guids = forceUtil.getForcedGuidValues(
|
||||
pfafList,
|
||||
forcedPfafs,
|
||||
resource.getGuidanceInterpolators().get(
|
||||
guidType), resource
|
||||
.getGuidSourceExpiration(guidType),
|
||||
ft);
|
||||
}
|
||||
|
||||
if ((!qpes.isEmpty())
|
||||
&& ((guids != null) && (!guids.isEmpty()))) {
|
||||
ratioValue = FFMPUtils
|
||||
.getMaxRatioValue(qpes, guids);
|
||||
diffValue = FFMPUtils.getMaxDiffValue(qpes, guids);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, diffValue));
|
||||
} else {
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(
|
||||
FIELDS.RATIO, Float.NaN));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(
|
||||
FIELDS.DIFF, Float.NaN));
|
||||
}
|
||||
|
||||
i += 3;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((rateBasin != null)
|
||||
&& (rateBasin.get(cBasin.getPfaf()) != null)) {
|
||||
rate = rateBasin.get(cBasin.getPfaf()).getValue(
|
||||
paintRefTime);
|
||||
}
|
||||
trd.setTableCellData(1,
|
||||
new FFMPTableCellData(FIELDS.RATE, rate));
|
||||
|
||||
if ((qpeBasin != null)
|
||||
&& (qpeBasin.get(cBasin.getPfaf()) != null)) {
|
||||
qpe = qpeBasin.get(cBasin.getPfaf()).getAccumValue(
|
||||
monitor.getQpeWindow().getAfterTime(),
|
||||
monitor.getQpeWindow().getBeforeTime(),
|
||||
expirationTime, isRate);
|
||||
}
|
||||
trd.setTableCellData(2, new FFMPTableCellData(FIELDS.QPE, qpe));
|
||||
|
||||
if ((qpfBasin != null)
|
||||
&& (qpfBasin.get(cBasin.getPfaf()) != null)) {
|
||||
qpf = new Float(qpfBasin.get(cBasin.getPfaf()).getMaxValue(
|
||||
monitor.getQpfWindow().getAfterTime(),
|
||||
monitor.getQpfWindow().getBeforeTime()))
|
||||
.floatValue();
|
||||
}
|
||||
trd.setTableCellData(3, new FFMPTableCellData(FIELDS.QPF, qpf));
|
||||
|
||||
processGuidance(trd, cBasin, pfafs, qpe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return trd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trd
|
||||
* @param cBasin
|
||||
* @param pfafs
|
||||
* @param qpe
|
||||
*/
|
||||
private void processGuidance(FFMPTableRowData trd, FFMPBasin cBasin,
|
||||
ArrayList<Long> pfafs, Float qpe) {
|
||||
Float guidance;
|
||||
Float ratioValue;
|
||||
Float diffValue;
|
||||
int i = 0;
|
||||
for (String guidType : guidBasins.keySet()) {
|
||||
guidance = Float.NaN;
|
||||
diffValue = Float.NaN;
|
||||
ratioValue = Float.NaN;
|
||||
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
FFMPBasinData guidBasin = guidBasins.get(guidType);
|
||||
|
||||
if (guidBasin != null) {
|
||||
|
||||
FFMPGuidanceBasin basin = ((FFMPGuidanceBasin) guidBasin
|
||||
.get(cBasin.getPfaf()));
|
||||
guidance = resource.getGuidanceValue(basin, monitor
|
||||
.getQpeWindow().getBeforeTime(), guidType);
|
||||
|
||||
if (guidance < 0.0f) {
|
||||
guidance = Float.NaN;
|
||||
}
|
||||
|
||||
ForceUtilResult forceResult = forceUtil.calculateForcings(
|
||||
pfafs, ft, cBasin);
|
||||
|
||||
List<Long> forcedPfafs = forceResult.getForcedPfafList();
|
||||
boolean forced = forceResult.isForced();
|
||||
|
||||
if (!forced) {
|
||||
if ((forcedPfafs != null) && (!forcedPfafs.isEmpty())) {
|
||||
forced = true;
|
||||
}
|
||||
}
|
||||
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, guidance, forced));
|
||||
} else {
|
||||
trd.setTableCellData(i + 4, new FFMPTableCellData(
|
||||
FIELDS.GUIDANCE, Float.NaN));
|
||||
}
|
||||
|
||||
// If guidance is NaN then it cannot be > 0
|
||||
if (!qpe.isNaN() && (guidance > 0.0f)) {
|
||||
ratioValue = FFMPUtils.getRatioValue(qpe, guidance);
|
||||
diffValue = FFMPUtils.getDiffValue(qpe, guidance);
|
||||
}
|
||||
trd.setTableCellData(i + 5, new FFMPTableCellData(FIELDS.RATIO,
|
||||
ratioValue));
|
||||
trd.setTableCellData(i + 6, new FFMPTableCellData(FIELDS.DIFF,
|
||||
diffValue));
|
||||
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
|
||||
private float getForcedAvg(String domain, FFMPBasin cBasin, String guidType) {
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
FFFGDataMgr fdm = FFFGDataMgr.getInstance();
|
||||
List<Long> forcedPfafs;
|
||||
List<Long> pfafList = new ArrayList<Long>();
|
||||
float guidance = Float.NaN;
|
||||
|
||||
boolean forced = false;
|
||||
if (fdm.isForcingConfigured()) {
|
||||
ForceUtilResult forceResult = forceUtil.calculateForcings(domain,
|
||||
ft, cBasin);
|
||||
forcedPfafs = forceResult.getForcedPfafList();
|
||||
forced = forceResult.isForced();
|
||||
if (!forced) {
|
||||
return Float.NaN;
|
||||
}
|
||||
} else {
|
||||
return Float.NaN;
|
||||
}
|
||||
|
||||
if (cBasin.getAggregated()) {
|
||||
if (domain == null) {
|
||||
pfafList = ft.getAggregatePfafs(cBasin.getPfaf(), siteKey, huc);
|
||||
} else if (!domain.equals(NA)) {
|
||||
if (!huc.equals(FFMPRecord.ALL)) {
|
||||
pfafList = ft.getAggregatePfafsByDomain(cBasin.getPfaf(),
|
||||
siteKey, domain, huc);
|
||||
}
|
||||
} else {
|
||||
pfafList = ft.getAggregatePfafsByDomain(cBasin.getPfaf(),
|
||||
siteKey, domain, huc);
|
||||
pfafList.add(ft.getAggregatedPfaf(cBasin.getPfaf(), siteKey,
|
||||
huc));
|
||||
}
|
||||
}
|
||||
|
||||
if (!isWorstCase || huc.equals(FFMPRecord.ALL)
|
||||
|| (centeredAggregationKey != null)) {
|
||||
if (((forcedPfafs.size() > 1)) || forced) {
|
||||
// Calculate an average
|
||||
guidance = forceUtil.getAvgForcedValue(pfafList, forcedPfafs,
|
||||
resource.getGuidanceInterpolators().get(guidType),
|
||||
resource.getGuidSourceExpiration(guidType), ft);
|
||||
}
|
||||
} else {
|
||||
// TODO Calculate a max value
|
||||
|
||||
}
|
||||
|
||||
return guidance;
|
||||
}
|
||||
|
||||
private FFMPTableCellData getGuidanceCellData(FFMPBasin cBasin,
|
||||
String domain, String guidType, Long parentBasinPfaf) {
|
||||
long cBasinPfaf = cBasin.getPfaf();
|
||||
|
||||
FFMPBasinData guidBasin = guidBasins.get(guidType);
|
||||
|
||||
FFMPGuidanceBasin ffmpGuidBasin = null;
|
||||
if (guidBasin != null) {
|
||||
ffmpGuidBasin = (FFMPGuidanceBasin) guidBasin.get(cBasinPfaf);
|
||||
}
|
||||
|
||||
if (ffmpGuidBasin == null) {
|
||||
return null;
|
||||
}
|
||||
List<Long> pfafList = Collections.emptyList();
|
||||
List<Long> forcedPfafs = Collections.emptyList();
|
||||
boolean forced = false;
|
||||
Float guidance = Float.NaN;
|
||||
FFFGForceUtil forceUtil = forceUtils.get(guidType);
|
||||
forceUtil.setSliderTime(sliderTime);
|
||||
|
||||
// If aggregate, get basins within the aggregate
|
||||
if (cBasin.getAggregated()) {
|
||||
if (domain == null) {
|
||||
pfafList = ft.getAggregatePfafs(cBasinPfaf, siteKey, huc);
|
||||
} else if (!domain.equals(NA)) {
|
||||
if (!huc.equals(FFMPRecord.ALL)) {
|
||||
pfafList = ft.getAggregatePfafsByDomain(parentBasinPfaf,
|
||||
siteKey, domain, huc);
|
||||
}
|
||||
} else {
|
||||
pfafList = ft.getAggregatePfafsByDomain(parentBasinPfaf,
|
||||
siteKey, domain, huc);
|
||||
pfafList.add(ft.getAggregatedPfaf(cBasinPfaf, siteKey, huc));
|
||||
}
|
||||
} else {
|
||||
pfafList = new ArrayList<Long>();
|
||||
pfafList.add(cBasinPfaf);
|
||||
}
|
||||
|
||||
if (FFFGDataMgr.getInstance().isForcingConfigured()) {
|
||||
FFMPBasin parentBasin = cBasin;
|
||||
if (cBasinPfaf != parentBasinPfaf.longValue()) {
|
||||
parentBasin = baseRec.getBasinData(FFMPRecord.ALL).get(
|
||||
parentBasinPfaf);
|
||||
}
|
||||
ForceUtilResult forceResult = forceUtil.calculateForcings(domain,
|
||||
ft, parentBasin);
|
||||
forcedPfafs = forceResult.getForcedPfafList();
|
||||
forced = forceResult.isForced();
|
||||
}
|
||||
|
||||
if (!forcedPfafs.isEmpty() || forced || !pfafList.isEmpty()) {
|
||||
// Recalculate guidance using the forced value(s)
|
||||
guidance = guidRecords
|
||||
.get(guidType)
|
||||
.getBasinData(FFMPRecord.ALL)
|
||||
.getAverageGuidanceValue(pfafList,
|
||||
resource.getGuidanceInterpolators().get(guidType),
|
||||
guidance, forcedPfafs,
|
||||
resource.getGuidSourceExpiration(guidType));
|
||||
} else {
|
||||
if (ffmpGuidBasin != null) {
|
||||
guidance = resource.getGuidanceValue(ffmpGuidBasin,
|
||||
paintRefTime, guidType);
|
||||
|
||||
if (guidance < 0.0f) {
|
||||
guidance = Float.NaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new FFMPTableCellData(FIELDS.GUIDANCE, guidance, forced);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.rsc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Holds the results of calculating forcings from the FFFGForceUtil.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 17, 2013 2085 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class ForceUtilResult {
|
||||
|
||||
protected boolean forced;
|
||||
|
||||
protected List<Long> pfafList;
|
||||
|
||||
protected List<Long> forcedPfafList;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param forced
|
||||
* @param pfafList
|
||||
* @param forcedPfafList
|
||||
*/
|
||||
protected ForceUtilResult(boolean forced, List<Long> pfafList,
|
||||
List<Long> forcedPfafList) {
|
||||
this.forced = forced;
|
||||
this.pfafList = pfafList;
|
||||
this.forcedPfafList = forcedPfafList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the forced
|
||||
*/
|
||||
public boolean isForced() {
|
||||
return forced;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the forcedPfafList
|
||||
*/
|
||||
public List<Long> getForcedPfafList() {
|
||||
return forcedPfafList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pfafList
|
||||
*/
|
||||
public List<Long> getPfafList() {
|
||||
return pfafList;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,313 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.thread;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.FFMPRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductXML;
|
||||
import com.raytheon.uf.common.monitor.xml.SourceXML;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.FFMPMonitor;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResourceData;
|
||||
|
||||
/**
|
||||
* FFMP load job that retrieves and loads data. Created by refactoring and
|
||||
* separating out the logic in the FFMPDataLoader.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 04, 2013 2075 njensen Initial creation
|
||||
* Jun 07, 2013 2075 njensen Added progress monitoring
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class AbstractLoadJob extends Job {
|
||||
|
||||
protected static final int PROGRESS_FACTOR = 10;
|
||||
|
||||
protected static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(AbstractLoadJob.class);
|
||||
|
||||
protected ProductXML product = null;
|
||||
|
||||
protected ProductRunXML productRun;
|
||||
|
||||
protected FFMPResourceData resourceData;
|
||||
|
||||
// TODO contemplate making the two times into a TimeRange
|
||||
protected Date startTime = null;
|
||||
|
||||
protected Date endTime = null;
|
||||
|
||||
protected FFMPMonitor ffmpMonitor;
|
||||
|
||||
protected List<String> hucsToLoad = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name
|
||||
* name of the job
|
||||
* @param resourceData
|
||||
* the resource data that is loading
|
||||
* @param timeBack
|
||||
* the oldest time to load data for
|
||||
* @param mostRecentTime
|
||||
* the newest time to load for
|
||||
* @param hucsToLoad
|
||||
* the hucs to load
|
||||
*/
|
||||
public AbstractLoadJob(String name, FFMPResourceData resourceData,
|
||||
Date timeBack, Date mostRecentTime, List<String> hucsToLoad) {
|
||||
super(name);
|
||||
this.setSystem(false);
|
||||
|
||||
this.resourceData = resourceData;
|
||||
this.startTime = timeBack;
|
||||
this.endTime = mostRecentTime;
|
||||
this.hucsToLoad = hucsToLoad;
|
||||
|
||||
// configure FFMP
|
||||
this.hucsToLoad.remove(FFMPRecord.VIRTUAL);
|
||||
FFMPRunXML runXML = FFMPRunConfigurationManager.getInstance()
|
||||
.getRunner(resourceData.wfo);
|
||||
this.productRun = runXML.getProduct(resourceData.siteKey);
|
||||
this.product = resourceData.getProduct();
|
||||
this.ffmpMonitor = FFMPMonitor.getInstance();
|
||||
|
||||
// just for debugging/logging
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name);
|
||||
sb.append(" hucs to load: ");
|
||||
Iterator<String> itr = this.hucsToLoad.iterator();
|
||||
while (itr.hasNext()) {
|
||||
sb.append(itr.next());
|
||||
if (itr.hasNext()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
System.out.println(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads the available URIs. Should NOT be called by the update job.
|
||||
*/
|
||||
protected void preloadAvailableUris() {
|
||||
// preload all the uris except guidance. Guidance loads data
|
||||
// much further back and it is not efficient to group with the
|
||||
// rest.
|
||||
Set<String> sources = new HashSet<String>();
|
||||
sources.add(product.getRate());
|
||||
sources.add(product.getQpe());
|
||||
sources.add(product.getVirtual());
|
||||
for (String qpfType : productRun.getQpfTypes(product)) {
|
||||
for (SourceXML qpfSource : productRun.getQpfSources(product,
|
||||
qpfType)) {
|
||||
sources.add(qpfSource.getSourceName());
|
||||
}
|
||||
}
|
||||
ffmpMonitor.preloadAvailableUris(resourceData.siteKey,
|
||||
resourceData.dataKey, sources, startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and processes the rate URIs. Should only be used by the initial job
|
||||
* and update jobs.
|
||||
*/
|
||||
protected void doRate() {
|
||||
String rateURI = null;
|
||||
if (!product.getRate().equals(product.getQpe())) {
|
||||
Map<Date, List<String>> rateURIs = ffmpMonitor.getAvailableUris(
|
||||
resourceData.siteKey, resourceData.dataKey,
|
||||
product.getRate(), endTime);
|
||||
if (rateURIs.containsKey(endTime)) {
|
||||
rateURI = rateURIs.get(endTime).get(0);
|
||||
}
|
||||
}
|
||||
if (rateURI != null) {
|
||||
for (String phuc : hucsToLoad) {
|
||||
ffmpMonitor.processUri(rateURI, resourceData.siteKey,
|
||||
product.getRate(), startTime, phuc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available QPE URIs
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected NavigableMap<Date, List<String>> getQpeUris() {
|
||||
return ffmpMonitor.getAvailableUris(resourceData.siteKey,
|
||||
resourceData.dataKey, product.getQpe(), startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the qpe URIs
|
||||
*
|
||||
* @param qpeURIs
|
||||
*/
|
||||
protected void doQpe(NavigableMap<Date, List<String>> qpeURIs,
|
||||
SubMonitor smonitor) {
|
||||
if (!qpeURIs.isEmpty()) {
|
||||
smonitor.beginTask(null, hucsToLoad.size() * PROGRESS_FACTOR);
|
||||
for (String phuc : hucsToLoad) {
|
||||
ffmpMonitor.processUris(qpeURIs, resourceData.siteKey,
|
||||
product.getQpe(), startTime, phuc,
|
||||
smonitor.newChild(PROGRESS_FACTOR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available QPF URIs for a particular source
|
||||
*
|
||||
* @param sourceName
|
||||
* @param qpfTime
|
||||
* @return
|
||||
*/
|
||||
protected NavigableMap<Date, List<String>> getQpfUris(String sourceName,
|
||||
Date qpfTime) {
|
||||
return ffmpMonitor.getAvailableUris(resourceData.siteKey,
|
||||
resourceData.dataKey, sourceName, qpfTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available QPF URIs for all sources
|
||||
*
|
||||
* @param qpfTime
|
||||
* @return
|
||||
*/
|
||||
protected List<NavigableMap<Date, List<String>>> getQpfUris(Date qpfTime) {
|
||||
ArrayList<NavigableMap<Date, List<String>>> qpfs = new ArrayList<NavigableMap<Date, List<String>>>();
|
||||
for (String qpfType : productRun.getQpfTypes(product)) {
|
||||
for (SourceXML qpfSource : productRun.getQpfSources(product,
|
||||
qpfType)) {
|
||||
NavigableMap<Date, List<String>> qpfURIs = getQpfUris(
|
||||
qpfSource.getSourceName(), qpfTime);
|
||||
|
||||
if (qpfURIs != null && !qpfURIs.isEmpty()) {
|
||||
qpfs.add(qpfURIs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qpfs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the QPF URIs
|
||||
*
|
||||
* @param qpfURIs
|
||||
* @param productQpf
|
||||
*/
|
||||
protected void doQpf(NavigableMap<Date, List<String>> qpfURIs,
|
||||
String productQpf, SubMonitor smonitor) {
|
||||
// Use this method of QPF data retrieval if you don't have cache
|
||||
// files
|
||||
if (!qpfURIs.isEmpty()) {
|
||||
smonitor.beginTask(null, hucsToLoad.size() * PROGRESS_FACTOR);
|
||||
for (String phuc : hucsToLoad) {
|
||||
ffmpMonitor.processUris(qpfURIs, resourceData.siteKey,
|
||||
productQpf, startTime, phuc,
|
||||
smonitor.newChild(PROGRESS_FACTOR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the available virtual URIs
|
||||
*/
|
||||
protected void doVirtual(SubMonitor smonitor) {
|
||||
NavigableMap<Date, List<String>> virtualURIs = ffmpMonitor
|
||||
.getAvailableUris(resourceData.siteKey, resourceData.dataKey,
|
||||
product.getVirtual(), startTime);
|
||||
if (!virtualURIs.isEmpty()) {
|
||||
ffmpMonitor.processUris(virtualURIs, resourceData.siteKey,
|
||||
product.getVirtual(), startTime, FFMPRecord.ALL, smonitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the available guidance URIs for a particular source
|
||||
*
|
||||
* @param sourceName
|
||||
* @param guidTime
|
||||
* @return
|
||||
*/
|
||||
protected NavigableMap<Date, List<String>> getGuidURIs(String sourceName,
|
||||
Date guidTime) {
|
||||
NavigableMap<Date, List<String>> retVal = null;
|
||||
if (guidTime != null) {
|
||||
retVal = ffmpMonitor.getAvailableUris(resourceData.siteKey,
|
||||
resourceData.dataKey, sourceName, guidTime);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and processes the available guidance URIs
|
||||
*
|
||||
* @param guidTime
|
||||
*/
|
||||
protected void doGuidance(Date guidTime, SubMonitor smonitor) {
|
||||
List<String> guidanceTypes = productRun.getGuidanceTypes(product);
|
||||
smonitor.beginTask(null, guidanceTypes.size() * PROGRESS_FACTOR);
|
||||
for (String type : guidanceTypes) {
|
||||
List<SourceXML> guidanceSources = productRun.getGuidanceSources(
|
||||
product, type);
|
||||
int subWork = guidanceSources.size();
|
||||
for (SourceXML guidSource : guidanceSources) {
|
||||
NavigableMap<Date, List<String>> iguidURIs = getGuidURIs(
|
||||
guidSource.getSourceName(), guidTime);
|
||||
if (iguidURIs != null && !iguidURIs.isEmpty()) {
|
||||
ffmpMonitor.processUris(iguidURIs, resourceData.siteKey,
|
||||
guidSource.getSourceName(), startTime,
|
||||
FFMPRecord.ALL,
|
||||
smonitor.newChild(PROGRESS_FACTOR / subWork));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.thread;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResourceData;
|
||||
|
||||
/**
|
||||
* Retrieves and loads FFMP data in the background. Used as the secondary and
|
||||
* tertiary loaders.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 04, 2013 2075 njensen Initial creation
|
||||
* Jun 07, 2013 2075 njensen Added progress monitoring
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class BackgroundLoadJob extends AbstractLoadJob {
|
||||
|
||||
protected boolean preloadAvailableUris = false;
|
||||
|
||||
public BackgroundLoadJob(String name, FFMPResourceData resourceData,
|
||||
Date timeBack, Date mostRecentTime, List<String> hucsToLoad) {
|
||||
super(name, resourceData, timeBack, mostRecentTime, hucsToLoad);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
|
||||
* IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
SubMonitor smonitor = SubMonitor.convert(monitor, "Loading Data", 2500);
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
// preload available URIs
|
||||
smonitor.subTask("Preloading URIs...");
|
||||
if (preloadAvailableUris) {
|
||||
preloadAvailableUris();
|
||||
}
|
||||
smonitor.worked(100);
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
// QPE
|
||||
smonitor.subTask("Processing QPE...");
|
||||
NavigableMap<Date, List<String>> qpeURIs = getQpeUris();
|
||||
smonitor.worked(100);
|
||||
doQpe(qpeURIs, smonitor.newChild(1000));
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
// QPF
|
||||
smonitor.subTask("Processing QPF...");
|
||||
List<NavigableMap<Date, List<String>>> qpfs = getQpfUris(startTime);
|
||||
smonitor.worked(100);
|
||||
SubMonitor qpfmonitor = smonitor.newChild(1000);
|
||||
qpfmonitor.beginTask(null, qpfs.size() * PROGRESS_FACTOR);
|
||||
int i = 0;
|
||||
for (NavigableMap<Date, List<String>> qpfURIs : qpfs) {
|
||||
doQpf(qpfURIs, product.getQpf(i),
|
||||
qpfmonitor.newChild(PROGRESS_FACTOR));
|
||||
i++;
|
||||
}
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
// Virtual
|
||||
smonitor.subTask("Processing Virtual...");
|
||||
doVirtual(smonitor.newChild(200));
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
// Guidance
|
||||
smonitor.subTask("Processing Guidance...");
|
||||
doGuidance(startTime, smonitor.newChild(200));
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
smonitor.done();
|
||||
System.out.println(this.getName() + " took: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
public void setPreloadAvailableUris(boolean preload) {
|
||||
this.preloadAvailableUris = preload;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.thread;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPTemplates;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.HucLevelGeometriesFactory;
|
||||
import com.raytheon.uf.common.monitor.xml.DomainXML;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
||||
/**
|
||||
* Initialization job that initializes the huc level geometries in the
|
||||
* HucLevelGeometriesFactory's internal cache. This is to speed up overall
|
||||
* loading of the display so the FFMPResource's paintInternal() does not have to
|
||||
* wait on these geometries.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 11, 2013 2075 njensen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class InitHucLevelGeomsJob extends Job {
|
||||
|
||||
protected static final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(InitHucLevelGeomsJob.class);
|
||||
|
||||
private String siteKey;
|
||||
|
||||
private FFMPTemplates templates;
|
||||
|
||||
private List<String> hucs;
|
||||
|
||||
public InitHucLevelGeomsJob(String siteKey, FFMPTemplates templates,
|
||||
List<String> hucs) {
|
||||
super("Initializing HUC Level Geometries");
|
||||
this.setSystem(true);
|
||||
this.siteKey = siteKey;
|
||||
this.templates = templates;
|
||||
this.hucs = hucs;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
|
||||
* IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
HucLevelGeometriesFactory hucGeomFactory = HucLevelGeometriesFactory
|
||||
.getInstance();
|
||||
for (DomainXML domain : templates.getDomains()) {
|
||||
String cwa = domain.getCwa();
|
||||
for (String huc : hucs) {
|
||||
try {
|
||||
// since there's only one instance and it caches the
|
||||
// results, this will speed up all future calls to the
|
||||
// factory, ie speed up the initial display
|
||||
hucGeomFactory.getGeometries(templates, siteKey, cwa, huc);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error with early initialization of huc geometries: cwa="
|
||||
+ cwa + ", huc=" + huc, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.thread;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPAggregateRecord;
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPUtils;
|
||||
import com.raytheon.uf.common.datastorage.DataStoreFactory;
|
||||
import com.raytheon.uf.common.datastorage.IDataStore;
|
||||
import com.raytheon.uf.common.datastorage.Request;
|
||||
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
|
||||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPRunConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.config.FFMPSourceConfigurationManager;
|
||||
import com.raytheon.uf.common.monitor.xml.ProductRunXML;
|
||||
import com.raytheon.uf.common.monitor.xml.SourceXML;
|
||||
import com.raytheon.uf.common.serialization.SerializationUtil;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResourceData;
|
||||
|
||||
/**
|
||||
* The initial FFMP load job for the data required initially by the displays.
|
||||
* Attempts to use the FFMPAggregateRecords for faster loading.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 04, 2013 2075 njensen Initial creation
|
||||
* Jun 07, 2013 2075 njensen Added progress monitoring
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class InitialLoadJob extends AbstractLoadJob {
|
||||
|
||||
public InitialLoadJob(FFMPResourceData resourceData, Date timeBack,
|
||||
Date mostRecentTime, List<String> hucsToLoad) {
|
||||
super("Initial FFMP Load", resourceData, timeBack, mostRecentTime,
|
||||
hucsToLoad);
|
||||
this.setPriority(INTERACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
SubMonitor smonitor = SubMonitor.convert(monitor, "Loading Data", 1200);
|
||||
long t0 = System.currentTimeMillis();
|
||||
smonitor.subTask("Preloading URIs...");
|
||||
preloadAvailableUris();
|
||||
smonitor.worked(100);
|
||||
|
||||
// Rate
|
||||
smonitor.subTask("Processing Rate...");
|
||||
doRate();
|
||||
smonitor.worked(200);
|
||||
|
||||
// QPE
|
||||
smonitor.subTask("Processing QPE...");
|
||||
NavigableMap<Date, List<String>> qpeURIs = getQpeUris();
|
||||
FFMPSourceConfigurationManager sourceConfig = this.ffmpMonitor
|
||||
.getSourceConfig();
|
||||
SourceXML source = sourceConfig.getSource(product.getQpe());
|
||||
FFMPAggregateRecord qpeCache = readAggregateRecord(source,
|
||||
resourceData.dataKey, resourceData.wfo);
|
||||
if (qpeCache != null) {
|
||||
this.ffmpMonitor.insertFFMPData(qpeCache, qpeURIs,
|
||||
resourceData.siteKey, product.getQpe());
|
||||
}
|
||||
smonitor.worked(25);
|
||||
doQpe(qpeURIs, smonitor.newChild(225));
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
// QPF
|
||||
smonitor.subTask("Processing QPF...");
|
||||
List<NavigableMap<Date, List<String>>> qpfs = new ArrayList<NavigableMap<Date, List<String>>>();
|
||||
List<SourceXML> qpfSources = new ArrayList<SourceXML>();
|
||||
for (String qpfType : productRun.getQpfTypes(product)) {
|
||||
for (SourceXML qpfSource : productRun.getQpfSources(product,
|
||||
qpfType)) {
|
||||
|
||||
NavigableMap<Date, List<String>> qpfURIs = getQpfUris(
|
||||
qpfSource.getSourceName(), startTime);
|
||||
|
||||
if (qpfURIs != null && !qpfURIs.isEmpty()) {
|
||||
qpfs.add(qpfURIs);
|
||||
qpfSources.add(qpfSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
smonitor.worked(25);
|
||||
SubMonitor qpfmonitor = smonitor.newChild(225);
|
||||
qpfmonitor.beginTask(null, qpfs.size() * PROGRESS_FACTOR);
|
||||
for (NavigableMap<Date, List<String>> qpfURIs : qpfs) {
|
||||
FFMPAggregateRecord qpfCache = null;
|
||||
source = qpfSources.get(i);
|
||||
|
||||
String pdataKey = findQPFHomeDataKey(source);
|
||||
qpfCache = readAggregateRecord(source, pdataKey, resourceData.wfo);
|
||||
|
||||
if (qpfCache != null) {
|
||||
this.ffmpMonitor.insertFFMPData(qpfCache, qpfURIs,
|
||||
resourceData.siteKey, source.getSourceName());
|
||||
}
|
||||
|
||||
doQpf(qpfURIs, product.getQpf(i),
|
||||
qpfmonitor.newChild(PROGRESS_FACTOR));
|
||||
i++;
|
||||
}
|
||||
if (!this.shouldRun()) {
|
||||
return Status.CANCEL_STATUS;
|
||||
}
|
||||
|
||||
// Virtual
|
||||
smonitor.subTask("Processing Virtual...");
|
||||
doVirtual(smonitor.newChild(200));
|
||||
|
||||
// Guidance
|
||||
smonitor.subTask("Processing Guidance...");
|
||||
doGuidance(startTime, smonitor.newChild(200));
|
||||
|
||||
System.out.println("Initial Load Job took: "
|
||||
+ (System.currentTimeMillis() - t0));
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the aggregate files
|
||||
*
|
||||
* @param sourceName
|
||||
* @param huc
|
||||
* @param wfo
|
||||
* @return
|
||||
*/
|
||||
private FFMPAggregateRecord readAggregateRecord(SourceXML source,
|
||||
String pdataKey, String wfo) {
|
||||
|
||||
FFMPAggregateRecord record = null;
|
||||
String sourceSiteDataKey = getSourceSiteDataKey(source, pdataKey);
|
||||
|
||||
try {
|
||||
File hdf5File = FFMPUtils.getHdf5File(wfo, sourceSiteDataKey);
|
||||
IDataStore dataStore = DataStoreFactory.getDataStore(hdf5File);
|
||||
IDataRecord rec = dataStore.retrieve(wfo, sourceSiteDataKey,
|
||||
Request.ALL);
|
||||
byte[] bytes = ((ByteDataRecord) rec).getByteData();
|
||||
record = SerializationUtil.transformFromThrift(
|
||||
FFMPAggregateRecord.class, bytes);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.WARN,
|
||||
"Couldn't read Aggregate Record" + sourceSiteDataKey);
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sourceSiteDataKey for this piece of data
|
||||
*
|
||||
* @param source
|
||||
* @param pdataKey
|
||||
* @return
|
||||
*/
|
||||
private String getSourceSiteDataKey(SourceXML source, String pdataKey) {
|
||||
return source.getSourceName() + "-" + resourceData.siteKey + "-"
|
||||
+ pdataKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the home datakey identifier for QPF sources
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private String findQPFHomeDataKey(SourceXML source) {
|
||||
|
||||
FFMPRunConfigurationManager runManager = FFMPRunConfigurationManager
|
||||
.getInstance();
|
||||
|
||||
for (ProductRunXML product : runManager.getProducts()) {
|
||||
|
||||
try {
|
||||
// we are just checking if it exists or not
|
||||
String pdataKey = product.getProductKey();
|
||||
String sourceSiteDataKey = getSourceSiteDataKey(source,
|
||||
pdataKey);
|
||||
File hdf5File = FFMPUtils.getHdf5File(resourceData.wfo,
|
||||
sourceSiteDataKey);
|
||||
DataStoreFactory.getDataStore(hdf5File);
|
||||
|
||||
return pdataKey;
|
||||
} catch (Exception e) {
|
||||
// not the right key, doesn't exist
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return resourceData.siteKey;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* 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.viz.monitor.ffmp.ui.thread;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.ffmp.FFMPRecord;
|
||||
import com.raytheon.uf.viz.monitor.ffmp.ui.rsc.FFMPResourceData;
|
||||
|
||||
/**
|
||||
* An FFMP load job for when updates arrive.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 04, 2013 2075 njensen Initial creation
|
||||
* Jun 07, 2013 2075 njensen Added progress monitoring
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class UpdateLoadJob extends AbstractLoadJob {
|
||||
|
||||
public UpdateLoadJob(FFMPResourceData resourceData, Date timeBack,
|
||||
Date mostRecentTime, List<String> hucsToLoad) {
|
||||
super("Update FFMP", resourceData, timeBack, mostRecentTime, hucsToLoad);
|
||||
this.setPriority(INTERACTIVE);
|
||||
hucsToLoad.remove(FFMPRecord.VIRTUAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.
|
||||
* IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
SubMonitor smonitor = SubMonitor.convert(monitor, "Loading Data", 1100);
|
||||
// Rate
|
||||
doRate();
|
||||
smonitor.worked(200);
|
||||
|
||||
// QPE
|
||||
NavigableMap<Date, List<String>> qpeURIs = getQpeUris();
|
||||
smonitor.worked(25);
|
||||
doQpe(qpeURIs, smonitor.newChild(250));
|
||||
|
||||
// QPF
|
||||
List<NavigableMap<Date, List<String>>> qpfs = getQpfUris(startTime);
|
||||
smonitor.worked(25);
|
||||
SubMonitor qpfMonitor = smonitor.newChild(225);
|
||||
int i = 0;
|
||||
qpfMonitor.beginTask(null, qpfs.size() * PROGRESS_FACTOR);
|
||||
for (NavigableMap<Date, List<String>> qpfURIs : qpfs) {
|
||||
doQpf(qpfURIs, product.getQpf(i),
|
||||
qpfMonitor.newChild(PROGRESS_FACTOR));
|
||||
i++;
|
||||
}
|
||||
|
||||
// Virtual
|
||||
doVirtual(smonitor.newChild(200));
|
||||
|
||||
// Guidance
|
||||
doGuidance(startTime, smonitor.newChild(200));
|
||||
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NavigableMap<Date, List<String>> getQpfUris(String sourceName,
|
||||
Date qpfTime) {
|
||||
return super.getQpfUris(sourceName, ffmpMonitor.getPreviousQueryTime(
|
||||
resourceData.siteKey, sourceName));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NavigableMap<Date, List<String>> getGuidURIs(String sourceName,
|
||||
Date guidTime) {
|
||||
NavigableMap<Date, List<String>> retVal = null;
|
||||
Date prevTime = ffmpMonitor.getPreviousQueryTime(resourceData.siteKey,
|
||||
sourceName);
|
||||
if (prevTime != null) {
|
||||
retVal = ffmpMonitor.getAvailableUris(resourceData.siteKey,
|
||||
resourceData.dataKey, sourceName, prevTime);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -96,6 +96,7 @@ import com.vividsolutions.jts.geom.LineString;
|
|||
* 10-27-2010 #6964 bkowal The LineStyle is now passed as a parameter to
|
||||
* the IGraphicsTarget drawWireframeShape method.
|
||||
* 15Mar2013 15693 mgamazaychikov Made sure that magnification capability works.
|
||||
* 06-11-2013 DR 16234 D. Friedman Fix pivot index when frames count is reduced.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -215,6 +216,12 @@ public class StormTrackDisplay implements IRenderable {
|
|||
}
|
||||
}
|
||||
|
||||
if (currentState.displayedPivotIndex >= times.length) {
|
||||
currentState.displayedPivotIndex = Math.max(0,
|
||||
currentFrame != times.length - 1 ?
|
||||
times.length - 1 : times.length - 2);
|
||||
}
|
||||
|
||||
currentState.geomChanged = true;
|
||||
target.setNeedsRefresh(true);
|
||||
} else if (lastFrame != -1 && lastFrame != currentFrame) {
|
||||
|
|
|
@ -22,6 +22,7 @@ package com.raytheon.viz.gfe.core.internal;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -112,6 +113,8 @@ import com.raytheon.viz.gfe.core.parm.Parm;
|
|||
* 07/09/09 #2590 njensen Site ID from preferences and sent on all requests.
|
||||
* 09/22/09 #3058 rjpeter Removed GFE Edex dependency.
|
||||
* 05/02/13 #1969 randerso Added createNewDb method
|
||||
* 06/06/13 #2073 dgilling Make getGridInventory() better match A1,
|
||||
* fix warnings.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -255,7 +258,7 @@ public class IFPClient {
|
|||
.asList(new ParmID[] { parmId }));
|
||||
List<TimeRange> times = inventory.get(parmId);
|
||||
if (times == null) {
|
||||
times = new ArrayList<TimeRange>();
|
||||
times = Collections.emptyList();
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
@ -275,7 +278,8 @@ public class IFPClient {
|
|||
throws GFEServerException {
|
||||
GetGridInventoryRequest request = new GetGridInventoryRequest();
|
||||
request.setParmIds(parmIds);
|
||||
ServerResponse<Map<ParmID, List<TimeRange>>> response = (ServerResponse<Map<ParmID, List<TimeRange>>>) makeRequest(request);
|
||||
ServerResponse<Map<ParmID, List<TimeRange>>> response = (ServerResponse<Map<ParmID, List<TimeRange>>>) makeRequest(
|
||||
request, false);
|
||||
return response.getPayload();
|
||||
}
|
||||
|
||||
|
@ -634,7 +638,6 @@ public class IFPClient {
|
|||
return (ServerResponse<List<DatabaseID>>) makeRequest(request);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ActiveTableRecord> getVTECActiveTable(String siteId)
|
||||
throws VizException {
|
||||
CAVEMode mode = dataManager.getOpMode();
|
||||
|
@ -695,6 +698,11 @@ public class IFPClient {
|
|||
|
||||
public ServerResponse<?> makeRequest(AbstractGfeRequest request)
|
||||
throws GFEServerException {
|
||||
return makeRequest(request, true);
|
||||
}
|
||||
|
||||
private ServerResponse<?> makeRequest(AbstractGfeRequest request,
|
||||
boolean throwExceptionsBasedOnResponse) throws GFEServerException {
|
||||
ServerResponse<?> rval = null;
|
||||
|
||||
try {
|
||||
|
@ -716,7 +724,8 @@ public class IFPClient {
|
|||
throw new GFEServerException(e);
|
||||
}
|
||||
|
||||
if ((rval != null) && !rval.isOkay()) {
|
||||
if ((throwExceptionsBasedOnResponse) && (rval != null)
|
||||
&& (!rval.isOkay())) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
if (rval.getMessages().size() > 1) {
|
||||
msg.append("Errors ");
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
@ -52,7 +52,7 @@ import com.raytheon.viz.gfe.types.MutableInteger;
|
|||
|
||||
/**
|
||||
* Contains a complete histogram for a single grid and parameter
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
|
@ -62,9 +62,10 @@ import com.raytheon.viz.gfe.types.MutableInteger;
|
|||
* Sep 9, 2008 1283 njensen Implemented sample methods
|
||||
* May 29, 2009 2159 rjpeter Optimized sample methods.
|
||||
* May 24, 2012 673 randerso Added defaulted method calls
|
||||
*
|
||||
* Jun 17, 2013 15951 ryu Fix index to wx/discrete key array
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author mnash
|
||||
* @version 1.0
|
||||
*/
|
||||
|
@ -175,7 +176,7 @@ public class HistSample {
|
|||
* Description : Constructor far HistSample taking a histogram in the form
|
||||
* of a time range and a sequence of HistPairs, stores the information in
|
||||
* private data. Counts up the samples and stores that in _numSamplePoints.
|
||||
*
|
||||
*
|
||||
* @param timeRange
|
||||
* @param histPairs
|
||||
*/
|
||||
|
@ -210,7 +211,7 @@ public class HistSample {
|
|||
* cached. Sets number of sample points to zero. Calls sampleGrid() to
|
||||
* sample the grid. If successful, stores the time range and counts up the
|
||||
* number of sample points.
|
||||
*
|
||||
*
|
||||
* @param gridSlice
|
||||
* @param sampleArea
|
||||
* @param cachePoints
|
||||
|
@ -250,7 +251,7 @@ public class HistSample {
|
|||
* for WEATHER. The most common value for DISCRETE. For vector, if
|
||||
* separateMagDir is true, the magnitude is averaged separately from the
|
||||
* direction.
|
||||
*
|
||||
*
|
||||
* @param separateMagDir
|
||||
* @return
|
||||
*/
|
||||
|
@ -360,7 +361,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* Description : the square root function
|
||||
*
|
||||
*
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
|
@ -377,7 +378,7 @@ public class HistSample {
|
|||
* Returns the standard deviation of each component separately for VECTOR.
|
||||
* Should not be called for WEATHER. For vector, if separate MagDir is true,
|
||||
* the magnitude is averaged separately from the direction.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final HistValue stdDev() {
|
||||
|
@ -469,7 +470,7 @@ public class HistSample {
|
|||
* the HistPair's for the maximum count value and returns it. In the case
|
||||
* where more than one entry shares the maximum count value, then only the
|
||||
* highest value (sort order) value will be returned.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final HistValue mostCommonValue() {
|
||||
|
@ -503,7 +504,7 @@ public class HistSample {
|
|||
* case where more than one entyr shares the maximum count value, then only
|
||||
* the highest value (sort order) value will be returned. Works only on
|
||||
* SCALAR and VECTOR.
|
||||
*
|
||||
*
|
||||
* @param resolution
|
||||
* @return
|
||||
*/
|
||||
|
@ -542,7 +543,7 @@ public class HistSample {
|
|||
* Finds and returns the middle value associated with the sample. The middle
|
||||
* value is that value that is halfway between the lowest and highest in
|
||||
* terms of count, and not value. This is a no-op for WEATHER/DISCRETE.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final HistValue middleValue() {
|
||||
|
@ -576,7 +577,7 @@ public class HistSample {
|
|||
* Description : Returns the absolute minimum value for the sample points.
|
||||
* This is a no-op for WEATHER/DISCRETE. Only the magnitude component for
|
||||
* VECTOR is used for comparison.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final HistValue absoluteMin() {
|
||||
|
@ -602,7 +603,7 @@ public class HistSample {
|
|||
* Description : REturns the absolute maximum value for the sample points.
|
||||
* This is a no-op for WEATHER/DISCRETE. Only the magnitude component for
|
||||
* VECTOR is used for comparison.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final HistValue absoluteMax() {
|
||||
|
@ -642,7 +643,7 @@ public class HistSample {
|
|||
* most common value is provide for WEATERH. Outliers are eliminated.
|
||||
* Percent ranges from 0 to 50. For vector, if separateMagDir is true, the
|
||||
* magnitude is averaged separately from the direction.
|
||||
*
|
||||
*
|
||||
* @param minpercent
|
||||
* @param maxpercent
|
||||
* @param separateMagDir
|
||||
|
@ -820,7 +821,7 @@ public class HistSample {
|
|||
* points. this is a no-op for WEATHER/DISCRETE. Percent should be between 0
|
||||
* and 50. This routine eliminates the bottom xx% of sample values and
|
||||
* returns that value.
|
||||
*
|
||||
*
|
||||
* @param percent
|
||||
* @return
|
||||
*/
|
||||
|
@ -864,7 +865,7 @@ public class HistSample {
|
|||
* points. This is a no-op for WEATHER/DISCRETE. Percent should be between 0
|
||||
* and 50. This routine eliminates the top 15% of sample values and returns
|
||||
* that value.
|
||||
*
|
||||
*
|
||||
* @param percent
|
||||
* @return
|
||||
*/
|
||||
|
@ -921,7 +922,7 @@ public class HistSample {
|
|||
* most common value is provided for WEATHER/DISCRETE. Outliers are
|
||||
* eliminated based on standard deviation. For vector, if separateMagDir is
|
||||
* true, the magnitude is averaged separately from the direction.
|
||||
*
|
||||
*
|
||||
* @param minStdD
|
||||
* @param maxStdD
|
||||
* @param separateMagDir
|
||||
|
@ -1074,7 +1075,7 @@ public class HistSample {
|
|||
* Description : Returns the representative minimum value for the sample
|
||||
* points. This is a no-op for WEATHER/DISCRETE. Based on standard
|
||||
* deviations.
|
||||
*
|
||||
*
|
||||
* @param stdD
|
||||
* @return
|
||||
*/
|
||||
|
@ -1117,7 +1118,7 @@ public class HistSample {
|
|||
* Description : Returns the representative maximum value for the sample
|
||||
* points. This is a no-op for WEATHER/DISCRETE. Based on standard
|
||||
* deviations.
|
||||
*
|
||||
*
|
||||
* @param stdD
|
||||
* @return
|
||||
*/
|
||||
|
@ -1155,7 +1156,7 @@ public class HistSample {
|
|||
/**
|
||||
* OUtputs the histogram for this grid, but binned by the specified float
|
||||
* value. This only applies to SCALAR and VECTOR data.
|
||||
*
|
||||
*
|
||||
* @param resolution
|
||||
* @return
|
||||
*/
|
||||
|
@ -1229,7 +1230,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* Description : Bins the data sample based on the resolution
|
||||
*
|
||||
*
|
||||
* @param v
|
||||
* @param resolution
|
||||
* @return
|
||||
|
@ -1254,7 +1255,7 @@ public class HistSample {
|
|||
* that the grid is valid and grid and Grid2DBit sizes match. Ensures there
|
||||
* are points in the sample area. Switch cases on data type and then
|
||||
* extracts out the data for each sample point.
|
||||
*
|
||||
*
|
||||
* @param grid
|
||||
* @param area
|
||||
* @param cachePoints
|
||||
|
@ -1309,7 +1310,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* If the sample was of scalars this function is called
|
||||
*
|
||||
*
|
||||
* @param grid
|
||||
* @param area
|
||||
* @param cachePoints
|
||||
|
@ -1411,7 +1412,7 @@ public class HistSample {
|
|||
for (int x = ll.x; x <= ur.x; x++) {
|
||||
for (int y = ll.y; y <= ur.y; y++) {
|
||||
if (area.get(x, y) != 0) {
|
||||
WeatherKey k = key[gs.get(x, y)];
|
||||
WeatherKey k = key[0xFF & gs.get(x, y)];
|
||||
if (_subkeymode) {
|
||||
List<WeatherSubKey> subkeys = k.getSubKeys();
|
||||
for (int z = 0; z < subkeys.size(); z++) {
|
||||
|
@ -1472,7 +1473,7 @@ public class HistSample {
|
|||
for (int x = ll.x; x <= ur.x; x++) {
|
||||
for (int y = ll.y; y <= ur.y; y++) {
|
||||
if (area.get(x, y) != 0) {
|
||||
DiscreteKey k = key[gs.get(x, y)];
|
||||
DiscreteKey k = key[0xFF & gs.get(x, y)];
|
||||
if (_subkeymode) {
|
||||
List<String> subkeys = k.getSubKeys();
|
||||
for (int z = 0; z < subkeys.size(); z++) {
|
||||
|
@ -1524,7 +1525,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* Description : counts the number of sample points and returns the number
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private int countSamplePoints() {
|
||||
|
@ -1552,7 +1553,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* Description : Returns the sample's valid time
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final TimeRange validTime() {
|
||||
|
@ -1561,7 +1562,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* Description : Returns the histogram associated with this sample
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public final HistPair[] histogram() {
|
||||
|
@ -1570,7 +1571,7 @@ public class HistSample {
|
|||
|
||||
/**
|
||||
* Description : Returns the number of points associated with this sample
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int numOfPoints() {
|
||||
|
|
|
@ -40,6 +40,7 @@ import com.raytheon.viz.hydrocommon.HydroDisplayManager;
|
|||
* 6/27/06 lvenable Initial creation.
|
||||
* 02/07/2013 1578 rferrel Changes for non-blocking ProductViewerDlg.
|
||||
* 03/27/2013 1790 rferrel Bug fix for non-blocking dialogs.
|
||||
* 06/19/2013 2119 rferrel Changed check for no selected lid.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -59,19 +60,18 @@ public class ProductViewerAction extends AbstractHandler {
|
|||
*/
|
||||
@Override
|
||||
public Object execute(ExecutionEvent arg0) throws ExecutionException {
|
||||
String currentLid = HydroDisplayManager.getInstance().getCurrentLid();
|
||||
HydroDisplayManager manager = HydroDisplayManager.getInstance();
|
||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||
.getShell();
|
||||
|
||||
if (dialog == null || dialog.isDisposed()) {
|
||||
|
||||
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
|
||||
.getShell();
|
||||
dialog = new ProductViewerDlg(shell);
|
||||
dialog.open();
|
||||
} else {
|
||||
dialog.bringToTop();
|
||||
}
|
||||
if (currentLid != null) {
|
||||
dialog.setLid(currentLid);
|
||||
if (manager.isCurrentLidSelected(shell)) {
|
||||
if (dialog == null || dialog.isDisposed()) {
|
||||
dialog = new ProductViewerDlg(shell);
|
||||
dialog.open();
|
||||
} else {
|
||||
dialog.setLid(manager.getCurrentLid());
|
||||
dialog.bringToTop();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
|||
* 12/11/2009 2488 mpduff Refactored dialog to work as
|
||||
* in AWIPS 1
|
||||
* 02/07/2013 1578 rferrel Make dialog non-blocking.
|
||||
* 06/19/2013 2119 rferrel Remove no longer needed shouldOpen.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -211,16 +212,6 @@ public class ProductViewerDlg extends CaveSWTDialog {
|
|||
loadProductList();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#shouldOpen()
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldOpen() {
|
||||
return HydroDisplayManager.getInstance().isCurrentLidSelected(shell);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Product Information group container.
|
||||
*/
|
||||
|
|
|
@ -83,6 +83,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 13, 2009 snaples Initial creation
|
||||
* Jun 27, 2013 15859 wkwock Update this dialog after click Apply button
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -1460,6 +1461,8 @@ public class EditPrecipStationsDialog extends AbstractMPEDialog implements
|
|||
changeCustomFile();
|
||||
// shell.dispose();
|
||||
}
|
||||
|
||||
this.open();//redraw this updated dialog
|
||||
}
|
||||
|
||||
protected void read_text() {
|
||||
|
|
|
@ -70,9 +70,11 @@ import com.raytheon.viz.ui.tools.ModalToolManager;
|
|||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 22, 2008 randerso Initial creation
|
||||
* Mar 26, 2013 1799 bsteffen Fix pan/zoom when in views.
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 22, 2008 randerso Initial creation
|
||||
* Mar 26, 2013 1799 bsteffen Fix pan/zoom when in views.
|
||||
* Jun 19, 2013 2116 bsteffen Do not deactivate contexts for parts
|
||||
* when closing an inactive perspective.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -512,8 +514,9 @@ public abstract class AbstractVizPerspectiveManager implements
|
|||
|
||||
protected void deactivateContexts(ContextManager manager) {
|
||||
manager.deactivateContexts(this);
|
||||
if (page != null && page.getActivePart() != null) {
|
||||
manager.deactivateContexts(page.getActivePart());
|
||||
if (page != null && page.getActivePart() != null
|
||||
&& perspectiveId.equals(page.getPerspective().getId())) {
|
||||
manager.deactivateContexts(page.getActivePart());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<classpath>
|
||||
<classpathentry exported="true" kind="lib" path="hibernate-spatial-1.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="hibernate-spatial-postgis-1.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="hibernate3.5.6-Final.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="hibernate3.5.6-Final.jar" sourcepath="hibernate-3.5.6-Final-source.zip"/>
|
||||
<classpathentry exported="true" kind="lib" path="javassist-3.9.0.GA.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="jta-1.1.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
|
|
BIN
cots/org.hibernate/hibernate-3.5.6-Final-source.zip
Normal file
BIN
cots/org.hibernate/hibernate-3.5.6-Final-source.zip
Normal file
Binary file not shown.
Binary file not shown.
|
@ -24,7 +24,6 @@ export DATA_ARCHIVE_ROOT=/tmp/sbn
|
|||
# setup db connections
|
||||
export DB_ADDR=localhost
|
||||
export DB_PORT=5432
|
||||
export DB_DIALECT=org.hibernate.dialect.PostgreSQLDialect
|
||||
|
||||
# setup connection to qpid
|
||||
export BROKER_ADDR=localhost
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
org.postgresql.Driver
|
||||
</property>
|
||||
<property name="dialect">
|
||||
${db.dialect}
|
||||
org.hibernate.dialect.PostgreSQLDialect
|
||||
</property>
|
||||
<property name="connection.url">
|
||||
jdbc:postgresql://${db.addr}:${db.port}/metadata
|
||||
|
@ -73,4 +73,4 @@
|
|||
<property name="cache.use_query_cache">false</property>
|
||||
|
||||
</session-factory>
|
||||
</hibernate-configuration>
|
||||
</hibernate-configuration>
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<level value="WARN"/>
|
||||
</logger>
|
||||
<logger name="org.hibernate" additivity="false">
|
||||
<level value="ERROR"/>
|
||||
<level value="WARN"/>
|
||||
<appender-ref ref="HibernateLog" />
|
||||
</logger>
|
||||
<logger name="org.geotools">
|
||||
|
|
|
@ -67,18 +67,18 @@
|
|||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- GFEPerformance log -->
|
||||
<appender name="GFEPerformanceLog" class="org.apache.log4j.rolling.RollingFileAppender">
|
||||
<!-- activeTableChange log -->
|
||||
<appender name="activeTableChangeLog" class="org.apache.log4j.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
|
||||
<param name="FileNamePattern" value="${edex.home}/logs/edex-ingest-GFEPerformance-%d{yyyyMMdd}.log"/>
|
||||
<param name="FileNamePattern" value="${edex.home}/logs/edex-ingest-activeTableChange-%d{yyyyMMdd}.log"/>
|
||||
</rollingPolicy>
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p %d [%t] %c{1}: %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="GFEPerformanceLogAsync" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="GFEPerformanceLog" />
|
||||
<appender name="activeTableChangeLogAsync" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="activeTableChangeLog" />
|
||||
</appender>
|
||||
|
||||
<!-- Purge log -->
|
||||
|
@ -251,7 +251,7 @@
|
|||
<level value="WARN"/>
|
||||
</logger>
|
||||
<logger name="org.hibernate" additivity="false">
|
||||
<level value="ERROR"/>
|
||||
<level value="WARN"/>
|
||||
<appender-ref ref="HibernateLog" />
|
||||
</logger>
|
||||
<logger name="org.geotools">
|
||||
|
@ -308,9 +308,9 @@
|
|||
<appender-ref ref="FailedTriggerLog"/>
|
||||
</logger>
|
||||
|
||||
<logger name="GFEPerformanceLogger" additivity="false">
|
||||
<logger name="ActiveTableChange" additivity="false">
|
||||
<level value="Debug"/>
|
||||
<appender-ref ref="GFEPerformanceLogAsync" />
|
||||
<appender-ref ref="activeTableChangeLogAsync" />
|
||||
</logger>
|
||||
|
||||
<!-- default logging -->
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
<level value="WARN"/>
|
||||
</logger>
|
||||
<logger name="org.hibernate" additivity="false">
|
||||
<level value="ERROR"/>
|
||||
<level value="WARN"/>
|
||||
<appender-ref ref="HibernateLog" />
|
||||
</logger>
|
||||
<logger name="org.geotools">
|
||||
|
|
|
@ -66,6 +66,20 @@
|
|||
<appender-ref ref="PerformanceLog" />
|
||||
</appender>
|
||||
|
||||
<!-- activeTableChange log -->
|
||||
<appender name="activeTableChangeLog" class="org.apache.log4j.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
|
||||
<param name="FileNamePattern" value="${edex.home}/logs/edex-${edex.run.mode}-activeTableChange-%d{yyyyMMdd}.log"/>
|
||||
</rollingPolicy>
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p %d [%t] %c{1}: %m%n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="activeTableChangeLogAsync" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="activeTableChangeLog" />
|
||||
</appender>
|
||||
|
||||
<logger name="ProductSrvRequestLogger" additivity="false">
|
||||
<level value="DEBUG"/>
|
||||
<appender-ref ref="ProductSrvRequestLogAsync"/>
|
||||
|
@ -76,9 +90,9 @@
|
|||
<appender-ref ref="ThriftSrvRequestLogAsync" />
|
||||
</logger>
|
||||
|
||||
<logger name="GFEPerformanceLogger" additivity="false">
|
||||
<level value="DEBUG"/>
|
||||
<appender-ref ref="PerformanceLogAsync" />
|
||||
<logger name="ActiveTableChange" additivity="false">
|
||||
<level value="Debug"/>
|
||||
<appender-ref ref="activeTableChangeLogAsync" />
|
||||
</logger>
|
||||
|
||||
<logger name="PerformanceLogger" additivity="false">
|
||||
|
@ -137,7 +151,7 @@
|
|||
<level value="WARN"/>
|
||||
</logger>
|
||||
<logger name="org.hibernate" additivity="false">
|
||||
<level value="ERROR"/>
|
||||
<level value="WARN"/>
|
||||
<appender-ref ref="HibernateLog" />
|
||||
</logger>
|
||||
<logger name="org.geotools">
|
||||
|
|
|
@ -237,6 +237,7 @@
|
|||
<include>persist-ingest.xml</include>
|
||||
<include>management-common.xml</include>
|
||||
<include>event-ingest.xml</include>
|
||||
<include>purge-logs.xml</include>
|
||||
<!--
|
||||
The pattern datadelivery-registry is used to signify spring configurations
|
||||
that should be loaded when running datadelivery and the registry in a single JVM
|
||||
|
@ -336,6 +337,7 @@
|
|||
<!-- Purge OGC/DPA registred plugins -->
|
||||
<include>purge-spring.xml</include>
|
||||
<include>ogc-purge.xml</include>
|
||||
<include>purge-logs.xml</include>
|
||||
</mode>
|
||||
<!-- This is MADIS implmentation of dataprovideragent -->
|
||||
<mode name="dataprovideragent">
|
||||
|
|
|
@ -165,11 +165,33 @@
|
|||
<constructor-arg><ref bean="pluginSetup"/></constructor-arg>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="stringToFile" class="com.raytheon.uf.edex.esb.camel.StringToFile"/>
|
||||
<bean id="extractWMOHeader" class="com.raytheon.uf.common.util.header.WMOHeaderRemover"/>
|
||||
<bean id="dataUnzipper" class="com.raytheon.uf.common.util.DataUnzipper"/>
|
||||
|
||||
<bean id="errorHandler" class="org.apache.camel.builder.LoggingErrorHandlerBuilder"/>
|
||||
|
||||
<!-- sets default settings of log component across all of edex -->
|
||||
<bean id="defaultEdexLogFormatter" class="org.apache.camel.component.log.LogFormatter">
|
||||
<property name="maxChars" value="0" />
|
||||
<property name="showBody" value="false" />
|
||||
<property name="showCaughtException" value="true" />
|
||||
<property name="showStackTrace" value="true" />
|
||||
</bean>
|
||||
<bean id="log" class="org.apache.camel.component.log.LogComponent">
|
||||
<property name="exchangeFormatter" ref="defaultEdexLogFormatter" />
|
||||
</bean>
|
||||
|
||||
<!-- for those special times when you really want to see the content of the message -->
|
||||
<bean id="showBodyLogFormatter" class="org.apache.camel.component.log.LogFormatter">
|
||||
<property name="maxChars" value="0" />
|
||||
<property name="showCaughtException" value="true" />
|
||||
<property name="showStackTrace" value="true" />
|
||||
</bean>
|
||||
<bean id="log-showbody" class="org.apache.camel.component.log.LogComponent">
|
||||
<property name="exchangeFormatter" ref="showBodyLogFormatter" />
|
||||
</bean>
|
||||
|
||||
<bean id="serializationUtil" class="com.raytheon.uf.common.serialization.SerializationUtil" />
|
||||
|
||||
|
@ -248,7 +270,7 @@
|
|||
<bean ref="jmsPooledConnectionFactory" method="checkPooledResources"/>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:jmsPooledResourceCheck?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:jmsPooledResourceCheck?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -264,7 +286,7 @@
|
|||
<bean ref="clusteredCamelContextMgr" method="checkClusteredContexts" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:monitorClusteredContexts?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:monitorClusteredContexts?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -100,13 +100,12 @@ wrapper.java.additional.qpid.1=-Dqpid.dest_syntax=BURL
|
|||
# hibernate.cfg.xml cannot read from ENV variables but can read from Java system properties
|
||||
wrapper.java.additional.db.1=-Ddb.addr=${DB_ADDR}
|
||||
wrapper.java.additional.db.2=-Ddb.port=${DB_PORT}
|
||||
wrapper.java.additional.db.3=-Ddb.dialect=${DB_DIALECT}
|
||||
wrapper.java.additional.db.4=-Ddc.db.name=${DC_DB_NAME}
|
||||
wrapper.java.additional.db.5=-Dfxa.db.name=${FXA_DB_NAME}
|
||||
wrapper.java.additional.db.6=-Dhm.db.name=${HM_DB_NAME}
|
||||
wrapper.java.additional.db.7=-Dih.db.name=${IH_DB_NAME}
|
||||
wrapper.java.additional.db.8=-Ddb.metadata.pool.min=${METADATA_POOL_MIN}
|
||||
wrapper.java.additional.db.9=-Ddb.metadata.pool.max=${METADATA_POOL_MAX}
|
||||
wrapper.java.additional.db.3=-Ddc.db.name=${DC_DB_NAME}
|
||||
wrapper.java.additional.db.4=-Dfxa.db.name=${FXA_DB_NAME}
|
||||
wrapper.java.additional.db.5=-Dhm.db.name=${HM_DB_NAME}
|
||||
wrapper.java.additional.db.6=-Dih.db.name=${IH_DB_NAME}
|
||||
wrapper.java.additional.db.7=-Ddb.metadata.pool.min=${METADATA_POOL_MIN}
|
||||
wrapper.java.additional.db.8=-Ddb.metadata.pool.max=${METADATA_POOL_MAX}
|
||||
|
||||
# site ID of EDEX for localization and site aware services
|
||||
wrapper.java.additional.site.1=-Daw.site.identifier=${AW_SITE_IDENTIFIER}
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
<SourceName>FFG0124hr</SourceName>
|
||||
<DisplayName>RFCFFG</DisplayName>
|
||||
<DurationHour>1</DurationHour>
|
||||
<dataPath>/grid/%/%/.*/.*/null/FFG0124hr/SFC/0.0/-999999.0/</dataPath>
|
||||
<dataPath>/grid/%/%/.*/.*/.*/FFG0124hr/SFC/0.0/-999999.0/</dataPath>
|
||||
<plugin>grid</plugin>
|
||||
<dataType>GRID</dataType>
|
||||
<sourceType>GUIDANCE</sourceType>
|
||||
|
@ -110,7 +110,7 @@
|
|||
<SourceName>FFG0324hr</SourceName>
|
||||
<DisplayName>RFCFFG</DisplayName>
|
||||
<DurationHour>3</DurationHour>
|
||||
<dataPath>/grid/%/%/.*/.*/null/FFG0324hr/SFC/0.0/-999999.0/</dataPath>
|
||||
<dataPath>/grid/%/%/.*/.*/.*/FFG0324hr/SFC/0.0/-999999.0/</dataPath>
|
||||
<plugin>grid</plugin>
|
||||
<dataType>GRID</dataType>
|
||||
<sourceType>GUIDANCE</sourceType>
|
||||
|
@ -126,7 +126,7 @@
|
|||
<SourceName>FFG0624hr</SourceName>
|
||||
<DisplayName>RFCFFG</DisplayName>
|
||||
<DurationHour>6</DurationHour>
|
||||
<dataPath>/grid/%/%/.*/.*/null/FFG0624hr/SFC/0.0/-999999.0/</dataPath>
|
||||
<dataPath>/grid/%/%/.*/.*/.*/FFG0624hr/SFC/0.0/-999999.0/</dataPath>
|
||||
<plugin>grid</plugin>
|
||||
<dataType>GRID</dataType>
|
||||
<sourceType>GUIDANCE</sourceType>
|
||||
|
|
|
@ -27,5 +27,4 @@ export EDEX_DEBUG_PORT=5010
|
|||
export EDEX_JMX_PORT=1621
|
||||
export LOG4J_CONF=log4j-dataprovideragent.xml
|
||||
export MGMT_PORT=9606
|
||||
export DB_DIALECT=org.hibernatespatial.postgis.PostgisDialect
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<bean ref="subscriptionDao" method="updateCache" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:subscription?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:subscription?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<bean ref="ldadScriptRunner" method="runScripts" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:subscription?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:subscription?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<bean ref="timerScriptRunner" method="runScripts" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:subscription?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:subscription?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<bean ref="dataScriptRunner" method="runScripts" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:subscription?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:subscription?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -55,7 +55,7 @@
|
|||
<bean ref="ldadScriptRunner" method="runScripts" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:subscription?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:subscription?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -55,14 +55,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:airep?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:airep?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:airep?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:airep?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:binlightning?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:binlightning?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
<!-- bean ref="processUtil" method="delete" / -->
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
**/
|
||||
package com.raytheon.edex.plugin.binlightning;
|
||||
|
||||
import gov.noaa.nws.ost.edex.plugin.binlightning.BinLigntningDecoderUtil;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -30,9 +32,6 @@ import org.apache.commons.logging.LogFactory;
|
|||
import com.raytheon.edex.esb.Headers;
|
||||
import com.raytheon.edex.exception.DecoderException;
|
||||
import com.raytheon.edex.plugin.AbstractDecoder;
|
||||
import com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory;
|
||||
import com.raytheon.edex.plugin.binlightning.impl.IBinLightningDecoder;
|
||||
import com.raytheon.edex.plugin.binlightning.impl.LightningDataSource;
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.PluginException;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
|
@ -41,7 +40,6 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
|
|||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.edex.decodertools.core.DecoderTools;
|
||||
import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
||||
import com.raytheon.uf.edex.decodertools.time.TimeTools;
|
||||
import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
||||
|
||||
|
@ -77,6 +75,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
|||
* 20080318 1026 jkorman Added debug strike info.
|
||||
* 20080408 1039 jkorman Added traceId for tracing data.
|
||||
* 11/11/08 1684 chammack Refactored for camel integration
|
||||
* 20130503 DCS 112 Wufeng Zhou Modified to be able to handle both the new encrypted data and legacy bit-shifted data
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -93,7 +92,7 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
|
||||
private SimpleDateFormat SDF;
|
||||
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* Default lightning strike type for FLASH messages. RT_FLASH documents
|
||||
|
@ -102,7 +101,7 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
public LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.STRIKE_CG;
|
||||
|
||||
private String traceId = null;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a BinLightning decoder. Calling hasNext() after construction
|
||||
* will return false, decode() will return a null.
|
||||
|
@ -119,13 +118,12 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
* @throws DecoderException
|
||||
* Thrown if no data is available.
|
||||
*/
|
||||
public PluginDataObject[] decode(byte[] data, Headers headers)
|
||||
throws DecoderException {
|
||||
public PluginDataObject[] decode(byte[] data, Headers headers) throws DecoderException {
|
||||
|
||||
String traceId = null;
|
||||
//String traceId = null;
|
||||
PluginDataObject[] reports = new PluginDataObject[0];
|
||||
if (data != null) {
|
||||
|
||||
if (data != null) {
|
||||
traceId = (String) headers.get(DecoderTools.INGEST_FILE_NAME);
|
||||
|
||||
WMOHeader wmoHdr = new WMOHeader(data);
|
||||
|
@ -133,92 +131,93 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
|
||||
Calendar baseTime = TimeTools.findDataTime(wmoHdr.getYYGGgg(),
|
||||
headers);
|
||||
|
||||
byte[] pdata = DecoderTools.stripWMOHeader(data, SFUS_PATTERN);
|
||||
if (pdata == null) {
|
||||
pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN);
|
||||
|
||||
// Because binary nature of the encrypted data, the string created with its byte[] array may not have the same length of the byte[] array length
|
||||
// So when DecoderTools.stripWMOHeader() assumes byte[] length == String length in it logic, it is observed that it may return a shorter byte[] than
|
||||
// the real data array. (Looks like a bug???)
|
||||
// byte[] pdata = DecoderTools.stripWMOHeader(data, SFUS_PATTERN);
|
||||
// if (pdata == null) {
|
||||
// pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN);
|
||||
// }
|
||||
// instead the following is used to strip WMO header a little more safely.
|
||||
byte[] pdata = null;
|
||||
if (wmoHdr.isValid() && wmoHdr.getMessageDataStart() > 0) {
|
||||
pdata = new byte[data.length - wmoHdr.getMessageDataStart()];
|
||||
System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, 0, data.length - wmoHdr.getMessageDataStart());
|
||||
}
|
||||
|
||||
if ((pdata == null) || (pdata.length == 0)) {
|
||||
return new PluginDataObject[0];
|
||||
}
|
||||
if (pdata != null) {
|
||||
|
||||
//
|
||||
// Modified by Wufeng Zhou to handle both legacy bit-shifted and new encryted data
|
||||
//
|
||||
// Preserved the legacy decoding in BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(), and added logic to process
|
||||
// both encrypted data and legacy data
|
||||
//
|
||||
|
||||
List<LightningStrikePoint> strikes = BinLigntningDecoderUtil.decodeBinLightningData(data, pdata, traceId, baseTime.getTime());
|
||||
|
||||
// Init all values before this decode cycle. This resets all
|
||||
// internal
|
||||
// decoder state.
|
||||
ArrayList<LightningStrikePoint> strikes = new ArrayList<LightningStrikePoint>();
|
||||
if (strikes == null) { // keep-alive record, log and return
|
||||
logger.info(traceId + " - found keep-alive record. ignore for now.");
|
||||
return reports;
|
||||
}
|
||||
|
||||
if ((pdata == null) || (pdata.length == 0)) {
|
||||
return new PluginDataObject[0];
|
||||
//
|
||||
// Done MOD by Wufeng Zhou
|
||||
//
|
||||
|
||||
// post processing data - if not keep-alive record
|
||||
BinLightningRecord report = null;
|
||||
if (strikes.size() > 0) {
|
||||
report = new BinLightningRecord(strikes.size());
|
||||
for (LightningStrikePoint strike : strikes) {
|
||||
report.addStrike(strike);
|
||||
logger.debug(traceId + "-" + strike);
|
||||
}
|
||||
} else {
|
||||
return new PluginDataObject[0];
|
||||
}
|
||||
|
||||
IBinDataSource msgData = new LightningDataSource(pdata);
|
||||
Calendar c = TimeTools.copy(baseTime);
|
||||
if (c == null) {
|
||||
throw new DecoderException(traceId + " - Error decoding times");
|
||||
}
|
||||
//report.setInsertTime(c); // OB13.4 source code does not have this line anymore, WZ 05/03/2013
|
||||
|
||||
boolean continueDecode = true;
|
||||
while (continueDecode) {
|
||||
IBinLightningDecoder decoder = BinLightningFactory
|
||||
.getDecoder(msgData);
|
||||
Calendar cStart = report.getStartTime();
|
||||
if (cStart.getTimeInMillis() > c.getTimeInMillis()
|
||||
+ TEN_MINUTES) {
|
||||
synchronized (SDF) {
|
||||
logger.info("Discarding future data for " + traceId
|
||||
+ " at " + SDF.format(cStart.getTime()));
|
||||
}
|
||||
} else {
|
||||
Calendar cStop = report.getStopTime();
|
||||
|
||||
switch (decoder.getError()) {
|
||||
case IBinLightningDecoder.NO_ERROR: {
|
||||
for (LightningStrikePoint strike : decoder) {
|
||||
strikes.add(strike);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
continueDecode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
TimeRange range = new TimeRange(
|
||||
cStart.getTimeInMillis(),
|
||||
cStop.getTimeInMillis());
|
||||
|
||||
BinLightningRecord report = null;
|
||||
DataTime dataTime = new DataTime(cStart, range);
|
||||
report.setDataTime(dataTime);
|
||||
|
||||
if (strikes.size() > 0) {
|
||||
report = new BinLightningRecord(strikes.size());
|
||||
for (LightningStrikePoint strike : strikes) {
|
||||
report.addStrike(strike);
|
||||
logger.debug(traceId + "-" + strike);
|
||||
}
|
||||
} else {
|
||||
return new PluginDataObject[0];
|
||||
}
|
||||
|
||||
Calendar c = TimeTools.copy(baseTime);
|
||||
if (c == null) {
|
||||
throw new DecoderException(traceId
|
||||
+ "-Error decoding times");
|
||||
}
|
||||
|
||||
Calendar cStart = report.getStartTime();
|
||||
if (cStart.getTimeInMillis() > c.getTimeInMillis()
|
||||
+ TEN_MINUTES) {
|
||||
synchronized (SDF) {
|
||||
logger.info("Discarding future data for " + traceId
|
||||
+ " at " + SDF.format(cStart.getTime()));
|
||||
}
|
||||
} else {
|
||||
Calendar cStop = report.getStopTime();
|
||||
|
||||
TimeRange range = new TimeRange(
|
||||
cStart.getTimeInMillis(),
|
||||
cStop.getTimeInMillis());
|
||||
|
||||
DataTime dataTime = new DataTime(cStart, range);
|
||||
report.setDataTime(dataTime);
|
||||
|
||||
if (report != null) {
|
||||
report.setTraceId(traceId);
|
||||
report.setPluginName("binlightning");
|
||||
try {
|
||||
report.constructDataURI();
|
||||
reports = new PluginDataObject[] { report };
|
||||
} catch (PluginException e) {
|
||||
logger.error("Error constructing datauri", e);
|
||||
}
|
||||
if (report != null) {
|
||||
report.setTraceId(traceId);
|
||||
report.setPluginName("binlightning");
|
||||
try {
|
||||
report.constructDataURI();
|
||||
reports = new PluginDataObject[] { report };
|
||||
} catch (PluginException e) {
|
||||
logger.error("Error constructing datauri", e);
|
||||
throw new DecoderException("Error constructing datauri", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.error("No WMOHeader found in data");
|
||||
}
|
||||
} else {
|
||||
logger.error("No WMOHeader found in data");
|
||||
}
|
||||
return reports;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/**
|
||||
* This code has been developed by NWS/OST to support AWIPS II
|
||||
*
|
||||
*/
|
||||
package gov.noaa.nws.ost.edex.plugin.binlightning;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* BinLightningAESKey
|
||||
*
|
||||
* Simple representation of bin lightning AES encryption key and its associated key aliases in the keystore
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20130503 DCS 112 Wufeng Zhou To handle both the new encrypted data and legacy bit-shifted data
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author Wufeng Zhou
|
||||
*
|
||||
*/
|
||||
public class BinLightningAESKey {
|
||||
/** Default location to search for BinLightningAESKey.properties file, and keystore file (normally binLightningAESKeystore.jce as configured in properties file) */
|
||||
public static final String DEFAULT_KEYSTORE_LOC = "/usr/local/ldm";
|
||||
|
||||
/** System property name that can used to specify configuration property file, which will overwrite the default keystore location */
|
||||
public static final String SYS_PROP_FOR_CONF_FILE = "binlightning.aeskeypropfile";
|
||||
|
||||
public static final String KEYSTORE_PROP = "binlightning.AESKeystore";
|
||||
public static final String KEYSTORE_PASS_PROP = "binlightning.AESKeystorePassword";
|
||||
|
||||
private static final String CONF_PROPERTIES_FILE = "BinLightningAESKey.properties";
|
||||
public static final String KEY_ALIAS_PREFIX = "^\\d{4}-\\d{2}-\\d{2}";
|
||||
private static final Pattern KEY_ALIAS_PREFIX_PATTERN = Pattern.compile(KEY_ALIAS_PREFIX);
|
||||
private static final SimpleDateFormat KEY_ALIAS_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
private static Log logger = LogFactory.getLog(BinLightningAESKey.class);
|
||||
|
||||
private static Properties props = new Properties();
|
||||
private static KeyStore keystore;
|
||||
private static BinLightningAESKey[] keys = null;
|
||||
|
||||
/**
|
||||
* Helper method to selectively get all the bin lightning related AES encryption keys, ordered by key issue date in descending order.
|
||||
* Keys will be ignored when its alias is not starting with yyyy-MM-dd prefix or key algorithm is not "AES"
|
||||
*
|
||||
* If properties file is specified through system property binlightning.aeskeypropfile, then use it to load the properties.
|
||||
* Otherwise, load the default property that is at the same place as this class, and overwrite properties
|
||||
* if the property is specified through system property.
|
||||
* So, binlightning.aeskeypropfile has higher priority, if it is specified, other properties specified in system property will be ignored
|
||||
*
|
||||
* Assumption: Valid key imported/stored to the keystore will have yyyy-MM-dd prefix in its alias.
|
||||
*
|
||||
* @return valid bin lightning AES keys (with aliases) in descending order of key issue date
|
||||
* or null when no valid keys found
|
||||
*/
|
||||
public static BinLightningAESKey[] getBinLightningAESKeys() {
|
||||
if (keys != null) return keys;
|
||||
|
||||
// if properties file is specified through system property binlightning.aeskeypropfile, then use it to load the properties
|
||||
// otherwise, use default property file and overwrite with available system properties
|
||||
try {
|
||||
if (System.getProperty(SYS_PROP_FOR_CONF_FILE, "").equals("") == false) {
|
||||
File file = new File(System.getProperty(SYS_PROP_FOR_CONF_FILE));
|
||||
if (file.exists() == false) {
|
||||
logger.error("System specified property file " + file.getAbsolutePath() + " does not exist.");
|
||||
} else {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
props.load(fis);
|
||||
fis.close();
|
||||
}
|
||||
} else {
|
||||
// load default properties file
|
||||
Properties defProps = new Properties();
|
||||
File file = new File(DEFAULT_KEYSTORE_LOC, CONF_PROPERTIES_FILE);
|
||||
if (file.exists() == false) {
|
||||
logger.error("Default properties file " + file.getAbsolutePath() + " does not exist.");
|
||||
} else {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
defProps.load(fis);
|
||||
fis.close();
|
||||
}
|
||||
props.putAll(defProps);
|
||||
|
||||
// now check if the properties should be overwritten, if it is specified in system properties
|
||||
Iterator<?> iter = defProps.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String key = (String)iter.next();
|
||||
if (System.getProperty(key, "").equals("") == false) {
|
||||
props.setProperty(key, System.getProperty(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
logger.error("Fail to load BinLightningAESCipher configuration from file or system properties.", ioe);
|
||||
}
|
||||
|
||||
// load keystore
|
||||
try {
|
||||
if (props.getProperty(KEYSTORE_PROP, "").equals("") == false) {
|
||||
File ksFile = new File(props.getProperty(KEYSTORE_PROP));
|
||||
keystore = KeyStore.getInstance("JCEKS"); // type JCEKS can store AES symmetric secret key, while default JKS store can't
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(ksFile);
|
||||
char[] keystorePassword = null;
|
||||
if (props.getProperty(KEYSTORE_PASS_PROP) != null) {
|
||||
keystorePassword = props.getProperty(KEYSTORE_PASS_PROP).toCharArray();
|
||||
}
|
||||
keystore.load(fis, keystorePassword);
|
||||
} finally {
|
||||
if (fis != null) fis.close();
|
||||
}
|
||||
|
||||
Enumeration<String> enu = keystore.aliases();
|
||||
TreeMap<String, Key> treeMap = new TreeMap<String, Key>();
|
||||
while (enu.hasMoreElements()) {
|
||||
String alias = enu.nextElement();
|
||||
Matcher matcher = KEY_ALIAS_PREFIX_PATTERN.matcher(alias);
|
||||
if (matcher.lookingAt()) { // alias starts with yyyy-MM-dd pattern
|
||||
Key key = keystore.getKey(alias, props.getProperty(KEYSTORE_PASS_PROP).toCharArray());
|
||||
if (key.getAlgorithm().equals("AES")) {
|
||||
// valid AES key for bin lightning decryption
|
||||
treeMap.put(alias, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<BinLightningAESKey> keyListSortedByAliasDesc = new ArrayList<BinLightningAESKey>();
|
||||
for (Entry<String, Key> entry = treeMap.pollLastEntry(); entry != null; entry = treeMap.pollLastEntry()) {
|
||||
Date keyDate = KEY_ALIAS_DATE_FORMAT.parse(entry.getKey().substring(0, 10));
|
||||
BinLightningAESKey blkey = new BinLightningAESKey(entry.getKey(), entry.getValue(), keyDate);
|
||||
keyListSortedByAliasDesc.add(blkey);
|
||||
}
|
||||
keys = keyListSortedByAliasDesc.toArray(new BinLightningAESKey[] {});
|
||||
return keys;
|
||||
} else {
|
||||
logger.error("binlightning.AESKeystore property not set.");
|
||||
}
|
||||
} catch (KeyStoreException kse) {
|
||||
logger.error("Fail to getInstance of JCEKS keystore.", kse);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
logger.error("Fail to find the keystore file configured: " + props.getProperty(KEYSTORE_PROP), fnfe);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
logger.error("NoSuchAlgorithmException in loading keystore from file: " + props.getProperty(KEYSTORE_PROP), e);
|
||||
} catch (CertificateException e) {
|
||||
logger.error("CertificateException in loading keystore from file: " + props.getProperty(KEYSTORE_PROP), e);
|
||||
} catch (IOException e) {
|
||||
logger.error("IOException in loading keystore from file: " + props.getProperty(KEYSTORE_PROP), e);
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
logger.error("UnrecoverableKeyException in loading keystore from file: " + props.getProperty(KEYSTORE_PROP), e);
|
||||
} catch (ParseException e) {
|
||||
logger.error("ParseException in parsing alias for key date: " + props.getProperty(KEYSTORE_PROP), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* force to reload keys, useful for testing
|
||||
* @return
|
||||
*/
|
||||
public static BinLightningAESKey[] reloadBinLightningAESKeys() {
|
||||
if (keys != null) keys = null;
|
||||
return getBinLightningAESKeys();
|
||||
}
|
||||
|
||||
|
||||
private String alias;
|
||||
private Key key;
|
||||
private Date keyDate;
|
||||
|
||||
public BinLightningAESKey(String alias, Key key, Date keyDate) {
|
||||
this.alias = alias;
|
||||
this.key = key;
|
||||
this.keyDate = keyDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the alias
|
||||
*/
|
||||
public String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
/**
|
||||
* @param alias the alias to set
|
||||
*/
|
||||
public void setAlias(String alias) {
|
||||
this.alias = alias;
|
||||
}
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public Key getKey() {
|
||||
return key;
|
||||
}
|
||||
/**
|
||||
* @param key the key to set
|
||||
*/
|
||||
public void setKey(Key key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Date getKeyDate() {
|
||||
return keyDate;
|
||||
}
|
||||
|
||||
public void setKeyDate(Date keyDate) {
|
||||
this.keyDate = keyDate;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# Sample template Configuration information for bin lightning AES cipher
|
||||
# Per design review discussions, the default location to look for this file is external to AWIPS II tree at /usr/local/ldm
|
||||
#
|
||||
# properties include:
|
||||
# binlightning.AESKeystore: the java keystore that store AES cipher key or keys (if ever vendors changes keys in the future)
|
||||
# Keystore type should be JCEKS, and the key aliases should be prefixed with date in the format of yyyy-MM-dd so
|
||||
# that if more than one keys found, the latest key will be tried first.
|
||||
# The keystore should not be distributed with AWIPS II and should be protected by a store password
|
||||
#
|
||||
# binlightning.AESKeystorePassword: the password for the keystore
|
||||
#
|
||||
# The above properties could be overwritten by system properties, e.g., through -D options in EDEX startup script
|
||||
#
|
||||
# NOTE: since the key is not supposed to release with the source and rpm files, the program has built two ways for you
|
||||
# to specify keystore and key pass information:
|
||||
# 1. Use binlightning.aeskeypropfile system property (e.g., -D option on command line) to specify location of a valid properties file
|
||||
# to overwrite the default location of this file (/usr/local/ldm/BinLightningAESKey.properties).
|
||||
# When binlightning.aeskeypropfile system property is used, other -D options (as listed below in 2) are ignored.
|
||||
# 2. Use system properties (e.g., -D optinos on command line) to overwrite binlightning.AESKeystore & binlightning.AESKeystorePassword properties
|
||||
#
|
||||
|
||||
#
|
||||
# sample, self-generated key, safe to distribute
|
||||
#
|
||||
binlightning.AESKeystore=/usr/local/ldm/binLightningTestKeystore.jce
|
||||
binlightning.AESKeystorePassword=testStorePass
|
||||
|
||||
#
|
||||
# production key, do not distribute keystore and password
|
||||
#
|
||||
#binlightning.AESKeystore=/usr/local/ldm/binLightningAESKeystore.jce
|
||||
#binlightning.AESKeystorePassword=notShownHere
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* This code has been developed by NWS/OST to support AWIPS II
|
||||
*
|
||||
*/
|
||||
package gov.noaa.nws.ost.edex.plugin.binlightning;
|
||||
|
||||
/**
|
||||
* BinLightningDataDecryptionException
|
||||
*
|
||||
* @author Wufeng Zhou
|
||||
*
|
||||
*/
|
||||
public class BinLightningDataDecryptionException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private byte[] data = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BinLightningDataDecryptionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public BinLightningDataDecryptionException(String message, byte[] data) {
|
||||
super(message);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the data
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,529 @@
|
|||
/**
|
||||
* This code has been developed by NWS/OST to support AWIPS II
|
||||
*
|
||||
*/
|
||||
package gov.noaa.nws.ost.edex.plugin.binlightning;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory;
|
||||
import com.raytheon.edex.plugin.binlightning.impl.IBinLightningDecoder;
|
||||
import com.raytheon.edex.plugin.binlightning.impl.LightningDataSource;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
|
||||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
||||
import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
||||
|
||||
/**
|
||||
* BinLigntningDecoderUtil
|
||||
*
|
||||
* Utility method to decode legacy (bit-shifted) or new encrypted bin lightning
|
||||
* data
|
||||
*
|
||||
* Some utility code were adapted from vendor supplied sample code
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20130503 DCS 112 Wufeng Zhou To handle both the new encrypted data and legacy bit-shifted data
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author Wufeng Zhou
|
||||
*
|
||||
*/
|
||||
public class BinLigntningDecoderUtil {
|
||||
|
||||
/**
|
||||
* Message type for keep alive data records.
|
||||
*/
|
||||
final static short KEEP_ALIVE_TYPE = 0x0000;
|
||||
|
||||
/**
|
||||
* Message type for lightning data records.
|
||||
*/
|
||||
final static short LIGHTNING_TYPE = 0x00ff;
|
||||
|
||||
/**
|
||||
* If there are more elements within the data record, this terminator is used.
|
||||
*/
|
||||
final static byte[] MORE_TERM_BYTES = {0x0d, 0x0d, 0x0a, 0x00};
|
||||
/**
|
||||
* Last element within data records should be terminated by these 4 bytes.
|
||||
*/
|
||||
final static byte[] LAST_TERM_BYTES = {0x0d, 0x0d, 0x0a, 0x03};
|
||||
|
||||
/**
|
||||
* WMO header start bytes, optional (it is known that TG will strip this away)
|
||||
*/
|
||||
final static byte[] WMO_HEADER_START_BYTES = {0x01, 0x0d, 0x0d, 0x0a};
|
||||
|
||||
/* Size of binary NWS lightning data record. */
|
||||
static final int BINLIGHTNING_RECORD_SIZE = 32;
|
||||
|
||||
private static Log logger = LogFactory.getLog(BinLigntningDecoderUtil.class);
|
||||
|
||||
/**
|
||||
* extracted from the decode() of the original
|
||||
* com.raytheon.edex.plugin.binlightning.BinLightningDecoder class
|
||||
*
|
||||
* @param pdata
|
||||
* @return
|
||||
*/
|
||||
public static List<LightningStrikePoint> decodeBitShiftedBinLightningData(byte[] pdata) {
|
||||
List<LightningStrikePoint> strikes = new ArrayList<LightningStrikePoint>();
|
||||
|
||||
IBinDataSource msgData = new LightningDataSource(pdata);
|
||||
|
||||
boolean continueDecode = true;
|
||||
while (continueDecode) {
|
||||
IBinLightningDecoder decoder = BinLightningFactory.getDecoder(msgData);
|
||||
|
||||
switch (decoder.getError()) {
|
||||
case IBinLightningDecoder.NO_ERROR: {
|
||||
for (LightningStrikePoint strike : decoder) {
|
||||
strikes.add(strike);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
continueDecode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return strikes;
|
||||
}
|
||||
|
||||
/**
|
||||
* decode the new bin lightning data, after the data record is decrypted, and it is not keep-alive record
|
||||
* @param pdata
|
||||
* @return
|
||||
*/
|
||||
public static List<LightningStrikePoint> decodeDecryptedBinLightningData(byte[] data) {
|
||||
List<LightningStrikePoint> strikes = new ArrayList<LightningStrikePoint>();
|
||||
|
||||
int offset = 0;
|
||||
// length of data to be put in ByteBuffer for easier reading of the little-endian data
|
||||
// data put into ByteBuffer would be byte 2 to byte 27 (skipping leading 2 type bytes and trailing 4 terminator bytes)
|
||||
int dataLen = BINLIGHTNING_RECORD_SIZE - 2 - LAST_TERM_BYTES.length;
|
||||
|
||||
for (int i = 0; i < data.length / BINLIGHTNING_RECORD_SIZE; i++) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(dataLen);
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
// put the data into ByteBuffer
|
||||
buffer.put(data, offset + 2, dataLen);
|
||||
|
||||
// Reset buffer position to read in data we just stored.
|
||||
buffer.position(0);
|
||||
|
||||
// Do NOT change the read order below
|
||||
// read signed 16 bit integer as short and assigned to short
|
||||
// read other 16 bit (unsigned) integer as short, but assign to int after bit & with 0xffff, so no negatives when first bit is 1
|
||||
// Read count of seconds first
|
||||
long epochSeconds = buffer.getInt() & 0xffffffffL;
|
||||
// Convert to millisecond and add on millisecond offset
|
||||
int miliseconds = buffer.getShort() & 0xffff; // valid range: 0 to 999
|
||||
long epochTime = epochSeconds * 1000 + miliseconds;
|
||||
|
||||
// read lat/lon as float
|
||||
float lat = buffer.getFloat(); // valid range: -90.0 to 90.0
|
||||
float lon = buffer.getFloat(); // valid range: -180.0 to 180.0
|
||||
|
||||
// vendor, 0x01 for CONUS, i.e. NLD data;
|
||||
// 0x02 for long range source, GLD360?
|
||||
int vendor = buffer.getShort() & 0xffff; // valid values: 0x0001 (CONUS) or 0x0002 (long range source)
|
||||
|
||||
int strokeType = buffer.getShort() & 0xffff; // 0x0000 for cloud-to-ground, 0x00ff for cloud-to-cloud, 0xffff for total flash
|
||||
short strokeKiloAmps = buffer.getShort(); // valid range: -254 to 254, specifically 16 bit signed integer
|
||||
int strokeMultiplicity = buffer.getShort() & 0xffff; // i.e. stroke count, valid range: 0 to 15
|
||||
int strokeDuration = buffer.getShort() & 0xffff; // valid range: 0 to 65535 (i.e., looks like unsigned short)
|
||||
int reserved = buffer.getShort() & 0xffff;
|
||||
|
||||
// Create the strike record from the report info and base time information.
|
||||
BasePoint base = new BasePoint(lat, lon);
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(epochTime);
|
||||
base.setYear(cal.get(Calendar.YEAR));
|
||||
base.setMonth(cal.get(Calendar.MONTH) + 1);
|
||||
base.setDay(cal.get(Calendar.DAY_OF_MONTH));
|
||||
base.setHour(cal.get(Calendar.HOUR_OF_DAY));
|
||||
base.setMinute(cal.get(Calendar.MINUTE));
|
||||
base.setSecond(cal.get(Calendar.SECOND));
|
||||
base.setMillis(cal.get(Calendar.MILLISECOND));
|
||||
|
||||
// new spec does not seem to have lightning message type indicator such as FL (Flash Lightning) or RT (Real Time flash lightning)
|
||||
// The source of lightning data in the vendor specific data bytes (byte 16-17) may related to this (???),
|
||||
// and it is used here for now. 04/182/013 Wufeng Zhou
|
||||
/** 05/02/2013, found DSI-9603 Spec (http://www1.ncdc.noaa.gov/pub/data/documentlibrary/tddoc/td9603.pdf) on NLDN lightning data format,
|
||||
* on Message Type and Stroke Type:
|
||||
* POS: 37-38 Message Type
|
||||
* This field identifies whether this record was U.S. continental data or an international location.
|
||||
* Values are “FL” and “RT”.
|
||||
* A value of “FL” stands for FLASH and identifies this record as U.S. data.
|
||||
* A value of “RT” stands for Real-Time data type and identifies this record as international data.
|
||||
* POS: 40-41 Stroke Type
|
||||
* This field identifies whether this lightning stroke was cloud-to-ground or cloud-to-cloud.
|
||||
* Values are “CG” for cloud-to-ground and “CC” for cloud-to-cloud. FLASH (FL) data are always cloud-to-ground
|
||||
* while REAL-TIME (RT) data can be either type.
|
||||
*/
|
||||
LtgMsgType msgType = LtgMsgType.STRIKE_MSG_FL; // as default
|
||||
if (vendor == ((short)0x0001)) { // CONUS source
|
||||
msgType = LtgMsgType.STRIKE_MSG_FL;
|
||||
} else if (vendor == ((short)0x0002)) { // long range source
|
||||
msgType = LtgMsgType.STRIKE_MSG_RT;
|
||||
}
|
||||
|
||||
LightningStrikePoint lsp = new LightningStrikePoint(base, lat, lon, msgType);
|
||||
LtgStrikeType ltgStrikeType = LtgStrikeType.STRIKE_CG; // default ??
|
||||
if (strokeType == 0x0000) {
|
||||
ltgStrikeType = LtgStrikeType.STRIKE_CG;
|
||||
} else if (strokeType == 0x00ff) {
|
||||
ltgStrikeType = LtgStrikeType.STRIKE_CC;
|
||||
} else if (strokeType == 0xffff) {
|
||||
ltgStrikeType = LtgStrikeType.STRIKE_TF;
|
||||
}
|
||||
lsp.setType(ltgStrikeType);
|
||||
|
||||
// as of OB13.3 for World Wide Lightning Location Network (WWLLN) data (decoded by textlightning though, not this bin lightning decoder),
|
||||
// added lightning source field in LightningStrikePoint, as well as column in binlightning database table defaults to NLDN
|
||||
if (vendor == ((short)0x0001)) { // CONUS source
|
||||
lsp.setLightSource("NLDN");
|
||||
} else if (vendor == ((short)0x0002)) { // long range source, i.e., GLD360.
|
||||
// However, since the database table column for lightning source is 5 characters
|
||||
lsp.setLightSource("GLD");
|
||||
}
|
||||
|
||||
lsp.setStrikeCount(strokeMultiplicity);
|
||||
lsp.setStrikeStrength(strokeKiloAmps);
|
||||
// stroke duration does not seem to be used
|
||||
|
||||
strikes.add(lsp);
|
||||
}
|
||||
return strikes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode bin lightning data, able to handle both legacy bit-shifted and new encryted data
|
||||
*
|
||||
* The modified BinLightningDecoder.decode() method will use this method to decode data, which
|
||||
* will try to decrypt first, and decode the old fashioned way when decryption fails
|
||||
*
|
||||
* @param data - data content from file, including WMO header section
|
||||
* @param pdata - data with WMO header stripped, optional, if null, will strip WMO header internally from passed in data parameter
|
||||
* @param traceId - the file name of the data to be deoced
|
||||
* @param dataDate - date of the data, optional, used as a hint to find appropriate encryption key faster
|
||||
* @return null if keep-alive record, otherwise a list (could be empty) of LightningStrikePoint
|
||||
*/
|
||||
public static List<LightningStrikePoint> decodeBinLightningData(byte[] data, byte[] pdata, String traceId, Date dataDate) {
|
||||
if (pdata == null) { // if data without header not passed, we'll strip the WMO header here
|
||||
WMOHeader header = new WMOHeader(data);
|
||||
if (header.isValid() && header.getMessageDataStart() > 0) {
|
||||
pdata = new byte[data.length - header.getMessageDataStart()];
|
||||
System.arraycopy(data, header.getMessageDataStart(), pdata, 0, data.length - header.getMessageDataStart());
|
||||
}
|
||||
}
|
||||
|
||||
List<LightningStrikePoint> strikes = new ArrayList<LightningStrikePoint>();
|
||||
boolean needDecrypt = true; // set as default unless clear evidence says otherwise
|
||||
boolean decodeDone = false;
|
||||
EncryptedBinLightningCipher cipher = new EncryptedBinLightningCipher();
|
||||
|
||||
//
|
||||
// Using different WMO headers to indicate whether the data is encrypted or not would be a nice option.
|
||||
// However, that idea has been discussed but not adopted.
|
||||
// If in the future, WMO header can be different for legacy and encrypted data, or some other metadata can be used to decide
|
||||
// whether deceyption is needed, logic can be added here.
|
||||
//
|
||||
// Before that happens, we'll use hints and trial & error to decode the data
|
||||
// Hints: Per lightning data format spec, there are 3 bytes in the WMO header starting line that indicates the size of the encrypted block
|
||||
// or the ASCII sequence # for legacy bit-shifted data
|
||||
// However, the starting line is optional and AWIPS decode may not see it at all because TG will strip that starting line away
|
||||
// We'll try to use this hint first, if is is not found, then trial and error way to decrypt and decode
|
||||
if (data != null) {
|
||||
byte[] sizeSeqBytes = BinLigntningDecoderUtil.findSizeOrSeqBytesFromWMOHeader(data);
|
||||
if (sizeSeqBytes != null) {
|
||||
// if this is in the header (which may not), use that as a hint to determine which decoding route to go
|
||||
if (BinLigntningDecoderUtil.isPossibleWMOHeaderSequenceNumber(sizeSeqBytes)
|
||||
&& BinLigntningDecoderUtil.getEncryptedBlockSizeFromWMOHeader(sizeSeqBytes) != pdata.length) {
|
||||
// looks like a sequence #, and if treat as size, it does not equal to the data block size, so most likely legacy data
|
||||
needDecrypt = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needDecrypt) {
|
||||
try {
|
||||
byte[] decryptedData = cipher.decryptData(pdata, dataDate);
|
||||
// decrypt ok, then decode, first check if keep-alive record
|
||||
if (BinLigntningDecoderUtil.isKeepAliveRecord(decryptedData)) {
|
||||
logger.info(traceId + " - Keep-alive record detected, ignore for now.");
|
||||
decodeDone = true;
|
||||
return null;
|
||||
}
|
||||
// not keep-alive record, then decode into an ArrayList<LightningStrikePoint> of strikes
|
||||
strikes = BinLigntningDecoderUtil.decodeDecryptedBinLightningData(decryptedData);
|
||||
decodeDone = true;
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
logger.info(traceId + " - " + e.getMessage() + ": Decryption failed, will try decode the old-fashioned way.");
|
||||
decodeDone = false;
|
||||
} catch (BadPaddingException e) {
|
||||
logger.info(traceId + " - " + e.getMessage() + ": Decryption failed, will try decode the old-fashioned way.");
|
||||
decodeDone = false;
|
||||
} catch (BinLightningDataDecryptionException e) {
|
||||
logger.info(traceId + " - " + e.getMessage() + ": Decryption failed, will try decode the old-fashioned way.");
|
||||
decodeDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (decodeDone == false) { // not decoded through decrypt->decode process, try the legacy decoder
|
||||
strikes = BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(pdata);
|
||||
}
|
||||
|
||||
return strikes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the bytes passed are a standard "NWS Keep Alive" message.
|
||||
*
|
||||
* Note, record type in data are represented as 16-bit little-endian integer
|
||||
* i.e., for keep alive record type (0x0000), byte[0] will be 0x00, byte[1] will be ox00
|
||||
*
|
||||
* @param raw - Buffer containing bytes to check.
|
||||
*
|
||||
* @return true if bytes specified match a full "keep alive" message.
|
||||
*/
|
||||
|
||||
public static boolean isKeepAliveRecord(byte[] data) {
|
||||
return (data.length == 6) && ((data[0] & 0xff) == (KEEP_ALIVE_TYPE & 0xff))
|
||||
&& ((data[1] & 0xff) == ((KEEP_ALIVE_TYPE >> 8) & 0xff))
|
||||
&& isLastTerminator(data, 2, data.length - 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the bytes passed are a standard "NWS Last Element" terminator sequence.
|
||||
*
|
||||
* Note, record type in data are represented as 16-bit little-endian integer
|
||||
* i.e., for lightning data record type (0x00ff), byte[0] will be 0xff, byte[1] will be ox00
|
||||
*
|
||||
* @param raw - Buffer containing bytes to check.
|
||||
* @param ofs - Offset within buffer to start check at.
|
||||
* @param len - How many bytes from offset are available in the buffer.
|
||||
*
|
||||
* @return true if enough bytes are available and match the expected sequence.
|
||||
*/
|
||||
public static boolean isLastTerminator(byte[] raw, int ofs, int len) {
|
||||
return compareBytes(LAST_TERM_BYTES, raw, ofs, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if raw data looks like a NWS lightning record.
|
||||
*
|
||||
* @param raw Buffer of bytes to inspect.
|
||||
* @param ofs Current offset into the buffer.
|
||||
* @param len Length of bytes left in the buffer.
|
||||
*
|
||||
* @return -1 if not bin lightning record,
|
||||
* 0 if bin lightning record with continuation terminator (terminated with bytes 0x0D 0x0D, 0x0A, 0x00)
|
||||
* 3 if it is the last bin lightning record (terminated with bytes 0x0D 0x0D, 0x0A, 0x03)
|
||||
*/
|
||||
public static int checkBinLightningRecord(byte[] raw, int ofs, int len) {
|
||||
if (len < 0) {
|
||||
len = raw.length - ofs;
|
||||
}
|
||||
if (len < BINLIGHTNING_RECORD_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
int terminatorOffset = BINLIGHTNING_RECORD_SIZE - 4;
|
||||
if (((raw[ofs] & 0xff) == (LIGHTNING_TYPE & 0xff)) && ((raw[ofs + 1] & 0xff) == ((LIGHTNING_TYPE >> 8) & 0xff))) {
|
||||
// record type indicates lightning record, now check record terminator
|
||||
if (isMoreTerminator(raw, ofs + terminatorOffset, len - terminatorOffset)) {
|
||||
return 0;
|
||||
} else if (isLastTerminator(raw, ofs + terminatorOffset, len - terminatorOffset)) {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the decrypted data is valid, i.e. contains either keep-alive record or a series of lightning data records
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static boolean isLightningDataRecords(byte[] data) {
|
||||
if (data == null) return false;
|
||||
|
||||
if (data.length % BINLIGHTNING_RECORD_SIZE != 0) { // not a multiple of bin lightning data record size (32)
|
||||
return false;
|
||||
}
|
||||
|
||||
// check all records
|
||||
int recordCount = data.length / BINLIGHTNING_RECORD_SIZE;
|
||||
for (int i = 0; i < recordCount; i++) {
|
||||
int offset = i * BINLIGHTNING_RECORD_SIZE;
|
||||
int lenLeft = data.length - offset;
|
||||
if (i < (recordCount - 1) && checkBinLightningRecord(data, offset, lenLeft) != 0) {
|
||||
return false;
|
||||
} else if (i == (recordCount - 1) && checkBinLightningRecord(data, offset, lenLeft) != 3) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the decrypted data is valid, check record by record for either keep-alive record or lightning data record
|
||||
*
|
||||
* NOTE: use this to check data validity only if keep-alive record is allowed to be mixed with lightning record (as in one sample file).
|
||||
* However, generally as email communication cleared, keep-alive record should be in its own file.
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidMixedRecordData(byte[] data) {
|
||||
if (data == null) return false;
|
||||
int ofs = 0;
|
||||
while ((ofs + 1) < data.length) {
|
||||
// check record type bytes
|
||||
if (((data[ofs] & 0xff) == (KEEP_ALIVE_TYPE & 0xff)) && ((data[ofs + 1] & 0xff) == ((KEEP_ALIVE_TYPE >> 8) & 0xff))) {
|
||||
// keep-alive record, check its ending bytes after 2 bytes
|
||||
if (isLastTerminator(data, ofs+2, data.length - ofs - 2)) {
|
||||
ofs += 6;
|
||||
if (data.length == ofs) return true; // reach the end
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (((data[ofs] & 0xff) == (LIGHTNING_TYPE & 0xff)) && ((data[ofs + 1] & 0xff) == ((LIGHTNING_TYPE >> 8) & 0xff))) {
|
||||
// lightning record, check ending bytes after 28 bytes
|
||||
if (isMoreTerminator(data, ofs + 28, data.length - ofs - 28)) {
|
||||
ofs += 32;
|
||||
if (data.length == ofs) return false; // reach the end but not last terminator
|
||||
} else if (isLastTerminator(data, ofs + 28, data.length - ofs - 28)) {
|
||||
ofs += 32;
|
||||
if (data.length == ofs) return true; // reach the end
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the bytes passed are a standard "NWS Last Element" OR a "NWS More Elements" terminator sequence.
|
||||
*
|
||||
* @param raw - Buffer containing bytes to check.
|
||||
* @param ofs - Offset within buffer to start check at.
|
||||
* @param len - How many bytes from offset are available in the buffer.
|
||||
*
|
||||
* @return true if enough bytes are available and match the expected sequence.
|
||||
*/
|
||||
|
||||
public static boolean isTerminator(byte[] raw, int ofs, int len) {
|
||||
return isMoreTerminator(raw, ofs, len) || isLastTerminator(raw, ofs, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the bytes passed are a standard "NWS More Element" terminator sequence.
|
||||
*
|
||||
* @param raw - Buffer containing bytes to check.
|
||||
* @param ofs - Offset within buffer to start check at.
|
||||
* @param len - How many bytes from offset are available in the buffer.
|
||||
*
|
||||
* @return true if enough bytes are available and match the expected sequence.
|
||||
*/
|
||||
|
||||
public static boolean isMoreTerminator(byte[] raw, int ofs, int len) {
|
||||
return compareBytes(MORE_TERM_BYTES, raw, ofs, len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method to compare bytes in a buffer to a known source.
|
||||
*
|
||||
* @param ref - Reference set of bytes you want to check against
|
||||
* (all bytes in this array must be present in the src array starting
|
||||
* at the offset specified and the length of the reference array
|
||||
* must be equal to or less than the 'len' specified).
|
||||
*
|
||||
* @param raw - Buffer containing bytes to check.
|
||||
* @param ofs - Offset within buffer to start check at.
|
||||
* @param len - How many bytes from offset are available in the buffer.
|
||||
*
|
||||
* @return true if byte range specified matches the reference array.
|
||||
*/
|
||||
private static boolean compareBytes(byte[] ref, byte[] src, int ofs, int len) {
|
||||
|
||||
int sizeToCompare = ref.length;
|
||||
if (len < sizeToCompare) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < sizeToCompare; i++) {
|
||||
if (ref[i] != src[ofs + i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Source bytes to check matched if this point reached
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* find from the optional WMO header line (which could be stripped by switching system such as TG) the size or sequence bytes (3 bytes)
|
||||
* the 3 bytes should be after the WMO header start bytes if they all exist
|
||||
*
|
||||
* @param data - data including the WMO header section
|
||||
* @return null if not found,
|
||||
*/
|
||||
public static byte[] findSizeOrSeqBytesFromWMOHeader(byte[] data) {
|
||||
if (compareBytes(WMO_HEADER_START_BYTES, data, 0, data.length) == true && data.length > 32) {
|
||||
// found the [SOH] [CR] [CR] [LF] byte sequence at the beginning, then the next 3 bytes is what we looking for
|
||||
return Arrays.copyOfRange(data, WMO_HEADER_START_BYTES.length, WMO_HEADER_START_BYTES.length + 3);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert the 3 bytes encrypted block size in WMO header to an integer according to spec.
|
||||
* @param sizeBytes
|
||||
* @return -1 if invalid sizeBytes
|
||||
*/
|
||||
public static int getEncryptedBlockSizeFromWMOHeader(byte[] sizeBytes) {
|
||||
if (sizeBytes == null || sizeBytes.length != 3) return -1;
|
||||
|
||||
return (sizeBytes[0] & 0xff) + ((sizeBytes[1] & 0xff) << 8) + ((sizeBytes[2] & 0xff) << 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the bytes looks like a sequence number in 3 ASCII characters
|
||||
*
|
||||
* @param seqBytes
|
||||
* @return
|
||||
*/
|
||||
public static boolean isPossibleWMOHeaderSequenceNumber(byte[] seqBytes) {
|
||||
if (seqBytes == null || seqBytes.length != 3) return false;
|
||||
|
||||
if (Character.isDigit(seqBytes[0]) && Character.isDigit(seqBytes[1]) && Character.isDigit(seqBytes[2])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* This code has been developed by NWS/OST to support AWIPS II
|
||||
*
|
||||
*/
|
||||
package gov.noaa.nws.ost.edex.plugin.binlightning;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* EncryptedBinLightningCipher
|
||||
*
|
||||
* Use AES secret keys found in configured keystore to decrypt bin lightning data
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20130503 DCS 112 Wufeng Zhou To handle both the new encrypted data and legacy bit-shifted data
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author Wufeng Zhou
|
||||
*
|
||||
*/
|
||||
public class EncryptedBinLightningCipher {
|
||||
private static final String BINLIGHTNING_CIPHER_TYPE = "AES";
|
||||
|
||||
/** Maximum size of the encrypted block, determined by 3 byte length field in the header */
|
||||
private static final int MAX_SIZE_ENCRYPTED_BLOCK = 0xffffff;
|
||||
|
||||
/**
|
||||
* Cipher creation is a relatively expensive operation and would be better to reuse it in the same thread.
|
||||
**/
|
||||
private static final ThreadLocal<HashMap<String, Cipher>> decryptCipherMap = new ThreadLocal<HashMap<String, Cipher>>() {
|
||||
|
||||
@Override
|
||||
protected HashMap<String, Cipher> initialValue() {
|
||||
// get AES keys from keystore and create encryption and decryption ciphers from them
|
||||
BinLightningAESKey[] keys = BinLightningAESKey.getBinLightningAESKeys();
|
||||
HashMap<String, Cipher> cipherMap = new HashMap<String, Cipher>();
|
||||
for (BinLightningAESKey key : keys) {
|
||||
try {
|
||||
SecretKeySpec skeySpec = (SecretKeySpec)key.getKey();
|
||||
Cipher cipher = Cipher.getInstance(BINLIGHTNING_CIPHER_TYPE);
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
|
||||
|
||||
cipherMap.put(key.getAlias(), cipher);
|
||||
} catch (Exception e) {
|
||||
logger.error("Fail to create decrypt Cipher from key " + key.getAlias(), e);
|
||||
}
|
||||
}
|
||||
return cipherMap;
|
||||
}
|
||||
};
|
||||
|
||||
private static Log logger = LogFactory.getLog(EncryptedBinLightningCipher.class);
|
||||
|
||||
public EncryptedBinLightningCipher() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt data with AES keys
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
* @throws IllegalBlockSizeException
|
||||
* @throws BadPaddingException
|
||||
*/
|
||||
public byte[] decryptData(byte[] data) throws IllegalBlockSizeException, BadPaddingException, BinLightningDataDecryptionException {
|
||||
return decryptData(data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* decrypt data with AES keys, using data observation date as a hint to find the best suitable key to try first
|
||||
*
|
||||
* @param data
|
||||
* @param dataDate
|
||||
* @return
|
||||
* @throws IllegalBlockSizeException
|
||||
* @throws BadPaddingException
|
||||
*/
|
||||
public byte[] decryptData(byte[] data, Date dataDate) throws IllegalBlockSizeException, BadPaddingException, BinLightningDataDecryptionException {
|
||||
if (data == null) {
|
||||
throw new IllegalBlockSizeException("Data is null");
|
||||
}
|
||||
if (data.length == 0) {
|
||||
throw new IllegalBlockSizeException("Data is empty");
|
||||
}
|
||||
if (data.length > MAX_SIZE_ENCRYPTED_BLOCK) {
|
||||
throw new IllegalBlockSizeException("Block size exceeds maxinum expected.");
|
||||
}
|
||||
|
||||
HashMap<String, Cipher> cipherMap = EncryptedBinLightningCipher.decryptCipherMap.get();
|
||||
// find the preferred key order to try decryption based on data date
|
||||
List<BinLightningAESKey> preferredKeyList = findPreferredKeyOrderForData(dataDate);
|
||||
|
||||
if (preferredKeyList == null || preferredKeyList.size() == 0) {
|
||||
throw new BinLightningDataDecryptionException("No AES key found to decrypt data. Please make sure keystore is properly configured with key(s).");
|
||||
}
|
||||
|
||||
// try to decrypt the data using ciphers in the list until successful
|
||||
byte[] decryptedData = null;
|
||||
for (int i = 0; i < preferredKeyList.size(); i++) {
|
||||
Cipher cipher = cipherMap.get(preferredKeyList.get(i).getAlias());
|
||||
try {
|
||||
decryptedData = cipher.doFinal(data, 0, data.length);
|
||||
|
||||
// wrong key will decrypt data into random noise/garbage, so we need to do a sanity check to make sure
|
||||
// we are decrypting with the right key
|
||||
if ( BinLigntningDecoderUtil.isKeepAliveRecord(decryptedData) == false && BinLigntningDecoderUtil.isLightningDataRecords(decryptedData) == false) {
|
||||
//if (BinLigntningDecoderUtil.isValidMixedRecordData(decryptedData) == false) { // use this only if keep-alive record could be mixed with lightning records
|
||||
logger.info("Decrypted data (" + decryptedData.length + " bytes) with key " + preferredKeyList.get(i).getAlias()
|
||||
+ " is not valid keep-alive or binLightning records. Try other key.");
|
||||
throw new BinLightningDataDecryptionException("Decrypted data (" + decryptedData.length + " bytes) with key "
|
||||
+ preferredKeyList.get(i).getAlias() + " is not valid keep-alive or binLightning records.", decryptedData);
|
||||
}
|
||||
logger.info("Data (" + data.length + " bytes) decrypted to " + decryptedData.length + " bytes with key: " + preferredKeyList.get(i).getAlias());
|
||||
break; // decrypt ok, break out
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
// ignore exception if not the last, and try next cipher
|
||||
logger.info("Fail to decrypt data (" + data.length + " bytes) with key: " + preferredKeyList.get(i).getAlias() + " - " + e.getMessage() + ", will try other keys");
|
||||
if (i == (preferredKeyList.size() - 1)) {
|
||||
logger.info("Fail to decrypt with all know keys, either data is not encrypted or is invalid.");
|
||||
throw e;
|
||||
}
|
||||
} catch (BadPaddingException e) {
|
||||
// ignore exception if not the last, and try next cipher
|
||||
logger.info("Fail to decrypt data (" + data.length + " bytes) with key: " + preferredKeyList.get(i).getAlias() + " - " + e.getMessage() + ", will try other keys");
|
||||
if (i == (preferredKeyList.size() - 1)) {
|
||||
logger.info("Fail to decrypt with all know keys, either data is not encrypted or is invalid.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return decryptedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming the best keys to decrypt data should be issued before the data observation date, so
|
||||
* if there were many keys issued, this hopefully will reduce the unnecessary decryption tries
|
||||
*
|
||||
* @param dataDate
|
||||
* @return preferred key list order
|
||||
*/
|
||||
private List<BinLightningAESKey> findPreferredKeyOrderForData(Date dataDate) {
|
||||
List<BinLightningAESKey> defKeyList = Arrays.asList(BinLightningAESKey.getBinLightningAESKeys());
|
||||
if (dataDate == null) {
|
||||
return defKeyList; // use default order
|
||||
}
|
||||
|
||||
int preferredKeyIndex = -1;
|
||||
for (int i = 0; i < defKeyList.size() - 2; i++) {
|
||||
if (dataDate.before(defKeyList.get(i).getKeyDate()) && dataDate.after(defKeyList.get(i+1).getKeyDate())) {
|
||||
// found the preferred key at index i+1
|
||||
preferredKeyIndex = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (preferredKeyIndex == -1) { // no preferred keys found for data date, use default order
|
||||
return defKeyList;
|
||||
} else {
|
||||
List<BinLightningAESKey> preferredList = new ArrayList<BinLightningAESKey>();
|
||||
preferredList.addAll(defKeyList.subList(preferredKeyIndex, defKeyList.size()));
|
||||
preferredList.addAll(defKeyList.subList(0, preferredKeyIndex));
|
||||
return preferredList;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -48,7 +48,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:bufrmos?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:bufrmos?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:bufrua?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:bufrua?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -51,14 +51,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ccfp?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ccfp?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ccfp?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ccfp?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<bean ref="parmIdFilter" method="updateParmIdCache" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:paramIdCache?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:paramIdCache?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -76,7 +76,7 @@
|
|||
</filter>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:gfeNotify?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:gfeNotify?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -92,7 +92,7 @@
|
|||
<bean ref="d2dParmIdCache" method="pluginPurged" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:paramIdCache?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:paramIdCache?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -104,7 +104,7 @@
|
|||
<bean ref="gridParmManager" method="processNotification" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:gridParmManager?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:gridParmManager?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -578,7 +578,7 @@
|
|||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to
|
||||
uri="log:svcBackup?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
uri="log:svcBackup?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -600,7 +600,7 @@
|
|||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to
|
||||
uri="log:svcBackup?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
uri="log:svcBackup?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -616,7 +616,7 @@
|
|||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to
|
||||
uri="log:svcBackup?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
uri="log:svcBackup?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -631,7 +631,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:iscDataRec?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:iscDataRec?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -649,7 +649,7 @@
|
|||
<bean ref="iscSendQueue" method="addSendJobs" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:iscSendQueue?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:iscSendQueue?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<bean ref="spcWatch" method="handleSpcWatch" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:gfeWatch?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:gfeWatch?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -56,7 +56,7 @@
|
|||
<bean ref="tpcWatch" method="handleTpcWatch" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:gfeWatch?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:gfeWatch?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -85,7 +85,7 @@
|
|||
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:gfeIngestFilter?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:gfeIngestFilter?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -98,7 +98,7 @@
|
|||
<bean ref="smartInitQueue" method="addManualInit" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:smartinit?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:smartinit?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -110,7 +110,7 @@
|
|||
<bean ref="vtecChangeListener" method="handleNotification" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:vtecChangeListener?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:vtecChangeListener?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -123,7 +123,7 @@
|
|||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to
|
||||
uri="log:gfeIngestFilter?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
uri="log:gfeIngestFilter?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -40,6 +40,7 @@ import com.raytheon.uf.common.time.TimeRange;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 04/18/08 #875 bphillip Initial Creation
|
||||
* 09/22/09 3058 rjpeter Converted to IRequestHandler
|
||||
* 06/06/13 #2073 dgilling Ensure payload is always populated.
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
|
@ -56,16 +57,11 @@ public class GetGridInventoryHandler implements
|
|||
ServerResponse<List<TimeRange>> timeSr = GridParmManager
|
||||
.getGridInventory(parmId);
|
||||
List<TimeRange> times = timeSr.getPayload();
|
||||
inventory.put(parmId, times);
|
||||
sr.addMessages(timeSr);
|
||||
|
||||
if (sr.isOkay()) {
|
||||
inventory.put(parmId, times);
|
||||
}
|
||||
}
|
||||
|
||||
if (sr.isOkay()) {
|
||||
sr.setPayload(inventory);
|
||||
}
|
||||
sr.setPayload(inventory);
|
||||
return sr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,12 @@ import com.raytheon.edex.plugin.gfe.server.lock.LockManager;
|
|||
import com.raytheon.edex.plugin.gfe.util.SendNotifications;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.request.LockChangeRequest;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerMsg;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.server.message.ServerResponse;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.server.notify.GfeNotification;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.server.notify.LockNotification;
|
||||
import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
|
||||
/**
|
||||
* GFE task for requesting a lock change
|
||||
|
@ -44,12 +45,17 @@ import com.raytheon.uf.common.serialization.comm.IRequestHandler;
|
|||
* 06/17/08 #940 bphillip Implemented GFE Locking
|
||||
* 09/22/09 3058 rjpeter Converted to IRequestHandler
|
||||
* 04/24/13 1949 rjpeter Added list sizing
|
||||
* 06/12/13 2099 randerso Send GridUpdateNotifications,
|
||||
* clean up error handling
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LockChangeHandler implements IRequestHandler<LockChangeRequest> {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(LockChangeHandler.class);
|
||||
|
||||
@Override
|
||||
public ServerResponse<List<LockTable>> handleRequest(
|
||||
LockChangeRequest request) throws Exception {
|
||||
|
@ -70,13 +76,16 @@ public class LockChangeHandler implements IRequestHandler<LockChangeRequest> {
|
|||
ServerResponse<?> notifyResponse = SendNotifications
|
||||
.send(notes);
|
||||
if (!notifyResponse.isOkay()) {
|
||||
for (ServerMsg msg : notifyResponse.getMessages()) {
|
||||
sr.addMessage(msg.getMessage());
|
||||
}
|
||||
statusHandler.error(notifyResponse.message());
|
||||
}
|
||||
|
||||
// send out grid update notifications
|
||||
notifyResponse = SendNotifications.send(sr.getNotifications());
|
||||
if (!notifyResponse.isOkay()) {
|
||||
statusHandler.error(notifyResponse.message());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
sr.addMessage("Error sending lock notification - "
|
||||
+ e.getMessage());
|
||||
statusHandler.error("Error sending lock notification", e);
|
||||
}
|
||||
}
|
||||
return sr;
|
||||
|
|
|
@ -41,6 +41,8 @@ import com.raytheon.uf.edex.core.EdexException;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 06/30/08 #875 bphillip Initial Creation
|
||||
* 09/22/09 3058 rjpeter changed to utility.
|
||||
* 06/12/13 2099 dgilling Remove error when passed empty list of
|
||||
* notifications.
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
|
@ -60,7 +62,6 @@ public class SendNotifications {
|
|||
List<? extends GfeNotification> notifications) {
|
||||
ServerResponse<?> sr = new ServerResponse<String>();
|
||||
if (notifications.isEmpty()) {
|
||||
sr.addMessage("Attempting to send empty notification list");
|
||||
return sr;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,14 +57,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:goessounding?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:goessounding?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:goessounding?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:goessounding?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:grib?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:grib?level=ERROR"/>
|
||||
</doCatch>
|
||||
<doFinally>
|
||||
<bean ref="gribSplitter" method="clean" />
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:grib?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:grib?level=ERROR"/>
|
||||
</doCatch>
|
||||
<doFinally>
|
||||
<bean ref="gribSplitter" method="clean" />
|
||||
|
|
|
@ -31,21 +31,21 @@
|
|||
<to uri="direct-vm:ldadmesonetIngest" />
|
||||
<catch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ldadmesonet?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ldadmesonet?level=ERROR"/>
|
||||
</catch>
|
||||
</try>
|
||||
<try>
|
||||
<to uri="direct-vm:ldadhydroIngest" />
|
||||
<catch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ldadhydro?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ldadhydro?level=ERROR"/>
|
||||
</catch>
|
||||
</try>
|
||||
<try>
|
||||
<to uri="direct-vm:ldadmanualIngest" />
|
||||
<catch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ldadmanual?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ldadmanual?level=ERROR"/>
|
||||
</catch>
|
||||
</try>
|
||||
</multicast>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ldadhydro?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ldadhydro?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ldadmanual?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ldadmanual?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:ldadprofiler?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:ldadprofiler?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -62,14 +62,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:modelsounding?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:modelsounding?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:modelsounding?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:modelsounding?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:metar?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:metar?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -55,14 +55,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:pirep?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:pirep?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:pirep?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:pirep?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:poessounding?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:poessounding?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:profiler?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:profiler?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:radar?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
<to uri="log:radar?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -55,14 +55,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:recco?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:recco?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:recco?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:recco?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -64,12 +64,15 @@ import com.vividsolutions.jts.geom.Geometry;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20080103 384 jkorman Initial Coding.
|
||||
* 20080107 720 jkorman remove default assignments from attributes.
|
||||
* Apr 4, 2013 1846 bkowal Added an index on refTime and forecastTime
|
||||
* Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation.
|
||||
* Jan 03, 2008 384 jkorman Initial Coding.
|
||||
* Jan 07, 2008 720 jkorman remove default assignments from
|
||||
* attributes.
|
||||
* Apr 04, 2013 1846 bkowal Added an index on refTime and
|
||||
* forecastTime
|
||||
* Apr 12, 2013 1857 bgonzale Added SequenceGenerator annotation.
|
||||
* May 07, 2013 1869 bsteffen Remove dataURI column from
|
||||
* PluginDataObject.
|
||||
* Jun 20, 2013 2128 bsteffen Ensure setDataURI sets the dataURI.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -621,6 +624,7 @@ public class RECCORecord extends PluginDataObject implements ISpatialEnabled,
|
|||
|
||||
@Override
|
||||
public void setDataURI(String dataURI) {
|
||||
super.setDataURI(dataURI);
|
||||
identifier = dataURI;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:redbook?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:redbook?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:sat?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:sat?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:sfcobs?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:sfcobs?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to
|
||||
uri="log:shef?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
uri="log:shef?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -167,7 +167,7 @@
|
|||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to
|
||||
uri="log:shef?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
uri="log:shef?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -58,14 +58,14 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:taf?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:taf?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</split>
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:taf?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:taf?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<bean ref="autoFaxDao" method="updateCache" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:autoFax?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:autoFax?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:text?level=INFO&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:text?level=INFO"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -109,7 +109,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:text?level=INFO&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:text?level=INFO"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -134,7 +134,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:text?level=INFO&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:text?level=INFO"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -167,7 +167,7 @@
|
|||
<to uri="jms-generic:queue:textPurgeRequest" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:purge?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:purge?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -179,7 +179,7 @@
|
|||
<bean ref="autoFaxManager" method="processEvent" />
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:autoFax?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:autoFax?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -196,7 +196,7 @@
|
|||
<bean ref="textVersionPurge" method="addAfosIdsToPurge"/>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:purge?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:purge?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
@ -206,7 +206,7 @@
|
|||
<bean ref="textVersionPurge" method="purgeAfosIds"/>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:purge?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:purge?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:textlightning?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true"/>
|
||||
<to uri="log:textlightning?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:warning?level=ERROR&showBody=false&showCaughtException=true&showStackTrace=true" />
|
||||
<to uri="log-showbody:warning?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
</route>
|
||||
|
|
|
@ -193,7 +193,7 @@ public class ArchiveConfig implements Comparable<ArchiveConfig> {
|
|||
|
||||
@Override
|
||||
public int compareTo(ArchiveConfig o) {
|
||||
return getName().compareTo(o.getName());
|
||||
return getName().compareToIgnoreCase(o.getName());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -378,12 +378,12 @@ public class ArchiveConfigManager {
|
|||
* Get a list of directories/files for the desired display label bounded by
|
||||
* the start and end time inclusive.
|
||||
*
|
||||
* @param displayInfo
|
||||
* @param displayData
|
||||
* @param startCal
|
||||
* @param endCal
|
||||
* @return files
|
||||
*/
|
||||
public List<File> getDisplayFiles(DisplayData displayInfo,
|
||||
public List<File> getDisplayFiles(DisplayData displayData,
|
||||
Calendar startCal, Calendar endCal) {
|
||||
long startTime = 0L;
|
||||
if (startCal != null) {
|
||||
|
@ -409,7 +409,7 @@ public class ArchiveConfigManager {
|
|||
cal.add(Calendar.HOUR_OF_DAY, 1);
|
||||
|
||||
long endTime = cal.getTimeInMillis();
|
||||
return getDisplayFiles(displayInfo, startTime, endTime);
|
||||
return getDisplayFiles(displayData, startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -420,8 +420,8 @@ public class ArchiveConfigManager {
|
|||
* @param displayLabel
|
||||
* @return files
|
||||
*/
|
||||
public List<File> getDisplayFiles(DisplayData displayInfo) {
|
||||
return getDisplayFiles(displayInfo, null, null);
|
||||
public List<File> getDisplayFiles(DisplayData displayData) {
|
||||
return getDisplayFiles(displayData, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -435,10 +435,10 @@ public class ArchiveConfigManager {
|
|||
* @param endTime
|
||||
* @return files
|
||||
*/
|
||||
private List<File> getDisplayFiles(DisplayData displayInfo, long startTime,
|
||||
private List<File> getDisplayFiles(DisplayData displayData, long startTime,
|
||||
long endTime) {
|
||||
ArchiveConfig archiveConfig = displayInfo.archiveConfig;
|
||||
CategoryConfig categoryConfig = displayInfo.categoryConfig;
|
||||
ArchiveConfig archiveConfig = displayData.archiveConfig;
|
||||
CategoryConfig categoryConfig = displayData.categoryConfig;
|
||||
|
||||
String[] indexValues = categoryConfig.getDateGroupIndices().split(
|
||||
"\\s*,\\s*");
|
||||
|
@ -452,7 +452,7 @@ public class ArchiveConfigManager {
|
|||
boolean dirOnly = (filePatternStr == null)
|
||||
|| ".*".equals(filePatternStr);
|
||||
|
||||
List<File> dirs = displayInfo.dirs;
|
||||
List<File> dirs = displayData.dirs;
|
||||
|
||||
int beginIndex = archiveConfig.getRootDir().length();
|
||||
|
||||
|
@ -506,7 +506,7 @@ public class ArchiveConfigManager {
|
|||
fileCal.set(year, month, day, hour, 0, 0);
|
||||
long fileTime = fileCal.getTimeInMillis();
|
||||
if ((startTime <= fileTime) && (fileTime < endTime)) {
|
||||
fileList.add(dir);
|
||||
fileList.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ public class CategoryConfig implements Comparable<CategoryConfig> {
|
|||
*/
|
||||
@Override
|
||||
public int compareTo(CategoryConfig o) {
|
||||
return getDisplay().compareTo(o.getDisplay());
|
||||
return getDisplay().compareToIgnoreCase(o.getDisplay());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue