Issue #1870 add Python and XML Incremental Override, implemented for both Java

and Python

Change-Id: I293b6abcdffbd2cef35e9b986362113186583c55

Former-commit-id: 27f86d4c39ce8b8e708408511c820a5dd765e4cb
This commit is contained in:
Matt Nash 2013-05-02 13:39:55 -05:00
parent da7a648a61
commit 288bd3b02c
6 changed files with 395 additions and 46 deletions

View file

@ -1,4 +1,4 @@
## # #
# This software was developed and / or modified by Raytheon Company, # This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government. # pursuant to Contract DG133W-05-CQ-1067 with the US Government.
# #
@ -16,7 +16,7 @@
# #
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for # See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information. # further licensing information.
## # #
from java.lang import Integer, Float, Long, Boolean, String from java.lang import Integer, Float, Long, Boolean, String
@ -86,6 +86,9 @@ def javaMapToPyDict(javaMap, customConverter=None):
return pyDict return pyDict
def pyDictToJavaMap(pyDict): def pyDictToJavaMap(pyDict):
if pyDict is None :
return None
if isinstance(pyDict, OrderedDict): if isinstance(pyDict, OrderedDict):
jmap = LinkedHashMap() jmap = LinkedHashMap()
else: else:
@ -159,4 +162,3 @@ class JavaWrapperClass(object):
def toJavaObj(self): def toJavaObj(self):
raise NotImplementedError, "Subclasses must override this method." raise NotImplementedError, "Subclasses must override this method."

View file

@ -77,11 +77,13 @@ class PathManager(IPathManager.IPathManager):
@summary: Returns the localization levels available for the file given @summary: Returns the localization levels available for the file given
''' '''
jtype = self._convertType(loctype) jtype = self._convertType(loctype)
jMap = JUtil.javaMapToPyDict(self.jpathManager.getTieredLocalizationFile(jtype, name)) jMap = self.jpathManager.getTieredLocalizationFile(jtype, name)
iterator = jMap.entrySet().iterator()
vals = dict() vals = dict()
for level in jMap: while iterator.hasNext() :
jlevel = self._convertLevel(level) nextValue = iterator.next()
vals[jlevel.name()] = LocalizationFile(jMap.get(level)) # 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 return vals
def listFiles(self, name, extensions, recursive, filesOnly, loctype=None, loclevel=None, locname=None): def listFiles(self, name, extensions, recursive, filesOnly, loctype=None, loclevel=None, locname=None):

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,
com.raytheon.uf.common.serialization.comm;bundle-version="1.0.0", com.raytheon.uf.common.serialization.comm;bundle-version="1.0.0",
com.raytheon.uf.common.auth, 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-BuddyPolicy: registered, ext, global
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Export-Package: com.raytheon.uf.common.localization, Export-Package: com.raytheon.uf.common.localization,
com.raytheon.uf.common.localization.exception, com.raytheon.uf.common.localization.exception,
com.raytheon.uf.common.localization.msgs, com.raytheon.uf.common.localization.msgs,
com.raytheon.uf.common.localization.overrides,
com.raytheon.uf.common.localization.stream com.raytheon.uf.common.localization.stream
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 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;
}
}