Clover coverage report - Maven Clover report
Coverage timestamp: Mon Sep 3 2007 08:24:07 EEST
file stats: LOC: 376   Methods: 8
NCLOC: 242   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JPatternsConfigBeansBuilderImpl.java 71.2% 85.1% 100% 81.2%
coverage coverage
 1    package com.sourceforge.jpatterns.core.configuration.model;
 2   
 3    import com.sourceforge.jpatterns.core.JPConstants;
 4    import com.sourceforge.jpatterns.core.configuration.PropertiesBasedFactory;
 5    import com.sourceforge.jpatterns.core.configuration.PropertiesProvider;
 6    import com.sourceforge.jpatterns.core.configuration.exceptions.JPConfigException;
 7    import com.sourceforge.jpatterns.core.configuration.exceptions.JPInitializationException;
 8    import com.sourceforge.jpatterns.schema.CastorConfigType;
 9    import com.sourceforge.jpatterns.schema.CastorFactoryType;
 10    import com.sourceforge.jpatterns.schema.CastorGroupType;
 11    import com.sourceforge.jpatterns.schema.CastorGroupTypeItem;
 12    import com.sourceforge.jpatterns.schema.CastorNameScopePriorityType;
 13    import com.sourceforge.jpatterns.schema.CastorSectionType;
 14    import com.sourceforge.jpatterns.schema.Item;
 15    import com.sourceforge.jpatterns.schema.JPatternsConfig;
 16    import com.sourceforge.jpatterns.utils.CastorUtils;
 17    import com.zmicer.utils.InputArgumentUtils;
 18    import com.zmicer.utils.ObjectStateUtils;
 19    import org.apache.commons.lang.StringUtils;
 20    import org.apache.log4j.Logger;
 21   
 22    import java.util.ArrayList;
 23    import java.util.List;
 24    import java.util.Map;
 25   
 26    /**
 27    * Default, "native" implementation of the appropriate interface.
 28    *
 29    * $Author:: zmicer $<br/>
 30    * $Rev:: 67 $<br/> * $Date:: 2007-08-28 21:37:07 #$<br/>
 31    * $Date:: 2007-08-28 21:37:07 #$<br/>
 32    */
 33    public class JPatternsConfigBeansBuilderImpl implements IJPatternsConfigBeansBuilder
 34    {
 35    /**
 36    * Logger instance.
 37    */
 38    final public static Logger LOG = Logger.getLogger(JPatternsConfigBeansBuilderImpl.class);
 39   
 40    /**
 41    * value for the com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.XML_CONFIG_OVERRIDING_DEPTH property
 42    */
 43    private static String OverridingDepth;
 44   
 45    /**
 46    * value for the
 47    * com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.XML_CONFIG_CUSTOM_OVERRIDES_NOT_DEPENDING_ON_PRIORITY
 48    */
 49    private static boolean OverrideNotDependingOnPriority;
 50   
 51    /**
 52    * Initialization block.
 53    */
 54    {
 55  203 PropertiesProvider propertiesProvider =
 56    PropertiesProvider.getInstance(PropertiesBasedFactory.getInstance().getPropertiesManager(), false);
 57  203 final String depth = propertiesProvider.getStringProperty(
 58    com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.XML_CONFIG_OVERRIDING_DEPTH);
 59  203 setOverridingDepth((null == depth) ? PropertiesProvider.OverridingDepths.OVERRIDING_LEVEL_SECTION.toString() : depth);
 60  203 final Boolean property = propertiesProvider.getBooleanProperty(com.sourceforge.jpatterns.core.configuration.
 61    PropertiesProvider.JPProperties.XML_CONFIG_CUSTOM_OVERRIDES_NOT_DEPENDING_ON_PRIORITY);
 62  203 setOverrideNotDependingOnPriority((null != property) && property);
 63    }
 64   
 65    /**
 66    * @see IJPatternsConfigBeansBuilder#build(com.sourceforge.jpatterns.schema.JPatternsConfig)
 67    * <br/>
 68    * <pre>
 69    * The algorithm is used here as follows:
 70    * <strong>Sections filling</strong>:
 71    * 1. the List of "section based" objects is formed<br/>
 72    * - in the case the section has not explicit scope - the default one from the root castor object or the
 73    * {@link com.sourceforge.jpatterns.core.JPConstants.DEFAULT_SCOPE_NAME} is set.
 74    * 2. all the "section based" objects are put to the map
 75    * - in the case {@link com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.XML_CONFIG_OVERRIDING_DEPTH}
 76    * property equals to
 77    * <code>com.sourceforge.jpatterns.core.configuration.PropertiesProvider.OverridingDepths.OVERRIDING_LEVEL_ITEM</code> then in the case
 78    * of two identical sections (scopes, section name and priority), they would be merged to the one by joining the appropriate business
 79    * items. If there are identical business items (scopes, name and priority) - the
 80    * <code>com.sourceforge.jpatterns.core.configuration.exceptions.JPInitializationException</code> exception would appear
 81    * - in the case {@link com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.XML_CONFIG_OVERRIDING_DEPTH}
 82    * property equals to
 83    * <code>com.sourceforge.jpatterns.core.configuration.PropertiesProvider.OverridingDepths.OVERRIDING_LEVEL_SECTION</code> then in the
 84    * case of two identical sections (scopes, section name and priority)
 85    * <code>com.sourceforge.jpatterns.core.configuration.exceptions.JPConfigException</code> exception would appear
 86    * - in the case of the identical pathes but different priorities they would be taken into consideration (in this case
 87    * com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.XML_CONFIG_CUSTOM_OVERRIDES_NOT_DEPENDING_ON_PRIORITY
 88    * would be considered too).
 89    * <p/>
 90    * <strong>Business items filling</strong>:
 91    * todo [zmicer]: <<t.b.d.>>
 92    * <p/>
 93    * note [zmicer]: please be noticed the Section with the certain scope is allowed to store the business items with different scopes
 94    * </pre>
 95    */
 96  102 public JPatternsConfigBean build(final JPatternsConfig config)
 97    {
 98    // 00: check the input params on the validness.
 99  102 InputArgumentUtils.checkObjects(config);
 100   
 101  101 JPatternsConfigBean result = new JPatternsConfigBean();
 102    // 01: set additional info
 103  101 result.setDefaultScope(config.getDefaultScope());
 104  101 result.setCastorConfig(config);
 105   
 106    // 02: fill with sections/items
 107  101 CastorUtils.validateAndNormalizeScopesPriorities(config);
 108  101 fill(result, CastorUtils.extractCastorSectionTypeObjects(config));
 109   
 110  101 return result;
 111    }
 112   
 113    /**
 114    * @see IJPatternsConfigBeansBuilder#build(com.sourceforge.jpatterns.schema.JPatternsConfig)
 115    */
 116  146 public JPatternsConfigsBean build(final List<JPatternsConfigBaseBean> beans)
 117    {
 118  146 InputArgumentUtils.checkObjects(beans);
 119  145 final JPatternsConfigsBean result = new JPatternsConfigsBean();
 120   
 121  145 final List<CastorSectionType> sections = new ArrayList<CastorSectionType>();
 122  145 for (JPatternsConfigBaseBean bean : beans)
 123    {
 124  167 ObjectStateUtils.strongCheck(bean);
 125  167 sections.addAll(bean.getListOfSectionItems());
 126    }
 127  145 fill(result, sections);
 128   
 129  145 return result;
 130    }
 131   
 132    /**
 133    * Please review the Java Docs to the method {@link fill}
 134    * todo [zmicer]: adjust Java Doc
 135    * todo [zmicer]: think if this method could be moved to interface of the builder too
 136    *
 137    * @param initialBaseBean the initial bean to fill.
 138    * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 139    * @param sections the List of the CastorSectionType objects. They should be normalized in the sense of scopes and priorities(for
 140    * details study
 141    * {@link com.sourceforge.jpatterns.utils.CastorUtils#validateAndNormalizeScopesPriorities(JPatternsConfig)}).
 142    * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 143    */
 144  250 protected void fill(final JPatternsConfigBaseBean initialBaseBean, final List<CastorSectionType> sections)
 145    {
 146  250 InputArgumentUtils.checkObjects(initialBaseBean, sections);
 147  247 ObjectStateUtils.strongCheck(initialBaseBean);
 148   
 149    // 01: working with the sections.
 150  247 for (final CastorSectionType section : sections)
 151    {
 152  513 if (null == section.getScope() && null == section.getName())
 153    {
 154  0 throw new JPConfigException("The scope and name of CastorSectionType can not be null.");
 155    }
 156  513 final CastorSectionType alreadySection = initialBaseBean.getSection(section.getScope(), section.getName());
 157    // A. section with the same path is not existed yet or the pathes are different - just put it
 158  513 if (null == alreadySection ||
 159    (!section.getScope().equals(alreadySection.getScope()) || !section.getName().equals(alreadySection.getName())))
 160    {
 161  489 initialBaseBean.setSection(section.getScope(), section);
 162    }
 163    else
 164    {
 165  24 initialBaseBean.setSection(section.getScope(),
 166    (CastorSectionType) choiceOrMergeCastorNameScopePriorityTypes(section, alreadySection));
 167    }
 168    }
 169   
 170    // 02: working with the business items
 171    // A. iterate through all the sections we have at this moment
 172  247 Map<String, Map<String, CastorSectionType>> sectionItems = initialBaseBean.getSectionItems();
 173  247 for (String sectionScope : sectionItems.keySet())
 174    {
 175  241 final Map<String, CastorSectionType> sectionsMap = sectionItems.get(sectionScope);
 176  241 for (String sectionName : sectionsMap.keySet())
 177    {
 178  489 final CastorSectionType section = sectionsMap.get(sectionName);
 179  489 final List<CastorNameScopePriorityType> items = CastorUtils.extractCastorNameScopePriorityTypeObjects(section);
 180  489 for (CastorNameScopePriorityType item : items)
 181    {
 182  1305 if (null == item.getScope() && null == section.getName())
 183    {
 184  0 throw new JPConfigException("The scope and name of Item can not be null.");
 185    }
 186  1305 if (StringUtils.isBlank(section.getScope()))
 187    {
 188  0 throw new JPInitializationException("Section should have scope set.");
 189    }
 190  1305 final CastorNameScopePriorityType alreadyItem =
 191    initialBaseBean.getBusinessItem(section.getScope(), sectionName, item.getScope(), item.getName());
 192    // A. item with the same path is not existed yet
 193  1305 if (null == alreadyItem)
 194    {
 195  1305 initialBaseBean.setBusinessItem(section.getScope(), sectionName, item);
 196    }
 197    else
 198    {
 199  0 initialBaseBean.setBusinessItem(section.getScope(), sectionName,
 200    choiceOrMergeCastorNameScopePriorityTypes(item, alreadyItem));
 201    }
 202    }
 203    }
 204    }
 205    }
 206   
 207    /**
 208    * Choice one of the given CastorNameScopePriorityType castor objects or perform the merging if it is necessary. Please review the
 209    * comments to the main <code>fill</code> method to understand how it works (depending on the mentioned properties etc.)
 210    * <br/>
 211    * These objects should have the equal pathes to be passed here (scope, name) - otherwise the IllegalArgumentException appear
 212    *
 213    * @param castor1 the first object, Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 214    * @param castor2 the second object, Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 215    *
 216    * @return the object is more prioritized here
 217    */
 218  44 protected CastorNameScopePriorityType choiceOrMergeCastorNameScopePriorityTypes(final CastorNameScopePriorityType castor1,
 219    final CastorNameScopePriorityType castor2)
 220    {
 221  44 InputArgumentUtils.checkObjects(castor1, castor2);
 222  42 InputArgumentUtils.checkStrings(true, castor1.getScope(), castor1.getName(), castor1.getPriority());
 223  40 InputArgumentUtils.checkStrings(true, castor2.getScope(), castor2.getName(), castor2.getPriority());
 224  40 if (!castor1.getScope().equals(castor2.getScope()) || !castor1.getName().equals(castor2.getName()))
 225    {
 226  1 throw new IllegalArgumentException("The provided object should have the identical pathes to be checked / compared.");
 227    }
 228  39 if (!castor1.getClass().equals(castor2.getClass()))
 229    {
 230  0 throw new IllegalArgumentException("The classes of the provided objects should be identical.");
 231    }
 232    // 00: priorities are equals
 233  39 if (castor1.getPriority().equals(castor2.getPriority()))
 234    {
 235    // in the case of business items - just exception.
 236  3 if (!(castor1 instanceof CastorSectionType))
 237    {
 238  1 throw new JPConfigException("The elements with identical pathes can not be merged - scope [" +
 239    castor1.getScope() + "], name [" + castor1.getName() + "], priority [" + castor1.getPriority() + "]; class name " +
 240    "is [" + castor1.getClass().getName() + "]");
 241    }
 242    // we need to apply overriding depth feature to here
 243    else
 244    {
 245    // 00:b exception should be thrown - two identical pathes (including priotities)
 246  2 if (OverridingDepth.equals(
 247    com.sourceforge.jpatterns.core.configuration.PropertiesProvider.OverridingDepths.OVERRIDING_LEVEL_SECTION.toString()))
 248    {
 249  1 throw new JPConfigException("The elements with identical pathes can not be merged - scope [" +
 250    castor1.getScope() + "], name [" + castor1.getName() + "], priority [" + castor1.getPriority() + "]; class " +
 251    "name is [" + castor1.getClass().getName() + "]");
 252    }
 253    // 00:c no exception - we should merge the two items into the one (we won't check the items here - it would be done when
 254    // the items would be put to the specialized map)
 255  1 else if (OverridingDepth.equals(
 256    com.sourceforge.jpatterns.core.configuration.PropertiesProvider.OverridingDepths.OVERRIDING_LEVEL_ITEM.toString()))
 257    {
 258  1 final List<CastorNameScopePriorityType> items =
 259    CastorUtils.extractCastorNameScopePriorityTypeObjects((CastorSectionType) castor2);
 260  1 for (CastorNameScopePriorityType item : items)
 261    {
 262    // perform add functionality through the reflexion
 263    // note [zmicer]: very risky block still it is better then reflexion. Seems to be these three base classes limit
 264    // the scope of root section classes
 265  1 if (castor1 instanceof CastorConfigType)
 266    {
 267  1 if (!(item instanceof Item))
 268    {
 269  0 throw new JPConfigException("The CastorNameScopePriorityType item should be of Item type in the " +
 270    "case castor section object is of the type CastorConfigType");
 271    }
 272  1 ((CastorConfigType) castor1).addItem((Item) item);
 273    }
 274  0 else if (castor1 instanceof CastorFactoryType)
 275    {
 276  0 if (!(item instanceof Item))
 277    {
 278  0 throw new JPConfigException("The CastorNameScopePriorityType item should be of Item type in the " +
 279    "case castor section object is of the type CastorFactoryType");
 280    }
 281  0 ((CastorFactoryType) castor1).addItem((Item) item);
 282    }
 283  0 else if (castor1 instanceof CastorGroupType)
 284    {
 285  0 final CastorGroupTypeItem groupItem = CastorUtils.constructGroupItem(item);
 286  0 ((CastorGroupType) castor1).addCastorGroupTypeItem(groupItem);
 287    }
 288    }
 289  1 return castor1;
 290    }
 291    }
 292    }
 293    else
 294    {
 295  36 int firstPriority = CastorUtils.getPriority(castor1);
 296  36 int secondPriority = CastorUtils.getPriority(castor2);
 297  36 boolean firstPrioritized = false;
 298  36 boolean secondPrioritized = false;
 299  36 if (castor1.getPriority().startsWith(JPConstants.PRIORITIZED_PRIOTITY_PREFIX))
 300    {
 301  6 firstPrioritized = true;
 302    }
 303  36 if (castor2.getPriority().startsWith(JPConstants.PRIORITIZED_PRIOTITY_PREFIX))
 304    {
 305  6 secondPrioritized = true;
 306    }
 307    // 00:d both prioritized or both not prioritized - just compare the priorities
 308  36 if (firstPrioritized && secondPrioritized || (!firstPrioritized && !secondPrioritized))
 309    {
 310  28 return (firstPriority > secondPriority) ? castor1 : castor2;
 311    }
 312    // 00:e first prioritized - check the property too
 313  8 else if (firstPrioritized)
 314    {
 315  4 if (OverrideNotDependingOnPriority)
 316    {
 317  2 return castor1;
 318    }
 319    else
 320    {
 321  2 return (firstPriority > secondPriority) ? castor1 : castor2;
 322    }
 323    }
 324    // 00:f second prioritized - check the property too
 325    else
 326    {
 327  4 if (OverrideNotDependingOnPriority)
 328    {
 329  2 return castor2;
 330    }
 331    else
 332    {
 333  2 return (firstPriority > secondPriority) ? castor1 : castor2;
 334    }
 335    }
 336    }
 337  0 return null;
 338    }
 339   
 340    /**
 341    * Set the overriding depth. This method is necessary for the unit testing.
 342    *
 343    * @param depth the value we ned to set, Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 344    */
 345  208 protected static void setOverridingDepth(final String depth)
 346    {
 347  208 InputArgumentUtils.checkStrings(true, depth);
 348  207 OverridingDepth = depth;
 349    }
 350   
 351    /**
 352    * @return overriding depth
 353    */
 354  3 protected static String getOverridingDepth()
 355    {
 356  3 return OverridingDepth;
 357    }
 358   
 359    /**
 360    * Set the OverrideNotDependingOnPriority static field with the new value. This method is necessary for unit testing.
 361    *
 362    * @param value new boolean value
 363    */
 364  209 protected static void setOverrideNotDependingOnPriority(final boolean value)
 365    {
 366  209 OverrideNotDependingOnPriority = value;
 367    }
 368   
 369    /**
 370    * @return the value of OverrideNotDependingOnPriority
 371    */
 372  3 protected static boolean getOverrideNotDependingOnPriority()
 373    {
 374  3 return OverrideNotDependingOnPriority;
 375    }
 376    }