2009/04/15 - Apache HiveMind has been retired.

For more information, please explore the Attic.

Clover coverage report - Code Coverage for hivemind release 1.2.1
Coverage timestamp: Fri Feb 10 2006 16:33:43 PST
file stats: LOC: 315   Methods: 15
NCLOC: 183   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ConfigurationPointImpl.java 78.1% 93.4% 93.3% 89.4%
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  1038 public int getContributionCount()
 80    {
 81  1038 if (_contributions == null)
 82  371 return 0;
 83   
 84  667 int total = 0;
 85   
 86  667 int count = _contributions.size();
 87  667 for (int i = 0; i < count; i++)
 88    {
 89  679 Contribution c = (Contribution) _contributions.get(i);
 90  679 total += c.getElements().size();
 91    }
 92   
 93  667 return total;
 94    }
 95   
 96  679 public void addContribution(Contribution c)
 97    {
 98  679 if (_contributions == null)
 99  667 _contributions = new ArrayList();
 100   
 101  679 _contributions.add(c);
 102    }
 103   
 104  1038 public Occurances getExpectedCount()
 105    {
 106  1038 return _expectedCount;
 107    }
 108   
 109  1038 public void setExpectedCount(Occurances occurances)
 110    {
 111  1038 _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  539 public synchronized List getElements()
 119    {
 120  539 if (_elements != null)
 121  1 return _elements;
 122   
 123  538 if (_elementsProxy == null)
 124    {
 125  533 ElementsProxyList outerProxy = new ElementsProxyList();
 126   
 127  533 new ElementsInnerProxyList(this, outerProxy);
 128   
 129  533 _shutdownCoordinator.addRegistryShutdownListener(outerProxy);
 130   
 131  533 _elementsProxy = outerProxy;
 132    }
 133   
 134  538 return _elementsProxy;
 135    }
 136   
 137  775 public boolean areElementsMappable()
 138    {
 139  775 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  124 public synchronized Map getElementsAsMap()
 147    {
 148  124 if (!areElementsMappable())
 149  0 throw new ApplicationRuntimeException(ImplMessages.unableToMapConfiguration(this));
 150   
 151  124 if (_mappedElements != null)
 152  0 return _mappedElements;
 153   
 154  124 if (_mappedElementsProxy == null)
 155    {
 156  124 ElementsProxyMap outerProxy = new ElementsProxyMap();
 157   
 158  124 new ElementsInnerProxyMap(this, outerProxy);
 159   
 160  124 _shutdownCoordinator.addRegistryShutdownListener(outerProxy);
 161   
 162  124 _mappedElementsProxy = outerProxy;
 163    }
 164   
 165  124 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  529 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  529 if (_building)
 180  0 throw new ApplicationRuntimeException(ImplMessages
 181    .recursiveConfiguration(getExtensionPointId()));
 182   
 183  529 try
 184    {
 185  529 if (_elements == null)
 186    {
 187  529 _building = true;
 188   
 189  529 processContributionElements();
 190    }
 191   
 192    // Now that we have the real list, we don't need the proxy anymore, either.
 193   
 194  526 _elementsProxy = null;
 195   
 196  526 return _elements;
 197    }
 198    finally
 199    {
 200  529 _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  123 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  123 if (_building)
 215  0 throw new ApplicationRuntimeException(ImplMessages
 216    .recursiveConfiguration(getExtensionPointId()));
 217   
 218  123 try
 219    {
 220  123 if (_mappedElements == null)
 221    {
 222  123 _building = true;
 223   
 224  123 processContributionElements();
 225    }
 226   
 227    // Now that we have the real map, we don't need the proxy anymore, either.
 228   
 229  123 _mappedElementsProxy = null;
 230   
 231  123 return _mappedElements;
 232    }
 233    finally
 234    {
 235  123 _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 #areElementsMappable()}).
 244    */
 245  652 private void processContributionElements()
 246    {
 247  652 if (LOG.isDebugEnabled())
 248  70 LOG.debug("Constructing extension point " + getExtensionPointId());
 249   
 250  652 if (_contributions == null)
 251    {
 252  122 _elements = Collections.EMPTY_LIST;
 253  122 _mappedElements = Collections.EMPTY_MAP;
 254   
 255  122 return;
 256    }
 257   
 258  530 SchemaProcessorImpl processor = new SchemaProcessorImpl(getErrorLog(), _contributionsSchema);
 259   
 260  530 int count = _contributions.size();
 261   
 262  530 try
 263    {
 264  530 for (int i = 0; i < count; i++)
 265    {
 266  536 Contribution extension = (Contribution) _contributions.get(i);
 267   
 268  536 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  527 if (areElementsMappable())
 279  123 _mappedElements = Collections.unmodifiableMap(processor.getMappedElements());
 280   
 281  527 _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  527 _contributionsSchema = null;
 289  527 _contributions = null;
 290    }
 291   
 292  0 public Schema getSchema()
 293    {
 294  0 return _contributionsSchema;
 295    }
 296   
 297  1038 public void setContributionsSchema(Schema schema)
 298    {
 299  1038 _contributionsSchema = schema;
 300   
 301  1038 _canElementsBeMapped = _contributionsSchema != null
 302    && _contributionsSchema.canInstancesBeKeyed();
 303    }
 304   
 305  1 public Schema getContributionsSchema()
 306    {
 307  1 return _contributionsSchema;
 308    }
 309   
 310  1038 public void setShutdownCoordinator(ShutdownCoordinator coordinator)
 311    {
 312  1038 _shutdownCoordinator = coordinator;
 313    }
 314   
 315    }