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