13.5.1-3 baseline

Former-commit-id: a0ff6c20ea [formerly d8176d4a4c] [formerly 63803c1424] [formerly a0ff6c20ea [formerly d8176d4a4c] [formerly 63803c1424] [formerly 72d22a30c9 [formerly 63803c1424 [formerly cc90f0c02410fef504ec9de389c07dfa41164247]]]]
Former-commit-id: 72d22a30c9
Former-commit-id: e1a5587dd0 [formerly deebdb874a] [formerly d0cb0ee5e39989d9bf546dcfaef136a80153b511 [formerly 810388f00a]]
Former-commit-id: 295839b2b350f5da0fea64ca71fc6c7482abe123 [formerly 1e939939b5]
Former-commit-id: 50d4376af7
This commit is contained in:
Steve Harris 2013-06-24 09:29:43 -04:00
parent 4d75e573f4
commit d3517d7c1d
80 changed files with 4540 additions and 6457 deletions

View file

@ -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;

View file

@ -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();
}
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -69,6 +69,7 @@ import com.raytheon.uf.viz.monitor.ffmp.xml.FFMPTableColumnXML;
* Mar 15,2012 DR 14406 gzhang Fixing QPF Column Title Missing
* Mar 20,2012 DR 14250 gzhang Eliminating column Missing values
* Aug 01, 2012 14168 mpduff Only allow filtering if ColorCell is true
* Jun 11, 2013 2075 njensen Optimized createTableItems()
* </pre>
*
* @author lvenable
@ -149,8 +150,6 @@ public abstract class FFMPTable extends Composite {
protected int textHeight = 0;
private String centeredAggregateKey;
private ArrayList<Integer> indexArray = new ArrayList<Integer>();
private Point extent = new Point(0, 0);
@ -281,7 +280,6 @@ public abstract class FFMPTable extends Composite {
item.setBackground(j, cellData[j].getBackgroungColor());
}
}
table.getColumn(0).setWidth(extent.x + 10);
table.redraw();
}
@ -394,7 +392,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;
@ -429,6 +429,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);
@ -444,7 +445,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
@ -731,7 +732,7 @@ public abstract class FFMPTable extends Composite {
int xCoord = 0;
int yCoord = 0;
if (colName.indexOf("\n") > 0) {
int maxTextLen = 0;
// int maxTextLen = 0;
String[] tmpArray = colName.split("\n");
for (int j = 0; j < tmpArray.length; j++) {
@ -835,14 +836,6 @@ public abstract class FFMPTable extends Composite {
showHideTableColumns(attrData);
}
public void setCenteredAggregationKey(Object key) {
if (key instanceof Long) {
this.centeredAggregateKey = String.valueOf(key);
} else {
this.centeredAggregateKey = (String) key;
}
}
/**
* Handle the mouse button down on the table.
*

View file

@ -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;
}
}
}

View file

@ -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();

View file

@ -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.
*

View file

@ -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;
@ -120,6 +118,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* Mar 29, 2013 1790 rferrel Bug fix for non-blocking dialogs.
* 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 06, 2013 2075 njensen Removed loading labels
* </pre>
*
* @author lvenable
@ -273,8 +272,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
@ -1751,8 +1748,6 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements
if (!ffmpTable.isDisposed()) {
this.mainTableData = tData;
ffmpTable.clearTableSelection();
ffmpTable
.setCenteredAggregationKey(resource.centeredAggregationKey);
ffmpTable.setTableData(mainTableData);
resetCursor();
shell.pack();
@ -2097,47 +2092,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}
*/
@ -2241,11 +2195,6 @@ public class FfmpBasinTableDlg extends CaveSWTDialog implements
updateGapValueLabel(fupdateData.getGapValueLabel());
resetCursor();
// start tertiary loader if not run yet
if (loadStatus != null) {
resource.manageLoaders(loadStatus);
}
}
/**

View file

@ -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) {

View file

@ -1,8 +0,0 @@
package com.raytheon.uf.viz.monitor.ffmp.ui.listeners;
public interface FFMPLoadListener {
public void loadStatus(FFMPLoaderEvent event);
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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();

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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));
}
}
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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) {

View file

@ -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 ");

View file

@ -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() {

View file

@ -121,6 +121,7 @@ import com.raytheon.viz.hydrocommon.util.StnClassSyncUtil;
* 30 Jan 2013 15264 wkwock Fix the missing group_definition.cfg file crash
* 05 Feb 2013 1578 rferrel Dialog made non-blocking and a singleton.
* 06 May 2013 1976 mpduff Code cleanup.
* 06 Jun 2013 2076 mpduff Fix station list selection and graph button enabling.
* </pre>
*
* @author lvenable
@ -678,6 +679,8 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
if (rsc instanceof MultiPointResource) {
((MultiPointResource) rsc).setTs(this);
}
checkBottomButtons();
}
/**
@ -1460,7 +1463,9 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
while (iter2.hasNext()) {
if (idRdo.getSelection()) {
if (iter2.next().equalsIgnoreCase(currentLid)) {
topDataList.setSelection(iter2.previousIndex());
// Bug with show selection requires the select(0) first.
topDataList.select(0);
topDataList.select(iter2.previousIndex());
topDataList.showSelection();
/* set to null so we don't enter this block again */
@ -2606,6 +2611,5 @@ public class TimeSeriesDlg extends CaveHydroSWTDialog {
@Override
protected void preOpened() {
super.preOpened();
checkBottomButtons();
}
}

View file

@ -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() {

View file

@ -56,18 +56,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 -->
@ -296,9 +296,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 -->

View file

@ -55,6 +55,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"/>
@ -65,9 +79,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">

View file

@ -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>

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -29,6 +29,7 @@ package com.raytheon.uf.common.dataplugin.binlightning.impl;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 20070810 379 jkorman Initial Coding from prototype.
* 20130425 DCS 112 Wufeng Zhou Added STRIKE_TF (for Total Flash) in definition for Total Flash
*
* </pre>
*
@ -38,7 +39,8 @@ package com.raytheon.uf.common.dataplugin.binlightning.impl;
public enum LtgStrikeType
{
STRIKE_CC("CC"),
STRIKE_CG("CG");
STRIKE_CG("CG"),
STRIKE_TF("TF");
private final String strikeType;

View file

@ -87,6 +87,7 @@ import com.vividsolutions.jts.io.WKBReader;
* 02/20/13 1635 D. Hladky Constants
* 03/18/13 1817 D. Hladky Fixed issue with BOX where only 1 HUC was showing up.
* 04/15/13 1902 M. Duff Generic List
* 06/10/13 2085 njensen Use countyMap for efficiency
* </pre>
*
* @author dhladky
@ -1282,7 +1283,8 @@ public class FFMPTemplates {
* @param huc
* @return
*/
public synchronized LinkedHashMap<Long, ?> getMap(String dataKey, String cwa, String huc) {
public synchronized LinkedHashMap<Long, ?> getMap(String dataKey,
String cwa, String huc) {
LinkedHashMap<Long, ?> map = null;
HashMap<String, LinkedHashMap<Long, ?>> hucMap = null;
@ -1927,8 +1929,8 @@ public class FFMPTemplates {
getAbsoluteFileName(dataKey, huc, cwa, "list"));
try {
list = (long[]) SerializationUtil.transformFromThrift(FileUtil
.file2bytes(f.getFile(), true));
list = SerializationUtil.transformFromThrift(long[].class,
FileUtil.file2bytes(f.getFile(), true));
} catch (SerializationException se) {
se.printStackTrace();
} catch (IOException e) {
@ -1959,12 +1961,12 @@ public class FFMPTemplates {
if (huc.equals(FFMPRecord.ALL)) {
map = (HashMap<Long, FFMPBasinMetaData>) SerializationUtil
.transformFromThrift(FileUtil.file2bytes(f.getFile(),
true));
.transformFromThrift(HashMap.class,
FileUtil.file2bytes(f.getFile(), true));
} else {
map = (HashMap<Long, long[]>) SerializationUtil
.transformFromThrift(FileUtil.file2bytes(f.getFile(),
true));
.transformFromThrift(HashMap.class,
FileUtil.file2bytes(f.getFile(), true));
}
} catch (SerializationException se) {
se.printStackTrace();
@ -1995,7 +1997,8 @@ public class FFMPTemplates {
try {
map = (HashMap<String, FFMPVirtualGageBasinMetaData>) SerializationUtil
.transformFromThrift(FileUtil.file2bytes(f.getFile(), true));
.transformFromThrift(HashMap.class,
FileUtil.file2bytes(f.getFile(), true));
} catch (SerializationException se) {
se.printStackTrace();
} catch (IOException e) {
@ -2022,8 +2025,8 @@ public class FFMPTemplates {
getAbsoluteFileName(dataKey, FFMPRecord.VIRTUAL, cwa, "list"));
try {
list = (String[]) SerializationUtil.transformFromThrift(FileUtil
.file2bytes(f.getFile(), true));
list = SerializationUtil.transformFromThrift(String[].class,
FileUtil.file2bytes(f.getFile(), true));
} catch (SerializationException se) {
se.printStackTrace();
} catch (IOException e) {
@ -2342,11 +2345,14 @@ public class FFMPTemplates {
getCounties(siteKey);
}
FFMPCounty county = FFMPUtils
.getCounty(countyPfaf, MODE.CAVE.getMode());
FFMPCounty county = countyMap.get(countyPfaf);
if (county == null) {
county = FFMPUtils.getCounty(countyPfaf, MODE.CAVE.getMode());
countyMap.put(countyPfaf, county);
}
if (county != null) {
StringBuffer name = new StringBuffer();
StringBuilder name = new StringBuilder();
name.append(county.getState() + ", ");
name.append(county.getCountyName());
rname = name.toString();

View file

@ -166,10 +166,6 @@ public class ColumnAttribData {
splitColumnName = this.name.replaceAll(splitStr, "\n");
columnNameWithSpace = tmpName;
System.out.println("originalName = " + originalName);
System.out.println("columnName = " + columnName);
System.out.println("splitColumnName = " + splitColumnName);
}
/**

View file

@ -1,182 +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.common.stats.xml;
import java.lang.reflect.Method;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.event.Event;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Statistics Configuration Event xml element.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Nov 6, 2012 728 mpduff Initial creation.
*
* </pre>
*
* @author mpduff
* @version 1.0
*/
@DynamicSerialize
@XmlRootElement(name = "event")
@XmlAccessorType(XmlAccessType.NONE)
public class StatisticsEvent {
@XmlAttribute
@DynamicSerializeElement
private String type;
@XmlAttribute
@DynamicSerializeElement
private String displayName;
@XmlAttribute
@DynamicSerializeElement
private String category;
@XmlElements({ @XmlElement(name = "statisticsGroup", type = StatisticsGroup.class) })
@DynamicSerializeElement
private List<StatisticsGroup> groupList;
@XmlElements({ @XmlElement(name = "statisticsAggregate", type = StatisticsAggregate.class) })
@DynamicSerializeElement
private List<StatisticsAggregate> aggregateList;
private Class<? extends Event> typeClass = null;
private List<Method> groupByMethods = null;
private List<Method> aggregateMethods = null;
/**
* @return the aggregateList
*/
public List<StatisticsAggregate> getAggregateList() {
return aggregateList;
}
/**
* @return the category
*/
public String getCategory() {
return category;
}
/**
* @return the displayName
*/
public String getDisplayName() {
return displayName;
}
/**
* @return the groupList
*/
public List<StatisticsGroup> getGroupList() {
return groupList;
}
/**
* @return the type
*/
public String getType() {
return type;
}
/**
* @param aggregateList
* the aggregateList to set
*/
public void setAggregateList(List<StatisticsAggregate> aggregateList) {
this.aggregateList = aggregateList;
}
/**
* @param category
* the category to set
*/
public void setCategory(String category) {
this.category = category;
}
/**
* @param displayName
* the displayName to set
*/
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
/**
* @param groupList
* the groupList to set
*/
public void setGroupList(List<StatisticsGroup> groupList) {
this.groupList = groupList;
}
/**
* @param type
* the type to set
*/
public void setType(String type) {
this.type = type;
}
public Class<? extends Event> getTypeClass() {
return typeClass;
}
public void setTypeClass(Class<? extends Event> typeClass) {
this.typeClass = typeClass;
}
public List<Method> getGroupByMethods() {
return groupByMethods;
}
public void setGroupByMethods(List<Method> groupByMethods) {
this.groupByMethods = groupByMethods;
}
public List<Method> getAggregateMethods() {
return aggregateMethods;
}
public void setAggregateMethods(List<Method> aggregateMethods) {
this.aggregateMethods = aggregateMethods;
}
}

View file

@ -23,6 +23,7 @@ Require-Bundle: com.raytheon.uf.common.localization;bundle-version="1.11.1",
com.raytheon.uf.common.message;bundle-version="1.12.1174",
com.raytheon.uf.common.activetable;bundle-version="1.12.1174",
com.raytheon.uf.edex.site;bundle-version="1.0.0",
com.google.guava;bundle-version="1.0.0"
com.google.guava;bundle-version="1.0.0",
org.apache.log4j;bundle-version="1.0.0"
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.edex.activetable

View file

@ -30,6 +30,8 @@ import java.util.TreeSet;
import jep.JepException;
import org.apache.log4j.Logger;
import com.raytheon.edex.util.Util;
import com.raytheon.uf.common.activetable.ActiveTableMode;
import com.raytheon.uf.common.activetable.ActiveTableRecord;
@ -78,6 +80,7 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery;
* for merge logic.
* May 14, 2013 1842 dgilling Also delete cluster locks when purging
* PRACTICE active table.
* Jun 11, 2013 2083 randerso Log active table changes
*
* </pre>
*
@ -89,15 +92,14 @@ public class ActiveTable {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ActiveTable.class);
public static final String NATIONAL_CENTERS = ",KWNS,KNHC";
private static final Logger changeLog = Logger
.getLogger("ActiveTableChange");
private static final String NEXT_ETN_LOCK = "ActiveTableNextEtn";
private static String filePath;
private static String pythonPath;
private static String vtecPath;
private static String includePath;
private static CoreDao practiceDao = new CoreDao(
DaoConfig.forClass(PracticeActiveTableRecord.class));
@ -113,8 +115,15 @@ public class ActiveTable {
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
filePath = pathMgr.getFile(commonCx,
"vtec" + File.separator + "ActiveTable.py").getPath();
pythonPath = pathMgr.getFile(commonCx, "python").getPath();
vtecPath = pathMgr.getFile(commonCx, "vtec").getPath();
String siteId = pathMgr.getContext(LocalizationType.COMMON_STATIC,
LocalizationLevel.SITE).getContextName();
String pythonPath = ActiveTablePyIncludeUtil
.getCommonPythonIncludePath();
String vtecPath = ActiveTablePyIncludeUtil.getVtecIncludePath(siteId);
String configPath = ActiveTablePyIncludeUtil
.getGfeConfigIncludePath(siteId);
includePath = PyUtil.buildJepIncludePath(pythonPath, vtecPath,
configPath);
}
public ActiveTable() {
@ -303,7 +312,7 @@ public class ActiveTable {
}
MergeResult result = filterTable(getActiveTable(siteId, mode),
newRecords, offsetSecs);
newRecords, mode, offsetSecs);
updateTable(siteId, result, mode);
@ -325,16 +334,18 @@ public class ActiveTable {
* active table and the second being the purged records
*/
private MergeResult filterTable(List<ActiveTableRecord> activeTable,
List<ActiveTableRecord> newRecords, float offsetSecs) {
HashMap<String, Object> args = new HashMap<String, Object>(2);
List<ActiveTableRecord> newRecords, ActiveTableMode mode,
float offsetSecs) {
HashMap<String, Object> args = new HashMap<String, Object>(5, 1.0f);
args.put("activeTable", activeTable);
args.put("newRecords", newRecords);
args.put("logger", changeLog);
args.put("mode", mode.toString());
args.put("offsetSecs", offsetSecs);
MergeResult result = null;
try {
try {
python = new PythonScript(filePath, PyUtil.buildJepIncludePath(
pythonPath, vtecPath),
python = new PythonScript(filePath, includePath,
ActiveTable.class.getClassLoader());
try {
result = (MergeResult) python

View file

@ -17,19 +17,39 @@
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
#
# Code mostly separated from legacy VTECDecoder.py
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/11/13 #2083 randerso Log active table changes, save backups
#
import time
import copy
import os
import siteConfig
import VTECTableUtil, VTECTableSqueeze, VTECPartners
import LogStream, ActiveTableVtec, ActiveTableRecord
from java.util import ArrayList
from com.raytheon.uf.common.localization import PathManagerFactory
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationLevel as LocalizationLevel
class ActiveTable(VTECTableUtil.VTECTableUtil):
def __init__(self):
def __init__(self, activeTableMode):
self._time = time.time()
# create a dummy name to simplify the file access code in VTECTableUtil
pathMgr = PathManagerFactory.getPathManager()
edexSiteCx = pathMgr.getContext(LocalizationType.EDEX_STATIC, LocalizationLevel.SITE)
filePath = pathMgr.getFile(edexSiteCx,"vtec").getPath()
VTECTableUtil.VTECTableUtil.__init__(self, os.path.join(filePath, activeTableMode + ".tbl"))
def updateActiveTable(self, activeTable, newRecords, offsetSecs=0):
#merges the previous active table and new records into a new table.
#Returns:
@ -228,27 +248,63 @@ class ActiveTable(VTECTableUtil.VTECTableUtil):
return outTable, purgedRecords, changes, changedFlag
def mergeFromJava(activeTable, newRecords, offsetSecs=0):
def mergeFromJava(activeTable, newRecords, logger, mode, offsetSecs=0):
pyActive = []
szActive = activeTable.size()
for i in range(szActive):
pyActive.append(ActiveTableRecord.ActiveTableRecord(activeTable.get(i)))
siteId = siteConfig.GFESUITE_SITEID
decoderSites = VTECPartners.VTEC_DECODER_SITES
decoderSites.append(VTECPartners.get4ID(siteId))
decoderSites.append(VTECPartners.VTEC_SPC_SITE)
decoderSites.append(VTECPartners.VTEC_TPC_SITE)
backup = False
pyNew = []
szNew = newRecords.size()
for i in range(szNew):
pyNew.append(ActiveTableRecord.ActiveTableRecord(newRecords.get(i)))
rec = ActiveTableRecord.ActiveTableRecord(newRecords.get(i))
if rec['officeid'] in decoderSites:
backup = True
pyNew.append(rec)
active = ActiveTable()
active = ActiveTable(mode)
updatedTable, purgedTable, changes, changedFlag = active.activeTableMerge(pyActive, pyNew, offsetSecs)
if backup:
oldActiveTable = active._convertTableToPurePython(pyActive, siteId)
active.saveOldActiveTable(oldActiveTable)
pTime = getattr(VTECPartners, "VTEC_BACKUP_TABLE_PURGE_TIME",168)
active.purgeOldSavedTables(pTime)
updatedTable, purgeRecords, changes, changedFlag = active.activeTableMerge(pyActive, pyNew, offsetSecs)
logger.info("Updated " + mode + " Active Table: purged\n" +
active.printActiveTable(purgeRecords, combine=1))
replaced = []
decoded = []
other = []
for r in updatedTable:
if r['state'] == "Replaced":
replaced.append(r)
elif r['state'] == "Decoded":
decoded.append(r)
else:
other.append(r)
logger.info("Updated " + mode + " Active Table: replaced\n" +
active.printActiveTable(replaced, combine=1))
logger.info("Updated " + mode + " Active Table: decoded\n" +
active.printActiveTable(decoded, combine=1))
updatedList = ArrayList()
for x in updatedTable:
updatedList.add(x.javaRecord())
purgedList = ArrayList()
for x in purgedTable:
for x in purgeRecords:
purgedList.add(x.javaRecord())
changeList = ArrayList()

View file

@ -31,6 +31,7 @@
# ------------ ---------- ----------- --------------------------
# 01/25/13 1447 dgilling Initial Creation.
# 03/19/13 1447 dgilling Merge A1 DR 21434.
# 06/11/13 #2083 randerso Move backups to edex_static
#
#
@ -75,10 +76,10 @@ class MergeVTEC(VTECTableUtil.VTECTableUtil):
# create a dummy name to simplify the file access code in VTECTableUtil
pathMgr = PathManagerFactory.getPathManager()
commonSiteCx = pathMgr.getContextForSite(
LocalizationType.COMMON_STATIC, siteConfig.GFESUITE_SITEID)
filePath = pathMgr.getFile(commonSiteCx,"vtec").getPath()
self._activeTableFilename = os.path.join(filePath, activeTableMode + ".tbl")
edexSiteCx = pathMgr.getContextForSite(
LocalizationType.EDEX_STATIC, siteConfig.GFESUITE_SITEID)
filePath = pathMgr.getFile(edexSiteCx,"vtec").getPath()
fileName = os.path.join(filePath, activeTableMode + ".tbl")
# to ensure time calls are based on Zulu
os.environ['TZ'] = "GMT0"
@ -86,7 +87,7 @@ class MergeVTEC(VTECTableUtil.VTECTableUtil):
self._makeBackups = makeBackups
VTECTableUtil.VTECTableUtil.__init__(self, self._activeTableFilename)
VTECTableUtil.VTECTableUtil.__init__(self, fileName)
# get the SPC site id from the configuration file
self._spcSite = getattr(VTECPartners, "VTEC_SPC_SITE", "KWNS")

View file

@ -17,6 +17,15 @@
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
#
# VTEC Partner configuration
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/11/13 #2083 randerso Fixed getISCSites to look in configured
#VTEC_Partners.py - configuration file to control filtering and merging
#of VTEC active table.
@ -228,9 +237,9 @@ def getISCSites():
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationLevel as LocalizationLevel
pathMgr = PathManagerFactory.getPathManager()
commonStaticSite = pathMgr.getContext(LocalizationType.COMMON_STATIC, LocalizationLevel.SITE)
commonStaticSite.setContextName(siteConfig.GFESUITE_SITEID)
eaDir = pathMgr.getFile(commonStaticSite, "gfe/editAreas").getCanonicalPath()
commonStaticCfg = pathMgr.getContext(LocalizationType.COMMON_STATIC, LocalizationLevel.CONFIGURED)
commonStaticCfg.setContextName(siteConfig.GFESUITE_SITEID)
eaDir = pathMgr.getFile(commonStaticCfg, "gfe/editAreas").getCanonicalPath()
files = glob.glob(eaDir + "/ISC_???.xml")
sites = []
WFOSites = BackupDict.keys()

View file

@ -1,4 +0,0 @@
# scan interval of stats table in minutes
stats.scanInterval=15
# bucket interval or period of when to aggregate in minutes
stats.period=5

View file

@ -1,51 +0,0 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="statsPurge"
class="com.raytheon.uf.edex.stats.StatsPurge"
depends-on="statsRegister"/>
<bean id="aggregateManager" class="com.raytheon.uf.edex.stats.AggregateManager">
<constructor-arg value="${stats.period}"/>
<property name="aggregateDao" ref="aggregateRecordDao"/>
<property name="statsRecordDao" ref="statsDao"/>
<property name="jaxbManager" ref="statsGroupingColumnJaxbManager"/>
</bean>
<bean id="edexStatsRegistered" factory-bean="clusteredCamelContextMgr"
factory-method="register" depends-on="persistCamelRegistered">
<constructor-arg ref="edexStats-camel"/>
</bean>
<bean id="aggregateRecordDao" class="com.raytheon.uf.edex.stats.dao.AggregateRecordDao">
<property name="sessionFactory" ref="metadataSessionFactory"/>
</bean>
<bean id="statsGroupingColumnJaxbManager" class="com.raytheon.uf.common.serialization.JAXBManager">
<constructor-arg value="com.raytheon.uf.common.stats.StatsGroupingColumn"/>
</bean>
<camelContext id="edexStats-camel"
xmlns="http://camel.apache.org/schema/spring"
errorHandlerRef="errorHandler"
autoStartup="false">
<endpoint id="statsScanTimer" uri="timer://scanStats?period=${stats.scanInterval}m"/>
<route id="statsTableScan">
<from ref="statsScanTimer" />
<doTry>
<bean ref="statsPurge" method="purgeAggregates"/>
<bean ref="aggregateManager" method="scan"/>
<doCatch>
<exception>java.lang.Throwable</exception>
<to uri="log:stats?level=ERROR&amp;showBody=false&amp;showCaughtException=true&amp;showStackTrace=true"/>
</doCatch>
</doTry>
</route>
</camelContext>
</beans>

View file

@ -1,18 +0,0 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="statsGraphDataHandler" class="com.raytheon.uf.edex.stats.handler.GraphDataHandler" >
<property name="aggregateRecordDao" ref="graphDataHandlerAggregateRecordDao" />
</bean>
<bean factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.stats.GraphDataRequest" />
<constructor-arg ref="statsGraphDataHandler" />
</bean>
<bean id="graphDataHandlerAggregateRecordDao" class="com.raytheon.uf.edex.stats.dao.AggregateRecordDao">
<property name="sessionFactory" ref="metadataSessionFactory" />
</bean>
</beans>

View file

@ -1,4 +0,0 @@
# scan interval of stats table in minutes
stats.scanInterval=2
# bucket interval or period of when to aggregate in minutes
stats.period=5

View file

@ -1,276 +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.edex.stats.util;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.xml.bind.JAXBException;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.stats.AggregateRecord;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.TimeRange;
/**
* Archives the data in the aggregate_bucket table to an xml file.
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 21, 2012 jsanchez Initial creation.
* Nov 09, 2012 dhladky Changed to CSV output
* Jan 24, 2013 1357 mpduff Fix comma output and paths.
*
* </pre>
*
* @author jsanchez
*
*/
public class Archiver {
private class StatisticsKey {
public String eventType;
public String grouping;
public TimeRange timeRange;
@Override
public boolean equals(Object o) {
if (o != null && o instanceof StatisticsKey) {
StatisticsKey other = (StatisticsKey) o;
return eventType.equals(other.eventType)
&& timeRange.getStart().equals(
other.timeRange.getStart())
&& timeRange.getEnd().equals(other.timeRange.getEnd());
}
return false;
}
@Override
public int hashCode() {
return 1;
}
}
private static final String COMMA = ",";
private static final Pattern NLPattern = Pattern.compile("[\\n\\r]+");
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(Archiver.class);
private final IPathManager pm = PathManagerFactory.getPathManager();
private final LocalizationContext context = pm.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.SITE);
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String FILE_DATE_FORMAT = "yyyyMMdd_HHmm";
private static final Pattern PERIOD_PATTERN = Pattern.compile("\\.");
public Archiver() {
}
/**
* Creates a filename in the format /stats/aggregates/group...
* /eventType.start-end.dat
*
* @param items
* @return
*/
private String createFilename(TimeRange tr, String eventType) {
SimpleDateFormat fileDateFormatter = new SimpleDateFormat(
FILE_DATE_FORMAT);
StringBuilder sb = new StringBuilder("stats/aggregates");
String[] chunks = PERIOD_PATTERN.split(eventType);
sb.append("/");
sb.append(chunks[chunks.length - 1]);
sb.append(".");
sb.append(fileDateFormatter.format(tr.getStart()));
sb.append("-");
sb.append(fileDateFormatter.format(tr.getEnd()));
sb.append(".csv");
return sb.toString();
}
/**
* Used for outputting the stats as CSV
*
* @return
*/
private String getCSVOutput(AggregateRecord agrec,
SimpleDateFormat dateFormat) {
StringBuilder sb = new StringBuilder();
String eventType = agrec.getEventType();
Calendar startDate = agrec.getStartDate();
Calendar endDate = agrec.getEndDate();
String grouping = agrec.getGrouping();
String field = agrec.getField();
double max = agrec.getMax();
double min = agrec.getMin();
double sum = agrec.getSum();
double count = agrec.getCount();
if (eventType != null) {
sb.append(eventType);
}
sb.append(COMMA);
if (startDate != null) {
sb.append(dateFormat.format(startDate.getTime()));
}
sb.append(COMMA);
if (endDate != null) {
sb.append(dateFormat.format(endDate.getTime()));
}
sb.append(COMMA);
if (grouping != null) {
sb.append(NLPattern.matcher(grouping).replaceAll(""));
}
sb.append(COMMA);
if (field != null) {
sb.append(field);
}
sb.append(COMMA);
sb.append(max).append(COMMA);
sb.append(min).append(COMMA);
sb.append(sum).append(COMMA);
sb.append(count);
return sb.toString();
}
/**
* Writes the aggregate records to disk.
*
* @param aggregateRecords
* @throws JAXBException
*/
public void writeToDisk(AggregateRecord[] aggregateRecords) {
Map<StatisticsKey, List<AggregateRecord>> statisticsMap = new HashMap<StatisticsKey, List<AggregateRecord>>();
for (AggregateRecord record : aggregateRecords) {
StatisticsKey key = new StatisticsKey();
key.eventType = record.getEventType();
key.grouping = record.getGrouping();
key.timeRange = new TimeRange(record.getStartDate(),
record.getEndDate());
List<AggregateRecord> aggregateRecordList = statisticsMap.get(key);
if (aggregateRecordList == null) {
aggregateRecordList = new ArrayList<AggregateRecord>();
statisticsMap.put(key, aggregateRecordList);
}
aggregateRecordList.add(record);
}
for (StatisticsKey key : statisticsMap.keySet()) {
String eventType = key.eventType;
List<AggregateRecord> records = statisticsMap.get(key);
String filename = createFilename(key.timeRange, eventType);
try {
writeToFile(filename, records);
} catch (JAXBException e) {
statusHandler.error("Unable to write statistics file "
+ filename, e);
}
}
}
/**
* Writes the statistics xml to disk.
*
* @param statistics
* @throws JAXBException
*/
public void writeToFile(String filename, List<AggregateRecord> records)
throws JAXBException {
BufferedWriter bw = null;
SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
LocalizationFile siteLocalization = pm.getLocalizationFile(context,
filename);
String outputFilePath = siteLocalization.getFile().getAbsolutePath();
// pre-create directories if necessary
siteLocalization.getFile().getParentFile().mkdirs();
// Write this to output CSV
try {
bw = new BufferedWriter(new FileWriter(outputFilePath));
if (bw != null) {
for (AggregateRecord agrec : records) {
bw.write(getCSVOutput(agrec, dateFormatter));
bw.newLine();
}
}
} catch (IOException e) {
statusHandler.handle(Priority.ERROR, "Failed to write File: "
+ outputFilePath, e);
} finally {
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
statusHandler.handle(Priority.PROBLEM,
"failed to close CSV output file stream. "
+ filename, e);
}
}
}
}
}

View file

@ -542,6 +542,9 @@ fi
# grab screen shot, spawns background process for each screen
grabScreenShot
# ls users home directory to check nas performance
/usr/bin/time -p ls -la ~ > ${dataPath}/nas_check_ls_home.txt 2>&1 &
# get reason for running capture
if [ "$reason" != "n" ]; then
reasonForCapture &

View file

@ -0,0 +1,51 @@
#!/bin/bash
##
# 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.
##
##############################################################################
# This script allows users to extract PGEN products from EDEX.
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/08/12 #674 dgilling Initial Creation.
##############################################################################
# this allows you to run this script from outside of ./bin
path_to_script=`readlink -f $0`
RUN_FROM_DIR=`dirname $path_to_script`
BASE_AWIPS_DIR=`dirname $RUN_FROM_DIR`
# get the base environment
source ${RUN_FROM_DIR}/setup.env
# setup the environment needed to run the the Python
export LD_LIBRARY_PATH=${BASE_AWIPS_DIR}/src/lib:${PYTHON_INSTALL}/lib
export PYTHONPATH=${RUN_FROM_DIR}/src:$PYTHONPATH
# execute the ifpInit Python module
_PYTHON="${PYTHON_INSTALL}/bin/python"
_MODULE="${RUN_FROM_DIR}/src/pgen/retrieveActivity.py"
# quoting of '$@' is used to prevent command line interpretation
#$_PYTHON $_MODULE -h ${DEFAULT_HOST} -p ${DEFAULT_PORT} "$@"
$_PYTHON $_MODULE "$@"

View file

@ -0,0 +1,50 @@
import os
from ufpy import ThriftClient
from dynamicserialize.dstypes.com.raytheon.uf.common.datastorage.records import StringDataRecord
from dynamicserialize.dstypes.com.raytheon.uf.common.datastorage.records import ByteDataRecord
from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.pgen.request import RetrieveAllProductsRequest
class ProductRetriever:
""" Retrieves all PGEN products for a given Activity (dataURI) and writes them to separate files."""
def __init__(self,dataURI,label):
self.dataURI = dataURI
self.label = label
self.outdir = os.getcwd()
self.host = os.getenv("DEFAULT_HOST", "localhost")
self.port = os.getenv("DEFAULT_PORT", "9581")
self.client = ThriftClient.ThriftClient(self.host, self.port)
def setOutputDir(self, outdir):
self.outdir = outdir
def _writeout(self,filename,bytes):
outname = self.outdir + str(os.sep) + filename
f = open(outname,"wb")
f.write(bytes)
f.close()
def getProducts(self):
""" Sends ThriftClient request and writes out received files."""
req = RetrieveAllProductsRequest()
req.setDataURI(self.dataURI)
resp = self.client.sendRequest(req)
#os.mkdir(self.outdir)
for item in resp:
if item.getName() == "ActivityXML":
if self.label.endswith(".xml"):
filename = self.label
else:
filename = self.label + ".xml"
else:
filename = item.getName()
print "Extracting... " + filename
if isinstance(item, StringDataRecord):
self._writeout(filename,item.getStringData()[0])
elif isinstance(item, ByteDataRecord):
self._writeout(filename,item.getByteData())
return resp

View file

@ -0,0 +1,28 @@
import os
from ufpy import ThriftClient
#from dynamicserialize.dstypes.com.raytheon.uf.common.datastorage.records import ByteDataRecord
from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.pgen.request import StoreActivityRequest
from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.pgen import ResponseMessageValidate
class ProductStorer:
""" Store a PGEN Activity (XML) to EDEX."""
def __init__(self, activityInfo, activityXML):
self.activityInfo = activityInfo
self.activityXML = activityXML
self.host = os.getenv("DEFAULT_HOST", "localhost")
self.port = os.getenv("DEFAULT_PORT", "9581")
self.client = ThriftClient.ThriftClient(self.host, self.port)
def storeActivity(self):
""" Sends ThriftClient request to store Activity."""
req = StoreActivityRequest()
req.setActivityInfo(self.activityInfo)
req.setActivityXML(self.activityXML)
resp = self.client.sendRequest(req)
if resp.getResult:
return resp.getDataURI()
else:
return None

View file

@ -0,0 +1,286 @@
#!/usr/bin/env python
##
# This script is used to extract PGEN products from EDEX.
# It can be run in batch mode by specifying the "-l" and "-t" options on the
# command line. Optionally, users can run it in interactive mode by invoking it
# with no argument.
#
# Users can override the default EDEX server and port name by specifying them
# in the $DEFAULT_HOST and $DEFAULT_PORT shell environment variables.
#
##
import os
import logging
import xml.etree.ElementTree as ET
from Tkinter import *
from ufpy import UsageArgumentParser
import lib.CommHandler as CH
import ProductRetriever
logger = None
def __initLogger():
global logger
logger = logging.getLogger("retrieveActivity")
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# Uncomment line below to enable debug-level logging
#ch.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S")
ch.setFormatter(formatter)
logger.addHandler(ch)
def __parseCommandLine():
parser = UsageArgumentParser.UsageArgumentParser(prog='retrieveActivity',description="Retrieve PGEN Activities from EDEX. When invoked without any arguments, retrieveActivity is run in interactive mode.")
bgroup = parser.add_argument_group(title='batch',description='For running in scripts and/or batch mode.')
bgroup.add_argument("-l", action="store", dest="label",
help="Activity Label being requested",
required=False, metavar="label")
bgroup.add_argument("-t", action="store", dest="type",
help="Activity Type being requested",
required=False, metavar="type")
options = parser.parse_args()
options.interactive = False
if options.label == None and options.type == None :
options.interactive = True
elif options.label == None or options.type == None :
print "Must enter values for both arguments -l and -t"
exit(0)
logger.debug("Command-line arguments: " + str(options))
return options
#
# This method sends a CatalogQuery request to the EDEX uEngine
# for the dataURI associated with the given activity type and label
#
def __getDataURI( type, label):
script='''import CatalogQuery
query = CatalogQuery.CatalogQuery("pgen")
query.addConstraint("activityType","{0}","=")
query.addConstraint("activityLabel","{1}","=")
query.addReturnedField("dataURI")
query.addReturnedField("dataTime.refTime")
return query.execute()'''.format(type,label)
service = '/services/pyproductjaxb'
host = os.getenv("DEFAULT_HOST", "localhost")
port = os.getenv("DEFAULT_PORT", "9581")
connection=str(host+":"+port)
ch = CH.CommHandler(connection,service)
ch.process(script)
if not ch.isGoodStatus():
print ch.formatResponse()
exit(1)
logger.debug( ch.getContents() )
return __parseResponse( ch.getContents() )
#
# Parses the XML response from the uEngine and extracts
# the value for the dataURI field. If multiple are returned, the last
# one is used.
#
def __parseResponse(xml):
tree = ET.fromstring(xml)
for attr in tree.iter('attributes'):
if attr.attrib['field'] == 'dataURI':
duri = attr.attrib['value']
return duri
def main():
__initLogger()
logger.info("Starting retrieveActivity.")
options = __parseCommandLine()
if options.interactive :
# Launch interactive GUI
logger.info("Running in interactive mode.")
root = Tk()
root.title("Retrieve Activity")
app = RetrieveGui(master=root)
app.mainloop()
root.destroy()
else:
# Retrieve products for given activity type and label
logger.info("looking for Product: " + options.type + " - " + options.label)
dataURI = __getDataURI(options.type, options.label)
logger.debug("Found dataURI = " + dataURI)
pr = ProductRetriever.ProductRetriever(dataURI, options.label)
outdir = os.getcwd() + str(os.sep) + options.type + str(os.sep) + options.label + str(os.sep)
#pr.setOutputDir(outdir)
pr.getProducts()
#print "Products were written to directory: " + outdir
logger.info("retrieveActivity is complete.")
class RetrieveGui(Frame):
""" Interactive GUI for PGEN product retrieval """
def __init__(self, master=None):
""" Initialize Frame and create widgets """
Frame.__init__(self, master)
self.pack()
self.createWidgets()
def getProducts(self):
# if an activity type and label have been selected, get products and write them out.
if len(self.typeList.curselection()) != 0 and len(self.nameList.curselection()) != 0:
type = self.typeList.get(self.typeList.curselection())
label = self.nameList.get(self.nameList.curselection())
labelindex = int(self.nameList.curselection()[0])
dataURI = self.activityMap[type][labelindex]['dataURI']
pr = ProductRetriever.ProductRetriever(dataURI, label)
#outdir = os.getcwd() + str(os.sep) + options.type + str(os.sep) + options.label + str(os.sep)
#pr.setOutputDir(outdir)
pr.getProducts()
def createWidgets(self):
activityType = Label(self)
activityType["text"] = "Activity Type"
activityType.pack()
# Activity Type list section
frame = Frame(self)
vscrollbar = Scrollbar(frame, orient=VERTICAL)
hscrollbar = Scrollbar(frame, orient=HORIZONTAL)
self.typeList = Listbox(frame,selectmode=BROWSE,yscrollcommand=vscrollbar.set,xscrollcommand=hscrollbar.set,exportselection=0,width=50,height=15,bg="white")
vscrollbar.config(command=self.typeList.yview)
hscrollbar.config(command=self.typeList.xview)
vscrollbar.pack(side=RIGHT, fill=Y)
hscrollbar.pack(side=BOTTOM, fill=BOTH)
self.typeList.pack(side=LEFT,fill=BOTH,expand=1)
frame.pack()
self.typeList.insert(END,"Loading...") # Temporary item while data are being requested from EDEX
activityLabel = Label(self)
activityLabel["text"] = "Activity Label"
activityLabel.pack()
# Activity Label list section
frame2 = Frame(self)
vscrollbar2 = Scrollbar(frame2, orient=VERTICAL)
hscrollbar2 = Scrollbar(frame2, orient=HORIZONTAL)
self.nameList = Listbox(frame2,yscrollcommand=vscrollbar2.set,xscrollcommand=hscrollbar2.set,exportselection=0, width=50,height=15,bg="white")
vscrollbar2.config(command=self.nameList.yview)
hscrollbar2.config(command=self.nameList.xview)
vscrollbar2.pack(side=RIGHT, fill=Y)
hscrollbar2.pack(side=BOTTOM, fill=BOTH)
self.nameList.pack()
frame2.pack()
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
self.QUIT.pack({"side": "right"})
self.retrieve = Button(self)
self.retrieve["text"] = "Retrieve",
self.retrieve["command"] = self.getProducts
self.retrieve.pack({"side": "left"})
#
# Get all Activity Types and Labels from EDEX for use in selection ListBoxes.
# Insert list of Types in Type Listbox
#
self.activityMap = self.__getActivityMap()
self.typeList.delete(0,END)
for key in self.activityMap.iterkeys():
self.typeList.insert(END,key)
self.current = None
self.poll()
#
# Continuously polls for user selection changes in the Activity Type ListBox
#
def poll(self):
now = self.typeList.curselection()
if len(now) == 0:
self.after(250, self.poll)
return
if now != self.current:
self.typeList_has_changed(now)
self.current = now
self.after(250, self.poll)
#
# Replace the list of Activity Labels in the Label Listbox
# with those associated with the current Activity Type selection
#
def typeList_has_changed(self, index):
self.nameList.delete(0,END)
for label in self.activityMap[ self.typeList.get(index) ]:
#print label
self.nameList.insert(END, label['activityLabel'])
#
# Sends a CatalogQuery to the EDEX uEngine to get a list of
# PGEN Activity TYpes, Labels, and associated dataURIs
# in the pgen database tables.
#
def __getActivityMap(self):
script='''import CatalogQuery
query = CatalogQuery.CatalogQuery("pgen")
query.addReturnedField("activityType")
query.addReturnedField("activityLabel")
query.addReturnedField("dataURI")
return query.execute()'''
service = '/services/pyproductjaxb'
host = os.getenv("DEFAULT_HOST", "localhost")
port = os.getenv("DEFAULT_PORT", "9581")
connection=str(host+":"+port)
ch = CH.CommHandler(connection,service)
ch.process(script)
if not ch.isGoodStatus():
print ch.formatResponse()
exit(1)
logger.debug( ch.getContents() )
return self.__generateMap( ch.getContents() )
#
# Generates a map of activity types, label, and dataURIs from
# the XML returned from EDEX uEngine for use in the activity type and label
# Listboxes.
#
# The map is a dictionary (dict) of Activity Types whose values are a list of dicts
# which have keys "activityType", "activityLabel", and "dataURI".
#
def __generateMap(self, xml):
aMap = dict()
tree = ET.fromstring(xml)
for item in tree.iter('items'):
#print item.attrib['key']
record = dict()
for attr in item.iter('attributes'):
record.update( {attr.attrib['field'] : attr.attrib['value'] } )
#print record
atype = record['activityType']
if aMap.has_key(atype):
aMap[atype].append(record)
else:
aMap.update( {atype: [record]} )
return aMap
if __name__ == '__main__':
main()

View file

@ -0,0 +1,113 @@
##
# This script is used to store a PGEN Activity to EDEX.
#
# Users can override the default EDEX server and port name by specifying them
# in the $DEFAULT_HOST and $DEFAULT_PORT shell environment variables.
#
##
import io
import logging
import xml.etree.ElementTree as ET
from ufpy import UsageArgumentParser
from dynamicserialize.dstypes.gov.noaa.nws.ncep.common.dataplugin.pgen import ActivityInfo
import ProductStorer
logger = None
def __initLogger():
global logger
logger = logging.getLogger("storeActivity")
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
# Uncomment line below to enable debug-level logging
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S")
ch.setFormatter(formatter)
logger.addHandler(ch)
def __parseCommandLine():
parser = UsageArgumentParser.UsageArgumentParser(prog='storeActivity',description="Store a PGEN Activity to EDEX.")
#bgroup = parser.add_argument_group(title='batch',description='For running in scripts and/or batch mode.')
#parser.add_argument("-i", action="store", dest="infoFile",
# help="Activity Information used to store Activity",
# required=True, metavar="infoFile")
parser.add_argument("-t", action="store", dest="activityType",
help="Activity Type",
required=False, metavar="type")
parser.add_argument("-st", action="store", dest="activitySubtype",
help="Activity Subtype",
required=False, metavar="subtype")
parser.add_argument("-n", action="store", dest="activityName",
help="Activity Name",
required=False, metavar="name")
parser.add_argument("-s", action="store", dest="site",
help="site identifier",
required=False, metavar="site")
parser.add_argument("-f", action="store", dest="forecaster",
help="forecaster",
required=False, metavar="forecaster")
parser.add_argument("filename",
help="File containing XML Activity to be stored",
metavar="filename")
options = parser.parse_args()
logger.debug("Command-line arguments: " + str(options))
return options
def __getActivityInfo(options):
ainfo = ActivityInfo()
ainfo.setActivityLabel(options.filename)
ainfo.setActivityName(options.activityName)
ainfo.setActivityType(options.activityType)
ainfo.setActivitySubtype(options.activitySubtype)
ainfo.setForecaster(options.forecaster)
ainfo.setSite(options.site)
return ainfo
# Update Product tag attributes with options given on command line
def __updateXML(xml, options):
tree = ET.fromstring(xml)
product = tree.find('Product')
if options.activityName != None:
product.attrib['name'] = options.activityName
if options.activityType != None:
product.attrib['type'] = options.activityType
if options.filename != None:
product.attrib['outputFile'] = options.filename
if options.forecaster != None:
product.attrib['forecaster'] = options.forecaster
if options.site != None:
product.attrib['center'] = options.site
return ET.tostring(tree)
def main():
__initLogger()
logger.info("Starting retrieveActivity.")
options = __parseCommandLine()
# read in XML from input file
actfile = io.open(options.filename, 'rb')
activityXML = actfile.read()
actfile.close()
# generate an activityInfo object and update XML with options
# from command line
actinfo = __getActivityInfo(options)
activityXML = __updateXML(activityXML, options)
# Store Activity to EDEX
ps = ProductStorer.ProductStorer(actinfo, activityXML)
dataURI = ps.storeActivity()
logger.info("Activity stored with dataURI: " + dataURI)
logger.info("storeActivity is complete.")
if __name__ == '__main__':
main()

View file

@ -7,6 +7,7 @@
# ------------ ---------- ----------- --------------------------
# 04/06/2012 10388 D. Friedman Initial version
# 10/09/12 DR 13901 D. Friedman Limit execution time
# 06/13/2013 DR 16242 D. Friedman Add Qpid authentication info
##############################################################################
import getopt
@ -23,6 +24,8 @@ from qpid.datatypes import Message, uuid4
DESTINATION = 'amq.topic'
TOPIC_NAME = 'mhs.ackmgr'
QPID_USERNAME = 'guest'
QPID_PASSWORD = 'guest'
class MhsAckNotification:
def __init__(self):
@ -38,7 +41,7 @@ def remove_file(*parts):
def get_qpid_connection(broker_addr):
try:
socket = connect(broker_addr, 5672)
connection = Connection (sock=socket)
connection = Connection (sock=socket, username=QPID_USERNAME, password=QPID_PASSWORD)
connection.start()
return connection
except:

View file

@ -0,0 +1,51 @@
#!/bin/bash
##
# 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.
##
##############################################################################
# This script allows users to extract PGEN products from EDEX.
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/08/12 #674 dgilling Initial Creation.
##############################################################################
# this allows you to run this script from outside of ./bin
path_to_script=`readlink -f $0`
RUN_FROM_DIR=`dirname $path_to_script`
BASE_AWIPS_DIR=`dirname $RUN_FROM_DIR`
# get the base environment
source ${RUN_FROM_DIR}/setup.env
# setup the environment needed to run the the Python
export LD_LIBRARY_PATH=${BASE_AWIPS_DIR}/src/lib:${PYTHON_INSTALL}/lib
export PYTHONPATH=${RUN_FROM_DIR}/src:$PYTHONPATH
# execute the ifpInit Python module
_PYTHON="${PYTHON_INSTALL}/bin/python"
_MODULE="${RUN_FROM_DIR}/src/pgen/storeActivity.py"
# quoting of '$@' is used to prevent command line interpretation
#$_PYTHON $_MODULE -h ${DEFAULT_HOST} -p ${DEFAULT_PORT} "$@"
$_PYTHON $_MODULE "$@"

View file

@ -33,7 +33,7 @@ import os
import logging
from ufpy import ThriftClient
from ufpy.UsageOptionParser import UsageOptionParser
from ufpy import UsageArgumentParser
#
# Provides a command-line utility to break all locks.
@ -44,10 +44,17 @@ from ufpy.UsageOptionParser import UsageOptionParser
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 04/05/2011 8826 rferrel Initial Creation.
# 06/12/2013 2099 dgilling Code cleanup, improve logging.
#
#
#
logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s",
datefmt="%H:%M:%S",
level=logging.INFO)
log = logging.getLogger('ifpBreakAllLocks')
def __WsId() :
return WsId(progName="ifpBreakAllLocks")
@ -71,13 +78,10 @@ def breakAllLocksGRIDRequest(officialDBs, lockTables, databaseIDs, allLocks):
if lt.getParmId().getDbId().getFormat() == "GRID":
locks = lt.getLocks()
for lock in locks:
tr = TimeRange()
tr.setStart(lock.getStartTime()/1000.0)
tr.setEnd(lock.getEndTime()/1000.0)
logInfo('Lock: %s %s' % (lt.getParmId(), tr))
log.info('Lock: {} {} {}'.format(lt.getParmId(), lock.getTimeRange(), lock.getWsId().toPrettyString()))
lr = LockRequest()
lr.setParmId(lt.getParmId())
lr.setTimeRange(tr)
lr.setTimeRange(lock.getTimeRange())
lr.setMode("BREAK_LOCK")
if len(req) == 0:
siteID = lt.getParmId().getDbId().getSiteId()
@ -90,147 +94,53 @@ def breakAllLocksGRIDRequest(officialDBs, lockTables, databaseIDs, allLocks):
lockChangeRequest.setSiteID(siteID)
lockChangeRequest.setWorkstationID(__WsId())
return lockChangeRequest
def __initLogger():
logger = logging.getLogger("ifpBreakAllLocks.py")
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S")
ch.setFormatter(formatter)
logger.addHandler(ch)
def getActiveSites(thriftClient):
sites = thriftClient.sendRequest(GetActiveSitesRequest())
return sites
def logInfo(msg):
logging.getLogger("ifpBreakAllLocks.py").info(msg)
def logError(msg):
logging.getLogger("ifpBreakAllLocks.py").error(msg)
def validateSiteId(siteId, thriftClient):
try:
sites = thriftClient.sendRequest(GetActiveSitesRequest())
except Exception, e:
logError("Unable to validate siteId: \n %s" % str(e))
sys.exit(1)
if not siteId in sites:
logError('Invalid or not installed siteID: "%s"' % siteId)
sys.exit(1)
def findSiteID(thriftClient):
try:
sites = thriftClient.sendRequest(GetActiveSitesRequest())
except Exception, e:
logError("Unable to obtain siteId: \n %s" % str(e))
sys.exit(1)
if len(sites) > 1 :
s = []
while len(sites) > 0 : s.append(sites.pop())
logError("Must use the -s option to specify one of the following sites: %s " % ", ".join(s))
sys.exit(1)
elif len(sites) == 0:
logError("No sites configured")
sys.exit(1)
return sites.pop()
def main():
(options, args) = validateArgs()
__initLogger()
logInfo('Break All Locks starting')
try:
thriftClient = ThriftClient.ThriftClient(options.host, options.port, "/services")
siteID = options.siteID
if siteID:
validateSiteId(options.siteID, thriftClient)
else:
siteID = findSiteID(thriftClient)
officialDbNamesRequest = getOfficialDbNamesRequest(siteID)
officialDbNameResponse = thriftClient.sendRequest(officialDbNamesRequest)
lockTablesRequest = getLockTablesRequest(siteID)
lockTableResponse = thriftClient.sendRequest(lockTablesRequest)
except Exception, e:
logError("Unhandled exception thrown during break all locks: \n %s" % str(e))
sys.exit(1)
if (not officialDbNameResponse.isOkay()):
logError("Errors occurred during break all locks: ", officialDbNameResponse.message())
sys.exit(1)
officialDBs = officialDbNameResponse.getPayload()
if (not lockTableResponse.isOkay()):
logError("Errors occurred during break all locks: ", lockTableResponse.message())
sys.exit(1)
lockTables = lockTableResponse.getPayload()
breakRequest = breakAllLocksGRIDRequest(officialDBs, lockTables, options.databaseIDs, options.allLocks)
if not breakRequest:
logInfo('No locks found')
else :
try :
breakResponse = thriftClient.sendRequest(breakRequest)
except Exception, e:
import traceback
logError("Unhandled exception thrown during break all locks: \n%s" % str(e))
print traceback.print_exc(file=sys.stdout)
sys.exit(1)
if not breakResponse.isOkay():
logError('Unable to break all locks.')
sys.exit(1)
logInfo('Break All Locks Finished')
def validateArgs():
usage = """%prog -h hostname -p port -s siteID -a -d databaseID ...
\tEither -a or at least one -d is required"""
parser = UsageOptionParser(usage=usage, conflict_handler="resolve")
parser.add_option("-h", action="store", type="string", dest="host",
help="ifpServer host name",
metavar="hostname")
parser.add_option("-p", action="store", type="int", dest="port",
help="port number of the ifpServer",
parser = UsageArgumentParser.UsageArgumentParser(prog='ifpBreakAllLocks', conflict_handler="resolve")
parser.add_argument("-h", action="store", dest="host",
help="The host the ifpServer is running on",
metavar="host")
parser.add_argument("-p", action="store", type=int, dest="port",
help="The port number the server is using",
metavar="port")
parser.add_option("-s", action="store", type="string", dest="siteID",
parser.add_argument("-s", action="store", dest="siteID",
help="Site ID",
metavar="siteID")
parser.set_defaults(allLocks=False)
parser.add_option("-a", action="store_true", dest="allLocks",
help="Break all database identifier's locks.",
metavar="allLocks")
parser.add_option("-d", action="append", type="string", dest="databaseIDs",
help="database identifier",
metavar="databaseIDs")
(options, args) = parser.parse_args()
parser.add_argument("-a", action="store_true", dest="allLocks",
help="Break locks on all databases")
parser.add_argument("-d", action="append", dest="databaseIDs", default=[],
help="Break locks on specified database identifier",
metavar="databaseID")
options = parser.parse_args()
if options.host == None:
if "CDSHOST" in os.environ:
options.host = os.environ["CDSHOST"]
else:
parser.error("No server hostname defined.")
parser.error("Error: host is not specified.")
if options.port == None:
if "CDSPORT" in os.environ:
options.port = int(os.environ["CDSPORT"])
else:
parser.error("No server port defined.")
if (options.allLocks == False and (options.databaseIDs is None or len(options.databaseIDs) == 0)):
parser.error("Must have -a or at least one DatabaseID (-d) must be provided.")
msg = []
parser.error("Error: port is not specified.")
if options.allLocks == False and not options.databaseIDs:
parser.error("Error: either -a or -d are required.")
invalidDbIds = []
if not options.allLocks:
for db in options.databaseIDs:
if not DatabaseID(dbIdentifier=db).isValid():
msg.append('Invalid database identifier "%s"' % db)
if len(msg) > 0:
parser.error("\n".join(msg))
return (options, args)
invalidDbIds.append(db)
if invalidDbIds:
parser.error("Invalid DatabaseIDs specified: {}".format(invalidDbIds))
return options
def getLockTablesRequest(siteID):
req = GetLockTablesRequest()
req.setWorkstationID(__WsId())
req.setSiteID(siteID)
req.setRequests([LockTableRequest()])
@ -238,11 +148,70 @@ def getLockTablesRequest(siteID):
def getOfficialDbNamesRequest(siteID):
req = GetOfficialDbNameRequest()
req.setWorkstationID(__WsId())
req.setSiteID(siteID)
return req
def main():
log.info('Break All Locks starting')
options = validateArgs()
log.info('allLocks= {}, Ids= {}'.format(options.allLocks, options.databaseIDs))
thriftClient = ThriftClient.ThriftClient(options.host, options.port, "/services")
activeSites = []
try:
activeSites = getActiveSites(thriftClient)
except:
log.exception("Could not retrieve current active sites:")
sys.exit(1)
if options.siteID and options.siteID in activeSites:
siteID = options.siteID
elif not options.siteID and len(activeSites) == 1:
siteID = activeSites[0]
else:
if options.siteID and options.siteID not in activeSites:
log.error("Invalid site ID {} specified, only sites {} are valid".format(options.siteID, activeSites))
else:
log.error("Must use the -s option to specify one of the following sites {}".format(activeSites))
sys.exit(1)
try:
officialDbNamesRequest = getOfficialDbNamesRequest(siteID)
officialDbNameResponse = thriftClient.sendRequest(officialDbNamesRequest)
except:
log.exception("Unable to retrieve official databases:")
sys.exit(1)
if not officialDbNameResponse.isOkay():
log.error("Unable to retrieve official databases: ", officialDbNameResponse.message())
sys.exit(1)
officialDBs = officialDbNameResponse.getPayload()
try:
lockTablesRequest = getLockTablesRequest(siteID)
lockTableResponse = thriftClient.sendRequest(lockTablesRequest)
except:
log.exception("Unable to retrieve lock table:")
sys.exit(1)
if (not lockTableResponse.isOkay()):
log.error("Unable to retrieve lock table: ", lockTableResponse.message())
sys.exit(1)
lockTables = lockTableResponse.getPayload()
breakRequest = breakAllLocksGRIDRequest(officialDBs, lockTables, options.databaseIDs, options.allLocks)
if breakRequest:
try:
breakResponse = thriftClient.sendRequest(breakRequest)
except:
log.exception("Unhandled exception thrown during break all locks:")
sys.exit(1)
if not breakResponse.isOkay():
log.error('Unable to break all locks.')
sys.exit(1)
log.info('Break All Locks Finished')
if __name__ == '__main__':
main()

View file

@ -49,12 +49,8 @@
<pipeline>
<bean ref="stringToFile" />
<doTry>
<pipeline>
<!--
need to replace the method decode with decodeNtransMetafile
<bean ref="ntransDecoder" method="decode" /> -->
<bean ref="ntransDecoder" method="decodeNtransMetafile" />
<pipeline>
<bean ref="ntransDecoder" method="decode" />
<to uri="direct-vm:persistIndexAlert" />
</pipeline>
<doCatch>

View file

@ -37,10 +37,6 @@
<property name="contextPath" value="/purgeWeb"/>
<property name="war" value="file:///${edex.home}/webapps/purgeWeb"/>
</bean>
<bean class="org.eclipse.jetty.webapp.WebAppContext">
<property name="contextPath" value="/activemqAdmin"/>
<property name="war" value="file:///${edex.home}/webapps/admin"/>
</bean>
</list>
</property>
</bean>
@ -52,7 +48,7 @@
</property>
</bean>
<camelContext id="nceppurge-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<camelContext id="nceppurge-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler">
<endpoint id="nceppurgeHttp_from"
uri="jetty:http://0.0.0.0:${http.port}/services/purgePlugin" />

View file

@ -34,8 +34,9 @@
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 06/09/10 njensen Initial Creation.
#
#
# 06/12/13 #2099 dgilling Implement readObject() and
# writeObject().
#
#
from thrift.Thrift import TType
@ -87,7 +88,7 @@ pythonToThriftMap = {
primitiveSupport = (TType.BYTE, TType.I16, TType.I32, TType.I64, SelfDescribingBinaryProtocol.FLOAT)
class ThriftSerializationContext:
class ThriftSerializationContext(object):
def __init__(self, serializationManager, selfDescribingBinaryProtocol):
self.serializationManager = serializationManager
@ -409,5 +410,9 @@ class ThriftSerializationContext:
self.protocol.writeI32(len(floats))
self.protocol.writeF32List(floats)
def readObject(self):
return self.deserializeMessage()
def writeObject(self, obj):
self.serializeMessage(obj)

View file

@ -18,7 +18,6 @@
# further licensing information.
##
#
# Adapter for com.raytheon.uf.common.dataplugin.gfe.server.lock.LockTable
#
@ -28,7 +27,7 @@
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 04/22/13 rjpeter Initial Creation.
#
# 06/12/13 #2099 dgilling Use new Lock constructor.
#
#
@ -75,11 +74,10 @@ def deserialize(context):
numLocks = context.readI32()
locks = []
for x in xrange(numLocks):
lock = Lock()
lock.setParmId(parmId)
lock.setStartTime(context.readI64())
lock.setEndTime(context.readI64())
lock.setWsId(wsIds[context.readI32()])
startTime = context.readI64()
endTime = context.readI64()
wsId = wsIds[context.readI32()]
lock = Lock(parmId, wsId, startTime, endTime)
locks.append(lock)
lockTable = LockTable()

View file

@ -18,49 +18,53 @@
# further licensing information.
##
#
# File auto-generated against equivalent DynamicSerialize Java class
# Modified by njensen to add __repr__
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# xx/xx/xxxx xxxxxxx Initial Creation.
# xx/xx/xxxx xxxx njensen Implemented __repr__.
# 06/12/2013 2099 dgilling Make class immutable,
# add getTimeRange().
#
#
import time
from dynamicserialize.dstypes.com.raytheon.uf.common.time import TimeRange
class Lock(object):
def __init__(self):
self.parmId = None
self.wsId = None
self.startTime = None
self.endTime = None
self.identifier = None
def __init__(self, parmId, wsId, startTime, endTime):
self.parmId = parmId
self.wsId = wsId
self.startTime = startTime
self.endTime = endTime
self.timeRange = None
def getParmId(self):
return self.parmId
def setParmId(self, parmId):
self.parmId = parmId
def getWsId(self):
return self.wsId
def setWsId(self, wsId):
self.wsId = wsId
def getStartTime(self):
return self.startTime
def setStartTime(self, startTime):
self.startTime = startTime
def getEndTime(self):
return self.endTime
def setEndTime(self, endTime):
self.endTime = endTime
def getIdentifier(self):
return self.identifier
def setIdentifier(self, identifier):
self.identifier = identifier
def getTimeRange(self):
if not self.timeRange:
start = self.startTime / 1000.0
end = self.endTime / 1000.0
self.timeRange = TimeRange(start, end)
return self.timeRange
def __repr__(self):
t0 = time.gmtime(self.getStartTime() / 1000.0)

View file

@ -24,6 +24,7 @@
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 04/25/12 545 randerso Repurposed the lockKey field as threadId
# 06/12/13 2099 dgilling Implemented toPrettyString().
#
import struct
@ -84,6 +85,10 @@ class WsId(object):
def toString(self):
return self.networkId + ":" + self.userName + ":" + self.progName + ":" + str(self.pid) + ":" + str(self.threadId)
def toPrettyString(self):
hostname = socket.gethostbyaddr(socket.inet_ntoa(struct.pack('<L', int(self.networkId))))[0]
return self.userName + "@" + hostname + ":" + self.progName + ":" + str(self.pid) + ":" + str(self.threadId)
def __str__(self):
return self.toString()

View file

@ -52,6 +52,12 @@
# conn.close()
#-------------------------------------------------------------------------------
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# ....
# 06/13/2013 DR 16242 D. Friedman Add Qpid authentication info
#
#===============================================================================
@ -59,7 +65,10 @@ import qpid
from qpid.util import connect
from qpid.connection import Connection
from qpid.datatypes import Message, uuid4
QPID_USERNAME = 'guest'
QPID_PASSWORD = 'guest'
class IngestViaQPID:
def __init__(self, host='localhost', port=5672):
'''
@ -71,7 +80,7 @@ class IngestViaQPID:
try:
#
self.socket = connect(host, port)
self.connection = Connection (sock=self.socket)
self.connection = Connection (sock=self.socket, username=QPID_USERNAME, password=QPID_PASSWORD)
self.connection.start()
self.session = self.connection.session(str(uuid4()))
self.session.exchange_bind(exchange='amq.direct', queue='external.dropbox', binding_key='external.dropbox')

View file

@ -68,7 +68,7 @@ diff -crB a/component.spec b/component.spec
%preun
%postun
--- 40,88 ----
--- 40,95 ----
rm -rf %{_build_root}
fi
mkdir -p %{_build_root}
@ -105,7 +105,7 @@ diff -crB a/component.spec b/component.spec
%post
+ # replace the service list script with the datadelivery service list script
+ if [ -f /etc/init.d/edexServiceList ]; then
+ rm -f /etc/init.d/edexServiceList
+ mv /etc/init.d/edexServiceList /etc/init.d/edexServiceList.orig
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
@ -116,6 +116,13 @@ diff -crB a/component.spec b/component.spec
+ fi
+
%preun
+ # restore the original service list script with the datadelivery service list script
+ if [ -f /etc/init.d/edexServiceList.orig ]; then
+ mv /etc/init.d/edexServiceList.orig /etc/init.d/edexServiceList
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+ fi
%postun
***************

View file

@ -33,7 +33,12 @@ fi
if [ -f /etc/rc.d/init.d/edexServiceList ]; then
. /etc/rc.d/init.d/edexServiceList
else
SERVICES=( 'request' 'ingest' 'ingestGrib' 'ingestDat')
# SERVICES=( 'request' 'ingest' 'ingestGrib' 'ingestDat')
# Now that services could be full edex or datadelivery, don't want to start
# defaults if list is missing to prevent start up of services on an unintended
# server
echo "ERROR: /etc/rc.d/init.d/edexServiceList not found, exiting. You can manage intended service(s) by providing them as an argument until issue is resolved"
return 1
fi
# Who to run EDEX server as, usually "awips". (NOT "root")

View file

@ -132,11 +132,17 @@ fi
if [ "${1}" = "-postgres" ]; then
buildRPM "awips2-postgres"
buildRPM "awips2-database-server-configuration"
buildRPM "awips2-database-standalone-configuration"
buildRPM "awips2-database"
buildRPM "awips2-maps-database"
#buildRPM "awips2-database-server-configuration"
buildRPM "awips2-pgadmin3"
buildRPM "awips2-tools"
buildRPM "awips2-notification"
buildRPM "awips2-edex-environment"
#buildRPM "awips2-database-standalone-configuration"
#buildRPM "awips2-database"
buildRPM "awips2-data.hdf5-gfe.climo"
buildRPM "awips2-data.hdf5-topo"
#buildRPM "awips2-maps-database"
buildRPM "awips2-python-dynamicserialize"
exit 0
fi
@ -344,7 +350,7 @@ fi
if [ "${1}" = "-viz" ]; then
buildRPM "awips2"
buildRPM "awips2-common-base"
# buildRPM "awips2-common-base"
buildRPM "awips2-rcm"
buildRPM "awips2-hydroapps-shared"
buildCAVE
@ -362,6 +368,9 @@ if [ "${1}" = "-edex" ]; then
buildRPM "awips2-cli"
buildRPM "awips2-gfesuite-client"
buildRPM "awips2-gfesuite-server"
buildRPM "awips2-python-dynamicserialize"
buildRPM "awips2-python-ufpy"
buildRPM "awips2-edex-environment"
buildEDEX
if [ $? -ne 0 ]; then
exit 1

View file

@ -1,81 +0,0 @@
Copyright \251 2008 Sun Microsystems, Inc., 4150 Network Circle, Santa
Clara, California 95054, U.S.A. All rights reserved.
Sun Microsystems, Inc. has intellectual property rights relating to
technology embodied in the product that is described in this document.
In particular, and without limitation, these intellectual property
rights may include one or more of the U.S. patents listed at
http://www.sun.com/patents and one or more additional patents or
pending patent applications in the U.S. and in other countries.
THIS PRODUCT CONTAINS CONFIDENTIAL INFORMATION AND TRADE SECRETS OF SUN
MICROSYSTEMS, INC. USE, DISCLOSURE OR REPRODUCTION IS PROHIBITED
WITHOUT THE PRIOR EXPRESS WRITTEN PERMISSION OF SUN MICROSYSTEMS, INC.
U.S. Government Rights - Commercial software. Government users are
subject to the Sun Microsystems, Inc. standard license agreement and
applicable provisions of the FAR and its supplements.
Use is subject to license terms.
This distribution may include materials developed by third parties.
Sun, Sun Microsystems, the Sun logo, Java, Jini and Java SE are
trademarks or registered trademarks of Sun Microsystems, Inc. in the
U.S. and other countries.
Products covered by and information contained in this service manual
are controlled by U.S. Export Control laws and may be subject to the
export or import laws in other countries. Nuclear, missile, chemical
biological weapons or nuclear maritime end uses or end users, whether
direct or indirect, are strictly prohibited. Export or reexport to
countries subject to U.S. embargo or to entities identified on U.S.
export exclusion lists, including, but not limited to, the denied
persons and specially designated nationals lists is strictly
prohibited.
Copyright © 2008 Sun Microsystems, Inc., 4150 Network Circle, Santa
Clara, California 95054, Etats-Unis. Tous droits réservés.
Sun Microsystems, Inc. détient les droits de propriété intellectuelle
relatifs à la technologie incorporée dans le produit qui est décrit dans
ce document. En particulier, et ce sans limitation, ces droits de
propriété intellectuelle peuvent inclure un ou plus des brevets américains
listés à l'adresse http://www.sun.com/patents et un ou les brevets
supplémentaires ou les applications de brevet en attente aux Etats -
Unis et dans les autres pays.
CE PRODUIT CONTIENT DES INFORMATIONS CONFIDENTIELLES ET DES SECRETS
COMMERCIAUX DE SUN MICROSYSTEMS, INC. SON UTILISATION, SA DIVULGATION
ET SA REPRODUCTION SONT INTERDITES SANS L AUTORISATION EXPRESSE, ECRITE
ET PREALABLE DE SUN MICROSYSTEMS, INC.
Droits du gouvernement des États-Unis - logiciel commercial. Les
droits des utilisateur du gouvernement des États-Unis sont
soumis aux termes de la licence standard Sun Microsystems et
aux conditions appliquées de la FAR et de ces compléments.
L'utilisation est soumise aux termes de la Licence.
Cette distribution peut inclure des élements développés par des tiers.
Sun, Sun Microsystems, le logo Sun, Java, Jini et Java SE sont des
marques de fabrique ou des marques déposées de Sun Microsystems, Inc. aux
Etats-Unis et dans d'autres pays.
Les produits qui font l'objet de ce manuel d'entretien et les
informations qu'il contient sont regis par la legislation americaine en
matiere de controle des exportations et peuvent etre soumis au droit
d'autres pays dans le domaine des exportations et importations. Les
utilisations finales, ou utilisateurs finaux, pour des armes
nucleaires, des missiles, des armes biologiques et chimiques ou du
nucleaire maritime, directement ou indirectement, sont strictement
interdites. Les exportations ou reexportations vers des pays sous
embargo des Etats-Unis, ou vers des entites figurant sur les listes
d'exclusion d'exportation americaines, y compris, mais de maniere non
exclusive, la liste de personnes qui font objet d'un ordre de ne pas
participer, d'une facon directe ou indirecte, aux exportations des
produits ou des services qui sont regi par la legislation americaine en
matiere de controle des exportations et la liste de ressortissants
specifiquement designes, sont rigoureusement interdites.

View file

@ -1,342 +0,0 @@
Sun Microsystems, Inc. Binary Code License Agreement
for the JAVA SE DEVELOPMENT KIT (JDK), VERSION 6
SUN MICROSYSTEMS, INC. ("SUN") IS WILLING TO LICENSE THE
SOFTWARE IDENTIFIED BELOW TO YOU ONLY UPON THE CONDITION
THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS BINARY
CODE LICENSE AGREEMENT AND SUPPLEMENTAL LICENSE TERMS
(COLLECTIVELY "AGREEMENT"). PLEASE READ THE AGREEMENT
CAREFULLY. BY DOWNLOADING OR INSTALLING THIS SOFTWARE, YOU
ACCEPT THE TERMS OF THE AGREEMENT. INDICATE ACCEPTANCE BY
SELECTING THE "ACCEPT" BUTTON AT THE BOTTOM OF THE
AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY ALL THE
TERMS, SELECT THE "DECLINE" BUTTON AT THE BOTTOM OF THE
AGREEMENT AND THE DOWNLOAD OR INSTALL PROCESS WILL NOT
CONTINUE.
1. DEFINITIONS. "Software" means the identified above in
binary form, any other machine readable materials
(including, but not limited to, libraries, source files,
header files, and data files), any updates or error
corrections provided by Sun, and any user manuals,
programming guides and other documentation provided to you
by Sun under this Agreement. "General Purpose Desktop
Computers and Servers" means computers, including desktop,
laptop and tablet computers, or servers, used for general
computing functions under end user control (such as but not
specifically limited to email, general purpose Internet
browsing, and office suite productivity tools).
The use of Software in systems and solutions that provide
dedicated functionality (other than as mentioned above) or
designed for use in embedded or function-specific software
applications, for example but not limited to: Software
embedded in or bundled with industrial control systems,
wireless mobile telephones, wireless handheld devices,
kiosks, TV/STB, Blu-ray Disc devices, telematics and
network control switching equipment, printers and storage
management systems, and other related systems are excluded
from this definition and not licensed under this
Agreement. "Programs" means Java technology applets and
applications intended to run on the Java Platform Standard
Edition (Java SE) platform on Java-enabled General Purpose
Desktop Computers and Servers.
2. LICENSE TO USE. Subject to the terms and conditions of
this Agreement, including, but not limited to the Java
Technology Restrictions of the Supplemental License Terms,
Sun grants you a non-exclusive, non-transferable, limited
license without license fees to reproduce and use
internally Software complete and unmodified for the sole
purpose of running Programs. Additional licenses for
developers and/or publishers are granted in the
Supplemental License Terms.
3. RESTRICTIONS. Software is confidential and copyrighted.
Title to Software and all associated intellectual property
rights is retained by Sun and/or its licensors. Unless
enforcement is prohibited by applicable law, you may not
modify, decompile, or reverse engineer Software. You
acknowledge that Licensed Software is not designed or
intended for use in the design, construction, operation or
maintenance of any nuclear facility. Sun Microsystems, Inc.
disclaims any express or implied warranty of fitness for
such uses. No right, title or interest in or to any
trademark, service mark, logo or trade name of Sun or its
licensors is granted under this Agreement. Additional
restrictions for developers and/or publishers licenses are
set forth in the Supplemental License Terms.
4. LIMITED WARRANTY. Sun warrants to you that for a period
of ninety (90) days from the date of purchase, as evidenced
by a copy of the receipt, the media on which Software is
furnished (if any) will be free of defects in materials and
workmanship under normal use. Except for the foregoing,
Software is provided "AS IS". Your exclusive remedy and
Sun's entire liability under this limited warranty will be
at Sun's option to replace Software media or refund the fee
paid for Software. Any implied warranties on the Software
are limited to 90 days. Some states do not allow
limitations on duration of an implied warranty, so the
above may not apply to you. This limited warranty gives you
specific legal rights. You may have others, which vary from
state to state.
5. DISCLAIMER OF WARRANTY. UNLESS SPECIFIED IN THIS
AGREEMENT, ALL EXPRESS OR IMPLIED CONDITIONS,
REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED
WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE
EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY
INVALID.
6. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY
LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
ANY LOST REVENUE, PROFIT OR DATA, OR FOR SPECIAL, INDIRECT,
CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT
OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE,
EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES. In no event will Sun's liability to you, whether
in contract, tort (including negligence), or otherwise,
exceed the amount paid by you for Software under this
Agreement. The foregoing limitations will apply even if the
above stated warranty fails of its essential purpose. Some
states do not allow the exclusion of incidental or
consequential damages, so some of the terms above may not
be applicable to you.
7. TERMINATION. This Agreement is effective until
terminated. You may terminate this Agreement at any time by
destroying all copies of Software. This Agreement will
terminate immediately without notice from Sun if you fail
to comply with any provision of this Agreement. Either
party may terminate this Agreement immediately should any
Software become, or in either party's opinion be likely to
become, the subject of a claim of infringement of any
intellectual property right. Upon Termination, you must
destroy all copies of Software.
8. EXPORT REGULATIONS. All Software and technical data
delivered under this Agreement are subject to US export
control laws and may be subject to export or import
regulations in other countries. You agree to comply
strictly with all such laws and regulations and acknowledge
that you have the responsibility to obtain such licenses to
export, re-export, or import as may be required after
delivery to you.
9. TRADEMARKS AND LOGOS. You acknowledge and agree as
between you and Sun that Sun owns the SUN, SOLARIS, JAVA,
JINI, FORTE, and iPLANET trademarks and all SUN, SOLARIS,
JAVA, JINI, FORTE, and iPLANET-related trademarks, service
marks, logos and other brand designations ("Sun Marks"),
and you agree to comply with the Sun Trademark and Logo
Usage Requirements currently located at
http://www.sun.com/policies/trademarks. Any use you make of
the Sun Marks inures to Sun's benefit.
10. U.S. GOVERNMENT RESTRICTED RIGHTS. If Software is being
acquired by or on behalf of the U.S. Government or by a
U.S. Government prime contractor or subcontractor (at any
tier), then the Government's rights in Software and
accompanying documentation will be only as set forth in
this Agreement; this is in accordance with 48 CFR 227.7201
through 227.7202-4 (for Department of Defense (DOD)
acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD
acquisitions).
11. GOVERNING LAW. Any action related to this Agreement
will be governed by California law and controlling U.S.
federal law. No choice of law rules of any jurisdiction
will apply.
12. SEVERABILITY. If any provision of this Agreement is
held to be unenforceable, this Agreement will remain in
effect with the provision omitted, unless omission would
frustrate the intent of the parties, in which case this
Agreement will immediately terminate.
13. INTEGRATION. This Agreement is the entire agreement
between you and Sun relating to its subject matter. It
supersedes all prior or contemporaneous oral or written
communications, proposals, representations and warranties
and prevails over any conflicting or additional terms of
any quote, order, acknowledgment, or other communication
between the parties relating to its subject matter during
the term of this Agreement. No modification of this
Agreement will be binding, unless in writing and signed by
an authorized representative of each party.
SUPPLEMENTAL LICENSE TERMS
These Supplemental License Terms add to or modify the terms
of the Binary Code License Agreement. Capitalized terms not
defined in these Supplemental Terms shall have the same
meanings ascribed to them in the Binary Code License
Agreement . These Supplemental Terms shall supersede any
inconsistent or conflicting terms in the Binary Code
License Agreement, or in any license contained within the
Software.
A. Software Internal Use and Development License Grant.
Subject to the terms and conditions of this Agreement and
restrictions and exceptions set forth in the Software
"README" file incorporated herein by reference, including,
but not limited to the Java Technology Restrictions of
these Supplemental Terms, Sun grants you a non-exclusive,
non-transferable, limited license without fees to reproduce
internally and use internally the Software complete and
unmodified for the purpose of designing, developing, and
testing your Programs.
B. License to Distribute Software. Subject to the terms and
conditions of this Agreement and restrictions and
exceptions set forth in the Software README file,
including, but not limited to the Java Technology
Restrictions of these Supplemental Terms, Sun grants you a
non-exclusive, non-transferable, limited license without
fees to reproduce and distribute the Software, provided
that (i) you distribute the Software complete and
unmodified and only bundled as part of, and for the sole
purpose of running, your Programs, (ii) the Programs add
significant and primary functionality to the Software,
(iii) you do not distribute additional software intended to
replace any component(s) of the Software, (iv) you do not
remove or alter any proprietary legends or notices
contained in the Software, (v) you only distribute the
Software subject to a license agreement that protects Sun's
interests consistent with the terms contained in this
Agreement, and (vi) you agree to defend and indemnify Sun
and its licensors from and against any damages, costs,
liabilities, settlement amounts and/or expenses (including
attorneys' fees) incurred in connection with any claim,
lawsuit or action by any third party that arises or results
from the use or distribution of any and all Programs and/or
Software.
C. License to Distribute Redistributables. Subject to the
terms and conditions of this Agreement and restrictions and
exceptions set forth in the Software README file, including
but not limited to the Java Technology Restrictions of
these Supplemental Terms, Sun grants you a non-exclusive,
non-transferable, limited license without fees to reproduce
and distribute those files specifically identified as
redistributable in the Software "README" file
("Redistributables") provided that: (i) you distribute the
Redistributables complete and unmodified, and only bundled
as part of Programs, (ii) the Programs add significant and
primary functionality to the Redistributables, (iii) you do
not distribute additional software intended to supersede
any component(s) of the Redistributables (unless otherwise
specified in the applicable README file), (iv) you do not
remove or alter any proprietary legends or notices
contained in or on the Redistributables, (v) you only
distribute the Redistributables pursuant to a license
agreement that protects Sun's interests consistent with the
terms contained in the Agreement, (vi) you agree to defend
and indemnify Sun and its licensors from and against any
damages, costs, liabilities, settlement amounts and/or
expenses (including attorneys' fees) incurred in connection
with any claim, lawsuit or action by any third party that
arises or results from the use or distribution of any and
all Programs and/or Software.
D. Java Technology Restrictions. You may not create,
modify, or change the behavior of, or authorize your
licensees to create, modify, or change the behavior of,
classes, interfaces, or subpackages that are in any way
identified as "java", "javax", "sun" or similar convention
as specified by Sun in any naming convention designation.
E. Distribution by Publishers. This section pertains to
your distribution of the Software with your printed book or
magazine (as those terms are commonly used in the industry)
relating to Java technology ("Publication"). Subject to and
conditioned upon your compliance with the restrictions and
obligations contained in the Agreement, in addition to the
license granted in Paragraph 1 above, Sun hereby grants to
you a non-exclusive, nontransferable limited right to
reproduce complete and unmodified copies of the Software on
electronic media (the "Media") for the sole purpose of
inclusion and distribution with your Publication(s),
subject to the following terms: (i) You may not distribute
the Software on a stand-alone basis; it must be distributed
with your Publication(s); (ii) You are responsible for
downloading the Software from the applicable Sun web site;
(iii) You must refer to the Software as JavaTM SE
Development Kit 6; (iv) The Software must be reproduced in
its entirety and without any modification whatsoever
(including, without limitation, the Binary Code License and
Supplemental License Terms accompanying the Software and
proprietary rights notices contained in the Software);
(v) The Media label shall include the following
information: Copyright 2006, Sun Microsystems, Inc. All
rights reserved. Use is subject to license terms. Sun, Sun
Microsystems, the Sun logo, Solaris, Java, the Java Coffee
Cup logo, J2SE, and all trademarks and logos based on Java
are trademarks or registered trademarks of Sun
Microsystems, Inc. in the U.S. and other countries. This
information must be placed on the Media label in such a
manner as to only apply to the Sun Software; (vi) You must
clearly identify the Software as Sun's product on the Media
holder or Media label, and you may not state or imply that
Sun is responsible for any third-party software contained
on the Media; (vii) You may not include any third party
software on the Media which is intended to be a replacement
or substitute for the Software; (viii) You shall indemnify
Sun for all damages arising from your failure to comply
with the requirements of this Agreement. In addition, you
shall defend, at your expense, any and all claims brought
against Sun by third parties, and shall pay all damages
awarded by a court of competent jurisdiction, or such
settlement amount negotiated by you, arising out of or in
connection with your use, reproduction or distribution of
the Software and/or the Publication. Your obligation to
provide indemnification under this section shall arise
provided that Sun: (a) provides you prompt notice of the
claim; (b) gives you sole control of the defense and
settlement of the claim; (c) provides you, at your expense,
with all available information, assistance and authority to
defend; and (d) has not compromised or settled such claim
without your prior written consent; and (ix) You shall
provide Sun with a written notice for each Publication;
such notice shall include the following information: (1)
title of Publication, (2) author(s), (3) date of
Publication, and (4) ISBN or ISSN numbers. Such notice
shall be sent to Sun Microsystems, Inc., 4150 Network
Circle, M/S USCA12-110, Santa Clara, California 95054,
U.S.A , Attention: Contracts Administration.
F. Source Code. Software may contain source code that,
unless expressly licensed for other purposes, is provided
solely for reference purposes pursuant to the terms of this
Agreement. Source code may not be redistributed unless
expressly provided for in this Agreement.
G. Third Party Code. Additional copyright notices and
license terms applicable to portions of the Software are
set forth in the THIRDPARTYLICENSEREADME.txt file. In
addition to any terms and conditions of any third party
opensource/freeware license identified in the
THIRDPARTYLICENSEREADME.txt file, the disclaimer of
warranty and limitation of liability provisions in
paragraphs 5 and 6 of the Binary Code License Agreement
shall apply to all Software in this distribution.
H. Termination for Infringement. Either party may terminate
this Agreement immediately should any Software become, or
in either party's opinion be likely to become, the subject
of a claim of infringement of any intellectual property
right.
I. Installation and Auto-Update. The Software's
installation and auto-update processes transmit a limited
amount of data to Sun (or its service provider) about those
specific processes to help Sun understand and optimize
them. Sun does not associate the data with personally
identifiable information. You can find more information
about the data Sun collects at http://java.com/data/.
For inquiries please contact: Sun Microsystems, Inc., 4150
Network Circle, Santa Clara, California 95054, U.S.A.

View file

@ -1,719 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=us-ascii">
<meta name="collection" content="reference">
<title>README -- Java Platform, Standard Edition Development Kit</title>
</head>
<body lang="en-US" bgcolor="#FFFFFF">
<h1 align="center">README</h1>
<h2 align="center">Java<sup><font size="-2">TM</font></sup> Platform,
Standard Edition 6<br>
Development Kit</h2>
<p align="center"><b>JDK<sup><font size="-2">TM</font></sup> 6</b></p>
<h2>Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#install">System Requirements &amp; Installation</a></li>
<li><a href="#docs">JDK Documentation</a></li>
<li><a href="#relnotes">Release Notes</a></li>
<li><a href="#compatibility">Compatibility</a></li>
<li><a href="#bugs">Bug Reports and Feedback</a></li>
<li><a href="#contents">Contents of the JDK</a></li>
<li><a href="#jre">Java Runtime Environment</a></li>
<li><a href="#redistribution">Redistribution</a></li>
<li><a href="#endorsed">Java Endorsed Standards Override
Mechanism</a></li>
<li><a href="#javadb">Java DB</a></li>
<li><a href="#webpages">Web Pages</a></li>
</ul>
<h2><a name="introduction" id="introduction"></a>Introduction</h2>
<blockquote>
Thank you for downloading this release of the Java<sup><font size=
"-2">TM</font></sup> Platform, Standard Edition Development Kit
(JDK<sup><font size="-2">TM</font></sup>). The JDK is a development
environment for building applications, applets, and components using the
Java programming language.
</blockquote>
<blockquote>
The JDK includes tools useful for developing and testing programs written
in the Java programming language and running on the Java<sup><font size=
"-2">TM</font></sup> platform.
</blockquote>
<h2><a name="install" id="install"></a>System Requirements &amp;
Installation</h2>
<blockquote>
System requirements, installation instructions and troubleshooting tips
are located on the Java Software web site at:
</blockquote>
<blockquote>
<a href="http://java.sun.com/javase/6/webnotes/install/">JDK 6
Installation Instructions</a>
</blockquote>
<h2><a name="docs" id="docs"></a>JDK<sup><font size="-2">TM</font></sup>
Documentation</h2>
<blockquote>
The on-line <a href=
"http://java.sun.com/javase/6/docs/">Java<sup><font size=
"-2">TM</font></sup> Platform, Standard Edition (Java SE)
Documentation</a> contains API specifications, feature descriptions,
developer guides, reference pages for JDK<sup><font size=
"-2">TM</font></sup> tools and utilities, demos, and links to related
information. This documentation is also available in a download bundle
which you can install on your machine. To obtain the documentation bundle,
see the <a href="http://java.sun.com/javase/6/download.jsp">download
page</a>. For API documentation, refer to the <a href=
"http://java.sun.com/javase/6/docs/api/index.html">The
Java<sup><font size="-2">TM</font></sup> Platform, Standard Edition API
Specification</a> This provides brief descriptions of the API with an
emphasis on specifications, not on code examples.
</blockquote>
<h2><a name="relnotes" id="relnotes"></a>Release Notes</h2>
<blockquote>
See the <a href="http://java.sun.com/javase/6/webnotes/">Java SE 6 Release
Notes</a> on the Java Software web site for additional information
pertaining to this release. Please check the on-line release notes
occasionally for the latest information as they will be updated as needed.
</blockquote>
<h2><a name="compatibility" id="compatibility"></a>Compatibility</h2>
<blockquote>
See <a href=
"http://java.sun.com/javase/6/webnotes/compatibility.html">Compatibility
with Previous Releases</a> on the Java Software web site for the list of
known compatibility issues. Every effort has been made to support programs
written for previous versions of the Java<sup><font size=
"-2">TM</font></sup> platform. Although some incompatible changes were
necessary, most software should migrate to the current version with no
reprogramming. Any failure to do so is considered a bug, except for a
small number of cases where compatibility was deliberately broken, as
described on our compatibility web page. Some compatibility-breaking
changes were required to close potential security holes or to fix
implementation or design bugs.
</blockquote>
<h2><a name="bugs" id="bugs"></a>Bug Reports and Feedback</h2>
<blockquote>
The <a href="http://bugs.sun.com/bugdatabase/index.jsp">Bug Database</a>
web site lets you search for and examine existing bug reports, submit your
own bug reports, and tell us which bug fixes matter most to you. To
directly submit a bug or request a feature, fill out this form:
</blockquote>
<blockquote>
<a href=
"http://bugs.sun.com/services/bugreport/index.jsp">http://bugs.sun.com/services/bugreport/index.jsp</a>
</blockquote>
<blockquote>
You can send feedback to the <a href=
"http://java.sun.com/docs/forms/sendusmail.html">Java SE documentation
team</a>. You can also send comments directly to <a href=
"http://developers.sun.com/contact/index.jsp">Java Software engineering
team email addresses</a>.
</blockquote>
<blockquote>
<b>Note</b> - Please do not seek technical support through the Bug
Database or our development teams. For support options, see <a href=
"http://java.sun.com/developer/support/">Support and Services</a> on the
Java Software web site.
</blockquote>
<h2><a name="contents" id="contents"></a>Contents of the JDK<sup><font size=
"-2">TM</font></sup></h2>
<blockquote>
This section contains a general summary of the files and directories in
the JDK<sup><font size="-2">TM</font></sup>. For details on the files and
directories, see the <a href=
"http://java.sun.com/javase/6/docs/technotes/tools/index.html#general">JDK
File Structure</a> section of the Java SE documentation for your platform.
</blockquote>
<dl>
<dd>
<dl>
<dt><b>Development Tools</b></dt>
<dd>(In the <code>bin/</code> subdirectory) Tools and utilities that
will help you develop, execute, debug, and document programs written
in the Java<sup><font size="-2">TM</font></sup> programming language.
For further information, see the <a href=
"http://java.sun.com/javase/6/docs/technotes/tools/index.html">tool
documentation</a>.<br>
<br></dd>
<dt><b>Runtime Environment</b></dt>
<dd>(In the <code>jre/</code> subdirectory) An implementation of the
Java Runtime Environment (JRE<sup><font size="-2">TM</font></sup>) for
use by the JDK. The JRE includes a Java<sup><font size=
"-2">TM</font></sup> Virtual Machine (JVM<sup><font size=
"-2">TM</font></sup>), class libraries, and other files that support
the execution of programs written in the Java<sup><font size=
"-2">TM</font></sup> programming language.<br>
<br></dd>
<dt><b>Additional Libraries</b></dt>
<dd>(In the <code>lib/</code> subdirectory) Additional class libraries
and support files required by the development tools.<br>
<br></dd>
<dt><b>Demo Applets and Applications</b></dt>
<dd>(In the <code>demo/</code> subdirectory) Examples, with source
code, of programming for the Java<sup><font size="-2">TM</font></sup>
platform. These include examples that use Swing and other
Java<sup><font size="-2">TM</font></sup> Foundation Classes, and the
Java<sup><font size="-2">TM</font></sup> Platform Debugger
Architecture.<br>
<br></dd>
<dt><b>Sample Code</b></dt>
<dd>(In the <code>sample</code> subdirectory) Samples, with source
code, of programming for certain Java API's.<br>
<br></dd>
<dt><b>C header Files</b></dt>
<dd>(In the <code>include/</code> subdirectory) Header files that
support native-code programming using the <a href=
"http://java.sun.com/javase/6/docs/technotes/guides/jni/">Java Native
Interface</a>, the <a href=
"http://java.sun.com/javase/6/docs/technotes/guides/jvmti/">JVM<sup><font size="-2">TM</font></sup>
Tool Interface</a>, and other functionality of the
Java<sup><font size="-2">TM</font></sup> platform.<br>
<br></dd>
<dt><b>Source Code</b></dt>
<dd>(In <code>src.zip</code>) Java<sup><font size="-2">TM</font></sup>
programming language source files for all classes that make up the
Java&nbsp;core API (that is, sources files for the java.*, javax.* and
some org.* packages, but not for com.sun.* packages). This source code
is provided for informational purposes only, to help developers learn
and use the Java<sup><font size="-2">TM</font></sup> programming
language. These files do not include platform-specific implementation
code and cannot be used to rebuild the class libraries. To extract
these file, use any common zip utility. Or, you may use the Jar
utility in the JDK's <code>bin/</code> directory:<br>
<br>
<code>jar xvf src.zip</code></dd>
</dl>
</dd>
</dl>
<h2><a name="jre" id="jre"></a>The Java Runtime Environment
(JRE<sup><font size="-2">TM</font></sup>)</h2>
<blockquote>
The Java<sup><font size="-2">TM</font></sup> Runtime Environment
(JRE<sup><font size="-2">TM</font></sup>) is available as a separately
downloadable product. See the <a href=
"http://java.sun.com/javase/6/download.jsp">download web site</a>.
</blockquote>
<blockquote>
The JRE allows you to run applications written in the Java<sup><font size=
"-2">TM</font></sup> programming language. Like the JDK<sup><font size=
"-2">TM</font></sup>, it contains the Java<sup><font size=
"-2">TM</font></sup> Virtual Machine (JVM<sup><font size=
"-2">TM</font></sup>), classes comprising the Java<sup><font size=
"-2">TM</font></sup> platform API, and supporting files. Unlike the JDK,
it does not contain development tools such as compilers and debuggers.
</blockquote>
<blockquote>
You can freely redistribute the JRE with your application, according to
the terms of the JRE license. Once you have developed your application
using the JDK, you can ship it with the JRE so your end-users will have a
Java<sup><font size="-2">TM</font></sup> platform on which to run your
software.
</blockquote>
<h2><a name="redistribution" id="redistribution"></a>Redistribution</h2>
<blockquote>
<blockquote>
<hr>
NOTE - The license for this software does not allow the redistribution
of beta and other pre-release versions.
<hr>
</blockquote>
</blockquote>
<blockquote>
Subject to the terms and conditions of the Software License Agreement and
the obligations, restrictions, and exceptions set forth below, You may
reproduce and distribute the Software (and also portions of Software
identified below as Redistributable), provided that:
</blockquote>
<blockquote>
<ol type="a">
<li>you distribute the Software complete and unmodified and only bundled
as part of Your applets and applications ("Programs"),</li>
<li>your Programs add significant and primary functionality to the
Software,</li>
<li>your Programs are only intended to run on Java-enabled general
purpose desktop computers and servers,</li>
<li>you distribute Software for the sole purpose of running your
Programs,</li>
<li>you do not distribute additional software intended to replace any
component(s) of the Software,</li>
<li>you do not remove or alter any proprietary legends or notices
contained in or on the Software,</li>
<li>you only distribute the Software subject to a license agreement that
protects Sun's interests consistent with the terms contained in this
Agreement, and</li>
<li>you agree to defend and indemnify Sun and its licensors from and
against any damages, costs, liabilities, settlement amounts and/or
expenses (including attorneys' fees) incurred in connection with any
claim, lawsuit or action by any third party that arises or results from
the use or distribution of any and all Programs and/or Software.</li>
</ol>
</blockquote>
<blockquote>
The term "vendors" used here refers to licensees, developers, and
independent software vendors (ISVs) who license and distribute the
Java<sup><font size="-2">TM</font></sup> Development Kit
(JDK<sup><font size="-2">TM</font></sup>) with their programs.
</blockquote>
<blockquote>
Vendors must follow the terms of the Java Development Kit Binary Code
License agreement.
</blockquote>
<h3>Required vs. Optional Files</h3>
<blockquote>
The files that make up the Java<sup><font size="-2">TM</font></sup>
Development Kit (JDK<sup><font size="-2">TM</font></sup>) are divided into
two categories: required and optional. Optional files may be excluded from
redistributions of the JDK at the vendor's discretion.
</blockquote>
<blockquote>
The following section contains a list of the files and directories that
may optionally be omitted from redistributions of the JDK. All files not
in these lists of optional files must be included in redistributions of
the JDK.
</blockquote>
<h3>Optional Files and Directories</h3>
<blockquote>
The following files may be optionally excluded from redistributions. These
files are located in the jdk1.6.0_&lt;version&gt; directory, where
&lt;version&gt; is the update version number. Solaris<sup><font size=
"-2">TM</font></sup> and Linux filenames and separators are shown. Windows
executables have the ".exe" suffix. Corresponding files with
<code>_g</code> in the name can also be excluded. The corresponding man
pages should be excluded for any excluded executables (with paths listed
below beginning with <code>bin/</code>, for the Solaris<sup><font size=
"-2">TM</font></sup> Operating System and Linux).
</blockquote>
<dl>
<dd>
<dl>
<dt><code>jre/lib/charsets.jar</code></dt>
<dd>Character conversion classes</dd>
<dt><code>jre/lib/ext/</code></dt>
<dd><code>sunjce_provider.jar</code> - the SunJCE provider for Java
Cryptography APIs<br>
<code>localedata.jar</code> - contains many of the resources needed
for non US English locales<br>
<code>ldapsec.jar</code> - contains security features supported by the
LDAP service provider<br>
<code>dnsns.jar</code> - for the InetAddress wrapper of JNDI DNS
provider</dd>
<dt><code>bin/rmid</code> and <code>jre/bin/rmid</code></dt>
<dd>Java RMI Activation System Daemon</dd>
<dt><code>bin/rmiregistry</code> and
<code>jre/bin/rmiregistry</code></dt>
<dd>Java Remote Object Registry</dd>
<dt><code>bin/tnameserv</code> and <code>jre/bin/tnameserv</code></dt>
<dd>Java IDL Name Server</dd>
<dt><code>bin/keytool</code> and <code>jre/bin/keytool</code></dt>
<dd>Key and Certificate Management Tool</dd>
<dt><code>bin/kinit</code> and <code>jre/bin/kinit</code></dt>
<dd>Used to obtain and cache Kerberos ticket-granting tickets</dd>
<dt><code>bin/klist</code> and <code>jre/bin/klist</code></dt>
<dd>Kerberos display entries in credentials cache and keytab</dd>
<dt><code>bin/ktab</code> and <code>jre/bin/ktab</code></dt>
<dd>Kerberos key table manager</dd>
<dt><code>bin/policytool</code> and
<code>jre/bin/policytool</code></dt>
<dd>Policy File Creation and Management Tool</dd>
<dt><code>bin/orbd</code> and <code>jre/bin/orbd</code></dt>
<dd>Object Request Broker Daemon</dd>
<dt><code>bin/servertool</code> and
<code>jre/bin/servertool</code></dt>
<dd>Java IDL Server Tool</dd>
<dt><code>bin/javaws</code>, <code>jre/bin/javaws</code>,
<code>jre/lib/javaws/</code> and <code>jre/lib/javaws.jar</code></dt>
<dd>Java Web Start</dd>
<dt><code>db/</code></dt>
<dd>
Java DB, Sun Microsystems's distribution of the Apache Derby
database technology. Default installation locations are:
<ul>
<li>Solaris: <code>/opt/SUNWjavadb</code></li>
<li>Linux: <code>/opt/sun/javadb</code></li>
<li>Windows: <code>C:\Program Files\Sun\JavaDB</code></li>
</ul>For information on Java DB and Derby, including user and API
documentation, the capabilities of Java DB and further resources,
see the index.html file in the above directories.
</dd>
<dt><code>demo/</code></dt>
<dd>Demo Applets and Applications</dd>
<dt><code>sample/</code></dt>
<dd>Sample Code</dd>
<dt><code>src.zip</code></dt>
<dd>Archive of source files</dd>
</dl>
</dd>
</dl>
<h3><a name="redistributablejdkfiles" id=
"redistributablejdkfiles"></a>Redistributable JDK<sup><font size=
"-2">TM</font></sup> Files</h3>
<blockquote>
The limited set of files and directories from the JDK listed below may be
included in vendor redistributions of the Java<sup><font size=
"-2">TM</font></sup> Runtime Environment (JRE<sup><font size=
"-2">TM</font></sup>). They cannot be redistributed separately, and must
accompany an identically versioned JRE distribution. All paths are
relative to the top-level directory of the JDK. The corresponding man
pages should be included for any included executables (with paths listed
below beginning with <code>bin/</code>, for the Solaris<sup><font size=
"-2">TM</font></sup> Operating System and Linux).
</blockquote>
<dl>
<dd>
<dl>
<dt><code>jre/lib/cmm/PYCC.pf</code></dt>
<dd>Color profile. This file is required only if one wishes to convert
between the PYCC color space and another color space.</dd>
<dt>All <code>.ttf</code> font files in the
<code>jre/lib/fonts/</code> directory.</dt>
<dd>Note that the LucidaSansRegular.ttf font is already contained in
the JRE, so there is no need to bring that file over from the
JDK.</dd>
<dt><code>jre/lib/audio/soundbank.gm</code></dt>
<dd>This MIDI soundbank is present in the JDK, but it has been removed
from the JRE in order to reduce the size of the JRE download bundle.
However, a soundbank file is necessary for MIDI playback, and
therefore the JDK's <code>soundbank.gm</code> file may be included in
redistributions of the JRE at the vendor's discretion. Several
versions of enhanced MIDI soundbanks are available from the Java Sound
web site: <a href=
"http://java.sun.com/products/java-media/sound/">http://java.sun.com/products/java-media/sound/</a>.
These alternative soundbanks may be included in redistributions of the
JRE.</dd>
<dt>The javac bytecode compiler, consisting of the following
files:</dt>
<dd><code>bin/javac</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System and Linux]<br>
<code>bin/sparcv9/javac</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (SPARC(R) Platform Edition)]<br>
<code>bin/amd64/javac</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (AMD)]<br>
<code>bin/javac.exe</code> [Microsoft Windows]<br>
<code>lib/tools.jar</code> [All platforms]</dd>
<dt>The Annotation Processing Tool, consisting of the following
files:</dt>
<dd><code>lib/tools.jar</code> [All platforms]<br>
<code>bin/apt</code> [Solaris<sup><font size="-2">TM</font></sup>
Operating System and Linux]<br>
<code>bin/sparcv9/apt</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (SPARC(R) Platform Edition)]<br>
<code>bin/amd64/apt</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (AMD)]<br>
<code>bin/apt.exe</code> [Microsoft Windows]</dd>
<dt><code>lib/jconsole.jar</code></dt>
<dd>The Jconsole application. NOTE: The Jconsole application requires
the dynamic attach mechanism.</dd>
<dt>The dynamic attach mechanism consisting of the following
files:</dt>
<dd><code>lib/tools.jar</code> [All platforms]<br>
<code>jre/lib/sparc/libattach.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (SPARC(R) Platform Edition) and
Linux]<br>
<code>jre/lib/sparcv9/libattach.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (SPARC(R) Platform Edition) and
Linux]<br>
<code>jre/lib/i386/libattach.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (x86) and Linux]<br>
<code>jre/lib/amd64/libattach.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (AMD) and Linux]<br>
<code>jre\bin\attach.dll</code> [Microsoft Windows]<br></dd>
<dt>The Java Platform Debugger Architecture implementation consisting
of the files shown in the dynamic attach section above, and the
following files:</dt>
<dd><code>lib/tools.jar</code> [All platforms]<br>
<code>lib/sa-jdi.jar</code> [All platforms]<br>
<code>jre/lib/sparc/libsaproc.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (SPARC(R) Platform Edition) and
Linux]<br>
<code>jre/lib/sparcv9/libsaproc.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (SPARC(R) Platform Edition) and
Linux]<br>
<code>jre/lib/i386/libsaproc.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (x86) and Linux]<br>
<code>jre/lib/amd64/libsaproc.so</code> [Solaris<sup><font size=
"-2">TM</font></sup> Operating System (AMD) and Linux]<br></dd>
<dt><code>jre\bin\server\</code></dt>
<dd>On Microsoft Windows platforms, the JDK includes both the Java
HotSpot<sup><font size="-2">TM</font></sup> Server VM and Java
HotSpot<sup><font size="-2">TM</font></sup> Client VM. However, the
JRE for Microsoft Windows platforms includes only the Java
HotSpot<sup><font size="-2">TM</font></sup> Client VM. Those wishing
to use the Java HotSpot<sup><font size="-2">TM</font></sup> Server VM
with the JRE may copy the JDK's <code>jre\bin\server</code> folder to
a <code>bin\server</code> directory in the JRE. Software vendors may
redistribute the Java HotSpot<sup><font size="-2">TM</font></sup>
Server VM with their redistributions of the JRE.</dd>
</dl>
</dd>
</dl>
<h3>Unlimited Strength Java Cryptography Extension</h3>
<blockquote>
Due to import control restrictions for some countries, the Java
Cryptography Extension (JCE) policy files shipped with the JDK and the JRE
allow strong but limited cryptography to be used. These files are located
at<br>
<br>
<code>&lt;java-home&gt;/lib/security/local_policy.jar</code><br>
<code>&lt;java-home&gt;/lib/security/US_export_policy.jar</code><br>
<br>
where <code>&lt;java-home&gt;</code> is the <code>jre</code> directory of
the JDK or the top-level directory of the JRE.
</blockquote>
<blockquote>
An unlimited strength version of these files indicating no restrictions on
cryptographic strengths is available on the JDK web site for those living
in eligible countries. Those living in eligible countries may download the
unlimited strength version and replace the strong cryptography jar files
with the unlimited strength files.
</blockquote>
<h3>The cacerts Certificates File</h3>
<blockquote>
Root CA certificates may be added to or removed from the Java SE
certificate file located at
</blockquote>
<blockquote>
<code>&lt;java-home&gt;/lib/security/cacerts</code>
</blockquote>
<blockquote>
For more information, see <a href=
"http://java.sun.com/javase/6/docs/technotes/tools/solaris/keytool.html#cacerts">
The cacerts Certificates File</a> section in the keytool documentation.
</blockquote>
<h2><a name="endorsed" id="endorsed"></a> Java Endorsed Standards Override
Mechanism</h2>
<blockquote>
From time to time it is necessary to update the Java platform in order to
incorporate newer versions of standards that are created outside of the
Java Community Process<font size="-2"><sup>SM</sup></font> (JCP<font size=
"-2"><sup>SM</sup></font> <a href=
"http://www.jcp.org/">http://www.jcp.org/</a>) (<i>Endorsed
Standards</i>), or in order to update the version of a technology included
in the platform to correspond to a later standalone version of that
technology (<i>Standalone Technologies</i>).
</blockquote>
<blockquote>
The <i>Endorsed Standards Override Mechanism</i> provides a means whereby
later versions of classes and interfaces that implement Endorsed Standards
or Standalone Technologies may be incorporated into the Java Platform.
</blockquote>
<blockquote>
For more information on the Endorsed Standards Override Mechanism,
including the list of platform packages that it may be used to override,
see
</blockquote>
<blockquote>
<a href=
"http://java.sun.com/javase/6/docs/technotes/guides/standards/">http://java.sun.com/javase/6/docs/technotes/guides/standards/</a>
</blockquote>
<h2><a name="javadb" id="javadb"></a>Java DB</h2>
<blockquote>
This distribution bundles Java DB, Sun Microsystems' distribution of the
Apache Derby pure Java database technology. Default installation locations
are:
<ul>
<li>Solaris: <code>/opt/SUNWjavadb</code></li>
<li>Linux: <code>/opt/sun/javadb</code></li>
<li>Windows: <code>C:\Program Files\Sun\JavaDB</code></li>
</ul>
<p>For information on Java DB and Derby, including user and API
documentation, the capabilities of Java DB and further resources, see the
index.html file in the above directories.</p>
</blockquote>
<h2><a name="webpages" id="webpages"></a>Web Pages</h2>
<blockquote>
For additional information, refer to these Sun Microsystems pages on the
World Wide Web:
</blockquote>
<dl>
<dd>
<dl>
<dt><a href="http://java.sun.com/">http://java.sun.com/</a></dt>
<dd>The Java Software web site, with the latest information on Java
technology, product information, news, and features.</dd>
<dt><a href=
"http://java.sun.com/docs">http://java.sun.com/docs</a></dt>
<dd>Java<sup><font size="-2">TM</font></sup> platform Documentation
provides access to white papers, the Java Tutorial and other
documents.</dd>
<dt><a href=
"http://developer.java.sun.com/">http://developer.java.sun.com</a></dt>
<dd>Developer Services web site (Free registration required).
Additional technical information, news, and features; user forums;
support information, and much more.</dd>
<dt><a href=
"http://java.sun.com/products/">http://java.sun.com/products/</a></dt>
<dd>Java Technology Products &amp; API</dd>
</dl>
</dd>
</dl>
<hr>
<p><font size="2">The Java<sup><font size="-2">TM</font></sup> Development
Kit (JDK<sup><font size="-2">TM</font></sup>) is a product of Sun
Microsystems<sup><font size="-2">TM</font></sup>, Inc.<br>
<br>
Copyright &copy; 2008 Sun Microsystems, Inc.<br>
4150 Network Circle, Santa Clara, California 95054, U.S.A.<br>
All rights reserved.</font></p>
<script type="text/javascript" language="JavaScript" src="/js/omi/jsc/s_code_remote.js">
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -1,15 +0,0 @@
License
PostgreSQL is released under the BSD license.
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.