it.unimi.dsi.util.Properties.java Source code

Java tutorial

Introduction

Here is the source code for it.unimi.dsi.util.Properties.java

Source

package it.unimi.dsi.util;

/*       
 * DSI utilities
 *
 * Copyright (C) 2005-2009 Sebastiano Vigna 
 *
 *  This library is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Lesser General Public License as published by the Free
 *  Software Foundation; either version 2.1 of the License, or (at your option)
 *  any later version.
 *
 *  This library 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConfigurationMap;
import org.apache.commons.configuration.ConfigurationUtils;
import org.apache.commons.configuration.PropertiesConfiguration;

/** An extension of {@link org.apache.commons.configuration.PropertiesConfiguration}
 * providing setters for primitive types, a simpler {@linkplain #save(CharSequence) way to save preferences}
 * and transparent handling of {@link java.lang.Enum} lowercased keys.
 * 
 * <p>All accessors defined in {@link org.apache.commons.configuration.PropertiesConfiguration} have a
 * polymorphic counterpart taking an {@link java.lang.Enum} instead of a string: {@link java.lang.Enum#name()}
 * <strong>and {@link java.lang.String#toLowerCase()}</strong> are applied before 
 * delegating to the corresponding string-based method. (This apparently wierd choice is due to the need to
 * accommodate the upper-case standard for {@link java.lang.Enum} elements and the lower-case standard
 * for property keys.) 
 * 
 * <p>Additionally, instances of this class can be serialised.
 */
public class Properties extends PropertiesConfiguration implements Serializable {

    private static final long serialVersionUID = 1L;

    public Properties() {
    }

    public Properties(final String filename) throws ConfigurationException {
        super(filename);
    }

    public Properties(final File file) throws ConfigurationException {
        super(file);
    }

    public Properties(final URL url) throws ConfigurationException {
        super(url);
    }

    /** Saves the configuration to the specified file.
     * 
     * @param filename a file name.
     */

    public void save(final CharSequence filename) throws ConfigurationException, IOException {
        final Writer w = new OutputStreamWriter(new FileOutputStream(filename.toString()), "UTF-8");
        super.save(w);
        w.close();
    }

    /** Adds all properties from the given configuration. 
     * 
     * <p>Properties from the new configuration will clear properties from the first one.
     * 
     * @param configuration a configuration.
     * */
    @SuppressWarnings("unchecked")
    public void addAll(final Configuration configuration) {
        new ConfigurationMap(this).putAll(new ConfigurationMap(configuration));
    }

    // Methods to add properties represented by primitive types easily

    public void addProperties(final String key, final String[] s) {
        for (int i = 0; i < s.length; i++)
            super.addProperty(key, s[i]);
    }

    public void addProperty(final String key, final boolean b) {
        super.addProperty(key, Boolean.valueOf(b));
    }

    public void setProperty(final String key, final boolean b) {
        super.setProperty(key, Boolean.valueOf(b));
    }

    public void addProperty(final String key, final byte b) {
        super.addProperty(key, Byte.valueOf(b));
    }

    public void setProperty(final String key, final byte b) {
        super.setProperty(key, Byte.valueOf(b));
    }

    public void addProperty(final String key, final short s) {
        super.addProperty(key, Short.valueOf(s));
    }

    public void setProperty(final String key, final short s) {
        super.setProperty(key, Short.valueOf(s));
    }

    public void addProperty(final String key, final char c) {
        super.addProperty(key, Character.valueOf(c));
    }

    public void setProperty(final String key, final char b) {
        super.setProperty(key, Character.valueOf(b));
    }

    public void addProperty(final String key, final int i) {
        super.addProperty(key, Integer.valueOf(i));
    }

    public void setProperty(final String key, final int i) {
        super.setProperty(key, Integer.valueOf(i));
    }

    public void addProperty(final String key, final long l) {
        super.addProperty(key, Long.valueOf(l));
    }

    public void setProperty(final String key, final long l) {
        super.setProperty(key, Long.valueOf(l));
    }

    public void addProperty(final String key, final float f) {
        super.addProperty(key, Float.valueOf(f));
    }

    public void setProperty(final String key, final float f) {
        super.setProperty(key, Float.valueOf(f));
    }

    public void addProperty(final String key, final double d) {
        super.addProperty(key, Double.valueOf(d));
    }

