Clover coverage report - Code Coverage for hivemind release 1.1-alpha-2
Coverage timestamp: Wed Feb 23 2005 09:59:04 EST
file stats: LOC: 315   Methods: 15
NCLOC: 183   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
ConfigurationPointImpl.java 81.2% 93.4% 93.3% 90.2%
coverage coverage
 1   
 // Copyright 2004, 2005 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.hivemind.impl;
 16   
 
 17   
 import java.util.ArrayList;
 18   
 import java.util.Collections;
 19   
 import java.util.List;
 20   
 import java.util.Map;
 21   
 
 22   
 import org.apache.commons.logging.Log;
 23   
 import org.apache.commons.logging.LogFactory;
 24   
 import org.apache.hivemind.*;
 25   
 import org.apache.hivemind.ApplicationRuntimeException;
 26   
 import org.apache.hivemind.Occurances;
 27   
 import org.apache.hivemind.internal.ConfigurationPoint;
 28   
 import org.apache.hivemind.internal.Contribution;
 29   
 import org.apache.hivemind.schema.Schema;
 30   
 import org.apache.hivemind.util.ToStringBuilder;
 31   
 
 32   
 /**
 33   
  * Implementation of the {@link org.apache.hivemind.internal.ConfigurationPoint}interface; a
 34   
  * container for {@link org.apache.hivemind.internal.Contribution}s.
 35   
  * 
 36   
  * @author Howard Lewis Ship
 37   
  */
 38   
 public final class ConfigurationPointImpl extends AbstractExtensionPoint implements
 39   
         ConfigurationPoint
 40   
 {
 41   
     private static final Log LOG = LogFactory.getLog(ConfigurationPointImpl.class);
 42   
 
 43   
     /**
 44   
      * The cached elements for the extension point (if caching is enabled).
 45   
      */
 46   
     private List _elements;
 47   
 
 48   
     private List _elementsProxy;
 49   
 
 50   
     private Map _mappedElements;
 51   
 
 52   
     private Map _mappedElementsProxy;
 53   
 
 54   
     private boolean _canElementsBeMapped = false;
 55   
 
 56   
     private Occurances _expectedCount;
 57   
 
 58   
     private List _contributions;
 59   
 
 60   
     private boolean _building;
 61   
 
 62   
     private Schema _contributionsSchema;
 63   
 
 64   
     private ShutdownCoordinator _shutdownCoordinator;
 65   
 
 66  1
     protected void extendDescription(ToStringBuilder builder)
 67   
     {
 68  1
         builder.append("expectedCount", _expectedCount);
 69  1
         builder.append("contributions", _contributions);
 70  1
         builder.append("schema", _contributionsSchema);
 71   
     }
 72   
 
 73   
     /**
 74   
      * Returns the number of contributions; it is expected that each top-level
 75   
      * {@link org.apache.hivemind.Element}in each {@link Contribution}will convert to one element
 76   
      * instance; the value returned is the total number of top-level elements in all contributed
 77   
      * Extensions.
 78   
      */
 79  924
     public int getContributionCount()
 80   
     {
 81  924
         if (_contributions == null)
 82  328
             return 0;
 83   
 
 84  596
         int total = 0;
 85   
 
 86  596
         int count = _contributions.size();
 87  596
         for (int i = 0; i < count; i++)
 88   
         {
 89  608
             Contribution c = (Contribution) _contributions.get(i);
 90  608
             total += c.getElements().size();
 91   
         }
 92   
 
 93  596
         return total;
 94   
     }
 95   
 
 96  608
     public void addContribution(Contribution c)
 97   
     {
 98  608
         if (_contributions == null)
 99  596
             _contributions = new ArrayList();
 100   
 
 101  608
         _contributions.add(c);
 102   
     }
 103   
 
 104  924
     public Occurances getExpectedCount()
 105   
     {
 106  924
         return _expectedCount;
 107   
     }
 108   
 
 109  924
     public void setExpectedCount(Occurances occurances)
 110   
     {
 111  924
         _expectedCount = occurances;
 112   
     }
 113   
 
 114   
     /**
 115   
      * Returns the contributed elements as an unmodifiable {@link List}. Internally, a proxy to the
 116   
      * real list is returned, such that the real list may not be constructed until actually needed.
 117   
      */
 118  483
     public synchronized List getElements()
 119   
     {
 120  483
         if (_elements != null)
 121  1
             return _elements;
 122   
 
 123  482
         if (_elementsProxy == null)
 124   
         {
 125  476
             ElementsProxyList outerProxy = new ElementsProxyList();
 126   
 
 127  476
             new ElementsInnerProxyList(this, outerProxy);
 128   
 
 129  476
             _shutdownCoordinator.addRegistryShutdownListener(outerProxy);
 130   
 
 131  476
             _elementsProxy = outerProxy;
 132   
         }
 133   
 
 134  482
         return _elementsProxy;
 135   
     }
 136   
 
 137  692
     public boolean canElementsBeMapped()
 138   
     {
 139  692
         return _canElementsBeMapped;
 140   
     }
 141   
 
 142   
     /**
 143   
      * Returns the contributed elements as an unmodifiable {@link Map}. Internally, a proxy to the
 144   
      * real map is returned, such that the real map may not be constructed until actually needed.
 145   
      */
 146  111
     public synchronized Map getMappedElements()
 147   
     {
 148  111
         if (!canElementsBeMapped())
 149  0
             throw new ApplicationRuntimeException(ImplMessages.unableToMapConfiguration(this));
 150   
 
 151  111
         if (_mappedElements != null)
 152  0
             return _mappedElements;
 153   
 
 154  111
         if (_mappedElementsProxy == null)
 155   
         {
 156  110
             ElementsProxyMap outerProxy = new ElementsProxyMap();
 157   
 
 158  110
             new ElementsInnerProxyMap(this, outerProxy);
 159   
 
 160  110
             _shutdownCoordinator.addRegistryShutdownListener(outerProxy);
 161   
 
 162  110
             _mappedElementsProxy = outerProxy;
 163   
         }
 164   
 
 165  111
         return _mappedElementsProxy;
 166   
     }
 167   
 
 168   
     /**
 169   
      * Invoked by {@link ElementsInnerProxyList}when the actual list is needed. Returns the List
 170   
      * (which is modifiable, but that's OK because ElementsInnerProxyList is unmodifiable) created
 171   
      * by calling {@link #processContributionElements()}.
 172   
      */
 173  472
     synchronized List constructElements()
 174   
     {
 175   
         // It's nice to have this protection, but (unlike services), you
 176   
         // would really have to go out of your way to provoke
 177   
         // a recursive configuration.
 178   
 
 179  472
         if (_building)
 180  0
             throw new ApplicationRuntimeException(ImplMessages
 181   
                     .recursiveConfiguration(getExtensionPointId()));
 182   
 
 183  472
         try
 184   
         {
 185  472
             if (_elements == null)
 186   
             {
 187  472
                 _building = true;
 188   
 
 189  472
                 processContributionElements();
 190   
             }
 191   
 
 192   
             // Now that we have the real list, we don't need the proxy anymore, either.
 193   
 
 194  469
             _elementsProxy = null;
 195   
 
 196  469
             return _elements;
 197   
         }
 198   
         finally
 199   
         {
 200  472
             _building = false;
 201   
         }
 202   
     }
 203   
 
 204   
     /**
 205   
      * Analoguously to {@link #constructElements()}this method will be called by
 206   
      * {@link ElementsInnerProxyMap}to construct the actual map.
 207   
      */
 208  109
     synchronized Map constructMapElements()
 209   
     {
 210   
         // It's nice to have this protection, but (unlike services), you
 211   
         // would really have to go out of your way to provoke
 212   
         // a recursive configuration.
 213   
 
 214  109
         if (_building)
 215  0
             throw new ApplicationRuntimeException(ImplMessages
 216   
                     .recursiveConfiguration(getExtensionPointId()));
 217   
 
 218  109
         try
 219   
         {
 220  109
             if (_mappedElements == null)
 221   
             {
 222  109
                 _building = true;
 223   
 
 224  109
                 processContributionElements();
 225   
             }
 226   
 
 227   
             // Now that we have the real map, we don't need the proxy anymore, either.
 228   
 
 229  109
             _mappedElementsProxy = null;
 230   
 
 231  109
             return _mappedElements;
 232   
         }
 233   
         finally
 234   
         {
 235  109
             _building = false;
 236   
         }
 237   
     }
 238   
 
 239   
     /**
 240   
      * Processes the contribution elements using the
 241   
      * {@link org.apache.hivemind.schema.SchemaProcessor}. The processed contributions will be
 242   
      * stored as an immutable list (in {@link #_elements}) and as an immutable map (in
 243   
      * {@link #_mappedElements}) if applicable (see {@link #canElementsBeMapped()}).
 244   
      */
 245  581
     private void processContributionElements()
 246   
     {
 247  581
         if (LOG.isDebugEnabled())
 248  70
             LOG.debug("Constructing extension point " + getExtensionPointId());
 249   
 
 250  581
         if (_contributions == null)
 251   
         {
 252  108
             _elements = Collections.EMPTY_LIST;
 253  108
             _mappedElements = Collections.EMPTY_MAP;
 254   
 
 255  108
             return;
 256   
         }
 257   
 
 258  473
         SchemaProcessorImpl processor = new SchemaProcessorImpl(getErrorLog(), _contributionsSchema);
 259   
 
 260  473
         int count = _contributions.size();
 261   
 
 262  473
         try
 263   
         {
 264  473
             for (int i = 0; i < count; i++)
 265   
             {
 266  479
                 Contribution extension = (Contribution) _contributions.get(i);
 267   
 
 268  479
                 processor.process(extension.getElements(), extension.getContributingModule());
 269   
             }
 270   
         }
 271   
         catch (Exception ex)
 272   
         {
 273  3
             throw new ApplicationRuntimeException(ImplMessages.unableToConstructConfiguration(
 274   
                     getExtensionPointId(),
 275   
                     ex), ex);
 276   
         }
 277   
 
 278  470
         if (canElementsBeMapped())
 279  109
             _mappedElements = Collections.unmodifiableMap(processor.getMappedElements());
 280   
 
 281  470
         _elements = Collections.unmodifiableList(processor.getElements());
 282   
 
 283   
         // After constructing the result, if the result
 284   
         // will be cached, then there's no need to keep
 285   
         // the schema and extensions (used to build the
 286   
         // result); it can all be released to the GC.
 287   
 
 288  470
         _contributionsSchema = null;
 289  470
         _contributions = null;
 290   
     }
 291   
 
 292  0
     public Schema getSchema()
 293   
     {
 294  0
         return _contributionsSchema;
 295   
     }
 296   
 
 297  924
     public void setContributionsSchema(Schema schema)
 298   
     {
 299  924
         _contributionsSchema = schema;
 300   
 
 301  924
         _canElementsBeMapped = _contributionsSchema != null
 302   
                 && _contributionsSchema.canInstancesBeKeyed();
 303   
     }
 304   
 
 305  1
     public Schema getContributionsSchema()
 306   
     {
 307  1
         return _contributionsSchema;
 308   
     }
 309   
 
 310  924
     public void setShutdownCoordinator(ShutdownCoordinator coordinator)
 311   
     {
 312  924
         _shutdownCoordinator = coordinator;
 313   
     }
 314   
 
 315   
 }