001    package net.sf.cpsolver.ifs.util;
002    
003    import java.util.Enumeration;
004    import java.util.HashMap;
005    import java.util.Map;
006    import java.util.Properties;
007    import java.util.StringTokenizer;
008    
009    /**
010     * Data properties.
011     * 
012     * @version IFS 1.2 (Iterative Forward Search)<br>
013     *          Copyright (C) 2006 - 2010 Tomas Muller<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     */
031    public 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    }