diff --git a/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textUtilities/headline/FormatterRunner.py b/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textUtilities/headline/FormatterRunner.py index 5627ac2ce4..5e76555ab0 100644 --- a/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textUtilities/headline/FormatterRunner.py +++ b/cave/com.raytheon.viz.gfe/localization/gfe/userPython/textUtilities/headline/FormatterRunner.py @@ -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 "\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: diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java index bf611ab86a..e3a64212ed 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java @@ -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); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java index 8113ed2d0c..9cb00af7e8 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/FormatterLauncherDialog.java @@ -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. * * * @@ -491,8 +492,8 @@ public class FormatterLauncherDialog extends CaveJFACEDialog implements .getStringArray("FormatterLauncherDialog_Categories"); Map> categoryMap = new HashMap>(); - String[] names = textProductMgr.getProductNames(); - if (names.length > 0) { + java.util.List names = textProductMgr.getProductNames(); + if (!names.isEmpty()) { ArrayList civilEmergencies = new ArrayList(); ArrayList hazards = new ArrayList(); ArrayList baselines = new ArrayList(); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ProductEditorComp.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ProductEditorComp.java index d4f4b7c94d..75480d4c59 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ProductEditorComp.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/ProductEditorComp.java @@ -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. * * * @author lvenable @@ -2037,7 +2038,7 @@ public class ProductEditorComp extends Composite implements // segment List zones = decodeUGCs(pds.getSegmentsArray() .get(i)); - List timeZones = dm.getTextProductMgr() + Collection timeZones = dm.getTextProductMgr() .getTimeZones(zones, officeTimeZone); StringBuilder sb = new StringBuilder(); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureMetadataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureMetadataManager.java index b16ca27a39..0d392d3acf 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureMetadataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureMetadataManager.java @@ -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 jobCoordinator; - private final AtomicReference> metadata; + private final Map 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 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 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 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 getMenuItems(String menuName) { - Map inventory = metadata.get(); List 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 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 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 result) { - metadata.set(result); + updateMetadata(result); } @Override diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolMetadataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolMetadataManager.java index 880c333731..9176485503 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolMetadataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolMetadataManager.java @@ -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 jobCoordinator; - private final AtomicReference> toolMetadata; + private final Map 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 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 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 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 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 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 result) { - toolMetadata.set(result); + updateMetadata(result); notifyListeners(); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScript.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScript.java index 537fa45549..38881098d1 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScript.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScript.java @@ -29,10 +29,13 @@ import com.raytheon.uf.common.python.PythonScript; * A script that runs the text formatter python * *
+ * 
  * 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.
  * 
  * 
