Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.configuration.HierarchicalConfigurationConverter |
100% |
100% |

1 |  |
     /*
2 |  |
      * Copyright 2001-2004 The Apache Software Foundation.
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 |  |
17 |  |
     package org.apache.commons.configuration;
18 |  |
19 |  |
     import java.util.ArrayList;
20 |  |
     import java.util.Collection;
21 |  |
     import java.util.Collections;
22 |  |
     import java.util.HashSet;
23 |  |
     import java.util.Iterator;
24 |  |
     import java.util.List;
25 |  |
     import java.util.Set;
26 |  |
27 |  |
     /**
28 |  |
      * <p>A base class for converters that transform a normal configuration
29 |  |
      * object into a hierarchical configuration.</p>
30 |  |
      * <p>This class provides a default mechanism for iterating over the keys in a
31 |  |
      * configuration and to throw corresponding element start and end events. By
32 |  |
      * handling these events a hierarchy can be constructed that is equivalent to
33 |  |
      * the keys in the original configuration.</p>
34 |  |
      * <p>Concrete sub classes will implement event handlers that generate SAX
35 |  |
      * events for XML processing or construct a
36 |  |
      * <code>HierarchicalConfiguration</code> root node. All in all with this class
37 |  |
      * it is possible to treat a default configuration as if it was a hierarchical
38 |  |
      * configuration, which can be sometimes useful.</p>
39 |  |
      * @see HierarchicalConfiguration
40 |  |
      *
41 |  |
      * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
42 |  |
      * @version $Id: HierarchicalConfigurationConverter.java,v 1.6 2004/09/20 09:37:07 henning Exp $
43 |  |
      */
44 | 8 |
     abstract class HierarchicalConfigurationConverter
