Coverage Report - org.simpleframework.xml.core.TextLabel
 
Classes in this File Line Coverage Branch Coverage Complexity
TextLabel
96%
32/33
83%
5/6
1.312
 
 1  
 /*
 2  
  * TextLabel.java April 2007
 3  
  *
 4  
  * Copyright (C) 2007, 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.annotation.Annotation;
 22  
 
 23  
 import org.simpleframework.xml.Text;
 24  
 import org.simpleframework.xml.strategy.Type;
 25  
 import org.simpleframework.xml.stream.Format;
 26  
 
 27  
 /**
 28  
  * The <code>TextLabel</code> represents a label that is used to get
 29  
  * a converter for a text entry within an XML element. This label is
 30  
  * used to convert an XML text entry into a primitive value such as 
 31  
  * a string or an integer, this will throw an exception if the field
 32  
  * value does not represent a primitive object.
 33  
  * 
 34  
  * @author Niall Gallagher
 35  
  * 
 36  
  *  @see org.simpleframework.xml.Text
 37  
  */
 38  221
 class TextLabel extends TemplateLabel {
 39  
    
 40  
    /**
 41  
     * This represents the signature of the annotated contact.
 42  
     */
 43  
    private Introspector detail;
 44  
    
 45  
    /**
 46  
     * This is the path that is used to represent this text.
 47  
     */
 48  
    private Expression path;
 49  
    
 50  
    /**
 51  
     * The contact that this annotation label represents.
 52  
     */
 53  
    private Contact contact;
 54  
    
 55  
    /**
 56  
     * References the annotation that was used by the contact.
 57  
     */
 58  
    private Text label;
 59  
    
 60  
    /**
 61  
     * This is the type of the class that the field references.
 62  
     */
 63  
    private Class type;
 64  
    
 65  
    /**
 66  
     * This is the default value to use if the real value is null.
 67  
     */
 68  
    private String empty;
 69  
    
 70  
    /**
 71  
     * This is used to determine if the attribute is required.
 72  
     */
 73  
    private boolean required;
 74  
    
 75  
    /**
 76  
     * This is used to determine if the attribute is data.
 77  
     */
 78  
    private boolean data;
 79  
    
 80  
    /**
 81  
     * Constructor for the <code>TextLabel</code> object. This is
 82  
     * used to create a label that can convert a XML node into a 
 83  
     * primitive value from an XML element text value.
 84  
     * 
 85  
     * @param contact this is the contact this label represents
 86  
     * @param label this is the annotation for the contact 
 87  
     * @param format this is the format used for this label
 88  
     */
 89  130
    public TextLabel(Contact contact, Text label, Format format) {
 90  130
       this.detail = new Introspector(contact, this, format);
 91  130
       this.required = label.required();
 92  130
       this.type = contact.getType();
 93  130
       this.empty = label.empty();
 94  130
       this.data = label.data();
 95  130
       this.contact = contact;
 96  130
       this.label = label;  
 97  130
    }
 98  
    
 99  
    /**
 100  
     * This is used to acquire the <code>Decorator</code> for this.
 101  
     * A decorator is an object that adds various details to the
 102  
     * node without changing the overall structure of the node. For
 103  
     * example comments and namespaces can be added to the node with
 104  
     * a decorator as they do not affect the deserialization.
 105  
     * 
 106  
     * @return this returns the decorator associated with this
 107  
     */
 108  
    public Decorator getDecorator() throws Exception {
 109  109
       return null;
 110  
    }
 111  
    
 112  
    /**
 113  
     * Creates a converter that can be used to transform an XML node to
 114  
     * an object and vice versa. The converter created will handles
 115  
     * only XML text and requires the context object to be provided. 
 116  
     * 
 117  
     * @param context this is the context object used for serialization
 118  
     * 
 119  
     * @return this returns a converter for serializing XML elements
 120  
     */
 121  
    public Converter getConverter(Context context) throws Exception {
 122  218
       String ignore = getEmpty(context);
 123  218
       Type type = getContact();
 124  
       
 125  218
       if(!context.isPrimitive(type)) {
 126  1
          throw new TextException("Cannot use %s to represent %s", type, label);
 127  
       }
 128  217
       return new Primitive(context, type, ignore);
 129  
    }
 130  
    
 131  
    /**
 132  
     * This is used to provide a configured empty value used when the
 133  
     * annotated value is null. This ensures that XML can be created
 134  
     * with required details regardless of whether values are null or
 135  
     * not. It also provides a means for sensible default values.
 136  
     * 
 137  
     * @param context this is the context object for the serialization
 138  
     * 
 139  
     * @return this returns the string to use for default values
 140  
     */
 141  
    public String getEmpty(Context context) {
 142  439
       if(detail.isEmpty(empty)) {
 143  439
          return null;
 144  
       }
 145  0
       return empty;
 146  
    }
 147  
    
 148  
    /**
 149  
     * This is used to acquire the path of the element or attribute
 150  
     * that is used by the class schema. The path is determined by
 151  
     * acquiring the XPath expression and appending the name of the
 152  
     * label to form a fully qualified path.
 153  
     * 
 154  
     * @return returns the path that is used for the XML property
 155  
     */
 156  
    public String getPath() throws Exception {
 157  478
       return getExpression().getPath();
 158  
    }
 159  
    
 160  
    /**
 161  
     * This method is used to return an XPath expression that is 
 162  
     * used to represent the position of this label. If there is no
 163  
     * XPath expression associated with this then an empty path is
 164  
     * returned. This will never return a null expression.
 165  
     * 
 166  
     * @return the XPath expression identifying the location
 167  
     */
 168  
    public Expression getExpression() throws Exception {
 169  608
       if(path == null) {
 170  130
          path = detail.getExpression();
 171  
       }
 172  608
       return path;
 173  
    }
 174  
    
 175  
    /**
 176  
     * This acquires the annotation associated with this label. This
 177  
     * is typically the annotation acquired from the field or method.
 178  
     * However, in the case of unions this will return the actual
 179  
     * annotation within the union group that this represents.
 180  
     * 
 181  
     * @return this returns the annotation that this represents
 182  
     */
 183  
    public Annotation getAnnotation() {
 184  109
       return label;
 185  
    }
 186  
    
 187  
    /**
 188  
     * This is used to acquire the contact object for this label. The 
 189  
     * contact retrieved can be used to set any object or primitive that
 190  
     * has been deserialized, and can also be used to acquire values to
 191  
     * be serialized in the case of object persistence. All contacts 
 192  
     * that are retrieved from this method will be accessible. 
 193  
     * 
 194  
     * @return returns the contact that this label is representing
 195  
     */
 196  
    public Contact getContact() {
 197  327
       return contact;
 198  
    }
 199  
    
 200  
    /**
 201  
     * This is used to acquire the name of the element or attribute
 202  
     * that is used by the class schema. The name is determined by
 203  
     * checking for an override within the annotation. If it contains
 204  
     * a name then that is used, if however the annotation does not
 205  
     * specify a name the the field or method name is used instead.
 206  
     * 
 207  
     * @return returns the name that is used for the XML property
 208  
     */
 209  
    public String getName() {
 210  239
       return "";
 211  
    }
 212  
    
 213  
    /**
 214  
     * This is used to acquire the name of the element or attribute
 215  
     * as taken from the annotation. If the element or attribute
 216  
     * explicitly specifies a name then that name is used for the
 217  
     * XML element or attribute used. If however no overriding name
 218  
     * is provided then the method or field is used for the name. 
 219  
     * 
 220  
     * @return returns the name of the annotation for the contact
 221  
     */
 222  
    public String getOverride(){
 223  109
       return contact.toString();
 224  
    }
 225  
    
 226  
    /**
 227  
     * This acts as a convenience method used to determine the type of
 228  
     * contact this represents. This is used when an object is written
 229  
     * to XML. It determines whether a <code>class</code> attribute
 230  
     * is required within the serialized XML element, that is, if the
 231  
     * class returned by this is different from the actual value of the
 232  
     * object to be serialized then that type needs to be remembered.
 233  
     *  
 234  
     * @return this returns the type of the contact class
 235  
     */  
 236  
    public Class getType() {
 237  130
       return type;
 238  
    }
 239  
    
 240  
    /**
 241  
     * This is used to determine whether the XML element is required. 
 242  
     * This ensures that if an XML element is missing from a document
 243  
     * that deserialization can continue. Also, in the process of
 244  
     * serialization, if a value is null it does not need to be 
 245  
     * written to the resulting XML document.
 246  
     * 
 247  
     * @return true if the label represents a some required data
 248  
     */   
 249  
    public boolean isRequired() {
 250  109
       return required;
 251  
    }
 252  
    
 253  
    /**
 254  
     * This is used to determine if the <code>Text</code> method or
 255  
     * field is to have its value written as a CDATA block. This will
 256  
     * set the output node to CDATA mode if this returns true, if it
 257  
     * is false data will be written according to an inherited mode.
 258  
     * By default inherited mode results in escaped XML text.
 259  
     * 
 260  
     * @return this returns true if the text is to be a CDATA block
 261  
     */
 262  
    public boolean isData() {
 263  109
       return data;
 264  
    }
 265  
    
 266  
    /**
 267  
     * This is used to determine if the label represents text. If
 268  
     * a label represents text it typically does not have a name,
 269  
     * instead the empty string represents the name. Also text
 270  
     * labels can not exist with other text labels, or elements.
 271  
     * 
 272  
     * @return this returns true if this label represents text
 273  
     */
 274  
    public boolean isText() {
 275  109
       return true;
 276  
    }
 277  
    
 278  
    /**
 279  
     * This method is used by the deserialization process to check
 280  
     * to see if an annotation is inline or not. If an annotation
 281  
     * represents an inline XML entity then the deserialization
 282  
     * and serialization process ignores overrides and special 
 283  
     * attributes. By default all text entities are inline.
 284  
     * 
 285  
     * @return this always returns true for text labels
 286  
     */
 287  
    public boolean isInline() {
 288  109
       return true;
 289  
    }
 290  
    
 291  
    /**
 292  
     * This is used to describe the annotation and method or field
 293  
     * that this label represents. This is used to provide error
 294  
     * messages that can be used to debug issues that occur when
 295  
     * processing a method. This will provide enough information
 296  
     * such that the problem can be isolated correctly. 
 297  
     * 
 298  
     * @return this returns a string representation of the label
 299  
     */
 300  
    public String toString() {
 301  7
       return detail.toString();
 302  
    }  
 303  
 }