Coverage Report - org.simpleframework.xml.load.ElementListLabel
 
Classes in this File Line Coverage Branch Coverage Complexity
ElementListLabel
95%
36/38
100%
6/6
1.667
 
 1  
 /*
 2  
  * ElementListLabel.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.ElementList;
 24  
 
 25  
 /**
 26  
  * The <code>ElementListLabel</code> represents a label that is used
 27  
  * to represent an XML element list in a class schema. This element 
 28  
  * list label can be used to convert an XML node into a collection of
 29  
  * composite objects. Each element converted with the converter this
 30  
  * creates must be an XML serializable element.
 31  
  * 
 32  
  * @author Niall Gallagher
 33  
  * 
 34  
  *  @see org.simpleframework.xml.ElementList
 35  
  */
 36  
 class ElementListLabel implements Label {
 37  
 
 38  
    /**
 39  
     * This references the annotation that the field uses.
 40  
     */
 41  
    private ElementList label;
 42  
    
 43  
    /**
 44  
     * This contains the details of the annotated contact object.
 45  
     */
 46  
    private Signature detail;
 47  
    
 48  
    /**
 49  
     * This is the type of collection this list will instantiate.
 50  
     */
 51  
    private Class type;
 52  
    
 53  
    /**
 54  
     * Represents the type of objects this list will hold.
 55  
     */
 56  
    private Class item;
 57  
    
 58  
    /**
 59  
     * This is the name of the XML entry from the annotation.
 60  
     */
 61  
    private String entry;
 62  
    
 63  
    /**
 64  
     * This is the name of the element for this label instance.
 65  
     */
 66  
    private String name;  
 67  
 
 68  
    /**
 69  
     * Constructor for the <code>ElementListLabel</code> object. This
 70  
     * creates a label object, which can be used to convert an XML 
 71  
     * node to a <code>Collection</code> of XML serializable objects.
 72  
     * 
 73  
     * @param contact this is the contact that this label represents
 74  
     * @param label the annotation that contains the schema details
 75  
     */
 76  58
    public ElementListLabel(Contact contact, ElementList label) {
 77  58
       this.detail = new Signature(contact, this);
 78  58
       this.type = contact.getType();
 79  58
       this.entry = label.entry();
 80  58
       this.item = label.type();
 81  58
       this.name = label.name();      
 82  58
       this.label = label;
 83  58
    }
 84  
 
 85  
    /**
 86  
     * This will create a <code>Converter</code> for transforming an XML
 87  
     * element into a collection of XML serializable objects. The XML
 88  
     * schema class for these objects must be present the element list
 89  
     * annotation. 
 90  
     * 
 91  
     * @param root this is the source object used for serialization
 92  
     * 
 93  
     * @return this returns the converter for creating a collection 
 94  
     */
 95  
    public Converter getConverter(Source root) throws Exception {
 96  42280
       String entry = getEntry();
 97  
       
 98  42280
       if(!label.inline()) {
 99  42203
          return getConverter(root, entry);
 100  
       }
 101  77
       return getInlineConverter(root, entry);      
 102  
    }
 103  
 
 104  
    /**
 105  
     * This will create a <code>Converter</code> for transforming an XML
 106  
     * element into a collection of XML serializable objects. The XML
 107  
     * schema class for these objects must be present the element list
 108  
     * annotation. 
 109  
     * 
 110  
     * @param root this is the source object used for serialization
 111  
     * @param name this is the name of the XML entry element to use
 112  
     * 
 113  
     * @return this returns the converter for creating a collection 
 114  
     */
 115  
    private Converter getConverter(Source root, String name) throws Exception {      
 116  42203
       Class item = getDependant();
 117  
       
 118  42203
       if(!Factory.isPrimitive(item)) {
 119  42162
          return new CompositeList(root, type, item, name);
 120  
       }
 121  41
       return new PrimitiveList(root, type, item, name);      
 122  
    }
 123  
    
 124  
    /**
 125  
     * This will create a <code>Converter</code> for transforming an XML
 126  
     * element into a collection of XML serializable objects. The XML
 127  
     * schema class for these objects must be present the element list
 128  
     * annotation. 
 129  
     * 
 130  
     * @param root this is the source object used for serialization
 131  
     * 
 132  
     * @return this returns the converter for creating a collection 
 133  
     */
 134  
    private Converter getInlineConverter(Source root, String name) throws Exception {      
 135  77
       Class item = getDependant();
 136  
       
 137  77
       if(!Factory.isPrimitive(item)) {
 138  42
          return new CompositeInlineList(root, type, item, name);
 139  
       }
 140  35
       return new PrimitiveInlineList(root, type, item, name);      
 141  
    }
 142  
    
 143  
    /**
 144  
     * This is used to acquire the dependant type for the annotated
 145  
     * list. This will simply return the type that the collection is
 146  
     * composed to hold. This must be a serializable type, that is,
 147  
     * a type that is annotated with the <code>Root</code> class.
 148  
     * 
 149  
     * @return this returns the component type for the collection
 150  
     */
 151  
    public Class getDependant() throws Exception  {      
 152  42386
       Contact contact = getContact();
 153  
      
 154  42386
       if(item == void.class) {
 155  34
          item = contact.getDependant();
 156  
       }        
 157  42386
       if(item == null) {
 158  0
          throw new ElementException("Unable to determine type for %s", label);           
 159  
       }     
 160  42386
       return item;
 161  
    }
 162  
    
 163  
    /**
 164  
     * This is used to either provide the entry value provided within
 165  
     * the annotation or compute a entry value. If the entry string
 166  
     * is not provided the the entry value is calculated as the type
 167  
     * of primitive the object is as a simplified class name.
 168  
     * 
 169  
     * @return this returns the name of the XML entry element used 
 170  
     */
 171  
    public String getEntry() throws Exception {      
 172  42396
       if(detail.isEmpty(entry)) {
 173  48
          entry = detail.getEntry();
 174  
       }
 175  42396
       return entry;
 176  
    }
 177  
    
 178  
    /**
 179  
     * This is used to acquire the name of the element or attribute
 180  
     * that is used by the class schema. The name is determined by
 181  
     * checking for an override within the annotation. If it contains
 182  
     * a name then that is used, if however the annotation does not
 183  
     * specify a name the the field or method name is used instead.
 184  
     * 
 185  
     * @return returns the name that is used for the XML property
 186  
     */
 187  
    public String getName() throws Exception {
 188  58
       return detail.getName();
 189  
    }
 190  
    
 191  
    /**
 192  
     * This acts as a convinience method used to determine the type of
 193  
     * contact this represents. This is used when an object is written
 194  
     * to XML. It determines whether a <code>class</code> attribute
 195  
     * is required within the serialized XML element, that is, if the
 196  
     * class returned by this is different from the actual value of the
 197  
     * object to be serialized then that type needs to be remembered.
 198  
     *  
 199  
     * @return this returns the type of the contact class
 200  
     */ 
 201  
    public Class getType() {
 202  58
       return type;      
 203  
    }
 204  
    
 205  
    /**
 206  
     * This is used to acquire the contact object for this label. The 
 207  
     * contact retrieved can be used to set any object or primitive that
 208  
     * has been deserialized, and can also be used to acquire values to
 209  
     * be serialized in the case of object persistance. All contacts 
 210  
     * that are retrieved from this method will be accessible. 
 211  
     * 
 212  
     * @return returns the contact that this label is representing
 213  
     */
 214  
    public Contact getContact() {
 215  42444
       return detail.getContact();
 216  
    }
 217  
    
 218  
    /**
 219  
     * This is used to acquire the name of the element or attribute
 220  
     * as taken from the annotation. If the element or attribute
 221  
     * explicitly specifies a name then that name is used for the
 222  
     * XML element or attribute used. If however no overriding name
 223  
     * is provided then the method or field is used for the name. 
 224  
     * 
 225  
     * @return returns the name of the annotation for the contact
 226  
     */
 227  
    public String getOverride() {
 228  99
       return name;
 229  
    }
 230  
    
 231  
    /**
 232  
     * This is used to determine whether the annotation requires it
 233  
     * and its children to be written as a CDATA block. This is done
 234  
     * when a primitive or other such element requires a text value
 235  
     * and that value needs to be encapsulated within a CDATA block.
 236  
     * 
 237  
     * @return currently the element list does not require CDATA
 238  
     */
 239  
    public boolean isData() {
 240  58
       return label.data();
 241  
    }
 242  
    
 243  
    /**
 244  
     * This is used to determine whether the XML element is required. 
 245  
     * This ensures that if an XML element is missing from a document
 246  
     * that deserialization can continue. Also, in the process of
 247  
     * serialization, if a value is null it does not need to be 
 248  
     * written to the resulting XML document.
 249  
     * 
 250  
     * @return true if the label represents a some required data
 251  
     */   
 252  
    public boolean isRequired() {
 253  58
       return label.required();
 254  
    }
 255  
    
 256  
    /**
 257  
     * This is used to determine whether the list has been specified
 258  
     * as inline. If the list is inline then no overrides are needed
 259  
     * and the outer XML element for the list is not used.
 260  
     * 
 261  
     * @return this returns whether the annotation is inline
 262  
     */
 263  
    public boolean isInline() {
 264  116
       return label.inline();
 265  
    }
 266  
    
 267  
    /**
 268  
     * This is used to provide a configured empty value used when the
 269  
     * annotated value is null. This ensures that XML can be created
 270  
     * with required details regardless of whether values are null or
 271  
     * not. It also provides a means for sensible default values.
 272  
     * 
 273  
     * @return this returns the string to use for default values
 274  
     */
 275  
    public String getEmpty() {
 276  58
       return null;
 277  
    }
 278  
    
 279  
    /**
 280  
     * This is used to describe the annotation and method or field
 281  
     * that this label represents. This is used to provide error
 282  
     * messages that can be used to debug issues that occur when
 283  
     * processing a method. This will provide enough information
 284  
     * such that the problem can be isolated correctly. 
 285  
     * 
 286  
     * @return this returns a string representation of the label
 287  
     */
 288  
    public String toString() {
 289  0
       return detail.toString();
 290  
    }   
 291  
 }