Merge "Issue #1870 add Python and XML Incremental Override, implemented for both Java and Python" into development

Former-commit-id: b438ff7294 [formerly eedf5cfb2e [formerly 834382386db28affb25c7ca00614d647f988c0e4]]
Former-commit-id: eedf5cfb2e
Former-commit-id: dd9d33f966
This commit is contained in:
Nate Jensen 2013-05-02 14:04:25 -05:00 committed by Gerrit Code Review
commit 52a3cabcae
6 changed files with 395 additions and 46 deletions

View file

@ -1,22 +1,22 @@
##
# #
# 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.
##
# #
from java.lang import Integer, Float, Long, Boolean, String
@ -26,18 +26,18 @@ from collections import OrderedDict
#
# Provides convenience methods for Java-Python bridging
#
#
#
#
#
# SOFTWARE HISTORY
#
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 05/01/08 njensen Initial Creation.
# 03/12/13 1759 dgilling Extend Java List types handled
# by javaObjToPyVal().
#
#
#
#
#
@ -64,7 +64,7 @@ def javaStringMapToPyDict(javaMap):
fval = str(val)
if fval.find('[') > -1:
exec "fval = " + fval
else:
else:
try:
fval = float(fval)
except:
@ -86,18 +86,21 @@ def javaMapToPyDict(javaMap, customConverter=None):
return pyDict
def pyDictToJavaMap(pyDict):
if pyDict is None :
return None
if isinstance(pyDict, OrderedDict):
jmap = LinkedHashMap()
else:
jmap = HashMap()
for key in pyDict:
for key in pyDict:
jmap.put(pyValToJavaObj(key), pyValToJavaObj(pyDict[key]))
return jmap
def pyValToJavaObj(val):
retObj = val
valtype = type(val)
retObj = val
valtype = type(val)
if valtype is int:
retObj = Integer(val)
elif valtype is float:
@ -120,12 +123,12 @@ def pyValToJavaObj(val):
elif issubclass(valtype, JavaWrapperClass):
retObj = val.toJavaObj()
return retObj
def javaObjToPyVal(obj, customConverter=None):
retVal = None
if obj is None:
return retVal
objtype = obj.jclassname
if objtype == "java.lang.Integer":
retVal = obj.intValue()
@ -150,7 +153,7 @@ def javaObjToPyVal(obj, customConverter=None):
retVal = javaMapToPyDict(obj, customConverter)
elif customConverter is not None:
retVal = customConverter(obj)
if retVal is None:
retVal = str(obj)
return retVal
@ -158,5 +161,4 @@ def javaObjToPyVal(obj, customConverter=None):
class JavaWrapperClass(object):
def toJavaObj(self):
raise NotImplementedError, "Subclasses must override this method."

View file

