Clover coverage report - brownies library - 1.0-beta-1
Coverage timestamp: 月 8 16 2004 17:14:42 GMT+09:00
file stats: LOC: 272   Methods: 18
NCLOC: 112   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
MapTree.java 69.2% 84.6% 83.3% 80.2%
coverage coverage
 1   
 /*
 2   
  * Joey and its relative products are published under the terms
 3   
  * of the Apache Software License.
 4   
  */
 5   
 /*
 6   
  * Created on 2004/01/04
 7   
  */
 8   
 package org.asyrinx.brownie.core.collection;
 9   
 
 10   
 import java.util.HashMap;
 11   
 import java.util.Iterator;
 12   
 import java.util.Map;
 13   
 import java.util.Properties;
 14   
 
 15   
 import org.asyrinx.brownie.core.lang.ArrayUtils;
 16   
 import org.asyrinx.brownie.core.lang.StringUtils;
 17   
 
 18   
 /**
 19   
  * 連鎖したマップをツリー構造として扱うためのクラスです。 <br>
 20   
  * Propertiesクラスへのシリアライズ、デシリアライズが可能です。 <br>
 21   
  * 例えば、以下のような要素を持っているPropertiesオブジェクトがあるとします。 <br>
 22   
  * 
 23   
  * <pre>
 24   
  * 
 25   
  *  
 26   
  *   
 27   
  *    aaa.aaa = 000
 28   
  *    aaa.bbb.ccc = 111
 29   
  *    aaa.bbb.ddd = 222
 30   
  *    aaa.bbb.eee.fff = 333
 31   
  *    
 32   
  *   
 33   
  *  
 34   
  * </pre>
 35   
  * 
 36   
  * このPropertiesオブジェクトをloadFromするとMapTreeオブジェクトは、 内部的に以下のようなMapのツリーを作成します。
 37   
  * 
 38   
  * <pre>
 39   
  * 
 40   
  *  
 41   
  *   
 42   
  *    (root:Map)根
 43   
  *      - aaa = Map 枝
 44   
  *        - aaa = 000 葉
 45   
  *        - bbb = Map 枝
 46   
  *          - ccc = 111 葉
 47   
  *          - ddd = 222 葉
 48   
  *          - eee = Map 枝
 49   
  *            - fff = 333 葉
 50   
  *    
 51   
  *   
 52   
  *  
 53   
  * </pre>
 54   
  * 
 55   
  * rootとなるMapはgetRootメソッドで取得が可能です。 <br>
 56   
  * またaaaやcccなどの要素もgetMapメソッドによって取得が可能です。 <br>
 57   
  * 
 58   
  * @author akima
 59   
  */
 60   
 public class MapTree {
 61   
 
 62   
     /**
 63   
      *  
 64   
      */
 65  3
     public MapTree() {
 66  3
         this(new HashMap());
 67   
     }
 68   
 
 69   
     /**
 70   
      *  
 71   
      */
 72  4
     public MapTree(Map root) {
 73  4
         super();
 74  4
         this.root = root;
 75   
     }
 76   
 
 77   
     /**
 78   
      *  
 79   
      */
 80  0
     public MapTree(MapTree mapTree) {
 81  0
         this(mapTree.getRoot());
 82   
     }
 83   
 
 84   
     protected final Map root;
 85   
 
 86   
     protected String keyDelimiter = ".";
 87   
 
 88  44
     protected Object[] toKeys(Object key) {
 89  44
         final String keyStr = String.valueOf(key);
 90  44
         return StringUtils.tokenizeToArray(keyStr, keyDelimiter);
 91   
     }
 92   
 
 93   
     /**
 94   
      * MapTreeに要素を追加します。
 95   
      * 
 96   
      * @param key
 97   
      *               Objectの配列あるいは文字列として扱われます。
 98   
      *               keyにオブジェクトの配列を指定した場合、その配列の各要素がツリーの枝となります。
 99   
      *               文字列の場合、keyDelimiterプロパティで指定した文字列によって分解され、 分解された各要素がツリーの枝となります。
 100   
      *               もし、キーによって指定されたが存在しない場合には自動的に作成されます。
 101   
      * 
 102   
      * @param value
 103   
      *               追加される要素です。
 104   
      */
 105  23
     public void put(Object key, Object value) {
 106  23
         if (key instanceof Object[]) {
 107  0
             put((Object[]) key, value);
 108   
         } else {
 109  23
             put(toKeys(key), value);
 110   
         }
 111   
     }
 112   
 
 113   
     /**
 114   
      * キーによって指定された枝あるいは葉を返します。
 115   
      * 
 116   
      * @param key
 117   
      *               Objectの配列あるいは文字列として扱われます。
 118   
      *               keyにオブジェクトの配列を指定した場合、その配列の各要素がツリーの枝となります。
 119   
      *               文字列の場合、keyDelimiterプロパティで指定した文字列によって分解され、 分解された各要素がツリーの枝となります。
 120   
      * 
 121   
      * @return キーによって指定されたが存在しない場合にはnullが返されます。
 122   
      */
 123  12
     public Object get(Object key) {
 124  12
         if (key instanceof Object[]) {
 125  0
             return get((Object[]) key);
 126   
         } else {
 127  12
             return get(toKeys(key));
 128   
         }
 129   
     }
 130   
 
 131   
     /**
 132   
      * @param key
 133   
      *               その配列の各要素がツリーの枝となります。 もし、キーによって指定されたが存在しない場合には自動的に作成されます。
 134   
      * 
 135   
      * @param value
 136   
      *               追加される要素です。
 137   
      */
 138  23
     public void put(Object[] key, Object value) {
 139  23
         if (key == null || key.length == 0)
 140  0
             return;
 141  23
         final Map map = (key.length == 1) ? root : needMap(ArrayUtils.subArray(key, 0, key.length - 1));
 142  23
         map.put(key[key.length - 1], value);
 143   
     }
 144   
 
 145   
     /**
 146   
      * キーによって指定された枝あるいは葉を返します。
 147   
      * 
 148   
      * @param key
 149   
      *               配列の各要素がツリーの枝として扱われます。
 150   
      * 
 151   
      * @return キーによって指定されたが存在しない場合にはnullが返されます。
 152   
      */
 153  12
     public Object get(Object[] keys) {
 154  12
         if (keys == null || keys.length == 0)
 155  0
             return null;
 156  12
         final Map map = (keys.length == 1) ? root : getMap(ArrayUtils.subArray(keys, 0, keys.length - 1));
 157  12
         return (map == null) ? null : map.get(keys[keys.length - 1]);
 158   
     }
 159   
 
 160   
     /**
 161   
      * MapTreeオブジェクトが保持する根のMapオブジェクトを返します。
 162   
      * 
 163   
      * @return
 164   
      */
 165  2
     public Map getRoot() {
 166  2
         return root;
 167   
     }
 168   
 
 169   
     /**
 170   
      * キーによって指定された枝のMapオブジェクトを返します。
 171   
      * 
 172   
      * @param key
 173   
      *               Objectの配列あるいは文字列として扱われます。
 174   
      *               keyにオブジェクトの配列を指定した場合、その配列の各要素がツリーの枝となります。
 175   
      *               文字列の場合、keyDelimiterプロパティで指定した文字列によって分解され、 分解された各要素がツリーの枝となります。
 176   
      * @return
 177   
      */
 178  9
     public Map getMap(Object key) {
 179  9
         if (key instanceof Object[]) {
 180  0
             return getMap((Object[]) key);
 181   
         } else {
 182  9
             return getMap(toKeys(key));
 183   
         }
 184   
     }
 185   
 
 186   
     /**
 187   
      * キーによって指定された枝のMapオブジェクトを返します。
 188   
      * 
 189   
      * @param key
 190   
      *               配列の各要素がツリーの枝として扱われます。
 191   
      * @return
 192   
      */
 193  21
     protected Map getMap(Object[] keys) {
 194  21
         Map current = root;
 195  21
         for (int i = 0; i < keys.length; i++) {
 196  39
             Object val = current.get(keys[i]);
 197  39
             if (val instanceof Map) {
 198  35
                 current = (Map) val;
 199   
             } else {
 200  4
                 return null;
 201   
             }
 202   
         }
 203  17
         return current;
 204   
     }
 205   
 
 206  23
     protected Map needMap(Object[] keys) {
 207  23
         Map current = root;
 208  23
         for (int i = 0; i < keys.length; i++) {
 209  46
             Object val = current.get(keys[i]);
 210  46
             if (val instanceof Map) {
 211  25
                 current = (Map) val;
 212   
             } else {
 213  21
                 final Map newMap = createMap();
 214  21
                 current.put(keys[i], newMap);
 215  21
                 current = newMap;
 216   
             }
 217   
         }
 218  23
         return current;
 219   
     }
 220   
 
 221  16
     protected Map createMap() {
 222  16
         return new HashMap();
 223   
     }
 224   
 
 225   
     /**
 226   
      * 文字列でキーを指定した場合に各枝の名称として分割するための文字列です。
 227   
      * 
 228   
      * @return
 229   
      */
 230  0
     public String getKeyDelimiter() {
 231  0
         return keyDelimiter;
 232   
     }
 233   
 
 234   
     /**
 235   
      * 文字列でキーを指定した場合に各枝の名称として分割するための文字列です。
 236   
      * 
 237   
      * @param string
 238   
      */
 239  0
     public void setKeyDelimiter(String string) {
 240  0
         keyDelimiter = string;
 241   
     }
 242   
 
 243   
     /**
 244   
      * 保持するデータをPropertiesオブジェクトにシリアライズします。
 245   
      * 
 246   
      * @param properties
 247   
      */
 248  1
     public void saveTo(Properties properties) {
 249  1
         final Properties props = properties;
 250  1
         final MapTreeVisitor visitor = new MapTreeVisitor(this.root) {
 251  7
             public void doOnLeaf(Object value) {
 252  7
                 final String key = StringUtils.join(keyStack.iterator(), keyDelimiter);
 253  7
                 props.put(key, value);
 254   
             }
 255   
         };
 256  1
         visitor.execute();
 257   
     }
 258   
 
 259   
     /**
 260   
      * Propertiesオブジェクトからデータをデシリアライズします。
 261   
      * 
 262   
      * @param properties
 263   
      */
 264  1
     public void loadFrom(Properties properties) {
 265  1
         final Iterator iterator = properties.keySet().iterator();
 266  1
         while (iterator.hasNext()) {
 267  5
             final Object key = iterator.next();
 268  5
             this.put(key, properties.get(key));
 269   
         }
 270   
     }
 271   
 
 272   
 }