Clover coverage report - Maven Clover report
Coverage timestamp: Mon Sep 3 2007 08:24:07 EEST
file stats: LOC: 404   Methods: 19
NCLOC: 271   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JPFactoryImpl.java 81.2% 88.5% 100% 87.7%
coverage coverage
 1    package com.sourceforge.jpatterns.patterns.factory;
 2   
 3    import com.sourceforge.jpatterns.core.JPConstants;
 4    import com.sourceforge.jpatterns.core.configuration.exceptions.JPConfigException;
 5    import com.sourceforge.jpatterns.patterns.PatternBase;
 6    import com.sourceforge.jpatterns.schema.CastorSectionType;
 7    import com.sourceforge.jpatterns.schema.Factory;
 8    import com.sourceforge.jpatterns.schema.Item;
 9    import com.sourceforge.jpatterns.schema.Param;
 10    import com.sourceforge.jpatterns.utils.CastorUtils;
 11    import com.zmicer.utils.InputArgumentUtils;
 12    import com.zmicer.utils.LoggingUtils;
 13    import com.zmicer.utils.ReflexionUtils;
 14    import org.apache.commons.lang.StringUtils;
 15    import org.apache.log4j.Logger;
 16   
 17    import java.util.HashMap;
 18    import java.util.List;
 19    import java.util.Map;
 20   
 21    /**
 22    * The default implementation of the <code>IJPFactory</code> interface.
 23    * <p/>
 24    * todo [zmicer]: increase the coverage later - almost all the cases are checked still we need to finish covering all the protected methods.
 25    *
 26    * todo [zmicer]: adjust logAndThrow method - actually we are able to detrmine where to thrown Consumer of Framework config exception.
 27    *
 28    * $Author:: zmicer $<br/>
 29    * $Rev:: 67 $<br/> * $Date:: 2007-08-28 21:37:07 #$<br/>
 30    */
 31    public class JPFactoryImpl extends PatternBase implements IJPFactory
 32    {
 33    /**
 34    * Logger instance.
 35    */
 36    final public static Logger LOG = Logger.getLogger(JPConstants.LoggingCategory.FACTORY.toString());
 37   
 38    /**
 39    * @see com.sourceforge.jpatterns.patterns.IJPattern#checkCastorConfig(com.sourceforge.jpatterns.schema.CastorSectionType)
 40    */
 41  16 public boolean checkCastorConfig(CastorSectionType castorSectionType)
 42    {
 43  16 InputArgumentUtils.checkObjects(castorSectionType);
 44  16 return (castorSectionType instanceof Factory);
 45    }
 46   
 47    /**
 48    * @see IJPFactory#getImplementation(java.lang.Class,java.lang.String)
 49    */
 50  11 public Object getImplementation(final Class interfaceClass, final String scope)
 51    {
 52  11 return instantiateObjectByItem(retrieveItem(interfaceClass, scope), interfaceClass);
 53    }
 54   
 55    /**
 56    * @see IJPFactory#getImplementation(java.lang.Class,java.lang.String)
 57    */
 58  6 public Object getImplementation(final String interfaceClassBaseName, final String scope)
 59    {
 60  6 return instantiateObjectByItem(retrieveItem(interfaceClassBaseName, scope), null);
 61    }
 62   
 63    /**
 64    * @see IJPFactory#getImplementationFullName(Class,String)
 65    */
 66  5 public String getImplementationFullName(final Class interfaceClass, final String scope)
 67    {
 68  5 return retrieveItem(interfaceClass, scope).getValue();
 69    }
 70   
 71    /**
 72    * @see IJPFactory#getImplementationFullName(String,String)
 73    */
 74  5 public String getImplementationFullName(final String interfaceClassBaseName, final String scope)
 75    {
 76  5 return retrieveItem(interfaceClassBaseName, scope).getValue();
 77    }
 78   
 79    /**
 80    * @see IJPFactory#getImplementation(java.lang.Class,java.lang.String,java.lang.String)
 81    */
 82  18 public Object getImplementation(final Class interfaceClass, final String implType, final String scope)
 83    {
 84  18 InputArgumentUtils.checkObjects(interfaceClass, implType);
 85  14 return instantiateObjectByItemAndType(retrieveItem(interfaceClass, scope), implType, interfaceClass);
 86    }
 87   
 88    /**
 89    * @see IJPFactory#getImplementation(java.lang.String,java.lang.String,java.lang.String)
 90    */
 91  10 public Object getImplementation(final String interfaceClassBaseName, final String implType, final String scope)
 92    {
 93  10 InputArgumentUtils.checkObjects(interfaceClassBaseName, implType);
 94  10 return instantiateObjectByItemAndType(retrieveItem(interfaceClassBaseName, scope), implType, null);
 95    }
 96   
 97    /**
 98    * @see IJPFactory#getImplementations(Class,String)
 99    */
 100  11 public Map<String, Object> getImplementations(final Class interfaceClass, final String scope)
 101    {
 102  11 InputArgumentUtils.checkObjects(interfaceClass);
 103  9 Map<String, Object> result = new HashMap<String, Object>();
 104  9 try
 105    {
 106  9 result = validateImplementationsMap(interfaceClass,
 107    ReflexionUtils.reflectObjects(getImplementationsNamesByItem(retrieveItem(interfaceClass, scope)), true));
 108    }
 109    catch (Exception e)
 110    {
 111  7 LoggingUtils.logException(LOG, e, "Exception occuried", JPFactoryImpl.class);
 112  7 logAndThrow("The message of exception occuried [" + e.getMessage() + "]");
 113    }
 114  2 return result;
 115    }
 116   
 117    /**
 118    * @see IJPFactory#getImplementations(String,String)
 119    */
 120  5 public Map<String, Object> getImplementations(final String interfaceClassBaseName, final String scope)
 121    {
 122  5 InputArgumentUtils.checkObjects(interfaceClassBaseName);
 123  5 Map<String, Object> result = new HashMap<String, Object>();
 124  5 try
 125    {
 126  5 result = ReflexionUtils.reflectObjects(getImplementationsNamesByItem(retrieveItem(interfaceClassBaseName, scope)), true);
 127    }
 128    catch (Exception e)
 129    {
 130  0 LoggingUtils.logException(LOG, e, "Exception occuried", JPFactoryImpl.class);
 131  0 logAndThrow("The message of exception occuried [" + e.getMessage() + "]");
 132    }
 133  5 return result;
 134    }
 135   
 136    /**
 137    * @see IJPFactory#getImplementationsFullNames(Class,String)
 138    */
 139  9 public Map<String, String> getImplementationsFullNames(final Class interfaceClass, final String scope)
 140    {
 141  9 return getImplementationsNamesByItem(retrieveItem(interfaceClass, scope));
 142    }
 143   
 144    /**
 145    * @see IJPFactory#getImplementationsFullNames(String,String)
 146    */
 147  3 public Map<String, String> getImplementationsFullNames(final String interfaceClassBaseName, final String scope)
 148    {
 149  3 return getImplementationsNamesByItem(retrieveItem(interfaceClassBaseName, scope));
 150    }
 151   
 152    /**
 153    * @see IJPFactory#getOperator(Class,Class,Object, String)
 154    */
 155  23 public Object getOperator(final Class productBaseClass, final Class operatorBaseClass, final Object productObj, final String scope)
 156    {
 157  23 InputArgumentUtils.checkObjects(productBaseClass, operatorBaseClass, productObj);
 158  20 if (!ReflexionUtils.instanceOf(productObj, productBaseClass))
 159    {
 160  2 logAndThrow("The provided object: class [" + productObj.getClass().getName() + "] is not of the class of the product: class[" +
 161    productBaseClass.getName() + "]");
 162    }
 163   
 164  18 final Map<String, String> implementations = getImplementationsNamesByItem(
 165    retrieveItem(ReflexionUtils.getBaseName(productBaseClass) + "_" + ReflexionUtils.getBaseName(operatorBaseClass), scope));
 166  17 if (null == implementations || implementations.isEmpty())
 167    {
 168  0 throw new JPConfigException("The map of the implementations names can not be null: product base class name [" +
 169    productBaseClass.getName() + "], operator base class name [" + operatorBaseClass + "], scope [" + scope + "]");
 170    }
 171    // using assumption the base name is used to define the concrete implementation (consider any jpatterns config - it is name of the param
 172    // object).
 173  17 final String productBaseName = ReflexionUtils.getBaseName(productObj.getClass());
 174  17 if (implementations.containsKey(productBaseName) &&
 175    implementations.containsKey(productObj.getClass().getName()))
 176    {
 177  0 logAndThrow("Incorrect case when the required operator configuration for product class [" + productBaseClass.getName() +
 178    "] is defined using both base and full names of the class of product specified [" + productObj.getClass().getName() + "]. It is " +
 179    "incorrect case.");
 180    }
 181  17 String className = implementations.get(productBaseName);
 182  17 if (StringUtils.isEmpty(className))
 183    {
 184  5 LoggingUtils.debug(LOG, this.getClass(), "The implementation of the provided object was obtained using the full product class " +
 185    "definition. Product class [" + productObj.getClass().getName() + "], implementation class [" + className + "].");
 186  5 className = implementations.get(productObj.getClass().getName());
 187    }
 188   
 189  17 if (null == className)
 190    {
 191  4 logAndThrow("Can not find the operator defined for the product object with an class [" + productObj.getClass().getName() +
 192    "]. The class of the operator [" + operatorBaseClass.getName() + "], the base class of the product [" +
 193    productBaseClass.getName() + "]");
 194    }
 195  13 final Object result = ReflexionUtils.reflectObject(className, false);
 196  13 if (null == result)
 197    {
 198  4 logAndThrow("Can not instantiate the operator with the full class name [" + className + "] for the product of the full class " +
 199    "name [" + productObj.getClass().getName() + "]");
 200    }
 201  9 else if (!ReflexionUtils.instanceOf(result, operatorBaseClass))
 202    {
 203  2 logAndThrow("The obtained operator instance: class [" + result.getClass().getName() + "] is not of the class of the operator " +
 204    "was provided: class[" + operatorBaseClass.getName() + "]");
 205    }
 206  7 return result;
 207    }
 208   
 209    /**
 210    * @see IJPFactory#getOperators(Class,Class,java.util.List, String)
 211    */
 212  10 public Map<Object, Object> getOperators(final Class productBaseClass, final Class operatorBaseClass, final List<Object> productObjs,
 213    final String scope)
 214    {
 215  10 InputArgumentUtils.checkObjects(productBaseClass, operatorBaseClass, productObjs);
 216  7 final Map<Class, Object> classesInfo = new HashMap<Class, Object>();
 217  7 final Map<Object, Object> result = new HashMap<Object, Object>();
 218  7 for (Object product : productObjs)
 219    {
 220  8 if (null == classesInfo.get(product.getClass()))
 221    {
 222  8 classesInfo.put(product.getClass(), getOperator(productBaseClass, operatorBaseClass, product, scope));
 223    }
 224  3 result.put(product, classesInfo.get(product.getClass()));
 225    }
 226  2 return result;
 227    }
 228   
 229    /**
 230    * @see com.zmicer.utils.model.ICheckable#check()
 231    */
 232  89 public boolean check()
 233    {
 234  89 return super.check() && (m_castorSection instanceof Factory);
 235    }
 236   
 237    /**
 238    * Get <code>Param</code> castor object by the key.
 239    *
 240    * @param item the castor <code>Item</code>. Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 241    * @param key The String key object for which we need to obtain the param.
 242    *
 243    * @return the Param Object
 244    */
 245  22 protected Param getParam(final Item item, final String key)
 246    {
 247  22 InputArgumentUtils.checkObjects(item, key);
 248  22 for (final Param param : item.getParam())
 249    {
 250  48 if (null != param.getName() && param.getName().equals(key))
 251    {
 252  22 return param;
 253    }
 254    }
 255  0 return null;
 256    }
 257   
 258    /**
 259    * Instantiate the Object using the provided item. The provided class object (if it is not null) is used for validating the correct
 260    * implementation is specified.
 261    *
 262    * @param item the Item from value attribute of which we would instantiate the object
 263    * @param claz the Class instance to check that implementation correlates with the interface for which we obtain this. Could be null.
 264    *
 265    * @return the instantiated Object.
 266    *
 267    * @throws JPConfigException in the case we can not instantiate the object using the value of the provided item
 268    */
 269  13 protected Object instantiateObjectByItem(final Item item, Class claz) throws JPConfigException
 270    {
 271  13 if (null == item)
 272    {
 273  0 throw new IllegalArgumentException("Item can not be null.");
 274    }
 275  13 final String implName = item.getValue();
 276  13 if (null == implName)
 277    {
 278  1 logAndThrow("The item should have the value attribute not empty to be processed here. String representation" +
 279    CastorUtils.toString(null, item));
 280    }
 281  12 final Object object = ReflexionUtils.reflectObject(implName, false);
 282  12 if (null == object)
 283    {
 284  3 logAndThrow("Can not instantiate the implementation of the [" + item.getName() +
 285    "] using the scope [" + item.getScope() + "]. The name of the implementation we got from the config [" + implName + "]");
 286    }
 287  9 if (null != claz)
 288    {
 289  4 if (!ReflexionUtils.instanceOf(object, claz))
 290    {
 291  1 logAndThrow("The obtained implementation instance: class [" + object.getClass().getName() + "] is not of the class of " +
 292    "the interface specified: class[" + claz.getName() + "]");
 293    }
 294    }
 295  8 return object;
 296    }
 297   
 298    /**
 299    * Instantiate the Object using the provided item and the type we need
 300    *
 301    * @param item the Item from value attribute of which we would instantiate the object
 302    * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 303    * @param type the type for which we need instantiate the object
 304    * Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 305    *
 306    * @param claz this is necessary to perform the validation that the correct implementation is defined at the configuration file.
 307    * @return the instantiated Object.
 308    *
 309    * @throws JPConfigException in the case we can not instantiate the object using the value of the provided item
 310    */
 311  22 protected Object instantiateObjectByItemAndType(final Item item, final String type, Class claz) throws JPConfigException
 312    {
 313  22 if (null == item)
 314    {
 315  0 throw new IllegalArgumentException("Item can not be null.");
 316    }
 317  22 final Param param = getParam(item, type);
 318  22 final String message = "Can not find the required implementation defined following the path: section scope [" +
 319    m_castorSection.getScope() + "] section name [" + m_castorSection.getName() + "] item scope [" + item.getScope() + "] item name [" +
 320    item.getName() + "] implementation type [" + type + "]";
 321  22 if (null == param || StringUtils.isBlank(param.getValue()))
 322    {
 323  0 LoggingUtils.error(LOG, JPFactoryImpl.class, message);
 324  0 throw new JPConfigException(message);
 325    }
 326  22 final Object object = ReflexionUtils.reflectObject(param.getValue(), false);
 327  22 if (null == object)
 328    {
 329  3 logAndThrow("Can not instantiate the implementation of the [" + item.getName() + "] using the scope [" +
 330    item.getScope() + "]. The name of the implementation we got from the config [" + param.getValue() + "]");
 331    }
 332  19 if (null != claz)
 333    {
 334  9 if (!ReflexionUtils.instanceOf(object, claz))
 335    {
 336  1 logAndThrow("The obtained implementation instance: class [" + object.getClass().getName() + "] is not of the class of " +
 337    "the interface specified: class[" + claz.getName() + "]");
 338    }
 339    }
 340   
 341  18 return object;
 342    }
 343   
 344    /**
 345    * Instantiate the Object using the provided item
 346    *
 347    * @param item the Item from value attribute of which we would instantiate the object
 348    *
 349    * @return the Map where #key is a types of implementation, and the #value is a full name of the implementation. In the case the castor
 350    * item do not contains the mapping the empty map is returned.
 351    *
 352    * @throws JPConfigException in the case we can not instantiate the object using the value of the provided item
 353    */
 354  37 protected Map<String, String> getImplementationsNamesByItem(final Item item) throws JPConfigException
 355    {
 356  37 if (null == item)
 357    {
 358  0 throw new IllegalArgumentException("Item can not be null.");
 359    }
 360  37 final Map<String, String> result = new HashMap<String, String>();
 361  37 if (item.getParam().length == 0)
 362    {
 363  5 logAndThrow("The item" + CastorUtils.toString(m_castorSection, item) + " doesn't contain the params configuration using which the " +
 364    "implementations names should be retrivied.");
 365    }
 366    // the names and values should be filled
 367  32 for (Param param : item.getParam())
 368    {
 369  68 if (StringUtils.isBlank(param.getName()) || StringUtils.isBlank(param.getValue()))
 370    {
 371  0 logAndThrow("The item" + CastorUtils.toString(m_castorSection, item) + " contains the params with blank name or " +
 372    "value. It is illegal case for the this type factory configuration.");
 373    }
 374  68 if (result.containsKey(param.getName()))
 375    {
 376  0 logAndThrow("The item" + CastorUtils.toString(m_castorSection, item) + " contains the params with duplicated names.");
 377    }
 378  68 result.put(param.getName(), param.getValue());
 379    }
 380  32 return result;
 381    }
 382   
 383    /**
 384    * Check that all the implementations of the map - are the types of the provided class.
 385    *
 386    * @param clazz The class against which we would check the map, Can not be null (otherwise <code>IllegalArgumentException</code> would appear).
 387    * @param map containing the implementation we need to check
 388    *
 389    * @return the map with the implementation without any changes - just pass through method making the check
 390    */
 391  5 protected Map<String, Object> validateImplementationsMap(final Class clazz, final Map<String, Object> map)
 392    {
 393  5 InputArgumentUtils.checkObjects(clazz, map);
 394  5 for (final Object object : map.values())
 395    {
 396  11 if (!ReflexionUtils.instanceOf(object, clazz))
 397    {
 398  2 logAndThrow("The map of implememntations was introduced for the class [" + clazz.getName() + "] can not contain the implementation" +
 399    " which is not of this class [" + object.getClass().getName() + "].");
 400    }
 401    }
 402  3 return map;
 403    }
 404    }