Coverage Report - org.simpleframework.xml.strategy.WriteGraph
 
Classes in this File Line Coverage Branch Coverage Complexity
WriteGraph
100%
27/27
100%
8/8
2.25
 
 1  
 /*
 2  
  * WriteGraph.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.strategy;
 20  
 
 21  
 import java.lang.reflect.Array;
 22  
 import java.util.IdentityHashMap;
 23  
 
 24  
 import org.simpleframework.xml.stream.NodeMap;
 25  
 
 26  
 /**
 27  
  * The <code>WriteGraph</code> object is used to build the graph that
 28  
  * is used to represent the serialized object and its references. The
 29  
  * graph is stored in an <code>IdentityHashMap</code> which will 
 30  
  * store the objects in such a way that this graph object can tell if
 31  
  * it has already been written to the XML document. If an object has
 32  
  * already been written to the XML document an reference attribute
 33  
  * is added to the element representing the object and serialization
 34  
  * of that object is complete, that is, no more elements are written.
 35  
  * <p>
 36  
  * The attribute values written by this are unique strings, which 
 37  
  * allows the deserialization process to identify object references
 38  
  * easily. By default these references are incrementing integers 
 39  
  * however for deserialization they can be any unique string value.
 40  
  * 
 41  
  * @author Niall Gallagher
 42  
  */
 43  
 class WriteGraph extends IdentityHashMap<Object, String> {
 44  
    
 45  
    /**
 46  
     * This is used to specify the length of array instances.
 47  
     */
 48  
    private final String length;
 49  
    
 50  
    /**
 51  
     * This is the label used to mark the type of an object.
 52  
     */
 53  
    private final String label;
 54  
    
 55  
    /**
 56  
     * This is the attribute used to mark the identity of an object.
 57  
     */
 58  
    private final String mark;
 59  
    
 60  
    /**
 61  
     * This is the attribute used to refer to an existing instance.
 62  
     */
 63  
    private final String refer;
 64  
    
 65  
    /**
 66  
     * Constructor for the <code>WriteGraph</code> object. This is
 67  
     * used to build the graph used for writing objects to the XML 
 68  
     * document. The specified strategy is used to acquire the names
 69  
     * of the special attributes used during the serialization.
 70  
     * 
 71  
     * @param contract this is the name scheme used by the strategy 
 72  
     */
 73  1957
    public WriteGraph(Contract contract) {
 74  1957
       this.refer = contract.getReference();
 75  1957
       this.mark = contract.getIdentity();
 76  1957
       this.length = contract.getLength();
 77  1957
       this.label = contract.getLabel();
 78  1957
    }
 79  
    
 80  
    /**
 81  
     * This is used to write the XML element attributes representing
 82  
     * the serialized object instance. If the object has already been
 83  
     * serialized to the XML document then a reference attribute is
 84  
     * inserted and this returns true, if not, then this will write
 85  
     * a unique identity marker attribute and return false.
 86  
     * 
 87  
     * @param type this is the type of the object to be serialized
 88  
     * @param value this is the instance that is to be serialized    
 89  
     * @param node this is the node that contains the attributes
 90  
     * 
 91  
     * @return returns true if the element has been fully written
 92  
     */
 93  
    public boolean write(Type type, Object value, NodeMap node){
 94  39766
       Class actual = value.getClass();
 95  39766
       Class expect = type.getType();
 96  39766
       Class real = actual;
 97  
       
 98  39766
       if(actual.isArray()) {
 99  221
          real = writeArray(actual, value, node);
 100  
       }
 101  39766
       if(actual != expect) {
 102  1672
          node.put(label, real.getName());
 103  
       }       
 104  39766
       return writeReference(value, node);
 105  
    }
 106  
    
 107  
    /**
 108  
     * This is used to write the XML element attributes representing
 109  
     * the serialized object instance. If the object has already been
 110  
     * serialized to the XML document then a reference attribute is
 111  
     * inserted and this returns true, if not, then this will write
 112  
     * a unique identity marker attribute and return false.
 113  
     *
 114  
     * @param value this is the instance that is to be serialized    
 115  
     * @param node this is the node that contains the attributes
 116  
     * 
 117  
     * @return returns true if the element has been fully written
 118  
     */   
 119  
    private boolean writeReference(Object value, NodeMap node) {
 120  39766
       String name = get(value);
 121  39766
       int size = size();
 122  
       
 123  39766
       if(name != null) {
 124  4340
          node.put(refer, name);
 125  4340
          return true;
 126  
       } 
 127  35426
       String unique = String.valueOf(size);
 128  
       
 129  35426
       node.put(mark, unique);
 130  35426
       put(value, unique);
 131  
       
 132  35426
       return false;   
 133  
    }
 134  
    
 135  
    /**
 136  
     * This is used to add a length attribute to the element due to
 137  
     * the fact that the serialized value is an array. The length
 138  
     * of the array is acquired and inserted in to the attributes.
 139  
     * 
 140  
     * @param field this is the field type for the array to set
 141  
     * @param value this is the actual value for the array to set
 142  
     * @param node this is the map of attributes for the element
 143  
     * 
 144  
     * @return returns the array component type that is set
 145  
     */
 146  
    private Class writeArray(Class field, Object value, NodeMap node){
 147  221
       int size = Array.getLength(value);
 148  
       
 149  221
       if(!containsKey(value)) {       
 150  185
          node.put(length, String.valueOf(size));
 151  
       }
 152  221
       return field.getComponentType();
 153  
    }
 154  
 }