Omaha #4263: Rewrite GFE TextProductManager so it can be initialized off main thread.
Change-Id: Ia0cc2cf0c01f6ec6573c61768cd638f45feb0893 Former-commit-id: ceed238549ff6a6a8be8aa30aef3dfaeef5ce25d
This commit is contained in:
parent
9797c7f2e0
commit
ed30c7d60e
16 changed files with 733 additions and 295 deletions
|
@ -44,6 +44,7 @@ import UFStatusHandler
|
|||
# 05/06/2015 #4467 randerso Convert to upper case before writing to files if
|
||||
# mixed case is not enabled for the product.
|
||||
# Cleaned up file writing code
|
||||
# 07/29/2015 #4263 dgilling Support updated TextProductManager.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -391,20 +392,22 @@ def writeToServerFile(forecasts, outputFile, writeToSite):
|
|||
return 0
|
||||
return 1
|
||||
|
||||
def getScripts(paths, nameMap, definitionMap):
|
||||
def importModules(paths):
|
||||
global displayNameDict
|
||||
displayNameDict = {}
|
||||
|
||||
rval = []
|
||||
split = paths.split(':')
|
||||
split = paths.split(os.path.pathsep)
|
||||
for path in split:
|
||||
if not path in sys.path:
|
||||
sys.path.append(path)
|
||||
inv = os.listdir(path)
|
||||
inv = filter(filterScripts, inv)
|
||||
logger.info("TextProduct FormatterLauncher Processing....")
|
||||
|
||||
inv = []
|
||||
if os.path.exists(path):
|
||||
inv = os.listdir(path)
|
||||
inv = filter(filterScripts, inv)
|
||||
|
||||
for pid in inv:
|
||||
name = string.split(pid, ".")[0]
|
||||
name = os.path.splitext(pid)[0]
|
||||
if sys.modules.has_key(name):
|
||||
del sys.modules[name]
|
||||
try:
|
||||
|
@ -429,30 +432,38 @@ def getScripts(paths, nameMap, definitionMap):
|
|||
logger.info("Formatter: No Definition Found " +
|
||||
name)
|
||||
continue
|
||||
#fs = FormatterScript(self._dataMgr, name, mod, definition)
|
||||
dspName = getDisplayName(definition)
|
||||
if dspName is None or dspName == "None":
|
||||
#LogStream.logVerbose("Formatter displayName is None: " +
|
||||
# ppDef(definition))
|
||||
continue
|
||||
#LogStream.logVerbose("Formatter displayName set: ", fs.dspName(),
|
||||
# ppDef(definition))
|
||||
nameMap.put(dspName, name)
|
||||
from com.raytheon.uf.common.dataplugin.gfe.textproduct import ProductDefinition
|
||||
pdef = ProductDefinition()
|
||||
pdef.setDefinition(JUtil.pyDictToJavaMap(definition))
|
||||
definitionMap.put(dspName, pdef)
|
||||
displayNameDict[dspName] = (mod, definition)
|
||||
#rval.append(fs)
|
||||
#rval.sort()
|
||||
|
||||
def getScripts(paths, getVtecCodes):
|
||||
from java.util import ArrayList
|
||||
from com.raytheon.uf.common.dataplugin.gfe.textproduct import ProductDefinition
|
||||
from com.raytheon.viz.gfe.textformatter import TextProductConfigData
|
||||
from com.raytheon.viz.gfe.textformatter import TextProductMetadata
|
||||
|
||||
logger.info("TextProduct FormatterLauncher Processing....")
|
||||
importModules(paths)
|
||||
textProducts = ArrayList()
|
||||
for (displayName, value) in displayNameDict.items():
|
||||
(module, definition) = value
|
||||
moduleName = module.__name__
|
||||
pdef = ProductDefinition(JUtil.pyDictToJavaMap(definition))
|
||||
productMetadata = TextProductMetadata(moduleName, displayName, pdef)
|
||||
textProducts.add(productMetadata)
|
||||
|
||||
vtecCodes = {}
|
||||
if getVtecCodes:
|
||||
import VTECMessageType
|
||||
vtecCodes = VTECMessageType.VTECMessageTypeDict
|
||||
|
||||
logger.info("TextProduct FormatterLauncher Done....")
|
||||
#return rval
|
||||
return TextProductConfigData(JUtil.pyValToJavaObj(vtecCodes), textProducts)
|
||||
|
||||
def filterScripts(name):
|
||||
result = False
|
||||
if name.endswith(".py") and not name.endswith("Definition.py"):
|
||||
result = True
|
||||
return result
|
||||
(filename, ext) = os.path.splitext(name)
|
||||
return ext == ".py" and not filename.endswith("Definition")
|
||||
|
||||
def getDisplayName(definition):
|
||||
try:
|
||||
|
@ -482,7 +493,9 @@ def ppDef(definition):
|
|||
else:
|
||||
return "<Definition not dictionary>\n" + `definition`
|
||||
|
||||
def getVarDict(dspName, dataMgr, issuedBy, dataSource):
|
||||
def getVarDict(paths, dspName, dataMgr, issuedBy, dataSource):
|
||||
importModules(paths)
|
||||
|
||||
tz = str(dataMgr.getClient().getSiteTimeZone())
|
||||
os.environ['TZ'] = tz
|
||||
time.tzset()
|
||||
|
@ -499,7 +512,7 @@ def getTimeZones(zones, officeTZ):
|
|||
import AreaDictionary
|
||||
timezones = []
|
||||
if zones is not None:
|
||||
for zone in JUtil.javaStringListToPylist(zones):
|
||||
for zone in zones:
|
||||
zdict = AreaDictionary.AreaDictionary.get(zone, {})
|
||||
tzs = zdict.get("ugcTimeZone", [])
|
||||
if type(tzs) is str:
|
||||
|
|
|
@ -209,6 +209,8 @@ public class DataManager {
|
|||
|
||||
private final AtomicBoolean proceduresInitialized;
|
||||
|
||||
private final AtomicBoolean textProductsInitialized;
|
||||
|
||||
public IISCDataAccess getIscDataAccess() {
|
||||
return iscDataAccess;
|
||||
}
|
||||
|
@ -246,6 +248,7 @@ public class DataManager {
|
|||
|
||||
smartToolsInitialized = new AtomicBoolean(false);
|
||||
proceduresInitialized = new AtomicBoolean(false);
|
||||
textProductsInitialized = new AtomicBoolean(false);
|
||||
initializeScriptControllers(discriminator);
|
||||
waitForScriptControllers();
|
||||
procJobPool = new ProcedureJobPool(4, 4, this);
|
||||
|
@ -542,27 +545,22 @@ public class DataManager {
|
|||
};
|
||||
procedureInterface.initialize(procedureListener);
|
||||
|
||||
// it would be really nice to be able to spawn the construction of these
|
||||
// two heavy objects into another thread. Unfortunately, Jep requires
|
||||
// creation and all subsequent access to happen on the same thread. So
|
||||
// we need to make use of runSync() here. It would be even be acceptable
|
||||
// if we could make this a UIJob; unfortunately the thread most often
|
||||
// used to create DataManager is the UI thread at perspective open, so
|
||||
// we can't block and wait on the UI thread for a job that
|
||||
// requires the UI thread to run.
|
||||
VizApp.runSync(new Runnable() {
|
||||
textProductMgr = new TextProductManager();
|
||||
IAsyncStartupObjectListener textProductListener = new IAsyncStartupObjectListener() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
DataManager.this.textProductMgr = new TextProductManager(
|
||||
discriminator != null);
|
||||
public void objectInitialized() {
|
||||
textProductsInitialized.set(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
boolean startLocalizationListener = (discriminator != null);
|
||||
textProductMgr.init(startLocalizationListener, textProductListener);
|
||||
}
|
||||
|
||||
private void waitForScriptControllers() {
|
||||
long waitTime = 0;
|
||||
while (!(smartToolsInitialized.get() && proceduresInitialized.get())) {
|
||||
while (!(smartToolsInitialized.get() && proceduresInitialized.get() && textProductsInitialized
|
||||
.get())) {
|
||||
try {
|
||||
waitTime += 10;
|
||||
Thread.sleep(10);
|
||||
|
|
|
@ -89,7 +89,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* Jun 19, 2010 4684 mduff Corrected the Data Sources menu for
|
||||
* practice and test modes
|
||||
* Sep 16, 2010 6831 ryu Show same product for different areas on a sub-menu
|
||||
* Nov 22, 2011 8781 mli remove Processor menu
|
||||
* Nov 22, 2011 8781 mli remove Processor menu
|
||||
* Jul 26, 2012 15165 ryu Set default db source when formatter has no db defined.
|
||||
* Oct 23, 2012 1287 rferrel Changes for non-blocking dialogs and code clean up.
|
||||
* Nov 08, 2012 1298 rferrel Changes for non-blocking IssuanceSiteIdDlg.
|
||||
|
@ -99,6 +99,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* May 15, 2013 1842 dgilling Pass DataManager instance down to sub-
|
||||
* components.
|
||||
* Feb 12, 2014 2801 randerso Added prompting if formatter is run against non-normal database
|
||||
* Jul 29, 2015 4263 dgilling Support changes to TextProductManager.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -491,8 +492,8 @@ public class FormatterLauncherDialog extends CaveJFACEDialog implements
|
|||
.getStringArray("FormatterLauncherDialog_Categories");
|
||||
Map<String, ArrayList<String>> categoryMap = new HashMap<String, ArrayList<String>>();
|
||||
|
||||
String[] names = textProductMgr.getProductNames();
|
||||
if (names.length > 0) {
|
||||
java.util.List<String> names = textProductMgr.getProductNames();
|
||||
if (!names.isEmpty()) {
|
||||
ArrayList<String> civilEmergencies = new ArrayList<String>();
|
||||
ArrayList<String> hazards = new ArrayList<String>();
|
||||
ArrayList<String> baselines = new ArrayList<String>();
|
||||
|
|
|
@ -168,7 +168,8 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* 04/20/2015 4027 randerso Renamed ProductStateEnum with an initial capital
|
||||
* Expunged Calendar from ActiveTableRecord
|
||||
* 07/02/2015 13753 lshi Update times for products in Product Editor
|
||||
* 07/22/2015 13753 lshi Keeps issue time unchanged
|
||||
* 07/22/2015 13753 lshi Keeps issue time unchanged
|
||||
* 07/28/2015 4263 dgilling Support changes to TextProductManager.
|
||||
* </pre>
|
||||
*
|
||||
* @author lvenable
|
||||
|
@ -2037,7 +2038,7 @@ public class ProductEditorComp extends Composite implements
|
|||
// segment
|
||||
List<String> zones = decodeUGCs(pds.getSegmentsArray()
|
||||
.get(i));
|
||||
List<String> timeZones = dm.getTextProductMgr()
|
||||
Collection<String> timeZones = dm.getTextProductMgr()
|
||||
.getTimeZones(zones, officeTimeZone);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
|
@ -22,9 +22,9 @@ package com.raytheon.viz.gfe.procedures;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
import com.raytheon.uf.common.localization.FileUpdatedMessage;
|
||||
|
@ -68,7 +68,9 @@ public final class ProcedureMetadataManager implements
|
|||
|
||||
private final PythonJobCoordinator<ProcedureMetadataController> jobCoordinator;
|
||||
|
||||
private final AtomicReference<Map<String, ProcedureMetadata>> metadata;
|
||||
private final Map<String, ProcedureMetadata> metadata;
|
||||
|
||||
private final Object accessLock;
|
||||
|
||||
private final LocalizationFile proceduresDir;
|
||||
|
||||
|
@ -78,16 +80,15 @@ public final class ProcedureMetadataManager implements
|
|||
ProcedureMetadataScriptFactory scriptFactory = new ProcedureMetadataScriptFactory(
|
||||
dataMgr);
|
||||
this.jobCoordinator = PythonJobCoordinator.newInstance(scriptFactory);
|
||||
Map<String, ProcedureMetadata> emptyMap = Collections.emptyMap();
|
||||
this.metadata = new AtomicReference<>(emptyMap);
|
||||
|
||||
this.metadata = new HashMap<>();
|
||||
this.accessLock = new Object();
|
||||
|
||||
LocalizationContext baseCtx = PathManagerFactory.getPathManager()
|
||||
.getContext(LocalizationType.CAVE_STATIC,
|
||||
LocalizationLevel.BASE);
|
||||
this.proceduresDir = GfePyIncludeUtil.getProceduresLF(baseCtx);
|
||||
this.proceduresDir.addFileUpdatedObserver(this);
|
||||
this.utilitiesDir = GfePyIncludeUtil.getUtilitiesLF(baseCtx);
|
||||
this.utilitiesDir.addFileUpdatedObserver(this);
|
||||
}
|
||||
|
||||
public void initialize(final IAsyncStartupObjectListener startupListener) {
|
||||
|
@ -96,7 +97,7 @@ public final class ProcedureMetadataManager implements
|
|||
|
||||
@Override
|
||||
public void jobFinished(Map<String, ProcedureMetadata> result) {
|
||||
metadata.set(result);
|
||||
updateMetadata(result);
|
||||
startupListener.objectInitialized();
|
||||
}
|
||||
|
||||
|
@ -112,6 +113,9 @@ public final class ProcedureMetadataManager implements
|
|||
} catch (Exception e1) {
|
||||
statusHandler.error("Error initializing procedure metadata.", e1);
|
||||
}
|
||||
|
||||
proceduresDir.addFileUpdatedObserver(this);
|
||||
utilitiesDir.addFileUpdatedObserver(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
@ -120,6 +124,13 @@ public final class ProcedureMetadataManager implements
|
|||
jobCoordinator.shutdown();
|
||||
}
|
||||
|
||||
private void updateMetadata(Map<String, ProcedureMetadata> newMetadata) {
|
||||
synchronized (accessLock) {
|
||||
metadata.clear();
|
||||
metadata.putAll(newMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the procedures that correspond to the menu name
|
||||
*
|
||||
|
@ -128,11 +139,12 @@ public final class ProcedureMetadataManager implements
|
|||
* @return the names of procedures that should appear in the menu.
|
||||
*/
|
||||
public List<String> getMenuItems(String menuName) {
|
||||
Map<String, ProcedureMetadata> inventory = metadata.get();
|
||||
List<String> proceduresForMenu = new ArrayList<>();
|
||||
for (ProcedureMetadata procMetadata : inventory.values()) {
|
||||
if (procMetadata.getMenuNames().contains(menuName)) {
|
||||
proceduresForMenu.add(procMetadata.getName());
|
||||
synchronized (accessLock) {
|
||||
for (ProcedureMetadata procMetadata : metadata.values()) {
|
||||
if (procMetadata.getMenuNames().contains(menuName)) {
|
||||
proceduresForMenu.add(procMetadata.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(proceduresForMenu);
|
||||
|
@ -140,20 +152,26 @@ public final class ProcedureMetadataManager implements
|
|||
}
|
||||
|
||||
public List<FieldDefinition> getVarDictWidgets(String procedureName) {
|
||||
ProcedureMetadata procMetadata = metadata.get().get(procedureName);
|
||||
ProcedureMetadata procMetadata = null;
|
||||
synchronized (accessLock) {
|
||||
procMetadata = metadata.get(procedureName);
|
||||
}
|
||||
|
||||
if (procMetadata != null) {
|
||||
return procMetadata.getVarDictWidgets();
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Collection<String> getMethodArguments(String procedureName) {
|
||||
ProcedureMetadata procMetadata = metadata.get().get(procedureName);
|
||||
ProcedureMetadata procMetadata = null;
|
||||
synchronized (accessLock) {
|
||||
procMetadata = metadata.get(procedureName);
|
||||
}
|
||||
|
||||
if (procMetadata != null) {
|
||||
return procMetadata.getArgNames();
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
@ -172,7 +190,7 @@ public final class ProcedureMetadataManager implements
|
|||
|
||||
@Override
|
||||
public void jobFinished(Map<String, ProcedureMetadata> result) {
|
||||
metadata.set(result);
|
||||
updateMetadata(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,10 +22,10 @@ package com.raytheon.viz.gfe.smarttool.script;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.core.runtime.ListenerList;
|
||||
|
||||
|
@ -72,7 +72,9 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
|
||||
private final PythonJobCoordinator<SmartToolMetadataController> jobCoordinator;
|
||||
|
||||
private final AtomicReference<Map<String, SmartToolMetadata>> toolMetadata;
|
||||
private final Map<String, SmartToolMetadata> toolMetadata;
|
||||
|
||||
private final Object accessLock;
|
||||
|
||||
private final LocalizationFile smartToolDir;
|
||||
|
||||
|
@ -84,16 +86,15 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
SmartToolMetadataScriptFactory scriptFactory = new SmartToolMetadataScriptFactory(
|
||||
dataMgr);
|
||||
this.jobCoordinator = PythonJobCoordinator.newInstance(scriptFactory);
|
||||
Map<String, SmartToolMetadata> emptyMap = Collections.emptyMap();
|
||||
this.toolMetadata = new AtomicReference<>(emptyMap);
|
||||
|
||||
this.toolMetadata = new HashMap<>();
|
||||
this.accessLock = new Object();
|
||||
|
||||
LocalizationContext baseCtx = PathManagerFactory.getPathManager()
|
||||
.getContext(LocalizationType.CAVE_STATIC,
|
||||
LocalizationLevel.BASE);
|
||||
this.smartToolDir = GfePyIncludeUtil.getSmartToolsLF(baseCtx);
|
||||
this.smartToolDir.addFileUpdatedObserver(this);
|
||||
this.utilitiesDir = GfePyIncludeUtil.getUtilitiesLF(baseCtx);
|
||||
this.utilitiesDir.addFileUpdatedObserver(this);
|
||||
|
||||
this.invChangedListeners = new ListenerList(ListenerList.IDENTITY);
|
||||
}
|
||||
|
@ -104,7 +105,7 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
|
||||
@Override
|
||||
public void jobFinished(Map<String, SmartToolMetadata> result) {
|
||||
toolMetadata.set(result);
|
||||
updateMetadata(result);
|
||||
startupListener.objectInitialized();
|
||||
}
|
||||
|
||||
|
@ -120,6 +121,9 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
} catch (Exception e1) {
|
||||
statusHandler.error("Error initializing smart tool metadata.", e1);
|
||||
}
|
||||
|
||||
smartToolDir.addFileUpdatedObserver(this);
|
||||
utilitiesDir.addFileUpdatedObserver(this);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
@ -128,6 +132,13 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
jobCoordinator.shutdown();
|
||||
}
|
||||
|
||||
private void updateMetadata(Map<String, SmartToolMetadata> newMetadata) {
|
||||
synchronized (accessLock) {
|
||||
toolMetadata.clear();
|
||||
toolMetadata.putAll(newMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the tools that apply to the specified parm
|
||||
*
|
||||
|
@ -145,23 +156,25 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
|
||||
Collection<String> tools = new HashSet<>();
|
||||
boolean listAll = ((parmName == null) && (parmTypeName == null));
|
||||
for (SmartToolMetadata toolData : toolMetadata.get().values()) {
|
||||
String toolName = toolData.getName();
|
||||
synchronized (accessLock) {
|
||||
for (SmartToolMetadata toolData : toolMetadata.values()) {
|
||||
String toolName = toolData.getName();
|
||||
|
||||
if (listAll) {
|
||||
tools.add(toolName);
|
||||
} else if (toolData.isHideTool()) {
|
||||
continue;
|
||||
} else if (parmName.equals(toolData.getWeatherElementEdited())) {
|
||||
tools.add(toolName);
|
||||
} else if (toolData.getScreenList() != null) {
|
||||
if ((toolData.getScreenList().contains(parmName))
|
||||
|| (toolData.getScreenList().contains(parmTypeName))) {
|
||||
if (listAll) {
|
||||
tools.add(toolName);
|
||||
} else if (toolData.isHideTool()) {
|
||||
continue;
|
||||
} else if (parmName.equals(toolData.getWeatherElementEdited())) {
|
||||
tools.add(toolName);
|
||||
} else if (toolData.getScreenList() != null) {
|
||||
if ((toolData.getScreenList().contains(parmName))
|
||||
|| (toolData.getScreenList().contains(parmTypeName))) {
|
||||
tools.add(toolName);
|
||||
}
|
||||
} else if (toolData.getWeatherElementEdited().equals(
|
||||
"variableElement")) {
|
||||
tools.add(toolName);
|
||||
}
|
||||
} else if (toolData.getWeatherElementEdited().equals(
|
||||
"variableElement")) {
|
||||
tools.add(toolName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,20 +191,26 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
* @return the WeatherElementEdited
|
||||
*/
|
||||
public String getWeatherElementEdited(String toolName) {
|
||||
SmartToolMetadata metadata = toolMetadata.get().get(toolName);
|
||||
if (metadata != null) {
|
||||
return metadata.getWeatherElementEdited();
|
||||
SmartToolMetadata toolData = null;
|
||||
synchronized (accessLock) {
|
||||
toolData = toolMetadata.get(toolName);
|
||||
}
|
||||
|
||||
if (toolData != null) {
|
||||
return toolData.getWeatherElementEdited();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<FieldDefinition> getVarDictWidgets(String toolName) {
|
||||
SmartToolMetadata metadata = toolMetadata.get().get(toolName);
|
||||
if (metadata != null) {
|
||||
return metadata.getVarDictWidgets();
|
||||
SmartToolMetadata toolData = null;
|
||||
synchronized (accessLock) {
|
||||
toolData = toolMetadata.get(toolName);
|
||||
}
|
||||
|
||||
if (toolData != null) {
|
||||
return toolData.getVarDictWidgets();
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
@ -203,11 +222,14 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
* @return the tool's execute() documentation, or null if there isn't any
|
||||
*/
|
||||
public String getInfo(String toolName) {
|
||||
SmartToolMetadata metadata = toolMetadata.get().get(toolName);
|
||||
if (metadata != null) {
|
||||
return metadata.getDocString();
|
||||
SmartToolMetadata toolData = null;
|
||||
synchronized (accessLock) {
|
||||
toolData = toolMetadata.get(toolName);
|
||||
}
|
||||
|
||||
if (toolData != null) {
|
||||
return toolData.getDocString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -240,7 +262,7 @@ public class SmartToolMetadataManager implements ILocalizationFileObserver {
|
|||
|
||||
@Override
|
||||
public void jobFinished(Map<String, SmartToolMetadata> result) {
|
||||
toolMetadata.set(result);
|
||||
updateMetadata(result);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,13 @@ import com.raytheon.uf.common.python.PythonScript;
|
|||
* A script that runs the text formatter python
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 2, 2008 njensen Initial creation
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 02, 2008 njensen Initial creation
|
||||
* Jul 30, 2015 #4263 dgilling Support updated TextProductManager.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -72,5 +75,4 @@ public class FormatterScript extends PythonScript {
|
|||
public Object execute(Map<String, Object> args) throws JepException {
|
||||
return execute(METHOD_NAME, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel
|
|||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.python.PyUtil;
|
||||
import com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory;
|
||||
import com.raytheon.uf.common.util.FileUtil;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.viz.gfe.python.GfeCavePyIncludeUtil;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +42,7 @@ import com.raytheon.viz.gfe.python.GfeCavePyIncludeUtil;
|
|||
* Jun 02, 2008 njensen Initial creation
|
||||
* Apr 20, 2015 4027 randerso Remove unused TextProductsTemplates path and added
|
||||
* Tests path for GFE formatter auto tests
|
||||
* Jul 28, 2015 4263 dgilling Refactor based on AbstractPythonScriptFactory.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -49,20 +50,28 @@ import com.raytheon.viz.gfe.python.GfeCavePyIncludeUtil;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class FormatterScriptFactory {
|
||||
public class FormatterScriptFactory extends
|
||||
AbstractPythonScriptFactory<FormatterScript> {
|
||||
|
||||
public static FormatterScript buildFormatterScript() throws JepException,
|
||||
VizException {
|
||||
private static final String SCRIPT_EXECUTOR_NAME = "text-product-metadata";
|
||||
|
||||
private static final int EXECUTOR_NUM_THREADS = 1;
|
||||
|
||||
public FormatterScriptFactory() {
|
||||
super(SCRIPT_EXECUTOR_NAME, EXECUTOR_NUM_THREADS);
|
||||
}
|
||||
|
||||
private static String buildScriptPath() {
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
|
||||
LocalizationContext baseContext = pathMgr.getContext(
|
||||
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
|
||||
|
||||
String headlineDir = GfePyIncludeUtil.getHeadlineLF(baseContext)
|
||||
.getFile().getPath();
|
||||
String runnerPath = FileUtil.join(headlineDir, "FormatterRunner.py");
|
||||
return runnerPath;
|
||||
}
|
||||
|
||||
private static String buildIncludePath() {
|
||||
String include = PyUtil.buildJepIncludePath(true,
|
||||
GfePyIncludeUtil.getCommonPythonIncludePath(),
|
||||
GfePyIncludeUtil.getVtecIncludePath(),
|
||||
|
@ -73,8 +82,19 @@ public class FormatterScriptFactory {
|
|||
GfePyIncludeUtil.getUtilitiesIncludePath(),
|
||||
GfePyIncludeUtil.getCombinationsIncludePath(),
|
||||
GfeCavePyIncludeUtil.getTestsIncludePath());
|
||||
return include;
|
||||
}
|
||||
|
||||
return new FormatterScript(runnerPath, include,
|
||||
FormatterScript.class.getClassLoader());
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.python.concurrent.AbstractPythonScriptFactory#
|
||||
* createPythonScript()
|
||||
*/
|
||||
@Override
|
||||
public FormatterScript createPythonScript() throws JepException {
|
||||
return new FormatterScript(buildScriptPath(), buildIncludePath(),
|
||||
getClass().getClassLoader());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.TimeZone;
|
||||
|
||||
import com.raytheon.uf.common.activetable.ActiveTableMode;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.viz.core.mode.CAVEMode;
|
||||
|
@ -46,6 +44,8 @@ import com.raytheon.viz.gfe.tasks.TaskManager;
|
|||
* Removed call to TextProductManager.reloadModule
|
||||
* Apr 20, 2015 4027 randerso Renamed ProductStateEnum with an initial capital
|
||||
* Fixed hard coded active table mode in runFormatterScript
|
||||
* Jul 30, 2015 4263 dgilling Pass DataManager instance to TextFormatter, stop passing
|
||||
* varDict through.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -54,8 +54,6 @@ import com.raytheon.viz.gfe.tasks.TaskManager;
|
|||
*/
|
||||
|
||||
public class FormatterUtil {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(FormatterUtil.class);
|
||||
|
||||
public static String[] VTEC_MODES = { "Normal: NoVTEC", "Normal: O-Vtec",
|
||||
"Normal: E-Vtec", "Normal: X-Vtec", "Test: NoVTEC", "Test: T-Vtec" };
|
||||
|
@ -107,33 +105,23 @@ public class FormatterUtil {
|
|||
}
|
||||
|
||||
String name = productMgr.getModuleName(productName);
|
||||
String varDict = productMgr.getVarDict(productName, dataMgr, dbId);
|
||||
|
||||
if (varDict != null) {
|
||||
String time = null;
|
||||
if (!SimulatedTime.getSystemTime().isRealTime()) {
|
||||
SimpleDateFormat gmtFormatter = new SimpleDateFormat(
|
||||
"yyyyMMdd_HHmm");
|
||||
gmtFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
|
||||
time = gmtFormatter.format(SimulatedTime.getSystemTime()
|
||||
.getTime());
|
||||
}
|
||||
runFormatterScript(name, shortVtec, dbId, varDict, atMode.name(),
|
||||
time, testMode, finish);
|
||||
} else {
|
||||
finish.textProductFinished("Formatter canceled",
|
||||
ConfigData.ProductStateEnum.Finished);
|
||||
String time = null;
|
||||
if (!SimulatedTime.getSystemTime().isRealTime()) {
|
||||
SimpleDateFormat gmtFormatter = new SimpleDateFormat(
|
||||
"yyyyMMdd_HHmm");
|
||||
gmtFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
time = gmtFormatter.format(SimulatedTime.getSystemTime().getTime());
|
||||
}
|
||||
runFormatterScript(name, shortVtec, dbId, atMode.name(), time,
|
||||
testMode, finish, dataMgr);
|
||||
}
|
||||
|
||||
public static void runFormatterScript(String name, String vtecMode,
|
||||
String databaseID, String varDict, String vtecActiveTable,
|
||||
String drtTime, int testMode, TextProductFinishListener finish) {
|
||||
String databaseID, String vtecActiveTable, String drtTime,
|
||||
int testMode, TextProductFinishListener finish, DataManager dataMgr) {
|
||||
TextFormatter formatter = new TextFormatter(name, vtecMode, databaseID,
|
||||
varDict, vtecActiveTable, drtTime, testMode, finish);
|
||||
// Thread thread = new Thread(formatter);
|
||||
// thread.start();
|
||||
vtecActiveTable, drtTime, testMode, finish, dataMgr);
|
||||
finish.textProductQueued(ConfigData.ProductStateEnum.Queued);
|
||||
TaskManager.getInstance().queueFormatter(formatter);
|
||||
}
|
||||
|
|
|
@ -22,8 +22,13 @@ package com.raytheon.viz.gfe.textformatter;
|
|||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
import com.raytheon.uf.common.status.IPerformanceStatusHandler;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.PerformanceStatus;
|
||||
|
@ -54,6 +59,8 @@ import com.raytheon.viz.gfe.tasks.AbstractGfeTask;
|
|||
* Dec 1, 2010 6130 ryu Set proper state and invoke callback
|
||||
* May 29, 2014 2841 randerso Handle failure to queue due to pending limit
|
||||
* Apr 20, 2015 4027 randerso Renamed ProductStateEnum with an initial capital
|
||||
* Jul 28, 2015 4263 dgilling Support changes to FormatterScriptFactory,
|
||||
* get DataManager instance via constructor.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -70,18 +77,20 @@ public class TextFormatter extends AbstractGfeTask {
|
|||
private final IPerformanceStatusHandler perfLog = PerformanceStatus
|
||||
.getHandler("GFE:");
|
||||
|
||||
private TextProductFinishListener listener;
|
||||
private final TextProductFinishListener listener;
|
||||
|
||||
private HashMap<String, Object> argMap;
|
||||
private final Map<String, Object> argMap;
|
||||
|
||||
private ConfigData.ProductStateEnum state;
|
||||
|
||||
private final DataManager dataMgr;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public TextFormatter(String productName, String vtecMode,
|
||||
String databaseID, String varDict, String vtecActiveTable,
|
||||
String drtTime, int testMode, TextProductFinishListener finish) {
|
||||
String databaseID, String vtecActiveTable, String drtTime,
|
||||
int testMode, TextProductFinishListener finish, DataManager dataMgr) {
|
||||
super(productName);
|
||||
String addr = null;
|
||||
|
||||
|
@ -91,16 +100,17 @@ public class TextFormatter extends AbstractGfeTask {
|
|||
addr = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
this.dataMgr = dataMgr;
|
||||
|
||||
argMap = new HashMap<String, Object>();
|
||||
argMap.put("testMode", testMode);
|
||||
argMap.put(ArgDictConstants.DATABASE_ID, databaseID);
|
||||
argMap.put(ArgDictConstants.SITE, DataManager.getCurrentInstance()
|
||||
.getSiteID());
|
||||
argMap.put(ArgDictConstants.SITE, this.dataMgr.getSiteID());
|
||||
argMap.put(ArgDictConstants.FORECAST_LIST, productName);
|
||||
argMap.put("username", System.getProperty("user.name") + ":" + addr);
|
||||
argMap.put("dataMgr", DataManager.getCurrentInstance());
|
||||
argMap.put("dataMgr", this.dataMgr);
|
||||
argMap.put(ArgDictConstants.VTEC_MODE, vtecMode);
|
||||
argMap.put(ArgDictConstants.CMDLINE_VARDICT, varDict);
|
||||
|
||||
argMap.put(ArgDictConstants.VTEC_ACTIVE_TABLE, vtecActiveTable);
|
||||
argMap.put("drtTime", drtTime);
|
||||
listener = finish;
|
||||
|
@ -121,15 +131,27 @@ public class TextFormatter extends AbstractGfeTask {
|
|||
});
|
||||
|
||||
argMap.put("logFile", getLogFile().getAbsolutePath());
|
||||
script = FormatterScriptFactory.buildFormatterScript();
|
||||
ITimer timer = TimeUtil.getTimer();
|
||||
timer.start();
|
||||
forecast = (String) script.execute(argMap);
|
||||
timer.stop();
|
||||
script = new FormatterScriptFactory().createPythonScript();
|
||||
|
||||
String productName = (String) argMap
|
||||
.get(ArgDictConstants.FORECAST_LIST);
|
||||
perfLog.logDuration("Text Formatter " + productName,
|
||||
timer.getElapsedTime());
|
||||
String issuedBy = dataMgr.getTextProductMgr().getIssuedBy();
|
||||
String dbId = (String) argMap.get(ArgDictConstants.DATABASE_ID);
|
||||
String varDict = getVarDict(productName, dataMgr, dbId, issuedBy,
|
||||
script);
|
||||
|
||||
if (varDict != null) {
|
||||
argMap.put(ArgDictConstants.CMDLINE_VARDICT, varDict);
|
||||
|
||||
ITimer timer = TimeUtil.getTimer();
|
||||
timer.start();
|
||||
forecast = (String) script.execute(argMap);
|
||||
timer.stop();
|
||||
perfLog.logDuration("Text Formatter " + productName,
|
||||
timer.getElapsedTime());
|
||||
} else {
|
||||
forecast = "Formatter canceled";
|
||||
}
|
||||
|
||||
state = ConfigData.ProductStateEnum.Finished;
|
||||
} catch (Throwable t) {
|
||||
|
@ -208,4 +230,19 @@ public class TextFormatter extends AbstractGfeTask {
|
|||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getVarDict(String productName, DataManager dataManager,
|
||||
String dbId, String issuedBy, FormatterScript script)
|
||||
throws JepException {
|
||||
Map<String, Object> map = new HashMap<String, Object>(5, 1f);
|
||||
map.put("paths", GfePyIncludeUtil.getTextProductsIncludePath());
|
||||
map.put("dspName",
|
||||
dataManager.getTextProductMgr().getDisplayName(productName));
|
||||
map.put("dataMgr", dataManager);
|
||||
map.put("issuedBy", issuedBy);
|
||||
map.put("dataSource", new DatabaseID(dbId).getModelName());
|
||||
|
||||
String varDict = (String) script.execute("getVarDict", map);
|
||||
return varDict;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* 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.viz.gfe.textformatter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Container object to pass text product configuration data between python and
|
||||
* Java.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 29, 2015 #4263 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class TextProductConfigData {
|
||||
|
||||
private final Map<String, String> defaultVtecModes;
|
||||
|
||||
private final Collection<TextProductMetadata> productInventory;
|
||||
|
||||
/**
|
||||
* @param defaultVtecModes
|
||||
* The default VTEC mode for each hazard product PIL.
|
||||
* @param productInventory
|
||||
* Text product inventory and the associated metadata for each
|
||||
* product.
|
||||
*/
|
||||
public TextProductConfigData(Map<String, String> defaultVtecModes,
|
||||
Collection<TextProductMetadata> productInventory) {
|
||||
this.defaultVtecModes = defaultVtecModes;
|
||||
this.productInventory = productInventory;
|
||||
}
|
||||
|
||||
public Map<String, String> getDefaultVtecModes() {
|
||||
return defaultVtecModes;
|
||||
}
|
||||
|
||||
public Collection<TextProductMetadata> getProductInventory() {
|
||||
return productInventory;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* 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.viz.gfe.textformatter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
|
||||
|
||||
/**
|
||||
* Executor object to retrieve text product configuration and metadata from
|
||||
* python into Java.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 29, 2015 #4263 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class TextProductConfigDataExecutor implements
|
||||
IPythonExecutor<FormatterScript, TextProductConfigData> {
|
||||
|
||||
private final boolean getVtecCodes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param handleVtecModes
|
||||
* Retrieve default VTEC mode configuration data
|
||||
*/
|
||||
public TextProductConfigDataExecutor(boolean getVtecCodes) {
|
||||
this.getVtecCodes = getVtecCodes;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.python.concurrent.IPythonExecutor#execute(com.
|
||||
* raytheon.uf.common.python.PythonInterpreter)
|
||||
*/
|
||||
@Override
|
||||
public TextProductConfigData execute(FormatterScript script)
|
||||
throws JepException {
|
||||
Map<String, Object> map = new HashMap<String, Object>(2, 1f);
|
||||
map.put("paths", GfePyIncludeUtil.getTextProductsIncludePath());
|
||||
map.put("getVtecCodes", getVtecCodes);
|
||||
TextProductConfigData data = (TextProductConfigData) script.execute(
|
||||
"getScripts", map);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -19,18 +19,14 @@
|
|||
**/
|
||||
package com.raytheon.viz.gfe.textformatter;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.python.GfePyIncludeUtil;
|
||||
import com.raytheon.uf.common.dataplugin.gfe.textproduct.ProductDefinition;
|
||||
import com.raytheon.uf.common.localization.FileUpdatedMessage;
|
||||
|
@ -41,13 +37,12 @@ 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.python.concurrent.IPythonJobListener;
|
||||
import com.raytheon.uf.common.python.concurrent.PythonJobCoordinator;
|
||||
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.core.VizApp;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.localization.LocalizationManager;
|
||||
import com.raytheon.viz.gfe.core.DataManager;
|
||||
import com.raytheon.viz.gfe.core.IAsyncStartupObjectListener;
|
||||
|
||||
/**
|
||||
* Manages the available text products.
|
||||
|
@ -64,6 +59,8 @@ import com.raytheon.viz.gfe.core.DataManager;
|
|||
* Dec 15, 2014 #14946 ryu Add getTimeZones() method.
|
||||
* Apr 20, 2015 4027 randerso Made fileObservers conditional as they are not needed
|
||||
* in a non-GUI environment like GFE formatter auto-tests
|
||||
* Jul 30, 2015 4263 dgilling Major refactor so this object can be initialized off
|
||||
* UI thread.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -71,104 +68,136 @@ import com.raytheon.viz.gfe.core.DataManager;
|
|||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TextProductManager {
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(TextProductManager.class);
|
||||
public class TextProductManager implements ILocalizationFileObserver {
|
||||
|
||||
private String issuedBy = "";
|
||||
private final IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(getClass());
|
||||
|
||||
private FormatterScript script;
|
||||
private String issuedBy;
|
||||
|
||||
private Map<String, String> scriptToModuleMap = new HashMap<String, String>();
|
||||
private final PythonJobCoordinator<FormatterScript> jobCoordinator;
|
||||
|
||||
private Map<String, ProductDefinition> scriptToDefinitionMap = new HashMap<String, ProductDefinition>();
|
||||
/**
|
||||
* Text product inventory. Maps product display name to product metadata.
|
||||
*/
|
||||
private final Map<String, TextProductMetadata> metadata;
|
||||
|
||||
private LocalizationFile lfConfigDir;
|
||||
/**
|
||||
* Manages the default VTEC mode for Hazard products. Maps PIL to VTEC mode
|
||||
* code.
|
||||
*/
|
||||
private final Map<String, String> productDefaultVtecCoding;
|
||||
|
||||
private LocalizationFile lfSiteDir;
|
||||
private final Object accessLock;
|
||||
|
||||
private LocalizationFile lfUserDir;
|
||||
private final LocalizationFile textProductsDir;
|
||||
|
||||
private TextProductListener listener;
|
||||
public TextProductManager() {
|
||||
this.issuedBy = "";
|
||||
|
||||
public TextProductManager(boolean startListener) {
|
||||
try {
|
||||
init(startListener);
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Exception initializing TextProductManager", e);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Exception initializing TextProductManager", e);
|
||||
}
|
||||
}
|
||||
FormatterScriptFactory factory = new FormatterScriptFactory();
|
||||
this.jobCoordinator = PythonJobCoordinator.newInstance(factory);
|
||||
|
||||
private void init(boolean startListener) throws VizException, JepException {
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationContext configContext = pm.getContext(
|
||||
LocalizationType.CAVE_STATIC, LocalizationLevel.CONFIGURED);
|
||||
LocalizationContext siteContext = pm.getContext(
|
||||
LocalizationType.CAVE_STATIC, LocalizationLevel.SITE);
|
||||
LocalizationContext userContext = pm.getContext(
|
||||
LocalizationType.CAVE_STATIC, LocalizationLevel.USER);
|
||||
LocalizationContext baseContext = pm.getContext(
|
||||
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
|
||||
this.textProductsDir = pm.getLocalizationFile(baseContext,
|
||||
GfePyIncludeUtil.TEXT_PRODUCTS);
|
||||
|
||||
this.productDefaultVtecCoding = new HashMap<>();
|
||||
this.metadata = new HashMap<>();
|
||||
this.accessLock = new Object();
|
||||
}
|
||||
|
||||
public void init(boolean startListener,
|
||||
final IAsyncStartupObjectListener initListener) {
|
||||
TextProductConfigDataExecutor executor = new TextProductConfigDataExecutor(
|
||||
true);
|
||||
IPythonJobListener<TextProductConfigData> listener = new IPythonJobListener<TextProductConfigData>() {
|
||||
|
||||
@Override
|
||||
public void jobFinished(TextProductConfigData result) {
|
||||
buildTextProductMaps(result, true);
|
||||
initListener.objectInitialized();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jobFailed(Throwable t) {
|
||||
statusHandler
|
||||
.error("Error building text product inventory.", t);
|
||||
initListener.objectInitialized();
|
||||
}
|
||||
};
|
||||
try {
|
||||
jobCoordinator.submitAsyncJob(executor, listener);
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Error building text product inventory.", e);
|
||||
}
|
||||
|
||||
lfConfigDir = pm.getLocalizationFile(configContext,
|
||||
GfePyIncludeUtil.TEXT_PRODUCTS);
|
||||
lfSiteDir = pm.getLocalizationFile(siteContext,
|
||||
GfePyIncludeUtil.TEXT_PRODUCTS);
|
||||
lfUserDir = pm.getLocalizationFile(userContext,
|
||||
GfePyIncludeUtil.TEXT_PRODUCTS);
|
||||
if (startListener) {
|
||||
listener = new TextProductListener();
|
||||
lfConfigDir.addFileUpdatedObserver(listener);
|
||||
lfSiteDir.addFileUpdatedObserver(listener);
|
||||
lfUserDir.addFileUpdatedObserver(listener);
|
||||
textProductsDir.addFileUpdatedObserver(this);
|
||||
}
|
||||
|
||||
script = FormatterScriptFactory.buildFormatterScript();
|
||||
|
||||
buildTextProductMaps();
|
||||
}
|
||||
|
||||
private void buildTextProductMaps() throws VizException, JepException {
|
||||
File configDir = lfConfigDir.getFile();
|
||||
File siteDir = lfSiteDir.getFile();
|
||||
File userDir = lfUserDir.getFile();
|
||||
private void buildTextProductMaps(TextProductConfigData configData,
|
||||
boolean updateVtecMap) {
|
||||
synchronized (accessLock) {
|
||||
if (updateVtecMap) {
|
||||
productDefaultVtecCoding.clear();
|
||||
productDefaultVtecCoding.putAll(configData
|
||||
.getDefaultVtecModes());
|
||||
}
|
||||
|
||||
scriptToModuleMap.clear();
|
||||
scriptToDefinitionMap.clear();
|
||||
|
||||
HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
String paths = configDir.getPath();
|
||||
if ((siteDir != null) && siteDir.exists()) {
|
||||
paths = siteDir + ":" + paths;
|
||||
metadata.clear();
|
||||
for (TextProductMetadata textProduct : configData
|
||||
.getProductInventory()) {
|
||||
metadata.put(textProduct.getDisplayName(), textProduct);
|
||||
}
|
||||
}
|
||||
if ((userDir != null) && userDir.exists()) {
|
||||
paths = userDir + ":" + paths;
|
||||
}
|
||||
map.put("paths", paths);
|
||||
map.put("nameMap", scriptToModuleMap);
|
||||
map.put("definitionMap", scriptToDefinitionMap);
|
||||
|
||||
script.execute("getScripts", map);
|
||||
}
|
||||
|
||||
public String[] getProductNames() {
|
||||
Set<String> keySet = scriptToModuleMap.keySet();
|
||||
String[] names = keySet.toArray(new String[keySet.size()]);
|
||||
Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
|
||||
public List<String> getProductNames() {
|
||||
List<String> names = Collections.emptyList();
|
||||
synchronized (accessLock) {
|
||||
names = new ArrayList<>(metadata.keySet());
|
||||
}
|
||||
Collections.sort(names, String.CASE_INSENSITIVE_ORDER);
|
||||
return names;
|
||||
}
|
||||
|
||||
public String[] getModuleNames() {
|
||||
Collection<String> vals = scriptToModuleMap.values();
|
||||
String[] names = vals.toArray(new String[vals.size()]);
|
||||
Arrays.sort(names);
|
||||
public List<String> getModuleNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
synchronized (accessLock) {
|
||||
for (TextProductMetadata textProduct : metadata.values()) {
|
||||
names.add(textProduct.getModuleName());
|
||||
}
|
||||
}
|
||||
Collections.sort(names);
|
||||
return names;
|
||||
}
|
||||
|
||||
public String getModuleName(String productName) {
|
||||
return scriptToModuleMap.get(productName);
|
||||
TextProductMetadata productMetadata = null;
|
||||
synchronized (accessLock) {
|
||||
productMetadata = metadata.get(productName);
|
||||
}
|
||||
|
||||
String moduleName = (productMetadata != null) ? productMetadata
|
||||
.getModuleName() : null;
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
public String getDisplayName(String moduleName) {
|
||||
String displayName = null;
|
||||
synchronized (accessLock) {
|
||||
for (Entry<String, TextProductMetadata> entry : metadata.entrySet()) {
|
||||
if (moduleName.equals(entry.getValue().getModuleName())) {
|
||||
displayName = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public String getCombinationsFileName(String productName) {
|
||||
|
@ -207,74 +236,49 @@ public class TextProductManager {
|
|||
}
|
||||
|
||||
public Object getDefinitionValue(String productName, String key) {
|
||||
Object obj;
|
||||
try {
|
||||
obj = scriptToDefinitionMap.get(productName).get(key);
|
||||
} catch (NullPointerException e) {
|
||||
obj = "Combinations_Default_" + productName;
|
||||
Object obj = null;
|
||||
synchronized (accessLock) {
|
||||
try {
|
||||
obj = metadata.get(productName).getProductDefinition().get(key);
|
||||
} catch (NullPointerException e) {
|
||||
obj = "Combinations_Default_" + productName;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public ProductDefinition getProductDefinition(String productName) {
|
||||
return scriptToDefinitionMap.get(productName);
|
||||
}
|
||||
|
||||
public String getVarDict(String productName, DataManager dataManager,
|
||||
String dbId) {
|
||||
String varDict = null;
|
||||
HashMap<String, Object> map = new HashMap<String, Object>(1);
|
||||
map.put("dspName", productName);
|
||||
map.put("dataMgr", dataManager);
|
||||
map.put("issuedBy", issuedBy);
|
||||
DatabaseID dataSource = new DatabaseID(dbId);
|
||||
map.put("dataSource", dataSource.getModelName());
|
||||
try {
|
||||
varDict = (String) script.execute("getVarDict", map);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Exception getting VarDict",
|
||||
e);
|
||||
ProductDefinition productDef = null;
|
||||
synchronized (accessLock) {
|
||||
productDef = metadata.get(productName).getProductDefinition();
|
||||
}
|
||||
|
||||
return varDict;
|
||||
return productDef;
|
||||
}
|
||||
|
||||
public String getVtecMessageType(String productCategory) {
|
||||
String vtec = null;
|
||||
HashMap<String, Object> map = new HashMap<String, Object>(1);
|
||||
map.put("productCategory", productCategory);
|
||||
try {
|
||||
vtec = (String) script.execute("getVTECMessageType", map);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Exception getting VTECMessageType", e);
|
||||
}
|
||||
String vtec = productDefaultVtecCoding.get(productCategory);
|
||||
if (vtec == null) {
|
||||
vtec = "";
|
||||
}
|
||||
return vtec;
|
||||
}
|
||||
|
||||
public List<String> getTimeZones(List<String> zones, String officeTimeZone) {
|
||||
List<String> timeZones = Collections.emptyList();
|
||||
HashMap<String, Object> map = new HashMap<String, Object>(2);
|
||||
map.put("zones", zones);
|
||||
map.put("officeTZ", officeTimeZone);
|
||||
public Collection<String> getTimeZones(Collection<String> zones,
|
||||
String officeTimeZone) {
|
||||
Collection<String> timeZones = Collections.emptyList();
|
||||
try {
|
||||
timeZones = (List<String>) script.execute("getTimeZones", map);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Exception getting time zones", e);
|
||||
timeZones = jobCoordinator
|
||||
.submitSyncJob(new TextProductTimeZonesExecutor(zones,
|
||||
officeTimeZone));
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Exception getting time zones.", e);
|
||||
}
|
||||
return timeZones;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
script.dispose();
|
||||
|
||||
lfConfigDir.removeFileUpdatedObserver(listener);
|
||||
lfSiteDir.removeFileUpdatedObserver(listener);
|
||||
lfUserDir.removeFileUpdatedObserver(listener);
|
||||
textProductsDir.removeFileUpdatedObserver(this);
|
||||
jobCoordinator.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -306,23 +310,34 @@ public class TextProductManager {
|
|||
return issuedBy;
|
||||
}
|
||||
|
||||
private class TextProductListener implements ILocalizationFileObserver {
|
||||
@Override
|
||||
public void fileUpdated(FileUpdatedMessage message) {
|
||||
VizApp.runAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
buildTextProductMaps();
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Exception updating TextProductManager", e);
|
||||
} catch (JepException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Exception updating TextProductManager", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.localization.ILocalizationFileObserver#fileUpdated
|
||||
* (com.raytheon.uf.common.localization.FileUpdatedMessage)
|
||||
*/
|
||||
@Override
|
||||
public void fileUpdated(FileUpdatedMessage message) {
|
||||
TextProductConfigDataExecutor executor = new TextProductConfigDataExecutor(
|
||||
false);
|
||||
IPythonJobListener<TextProductConfigData> listener = new IPythonJobListener<TextProductConfigData>() {
|
||||
|
||||
@Override
|
||||
public void jobFinished(TextProductConfigData result) {
|
||||
buildTextProductMaps(result, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jobFailed(Throwable t) {
|
||||
statusHandler
|
||||
.error("Error updating text product inventory.", t);
|
||||
}
|
||||
};
|
||||
try {
|
||||
jobCoordinator.submitAsyncJob(executor, listener);
|
||||
} catch (Exception e) {
|
||||
statusHandler.error("Error updating text product inventory.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* 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.viz.gfe.textformatter;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.gfe.textproduct.ProductDefinition;
|
||||
|
||||
/**
|
||||
* Container object for passing metadata about a given text product between
|
||||
* python and Java.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 29, 2015 #4263 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class TextProductMetadata {
|
||||
|
||||
private final String moduleName;
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private final ProductDefinition productDefinition;
|
||||
|
||||
/**
|
||||
* @param moduleName
|
||||
* @param displayName
|
||||
* @param productDefinition
|
||||
*/
|
||||
public TextProductMetadata(String moduleName, String displayName,
|
||||
ProductDefinition productDefinition) {
|
||||
this.moduleName = moduleName;
|
||||
this.displayName = displayName;
|
||||
this.productDefinition = productDefinition;
|
||||
}
|
||||
|
||||
public String getModuleName() {
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public ProductDefinition getProductDefinition() {
|
||||
return productDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("TextProductMetadata [moduleName=");
|
||||
builder.append(moduleName);
|
||||
builder.append(", displayName=");
|
||||
builder.append(displayName);
|
||||
builder.append(", productDefinition=");
|
||||
builder.append(productDefinition);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* 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.viz.gfe.textformatter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jep.JepException;
|
||||
|
||||
import com.raytheon.uf.common.python.concurrent.IPythonExecutor;
|
||||
|
||||
/**
|
||||
* Executor object to get the necessary time zones for a text product.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 28, 2015 #4263 dgilling Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author dgilling
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public final class TextProductTimeZonesExecutor implements
|
||||
IPythonExecutor<FormatterScript, Collection<String>> {
|
||||
|
||||
private final Collection<String> zones;
|
||||
|
||||
private final String officeTimeZone;
|
||||
|
||||
/**
|
||||
* @param zones
|
||||
* @param officeTimeZone
|
||||
*/
|
||||
public TextProductTimeZonesExecutor(Collection<String> zones,
|
||||
String officeTimeZone) {
|
||||
this.zones = zones;
|
||||
this.officeTimeZone = officeTimeZone;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.common.python.concurrent.IPythonExecutor#execute(com.
|
||||
* raytheon.uf.common.python.PythonInterpreter)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<String> execute(FormatterScript script)
|
||||
throws JepException {
|
||||
Map<String, Object> map = new HashMap<String, Object>(2, 1f);
|
||||
map.put("zones", zones);
|
||||
map.put("officeTZ", officeTimeZone);
|
||||
Collection<String> timeZones = (Collection<String>) script.execute(
|
||||
"getTimeZones", map);
|
||||
return timeZones;
|
||||
}
|
||||
}
|
|
@ -20,8 +20,8 @@
|
|||
package com.raytheon.uf.common.dataplugin.gfe.textproduct;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.raytheon.uf.common.serialization.ISerializableObject;
|
||||
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
|
||||
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
||||
|
||||
|
@ -34,6 +34,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 23, 2010 #2866 randerso Initial creation
|
||||
* Jul 30, 2015 #4263 dgilling Add second constructor.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -42,19 +43,24 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
|||
*/
|
||||
|
||||
@DynamicSerialize
|
||||
public class ProductDefinition implements ISerializableObject {
|
||||
public class ProductDefinition {
|
||||
|
||||
@DynamicSerializeElement
|
||||
private HashMap<String, Object> definition;
|
||||
private Map<String, Object> definition;
|
||||
|
||||
public ProductDefinition() {
|
||||
definition = new HashMap<String, Object>();
|
||||
this.definition = new HashMap<>();
|
||||
}
|
||||
|
||||
public HashMap<String, Object> getDefinition() {
|
||||
public ProductDefinition(Map<String, Object> definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public Map<String, Object> getDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
public void setDefinition(HashMap<String, Object> definition) {
|
||||
public void setDefinition(Map<String, Object> definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue