Changeset 28

Show
Ignore:
Timestamp:
07/26/05 11:32:59 (3 years ago)
Author:
schst
Message:

Split convertValue() method into smaller methods, automatically ignore all children that have been used in the constructor (fixes bug #8 in a more elegant manner)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/net/schst/XJConf/ConstructorDefinition.java

    r25 r28  
    5656    } 
    5757     
    58      
    5958    /** 
    6059     * Get the setter method 
     
    6362        return null; 
    6463    } 
     64 
     65    /** 
     66     * Get the names of all child elements that are used in 
     67     * the constructor. 
     68     *  
     69     * These children are not used, when adding them using 
     70     * setter-methods. 
     71     *  
     72     * @return 
     73     */ 
     74    public ArrayList getUsedChildrenNames() { 
     75        ArrayList childrenNames = new ArrayList(); 
     76        Definition def; 
     77        for (int i = 0; i < this.params.size(); i++) { 
     78            def = (Definition)this.params.get(i); 
     79            if (def instanceof ChildDefinition) { 
     80                childrenNames.add(def.getName()); 
     81            } 
     82        } 
     83        return childrenNames; 
     84    } 
    6585} 
  • trunk/src/net/schst/XJConf/TagDefinition.java

    r27 r28  
    1212 */ 
    1313public class TagDefinition implements Definition { 
     14 
    1415    private String name = null; 
    1516    private String tagName = null; 
     
    1920    private String nameAttribute = null; 
    2021    private ConstructorDefinition constructor = null; 
    21      
     22    private ArrayList ignoredChildren = new ArrayList(); 
     23 
    2224    // TODO: Eventually call the setter method for the cdata 
    2325    private CDataDefinition cdata = null; 
     
    5658        } 
    5759    } 
    58      
     60 
    5961    /** 
    6062     * Add an attribute to the tag 
     
    164166     
    165167    /** 
    166      * Convert the value 
    167      *  
    168      * You should pass a Tag object to this method. 
    169      *  
    170      * @param v    value to convert 
    171      * @return     converted value 
     168     * Convert the value of the tag. 
     169     *  
     170     * @param tag      tag that will be converted 
     171     * @param loader   ClassLoader that should be used for loading new classes 
     172     * @return         converted value 
    172173     * @throws ValueConversionException 
    173174     */ 
    174     public Object convertValue(Tag tag, ClassLoader loader) throws ValueConversionException { 
    175         Class cl; 
     175    public Object convertValue(Tag tag, ClassLoader loader) 
     176        throws ValueConversionException { 
     177 
     178        Class instanceClass; 
    176179        Object instance = null; 
    177          
     180 
    178181        // get the data 
    179182        String data = tag.getData(); 
     
    184187        // try to get the class object 
    185188        try { 
    186             // get the class object 
    187             cl = Class.forName(this.type,true,loader); 
     189            instanceClass = Class.forName(this.type,true,loader); 
    188190        } catch (Exception e) { 
    189191            throw new ValueConversionException("Class " + this.type + " does not exist", e); 
     
    209211        // get all values and their types 
    210212        for (int i = 0; i < conParams.size(); i++) { 
    211             paramDef = (Definition)conParams.get(i); 
    212             Object val = paramDef.convertValue(tag,loader); 
     213            paramDef       = (Definition)conParams.get(i); 
     214            cParams[i]    = paramDef.convertValue(tag,loader); 
    213215            cParamTypes[i] = paramDef.getValueType(tag); 
    214             cParams[i] = val; 
    215216        } 
    216217 
    217218        // try to create a new instance 
    218219        try { 
    219             Constructor co = cl.getConstructor(cParamTypes); 
     220            Constructor co = instanceClass.getConstructor(cParamTypes); 
    220221            instance = co.newInstance(cParams); 
    221222        } catch (Exception e){ 
    222223            try { 
    223                 instance = cl.newInstance(); 
    224             } catch (Exception t) { 
    225                 throw new ValueConversionException("Could not create instance of " + this.type, t); 
    226             } 
    227         } 
    228  
     224                // no matching constructor has been found 
     225                // try to instantiate the class without using 
     226                // a constructor 
     227                instance = instanceClass.newInstance(); 
     228            } catch (Exception e2) { 
     229                throw new ValueConversionException("Could not create instance of " + this.type, e2); 
     230            } 
     231        } 
     232         
     233        // add attributes and child elements 
     234        this.addAttributesToValue(instance, tag, loader); 
     235        this.addChildrenToValue(instance, tag, loader); 
     236        return instance; 
     237    } 
     238 
     239    /** 
     240     * Add all attributes using the appropriate setter methods 
     241     *   
     242     * @param instance 
     243     * @param tag 
     244     * @param loader 
     245     * @throws ValueConversionException 
     246     */ 
     247    private void addAttributesToValue(Object instance, Tag tag, ClassLoader loader) 
     248        throws ValueConversionException { 
     249         
     250        Class cl = instance.getClass(); 
     251         
    229252        // set all attributes 
    230         String methodName = null; 
    231         for (int i = 0; i < this.atts.size(); i++) { 
    232              
    233             // get the attribute definition 
    234             AttributeDefinition att = (AttributeDefinition)this.atts.get(i); 
    235             Object val = att.convertValue(tag,loader); 
    236             if (val == null) { 
    237                 continue; 
    238             } 
     253        String methodName = null; 
     254        for (int i = 0; i < this.atts.size(); i++) { 
    239255             
    240             try { 
    241                 methodName = att.getSetterMethod(); 
    242                 Class meParamTypes[] = {att.getValueType(tag)}; 
    243                  
    244                 Method me = cl.getMethod(methodName, meParamTypes); 
    245                 Object meParams[] = {val}; 
    246                  
    247                 me.invoke(instance, meParams); 
    248             } catch (Exception t) { 
    249                 throw new ValueConversionException("Could not set attribute " + att.getName() + " of " + this.type, t); 
    250             } 
    251         } 
    252          
    253         // traverse all children 
    254         ArrayList children = tag.getChildren();            
    255         if (children.size() == 0) { 
    256             return instance; 
    257         } 
    258              
    259         for (int i = 0; i < children.size(); i++) { 
    260             Tag child = (Tag)children.get(i); 
    261  
     256            // get the attribute definition 
     257            AttributeDefinition att = (AttributeDefinition)this.atts.get(i); 
     258            Object val = att.convertValue(tag,loader); 
     259             
     260            // attribute has not been set and there is no 
     261            // default value, skip the method call 
     262            if (val == null) { 
     263                continue; 
     264            } 
     265 
     266            try { 
     267                methodName           = att.getSetterMethod(); 
     268                Class meParamTypes[] = {att.getValueType(tag)}; 
     269                 
     270                Method me         = cl.getMethod(methodName, meParamTypes); 
     271                Object meParams[] = {val}; 
     272 
     273                me.invoke(instance, meParams); 
     274            } catch (Exception e) { 
     275                throw new ValueConversionException("Could not set attribute '" + att.getName() + "' of '" + this.type + "'.", e); 
     276            } 
     277        } 
     278    } 
     279     
     280    /** 
     281     * Add all children to the created instance 
     282     *  
     283     * @param instance 
     284     * @param tag 
     285     * @param loader 
     286     * @throws ValueConversionException 
     287     */ 
     288    private void addChildrenToValue(Object instance, Tag tag, ClassLoader loader) 
     289        throws ValueConversionException { 
     290         
     291        ArrayList ignore = this.constructor.getUsedChildrenNames(); 
     292         
     293        String methodName; 
     294        Class cl = instance.getClass(); 
     295         
     296        // traverse all children 
     297        ArrayList children = tag.getChildren();            
     298        if (children.size() == 0) { 
     299            return; 
     300        } 
     301 
     302        for (int i = 0; i < children.size(); i++) { 
     303            Tag child = (Tag)children.get(i); 
     304 
     305            if (ignore.contains(child.getName())) { 
     306                continue; 
     307            } 
     308             
    262309            methodName = child.getDefinition().getSetterMethod(); 
    263              
    264             // if the method name is set to ignore, the child will 
    265             // be ignored 
    266             if (methodName != null && methodName.equals("__ignore")) { 
    267                 continue; 
    268             } 
    269310            Object childValue = child.getDefinition().convertValue(child,loader); 
    270311            Object childParams[] = {childValue}; 
    271312             
    272            try { 
     313            try { 
    273314 
    274315                // Check, whether the current instance is a Properties object 
     
    291332                // Check, whether the current instance is a collection 
    292333                } else if (methodName == null && instance instanceof java.util.AbstractCollection) { 
    293                    Class childParamTypes[] = {Object.class}; 
    294                    Method childMethod = cl.getMethod("add", childParamTypes); 
    295                    childMethod.invoke(instance, childParams); 
     334                    Class childParamTypes[] = {Object.class}; 
     335                    Method childMethod      = cl.getMethod("add", childParamTypes); 
     336                    childMethod.invoke(instance, childParams); 
    296337                     
    297                // instance is any generic object 
     338                // instance is any generic object 
    298339                } else { 
    299                    Class childParamTypes[] = {child.getValueType(child)}; 
     340                    Class childParamTypes[] = {child.getValueType(child)}; 
    300341                    Method childMethod = null; 
    301342                     
     
    318359                    } 
    319360                    childMethod.invoke(instance, childParams); 
    320                 } 
    321             } catch (Exception t) { 
    322                 throw new ValueConversionException("Could not add child " + child.getKey() + " to " + this.getType() + " using "+methodName+"().", t); 
    323             } 
    324         } 
    325         return instance; 
    326     } 
    327  
     361                } 
     362            } catch (Exception e) { 
     363                throw new ValueConversionException("Could not add child " + child.getKey() + " to " + this.getType() + " using "+methodName+"().", e); 
     364            } 
     365        } 
     366    } 
     367     
    328368    /** 
    329369     * Get all interfaces of a class