Coverage Report - org.simpleframework.xml.core.ConstructorScanner
 
Classes in this File Line Coverage Branch Coverage Complexity
ConstructorScanner
96%
25/26
83%
10/12
2.167
 
 1  
 /*
 2  
  * ConstructorScanner.java July 2009
 3  
  *
 4  
  * Copyright (C) 2009, Niall Gallagher <niallg@users.sf.net>
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 15  
  * implied. See the License for the specific language governing 
 16  
  * permissions and limitations under the License.
 17  
  */
 18  
 
 19  
 package org.simpleframework.xml.core;
 20  
 
 21  
 import java.lang.reflect.Constructor;
 22  
 import java.util.ArrayList;
 23  
 import java.util.List;
 24  
 
 25  
 /**
 26  
  * The <code>ConstructorScanner</code> object is used to scan all 
 27  
  * all constructors that have XML annotations for their parameters. 
 28  
  * parameters. Each constructor scanned is converted in to a 
 29  
  * <code>Initializer</code> object. In order to ensure consistency
 30  
  * amongst the annotated parameters each named parameter must have
 31  
  * the exact same type and annotation attributes across the 
 32  
  * constructors. This ensures a consistent XML representation.
 33  
  *
 34  
  * @author Niall Gallagher
 35  
  * 
 36  
  * @see org.simpleframework.xml.core.Scanner
 37  
  */
 38  
 class ConstructorScanner {
 39  
 
 40  
    /**
 41  
     * This is a list of all the signatures represented by the type.
 42  
     */
 43  
    private List<Signature> signatures;
 44  
    
 45  
    /**
 46  
     * This is used to acquire a parameter by the parameter name.
 47  
     */
 48  
    private ParameterMap registry;
 49  
    
 50  
    /**
 51  
     * This represents the default no argument constructor.
 52  
     */
 53  
    private Signature primary;
 54  
    
 55  
    /**
 56  
     * This object contains various support functions for the class.
 57  
     */
 58  
    private Support support;
 59  
    
 60  
    /**
 61  
     * Constructor for the <code>ConstructorScanner</code> object. 
 62  
     * This is used to scan the specified detail for constructors that
 63  
     * can be used to instantiate the class. Only constructors that
 64  
     * have all parameters annotated will be considered.
 65  
     * 
 66  
     * @param detail this contains the details for the class scanned
 67  
     * @param support this contains various support functions
 68  
     */
 69  2389
    public ConstructorScanner(Detail detail, Support support) throws Exception {
 70  2389
       this.signatures = new ArrayList<Signature>();
 71  2389
       this.registry = new ParameterMap();
 72  2389
       this.support = support;
 73  2389
       this.scan(detail);
 74  2383
    }
 75  
    
 76  
    /**
 77  
     * This is used to acquire the default signature for the class. 
 78  
     * The default signature is the signature for the no argument
 79  
     * constructor for the type. If there is no default constructor
 80  
     * for the type then this will return null.
 81  
     * 
 82  
     * @return this returns the default signature if it exists
 83  
     */
 84  
    public Signature getSignature() {
 85  2370
       return primary;
 86  
    }
 87  
    
 88  
    /**
 89  
     * This returns the signatures for the type. All constructors are
 90  
     * represented as a signature and returned. More signatures than
 91  
     * constructors will be returned if a constructor is annotated 
 92  
     * with a union annotation.
 93  
     *
 94  
     * @return this returns the list of signatures for the type
 95  
     */
 96  
    public List<Signature> getSignatures() {
 97  2370
       return new ArrayList<Signature>(signatures);
 98  
    }
 99  
    
 100  
    /**
 101  
     * This returns a map of all parameters that exist. This is used
 102  
     * to validate all the parameters against the field and method
 103  
     * annotations that exist within the class. 
 104  
     * 
 105  
     * @return this returns a map of all parameters within the type
 106  
     */
 107  
    public ParameterMap getParameters() {
 108  4743
       return registry;
 109  
    }
 110  
    
 111  
    /**
 112  
     * This is used to scan the specified class for constructors that
 113  
     * can be used to instantiate the class. Only constructors that
 114  
     * have all parameters annotated will be considered.
 115  
     * 
 116  
     * @param detail this is the class detail that is to be scanned
 117  
     */
 118  
    private void scan(Detail detail) throws Exception {
 119  2389
       Constructor[] array = detail.getConstructors();
 120  
       
 121  2389
       if(!detail.isInstantiable()) {
 122  0
          throw new ConstructorException("Can not construct inner %s", detail);
 123  
       }
 124  6043
       for(Constructor factory: array){
 125  3660
          if(!detail.isPrimitive()) { 
 126  3660
             scan(factory);
 127  
          }
 128  
       } 
 129  2383
    }
 130  
    
 131  
    /**
 132  
     * This is used to scan the parameters within a constructor to 
 133  
     * determine the signature of the constructor. If the constructor
 134  
     * contains a union annotation multiple signatures will be used.
 135  
     * 
 136  
     * @param factory the constructor to scan for parameters
 137  
     */
 138  
    private void scan(Constructor factory) throws Exception {
 139  3660
       SignatureScanner scanner = new SignatureScanner(factory, registry, support);
 140  
 
 141  3657
       if(scanner.isValid()) {
 142  2098
          List<Signature> list = scanner.getSignatures();
 143  
             
 144  2095
          for(Signature signature : list) {
 145  2102
             int size = signature.size();
 146  
                
 147  2102
             if(size == 0) {
 148  1818
                primary = signature;
 149  
             }
 150  2102
             signatures.add(signature);
 151  2102
          }
 152  
       }
 153  3654
    }
 154  
 }