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