All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graphstream.util.Environment Maven / Gradle / Ivy

/*
 * This file is part of GraphStream .
 * 
 * GraphStream is a library whose purpose is to handle static or dynamic
 * graph, create them from scratch, file or any source and display them.
 * 
 * This program is free software distributed under the terms of two licenses, the
 * CeCILL-C license that fits European law, and the GNU Lesser General Public
 * License. You can  use, modify and/ or redistribute the software under the terms
 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 * URL  or under the terms of the GNU LGPL as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
 */

/**
 * @since 2011-07-22
 * 
 * @author Guilhelm Savin 
 * @author Richard O. Legendi 
 * @author Alex Bowen 
 * @author Hicham Brahimi 
 */
package org.graphstream.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Representation of a set of parameters.
 * 
 * 

* The environment class mimics the environment variables available in any shell * using a hash map of keys/values, the key being the variables names, excepted * here they are called parameters. *

* *

* In addition, this class provides facilities to: *

    *
  • Read a parameter file and set the parameters from this file;
  • *
  • Write a parameter file from the parameter of this environment;
  • *
  • Parse the command line and get parameters from it;
  • *
  • Take a class as argument and set all its fields having the same name as * parameters in this class;
  • *
*

* *

* As in any shell, most of the time, the environment is global and accessible * from any part of the system. Here a singleton instance of this class is * created and accessible from anywhere in the JVM using the * {@link #getGlobalEnvironment()} method (indeed the singleton instance is * created at its first access). However, it is still possible to create a * private instance of this class for use in a specific part of a program. *

* *

* To read a file of parameters, simply call the * {@link #readParameterFile(String)} method. In the same way, to write a set of * parameters to a file, call the {@link #writeParameterFile(String)} method. * The format of the parameter file is given in the description of these * methods. *

* *

* To read parameters from he command line, call the * {@link #readCommandLine(String[])} or * {@link #readCommandLine(String[], Collection)} methods. These methods expect * a format for the command line that is described in there respective * documentations. *

* *

* It is also possible to setup automatically the fields of an arbitrary object, * provided these fields have name that match parameters in this environment. To * do this call the {@link #initializeFieldsOf(Object)} method passing the * object to initialise as argument. The object to setup must provide methods of * the form "setThing(Type)" where "Thing" or "thing" is the name of the field * to set and "Type" is one of "int", "long", "float", "double", "String" and * "boolean". For the boolean type, the accepted values meaning true are "true", * "on", "1", and "yes", all other value are considered as false. *

* * TODO: how (or when) does the default configuration file is read? TODO: how to * handle parameters that cannot be setup in the * {@link #initializeFieldsOf(Object)}? * * @author Frédéric Guinand * @author Yoann Pigné * @author Antoine Dutot * @version 1.0 (jdk 1.5) */ public class Environment implements Cloneable { private static final Logger logger = Logger.getLogger(Environment.class.getSimpleName()); // ---------- Attributes ----------- /** * Name of the configuration file. Default is "config" */ protected String configFileName = "config"; /** * Has the configuration file been read yet?. */ protected boolean configFileRead = false; /** * Set of parameters. This is a hash table and not a hashmap since several * thread may access this class at once. */ protected Hashtable parameters = new Hashtable(); /** * When locked the environment parameters value still can be changed but it is * no more possible to add new parameters. */ protected boolean locked; // --------- Static attributes --------- /** * Global environment for the whole JVM. This global environment is available * and editable from everywhere. It is create as soon as the * {@link #getGlobalEnvironment()} static method is called if this field was not * yet initialized by any other mean. * * @see #getGlobalEnvironment() */ public static Environment GLOBAL_ENV; // --------- Static methods ----------- /** * Access to the global shared environment for the whole JVM. This method allows * to access a shared environment, that can be read and written from anywhere. * * @return A singleton instance of the global environment. */ public static Environment getGlobalEnvironment() { if (GLOBAL_ENV == null) GLOBAL_ENV = new Environment(); return GLOBAL_ENV; } // --------- Methods ------------- /** * Is the environment locked?. * * @return True if the environment is locked. * @see #lockEnvironment(boolean) */ public boolean isLocked() { return locked; } /** * Access to a parameter in the environment. * * @param parameter * The parameter name. * @return The parameter value (empty string if not set). */ public String getParameter(String parameter) { String p = parameters.get(parameter); return (p == null) ? "" : p; } /** * True if the given paramter exist. * * @param parameter * The parameter name. * @return True if the given paramter name points to a value. */ public boolean hasParameter(String parameter) { return (parameters.get(parameter) != null); } /** * Check a parameter expected to be of boolean type. This method returns "true" * if the parameter exists and has a value that is "1", "true", "on" or "yes" * (with any possible combination of upper or lower-case letters). For any other * values of the parameter or if the parameter does not exist in the * environment, "false" is returned. * * @param parameter * The parameter name. * @return True if the parameter value means "true", false for any other value * or if the parameter does not exist. * @see #getBooleanParameteri(String) */ public boolean getBooleanParameter(String parameter) { int val = getBooleanParameteri(parameter); return (val == 1); } /** * Check a parameter expected to be of boolean type. This method returns the * value 1 if the parameter has value "1", "true", "on", "yes" (the case does * not matter). Else it returns 0. To account the case of non-existing * parameters, this method returns -1 if the given parameter does not exist. * * @param parameter * The parameter name. * @return 1 if the parameter value means "true", 0 if it has any other value, * or -1 if it does not exist. * @see #getBooleanParameter(String) */ public int getBooleanParameteri(String parameter) { String p = parameters.get(parameter); if (p != null) { p = p.toLowerCase(); if (p.equals("1")) return 1; if (p.equals("true")) return 1; if (p.equals("on")) return 1; if (p.equals("yes")) return 1; return 0; } return -1; } /** * Get the value of a parameter that is expected to be a number. If the * parameter does not exist or is not a number, 0 is returned. * * @param parameter * The parameter name. * @return The numeric value of the parameter. 0 if the parameter does not exist * or is not a number. */ public double getNumberParameter(String parameter) { String p = parameters.get(parameter); if (p != null) { try { return Double.parseDouble(p); } catch (NumberFormatException e) { return 0; } } return 0; } /** * Returns the number of parameters found in the configuration file. * * @return The number of parameters found in the configuration file. */ public int getParameterCount() { return parameters.size(); } /** * Set of all parameter names. * * @return A set of all the names identifying parameters in this environment. */ public Set getParametersKeySet() { return parameters.keySet(); } /** * Generate a new Environment object with a deep copy of the elements this * object. * * @return An Environment object identical to this one */ @Override public Environment clone() { Environment e = new Environment(); e.configFileName = configFileName; e.configFileRead = configFileRead; e.locked = locked; for (String key : parameters.keySet()) { e.parameters.put(key, parameters.get(key)); } return e; } /** * Set the value of a parameter. If the parameter already exists its old value * is overwritten. This works only if the environment is not locked. * * @param parameter * The parameter name. * @param value * The new parameter value. * @see #isLocked() * @see #lockEnvironment(boolean) */ public void setParameter(String parameter, String value) { if (!locked) { parameters.put(parameter, value); } else { if (parameters.get(parameter) != null) parameters.put(parameter, value); } } /** * Disallow the addition of new parameters. The already declared parameters are * still modifiable, but no new parameter can be added. * * @param on * If true the environment is locked. */ public void lockEnvironment(boolean on) { locked = on; } /** * Initialize all the fields of the given object whose name correspond to * parameters of this environment. This works only if the object to initialize * provides methods that begins by "set". For example if the object provides a * method named "setThing(int value)", and if there is a parameter named "thing" * in this environment and its value is convertible to an integer, then the * method "setThing()" will be invoked on the object with the correct value. * * @see #initializeFieldsOf(Object, String[]) * @see #initializeFieldsOf(Object, Collection) * @param object * The object to initialize. */ public void initializeFieldsOf(Object object) { Method[] methods = object.getClass().getMethods(); for (Method method : methods) { if (method.getName().startsWith("set")) { Class types[] = method.getParameterTypes(); if (types.length == 1) { String name = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4); String value = parameters.get(name); if (value != null) { invokeSetMethod(object, method, types, name, value); } } } } } /** * Initialize all the fields of the given object that both appear in the given * field list and whose name correspond to parameters of this environment. See * the {@link #initializeFieldsOf(Object)} method description. * * @see #initializeFieldsOf(Object) * @see #initializeFieldsOf(Object, Collection) * @param object * The object to initialize. * @param fieldList * The name of the fields to initialize in the object. */ public void initializeFieldsOf(Object object, String... fieldList) { Method[] methods = object.getClass().getMethods(); HashSet names = new HashSet(); for (String s : fieldList) names.add(s); for (Method method : methods) { if (method.getName().startsWith("set")) { Class types[] = method.getParameterTypes(); if (types.length == 1) { String name = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4); if (names.contains(name)) { String value = parameters.get(name); if (value != null) { invokeSetMethod(object, method, types, name, value); } } } } } } /** * Initialize all the fields of the given object that both appear in the given * field list and whose name correspond to parameters of this environment. See * the {@link #initializeFieldsOf(Object)} method description. * * @see #initializeFieldsOf(Object) * @see #initializeFieldsOf(Object, String[]) * @param object * The object to initialize. * @param fieldList * The name of the fields to initialize in the object. */ protected void initializeFieldsOf(Object object, Collection fieldList) { Method[] methods = object.getClass().getMethods(); for (Method method : methods) { if (method.getName().startsWith("set")) { Class types[] = method.getParameterTypes(); if (types.length == 1) { String name = method.getName().substring(3).toLowerCase(); if (fieldList.contains(name)) { String value = parameters.get(name); if (value != null) { invokeSetMethod(object, method, types, name, value); } } } } } } protected void invokeSetMethod(Object object, Method method, Class types[], String name, String value) { try { // XXX a way to avoid this overlong and repetitive // list of setters ? if (types[0] == Long.TYPE) { try { long val = Long.parseLong(value); method.invoke(object, new Long(val)); } catch (NumberFormatException e) { logger.warning(String.format("cannot set '%s' to the value '%s', values is not a long%n", method.toString(), value)); } } else if (types[0] == Integer.TYPE) { try { int val = (int) Double.parseDouble(value); method.invoke(object, new Integer(val)); } catch (NumberFormatException e) { logger.warning(String.format("cannot set '%s' to the value '%s', values is not a int%n", method.toString(), value)); } } else if (types[0] == Double.TYPE) { try { double val = Double.parseDouble(value); method.invoke(object, new Double(val)); } catch (NumberFormatException e) { logger.warning(String.format("cannot set '%s' to the value '%s', values is not a double%n", method.toString(), value)); } } else if (types[0] == Float.TYPE) { try { float val = Float.parseFloat(value); method.invoke(object, new Float(val)); } catch (NumberFormatException e) { logger.warning(String.format("cannot set '%s' to the value '%s', values is not a float%n", method.toString(), value)); } } else if (types[0] == Boolean.TYPE) { try { boolean val = false; value = value.toLowerCase(); if (value.equals("1") || value.equals("true") || value.equals("yes") || value.equals("on")) val = true; method.invoke(object, new Boolean(val)); } catch (NumberFormatException e) { logger.warning(String.format("cannot set '%s' to the value '%s', values is not a boolean%n", method.toString(), value)); } } else if (types[0] == String.class) { method.invoke(object, value); } else { logger.warning( String.format("cannot match parameter '%s' and the method '%s'%n", value, method.toString())); } } catch (InvocationTargetException ite) { logger.warning(String.format("cannot invoke method '%s' : invocation targer error : %s%n", method.toString(), ite.getMessage())); } catch (IllegalAccessException iae) { logger.warning(String.format("cannot invoke method '%s' : illegal access error : %s%n", method.toString(), iae.getMessage())); } } /** * Print all parameters to the given stream. * * @param out * The output stream to use. */ public void printParameters(PrintStream out) { out.println(toString()); } /** * Print all parameters the stdout. */ public void printParameters() { printParameters(System.out); } @Override public String toString() { return parameters.toString(); } /** * Read the parameters from the given command line array. See the more complete * {@link #readCommandLine(String[], Collection)} method. * * @param args * The command line. */ public void readCommandLine(String[] args) { readCommandLine(args, null); } /** * Read the parameters from the given command line array. The expected format of * this array is the following: *
    *
  • a word beginning by a "-" is the parameter name (for example * "-param");
  • *
  • if this word is immediately followed by a "=" and another word, this word * is considered as its string value (for example "-param=aValue");
  • *
  • If the parameter name is not followed by "=", it is considered a boolean * option and its value is set to the string "true" (to set this to false simply * give the string "-param=false");
  • *
  • If a word is found on the command line without any preceding "-" but is * followed by a "=" and by another word, then it is considered as a key,value * brace
  • *
  • If a word is found on the command line without any preceding "-" and is * not followed by any "=", the it is considered to be a filename for a * configuration file. The method will try to open this file for reading. A * configuration file is composed of lines. Each line is composed of a brace * key/value separated by a "=". If a line starts with a "#", then it is * considered as a comment. Finally if no format is recognized the line is * inserted to the trashcan.
  • *
* * @param args * The command line. * @param trashcan * Will be filled by the set of unparsed strings (can be null if * these strings can be ignored). */ public void readCommandLine(String[] args, Collection trashcan) { for (String arg : args) { boolean startsWithMinus = arg.startsWith("-"); int equalPos = arg.indexOf('='); String value = "true"; if (equalPos >= 0) { value = arg.substring(equalPos + 1); if (startsWithMinus) { arg = arg.substring(1, equalPos); } else { arg = arg.substring(0, equalPos); } parameters.put(arg, value); } else { if (startsWithMinus) { arg = arg.substring(1); parameters.put(arg, value); } else { readConfigFile(arg, trashcan); } } } } /** * Internal method that reads a configuration file. */ protected void readConfigFile(String filename, Collection trashcan) { BufferedReader br; int count = 0; try { br = new BufferedReader(new FileReader(filename)); String str; while ((str = br.readLine()) != null) { count++; if (str.length() > 0 && !str.substring(0, 1).equals("#")) { String[] val = str.split("="); if (val.length != 2) { if (val.length == 1) { parameters.put(val[0].trim(), "true"); } else { logger.warning(String.format( "Something is wrong with the configuration file \"%s\"near line %d :\n %s", filename, count, str)); if (trashcan != null) { trashcan.add(str); } } } else { String s0 = val[0].trim(); String s1 = val[1].trim(); parameters.put(s0, s1); } } } } catch (FileNotFoundException fnfe) { System.err.printf("Tried to open \"%s\" as a config file: file not found.%n", filename); if (trashcan != null) { trashcan.add(filename); } } catch (IOException ioe) { ioe.printStackTrace(); System.exit(0); } } /** * Save the curent parameters to a file. * * @param fileName * Name of the file to save the config in. * @throws IOException * For any output error on the given file name. */ public void writeParameterFile(String fileName) throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter(fileName)); Set ks = parameters.keySet(); for (String key : ks) { bw.write(key + " = " + parameters.get(key)); bw.newLine(); } bw.close(); } /** * Read the default configuration file. Once this file has been correctly * parsed, the {@link #configFileRead} boolean is set to true. * * @see #configFileName */ protected void readConfigurationFile() { try { readParameterFile(configFileName); configFileRead = true; } catch (IOException ioe) { logger.log(Level.WARNING, String.format("%-5s : %s : %s\n", "Warning", "Environment", "Something wrong while reading the configuration file."), ioe); } } /** * Read a parameter file. The format of this file is as follows: *
    *
  • Each line contains a parameter setting or a comment;
  • *
  • Lines beginning by a "#" are considered comments (be careful, a "#" in * the middle of a line is not a comment);
  • *
  • parameters settings are of the form "name=value", spaces are allowed, but * space before and after the parameter name of value will be stripped.
  • *
* * @param fileName * Name of the parameter file to read. * @throws IOException * For any error with the given parameter file name. */ public void readParameterFile(String fileName) throws IOException { BufferedReader br; int count = 0; br = new BufferedReader(new FileReader(fileName)); String str; while ((str = br.readLine()) != null) { count++; if (str.length() > 0 && !str.startsWith("#")) { String[] val = str.split("="); if (val.length != 2) { logger.warning(String.format("%-5s : %s : %s\n", "Warn", "Environment", "Something is wrong in your configuration file near line " + count + " : \n" + Arrays.toString(val))); } else { String s0 = val[0].trim(); String s1 = val[1].trim(); setParameter(s0, s1); } } } br.close(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy