Coverage Report - org.ini4j.BasicProfile
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicProfile
100%
85/85
100%
44/44
1.882
BasicProfile$1
N/A
N/A
1.882
BasicProfile$BeanInvocationHandler
100%
31/31
100%
16/16
1.882
 
 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.AbstractBeanInvocationHandler;
 19  
 import org.ini4j.spi.BeanTool;
 20  
 import org.ini4j.spi.IniHandler;
 21  
 
 22  
 import java.lang.reflect.Array;
 23  
 import java.lang.reflect.Proxy;
 24  
 
 25  
 import java.util.regex.Matcher;
 26  
 import java.util.regex.Pattern;
 27  
 
 28  
 public class BasicProfile extends CommonMultiMap<String, Profile.Section> implements Profile
 29  
 {
 30  
     private static final String SECTION_SYSTEM_PROPERTIES = "@prop";
 31  
     private static final String SECTION_ENVIRONMENT = "@env";
 32  1
     private static final Pattern EXPRESSION = Pattern.compile(
 33  
             "(?<!\\\\)\\$\\{(([^\\[\\}]+)(\\[([0-9]+)\\])?/)?([^\\[^/\\}]+)(\\[(([0-9]+))\\])?\\}");
 34  
     private static final int G_SECTION = 2;
 35  
     private static final int G_SECTION_IDX = 4;
 36  
     private static final int G_OPTION = 5;
 37  
     private static final int G_OPTION_IDX = 7;
 38  
     private static final long serialVersionUID = -1817521505004015256L;
 39  
     private String _comment;
 40  
     private final boolean _propertyFirstUpper;
 41  
     private final boolean _treeMode;
 42  
 
 43  
     public BasicProfile()
 44  
     {
 45  140
         this(false, false);
 46  140
     }
 47  
 
 48  
     public BasicProfile(boolean treeMode, boolean propertyFirstUpper)
 49  141
     {
 50  141
         _treeMode = treeMode;
 51  141
         _propertyFirstUpper = propertyFirstUpper;
 52  141
     }
 53  
 
 54  
     @Override public String getComment()
 55  
     {
 56  21
         return _comment;
 57  
     }
 58  
 
 59  
     @Override public void setComment(String value)
 60  
     {
 61  64
         _comment = value;
 62  64
     }
 63  
 
 64  
     @Override public Section add(String name)
 65  
     {
 66  585
         if (isTreeMode())
 67  
         {
 68  531
             int idx = name.lastIndexOf(getPathSeparator());
 69  
 
 70  531
             if (idx > 0)
 71  
             {
 72  164
                 String parent = name.substring(0, idx);
 73  
 
 74  164
                 if (!containsKey(parent))
 75  
                 {
 76  5
                     add(parent);
 77  
                 }
 78  
             }
 79  
         }
 80  
 
 81  585
         Section section = newSection(name);
 82  
 
 83  585
         add(name, section);
 84  
 
 85  585
         return section;
 86  
     }
 87  
 
 88  
     @Override public void add(String section, String option, Object value)
 89  
     {
 90  7
         getOrAdd(section).add(option, value);
 91  7
     }
 92  
 
 93  
     @Override public <T> T as(Class<T> clazz)
 94  
     {
 95  15
         return as(clazz, null);
 96  
     }
 97  
 
 98  
     @Override public <T> T as(Class<T> clazz, String prefix)
 99  
     {
 100  22
         return clazz.cast(Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { clazz },
 101  
                     new BeanInvocationHandler(prefix)));
 102  
     }
 103  
 
 104  
     @Override public String fetch(Object sectionName, Object optionName)
 105  
     {
 106  4
         Section sec = get(sectionName);
 107  
 
 108  4
         return (sec == null) ? null : sec.fetch(optionName);
 109  
     }
 110  
 
 111  
     @Override public <T> T fetch(Object sectionName, Object optionName, Class<T> clazz)
 112  
     {
 113  6
         Section sec = get(sectionName);
 114  
 
 115  6
         return (sec == null) ? BeanTool.getInstance().zero(clazz) : sec.fetch(optionName, clazz);
 116  
     }
 117  
 
 118  
     @Override public String get(Object sectionName, Object optionName)
 119  
     {
 120  5
         Section sec = get(sectionName);
 121  
 
 122  5
         return (sec == null) ? null : sec.get(optionName);
 123  
     }
 124  
 
 125  
     @Override public <T> T get(Object sectionName, Object optionName, Class<T> clazz)
 126  
     {
 127  6
         Section sec = get(sectionName);
 128  
 
 129  6
         return (sec == null) ? BeanTool.getInstance().zero(clazz) : sec.get(optionName, clazz);
 130  
     }
 131  
 
 132  
     @Override public String put(String sectionName, String optionName, Object value)
 133  
     {
 134  5
         return getOrAdd(sectionName).put(optionName, value);
 135  
     }
 136  
 
 137  
     @Override public Section remove(Section section)
 138  
     {
 139  9
         return remove((Object) section.getName());
 140  
     }
 141  
 
 142  
     @Override public String remove(Object sectionName, Object optionName)
 143  
     {
 144  2
         Section sec = get(sectionName);
 145  
 
 146  2
         return (sec == null) ? null : sec.remove(optionName);
 147  
     }
 148  
 
 149  
     boolean isTreeMode()
 150  
     {
 151  33
         return _treeMode;
 152  
     }
 153  
 
 154  
     char getPathSeparator()
 155  
     {
 156  89
         return PATH_SEPARATOR;
 157  
     }
 158  
 
 159  
     boolean isPropertyFirstUpper()
 160  
     {
 161  654
         return _propertyFirstUpper;
 162  
     }
 163  
 
 164  
     Section newSection(String name)
 165  
     {
 166  449
         return new BasicProfileSection(this, name);
 167  
     }
 168  
 
 169  
     void resolve(StringBuilder buffer, Section owner)
 170  
     {
 171  171
         Matcher m = EXPRESSION.matcher(buffer);
 172  
 
 173  346
         while (m.find())
 174  
         {
 175  175
             String sectionName = m.group(G_SECTION);
 176  175
             String optionName = m.group(G_OPTION);
 177  175
             int optionIndex = parseOptionIndex(m);
 178  175
             Section section = parseSection(m, owner);
 179  175
             String value = null;
 180  
 
 181  175
             if (SECTION_ENVIRONMENT.equals(sectionName))
 182  
             {
 183  1
                 value = Config.getEnvironment(optionName);
 184  
             }
 185  174
             else if (SECTION_SYSTEM_PROPERTIES.equals(sectionName))
 186  
             {
 187  1
                 value = Config.getSystemProperty(optionName);
 188  
             }
 189  173
             else if (section != null)
 190  
             {
 191  172
                 value = (optionIndex == -1) ? section.fetch(optionName) : section.fetch(optionName, optionIndex);
 192  
             }
 193  
 
 194  175
             if (value != null)
 195  
             {
 196  172
                 buffer.replace(m.start(), m.end(), value);
 197  172
                 m.reset(buffer);
 198  
             }
 199  175
         }
 200  171
     }
 201  
 
 202  
     void store(IniHandler formatter)
 203  
     {
 204  16
         formatter.startIni();
 205  16
         store(formatter, getComment());
 206  16
         for (Ini.Section s : values())
 207  
         {
 208  85
             store(formatter, s);
 209  
         }
 210  
 
 211  16
         formatter.endIni();
 212  16
     }
 213  
 
 214  
     void store(IniHandler formatter, Section s)
 215  
     {
 216  85
         store(formatter, getComment(s.getName()));
 217  85
         formatter.startSection(s.getName());
 218  85
         for (String name : s.keySet())
 219  
         {
 220  328
             store(formatter, s, name);
 221  
         }
 222  
 
 223  85
         formatter.endSection();
 224  85
     }
 225  
 
 226  
     void store(IniHandler formatter, String comment)
 227  
     {
 228  429
         formatter.handleComment(comment);
 229  429
     }
 230  
 
 231  
     void store(IniHandler formatter, Section section, String option)
 232  
     {
 233  239
         store(formatter, section.getComment(option));
 234  239
         int n = section.length(option);
 235  
 
 236  507
         for (int i = 0; i < n; i++)
 237  
         {
 238  268
             store(formatter, section, option, i);
 239  
         }
 240  239
     }
 241  
 
 242  
     void store(IniHandler formatter, Section section, String option, int index)
 243  
     {
 244  265
         formatter.handleOption(option, section.get(option, index));
 245  265
     }
 246  
 
 247  
     private Section getOrAdd(String sectionName)
 248  
     {
 249  12
         Section section = get(sectionName);
 250  
 
 251  12
         return ((section == null)) ? add(sectionName) : section;
 252  
     }
 253  
 
 254  
     private int parseOptionIndex(Matcher m)
 255  
     {
 256  175
         return (m.group(G_OPTION_IDX) == null) ? -1 : Integer.parseInt(m.group(G_OPTION_IDX));
 257  
     }
 258  
 
 259  
     private Section parseSection(Matcher m, Section owner)
 260  
     {
 261  175
         String sectionName = m.group(G_SECTION);
 262  175
         int sectionIndex = parseSectionIndex(m);
 263  
 
 264  175
         return (sectionName == null) ? owner : ((sectionIndex == -1) ? get(sectionName) : get(sectionName, sectionIndex));
 265  
     }
 266  
 
 267  
     private int parseSectionIndex(Matcher m)
 268  
     {
 269  175
         return (m.group(G_SECTION_IDX) == null) ? -1 : Integer.parseInt(m.group(G_SECTION_IDX));
 270  
     }
 271  
 
 272  22
     private final class BeanInvocationHandler extends AbstractBeanInvocationHandler
 273  
     {
 274  
         private final String _prefix;
 275  
 
 276  
         private BeanInvocationHandler(String prefix)
 277  22
         {
 278  22
             _prefix = prefix;
 279  22
         }
 280  
 
 281  
         @Override protected Object getPropertySpi(String property, Class<?> clazz)
 282  
         {
 283  136
             String key = transform(property);
 284  136
             Object o = null;
 285  
 
 286  136
             if (containsKey(key))
 287  
             {
 288  133
                 if (clazz.isArray())
 289  
                 {
 290  2
                     o = Array.newInstance(clazz.getComponentType(), length(key));
 291  5
                     for (int i = 0; i < length(key); i++)
 292  
                     {
 293  3
                         Array.set(o, i, get(key, i).as(clazz.getComponentType()));
 294  
                     }
 295  
                 }
 296  
                 else
 297  
                 {
 298  131
                     o = get(key).as(clazz);
 299  
                 }
 300  
             }
 301  
 
 302  136
             return o;
 303  
         }
 304  
 
 305  
         @Override protected void setPropertySpi(String property, Object value, Class<?> clazz)
 306  
         {
 307  5
             String key = transform(property);
 308  
 
 309  5
             remove(key);
 310  5
             if (value != null)
 311  
             {
 312  4
                 if (clazz.isArray())
 313  
                 {
 314  3
                     for (int i = 0; i < Array.getLength(value); i++)
 315  
                     {
 316  2
                         Section sec = add(key);
 317  
 
 318  2
                         sec.from(Array.get(value, i));
 319  
                     }
 320  
                 }
 321  
                 else
 322  
                 {
 323  3
                     Section sec = add(key);
 324  
 
 325  3
                     sec.from(value);
 326  
                 }
 327  
             }
 328  5
         }
 329  
 
 330  
         @Override protected boolean hasPropertySpi(String property)
 331  
         {
 332  1
             return containsKey(transform(property));
 333  
         }
 334  
 
 335  
         String transform(String property)
 336  
         {
 337  142
             String ret = (_prefix == null) ? property : (_prefix + property);
 338  
 
 339  142
             if (isPropertyFirstUpper())
 340  
             {
 341  2
                 StringBuilder buff = new StringBuilder();
 342  
 
 343  2
                 buff.append(Character.toUpperCase(property.charAt(0)));
 344  2
                 buff.append(property.substring(1));
 345  2
                 ret = buff.toString();
 346  
             }
 347  
 
 348  142
             return ret;
 349  
         }
 350  
     }
 351  
 }