    public void setProperty(final String key, final double d) {
        super.setProperty(key, Double.valueOf(d));
    }

    // Same methods, but with Enum keys

    public void addProperties(final Enum<?> key, final String[] s) {
        for (int i = 0; i < s.length; i++)
            super.addProperty(key.name().toLowerCase(), s[i]);
    }

    public void addProperty(final Enum<?> key, final boolean b) {
        super.addProperty(key.name().toLowerCase(), Boolean.valueOf(b));
    }

    public void setProperty(final Enum<?> key, final boolean b) {
        super.setProperty(key.name().toLowerCase(), Boolean.valueOf(b));
    }

    public void addProperty(final Enum<?> key, final byte b) {
        super.addProperty(key.name().toLowerCase(), Byte.valueOf(b));
    }

    public void setProperty(final Enum<?> key, final byte b) {
        super.setProperty(key.name().toLowerCase(), Byte.valueOf(b));
    }

    public void addProperty(final Enum<?> key, final short s) {
        super.addProperty(key.name().toLowerCase(), Short.valueOf(s));
    }

    public void setProperty(final Enum<?> key, final short s) {
        super.setProperty(key.name().toLowerCase(), Short.valueOf(s));
    }

    public void addProperty(final Enum<?> key, final char c) {
        super.addProperty(key.name().toLowerCase(), Character.valueOf(c));
    }

    public void setProperty(final Enum<?> key, final char b) {
        super.setProperty(key.name().toLowerCase(), Character.valueOf(b));
    }

    public void addProperty(final Enum<?> key, final int i) {
        super.addProperty(key.name().toLowerCase(), Integer.valueOf(i));
    }

    public void setProperty(final Enum<?> key, final int i) {
        super.setProperty(key.name().toLowerCase(), Integer.valueOf(i));
    }

    public void addProperty(final Enum<?> key, final long l) {
        super.addProperty(key.name().toLowerCase(), Long.valueOf(l));
    }

    public void setProperty(final Enum<?> key, final long l) {
        super.setProperty(key.name().toLowerCase(), Long.valueOf(l));
    }

    public void addProperty(final Enum<?> key, final float f) {
        super.addProperty(key.name().toLowerCase(), Float.valueOf(f));
    }

    public void setProperty(final Enum<?> key, final float f) {
        super.setProperty(key.name().toLowerCase(), Float.valueOf(f));
    }

    public void addProperty(final Enum<?> key, final double d) {
        super.addProperty(key.name().toLowerCase(), Double.valueOf(d));
    }

    public void setProperty(final Enum<?> key, final double d) {
        super.setProperty(key.name().toLowerCase(), Double.valueOf(d));
    }

    // Polimorphic Enum version of superclass string-based methods

    public boolean containsKey(final Enum<?> key) {
        return containsKey(key.name().toLowerCase());
    }

    public Object getProperty(final Enum<?> key) {
        return getProperty(key.name().toLowerCase());
    }

    public void addProperty(final Enum<?> key, Object arg) {
        addProperty(key.name().toLowerCase(), arg);
    }

    public BigDecimal getBigDecimal(final Enum<?> key, BigDecimal arg) {
        return getBigDecimal(key.name().toLowerCase(), arg);
    }

    public BigDecimal getBigDecimal(final Enum<?> key) {
        return getBigDecimal(key.name().toLowerCase());
    }

    public BigInteger getBigInteger(final Enum<?> key, BigInteger arg) {
        return getBigInteger(key.name().toLowerCase(), arg);
    }

    public BigInteger getBigInteger(final Enum<?> key) {
        return getBigInteger(key.name().toLowerCase());
    }

    public boolean getBoolean(final Enum<?> key, boolean arg) {
        return getBoolean(key.name().toLowerCase(), arg);
    }

    public Boolean getBoolean(final Enum<?> key, Boolean arg) {
        return getBoolean(key.name().toLowerCase(), arg);
    }

    public boolean getBoolean(final Enum<?> key) {
        return getBoolean(key.name().toLowerCase());
    }

    public byte getByte(final Enum<?> key, byte arg) {
        return getByte(key.name().toLowerCase(), arg);
    }

    public Byte getByte(final Enum<?> key, Byte arg) {
        return getByte(key.name().toLowerCase(), arg);
    }

    public byte getByte(final Enum<?> key) {
        return getByte(key.name().toLowerCase());
    }

