Coverage Report - org.apache.commons.clazz.bean.BeanClazz
 
Classes in this File Line Coverage Branch Coverage Complexity
BeanClazz
0%
0/151
0%
0/70
2.25
BeanClazz$1
0%
0/17
0%
0/12
2.25
 
 1  
 /*
 2  
  * Copyright 2002-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  
 package org.apache.commons.clazz.bean;
 17  
 
 18  
 import java.lang.reflect.Constructor;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collections;
 21  
 import java.util.HashMap;
 22  
 import java.util.HashSet;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 import java.util.Set;
 27  
 
 28  
 import org.apache.commons.clazz.Clazz;
 29  
 import org.apache.commons.clazz.ClazzChangeListener;
 30  
 import org.apache.commons.clazz.ClazzInstanceFactory;
 31  
 import org.apache.commons.clazz.ClazzLoader;
 32  
 import org.apache.commons.clazz.ClazzOperation;
 33  
 import org.apache.commons.clazz.ClazzProperty;
 34  
 
 35  
 /**
 36  
  * Dynamically constructed Clazz. BeanClazzes are created by invoking {@link
 37  
  * ClazzLoader#defineClazz(String, Class, Class) clazzLoader.defineClazz (name,
 38  
  * clazzClass, instanceClass)}.
 39  
  * 
 40  
  * @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
 41  
  * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
 42  
  * @version $Id: BeanClazz.java 155436 2005-02-26 13:17:48Z dirkv $
 43  
  */
 44  0
 public class BeanClazz extends Clazz {
 45  
     private Clazz superClazz;
 46  0
     private List declaredProperties = new ArrayList();
 47  0
     private List properties = new ArrayList();
 48  0
     private Map propertyMap = new HashMap();
 49  0
     private List declaredOperations = new ArrayList();
 50  0
     private List operations = new ArrayList();
 51  0
     private Map operationMap = new HashMap();
 52  
     private List instanceFactories;
 53  0
     private Map instanceFactoryMap = new HashMap();
 54  
     private Class instanceClass;
 55  0
     private List subclasses = new ArrayList();
 56  
 
 57  
     /**
 58  
      * Constructor for BeanClazz.
 59  
      * @param loader
 60  
      * @param name
 61  
      * @param instanceClass
 62  
      */
 63  
     public BeanClazz(ClazzLoader loader, String name, Class instanceClass) {
 64  0
         super(loader, name);
 65  0
         this.instanceClass = instanceClass;
 66  0
     }
 67  
 
 68  
     public Class getInstanceClass() {
 69  0
         if (instanceClass != null) {
 70  0
             return instanceClass;
 71  
         }
 72  
 
 73  0
         if (superClazz instanceof BeanClazz) {
 74  0
             return ((BeanClazz) superClazz).getInstanceClass();
 75  
         }
 76  
 
 77  0
         return BasicBean.class;
 78  
     }
 79  
 
 80  
     /**
 81  
      * @see org.apache.commons.clazz.Clazz#getSuperclazz()
 82  
      */
 83  
     public Clazz getSuperclazz() {
 84  0
         return superClazz;
 85  
     }
 86  
 
 87  
     public void setSuperclazz(Clazz clazz) {
 88  0
         if (superClazz != null) {
 89  0
             superClazz.removeClazzChangeListener(listener);
 90  
         }
 91  0
         superClazz = clazz;
 92  0
         if (clazz != null) {
 93  0
             superClazz.addClazzChangeListener(listener);
 94  
         }
 95  0
         refreshAllCaches();
 96  0
     }
 97  
 
 98  
     protected void refreshAllCaches() {
 99  0
         refreshPropertyCache();
 100  0
         refreshOperationCache();
 101  0
     }
 102  
 
 103  
     protected void refreshPropertyCache() {
 104  0
         properties = new ArrayList();
 105  0
         propertyMap = new HashMap();
 106  
 
 107  0
         Set propertyNames = new HashSet();
 108  0
         if (superClazz != null) {
 109  0
             List superProperties = superClazz.getProperties();
 110  0
             properties.addAll(superProperties);
 111  0
             for (int i = 0; i < superProperties.size(); i++) {
 112  0
                 ClazzProperty superProperty =
 113  
                     (ClazzProperty) superProperties.get(i);
 114  0
                 propertyNames.add(superProperty.getName());
 115  
             }
 116  
         }
 117  0
         for (int i = 0; i < declaredProperties.size(); i++) {
 118  0
             ClazzProperty property = (ClazzProperty) declaredProperties.get(i);
 119  0
             String name = property.getName();
 120  0
             if (!propertyNames.contains(name)) {
 121  0
                 properties.add(property);
 122  
             }
 123  
         }
 124  
 
 125  0
         for (Iterator iter = properties.iterator(); iter.hasNext();) {
 126  0
             ClazzProperty property = (ClazzProperty) iter.next();
 127  0
             propertyMap.put(property.getName(), property);
 128  0
         }
 129  0
     }
 130  
 
 131  
     protected void refreshOperationCache() {
 132  0
         List operations = new ArrayList();
 133  0
         Set signatures = new HashSet();
 134  0
         if (superClazz != null) {
 135  0
             List superOperations = superClazz.getOperations();
 136  0
             operations.addAll(superOperations);
 137  0
             for (int i = 0; i < superOperations.size(); i++) {
 138  0
                 ClazzOperation superOperation =
 139  
                     (ClazzOperation) superOperations.get(i);
 140  0
                 signatures.add(superOperation.getSignature());
 141  
             }
 142  
         }
 143  0
         for (int i = 0; i < declaredOperations.size(); i++) {
 144  0
             ClazzOperation operation =
 145  
                 (ClazzOperation) declaredOperations.get(i);
 146  0
             String signature = operation.getSignature();
 147  0
             if (!signatures.contains(signature)) {
 148  0
                 operations.add(operation);
 149  
             }
 150  
         }
 151  0
     }
 152  
 
 153  
     /**
 154  
      * @see org.apache.commons.clazz.Clazz#getDeclaredProperties()
 155  
      */
 156  
     public List getDeclaredProperties() {
 157  0
         return Collections.unmodifiableList(declaredProperties);
 158  
     }
 159  
 
 160  
     public void addDeclaredProperty(ClazzProperty property) {
 161  0
         if (property.getDeclaringClazz() != this) {
 162  0
             throw new BeanClazzConfigurationException(
 163  
                 "Property belongs to a different clazz: "
 164  
                     + property.getDeclaringClazz().getName());
 165  
         }
 166  
 
 167  0
         ClazzProperty oldProperty =
 168  
             (ClazzProperty) propertyMap.get(property.getName());
 169  0
         if (oldProperty != null) {
 170  0
             removeDeclaredProperty(oldProperty);
 171  
         }
 172  
 
 173  0
         declaredProperties.add(property);
 174  
 
 175  0
         addProperty(property);
 176  0
     }
 177  
 
 178  
     /**
 179  
      * Called indirectly when declared properties are manipulated.
 180  
      */
 181  
     protected void addProperty(ClazzProperty property) {
 182  0
         properties.add(property);
 183  0
         propertyMap.put(property.getName(), property);
 184  0
         firePropertyAdded(property);
 185  0
     }
 186  
 
 187  
     public void removeDeclaredProperty(ClazzProperty property) {
 188  0
         String name = property.getName();
 189  0
         property = (ClazzProperty) propertyMap.get(name);
 190  0
         if (property != null) {
 191  0
             declaredProperties.remove(property);
 192  0
             removeProperty(property);
 193  
         }
 194  0
     }
 195  
 
 196  
     /**
 197  
      * Called indirectly when declared properties are manipulated.
 198  
      */
 199  
     protected void removeProperty(ClazzProperty property) {
 200  0
         String name = property.getName();
 201  0
         properties.remove(property);
 202  0
         propertyMap.remove(name);
 203  0
         firePropertyRemoved(property);
 204  
 
 205  
         // By deleting this declared property, we may have exposed 
 206  
         // an inherited one
 207  0
         if (superClazz != null) {
 208  0
             property = superClazz.getProperty(name);
 209  0
             if (property != null) {
 210  0
                 addProperty(property);
 211  
             }
 212  
         }
 213  0
     }
 214  
 
 215  
     /**
 216  
      * @see org.apache.commons.clazz.Clazz#getProperties()
 217  
      */
 218  
     public List getProperties() {
 219  0
         return properties;
 220  
     }
 221  
 
 222  
     /**
 223  
      * @see org.apache.commons.clazz.Clazz#getProperty(java.lang.String)
 224  
      */
 225  
     public ClazzProperty getProperty(String name) {
 226  0
         return (ClazzProperty) propertyMap.get(name);
 227  
     }
 228  
 
 229  
     /**
 230  
      * @see org.apache.commons.clazz.Clazz#getDeclaredOperations()
 231  
      */
 232  
     public List getDeclaredOperations() {
 233  0
         return Collections.unmodifiableList(declaredOperations);
 234  
     }
 235  
 
 236  
     public void addDeclaredOperation(ClazzOperation operation) {
 237  0
         if (operation.getDeclaringClazz() != this) {
 238  0
             throw new BeanClazzConfigurationException(
 239  
                 "Operation belongs to a different clazz: "
 240  
                     + operation.getDeclaringClazz().getName());
 241  
         }
 242  
 
 243  0
         ClazzOperation oldOperation =
 244  
             (ClazzOperation) operationMap.get(operation.getSignature());
 245  0
         if (oldOperation != null) {
 246  0
             removeDeclaredOperation(oldOperation);
 247  
         }
 248  
 
 249  0
         declaredOperations.add(operation);
 250  
 
 251  0
         addOperation(operation);
 252  0
     }
 253  
 
 254  
     /**
 255  
      * Called indirectly when declared operations are manipulated.
 256  
      */
 257  
     protected void addOperation(ClazzOperation operation) {
 258  0
         operations.add(operation);
 259  0
         operationMap.put(operation.getSignature(), operation);
 260  0
         fireOperationAdded(operation);
 261  0
     }
 262  
 
 263  
     public void removeDeclaredOperation(ClazzOperation operation) {
 264  0
         String signature = operation.getSignature();
 265  0
         operation = (ClazzOperation) operationMap.get(signature);
 266  0
         if (operation != null) {
 267  0
             declaredOperations.remove(operation);
 268  0
             removeOperation(operation);
 269  
         }
 270  0
     }
 271  
 
 272  
     /**
 273  
      * Called indirectly when declared operations are manipulated.
 274  
      */
 275  
     protected void removeOperation(ClazzOperation operation) {
 276  0
         String signature = operation.getSignature();
 277  0
         operations.remove(operation);
 278  0
         operationMap.remove(signature);
 279  0
         fireOperationRemoved(operation);
 280  
 
 281  
         // By deleting this declared operation, we may have exposed
 282  
         // an inherited one
 283  0
         if (superClazz != null) {
 284  0
             operation = superClazz.getOperation(signature);
 285  0
             if (operation != null) {
 286  0
                 addOperation(operation);
 287  
             }
 288  
         }
 289  0
     }
 290  
 
 291  
     /**
 292  
      * @see org.apache.commons.clazz.Clazz#getOperations()
 293  
      */
 294  
     public List getOperations() {
 295  0
         return operations;
 296  
     }
 297  
 
 298  
     /**
 299  
      * @see org.apache.commons.clazz.Clazz#getOperation(java.lang.String)
 300  
      */
 301  
     public ClazzOperation getOperation(String signature) {
 302  0
         return (ClazzOperation) operationMap.get(signature);
 303  
     }
 304  
 
 305  
     /**
 306  
      * @see org.apache.commons.clazz.Clazz#getInstanceFactories()
 307  
      */
 308  
     public List getInstanceFactories() {
 309  0
         if (instanceFactories == null) {
 310  0
             introspectInstanceFactories();
 311  
         }
 312  0
         return Collections.unmodifiableList(instanceFactories);
 313  
     }
 314  
 
 315  
     /**
 316  
      * @see org.apache.commons.clazz.Clazz#getInstanceFactory(java.lang.String)
 317  
      */
 318  
     public ClazzInstanceFactory getInstanceFactory(String signature) {
 319  0
         if (instanceFactories == null) {
 320  0
             introspectInstanceFactories();
 321  
         }
 322  
 
 323  0
         return (ClazzInstanceFactory) instanceFactoryMap.get(signature);
 324  
     }
 325  
 
 326  
     public void addInstanceFactory(ClazzInstanceFactory factory) {
 327  0
         if (factory.getDeclaringClazz() != this) {
 328  0
             throw new BeanClazzConfigurationException(
 329  
                 "Instance factory belongs to a different clazz: "
 330  
                     + factory.getDeclaringClazz().getName());
 331  
         }
 332  
 
 333  0
         if (instanceFactories == null) {
 334  0
             introspectInstanceFactories();
 335  
         }
 336  0
         ClazzInstanceFactory oldFactory =
 337  
             (ClazzInstanceFactory) instanceFactoryMap.get(
 338  
                 factory.getSignature());
 339  0
         if (oldFactory != null) {
 340  0
             removeInstanceFactory(oldFactory);
 341  
         }
 342  0
         instanceFactories.add(factory);
 343  0
         instanceFactoryMap.put(factory.getSignature(), factory);
 344  0
         fireInstanceFactoryAdded(factory);
 345  0
     }
 346  
 
 347  
     public void removeInstanceFactory(ClazzInstanceFactory factory) {
 348  0
         if (instanceFactories.remove(factory)) {
 349  0
             instanceFactoryMap.remove(factory.getSignature());
 350  0
             fireInstanceFactoryRemoved(factory);
 351  
         }
 352  0
     }
 353  
 
 354  
     /**
 355  
      * Finds all constructors of the <code>instanceClass</code> that have at
 356  
      * least one argument and the first argument is of type Clazz. Wraps
 357  
      * each of those constructors into
 358  
      * a {@link BeanClazzConstructorInstanceFactory
 359  
      * BeanClazzConstructorInstanceFactory} and registers it as an
 360  
      * InstanceFactory for this clazz.
 361  
      */
 362  
     private void introspectInstanceFactories() {
 363  0
         instanceFactories = new ArrayList();
 364  0
         Class instanceClass = getInstanceClass();
 365  0
         Constructor constructors[] = instanceClass.getConstructors();
 366  0
         for (int i = 0; i < constructors.length; i++) {
 367  0
             Class[] parameterTypes = constructors[i].getParameterTypes();
 368  0
             if (parameterTypes != null
 369  
                 && parameterTypes.length >= 1
 370  
                 && Clazz.class.isAssignableFrom(parameterTypes[0])) {
 371  0
                 addInstanceFactory(
 372  
                     new BeanClazzConstructorInstanceFactory(
 373  
                         this,
 374  
                         constructors[i]));
 375  
             }
 376  
         }
 377  0
     }
 378  
 
 379  0
     private ClazzChangeListener listener = new ClazzChangeListener() {
 380  
         public void propertyAdded(Clazz clazz, ClazzProperty property) {
 381  0
             if (propertyMap.get(property.getName()) == null) {
 382  0
                 addProperty(property);
 383  
             }
 384  0
         }
 385  
 
 386  
         public void propertyRemoved(Clazz clazz, ClazzProperty property) {
 387  0
             ClazzProperty declared =
 388  
                 (ClazzProperty) propertyMap.get(property.getName());
 389  0
             if (declared != null && declared.equals(property)) {
 390  0
                 removeProperty(property);
 391  
             }
 392  0
         }
 393  
 
 394  
         public void operationAdded(Clazz clazz, ClazzOperation operation) {
 395  0
             if (operationMap.get(operation.getSignature()) == null) {
 396  0
                 addOperation(operation);
 397  
             }
 398  0
         }
 399  
 
 400  
         public void operationRemoved(Clazz clazz, ClazzOperation operation) {
 401  0
             ClazzOperation declared =
 402  
                 (ClazzOperation) operationMap.get(operation.getSignature());
 403  0
             if (declared != null && declared.equals(operation)) {
 404  0
                 removeOperation(operation);
 405  
             }
 406  0
         }
 407  
 
 408  
         public void instanceFactoryAdded(
 409  
             Clazz clazz,
 410  
             ClazzInstanceFactory property) 
 411  
         {
 412  
             // Ignore - factories are not inherited
 413  0
         }
 414  
 
 415  
         public void instanceFactoryRemoved(
 416  
             Clazz clazz,
 417  
             ClazzInstanceFactory property) 
 418  
         {
 419  
             // Ignore - factories are not inherited
 420  0
         }
 421  
     };
 422  
 }