    001package net.sf.cpsolver.ifs.util;
    002
    003import java.util.Enumeration;
    004import java.util.HashMap;
    005import java.util.Map;
    006import java.util.Properties;
    007import java.util.StringTokenizer;
    008
    009/**
    010 * Data properties.
    011 *
    012 * @version IFS 1.2 (Iterative Forward Search)<br>
    013 *          Copyright (C) 2006 - 2010 Tomáš Müller<br>
    014 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
    015 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
    016 * <br>
    017 *          This library is free software; you can redistribute it and/or modify
    018 *          it under the terms of the GNU Lesser General Public License as
    019 *          published by the Free Software Foundation; either version 3 of the
    020 *          License, or (at your option) any later version. <br>
    021 * <br>
    022 *          This library is distributed in the hope that it will be useful, but
    023 *          WITHOUT ANY WARRANTY; without even the implied warranty of
    024 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    025 *          Lesser General Public License for more details. <br>
    026 * <br>
    027 *          You should have received a copy of the GNU Lesser General Public
    028 *          License along with this library; if not see
    029 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
    030 */
    031public class DataProperties extends Properties {
    032    private boolean iSaveDefaults = false;
    033    private static final long serialVersionUID = 1L;
    034
    035    /** Constructor */
    036    public DataProperties() {
    037        super();
    038    }
    039
    040    /**
    041     * Constructor
    042     *
    043     * @param defaults
    044     *            default properties
    045     */
    046    public DataProperties(Properties defaults) {
    047        super(defaults);
    048        iSaveDefaults = getPropertyBoolean("General.SaveDefaultProperties", false);
    049    }
    050
    051    /**
    052     * Constructor
    053     *
    054     * @param properties
    055     *            default properties
    056     */
    057    public DataProperties(Map<String, String> properties) {
    058        super();
    059        for (Map.Entry<String, String> entry : properties.entrySet()) {
    060            setProperty(entry.getKey(), entry.getValue());
    061        }
    062        iSaveDefaults = getPropertyBoolean("General.SaveDefaultProperties", false);
    063    }
    064
    065    /**
    066     * Returns string property
    067     *
    068     * @param key
    069     *            key
    070     * @param defaultValue
    071     *            default value to be returned when such property is not present
    072     */
    073    @Override
    074    public String getProperty(String key, String defaultValue) {
    075        if (!iSaveDefaults || containsPropery(key))
    076            return super.getProperty(key, defaultValue);
    077        if (defaultValue != null)
    078            setProperty(key, defaultValue);
    079        return defaultValue;
    080    }
    081
    082    /**
    083     * Sets string property
    084     *
    085     * @param key
    086     *            key
    087     * @param value
    088     *            value
    089     */
    090    @Override
    091    public Object setProperty(String key, String value) {
    092        if (value == null) {
    093            Object ret = getProperty(key);
    094            remove(key);
    095            return ret;
    096        }
    097        Object ret = super.setProperty(key, value);
    098        if ("General.SaveDefaultProperties".equals(key))
    099            iSaveDefaults = getPropertyBoolean("General.SaveDefaultProperties", false);
    100        return ret;
    101    }
    102
    103    /**
    104     * Returns int property
    105     *
    106     * @param key
    107     *            key
    108     * @param defaultValue
    109     *            default value to be returned when such property is not present
    110     */
    111    public int getPropertyInt(String key, int defaultValue) {
    112        try {
    113            if (containsPropery(key))
    114                return Integer.parseInt(getProperty(key));
    115            if (iSaveDefaults)
    116                setProperty(key, String.valueOf(defaultValue));
    117            return defaultValue;
    118        } catch (NumberFormatException nfe) {
    119            if (iSaveDefaults)
    120                setProperty(key, String.valueOf(defaultValue));
    121            return defaultValue;
    122        }
    123    }
    124
    125    /**
    126     * Returns long property
    127     *
    128     * @param key
    129     *            key
    130     * @param defaultValue
    131     *            default value to be returned when such property is not present
    132     */
    133    public long getPropertyLong(String key, long defaultValue) {
    134        try {
    135            if (containsPropery(key))
    136                return Long.parseLong(getProperty(key));
    137            if (iSaveDefaults)
    138                setProperty(key, String.valueOf(defaultValue));
    139            return defaultValue;
    140        } catch (NumberFormatException nfe) {
    141            if (iSaveDefaults)
    142                setProperty(key, String.valueOf(defaultValue));
    143            return defaultValue;
    144        }
    145    }
    146
    147    /**
    148     * Returns int property
    149     *
    150     * @param key
    151     *            key
    152     * @param defaultValue
    153     *            default value to be returned when such property is not present
    154     */
    155    public Integer getPropertyInteger(String key, Integer defaultValue) {
    156        try {
    157            if (containsPropery(key))
    158                return Integer.valueOf(getProperty(key));
    159            if (iSaveDefaults && defaultValue != null)
    160                setProperty(key, String.valueOf(defaultValue));
    161            return defaultValue;
    162        } catch (NumberFormatException nfe) {
    163            if (iSaveDefaults && defaultValue != null)
    164                setProperty(key, String.valueOf(defaultValue));
    165            return defaultValue;
    166        }
    167    }
    168
    169    /**
    170     * Returns long property
    171     *
    172     * @param key
    173     *            key
    174     * @param defaultValue
    175     *            default value to be returned when such property is not present
    176     */
    177    public Long getPropertyLong(String key, Long defaultValue) {
    178        try {
    179            if (containsPropery(key))
    180                return Long.valueOf(getProperty(key));
    181            if (iSaveDefaults && defaultValue != null)
    182                setProperty(key, String.valueOf(defaultValue));
    183            return defaultValue;
    184        } catch (NumberFormatException nfe) {
    185            if (iSaveDefaults && defaultValue != null)
    186                setProperty(key, String.valueOf(defaultValue));
    187            return defaultValue;
    188        }
    189    }
    190
    191    /**
    192     * Returns true if there is such property
    193     *
    194     * @param key
    195     *            key
    196     */
    197    public boolean containsPropery(String key) {
    198        return getProperty(key) != null;
    199    }
    200
    201    /**
    202     * Returns boolean property
    203     *
    204     * @param key
    205     *            key
    206     * @param defaultValue
    207     *            default value to be returned when such property is not present
    208     */
    209    public boolean getPropertyBoolean(String key, boolean defaultValue) {
    210        try {
    211            if (containsPropery(key))
    212                return (getProperty(key).equalsIgnoreCase("on") || getProperty(key).equalsIgnoreCase("true"));
    213            if (iSaveDefaults)
    214                setProperty(key, (defaultValue ? "true" : "false"));
    215            return defaultValue;
    216        } catch (Exception nfe) {
    217            if (iSaveDefaults)
    218                setProperty(key, (defaultValue ? "true" : "false"));
    219            return defaultValue;
    220        }
    221    }
    222
    223    /**
    224     * Returns double property
    225     *
    226     * @param key
    227     *            key
    228     * @param defaultValue
    229     *            default value to be returned when such property is not present
    230     */
    231    public double getPropertyDouble(String key, double defaultValue) {
    232        try {
    233            if (containsPropery(key))
    234                return Double.parseDouble(getProperty(key));
    235            if (iSaveDefaults)
    236                setProperty(key, String.valueOf(defaultValue));
    237            return defaultValue;
    238        } catch (NumberFormatException nfe) {
    239            if (iSaveDefaults)
    240                setProperty(key, String.valueOf(defaultValue));
    241            return defaultValue;
    242        }
    243    }
    244
    245    /**
    246     * Returns float property
    247     *
    248     * @param key
    249     *            key
    250     * @param defaultValue
    251     *            default value to be returned when such property is not present
    252     */
    253    public float getPropertyFloat(String key, float defaultValue) {
    254        try {
    255            if (containsPropery(key))
    256                return Float.parseFloat(getProperty(key));
    257            if (iSaveDefaults)
    258                setProperty(key, String.valueOf(defaultValue));
    259            return defaultValue;
    260        } catch (NumberFormatException nfe) {
    261            if (iSaveDefaults)
    262                setProperty(key, String.valueOf(defaultValue));
    263            return defaultValue;
    264        }
    265    }
    266
    267    /**
    268     * Returns boolean property
    269     *
    270     * @param key
    271     *            key
    272     * @param defaultValue
    273     *            default value to be returned when such property is not present
    274     */
    275    public Boolean getPropertyBoolean(String key, Boolean defaultValue) {
    276        try {
    277            if (containsPropery(key))
    278                return new Boolean(getProperty(key).equalsIgnoreCase("on") || getProperty(key).equalsIgnoreCase("true"));
    279            if (iSaveDefaults && defaultValue != null)
    280                setProperty(key, (defaultValue.booleanValue() ? "true" : "false"));
    281            return defaultValue;
    282        } catch (Exception nfe) {
    283            if (iSaveDefaults && defaultValue != null)
    284                setProperty(key, (defaultValue.booleanValue() ? "true" : "false"));
    285            return defaultValue;
    286        }
    287    }
    288
    289    /**
    290     * Returns double property
    291     *
    292     * @param key
    293     *            key
    294     * @param defaultValue
    295     *            default value to be returned when such property is not present
    296     */
    297    public Double getPropertyDouble(String key, Double defaultValue) {
    298        try {
    299            if (containsPropery(key))
    300                return Double.valueOf(getProperty(key));
    301            if (iSaveDefaults && defaultValue != null)
    302                setProperty(key, String.valueOf(defaultValue));
    303            return defaultValue;
    304        } catch (NumberFormatException nfe) {
    305            if (iSaveDefaults && defaultValue != null)
    306                setProperty(key, String.valueOf(defaultValue));
    307            return defaultValue;
    308        }
    309    }
    310
    311    /**
    312     * Returns float property
    313     *
    314     * @param key
    315     *            key
    316     * @param defaultValue
    317     *            default value to be returned when such property is not present
    318     */
    319    public Float getPropertyFloat(String key, Float defaultValue) {
    320        try {
    321            if (containsPropery(key))
    322                return Float.valueOf(getProperty(key));
    323            if (iSaveDefaults && defaultValue != null)
    324                setProperty(key, String.valueOf(defaultValue));
    325            return defaultValue;
    326        } catch (NumberFormatException nfe) {
    327            if (iSaveDefaults && defaultValue != null)
    328                setProperty(key, String.valueOf(defaultValue));
    329            return defaultValue;
    330        }
    331    }
    332
    333    public void setProperty(String key, Object[] value) {
    334        StringBuffer sb = new StringBuffer();
    335        for (int i = 0; i < value.length; i++) {
    336            if (i > 0)
    337                sb.append(",");
    338            sb.append(value[i] == null ? "null" : value[i].toString());
    339        }
    340        setProperty(key, sb.toString());
    341    }
    342
    343    public Long[] getPropertyLongArry(String key, Long[] defaultValue) {
    344        try {
    345            if (containsPropery(key)) {
    346                StringTokenizer stk = new StringTokenizer(getProperty(key), ",");
    347                Long ret[] = new Long[stk.countTokens()];
    348                for (int i = 0; stk.hasMoreTokens(); i++) {
    349                    String t = stk.nextToken();
    350                    ret[i] = ("null".equals(t) ? null : Long.valueOf(t));
    351                }
    352                return ret;
    353            }
    354            if (iSaveDefaults && defaultValue != null)
    355                setProperty(key, defaultValue);
    356            return defaultValue;
    357        } catch (NumberFormatException nfe) {
    358            if (iSaveDefaults && defaultValue != null)
    359                setProperty(key, defaultValue);
    360            return defaultValue;
    361        }
    362    }
    363
    364    public Integer[] getPropertyIntegerArry(String key, Integer[] defaultValue) {
    365        try {
    366            if (containsPropery(key)) {
    367                StringTokenizer stk = new StringTokenizer(getProperty(key), ",");
    368                Integer ret[] = new Integer[stk.countTokens()];
    369                for (int i = 0; stk.hasMoreTokens(); i++) {
    370                    String t = stk.nextToken();
    371                    ret[i] = ("null".equals(t) ? null : Integer.valueOf(t));
    372                }
    373                return ret;
    374            }
    375            if (iSaveDefaults && defaultValue != null)
    376                setProperty(key, defaultValue);
    377            return defaultValue;
    378        } catch (NumberFormatException nfe) {
    379            if (iSaveDefaults && defaultValue != null)
    380                setProperty(key, defaultValue);
    381            return defaultValue;
    382        }
    383    }
    384
    385    /**
    386     * Returns properties as dictionary.
    387     */
    388    public Map<String, String> toMap() {
    389        HashMap<String, String> ret = new HashMap<String, String>();
    390        for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
    391            String key = (String) e.nextElement();
    392            String prop = getProperty(key);
    393            if (key != null && prop != null)
    394                ret.put(key, prop);
    395        }
    396        return ret;
    397    }
    398
    399    private void expand(String key) {
    400        String value = getProperty(key);
    401        if (value == null)
    402            return;
    403        int done = -1, idx = -1;
    404        while ((idx = value.indexOf('%', done + 1)) >= 0) {
    405            int idx2 = value.indexOf('%', idx + 1);
    406            if (idx2 < 0)
    407                return;
    408            String subString = value.substring(idx + 1, idx2);
    409            if (containsPropery(subString))
    410                value = value.substring(0, idx) + getProperty(subString) + value.substring(idx2 + 1);
    411            else
    412                done = idx;
    413        }
    414        setProperty(key, value);
    415    }
    416
    417    public void expand() {
    418        for (Enumeration<?> e = keys(); e.hasMoreElements();) {
    419            expand((String) e.nextElement());
    420        }
    421    }
    422
    423    /** Loads properties from an input stream */
    424    @Override
    425    public void load(java.io.InputStream inputStream) throws java.io.IOException {
    426        super.load(inputStream);
    427        expand();
    428        iSaveDefaults = getPropertyBoolean("General.SaveDefaultProperties", false);
    429    }
    430}