Coverage Report - org.simpleframework.xml.core.Primitive
 
Classes in this File Line Coverage Branch Coverage Complexity
Primitive
91%
41/45
77%
17/22
2.545
 
 1  
 /*
 2  
  * Primitive.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 org.simpleframework.xml.strategy.Type;
 22  
 import org.simpleframework.xml.stream.InputNode;
 23  
 import org.simpleframework.xml.stream.OutputNode;
 24  
 
 25  
 /**
 26  
  * The <code>Primitive</code> object is used to provide serialization
 27  
  * for primitive objects. This can serialize and deserialize any
 28  
  * primitive object and enumerations. Primitive values are converted
 29  
  * to text using the <code>String.valueOf</code> method. Enumerated
 30  
  * types are converted using the <code>Enum.valueOf</code> method.
 31  
  * <p>
 32  
  * Text within attributes and elements can contain template variables
 33  
  * similar to those found in Apache <cite>Ant</cite>. This allows
 34  
  * values such as system properties, environment variables, and user
 35  
  * specified mappings to be inserted into the text in place of the
 36  
  * template reference variables.
 37  
  * <pre>
 38  
  * 
 39  
  *    &lt;example attribute="${value}&gt;
 40  
  *       &lt;text&gt;Text with a ${variable}&lt;/text&gt;
 41  
  *    &lt;/example&gt;
 42  
  * 
 43  
  * </pre>
 44  
  * In the above XML element the template variable references will be
 45  
  * checked against the <code>Filter</code> object used by the context
 46  
  * serialization object. If they corrospond to a filtered value then
 47  
  * they are replaced, if not the text remains unchanged.
 48  
  *
 49  
  * @author Niall Gallagher
 50  
  *
 51  
  * @see org.simpleframework.xml.filter.Filter
 52  
  */ 
 53  
 class Primitive implements Converter {
 54  
 
 55  
    /**
 56  
     * This is used to convert the string values to primitives.
 57  
     */         
 58  
    private final PrimitiveFactory factory;
 59  
         
 60  
    /**
 61  
     * The context object is used to perform text value filtering.
 62  
     */ 
 63  
    private final Context context;
 64  
    
 65  
    /**
 66  
     * This the value used to represent a null primitive value.
 67  
     */
 68  
    private final String empty;
 69  
    
 70  
    /**
 71  
     * This is the type that this primitive expects to represent.
 72  
     */
 73  
    private final Class expect;
 74  
    
 75  
    /**
 76  
     * This is the actual method or field that has been annotated.
 77  
     */
 78  
    private final Type type;
 79  
    
 80  
    /**
 81  
     * Constructor for the <code>Primitive</code> object. This is used
 82  
     * to convert an XML node to a primitive object and vice versa. To
 83  
     * perform deserialization the primitive object requires the context
 84  
     * object used for the instance of serialization to performed.
 85  
     *
 86  
     * @param context the context object used for the serialization
 87  
     * @param type this is the type of primitive this represents
 88  
     */ 
 89  
    public Primitive(Context context, Type type) {
 90  2263382
       this(context, type, null);          
 91  2263382
    }
 92  
    
 93  
    /**
 94  
     * Constructor for the <code>Primitive</code> object. This is used
 95  
     * to convert an XML node to a primitive object and vice versa. To
 96  
     * perform deserialization the primitive object requires the context
 97  
     * object used for the instance of serialization to performed.
 98  
     *
 99  
     * @param context the context object used for the serialization
 100  
     * @param type this is the type of primitive this represents
 101  
     * @param empty this is the value used to represent a null value
 102  
     */ 
 103  2971319
    public Primitive(Context context, Type type, String empty) {
 104  2971319
       this.factory = new PrimitiveFactory(context, type);  
 105  2971319
       this.expect = type.getType();
 106  2971319
       this.context = context; 
 107  2971319
       this.empty = empty;     
 108  2971319
       this.type = type;     
 109  2971319
    }
 110  
 
 111  
    /**
 112  
     * This <code>read</code> method will extract the text value from
 113  
     * the node and replace any template variables before converting
 114  
     * it to a primitive value. This uses the <code>Context</code>
 115  
     * object used for this instance of serialization to replace all
 116  
     * template variables with values from the context filter.
 117  
     *
 118  
     * @param node this is the node to be converted to a primitive
 119  
     *
 120  
     * @return this returns the primitive that has been deserialized
 121  
     */ 
 122  
    public Object read(InputNode node) throws Exception{
 123  1715210
       if(node.isElement()) {
 124  1008142
          return readElement(node);
 125  
       }
 126  707068
       return read(node, expect);
 127  
    }  
 128  
    
 129  
    /**
 130  
     * This <code>read</code> method will extract the text value from
 131  
     * the node and replace any template variables before converting
 132  
     * it to a primitive value. This uses the <code>Context</code>
 133  
     * object used for this instance of serialization to replace all
 134  
     * template variables with values from the context filter.
 135  
     *
 136  
     * @param node this is the node to be converted to a primitive
 137  
     * @param value this is the original primitive value used
 138  
     *
 139  
     * @return this returns the primitive that has been deserialized
 140  
     * 
 141  
     * @throws Exception if value is not null an exception is thrown
 142  
     */ 
 143  
    public Object read(InputNode node, Object value) throws Exception{
 144  0
       if(value != null) {
 145  0
          throw new PersistenceException("Can not read existing %s for %s", expect, type);
 146  
       }
 147  0
       return read(node);
 148  
    }
 149  
    
 150  
    /**
 151  
     * This <code>read</code> method will extract the text value from
 152  
     * the node and replace any template variables before converting
 153  
     * it to a primitive value. This uses the <code>Context</code>
 154  
     * object used for this instance of serialization to replace all
 155  
     * template variables with values from the context filter.
 156  
     *
 157  
     * @param node this is the node to be converted to a primitive
 158  
     * @param type this is the type to read the primitive with
 159  
     *
 160  
     * @return this returns the primitive that has been deserialized
 161  
     */ 
 162  
    public Object read(InputNode node, Class type) throws Exception{
 163  1714192
       String value = node.getValue();
 164  
 
 165  1714192
       if(value == null) {
 166  60
          return null;
 167  
       }
 168  1714132
       if(empty != null && value.equals(empty)) {
 169  7
          return empty;         
 170  
       }
 171  1714125
       return readTemplate(value, type);
 172  
    }
 173  
    
 174  
    /**
 175  
     * This <code>read</code> method will extract the text value from
 176  
     * the node and replace any template variables before converting
 177  
     * it to a primitive value. This uses the <code>Context</code>
 178  
     * object used for this instance of serialization to replace all
 179  
     * template variables with values from the context filter.
 180  
     *
 181  
     * @param node this is the node to be converted to a primitive
 182  
     *
 183  
     * @return this returns the primitive that has been deserialized
 184  
     */ 
 185  
    private Object readElement(InputNode node) throws Exception {
 186  1008142
       Instance value = factory.getInstance(node);
 187  
       
 188  1008142
       if(!value.isReference()) {
 189  1007068
          return readElement(node, value);
 190  
       }
 191  1074
       return value.getInstance();
 192  
    }
 193  
    
 194  
    /**
 195  
     * This <code>read</code> method will extract the text value from
 196  
     * the node and replace any template variables before converting
 197  
     * it to a primitive value. This uses the <code>Context</code>
 198  
     * object used for this instance of serialization to replace all
 199  
     * template variables with values from the context filter.
 200  
     *
 201  
     * @param node this is the node to be converted to a primitive
 202  
     * @param value this is the instance to set the result to
 203  
     *
 204  
     * @return this returns the primitive that has been deserialized
 205  
     */ 
 206  
    private Object readElement(InputNode node, Instance value) throws Exception {
 207  1007068
       Object result = read(node, expect);
 208  
       
 209  1007068
       if(value != null) {
 210  1007068
          value.setInstance(result);
 211  
       }
 212  1007068
       return result;
 213  
    }
 214  
    
 215  
    /**
 216  
     * This <code>read</code> method will extract the text value from
 217  
     * the node and replace any template variables before converting
 218  
     * it to a primitive value. This uses the <code>Context</code>
 219  
     * object used for this instance of serialization to replace all
 220  
     * template variables with values from the context filter.
 221  
     *
 222  
     * @param value this is the value to be processed as a template
 223  
     * @param type this is the type that that the primitive is
 224  
     *
 225  
     * @return this returns the primitive that has been deserialized
 226  
     */ 
 227  
    private Object readTemplate(String value, Class type) throws Exception {
 228  1714125
       String text = context.getProperty(value);
 229  
       
 230  1714125
       if(text != null) {
 231  1714125
          return factory.getInstance(text, type);
 232  
       }
 233  0
       return null;
 234  
    }  
 235  
    
 236  
    /**
 237  
     * This <code>validate</code> method will validate the primitive 
 238  
     * by checking the node text. If the value is a reference then 
 239  
     * this will not extract any value from the node. Transformation
 240  
     * of the extracted value is not done as it can not account for
 241  
     * template variables. Thus any text extracted is valid.
 242  
     *
 243  
     * @param node this is the node to be validated as a primitive
 244  
     *
 245  
     * @return this returns the primitive that has been validated
 246  
     */ 
 247  
    public boolean validate(InputNode node) throws Exception {
 248  5439
       if(node.isElement()) {
 249  4551
          validateElement(node);
 250  
       } else {
 251  888
          node.getValue();
 252  
       }
 253  5439
       return true;
 254  
    }
 255  
    
 256  
    /**
 257  
     * This <code>validateElement</code> method validates a primitive 
 258  
     * by checking the node text. If the value is a reference then 
 259  
     * this will not extract any value from the node. Transformation
 260  
     * of the extracted value is not done as it can not account for
 261  
     * template variables. Thus any text extracted is valid.
 262  
     *
 263  
     * @param node this is the node to be validated as a primitive
 264  
     *
 265  
     * @return this returns the primitive that has been validated
 266  
     */ 
 267  
    private boolean validateElement(InputNode node) throws Exception {
 268  4551
       Instance type = factory.getInstance(node);
 269  
       
 270  4551
       if(!type.isReference()) {         
 271  4539
          type.setInstance(null);
 272  
       }
 273  4551
       return true;
 274  
    }
 275  
    
 276  
    /**
 277  
     * This <code>write</code> method will serialize the contents of
 278  
     * the provided object to the given XML element. This will use
 279  
     * the <code>String.valueOf</code> method to convert the object to
 280  
     * a string if the object represents a primitive, if however the
 281  
     * object represents an enumerated type then the text value is
 282  
     * created using <code>Enum.name</code>.
 283  
     *
 284  
     * @param source this is the object to be serialized
 285  
     * @param node this is the XML element to have its text set
 286  
     */  
 287  
    public void write(OutputNode node, Object source) throws Exception {
 288  316661
       String text = factory.getText(source);
 289  
     
 290  316661
       if(text != null) {
 291  316661
          node.setValue(text);
 292  
       }  
 293  316661
    }
 294  
 }