    public double getDouble(final Enum<?> key, double arg) {
        return getDouble(key.name().toLowerCase(), arg);
    }

    public Double getDouble(final Enum<?> key, Double arg) {
        return getDouble(key.name().toLowerCase(), arg);
    }

    public double getDouble(final Enum<?> key) {
        return getDouble(key.name().toLowerCase());
    }

    public float getFloat(final Enum<?> key, float arg) {
        return getFloat(key.name().toLowerCase(), arg);
    }

    public Float getFloat(final Enum<?> key, Float arg) {
        return getFloat(key.name().toLowerCase(), arg);
    }

    public float getFloat(final Enum<?> key) {
        return getFloat(key.name().toLowerCase());
    }

    public int getInt(final Enum<?> key, int arg) {
        return getInt(key.name().toLowerCase(), arg);
    }

    public int getInt(final Enum<?> key) {
        return getInt(key.name().toLowerCase());
    }

    public Integer getInteger(final Enum<?> key, Integer arg) {
        return getInteger(key.name().toLowerCase(), arg);
    }

    public Iterator<?> getKeys(final Enum<?> key) {
        return getKeys(key.name().toLowerCase());
    }

    public List<?> getList(final Enum<?> key, List<?> arg) {
        return getList(key.name().toLowerCase(), arg);
    }

    public List<?> getList(final Enum<?> key) {
        return getList(key.name().toLowerCase());
    }

    public long getLong(final Enum<?> key, long arg) {
        return getLong(key.name().toLowerCase(), arg);
    }

    public Long getLong(final Enum<?> key, Long arg) {
        return getLong(key.name().toLowerCase(), arg);
    }

    public long getLong(final Enum<?> key) {
        return getLong(key.name().toLowerCase());
    }

    public java.util.Properties getProperties(final Enum<?> key, java.util.Properties arg) {
        return getProperties(key.name().toLowerCase(), arg);
    }

    public java.util.Properties getProperties(final Enum<?> key) {
        return getProperties(key.name().toLowerCase());
    }

    public short getShort(final Enum<?> key, short arg) {
        return getShort(key.name().toLowerCase(), arg);
    }

    public Short getShort(final Enum<?> key, Short arg) {
        return getShort(key.name().toLowerCase(), arg);
    }

    public short getShort(final Enum<?> key) {
        return getShort(key.name().toLowerCase());
    }

    public String getString(final Enum<?> key, String arg) {
        return getString(key.name().toLowerCase(), arg);
    }

    public String getString(final Enum<?> key) {
        return getString(key.name().toLowerCase());
    }

    public String[] getStringArray(final Enum<?> key) {
        return getStringArray(key.name().toLowerCase());
    }

    public void setProperty(final Enum<?> key, Object arg) {
        setProperty(key.name().toLowerCase(), arg);
    }

    public Configuration subset(final Enum<?> key) {
        return subset(key.name().toLowerCase());
    }

    public String toString() {
        return ConfigurationUtils.toString(this);
    }

    public int hashCode() {
        int h = 0;
        for (Iterator<?> i = getKeys(); i.hasNext();)
            h = h * 31 + Arrays.hashCode(getStringArray((String) i.next()));
        return h;
    }

    /** Returns true if the provided object is equal to this set of properties.
     * 
     * <p>Equality between set of properties happens when the keys are the same,
     * and the list of strings associated to each key is the same. Note that the order
     * in which different keys appear in a property file is irrelevant, but <em>the order
     * between properties with the same key is significant</em>.
     *
     * <p>Due to the strictness of the check (e.g., no number conversion is performed)
     * this method is mainly useful when writing tests.
     * 
     * @return true if the argument is equal to this set of properties.
     */

    public boolean equals(final Object o) {
        if (!(o instanceof Properties))
            return false;
        final Properties p = (Properties) o;
        for (Iterator<?> i = getKeys(); i.hasNext();) {
            String key = (String) i.next();
            String[] value = p.getStringArray(key);
            if (value == null || !Arrays.equals(getStringArray(key), value))
                return false;
        }

        for (Iterator<?> i = p.getKeys(); i.hasNext();)
            if (getStringArray((String) i.next()) == null)
                return false;

        return true;
    }

    private void writeObject(final ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
        try {
            save(s);
        } catch (ConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        try {
            load(s);
        } catch (ConfigurationException e) {
            throw new RuntimeException(e);
        }
    }
}