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:
David Gillingham 2015-07-30 13:23:00 -05:00
parent 9797c7f2e0
commit ed30c7d60e
16 changed files with 733 additions and 295 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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