Coverage Report - org.ini4j.BasicOptionMap
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicOptionMap
100%
85/85
96%
54/56
1.829
BasicOptionMap$Access
95%
23/24
90%
9/10
1.829
 
 1  
 /*
 2  
  * Copyright 2005,2009 Ivan SZKIBA
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.ini4j;
 17  
 
 18  
 import org.ini4j.spi.BeanAccess;
 19  
 import org.ini4j.spi.BeanTool;
 20  
 import org.ini4j.spi.Warnings;
 21  
 
 22  
 import java.lang.reflect.Array;
 23  
 
 24  
 import java.util.regex.Matcher;
 25  
 import java.util.regex.Pattern;
 26  
 
 27  
 public class BasicOptionMap extends CommonMultiMap<String, String> implements OptionMap
 28  
 {
 29  
     private static final char SUBST_CHAR = '$';
 30  
     private static final String SYSTEM_PROPERTY_PREFIX = "@prop/";
 31  
     private static final String ENVIRONMENT_PREFIX = "@env/";
 32  1
     private static final int SYSTEM_PROPERTY_PREFIX_LEN = SYSTEM_PROPERTY_PREFIX.length();
 33  1
     private static final int ENVIRONMENT_PREFIX_LEN = ENVIRONMENT_PREFIX.length();
 34  1
     private static final Pattern EXPRESSION = Pattern.compile("(?<!\\\\)\\$\\{(([^\\[\\}]+)(\\[([0-9]+)\\])?)\\}");
 35  
     private static final int G_OPTION = 2;
 36  
     private static final int G_INDEX = 4;
 37  
     private static final long serialVersionUID = 325469712293707584L;
 38  
     private BeanAccess _defaultBeanAccess;
 39  
     private final boolean _propertyFirstUpper;
 40  
 
 41  
     public BasicOptionMap()
 42  
     {
 43  659
         this(false);
 44  659
     }
 45  
 
 46  
     public BasicOptionMap(boolean propertyFirstUpper)
 47  660
     {
 48  660
         _propertyFirstUpper = propertyFirstUpper;
 49  660
     }
 50  
 
 51  
     @Override
 52  
     @SuppressWarnings(Warnings.UNCHECKED)
 53  
     public <T> T getAll(Object key, Class<T> clazz)
 54  
     {
 55  4
         requireArray(clazz);
 56  
         T value;
 57  
 
 58  3
         value = (T) Array.newInstance(clazz.getComponentType(), length(key));
 59  11
         for (int i = 0; i < length(key); i++)
 60  
         {
 61  8
             Array.set(value, i, BeanTool.getInstance().parse(get(key, i), clazz.getComponentType()));
 62  
         }
 63  
 
 64  3
         return value;
 65  
     }
 66  
 
 67  
     @Override public void add(String key, Object value)
 68  
     {
 69  26
         super.add(key, ((value == null) || (value instanceof String)) ? (String) value : String.valueOf(value));
 70  26
     }
 71  
 
 72  
     @Override public void add(String key, Object value, int index)
 73  
     {
 74  4
         super.add(key, ((value == null) || (value instanceof String)) ? (String) value : String.valueOf(value), index);
 75  4
     }
 76  
 
 77  
     @Override public <T> T as(Class<T> clazz)
 78  
     {
 79  169
         return BeanTool.getInstance().proxy(clazz, getDefaultBeanAccess());
 80  
     }
 81  
 
 82  
     @Override public <T> T as(Class<T> clazz, String keyPrefix)
 83  
     {
 84  8
         return BeanTool.getInstance().proxy(clazz, newBeanAccess(keyPrefix));
 85  
     }
 86  
 
 87  
     @Override public String fetch(Object key)
 88  
     {
 89  1527
         int len = length(key);
 90  
 
 91  1527
         return (len == 0) ? null : fetch(key, len - 1);
 92  
     }
 93  
 
 94  
     @Override public String fetch(Object key, String defaultValue)
 95  
     {
 96  2
         String str = get(key);
 97  
 
 98  2
         return (str == null) ? defaultValue : str;
 99  
     }
 100  
 
 101  
     @Override public String fetch(Object key, int index)
 102  
     {
 103  1628
         String value = get(key, index);
 104  
 
 105  1628
         if ((value != null) && (value.indexOf(SUBST_CHAR) >= 0))
 106  
         {
 107  197
             StringBuilder buffer = new StringBuilder(value);
 108  
 
 109  197
             resolve(buffer);
 110  197
             value = buffer.toString();
 111  
         }
 112  
 
 113  1628
         return value;
 114  
     }
 115  
 
 116  
     @Override public <T> T fetch(Object key, Class<T> clazz)
 117  
     {
 118  7
         return BeanTool.getInstance().parse(fetch(key), clazz);
 119  
     }
 120  
 
 121  
     @Override public <T> T fetch(Object key, Class<T> clazz, T defaultValue)
 122  
     {
 123  2
         String str = fetch(key);
 124  
 
 125  2
         return (str == null) ? defaultValue : BeanTool.getInstance().parse(str, clazz);
 126  
     }
 127  
 
 128  
     @Override public <T> T fetch(Object key, int index, Class<T> clazz)
 129  
     {
 130  1
         return BeanTool.getInstance().parse(fetch(key, index), clazz);
 131  
     }
 132  
 
 133  
     @Override
 134  
     @SuppressWarnings(Warnings.UNCHECKED)
 135  
     public <T> T fetchAll(Object key, Class<T> clazz)
 136  
     {
 137  3
         requireArray(clazz);
 138  
         T value;
 139  
 
 140  2
         value = (T) Array.newInstance(clazz.getComponentType(), length(key));
 141  6
         for (int i = 0; i < length(key); i++)
 142  
         {
 143  4
             Array.set(value, i, BeanTool.getInstance().parse(fetch(key, i), clazz.getComponentType()));
 144  
         }
 145  
 
 146  2
         return value;
 147  
     }
 148  
 
 149  
     @Override public void from(Object bean)
 150  
     {
 151  18
         BeanTool.getInstance().inject(getDefaultBeanAccess(), bean);
 152  18
     }
 153  
 
 154  
     @Override public void from(Object bean, String keyPrefix)
 155  
     {
 156  7
         BeanTool.getInstance().inject(newBeanAccess(keyPrefix), bean);
 157  7
     }
 158  
 
 159  
     @Override public <T> T get(Object key, Class<T> clazz)
 160  
     {
 161  11
         return BeanTool.getInstance().parse(get(key), clazz);
 162  
     }
 163  
 
 164  
     @Override public String get(Object key, String defaultValue)
 165  
     {
 166  2
         String str = get(key);
 167  
 
 168  2
         return (str == null) ? defaultValue : str;
 169  
     }
 170  
 
 171  
     @Override public <T> T get(Object key, Class<T> clazz, T defaultValue)
 172  
     {
 173  2
         String str = get(key);
 174  
 
 175  2
         return (str == null) ? defaultValue : BeanTool.getInstance().parse(str, clazz);
 176  
     }
 177  
 
 178  
     @Override public <T> T get(Object key, int index, Class<T> clazz)
 179  
     {
 180  3
         return BeanTool.getInstance().parse(get(key, index), clazz);
 181  
     }
 182  
 
 183  
     @Override public String put(String key, Object value)
 184  
     {
 185  14
         return super.put(key, ((value == null) || (value instanceof String)) ? (String) value : String.valueOf(value));
 186  
     }
 187  
 
 188  
     @Override public String put(String key, Object value, int index)
 189  
     {
 190  4
         return super.put(key, ((value == null) || (value instanceof String)) ? (String) value : String.valueOf(value), index);
 191  
     }
 192  
 
 193  
     @Override public void putAll(String key, Object value)
 194  
     {
 195  3
         if (value != null)
 196  
         {
 197  2
             requireArray(value.getClass());
 198  
         }
 199  
 
 200  2
         remove(key);
 201  2
         if (value != null)
 202  
         {
 203  1
             int n = Array.getLength(value);
 204  
 
 205  5
             for (int i = 0; i < n; i++)
 206  
             {
 207  4
                 add(key, Array.get(value, i));
 208  
             }
 209  
         }
 210  2
     }
 211  
 
 212  
     @Override public void to(Object bean)
 213  
     {
 214  29
         BeanTool.getInstance().inject(bean, getDefaultBeanAccess());
 215  29
     }
 216  
 
 217  
     @Override public void to(Object bean, String keyPrefix)
 218  
     {
 219  22
         BeanTool.getInstance().inject(bean, newBeanAccess(keyPrefix));
 220  22
     }
 221  
 
 222  
     synchronized BeanAccess getDefaultBeanAccess()
 223  
     {
 224  216
         if (_defaultBeanAccess == null)
 225  
         {
 226  178
             _defaultBeanAccess = newBeanAccess();
 227  
         }
 228  
 
 229  216
         return _defaultBeanAccess;
 230  
     }
 231  
 
 232  
     boolean isPropertyFirstUpper()
 233  
     {
 234  762
         return _propertyFirstUpper;
 235  
     }
 236  
 
 237  
     BeanAccess newBeanAccess()
 238  
     {
 239  181
         return new Access();
 240  
     }
 241  
 
 242  
     BeanAccess newBeanAccess(String propertyNamePrefix)
 243  
     {
 244  43
         return new Access(propertyNamePrefix);
 245  
     }
 246  
 
 247  
     void resolve(StringBuilder buffer)
 248  
     {
 249  51
         Matcher m = EXPRESSION.matcher(buffer);
 250  
 
 251  100
         while (m.find())
 252  
         {
 253  49
             String name = m.group(G_OPTION);
 254  49
             int index = (m.group(G_INDEX) == null) ? -1 : Integer.parseInt(m.group(G_INDEX));
 255  
             String value;
 256  
 
 257  49
             if (name.startsWith(ENVIRONMENT_PREFIX))
 258  
             {
 259  1
                 value = Config.getEnvironment(name.substring(ENVIRONMENT_PREFIX_LEN));
 260  
             }
 261  48
             else if (name.startsWith(SYSTEM_PROPERTY_PREFIX))
 262  
             {
 263  1
                 value = Config.getSystemProperty(name.substring(SYSTEM_PROPERTY_PREFIX_LEN));
 264  
             }
 265  
             else
 266  
             {
 267  47
                 value = (index == -1) ? fetch(name) : fetch(name, index);
 268  
             }
 269  
 
 270  49
             if (value != null)
 271  
             {
 272  48
                 buffer.replace(m.start(), m.end(), value);
 273  48
                 m.reset(buffer);
 274  
             }
 275  49
         }
 276  51
     }
 277  
 
 278  
     private void requireArray(Class clazz)
 279  
     {
 280  9
         if (!clazz.isArray())
 281  
         {
 282  3
             throw new IllegalArgumentException("Array required");
 283  
         }
 284  6
     }
 285  
 
 286  
     class Access implements BeanAccess
 287  
     {
 288  
         private final String _prefix;
 289  
 
 290  
         Access()
 291  
         {
 292  181
             this(null);
 293  181
         }
 294  
 
 295  
         Access(String prefix)
 296  224
         {
 297  224
             _prefix = prefix;
 298  224
         }
 299  
 
 300  
         @Override public void propAdd(String propertyName, String value)
 301  
         {
 302  59
             add(transform(propertyName), value);
 303  59
         }
 304  
 
 305  
         @Override public String propDel(String propertyName)
 306  
         {
 307  9
             return remove(transform(propertyName));
 308  
         }
 309  
 
 310  
         @Override public String propGet(String propertyName)
 311  
         {
 312  1186
             return fetch(transform(propertyName));
 313  
         }
 314  
 
 315  
         @Override public String propGet(String propertyName, int index)
 316  
         {
 317  98
             return fetch(transform(propertyName), index);
 318  
         }
 319  
 
 320  
         @Override public int propLength(String propertyName)
 321  
         {
 322  1172
             return length(transform(propertyName));
 323  
         }
 324  
 
 325  
         @Override public String propSet(String propertyName, String value)
 326  
         {
 327  200
             return put(transform(propertyName), value);
 328  
         }
 329  
 
 330  
         @Override public String propSet(String propertyName, String value, int index)
 331  
         {
 332  0
             return put(transform(propertyName), value, index);
 333  
         }
 334  
 
 335  
         private String transform(String orig)
 336  
         {
 337  2724
             String ret = orig;
 338  
 
 339  2724
             if (((_prefix != null) || isPropertyFirstUpper()) && (orig != null))
 340  
             {
 341  597
                 StringBuilder buff = new StringBuilder();
 342  
 
 343  597
                 if (_prefix != null)
 344  
                 {
 345  567
                     buff.append(_prefix);
 346  
                 }
 347  
 
 348  597
                 if (isPropertyFirstUpper())
 349  
                 {
 350  30
                     buff.append(Character.toUpperCase(orig.charAt(0)));
 351  30
                     buff.append(orig.substring(1));
 352  
                 }
 353  
                 else
 354  
                 {
 355  567
                     buff.append(orig);
 356  
                 }
 357  
 
 358  597
                 ret = buff.toString();
 359  
             }
 360  
 
 361  2724
             return ret;
 362  
         }
 363  
     }
 364  
 }