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

src.it.unimi.dsi.util.Properties Maven / Gradle / Ivy

Go to download

The DSI utilities are a mishmash of classes accumulated during the last twenty years in projects developed at the DSI (Dipartimento di Scienze dell'Informazione, i.e., Information Sciences Department), now DI (Dipartimento di Informatica, i.e., Informatics Department), of the Universita` degli Studi di Milano.

There is a newer version: 2.7.3
Show newest version
/*
 * DSI utilities
 *
 * Copyright (C) 2005-2020 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 3 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, see .
 *
 */

package it.unimi.dsi.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ConfigurationMap;
import org.apache.commons.configuration2.ConfigurationUtils;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.io.FileHandler;

/**
 * An extension of {@link org.apache.commons.configuration2.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.
 *
 * 

* All accessors defined in {@link org.apache.commons.configuration2.PropertiesConfiguration} have a * polymorphic counterpart taking an {@link java.lang.Enum} instead of a string: * {@link java.lang.Enum#name()} and {@link java.lang.String#toLowerCase()} 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.) * *

* Additionally, instances of this class can be serialised. */ public class Properties extends PropertiesConfiguration implements Serializable { private static final long serialVersionUID = 1L; /** A delimiter mimicking the pre-version 2 list behavior. */ private static final DefaultListDelimiterHandler COMMA_LIST_DELIMITER_HANDLER = new DefaultListDelimiterHandler(','); /** A file handler for input/output. */ private transient FileHandler fileHandler; public Properties() { getLayout().setGlobalSeparator("="); setListDelimiterHandler(COMMA_LIST_DELIMITER_HANDLER); fileHandler = new FileHandler(this); fileHandler.setEncoding(StandardCharsets.UTF_8.toString()); } public Properties(final String filename) throws ConfigurationException { this(); fileHandler.setFileName(filename); fileHandler.load(); } public Properties(final File file) throws ConfigurationException { this(); fileHandler.setFile(file); fileHandler.load(); } public Properties(final URL url) throws ConfigurationException { this(); fileHandler.setURL(url); fileHandler.load(); } public Properties(final InputStream inputStream) throws ConfigurationException { this(); fileHandler.load(inputStream); } /** Saves the configuration to the specified file. * * @param filename a file name. */ public void save(final CharSequence filename) throws ConfigurationException, IOException { final FileOutputStream os = new FileOutputStream(filename.toString()); fileHandler.save(os); os.close(); } /** * Saves the configuration to the specified file. * * @param file a file. */ public void save(final File file) throws ConfigurationException, IOException { save(file.toString()); } /** * Saves the configuration to an output stream. * * @param os an output stream. */ public void save(final OutputStream os) throws ConfigurationException { fileHandler.save(os); } /** Adds all properties from the given configuration. * *

Properties from the new configuration will clear properties from the first one. * * @param configuration a configuration. * */ 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 (final String element : s) super.addProperty(key, element); } 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 (final String element : s) super.addProperty(key.name().toLowerCase(), element); } 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, final Object arg) { addProperty(key.name().toLowerCase(), arg); } public BigDecimal getBigDecimal(final Enum key, final 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, final 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, final boolean arg) { return getBoolean(key.name().toLowerCase(), arg); } public Boolean getBoolean(final Enum key, final 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, final byte arg) { return getByte(key.name().toLowerCase(), arg); } public Byte getByte(final Enum key, final 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, final double arg) { return getDouble(key.name().toLowerCase(), arg); } public Double getDouble(final Enum key, final 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, final float arg) { return getFloat(key.name().toLowerCase(), arg); } public Float getFloat(final Enum key, final 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, final 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, final 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, final 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, final long arg) { return getLong(key.name().toLowerCase(), arg); } public Long getLong(final Enum key, final 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, final 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, final short arg) { return getShort(key.name().toLowerCase(), arg); } public Short getShort(final Enum key, final 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, final 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, final Object arg) { setProperty(key.name().toLowerCase(), arg); } public Configuration subset(final Enum key) { return subset(key.name().toLowerCase()); } @Override public String toString() { return ConfigurationUtils.toString(this); } @Override public int hashCode() { int h = 0; for(final 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. * *

Equality between set of properties happens when the keys are the same, * and the list of strings associated with each key is the same. Note that the order * in which different keys appear in a property file is irrelevant, but the order * between properties with the same key is significant. * *

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. */ @Override public boolean equals(final Object o) { if (! (o instanceof Properties)) return false; final Properties p = (Properties)o; for(final Iterator i = getKeys(); i.hasNext();) { final String key = (String)i.next(); final String[] value = p.getStringArray(key); if (value == null || ! Arrays.equals(getStringArray(key), value)) return false; } for(final 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(); fileHandler = new FileHandler(this); fileHandler.setEncoding(StandardCharsets.UTF_8.toString()); try { fileHandler.save(s); } catch (final ConfigurationException e) { throw new RuntimeException(e); } } private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); fileHandler = new FileHandler(this); fileHandler.setEncoding(StandardCharsets.UTF_8.toString()); try { fileHandler.load(s); } catch (final ConfigurationException e) { throw new RuntimeException(e); } } }