@ -1,35 +1,35 @@
# #
# 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.
# #
#
# Python should use this interface to get to the localization files.
#
#
#
#
#
# SOFTWARE HISTORY
#
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 03/18/13 mnash Initial Creation.
#
#
#
#
#
import os, os.path
@ -43,14 +43,14 @@ from LockingFile import File
from com.raytheon.uf.common.localization import PathManagerFactory
from com.raytheon.uf.common.localization import LocalizationContext as JavaLocalizationContext
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType, LocalizationContext_LocalizationLevel as LocalizationLevel
from java.io import File as JavaFile
from java.io import File as JavaFile
from java.lang import String
class PathManager(IPathManager.IPathManager):
def __init__(self):
self.jpathManager = PathManagerFactory.getPathManager()
def getLocalizationFile(self, name, loctype=None, loclevel=None, locname=None):
'''
@param context: the localization context for which to get the file
@ -68,7 +68,7 @@ class PathManager(IPathManager.IPathManager):
lFile = self.jpathManager.getStaticLocalizationFile(name)
if lFile is not None:
return LocalizationFile(lFile)
def getTieredLocalizationFile(self, loctype, name):
'''
@param loctype: The localization type to look in
@ -77,13 +77,15 @@ class PathManager(IPathManager.IPathManager):
@summary: Returns the localization levels available for the file given
'''
jtype = self._convertType(loctype)
jMap = JUtil.javaMapToPyDict(self.jpathManager.getTieredLocalizationFile(jtype, name))
jMap = self.jpathManager.getTieredLocalizationFile(jtype, name)
iterator = jMap.entrySet().iterator()
vals = dict()
for level in jMap:
jlevel = self._convertLevel(level)
vals[jlevel.name()] = LocalizationFile(jMap.get(level))
while iterator.hasNext() :
nextValue = iterator.next()
# the key of the entry set is a localization level, the value is a localization file
vals[nextValue.getKey().name()] = LocalizationFile(nextValue.getValue())
return vals
def listFiles(self, name, extensions, recursive, filesOnly, loctype=None, loclevel=None, locname=None):
'''
@param name: the name and path of the file
@ -102,8 +104,8 @@ class PathManager(IPathManager.IPathManager):
extArr = jarray(extensionSize, String)
for i in range(extensionSize):
extArr[i] = String(extensions[i])
if contexts is not None :
if contexts is not None :
jfiles = self.jpathManager.listFiles(contexts, name, extArr, recursive, filesOnly)
else :
jfiles = self.jpathManager.listStaticFiles(name, extArr, recursive, filesOnly)
@ -112,7 +114,7 @@ class PathManager(IPathManager.IPathManager):
for file in jfiles :
files.append(LocalizationFile(file))
return files
def getAvailableLevels(self):
'''
@return: the levels available to the caller
@ -122,7 +124,7 @@ class PathManager(IPathManager.IPathManager):
levels = list()
for level in jLevels :
levels.append(level.name())
return levels
return levels
# converts a type of a list of types to the java counterparts
def _convertType(self, loctype):
@ -135,7 +137,7 @@ class PathManager(IPathManager.IPathManager):
for i in range(loctype):
jtype[i] = self._convertType(loctype[i])
return jtype
# converts a level or a list of levels to the java counterparts
def _convertLevel(self, loclevel):
if loclevel is not None :
@ -147,7 +149,7 @@ class PathManager(IPathManager.IPathManager):
for i in range(loclevel):
jlevel[i] = self._convertLevel(loclevel[i])
return jlevel
def _getContext(self, loctype, loclevel, locname=None):
jtype = self._convertType(loctype)
jlevel = self._convertLevel(loclevel)
@ -158,7 +160,7 @@ class PathManager(IPathManager.IPathManager):
if jlevel is not None :
jlevel = [jlevel]
return self._contextForList(jtype, jlevel, locname)
def _contextForList(self, loctypes, loclevels, locname=None):
# gets the contexts in list form, for ease of use, we always use a list of contexts
# for methods that can take both
@ -167,7 +169,7 @@ class PathManager(IPathManager.IPathManager):
if locname is None and loclevels is None:
return None
elif loclevels is not None :
contexts[i] = self.jpathManager.getContext(loctypes[i], loclevels[i])
contexts[i] = self.jpathManager.getContext(loctypes[i], loclevels[i])
if locname is not None :
contexts[i].setContextName(locname)
return contexts

View file

@ -0,0 +1,118 @@
# #
# 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.
# #
#
# Overrides python modules with each other and returns a new module
#
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 03/12/13 mnash Initial Creation.
#
#
#
import os
import imp
import inspect
from PathManager import PathManager
import LocalizationUtil
def override(name, loctype):
"""
Takes a name (filename and localization path) and the localization type and finds the
file and overrides it, and returns the module
Args:
name : the name and path of the file in localization
loctype : a string representation of the localization type
Returns:
a module that has all the correct methods after being overridden
"""
pathManager = PathManager()
tieredFiles = pathManager.getTieredLocalizationFile(loctype, name)
levels = pathManager.getAvailableLevels()
lfiles = list()
for level in levels :
if tieredFiles.has_key(level) :
lfiles.append(tieredFiles[level].getPath())
themodule = _internalOverride(lfiles)
return themodule
def _internalOverride(files):
"""
Takes the files and overrides them
Args:
files : the files that are to be overridden
Returns:
a new module that contains all the necessary elements
"""
themodule = imp.new_module('tmpmodule')
# modules = list of all the modules
for module in files :
# load each module, temporarily
tmpmodule = LocalizationUtil.loadModule(module)
the_module = _combineMembers(tmpmodule, themodule)
return themodule
def _combineMembers(tocombine, finalmodule):
"""
Loops over the necessary parts of each module and decides how to combine them
Args:
tocombine : the module to combine in
finalmodule : the module that is being combined into
Returns:
a new python module that was created above
"""
# get the functions
members = inspect.getmembers(tocombine, inspect.isfunction)
for member in members :
finalmodule.__setattr__(member[0], member[1])
# get the classes
classes = inspect.getmembers(tocombine, inspect.isclass)
for clazz in classes:
finalmodule.__setattr__(clazz[0], clazz[1])
for attr in dir(tocombine):
if attr.startswith('__') == False or attr.startswith('_') == False:
if hasattr(finalmodule, attr):
if isinstance(attr, dict):
# simply update dicts with the new keys
getattr(finalmodule, attr).update(getattr(tocombine, attr))
if isinstance(attr, list):
listattr = getattr(tocombine, attr)
for i in listattr:
# override each element in the list if it exists
getattr(finalmodule, attr)[i] = listattr[i]
else :
finalmodule.__setattr__(attr, getattr(tocombine, attr))
else :
if inspect.ismethod(attr) == False and inspect.isbuiltin(attr) == False and inspect.isclass(attr) == False:
finalmodule.__setattr__(attr, getattr(tocombine, attr))
return finalmodule

View file

@ -0,0 +1,84 @@
# #
# This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
#
# U.S. EXPORT CONTROLLED TECHNICAL DATA
# This software product contains export-restricted data whose
# export/transfer/disclosure is restricted by U.S. law. Dissemination
# to non-U.S. persons whether in the United States or abroad requires
# an export license or other authorization.
#
# Contractor Name: Raytheon Company
# Contractor Address: 6825 Pine Street, Suite 340
# Mail Stop B8
# Omaha, NE 68106
# 402.291.0100
#
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
# #
#
# Overrides xml files with each other and returns a dict
#
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 03/12/13 mnash Initial Creation.
#
#
#
from com.raytheon.uf.common.localization.overrides import XMLOverrider as JavaXMLOverrider
from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType
def override(name, loctype):
"""
Takes a name (filename and localization path) and the localization type and finds the
file and overrides it using the Java overrider, and then takes that value and returns
a dictionary
Args:
name : the name and path of the file in localization
loctype : a string representation of the localization type
Returns:
a dictionary representing the XML
"""
# call into the Java XMLOverrider class which will do the combining for us!
configurationNode = JavaXMLOverrider.override(LocalizationType.valueOf(loctype), name)
finalDict = _internalOverride(configurationNode)
return finalDict
def _internalOverride(configurationNode):
"""
Takes a configuration node from java and returns a dictionary of dictionaries corresponding to an XML file
Args:
configurationNode : the ConfigurationNode from Java
Returns:
a dictionary of dictionaries (key is the xml tag, value is its children or the value)
"""
theDict = dict()
for child in configurationNode.getChildren() :
# if there are children, then we can't just make this a value, so it needs to be a dict
if child.getChildrenCount() > 0 :
d = dict()
theDict[child.getName()] = _internalOverride(child, d)
else :
# if this key is already in the dictionary, add to the list if there is one, or make a new one
if theDict.has_key(child.getName()) :
if isinstance(theDict.__getitem__(child.getName()), list) :
theDict.__getitem__(child.getName()).append(child.getValue())
else :
l = list()
l.append(theDict.__getitem__(child.getName()))
l.append(str(child.getValue()))
theDict[child.getName()] = l
else :
theDict[child.getName()] = str(child.getValue())
return theDict

View file

@ -8,11 +8,13 @@ Require-Bundle: org.apache.commons.lang,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.comm;bundle-version="1.0.0",
com.raytheon.uf.common.auth,
com.raytheon.uf.common.status;bundle-version="1.12.1174"
com.raytheon.uf.common.status;bundle-version="1.12.1174",
org.apache.commons.configuration;bundle-version="1.6.0"
Eclipse-BuddyPolicy: registered, ext, global
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.common.localization,
com.raytheon.uf.common.localization.exception,
com.raytheon.uf.common.localization.msgs,
com.raytheon.uf.common.localization.overrides,
com.raytheon.uf.common.localization.stream
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

View file

@ -0,0 +1,141 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.localization.overrides;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.configuration.CombinedConfiguration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.NodeCombiner;
import org.apache.commons.configuration.tree.OverrideCombiner;
import com.raytheon.uf.common.localization.IPathManager;
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.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Override a set of XML files incrementally.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 14, 2013 mnash Initial creation
*
* </pre>
*
* @author mnash
* @version 1.0
*/
public class XMLOverrider {
private static final IUFStatusHandler handler = UFStatus
.getHandler(XMLOverrider.class);
/**
* Takes the information needed to get a file from localization using an
* {@link IPathManager}, and then combines them and returns.
*
* @param type
* @param name
* @return
*/
public static CombinedConfiguration override(LocalizationType type,
String name) {
IPathManager manager = PathManagerFactory.getPathManager();
Map<LocalizationLevel, LocalizationFile> mapFiles = manager
.getTieredLocalizationFile(type, name);
List<File> files = new ArrayList<File>();
for (LocalizationLevel level : manager.getAvailableLevels()) {
files.add(mapFiles.get(level).getFile());
}
return override(files.toArray(new File[files.size()]));
}
/**
* Takes an array of {@link LocalizationFile} and returns a combined version
* of them.
*
* @param lFiles
* @return
*/
public static CombinedConfiguration override(LocalizationFile... lFiles) {
File[] files = convertToFiles(lFiles);
return override(files);
}
/**
* Provide the override functionality for XML. This takes the XML files and
* integrates them together.
*/
public static CombinedConfiguration override(File... files) {
NodeCombiner combiner = new OverrideCombiner();
// lowest level first
XMLConfiguration[] configurations = new XMLConfiguration[files.length];
for (int i = 0; i < files.length; i++) {
try {
configurations[i] = new XMLConfiguration(files[i]);
} catch (ConfigurationException e) {
handler.handle(Priority.ERROR,
"Unable to make a new XML configuration", e);
}
}
CombinedConfiguration combinedConfiguration = new CombinedConfiguration(
combiner);
combinedConfiguration.setForceReloadCheck(true);
// loop through each xml configuration
for (XMLConfiguration config : configurations) {
combinedConfiguration.addConfiguration(config);
}
return combinedConfiguration;
}
/**
* Converts localization files to files for use later
*
* @param lFiles
* @return
*/
private static File[] convertToFiles(LocalizationFile[] lFiles) {
File[] files = new File[lFiles.length];
for (int i = 0; i < files.length; i++) {
File file = lFiles[i].getFile();
if (file != null && file.exists()) {
files[i] = file;
}
}
return files;
}
}