Coverage Report - org.simpleframework.xml.core.CompositeValue
 
Classes in this File Line Coverage Branch Coverage Complexity
CompositeValue
89%
34/38
85%
12/14
3
 
 1  
 /*
 2  
  * CompositeValue.java July 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 org.simpleframework.xml.strategy.Type;
 22  
 import org.simpleframework.xml.stream.InputNode;
 23  
 import org.simpleframework.xml.stream.OutputNode;
 24  
 import org.simpleframework.xml.stream.Style;
 25  
 
 26  
 /**
 27  
  * The <code>CompositeValue</code> object is used to convert an object
 28  
  * to an from an XML element. This accepts only composite objects and
 29  
  * will maintain all references within the object using the cycle
 30  
  * strategy if required. This also ensures that should the value to
 31  
  * be written to the XML element be null that nothing is written. 
 32  
  * 
 33  
  * @author Niall Gallagher
 34  
  * 
 35  
  * @see org.simpleframework.xml.ElementMap
 36  
  */
 37  
 class CompositeValue implements Converter {
 38  
    
 39  
    /**
 40  
     * This is the context used to support the serialization process.
 41  
     */
 42  
    private final Context context;
 43  
    
 44  
    /**
 45  
     * This is the traverser used to read and write the value with.
 46  
     */
 47  
    private final Traverser root;
 48  
    
 49  
    /**
 50  
     * This is the style used to style the names used for the XML.
 51  
     */
 52  
    private final Style style;
 53  
    
 54  
    /**
 55  
     * This is the entry object used to provide configuration details.
 56  
     */   
 57  
    private final Entry entry;
 58  
   
 59  
    /**
 60  
     * This represents the type of object the value is written as.
 61  
     */
 62  
    private final Type type;
 63  
    
 64  
    /**
 65  
     * Constructor for the <code>CompositeValue</code> object. This 
 66  
     * will create an object capable of reading an writing composite 
 67  
     * values from an XML element. This also allows a parent element 
 68  
     * to be created to wrap the key object if desired.
 69  
     * 
 70  
     * @param context this is the root context for the serialization
 71  
     * @param entry this is the entry object used for configuration
 72  
     * @param type this is the type of object the value represents
 73  
     */
 74  431
    public CompositeValue(Context context, Entry entry, Type type) throws Exception {
 75  431
       this.root = new Traverser(context);
 76  431
       this.style = context.getStyle();
 77  431
       this.context = context;
 78  431
       this.entry = entry;
 79  431
       this.type = type;
 80  431
    }
 81  
    
 82  
    /**
 83  
     * This method is used to read the value object from the node. The 
 84  
     * value read from the node is resolved using the template filter.
 85  
     * If the value data can not be found according to the annotation 
 86  
     * attributes then null is assumed and returned.
 87  
     * 
 88  
     * @param node this is the node to read the value object from
 89  
     * 
 90  
     * @return this returns the value deserialized from the node
 91  
     */ 
 92  
    public Object read(InputNode node) throws Exception { 
 93  291
       InputNode next = node.getNext();
 94  291
       Class expect = type.getType();
 95  
       
 96  291
       if(next == null) {
 97  2
          return null;
 98  
       }
 99  289
       if(next.isEmpty()) {
 100  11
          return null;
 101  
       }
 102  278
       return root.read(next, expect);
 103  
    }
 104  
    
 105  
    /**
 106  
     * This method is used to read the value object from the node. The 
 107  
     * value read from the node is resolved using the template filter.
 108  
     * If the value data can not be found according to the annotation 
 109  
     * attributes then null is assumed and returned.
 110  
     * 
 111  
     * @param node this is the node to read the value object from
 112  
     * @param value this is the value to deserialize in to
 113  
     * 
 114  
     * @return this returns the value deserialized from the node
 115  
     *
 116  
     * @throws Exception if value is not null an exception is thrown
 117  
     */ 
 118  
    public Object read(InputNode node, Object value) throws Exception { 
 119  0
       Class expect = type.getType();
 120  
       
 121  0
       if(value != null) {
 122  0
          throw new PersistenceException("Can not read value of %s for %s", expect, entry);
 123  
       }
 124  0
       return read(node);
 125  
    }
 126  
    
 127  
    /**
 128  
     * This method is used to read the value object from the node. The 
 129  
     * value read from the node is resolved using the template filter.
 130  
     * If the value data can not be found according to the annotation 
 131  
     * attributes then null is assumed and the node is valid.
 132  
     * 
 133  
     * @param node this is the node to read the value object from
 134  
     * 
 135  
     * @return this returns true if this represents a valid value
 136  
     */ 
 137  
    public boolean validate(InputNode node) throws Exception { 
 138  109
       Class expect = type.getType();
 139  109
       String name = entry.getValue();
 140  
       
 141  109
       if(name == null) {
 142  89
          name = context.getName(expect);
 143  
       }
 144  109
       return validate(node, name);
 145  
    }  
 146  
    
 147  
    /**
 148  
     * This method is used to read the value object from the node. The 
 149  
     * value read from the node is resolved using the template filter.
 150  
     * If the value data can not be found according to the annotation 
 151  
     * attributes then null is assumed and the node is valid.
 152  
     * 
 153  
     * @param node this is the node to read the value object from
 154  
     * @param key this is the name of the value element
 155  
     * 
 156  
     * @return this returns true if this represents a valid value
 157  
     */    
 158  
    private boolean validate(InputNode node, String key) throws Exception {  
 159  109
       String name = style.getElement(key);
 160  109
       InputNode next = node.getNext(name);
 161  109
       Class expect = type.getType();
 162  
       
 163  109
       if(next == null) {
 164  1
          return true;
 165  
       }
 166  108
       if(next.isEmpty()) {
 167  6
          return true;
 168  
       }
 169  102
       return root.validate(next, expect);
 170  
    }
 171  
    
 172  
    /**
 173  
     * This method is used to write the value to the specified node.
 174  
     * The value written to the node must be a composite object and if
 175  
     * the object provided to this is null then nothing is written.
 176  
     * 
 177  
     * @param node this is the node that the value is written to
 178  
     * @param item this is the item that is to be written
 179  
     */
 180  
    public void write(OutputNode node, Object item) throws Exception {
 181  578
       Class expect = type.getType();
 182  578
       String key = entry.getValue();
 183  
       
 184  578
       if(key == null) {
 185  468
          key = context.getName(expect);
 186  
       }
 187  578
       String name = style.getElement(key);
 188  
       
 189  578
       root.write(node, item, expect, name);      
 190  578
    }
 191  
 }