Coverage Report - org.simpleframework.xml.core.InstanceFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
InstanceFactory
91%
11/12
75%
3/4
1.5
InstanceFactory$ClassInstance
100%
9/9
50%
1/2
1.5
InstanceFactory$ValueInstance
0%
0/15
0%
0/6
1.5
 
 1  
 /*
 2  
  * Instantiator.java July 2006
 3  
  *
 4  
  * Copyright (C) 2006, 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  
 
 23  
 import org.simpleframework.xml.strategy.Value;
 24  
 import org.simpleframework.xml.util.Cache;
 25  
 import org.simpleframework.xml.util.ConcurrentCache;
 26  
 
 27  
 /**
 28  
  * The <code>Instantiator</code> is used to instantiate types that 
 29  
  * will leverage a constructor cache to quickly create the objects.
 30  
  * This is used by the various object factories to return type 
 31  
  * instances that can be used by converters to create the objects 
 32  
  * that will later be deserialized.
 33  
  *
 34  
  * @author Niall Gallagher
 35  
  * 
 36  
  * @see org.simpleframework.xml.core.Instance
 37  
  */
 38  
 class InstanceFactory {
 39  
 
 40  
    /**
 41  
     * This is used to cache the constructors for the given types.
 42  
     */
 43  
    private final Cache<Constructor> cache;
 44  
    
 45  
    /**
 46  
     * Constructor for the <code>Instantiator</code> object. This will
 47  
     * create a constructor cache that can be used to cache all of 
 48  
     * the constructors instantiated for the required types. 
 49  
     */
 50  950
    public InstanceFactory() {
 51  950
       this.cache = new ConcurrentCache<Constructor>();
 52  950
    }
 53  
    
 54  
    /**
 55  
     * This will create an <code>Instance</code> that can be used
 56  
     * to instantiate objects of the specified class. This leverages
 57  
     * an internal constructor cache to ensure creation is quicker.
 58  
     * 
 59  
     * @param value this contains information on the object instance
 60  
     * 
 61  
     * @return this will return an object for instantiating objects
 62  
     */
 63  
    public Instance getInstance(Value value) {
 64  0
       return new ValueInstance(value);
 65  
    }
 66  
 
 67  
    /**
 68  
     * This will create an <code>Instance</code> that can be used
 69  
     * to instantiate objects of the specified class. This leverages
 70  
     * an internal constructor cache to ensure creation is quicker.
 71  
     * 
 72  
     * @param type this is the type that is to be instantiated
 73  
     * 
 74  
     * @return this will return an object for instantiating objects
 75  
     */
 76  
    public Instance getInstance(Class type) {
 77  1784132
       return new ClassInstance(type);
 78  
    }
 79  
    
 80  
    /**
 81  
     * This method will instantiate an object of the provided type. If
 82  
     * the object or constructor does not have public access then this
 83  
     * will ensure the constructor is accessible and can be used.
 84  
     * 
 85  
     * @param type this is used to ensure the object is accessible
 86  
     *
 87  
     * @return this returns an instance of the specific class type
 88  
     */ 
 89  
    protected Object getObject(Class type) throws Exception {
 90  782955
       Constructor method = cache.fetch(type);
 91  
       
 92  782955
       if(method == null) {
 93  1365
          method = type.getDeclaredConstructor();      
 94  
 
 95  1365
          if(!method.isAccessible()) {
 96  1365
             method.setAccessible(true);              
 97  
          }
 98  1365
          cache.cache(type, method);
 99  
       }
 100  782955
       return method.newInstance();   
 101  
    }
 102  
    
 103  
    /**
 104  
     * The <code>ValueInstance</code> object is used to create an object
 105  
     * by using a <code>Value</code> instance to determine the type. If
 106  
     * the provided value instance represents a reference then this will
 107  
     * simply provide the value of the reference, otherwise it will
 108  
     * instantiate a new object and return that.
 109  
     */
 110  
    private class ValueInstance implements Instance {
 111  
       
 112  
       /**
 113  
        * This is the internal value that contains the criteria.
 114  
        */
 115  
       private final Value value;
 116  
       
 117  
       /**
 118  
        * This is the type that is to be instantiated by this.
 119  
        */
 120  
       private final Class type;
 121  
       
 122  
       /**
 123  
        * Constructor for the <code>ValueInstance</code> object. This 
 124  
        * is used to represent an instance that delegates to the given
 125  
        * value object in order to acquire the object. 
 126  
        * 
 127  
        * @param value this is the value object that contains the data
 128  
        */
 129  0
       public ValueInstance(Value value) {
 130  0
          this.type = value.getType();
 131  0
          this.value = value;
 132  0
       }
 133  
       
 134  
       /**
 135  
        * This method is used to acquire an instance of the type that
 136  
        * is defined by this object. If for some reason the type can
 137  
        * not be instantiated an exception is thrown from this.
 138  
        * 
 139  
        * @return an instance of the type this object represents
 140  
        */
 141  
       public Object getInstance() throws Exception {
 142  0
          if(value.isReference()) {
 143  0
             return value.getValue();
 144  
          }
 145  0
          Object object = getObject(type);
 146  
          
 147  0
          if(value != null) {
 148  0
             value.setValue(object);
 149  
          }
 150  0
          return object;
 151  
       }
 152  
       
 153  
       /**
 154  
        * This method is used acquire the value from the type and if
 155  
        * possible replace the value for the type. If the value can
 156  
        * not be replaced then an exception should be thrown. This 
 157  
        * is used to allow primitives to be inserted into a graph.
 158  
        * 
 159  
        * @param object this is the object to insert as the value
 160  
        * 
 161  
        * @return an instance of the type this object represents
 162  
        */
 163  
       public Object setInstance(Object object) {
 164  0
          if(value != null) {
 165  0
             value.setValue(object);
 166  
          }
 167  0
          return object;
 168  
       }
 169  
 
 170  
       /**
 171  
        * This is used to determine if the type is a reference type.
 172  
        * A reference type is a type that does not require any XML
 173  
        * deserialization based on its annotations. Values that are
 174  
        * references could be substitutes objects or existing ones. 
 175  
        * 
 176  
        * @return this returns true if the object is a reference
 177  
        */
 178  
       public boolean isReference() {
 179  0
          return value.isReference();
 180  
       }
 181  
 
 182  
       /**
 183  
        * This is the type of the object instance that will be created
 184  
        * by the <code>getInstance</code> method. This allows the 
 185  
        * deserialization process to perform checks against the field.
 186  
        * 
 187  
        * @return the type of the object that will be instantiated
 188  
        */
 189  
       public Class getType() {
 190  0
          return type;
 191  
       }
 192  
    }
 193  
    
 194  
    /**
 195  
     * The <code>ClassInstance</code> object is used to create an object
 196  
     * by using a <code>Class</code> to determine the type. If the given
 197  
     * class can not be instantiated then this throws an exception when
 198  
     * the instance is requested. For performance an instantiator is
 199  
     * given as it contains a reflection cache for constructors.
 200  
     */
 201  
    private class ClassInstance implements Instance {
 202  
       
 203  
       /**
 204  
        * This represents the value of the instance if it is set.
 205  
        */
 206  
       private Object value;
 207  
       
 208  
       /**
 209  
        * This is the type of the instance that is to be created.
 210  
        */
 211  
       private Class type;
 212  
       
 213  
       /**
 214  
        * Constructor for the <code>ClassInstance</code> object. This is
 215  
        * used to create an instance of the specified type. If the given
 216  
        * type can not be instantiated then an exception is thrown.
 217  
        * 
 218  
        * @param type this is the type that is to be instantiated
 219  
        */
 220  1784132
       public ClassInstance(Class type) {
 221  1784132
          this.type = type;
 222  1784132
       }
 223  
 
 224  
       /**
 225  
        * This method is used to acquire an instance of the type that
 226  
        * is defined by this object. If for some reason the type can
 227  
        * not be instantiated an exception is thrown from this.
 228  
        * 
 229  
        * @return an instance of the type this object represents
 230  
        */
 231  
       public Object getInstance() throws Exception {
 232  782955
          if(value == null) {
 233  782955
             value = getObject(type);
 234  
          }
 235  782955
          return value;
 236  
       }
 237  
       
 238  
       /**
 239  
        * This method is used acquire the value from the type and if
 240  
        * possible replace the value for the type. If the value can
 241  
        * not be replaced then an exception should be thrown. This 
 242  
        * is used to allow primitives to be inserted into a graph.
 243  
        * 
 244  
        * @param value this is the value to insert as the type
 245  
        * 
 246  
        * @return an instance of the type this object represents
 247  
        */
 248  
       public Object setInstance(Object value) throws Exception {
 249  2409219
          return this.value = value;
 250  
       }
 251  
 
 252  
       /**
 253  
        * This is the type of the object instance that will be created
 254  
        * by the <code>getInstance</code> method. This allows the 
 255  
        * deserialization process to perform checks against the field.
 256  
        * 
 257  
        * @return the type of the object that will be instantiated
 258  
        */
 259  
       public Class getType() {
 260  705921
          return type;
 261  
       }
 262  
 
 263  
       /**
 264  
        * This is used to determine if the type is a reference type.
 265  
        * A reference type is a type that does not require any XML
 266  
        * deserialization based on its annotations. Values that are
 267  
        * references could be substitutes objects or existing ones. 
 268  
        * 
 269  
        * @return this returns true if the object is a reference
 270  
        */
 271  
       public boolean isReference() {
 272  1705221
          return false;
 273  
       }
 274  
    }
 275  
 }