45 |  |
     {
46 |  |
         /**
47 |  |
          * Processes the specified configuration object. This method implements
48 |  |
          * the iteration over the configuration's keys. All defined keys are
49 |  |
          * translated into a set of element start and end events represented by
50 |  |
          * calls to the <code>elementStart()</code> and
51 |  |
          * <code>elementEnd()</code> methods.
52 |  |
          *
53 |  |
          * @param config the configuration to be processed
54 |  |
          */
55 |  |
         public void process(Configuration config)
56 |  |
         {
57 | 8 |
             if (config != null)
58 |  |
             {
59 | 8 |
                 ConfigurationKey keyEmpty = new ConfigurationKey();
60 | 8 |
                 ConfigurationKey keyLast = keyEmpty;
61 | 8 |
                 Set keySet = new HashSet();
62 |  |
63 | 8 |
                 for (Iterator it = config.getKeys(); it.hasNext();)
64 |  |
                 {
65 | 72 |
                     String key = (String) it.next();
66 | 72 |
                     if (keySet.contains(key))
67 |  |
                     {
68 |  |
                         // this key has already been processed by openElements
69 | 5 |
                         continue;
70 |  |
                     }
71 | 67 |
                     ConfigurationKey keyAct = new ConfigurationKey(key);
72 | 67 |
                     closeElements(keyLast, keyAct);
73 | 67 |
                     String elem = openElements(keyLast, keyAct, config, keySet);
74 | 67 |
                     fireValue(elem, config.getProperty(key));
75 | 67 |
                     keyLast = keyAct;
76 |  |
                 }
77 |  |
78 |  |
                 // close all open
79 | 8 |
                 closeElements(keyLast, keyEmpty);
80 |  |
             }
81 | 8 |
         }
82 |  |
83 |  |
         /**
84 |  |
          * An event handler method that is called when an element starts.
85 |  |
          * Concrete sub classes must implement it to perform a proper event
86 |  |
          * handling.
87 |  |
          *
88 |  |
          * @param name the name of the new element
89 |  |
          * @param value the element's value; can be <b>null</b> if the element
90 |  |
          * does not have any value
91 |  |
          */
92 |  |
         protected abstract void elementStart(String name, Object value);
93 |  |
94 |  |
         /**
95 |  |
          * An event handler method that is called when an element ends. For each
96 |  |
          * call of <code>elementStart()</code> there will be a corresponding call
97 |  |
          * of this method. Concrete sub classes must implement it to perform a
98 |  |
          * proper event handling.
99 |  |
          *
100 |  |
          * @param name the name of the ending element
101 |  |
          */
102 |  |
         protected abstract void elementEnd(String name);
103 |  |
104 |  |
         /**
105 |  |
          * Fires all necessary element end events for the specified keys. This
106 |  |
          * method is called for each key obtained from the configuration to be
107 |  |
          * converted. It calculates the common part of the actual and the last
108 |  |
          * processed key and thus determines how many elements must be
109 |  |
          * closed.
110 |  |
          *
111 |  |
          * @param keyLast the last processed key
112 |  |
          * @param keyAct the actual key
113 |  |
          */
114 |  |
         protected void closeElements(ConfigurationKey keyLast, ConfigurationKey keyAct)
115 |  |
         {
116 | 75 |
             ConfigurationKey keyDiff = keyAct.differenceKey(keyLast);
117 | 75 |
             Iterator it = reverseIterator(keyDiff);
118 | 75 |
             if (it.hasNext())
119 |  |
             {
120 |  |
                 // Skip first because it has already been closed by fireValue()
121 | 67 |
                 it.next();
122 |  |
             }
123 |  |
124 | 109 |
             while (it.hasNext())
125 |  |
             {
126 | 34 |
                 elementEnd((String) it.next());
127 |  |
             }
128 | 75 |
         }
129 |  |
130 |  |
         /**
131 |  |
          * Helper method for determining a reverse iterator for the specified key.
132 |  |
          * This implementation returns an iterator that returns the parts of the
133 |  |
          * given key in reverse order, ignoring indices.
134 |  |
          *
135 |  |
          * @param key the key
136 |  |
          * @return a reverse iterator for the parts of this key
137 |  |
          */
138 |  |
         protected Iterator reverseIterator(ConfigurationKey key)
139 |  |
         {
140 | 75 |
             List list = new ArrayList();
141 | 75 |
             for (ConfigurationKey.KeyIterator it = key.iterator(); it.hasNext();)
142 |  |
             {
143 | 101 |
                 list.add(it.nextKey());
144 |  |
             }
145 |  |
146 | 75 |
             Collections.reverse(list);
147 | 75 |
             return list.iterator();
148 |  |
         }
149 |  |
150 |  |
         /**
151 |  |
          * Fires all necessary element start events for the specified key. This
152 |  |
          * method is called for each key obtained from the configuration to be
153 |  |
          * converted. It ensures that all elements "between" the last key and the
154 |  |
          * actual key are opened and their values are set.
155 |  |
          *
156 |  |
          * @param keyLast the last processed key
157 |  |
          * @param keyAct the actual key
158 |  |
          * @param config the configuration to process
159 |  |
          * @param keySet the set with the processed keys
160 |  |
          * @return the name of the last element on the path
161 |  |
          */
162 |  |
         protected String openElements(ConfigurationKey keyLast, ConfigurationKey keyAct, Configuration config, Set keySet)
163 |  |
         {
164 | 67 |
             ConfigurationKey.KeyIterator it = keyLast.differenceKey(keyAct).iterator();
165 | 67 |
             ConfigurationKey k = keyLast.commonKey(keyAct);
166 | 101 |
             for (it.nextKey(); it.hasNext(); it.nextKey())
167 |  |
             {
168 | 34 |
                 k.append(it.currentKey(true));
169 | 34 |
                 elementStart(it.currentKey(true), config.getProperty(k.toString()));
170 | 34 |
                 keySet.add(k.toString());
171 |  |
             }
172 | 67 |
             return it.currentKey(true);
173 |  |
         }
174 |  |
175 |  |
         /**
176 |  |
          * Fires all necessary element start events with the actual element values.
177 |  |
          * This method is called for each key obtained from the configuration to be
178 |  |
          * processed with the last part of the key as argument. The value can be
179 |  |
          * either a single value or a collection.
180 |  |
          *
181 |  |
          * @param name the name of the actual element
182 |  |
          * @param value the element's value
183 |  |
          */
184 |  |
         protected void fireValue(String name, Object value)
185 |  |
         {
186 | 96 |
             if (value != null && value instanceof Collection)
187 |  |
             {
188 | 9 |
                 for (Iterator it = ((Collection) value).iterator(); it.hasNext();)
189 |  |
                 {
190 | 29 |
                     fireValue(name, it.next());
191 |  |
                 }
192 |  |
             }
193 |  |
             else
194 |  |
             {
195 | 87 |
                 elementStart(name, value);
196 | 87 |
                 elementEnd(name);
197 |  |
             }
198 | 96 |
         }
199 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.