package vroom.common.utilities.params; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import vroom.common.utilities.SortedProperties; import vroom.common.utilities.Utilities; import vroom.common.utilities.logging.Logging; /** * Creation date: Feb 25, 2010 - 3:13:09 PM<br/> * <code>GlobalParametersPersistenceDelegate</code> is a delegate class used to write and read {@link GlobalParameters} * instance to and from a {@link Properties property file}. * * @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a * href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a * href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a> * @version 1.0 */ public class ParametersFilePersistenceDelegate implements IParametersPersistenceDelegate<File> { public static final String CFG_PARENT = "CFG_PARENT"; @Override public void loadParameters(GlobalParameters params, File file) throws Exception { // Loading the properties file Properties properties = new Properties(); FileInputStream sf = new FileInputStream(file); properties.load(sf); // Check for a parent configuration file Object parent = properties.get(CFG_PARENT); if (parent != null && parent instanceof String) { File parentCfg = new File((String) parent); if (!parentCfg.equals(file)) params.loadParameters(parentCfg); } Logging.getSetupLogger().info( "ParametersFilePersistenceDelegate.loadParameters: loading parameters from file %s", file); // Get the keys from the property file Set<String> propKeys = properties.stringPropertyNames(); // Get the registered keys from the parameters Set<ParameterKey<?>> registeredKeys = params.getRegisteredKeys(); // Registered keys map HashMap<String, ParameterKey<?>> regKeysMap = new HashMap<String, ParameterKey<?>>(); for (ParameterKey<?> regKey : registeredKeys) { regKeysMap.put(regKey.getName(), regKey); } // Add the properties content for (String k : propKeys) { if (regKeysMap.containsKey(k)) { ParameterKey<?> pK = regKeysMap.get(k); setRegisteredParameter(params, pK, properties.getProperty(k)); } else { setUnregisteredParameter(params, k, properties.getProperty(k)); } } sf.close(); } /** * Handling of registered keys * * @param params * @param key * @param value * @throws ClassNotFoundException */ protected void setRegisteredParameter(GlobalParameters params, ParameterKey<?> key, String value) throws ClassNotFoundException { params.setNoCheck(key, castProperty(key, value)); } /** * Special handling of keys that have not been found as registered * * @param params * the parameters being loaded * @param key * the unregistered key * @param value * the associated value in the property file * @throws Exception */ protected void setUnregisteredParameter(GlobalParameters params, String key, String value) throws Exception { params.setNoCheck(new ParameterKey<Object>(key, Object.class), value); } /** * Try to cast <code>value</code> to the correct type * * @param <T> * @param key * @param value * @return * @throws ClassNotFoundException */ @SuppressWarnings("unchecked") public static Object castProperty(ParameterKey<?> key, String value) throws ClassNotFoundException { if (key == null || key.getType() == null) return value; else if (String.class.isAssignableFrom(key.getType())) { return value; } else if (Boolean.class.isAssignableFrom(key.getType())) { return Boolean.valueOf(value); } else if (Integer.class.isAssignableFrom(key.getType())) { return Integer.valueOf(value); } else if (Long.class.isAssignableFrom(key.getType())) { return Long.valueOf(value); } else if (Double.class.isAssignableFrom(key.getType())) { return Double.valueOf(value); } else if (Float.class.isAssignableFrom(key.getType())) { return Float.valueOf(value); } else if (File.class.isAssignableFrom(key.getType())) { return new File(value); } else if (key instanceof ClassParameterKey<?>) { return Class.forName(value); } else if (key.getType().isArray()) { Class<?> compType = key.getType().getComponentType(); if (int.class.isAssignableFrom(compType)) { return Utilities.toIntArray(value); } else if (double.class.isAssignableFrom(compType)) { return Utilities.toDoubleArray(value); } else if (long.class.isAssignableFrom(compType)) { return Utilities.toLongArray(value); } else { throw new UnsupportedOperationException(String.format("Value for key %s could not be cast (%s)", key, value)); } } else if (key.getType().isEnum()) { @SuppressWarnings("rawtypes") Class<? extends Enum> enumType = (Class<? extends Enum>) key.getType(); return Enum.valueOf(enumType, value); } // else { // throw new UnsupportedOperationException( // String.format("Value for key %s could not be cast (%s)", key, value)); // } return value; } @Override public void saveParameters(GlobalParameters params, File file, boolean omitDefaults) throws IOException { SortedProperties settings = new SortedProperties(); for (Entry<ParameterKey<?>, Object> e : params.getParametersMapping()) { if (e.getValue() != null && (!omitDefaults || !Utilities.equal(e.getKey().getDefaultValue(), e.getValue()))) { if (e.getKey() instanceof ClassParameterKey<?>) { settings.put(e.getKey().getName(), ((Class<?>) e.getValue()).getCanonicalName()); } else if (e.getValue().getClass().isArray()) { settings.put(e.getKey().getName(), Utilities.toShortString(e.getValue())); } else { settings.put(e.getKey().getName(), e.getValue().toString()); } } } FileOutputStream sf = new FileOutputStream(file); settings.store( sf, String.format("Created by %s \nDate: %s", this.getClass().getName(), new Date(System.currentTimeMillis()))); sf.flush(); sf.close(); Logging.getSetupLogger().info("ParametersFilePersistenceDelegate.loadParameters: parameters saved to file %s", file); } }