// ********************************************************************** // // <copyright> // // BBN Technologies // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // </copyright> // ********************************************************************** // // $Source: // /cvs/distapps/openmap/src/openmap/com/bbn/openmap/util/PropUtils.java,v // $ // $RCSfile: PropUtils.java,v $ // $Revision: 1.16 $ // $Date: 2008/09/26 12:07:56 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.util; /* Java Core */ import java.awt.Color; import java.awt.Paint; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.Properties; import java.util.StringTokenizer; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFileChooser; import com.bbn.openmap.Environment; import com.bbn.openmap.I18n; import com.bbn.openmap.Layer; import com.bbn.openmap.PropertyConsumer; public class PropUtils { public static Logger logger = Logger.getLogger("com.bbn.openmap.util.PropUtils"); /** * Parse a list of marker names from a space separated list within a String. * <p> * * @param markerList a string containing a space delimited list of marker * names. * @return Vector of marker names. */ public static Vector<String> parseSpacedMarkers(String markerList) { return parseMarkers(markerList, " "); } /** * Parse a list of marker names from a space separated list within a String. * <p> * * @param markerList a string containing a list of things to be parsed. * @param delim the list of tokens to look for which separate the list * elements. * @return Vector of marker names. */ public static Vector<String> parseMarkers(String markerList, String delim) { Vector<String> vector = null; if (markerList == null) { logger.fine("marker list null!"); return new Vector<String>(0); } if (logger.isLoggable(Level.FINE)) { logger.fine("parsing marker list |" + markerList + "|"); } // First, get rid of the quotation marks; markerList = markerList.replace('\"', '\0'); // Next, tokenize the space delimited string StringTokenizer tokens = new StringTokenizer(markerList, delim); vector = new Vector<String>(tokens.countTokens()); while (tokens.hasMoreTokens()) { String name = tokens.nextToken().trim(); vector.addElement(name); } return vector; } /** * A string used in marker names for property editors, when a custom editor * used by an Inspector can set several top-level properties. */ public final static String DUMMY_MARKER_NAME = "DUMMY_MARKER_NAME"; /** Borrowed from Properties.java */ public static final String keyValueSeparators = "=: \t\r\n\f"; /** Borrowed from Properties.java */ public static final String strictKeyValueSeparators = "=:"; /** Borrowed from Properties.java */ public static final String whiteSpaceChars = " \t\r\n\f"; /** As defined in the OGC Web Mapping Test bed. */ public static final String propertySeparators = "&"; /** * Take a property list, defined in a single string, and return a Properties * object. The properties, as key-value pairs, are separated by another type * of symbol. In this method, the key-values are assumed to be separated * from other key-value pairs by PropUtils.propertySeparators String * characters, and each key is separated from its value by any character in * the PropUtils.keyValueSeparators list. * * @param list the properties list string. * @return Properties object containing keys and values. * @throws PropertyStringFormatException if a key doesn't have a value. */ public static Properties parsePropertyList(String list) throws PropertyStringFormatException { return parsePropertyList(list, propertySeparators, keyValueSeparators); } /** * Take a property list, defined in a single string, and return a Properties * object. The properties, as key-value pairs, are separated by another type * of symbol. * * @param list the properties list string. * @return Properties object containing keys and values. * @param propertySeparators the key-values are assumed to be separated from * other key-value pairs by any character in this String. * @param keyValueSeparators each key is separated from its value by any * character in this String. * @throws PropertyStringFormatException if a key doesn't have a value. */ public static Properties parsePropertyList(String list, String propertySeparators, String keyValueSeparators) throws PropertyStringFormatException { Properties props = new Properties(); Vector<String> keyValuePairs = parseMarkers(list, propertySeparators); for (int i = 0; i < keyValuePairs.size(); i++) { // Next, tokenize the space delimited string StringTokenizer tokens = new StringTokenizer(keyValuePairs.elementAt(i), keyValueSeparators); try { String key = tokens.nextToken().trim(); String value = tokens.nextToken().trim(); props.put(key, value); } catch (NoSuchElementException nsee) { throw new PropertyStringFormatException(list); } } return props; } /** * Copy the contents from one properties object to another. * * @param from the source Properties object. * @param to the destination Properties object. */ public static void copyProperties(Properties from, Properties to) { Enumeration<Object> keys = from.keys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); to.put(key, from.getProperty(key)); } } /** * Load the named file from the named directory into the given * <code>Properties</code> instance. If the file is not found a warning is * issued. If an IOException occurs, a fatal error is printed. * * @param props the instance to receive the loaded properties * @param dir the directory where the properties file resides * @param file the name of the file * @return true if the properties file exists and was loaded. */ public static boolean loadProperties(Properties props, String dir, String file) { File propsFile = new File(dir, file); try { InputStream propsStream = new FileInputStream(propsFile); props.load(propsStream); if (logger.isLoggable(Level.FINE)) { logger.fine("Found " + propsFile); } return true; } catch (java.io.FileNotFoundException e) { if (logger.isLoggable(Level.FINE)) { logger.fine("File not found - \"" + propsFile + "\""); } } catch (java.io.IOException e) { logger.warning("Caught IO Exception reading \"" + propsFile + "\""); e.printStackTrace(); } catch (java.security.AccessControlException ace) { } return false; } /** * Loads properties from a java resource. This will load the named resource * identifier into the given properties instance. * * @param properties the Properties instance to receive the properties. * @param propsIn an InputStream to read properties from * @return true if the properties file exists and was loaded. */ public static boolean loadProperties(Properties properties, InputStream propsIn) { try { properties.load(propsIn); return true; } catch (java.io.IOException e) { if (logger.isLoggable(Level.FINE)) { logger.warning("Caught IOException loading properties from InputStream."); } return false; } } /** * A function that brings up a file chooser window in order to have the user * look for a valid Java properties file. * * @return properties object with selected file contents. */ public static Properties promptUserForProperties() { JFileChooser fileChooser = new JFileChooser(); int retvalue = fileChooser.showOpenDialog(null); Properties props = new Properties(); if (retvalue != JFileChooser.APPROVE_OPTION) { return props; } try { FileInputStream inputStream = new FileInputStream(fileChooser.getSelectedFile()); props.load(inputStream); return props; } catch (Exception ioe) { System.err.println("PropUtils.promptUserForProperties: Exception reading properties file."); System.err.println(ioe.getMessage()); ioe.printStackTrace(); return props; } } /** * It seems like every PropertyConsumer wrestles with having a prefix or * not. This method lets you just get the prefix with a period on the end * (for scoping purposes), or just returns an empty String. Either way, you * get a String you can slap on the beginning of your defined property names * to get a valid property based on what the prefix is. * * @param pc the PropertyConsumer to fetch from * @return an empty string if no prefix, or the prefix with a period at the * end */ public static String getScopedPropertyPrefix(PropertyConsumer pc) { return getScopedPropertyPrefix(pc.getPropertyPrefix()); } /** * Given the string, check if it's null. If it isn't, check to see if it * ends with a period, and do nothing if it does. If it doesn't end in a * period, add one, and then return that. The returned string should be good * for prepending to other properties. * * @param pre the string to check * @return an empty string or one that ends with a period */ public static String getScopedPropertyPrefix(String pre) { if (pre == null || pre.length() == 0) { return ""; } else if (pre.endsWith(".")) { return pre; } else { return pre + "."; } } /** * Should be called by a PropertyConsumer in the * getPropertiesInfo(Properties) method to create a property marker name for * a custom PropertyEditor that will modify several top-level properties, * i.e. the com.bbn.openmap.omGraphics.DrawingAttributesPropertyEditor. * * @param realComponentPropertyPrefix the top-level prefix that the * PropertyConsumer being set with the properties has. Can be null. * @param anyDesiredScoper an additional scoping mechanism if there are more * than one custom editors being used for a given getPropertyInfo * call. * @return The string that is used for a marker for a custom editor. */ public static String getDummyMarkerForPropertyInfo(String realComponentPropertyPrefix, String anyDesiredScoper) { return DUMMY_MARKER_NAME + (anyDesiredScoper != null ? anyDesiredScoper : "") + "." + (realComponentPropertyPrefix != null ? realComponentPropertyPrefix : ""); } /** * Should be used inside a * PropertyConsumerPropertyEditor.setProperties(String, Properties) method * to set the real property prefix. The PropertyConsumer that the Inspector * is looking at should use the getDummyMarker() call to create the marker * for the getPropertyInfor(Properties) call. * * @param possibleDummyMarker string to check for DUMMY_MARKER_NAME, * indicating that's a dummy * @return the encoded 'real' property prefix for the PropertyConsumer * embedded in the dummy marker, or the possibleDummyMarker if it's * not a dummy marker. */ public static String decodeDummyMarkerFromPropertyInfo(String possibleDummyMarker) { if (possibleDummyMarker != null && possibleDummyMarker.startsWith(DUMMY_MARKER_NAME)) { int lastDot = possibleDummyMarker.lastIndexOf("."); if (lastDot != -1) { possibleDummyMarker = possibleDummyMarker.substring(lastDot + 1); } } return possibleDummyMarker; } /** * It kills Properties to have null values set. You can wrap a property * value in this in PropertyConsumer.getProperties() to not worry about it. * * @param prop property value to be set in properties after this call * @return empty string if prop equals null, else returns what was passed in */ public static String unnull(Object prop) { if (prop == null) { return ""; } return prop.toString(); } /** * Takes a string of `;' separated paths and returns an array of parsed * strings. NOTE: this method currently doesn't support appropriate quoting * of the `;' character, although it probably should... * * @param p properties * @param propName the name of the property * @return Array of strings representing paths. */ public static String[] initPathsFromProperties(Properties p, String propName) { return initPathsFromProperties(p, propName, null); } /** * Takes a string of `;' separated paths and returns an array of parsed * strings. NOTE: this method currently doesn't support appropriate quoting * of the `;' character, although it probably should... * * @param p properties * @param propName the name of the property * @param defaultPaths the value of the paths to set if the property doesn't * exist, or if is doesn't contain anything. * @return Array of strings representing paths. */ public static String[] initPathsFromProperties(Properties p, String propName, String[] defaultPaths) { String[] ret = stringArrayFromProperties(p, propName, ";"); if (ret == null) { ret = defaultPaths; } return ret; } /** * Return the first letter of the property specified by propName. If that * value is null or has length of zero, the default char is returned. * * @param p properties to load from * @param propName property name * @param defaultValue default to use if property isn't found * @return first char from property, or default. */ public static char charFromProperties(Properties p, String propName, char defaultValue) { char ret = defaultValue; String charString = p.getProperty(propName); if (charString != null && charString.length() > 0) { return charString.charAt(0); } return ret; } /** * Gets an integer out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return integer value associated with the property. */ public static int intFromProperties(Properties p, String propName, int defaultValue) { int ret = defaultValue; String intString = p.getProperty(propName); if (intString != null) { try { ret = Integer.parseInt(intString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Gets an float out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return float value associated with the property. */ public static float floatFromProperties(Properties p, String propName, float defaultValue) { float ret = defaultValue; String floatString = p.getProperty(propName); if (floatString != null) { try { ret = Float.parseFloat(floatString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Gets an boolean out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return boolean value associated with the property. */ public static boolean booleanFromProperties(Properties p, String propName, boolean defaultValue) { boolean ret = defaultValue; String booleanString = p.getProperty(propName); if (booleanString != null) { ret = booleanString.trim().equalsIgnoreCase("true"); } return ret; } /** * Creates an object out of a property name. If anything fails, return null. * * @param p properties * @param propName name of class to instantiate. * @return null on failure, otherwise, a default constructed instance of the * class named in the property. */ public static Object objectFromProperties(Properties p, String propName) { Object ret = null; String objectName = p.getProperty(propName); if (objectName != null) { ret = ComponentFactory.create(objectName); } return ret; } /** * Takes a string of representing token separated properties and returns an * array of parsed strings. NOTE: this method currently doesn't support * appropriate quoting of the token, although it probably should... * * @param p properties * @param propName the name of the property * @param tok the characters separating the strings. * @return Array of strings between the tokens. */ public static String[] stringArrayFromProperties(Properties p, String propName, String tok) { String[] ret = null; String raw = p.getProperty(propName); if (raw != null && raw.length() > 0) { try { StringTokenizer token = new StringTokenizer(raw, tok); int numPaths = token.countTokens(); ret = new String[numPaths]; for (int i = 0; i < numPaths; i++) { ret[i] = token.nextToken(); } return ret; } catch (java.util.NoSuchElementException e) { e.printStackTrace(); } } return ret; } /** * Gets a double out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return double value associated with the property. */ public static double doubleFromProperties(Properties p, String propName, double defaultValue) { double ret = defaultValue; String doubleString = p.getProperty(propName); if (doubleString != null) { try { ret = Double.parseDouble(doubleString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Gets a long out of a properties object. Returns the default value if * something goes wrong. * * @param p properties * @param propName name of the property associated with the wanted value. * @param defaultValue what to return if the property name doesn't exist, or * if the value isn't a numerical value. * @return long value associated with the property. */ public static long longFromProperties(Properties p, String propName, long defaultValue) { long ret = defaultValue; String longString = p.getProperty(propName); if (longString != null) { try { ret = Long.parseLong(longString.trim()); } catch (NumberFormatException e) { ret = defaultValue; } } return ret; } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p properties * @param propName the name of the property * @param dfault color to use if the property value doesn't work * @return java.awt.Color * @exception NumberFormatException if the specified string cannot be * interpreted as a hexidecimal integer * @see ColorFactory#parseColorFromProperties(Properties, String, String, * boolean) */ public static Color parseColorFromProperties(Properties p, String propName, String dfault) throws NumberFormatException { return ColorFactory.parseColorFromProperties(p, propName, dfault, false); } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p properties * @param propName the name of the property * @param dfault color to use if the property value doesn't work * @param forceAlpha force using alpha value * @return java.awt.Color * @exception NumberFormatException if the specified string cannot be * interpreted as a hexidecimal integer * @see ColorFactory#parseColorFromProperties(Properties, String, String, * boolean) */ public static Color parseColorFromProperties(Properties p, String propName, String dfault, boolean forceAlpha) throws NumberFormatException { return ColorFactory.parseColorFromProperties(p, propName, dfault, forceAlpha); } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p properties * @param propName the name of the property * @param dfault color to use if the property value doesn't work * @return java.awt.Color * @see ColorFactory#parseColorFromProperties(Properties, String, String, * boolean) */ public static Paint parseColorFromProperties(Properties p, String propName, Paint dfault) { return ColorFactory.parseColorFromProperties(p, propName, dfault); } /** * Convert a string representing a 24/32bit hex color value into a Color * value. NOTE: * <ul> * <li>Only 24bit (RGB) java.awt.Color is supported on the JDK 1.1 platform. * <li>Both 24/32bit (ARGB) java.awt.Color is supported on the Java 2 * platform. * </ul> * * @param colorString the 24/32bit hex string value (ARGB) * @param forceAlpha force using alpha value * @return java.awt.Color (24bit RGB on JDK 1.1, 24/32bit ARGB on JDK1.2) * @exception NumberFormatException if the specified string cannot be * interpreted as a hexidecimal integer * @see ColorFactory#parseColor(String, boolean) */ public static Color parseColor(String colorString, boolean forceAlpha) throws NumberFormatException { return ColorFactory.parseColor(colorString, forceAlpha); } /** * Convert a string representing a 24/32bit hex color value into a Color * value. NOTE: * <ul> * <li>Only 24bit (RGB) java.awt.Color is supported on the JDK 1.1 platform. * <li>Both 24/32bit (ARGB) java.awt.Color is supported on the Java 2 * platform. * </ul> * * @param colorString the 24/32bit hex string value (ARGB) * @return java.awt.Color (24bit RGB on JDK 1.1, 24/32bit ARGB on JDK1.2) * @exception NumberFormatException if the specified string cannot be * interpreted as a hexidecimal integer * @see ColorFactory#parseColor(String, boolean) */ public static Color parseColor(String colorString) throws NumberFormatException { return ColorFactory.parseColor(colorString, false); } /** * Returns a string representing a color, properly buffered for zeros for * different alpha values. * * @param color the source Color * @return string for color with alpha values. */ public static String getProperty(Color color) { StringBuffer hexstring = new StringBuffer(Integer.toHexString(color.getRGB())); while (hexstring.length() < 8) { hexstring.insert(0, '0'); } return hexstring.toString(); } /** * Converts a properties object to an array of Strings. The resulting array * will consist of alternating key-value strings. * * @param props the properties object to convert. * @return an array of Strings representing key-value pairs. */ public static String[] getPropertiesAsStringArray(Properties props) { int size = props.size(); String[] ret = new String[size * 2]; // key and value int count = 0; Enumeration<?> things = props.propertyNames(); while (things.hasMoreElements()) { ret[count] = (String) things.nextElement(); ret[count + 1] = (String) props.getProperty(ret[count]); count += 2; } return ret; } /** * Returns a URL that names either a resource, a local file, or an internet * URL. Resources are checked for in the general classpath. * * @param name name of the resource, file or URL. * @throws java.net.MalformedURLException if there's a problem finding the * thingy * @return URL */ public static URL getResourceOrFileOrURL(String name) throws java.net.MalformedURLException { return getResourceOrFileOrURL(null, name); } /** * Returns a URL that names either a resource, a local file, or an internet * URL. * * @param askingClass the object asking for the URL. * @param name name of the resource, file or URL. * @throws java.net.MalformedURLException if there's a problem finding the * thingy * @return URL */ public static URL getResourceOrFileOrURL(Object askingClass, String name) throws java.net.MalformedURLException { return getResourceOrFileOrURL(askingClass.getClass(), name); } /** * Returns a URL that names either a resource, a local file, or an internet * URL. * * @param askingClass the class asking for the URL. Can be null. * @param name name of the resource, file or URL. * @throws java.net.MalformedURLException if there's a problem finding the * thingy * @return URL */ public static URL getResourceOrFileOrURL(Class<? extends Object> askingClass, String name) throws java.net.MalformedURLException { boolean DEBUG = logger.isLoggable(Level.FINE); if (name == null) { if (DEBUG) logger.fine("null file name"); return null; } URL retval = null; if (DEBUG) logger.fine("looking for " + name); if (askingClass != null) { // First see if we have a resource by that name if (DEBUG) logger.fine("checking as resource"); retval = askingClass.getResource(name); } if (retval == null) { // Check the general classpath... if (DEBUG) logger.fine("checking in general classpath"); retval = Thread.currentThread().getContextClassLoader().getResource(name); } // if (retval == null && !Environment.isApplet()) { // // Check the classpath plus the share directory, which may // // be in the openmap.jar file or in the development // // environment. // if (DEBUG) // logger.fine("checking with ClassLoader"); // retval = ClassLoader.getSystemResource("share/" + name); // } if (retval == null && Environment.isApplet()) { if (DEBUG) logger.fine("checking with URLClassLoader"); URL[] cba = new URL[1]; cba[0] = Environment.getApplet().getCodeBase(); URLClassLoader ucl = URLClassLoader.newInstance(cba); retval = ucl.getResource(name); } // If there was no resource by that name available if (retval == null) { if (DEBUG) logger.fine("not found as resource"); try { java.io.File file = new java.io.File(name); if (file.exists()) { retval = file.toURI().toURL(); if (DEBUG) logger.fine("found as file :)"); } else { // Otherwise treat it as a raw URL. if (DEBUG) logger.fine("Not a file, checking as URL"); retval = new URL(name); java.io.InputStream is = retval.openStream(); is.close(); if (DEBUG) logger.fine("OK as URL :)"); } } catch (java.io.IOException ioe) { retval = null; } catch (java.security.AccessControlException ace) { logger.warning("AccessControlException trying to access " + name); retval = null; } catch (Exception e) { logger.warning("caught exception " + e.getMessage()); retval = null; } } if (DEBUG) { if (retval != null) { logger.fine("Resource " + name + "=" + retval.toString()); } else { logger.fine("Resource " + name + " can't be found..."); } } return retval; } /** * Simple space saving implementation of common I18n Property Info setting. * * @param i18n i18n object to use to search for internationalized strings. * @param info the properties class being used to set information into. * @param classToSetFor class to use for i18n search. * @param propertyName property to set for. * @param label label to use for GUI (can be null if N/A). * @param tooltip tooltip to use for GUI (can be null if N/A). * @param editor editor class string to use for GUI (can be null if N/A). * @return Properties object passed in, or new one if null Properties passed * in. */ public static Properties setI18NPropertyInfo(I18n i18n, Properties info, Class<? extends Object> classToSetFor, String propertyName, String label, String tooltip, String editor) { if (info == null) { info = new Properties(); } if (i18n != null) { if (tooltip != null) { String internString = i18n.get(classToSetFor, propertyName, I18n.TOOLTIP, tooltip); info.put(propertyName, internString); } if (label != null) { String internString = i18n.get(classToSetFor, propertyName, label); info.put(propertyName + PropertyConsumer.LabelEditorProperty, internString); } if (editor != null) { info.put(propertyName + PropertyConsumer.ScopedEditorProperty, editor); } } return info; } /** * If the layer has a dataPathPrefix attribute set, that attribute value can * be used as a common path to prepend to any layer's data path. This allows * you to set a relative path to files in the layer's properties, and then * prepend the absolute path later at runtime. * <p> * * The dataPathPrefix can be set in the properties for a layer, where it is * pushed to the layer's attributes in Layer.setProperties(). This method is * intended for layers that have sub-layers, so the parent layer can set * that dataPathPrefix property on it's children automatically. * * @param layer the parent layer to retrieve the attribute from * @param props the properties that define the children, and also passed to * them for configuration * @param layerListProperty the property for the parent that lists the * marker names for the children */ public static void putDataPrefixToLayerList(Layer layer, Properties props, String layerListProperty) { String dataPrefix = (String) layer.getAttribute(Layer.DataPathPrefixProperty); if (dataPrefix != null && dataPrefix.length() > 0) { putDataPrefixToLayerList(dataPrefix, props, layerListProperty); } } /** * If the layer has a dataPathPrefix attribute set, that attribute value can * be used as a common path to prepend to any layer's data path. This allows * you to set a relative path to files in the layer's properties, and then * prepend the absolute path later at runtime. * <p> * * The dataPathPrefix can be set in the properties for a layer, where it is * pushed to the layer's attributes in Layer.setProperties(). This method is * intended for layers that have sub-layers, so the parent layer can set * that dataPathPrefix property on it's children automatically. * * @param dataPrefix the dataPathPrefix retrieved from the parent attributes * @param props the properties that define the children, and also passed to * them for configuration * @param layerListProperty the property for the parent that lists the * marker names for the children */ public static void putDataPrefixToLayerList(String dataPrefix, Properties props, String layerListProperty) { Vector<String> layersValue = parseSpacedMarkers(props.getProperty(layerListProperty)); for (Iterator<String> it = layersValue.iterator(); it.hasNext();) { String markerName = getScopedPropertyPrefix(it.next()); props.setProperty(markerName + Layer.DataPathPrefixProperty, dataPrefix); } } /** * Get a List of Objects defined by marker names listed in a property. If * the objects are PropertyConsumers, they will be given the properties and * their scoped property prefix so they can configure themselves. * * <pre> * * listProperty=markername1 markername2 markername3 * markername1.definingProperty=classname1 * markername2.definingProperty=classname2 * markername3.definingProperty=classname3 * * </pre> * * @param p Properties object containing all properties * @param markerListProperty listProperty in example above * @param definingProperty definingProperty in example above, scoped * property when combined with marker name to define the class that * should be created for an object. * @return List of objects created from properties */ public static List<?> objectsFromProperties(Properties p, String markerListProperty, String definingProperty) { return objectsFromScopedProperties(p, markerListProperty, definingProperty, null); // // String markerList = p.getProperty(markerListProperty); // List<Object> ret = new LinkedList<Object>(); // // if (markerList != null) { // Vector<String> markerNames = parseSpacedMarkers(markerList); // for (String markerName : markerNames) { // String classname = p.getProperty(markerName + "." // + definingProperty); // if (classname != null) { // Object obj = ComponentFactory.create(classname, markerName, // p); // // if (obj != null) { // ret.add(obj); // } // } // } // // } // // return ret; } /** * Get a List of Objects defined by marker names listed in a property, when * this list property has been scoped by a parent object definition. If the * objects are PropertyConsumers, they will be given the properties and * their scoped property prefix so they can configure themselves. * * <pre> * * parentMarker.listProperty=markername1 markername2 markername3 * parentMarker.markername1.definingProperty=classname1 * parentMarker.markername2.definingProperty=classname2 * parentMarker.markername3.definingProperty=classname3 * * </pre> * * @param p Properties object containing all properties * @param markerListProperty listProperty in example above * @param definingProperty definingProperty in example above, scoped * property when combined with marker name to define the class that * should be created for an object. * @param parentMarker the string that should be used as the prefix for the * defining property * @return List of objects created from properties, where properties are * scoped for each object. */ public static List<?> objectsFromScopedProperties(Properties p, String markerListProperty, String definingProperty, String parentMarker) { String markerList = p.getProperty(markerListProperty); List<Object> ret = new LinkedList<Object>(); parentMarker = PropUtils.getScopedPropertyPrefix(parentMarker); if (markerList != null) { Vector<String> markerNames = parseSpacedMarkers(markerList); for (String markerName : markerNames) { String classname = p.getProperty(parentMarker + markerName + "." + definingProperty); if (classname != null) { Object obj = ComponentFactory.create(classname, markerName, p); if (obj != null) { ret.add(obj); } } } } return ret; } /** * Add the object property value to properties if it's not null or empty, * which assumes it should be set to the default value. * * @param props Properties to write to * @param propertyName the scoped property to enter value under * @param value the object to get property from - toString() will be called * if not null. * @param <T> class for property */ public static <T extends Object> void putIfNotDefault(Properties props, String propertyName, T value) { putIfNotDefault(props, propertyName, value, null); } /** * Add the object property value to properties if it's not null or default * value. * * @param props Properties to write to * @param propertyName the scoped property to enter value under * @param value the object to get property from - toString() will be called * if not null. * @param def the default value of the property. If not null and value not * null, toString().equals() will be used to determine equality. If * not equal, then value will be set in props. * @param <T> matching class types for the property */ public static <T extends Object> void putIfNotDefault(Properties props, String propertyName, T value, T def) { if (value != null) { String valString = value.toString().trim(); if (def == null || (def != null && !def.toString().trim().equals(valString))) { // empty property strings are a pain... if (valString.length() != 0) { props.put(propertyName, valString); } } } } }