Clover coverage report - brownies library - 1.0-beta-1 Coverage timestamp: 月 8 16 2004 17:14:42 GMT+09:00 FRAMES NO FRAMES |
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% |

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 |  |
     }