Coverage Report - org.simpleframework.xml.load.LabelFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
LabelFactory
83%
20/24
100%
8/8
3.286
LabelFactory$Entry
100%
6/6
N/A
3.286
 
 1  
 /*
 2  
  * LabelFactory.java July 2006
 3  
  *
 4  
  * Copyright (C) 2006, Niall Gallagher <niallg@users.sf.net>
 5  
  *
 6  
  * This library is free software; you can redistribute it and/or
 7  
  * modify it under the terms of the GNU Lesser General Public
 8  
  * License as published by the Free Software Foundation.
 9  
  *
 10  
  * This library is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  
  * GNU Lesser General Public License for more details.
 14  
  *
 15  
  * You should have received a copy of the GNU Lesser General 
 16  
  * Public License along with this library; if not, write to the 
 17  
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 18  
  * Boston, MA  02111-1307  USA
 19  
  */
 20  
 
 21  
 package org.simpleframework.xml.load;
 22  
 
 23  
 import org.simpleframework.xml.Attribute;
 24  
 import org.simpleframework.xml.Element;
 25  
 import org.simpleframework.xml.ElementArray;
 26  
 import org.simpleframework.xml.ElementList;
 27  
 import org.simpleframework.xml.ElementMap;
 28  
 import org.simpleframework.xml.Text;
 29  
 import java.lang.annotation.Annotation;
 30  
 import java.lang.reflect.Constructor;
 31  
 
 32  
 /**
 33  
  * The <code>LabelFactory</code> object is used to create instances of
 34  
  * the <code>Label</code> object that can be used to convert an XML
 35  
  * node into a Java object. Each label created requires the contact it
 36  
  * represents and the XML annotation it is marked with.  
 37  
  * <p>
 38  
  * The <code>Label</code> objects created by this factory a selected
 39  
  * using the XML annotation type. If the annotation type is not known
 40  
  * the factory will throw an exception, otherwise a label instance
 41  
  * is created that will expose the properties of the annotation.
 42  
  * 
 43  
  * @author Niall Gallagher
 44  
  */
 45  0
 final class LabelFactory {
 46  
 
 47  
    /**
 48  
     * Creates a <code>Label</code> using the provided contact and XML
 49  
     * annotation. The label produced contains all information related
 50  
     * to an object member. It knows the name of the XML entity, as
 51  
     * well as whether it is required. Once created the converter can
 52  
     * transform an XML node into Java object and vice versa.
 53  
     * 
 54  
     * @param contact this is contact that the label is produced for
 55  
     * @param label represents the XML annotation for the contact
 56  
     * 
 57  
     * @return returns the label instantiated for the field
 58  
     */
 59  
    public static Label getInstance(Contact contact, Annotation label) throws Exception {
 60  436
       Label value = getLabel(contact, label);
 61  
       
 62  436
       if(value == null) {
 63  0
          return value;
 64  
       }      
 65  436
       return new CacheLabel(value);
 66  
    } 
 67  
    
 68  
    /**
 69  
     * Creates a <code>Label</code> using the provided contact and XML
 70  
     * annotation. The label produced contains all information related
 71  
     * to an object member. It knows the name of the XML entity, as
 72  
     * well as whether it is required. Once created the converter can
 73  
     * transform an XML node into Java object and vice versa.
 74  
     * 
 75  
     * @param contact this is contact that the label is produced for
 76  
     * @param label represents the XML annotation for the contact
 77  
     * 
 78  
     * @return returns the label instantiated for the field
 79  
     */
 80  
    private static Label getLabel(Contact contact, Annotation label) throws Exception {      
 81  436
       Constructor factory = getConstructor(label);    
 82  
       
 83  436
       if(!factory.isAccessible()) {
 84  436
          factory.setAccessible(true);
 85  
       }
 86  436
       return (Label)factory.newInstance(contact, label);
 87  
    }
 88  
     
 89  
     /**
 90  
      * Creates a constructor that can be used to instantiate the label
 91  
      * used to represent the specified annotation. The constructor
 92  
      * created by this method takes two arguments, a contact object 
 93  
      * and an <code>Annotation</code> of the type specified.
 94  
      * 
 95  
      * @param label the XML annotation representing the label
 96  
      * 
 97  
      * @return returns a constructor for instantiating the label 
 98  
      * 
 99  
      * @throws Exception thrown if the annotation is not supported
 100  
      */
 101  
     private static Constructor getConstructor(Annotation label) throws Exception {
 102  436
        return getEntry(label).getConstructor();
 103  
     }
 104  
     
 105  
     /**
 106  
      * Creates an entry that is used to select the constructor for the
 107  
      * label. Each label must implement a constructor that takes a
 108  
      * contact and the specific XML annotation for that field. If the
 109  
      * annotation is not know this method throws an exception.
 110  
      * 
 111  
      * @param label the XML annotation used to create the label
 112  
      * 
 113  
      * @return this returns the entry used to create a suitable
 114  
      *         constructor for the label
 115  
      * 
 116  
      * @throws Exception thrown if the annotation is not supported
 117  
      */
 118  
     private static Entry getEntry(Annotation label) throws Exception{      
 119  436
        if(label instanceof Element) {
 120  182
           return new Entry(ElementLabel.class, Element.class);
 121  
        }
 122  254
        if(label instanceof ElementList) {
 123  58
           return new Entry(ElementListLabel.class, ElementList.class);
 124  
        }
 125  196
        if(label instanceof ElementArray) {
 126  29
           return new Entry(ElementArrayLabel.class, ElementArray.class);               
 127  
        }
 128  167
        if(label instanceof ElementMap) {
 129  17
           return new Entry(ElementMapLabel.class, ElementMap.class);
 130  
        }
 131  150
        if(label instanceof Attribute) {
 132  132
           return new Entry(AttributeLabel.class, Attribute.class);
 133  
        }
 134  18
        if(label instanceof Text) {
 135  18
           return new Entry(TextLabel.class, Text.class);
 136  
        }
 137  0
        throw new PersistenceException("Annotation %s not supported", label);
 138  
     }
 139  
     
 140  
     /**
 141  
      * The <code>Entry<code> object is used to create a constructor 
 142  
      * that can be used to instantiate the correct label for the XML
 143  
      * annotation specified. The constructor requires two arguments
 144  
      * a <code>Contact</code> and the specified XML annotation.
 145  
      * 
 146  
      * @see java.lang.reflect.Constructor
 147  
      */
 148  0
     private static class Entry {
 149  
        
 150  
        /**       
 151  
         * This is the XML annotation type within the constructor.
 152  
         */
 153  
        public Class argument;
 154  
        
 155  
        /**
 156  
         * This is the label type that is to be instantiated.
 157  
         */
 158  
        public Class label;
 159  
        
 160  
        /**
 161  
         * Constructor for the <code>Entry</code> object. This pairs
 162  
         * the label type with the XML annotation argument used within
 163  
         * the constructor. This allows constructor to be selected.
 164  
         * 
 165  
         * @param label this is the label type to be instantiated
 166  
         * @param argument type that is used within the constructor
 167  
         */
 168  436
        public Entry(Class label, Class argument) {
 169  436
           this.argument = argument;
 170  436
           this.label = label;
 171  436
        }
 172  
        
 173  
        /**
 174  
         * Creates the constructor used to instantiate the label for
 175  
         * the XML annotation. The constructor returned will take two
 176  
         * arguments, a contact and the XML annotation type. 
 177  
         * 
 178  
         * @return returns the constructor for the label object
 179  
         */
 180  
        public Constructor getConstructor() throws Exception {
 181  436
           return getConstructor(Contact.class);
 182  
        }
 183  
        
 184  
        /**
 185  
         * Creates the constructor used to instantiate the label for
 186  
         * the XML annotation. The constructor returned will take two
 187  
         * arguments, a contact and the XML annotation type.
 188  
         * 
 189  
         * @param type this is the XML annotation argument type used
 190  
         * 
 191  
         * @return returns the constructor for the label object
 192  
         */
 193  
        private Constructor getConstructor(Class type) throws Exception {
 194  436
           return label.getConstructor(type, argument);
 195  
        }
 196  
     }
 197  
 }