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 * @version IFS 1.3 (Iterative Forward Search)<br> 013 * Copyright (C) 2006 - 2014 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 * @return value of the property 111 */ 112 public int getPropertyInt(String key, int defaultValue) { 113 try { 114 if (containsPropery(key)) 115 return Integer.parseInt(getProperty(key)); 116 if (iSaveDefaults) 117 setProperty(key, String.valueOf(defaultValue)); 118 return defaultValue; 119 } catch (NumberFormatException nfe) { 120 if (iSaveDefaults) 121 setProperty(key, String.valueOf(defaultValue)); 122 return defaultValue; 123 } 124 } 125 126 /** 127 * Returns long property 128 * 129 * @param key 130 * key 131 * @param defaultValue 132 * default value to be returned when such property is not present 133 * @return value of the property 134 */ 135 public long getPropertyLong(String key, long defaultValue) { 136 try { 137 if (containsPropery(key)) 138 return Long.parseLong(getProperty(key)); 139 if (iSaveDefaults) 140 setProperty(key, String.valueOf(defaultValue)); 141 return defaultValue; 142 } catch (NumberFormatException nfe) { 143 if (iSaveDefaults) 144 setProperty(key, String.valueOf(defaultValue)); 145 return defaultValue; 146 } 147 } 148 149 /** 150 * Returns int property 151 * 152 * @param key 153 * key 154 * @param defaultValue 155 * default value to be returned when such property is not present 156 * @return value of the property 157 */ 158 public Integer getPropertyInteger(String key, Integer defaultValue) { 159 try { 160 if (containsPropery(key)) 161 return Integer.valueOf(getProperty(key)); 162 if (iSaveDefaults && defaultValue != null) 163 setProperty(key, String.valueOf(defaultValue)); 164 return defaultValue; 165 } catch (NumberFormatException nfe) { 166 if (iSaveDefaults && defaultValue != null) 167 setProperty(key, String.valueOf(defaultValue)); 168 return defaultValue; 169 } 170 } 171 172 /** 173 * Returns long property 174 * 175 * @param key 176 * key 177 * @param defaultValue 178 * default value to be returned when such property is not present 179 * @return value of the property 180 */ 181 public Long getPropertyLong(String key, Long defaultValue) { 182 try { 183 if (containsPropery(key)) 184 return Long.valueOf(getProperty(key)); 185 if (iSaveDefaults && defaultValue != null) 186 setProperty(key, String.valueOf(defaultValue)); 187 return defaultValue; 188 } catch (NumberFormatException nfe) { 189 if (iSaveDefaults && defaultValue != null) 190 setProperty(key, String.valueOf(defaultValue)); 191 return defaultValue; 192 } 193 } 194 195 /** 196 * Returns true if there is such property 197 * 198 * @param key 199 * key 200 * @return true if there is such property 201 */ 202 public boolean containsPropery(String key) { 203 return getProperty(key) != null; 204 } 205 206 /** 207 * Returns boolean property 208 * 209 * @param key 210 * key 211 * @param defaultValue 212 * default value to be returned when such property is not present 213 * @return value of the property 214 */ 215 public boolean getPropertyBoolean(String key, boolean defaultValue) { 216 try { 217 if (containsPropery(key)) 218 return (getProperty(key).equalsIgnoreCase("on") || getProperty(key).equalsIgnoreCase("true")); 219 if (iSaveDefaults) 220 setProperty(key, (defaultValue ? "true" : "false")); 221 return defaultValue; 222 } catch (Exception nfe) { 223 if (iSaveDefaults) 224 setProperty(key, (defaultValue ? "true" : "false")); 225 return defaultValue; 226 } 227 } 228 229 /** 230 * Returns double property 231 * 232 * @param key 233 * key 234 * @param defaultValue 235 * default value to be returned when such property is not present 236 * @return value of the property 237 */ 238 public double getPropertyDouble(String key, double defaultValue) { 239 try { 240 if (containsPropery(key)) 241 return Double.parseDouble(getProperty(key)); 242 if (iSaveDefaults) 243 setProperty(key, String.valueOf(defaultValue)); 244 return defaultValue; 245 } catch (NumberFormatException nfe) { 246 if (iSaveDefaults) 247 setProperty(key, String.valueOf(defaultValue)); 248 return defaultValue; 249 } 250 } 251 252 /** 253 * Returns float property 254 * 255 * @param key 256 * key 257 * @param defaultValue 258 * default value to be returned when such property is not present 259 * @return value of the property 260 */ 261 public float getPropertyFloat(String key, float defaultValue) { 262 try { 263 if (containsPropery(key)) 264 return Float.parseFloat(getProperty(key)); 265 if (iSaveDefaults) 266 setProperty(key, String.valueOf(defaultValue)); 267 return defaultValue; 268 } catch (NumberFormatException nfe) { 269 if (iSaveDefaults) 270 setProperty(key, String.valueOf(defaultValue)); 271 return defaultValue; 272 } 273 } 274 275 /** 276 * Returns boolean property 277 * 278 * @param key 279 * key 280 * @param defaultValue 281 * default value to be returned when such property is not present 282 * @return value of the property 283 */ 284 public Boolean getPropertyBoolean(String key, Boolean defaultValue) { 285 try { 286 if (containsPropery(key)) 287 return Boolean.valueOf(getProperty(key).equalsIgnoreCase("on") || getProperty(key).equalsIgnoreCase("true")); 288 if (iSaveDefaults && defaultValue != null) 289 setProperty(key, (defaultValue.booleanValue() ? "true" : "false")); 290 return defaultValue; 291 } catch (Exception nfe) { 292 if (iSaveDefaults && defaultValue != null) 293 setProperty(key, (defaultValue.booleanValue() ? "true" : "false")); 294 return defaultValue; 295 } 296 } 297 298 /** 299 * Returns double property 300 * 301 * @param key 302 * key 303 * @param defaultValue 304 * default value to be returned when such property is not present 305 * @return value of the property 306 */ 307 public Double getPropertyDouble(String key, Double defaultValue) { 308 try { 309 if (containsPropery(key)) 310 return Double.valueOf(getProperty(key)); 311 if (iSaveDefaults && defaultValue != null) 312 setProperty(key, String.valueOf(defaultValue)); 313 return defaultValue; 314 } catch (NumberFormatException nfe) { 315 if (iSaveDefaults && defaultValue != null) 316 setProperty(key, String.valueOf(defaultValue)); 317 return defaultValue; 318 } 319 } 320 321 /** 322 * Returns float property 323 * 324 * @param key 325 * key 326 * @param defaultValue 327 * default value to be returned when such property is not present 328 * @return value of the property 329 */ 330 public Float getPropertyFloat(String key, Float defaultValue) { 331 try { 332 if (containsPropery(key)) 333 return Float.valueOf(getProperty(key)); 334 if (iSaveDefaults && defaultValue != null) 335 setProperty(key, String.valueOf(defaultValue)); 336 return defaultValue; 337 } catch (NumberFormatException nfe) { 338 if (iSaveDefaults && defaultValue != null) 339 setProperty(key, String.valueOf(defaultValue)); 340 return defaultValue; 341 } 342 } 343 344 public void setProperty(String key, Object[] value) { 345 StringBuffer sb = new StringBuffer(); 346 for (int i = 0; i < value.length; i++) { 347 if (i > 0) 348 sb.append(","); 349 sb.append(value[i] == null ? "null" : value[i].toString()); 350 } 351 setProperty(key, sb.toString()); 352 } 353 354 public Long[] getPropertyLongArry(String key, Long[] defaultValue) { 355 try { 356 if (containsPropery(key)) { 357 StringTokenizer stk = new StringTokenizer(getProperty(key), ","); 358 Long ret[] = new Long[stk.countTokens()]; 359 for (int i = 0; stk.hasMoreTokens(); i++) { 360 String t = stk.nextToken(); 361 ret[i] = ("null".equals(t) ? null : Long.valueOf(t)); 362 } 363 return ret; 364 } 365 if (iSaveDefaults && defaultValue != null) 366 setProperty(key, defaultValue); 367 return defaultValue; 368 } catch (NumberFormatException nfe) { 369 if (iSaveDefaults && defaultValue != null) 370 setProperty(key, defaultValue); 371 return defaultValue; 372 } 373 } 374 375 public Integer[] getPropertyIntegerArry(String key, Integer[] defaultValue) { 376 try { 377 if (containsPropery(key)) { 378 StringTokenizer stk = new StringTokenizer(getProperty(key), ","); 379 Integer ret[] = new Integer[stk.countTokens()]; 380 for (int i = 0; stk.hasMoreTokens(); i++) { 381 String t = stk.nextToken(); 382 ret[i] = ("null".equals(t) ? null : Integer.valueOf(t)); 383 } 384 return ret; 385 } 386 if (iSaveDefaults && defaultValue != null) 387 setProperty(key, defaultValue); 388 return defaultValue; 389 } catch (NumberFormatException nfe) { 390 if (iSaveDefaults && defaultValue != null) 391 setProperty(key, defaultValue); 392 return defaultValue; 393 } 394 } 395 396 public Double[] getPropertyDoubleArry(String key, Double[] defaultValue) { 397 try { 398 if (containsPropery(key)) { 399 StringTokenizer stk = new StringTokenizer(getProperty(key), ","); 400 Double ret[] = new Double[stk.countTokens()]; 401 for (int i = 0; stk.hasMoreTokens(); i++) { 402 String t = stk.nextToken(); 403 ret[i] = ("null".equals(t) ? null : Double.valueOf(t)); 404 } 405 return ret; 406 } 407 if (iSaveDefaults && defaultValue != null) 408 setProperty(key, defaultValue); 409 return defaultValue; 410 } catch (NumberFormatException nfe) { 411 if (iSaveDefaults && defaultValue != null) 412 setProperty(key, defaultValue); 413 return defaultValue; 414 } 415 } 416 417 /** 418 * Returns properties as a map 419 * @return properties as a map 420 */ 421 public Map<String, String> toMap() { 422 HashMap<String, String> ret = new HashMap<String, String>(); 423 for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) { 424 String key = (String) e.nextElement(); 425 String prop = getProperty(key); 426 if (key != null && prop != null) 427 ret.put(key, prop); 428 } 429 return ret; 430 } 431 432 private void expand(String key) { 433 String value = getProperty(key); 434 if (value == null) 435 return; 436 int done = -1, idx = -1; 437 while ((idx = value.indexOf('%', done + 1)) >= 0) { 438 int idx2 = value.indexOf('%', idx + 1); 439 if (idx2 < 0) 440 return; 441 String subString = value.substring(idx + 1, idx2); 442 if (containsPropery(subString)) 443 value = value.substring(0, idx) + getProperty(subString) + value.substring(idx2 + 1); 444 else 445 done = idx; 446 } 447 setProperty(key, value); 448 } 449 450 public void expand() { 451 for (Enumeration<?> e = keys(); e.hasMoreElements();) { 452 expand((String) e.nextElement()); 453 } 454 } 455 456 /** Loads properties from an input stream */ 457 @Override 458 public void load(java.io.InputStream inputStream) throws java.io.IOException { 459 super.load(inputStream); 460 expand(); 461 iSaveDefaults = getPropertyBoolean("General.SaveDefaultProperties", false); 462 } 463}