Coverage Report - org.simpleframework.xml.core.Signature
 
Classes in this File Line Coverage Branch Coverage Complexity
Signature
85%
30/35
62%
5/8
1.222
 
 1  
 /*
 2  
  * Signature.java April 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.Iterator;
 23  
 import java.util.List;
 24  
 
 25  
 /**
 26  
  * The <code>Signature</code> object represents a constructor
 27  
  * of parameters iterable in declaration order. This is used so
 28  
  * that parameters can be acquired by name for validation. It is
 29  
  * also used to create an array of <code>Parameter</code> objects
 30  
  * that can be used to acquire the correct deserialized values
 31  
  * to use in order to instantiate the object.
 32  
  * 
 33  
  * @author Niall Gallagher
 34  
  */
 35  
 class Signature implements Iterable<Parameter> {
 36  
    
 37  
    /**
 38  
     * This is the map of parameters that this signature uses.
 39  
     */
 40  
    private final ParameterMap parameters;
 41  
    
 42  
    /**
 43  
     * This is the type that the parameters are created for.
 44  
     */
 45  
    private final Constructor factory;
 46  
    
 47  
    /**
 48  
     * This is the type that the signature was created for.
 49  
     */
 50  
    private final Class type;
 51  
    
 52  
    /**
 53  
     * Constructor for the <code>Signature</code> object. This 
 54  
     * is used to create a hash map that can be used to acquire
 55  
     * parameters by name. It also provides the parameters in
 56  
     * declaration order within a for each loop.
 57  
     * 
 58  
     * @param signature this is the signature to be copied
 59  
     */
 60  
    public Signature(Signature signature) {
 61  2419
       this(signature.factory, signature.type);
 62  2419
    }
 63  
    
 64  
    /**
 65  
     * Constructor for the <code>Signature</code> object. This 
 66  
     * is used to create a hash map that can be used to acquire
 67  
     * parameters by name. It also provides the parameters in
 68  
     * declaration order within a for each loop.
 69  
     * 
 70  
     * @param factory this is the constructor this represents
 71  
     */
 72  
    public Signature(Constructor factory) {
 73  2142
       this(factory, factory.getDeclaringClass());
 74  2142
    }
 75  
    
 76  
    /**
 77  
     * Constructor for the <code>Signature</code> object. This 
 78  
     * is used to create a hash map that can be used to acquire
 79  
     * parameters by name. It also provides the parameters in
 80  
     * declaration order within a for each loop.
 81  
     * 
 82  
     * @param factory this is the constructor this represents
 83  
     * @param type this is the type the map is created for
 84  
     */
 85  4561
    public Signature(Constructor factory, Class type) {
 86  4561
       this.parameters = new ParameterMap();
 87  4561
       this.factory = factory;
 88  4561
       this.type = type;
 89  4561
    }
 90  
    
 91  
    /**
 92  
     * This represents the number of parameters this signature has.
 93  
     * A signature with no parameters is the default no argument
 94  
     * constructor, anything else is a candidate for injection.
 95  
     * 
 96  
     * @return this returns the number of annotated parameters
 97  
     */
 98  
    public int size() {
 99  2102
       return parameters.size();
 100  
    }
 101  
    
 102  
    /**
 103  
     * This is used to determine if there are any parameters in the
 104  
     * signature. If the signature contains no parameters then this
 105  
     * will return true, if it does then this returns false.
 106  
     * 
 107  
     * @return this returns true of the signature has no parameters
 108  
     */
 109  
    public boolean isEmpty() {
 110  0
       return parameters.isEmpty();
 111  
    }
 112  
    
 113  
    /**
 114  
     * This returns true if the signature contains a parameter that
 115  
     * is mapped to the specified key. If no parameter exists with
 116  
     * this key then this will return false.
 117  
     * 
 118  
     * @param key this is the key the parameter is mapped to
 119  
     * 
 120  
     * @return this returns true if there is a parameter mapping
 121  
     */
 122  
    public boolean contains(Object key) {
 123  649
       return parameters.containsKey(key);
 124  
    }
 125  
    
 126  
    /**
 127  
     * This is used to iterate over <code>Parameter</code> objects.
 128  
     * Parameters are iterated in the order that they are added to
 129  
     * the map. This is primarily used for convenience iteration. 
 130  
     * 
 131  
     * @return this returns an iterator for the parameters
 132  
     */
 133  
    public Iterator<Parameter> iterator() {
 134  2419
       return parameters.iterator();
 135  
    }
 136  
    
 137  
    /**
 138  
     * This is used to remove a parameter from the signature. This 
 139  
     * returns any parameter removed if it exists, if not then this
 140  
     * returns null. This is used when performing matching.
 141  
     * 
 142  
     * @param key this is the key of the parameter to remove
 143  
     * 
 144  
     * @return this returns the parameter that was removed
 145  
     */
 146  
    public Parameter remove(Object key) {
 147  0
       return parameters.remove(key);
 148  
    }
 149  
    
 150  
    /**
 151  
     * This is used to acquire a <code>Parameter</code> using the
 152  
     * position of that parameter within the constructor. This 
 153  
     * allows a builder to determine which parameters to use.
 154  
     * 
 155  
     * @param ordinal this is the position of the parameter
 156  
     * 
 157  
     * @return this returns the parameter for the position
 158  
     */
 159  
    public Parameter get(int ordinal) {
 160  48
       return parameters.get(ordinal);
 161  
    }
 162  
    
 163  
    /**
 164  
     * This is used to acquire the parameter based on its name. This
 165  
     * is used for convenience when the parameter name needs to be
 166  
     * matched up with an annotated field or method.
 167  
     * 
 168  
     * @param key this is the key of the parameter to acquire
 169  
     * 
 170  
     * @return this is the parameter mapped to the given name
 171  
     */
 172  
    public Parameter get(Object key) {
 173  1199
       return parameters.get(key);
 174  
    }
 175  
     
 176  
    /**
 177  
     * This is used to acquire an list of <code>Parameter</code>
 178  
     * objects in declaration order. This list will help with the
 179  
     * resolution of the correct constructor for deserialization
 180  
     * of the XML. It also provides a faster method of iteration.
 181  
     * 
 182  
     * @return this returns the parameters in declaration order
 183  
     */
 184  
    public List<Parameter> getAll() {
 185  4123
       return parameters.getAll();
 186  
    }
 187  
    
 188  
    /**
 189  
     * This will add the provided parameter to the signature. The
 190  
     * parameter is added to the signature mapped to the key of
 191  
     * the parameter. If the key is null it is not added.
 192  
     * 
 193  
     * @param parameter this is the parameter to be added
 194  
     */
 195  
    public void add(Parameter parameter) {
 196  1803
       Object key = parameter.getKey();
 197  
       
 198  1803
       if(key != null) {
 199  1803
          parameters.put(key, parameter);
 200  
       }
 201  1803
    }
 202  
    
 203  
    /**
 204  
     * This will add a new mapping to the signature based on the
 205  
     * provided key. Adding a mapping to a parameter using something
 206  
     * other than the key for the parameter allows for resolution
 207  
     * of the parameter based on a path or a name if desired.
 208  
     * 
 209  
     * @param key this is the key to map the parameter to
 210  
     * 
 211  
     * @param parameter this is the parameter to be mapped
 212  
     */
 213  
    public void set(Object key, Parameter parameter) {
 214  33
       parameters.put(key, parameter);
 215  33
    }
 216  
    
 217  
    /**
 218  
     * This is used to instantiate the object using the default no
 219  
     * argument constructor. If for some reason the object can not be
 220  
     * instantiated then this will throw an exception with the reason.    
 221  
     * 
 222  
     * @return this returns the object that has been instantiated
 223  
     */
 224  
    public Object create() throws Exception {
 225  0
       if(!factory.isAccessible()) {
 226  0
          factory.setAccessible(true);
 227  
       } 
 228  0
       return factory.newInstance();
 229  
    }
 230  
    
 231  
    /**
 232  
     * This is used to instantiate the object using a constructor that
 233  
     * takes deserialized objects as arguments. The objects that have
 234  
     * been deserialized are provided in declaration order so they can
 235  
     * be passed to the constructor to instantiate the object.
 236  
     * 
 237  
     * @param list this is the list of objects used for instantiation
 238  
     * 
 239  
     * @return this returns the object that has been instantiated
 240  
     */
 241  
    public Object create(Object[] list) throws Exception {
 242  276
       if(!factory.isAccessible()) {
 243  191
          factory.setAccessible(true);
 244  
       } 
 245  276
       return factory.newInstance(list);
 246  
    }
 247  
    
 248  
    /**
 249  
     * This is used to build a <code>Signature</code> with the given
 250  
     * context so that keys are styled. This allows serialization to
 251  
     * match styled element names or attributes to ensure that they 
 252  
     * can be used to acquire the parameters.
 253  
     * 
 254  
     * @return this returns a signature with styled keys
 255  
     */
 256  
    public Signature copy() throws Exception {
 257  332
       Signature signature = new Signature(this);
 258  
       
 259  332
       for(Parameter parameter : this) {  
 260  637
          signature.add(parameter);
 261  
       }
 262  332
       return signature;
 263  
    }
 264  
    
 265  
    /**
 266  
     * This is the type associated with the <code>Signature</code>.
 267  
     * All instances returned from this creator will be of this type.
 268  
     * 
 269  
     * @return this returns the type associated with the signature
 270  
     */
 271  
    public Class getType() {
 272  3895
       return type;
 273  
    }
 274  
    
 275  
    /**
 276  
     * This is used to acquire a descriptive name for the instantiator.
 277  
     * Providing a name is useful in debugging and when exceptions are
 278  
     * thrown as it describes the constructor the instantiator represents.
 279  
     * 
 280  
     * @return this returns the name of the constructor to be used
 281  
     */
 282  
    public String toString() {
 283  3
       return factory.toString();
 284  
    }
 285  
 }