* @@ -72,5 +75,4 @@ public class FormatterScript extends PythonScript { public Object execute(Map args) throws JepException { return execute(METHOD_NAME, args); } - } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScriptFactory.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScriptFactory.java index 16dc0dc958..e3814f7566 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScriptFactory.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterScriptFactory.java @@ -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. * * * @@ -49,20 +50,28 @@ import com.raytheon.viz.gfe.python.GfeCavePyIncludeUtil; * @version 1.0 */ -public class FormatterScriptFactory { +public class FormatterScriptFactory extends + AbstractPythonScriptFactory { - 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()); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterUtil.java index 74e651fa61..7549daccb6 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/FormatterUtil.java @@ -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. * * * @@ -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); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextFormatter.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextFormatter.java index b7b5bddabc..7d3f871d43 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextFormatter.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextFormatter.java @@ -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. * * * @@ -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 argMap; + private final Map 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(); 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 map = new HashMap(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; + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductConfigData.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductConfigData.java new file mode 100644 index 0000000000..c038190d23 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductConfigData.java @@ -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. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 29, 2015  #4263     dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public final class TextProductConfigData { + + private final Map defaultVtecModes; + + private final Collection 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 defaultVtecModes, + Collection productInventory) { + this.defaultVtecModes = defaultVtecModes; + this.productInventory = productInventory; + } + + public Map getDefaultVtecModes() { + return defaultVtecModes; + } + + public Collection getProductInventory() { + return productInventory; + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductConfigDataExecutor.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductConfigDataExecutor.java new file mode 100644 index 0000000000..c2f0a472bc --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductConfigDataExecutor.java @@ -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. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 29, 2015  #4263     dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public final class TextProductConfigDataExecutor implements + IPythonExecutor { + + 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 map = new HashMap(2, 1f); + map.put("paths", GfePyIncludeUtil.getTextProductsIncludePath()); + map.put("getVtecCodes", getVtecCodes); + TextProductConfigData data = (TextProductConfigData) script.execute( + "getScripts", map); + + return data; + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductManager.java index a5ce7ed3f7..63fd7b0b72 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductManager.java @@ -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. * * * @@ -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 scriptToModuleMap = new HashMap(); + private final PythonJobCoordinator jobCoordinator; - private Map scriptToDefinitionMap = new HashMap(); + /** + * Text product inventory. Maps product display name to product metadata. + */ + private final Map metadata; - private LocalizationFile lfConfigDir; + /** + * Manages the default VTEC mode for Hazard products. Maps PIL to VTEC mode + * code. + */ + private final Map 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 listener = new IPythonJobListener() { + + @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 map = new HashMap(); - 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 keySet = scriptToModuleMap.keySet(); - String[] names = keySet.toArray(new String[keySet.size()]); - Arrays.sort(names, String.CASE_INSENSITIVE_ORDER); + public List getProductNames() { + List names = Collections.emptyList(); + synchronized (accessLock) { + names = new ArrayList<>(metadata.keySet()); + } + Collections.sort(names, String.CASE_INSENSITIVE_ORDER); return names; } - public String[] getModuleNames() { - Collection vals = scriptToModuleMap.values(); - String[] names = vals.toArray(new String[vals.size()]); - Arrays.sort(names); + public List getModuleNames() { + List 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 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 map = new HashMap(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 map = new HashMap(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 getTimeZones(List zones, String officeTimeZone) { - List timeZones = Collections.emptyList(); - HashMap map = new HashMap(2); - map.put("zones", zones); - map.put("officeTZ", officeTimeZone); + public Collection getTimeZones(Collection zones, + String officeTimeZone) { + Collection timeZones = Collections.emptyList(); try { - timeZones = (List) 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 listener = new IPythonJobListener() { + + @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); } } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductMetadata.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductMetadata.java new file mode 100644 index 0000000000..1f81c08bcd --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductMetadata.java @@ -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. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 29, 2015  #4263     dgilling     Initial creation
+ * 
+ * 
+ * + * @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(); + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductTimeZonesExecutor.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductTimeZonesExecutor.java new file mode 100644 index 0000000000..d5d24c8106 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/TextProductTimeZonesExecutor.java @@ -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. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 28, 2015  #4263     dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public final class TextProductTimeZonesExecutor implements + IPythonExecutor> { + + private final Collection zones; + + private final String officeTimeZone; + + /** + * @param zones + * @param officeTimeZone + */ + public TextProductTimeZonesExecutor(Collection 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 execute(FormatterScript script) + throws JepException { + Map map = new HashMap(2, 1f); + map.put("zones", zones); + map.put("officeTZ", officeTimeZone); + Collection timeZones = (Collection) script.execute( + "getTimeZones", map); + return timeZones; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/textproduct/ProductDefinition.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/textproduct/ProductDefinition.java index bd921a4ef8..39814f7959 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/textproduct/ProductDefinition.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/textproduct/ProductDefinition.java @@ -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. * * * @@ -42,19 +43,24 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; */ @DynamicSerialize -public class ProductDefinition implements ISerializableObject { +public class ProductDefinition { + @DynamicSerializeElement - private HashMap definition; + private Map definition; public ProductDefinition() { - definition = new HashMap(); + this.definition = new HashMap<>(); } - public HashMap getDefinition() { + public ProductDefinition(Map definition) { + this.definition = definition; + } + + public Map getDefinition() { return definition; } - public void setDefinition(HashMap definition) { + public void setDefinition(Map definition) { this.definition = definition; }