Coverage Report - org.simpleframework.xml.strategy.CycleStrategy
 
Classes in this File Line Coverage Branch Coverage Complexity
CycleStrategy
89%
17/19
50%
2/4
1.667
 
 1  
 /*
 2  
  * CycleStrategy.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 static org.simpleframework.xml.strategy.Name.LABEL;
 22  
 import static org.simpleframework.xml.strategy.Name.LENGTH;
 23  
 import static org.simpleframework.xml.strategy.Name.MARK;
 24  
 import static org.simpleframework.xml.strategy.Name.REFER;
 25  
 
 26  
 import java.util.Map;
 27  
 
 28  
 import org.simpleframework.xml.stream.NodeMap;
 29  
 
 30  
 /**
 31  
  * The <code>CycleStrategy</code> represents a strategy that is used
 32  
  * to augment the deserialization and serialization process such that
 33  
  * cycles in an object graph can be supported. This adds additional 
 34  
  * attributes to the serialized XML elements so that during the 
 35  
  * deserialization process an objects cycles can be created. Without
 36  
  * the use of a strategy such as this, cycles could cause an infinite
 37  
  * loop during the serialization process while traversing the graph.
 38  
  * <pre>
 39  
  * 
 40  
  *    &lt;root id="1"&gt;
 41  
  *       &lt;object id="2"&gt;
 42  
  *          &lt;object id="3" name="name"&gt;Example&lt;/item&gt;
 43  
  *          &lt;object reference="2"/&gt;
 44  
  *       &lt;/object&gt;
 45  
  *    &lt;/root&gt;
 46  
  * 
 47  
  * </pre>
 48  
  * In the above serialized XML there is a circular reference, where
 49  
  * the XML element with id "2" contains a reference to itself. In
 50  
  * most data binding frameworks this will cause an infinite loop, 
 51  
  * or in some cases will just fail to represent the references well.
 52  
  * With this strategy you can ensure that cycles in complex object
 53  
  * graphs will be maintained and can be serialized safely.
 54  
  * 
 55  
  * @author Niall Gallagher
 56  
  * 
 57  
  * @see org.simpleframework.xml.core.Persister
 58  
  * @see org.simpleframework.xml.strategy.Strategy
 59  
  */
 60  
 public class CycleStrategy implements Strategy {
 61  
    
 62  
    /**
 63  
     * This is used to maintain session state for writing the graph.
 64  
     */
 65  
    private final WriteState write;
 66  
    
 67  
    /**
 68  
     * This is used to maintain session state for reading the graph.
 69  
     */
 70  
    private final ReadState read;
 71  
    
 72  
    /**
 73  
     * This is used to provide the names of the attributes to use.
 74  
     */
 75  
    private final Contract contract;
 76  
    
 77  
    /**
 78  
     * Constructor for the <code>CycleStrategy</code> object. This is
 79  
     * used to create a strategy with default values. By default the
 80  
     * values used are "id" and "reference". These values will be
 81  
     * added to XML elements during the serialization process. And 
 82  
     * will be used to deserialize the object cycles fully.
 83  
     */
 84  
    public CycleStrategy() {
 85  22
       this(MARK, REFER);
 86  22
    }
 87  
    
 88  
    /**
 89  
     * Constructor for the <code>CycleStrategy</code> object. This is
 90  
     * used to create a strategy with the specified attributes, which
 91  
     * will be added to serialized XML elements. These attributes 
 92  
     * are used to serialize the objects in such a way the cycles in
 93  
     * the object graph can be deserialized and used fully. 
 94  
     * 
 95  
     * @param mark this is used to mark the identity of an object
 96  
     * @param refer this is used to refer to an existing object
 97  
     */
 98  
    public CycleStrategy(String mark, String refer) {
 99  260
       this(mark, refer, LABEL);      
 100  260
    }
 101  
    
 102  
    /**
 103  
     * Constructor for the <code>CycleStrategy</code> object. This is
 104  
     * used to create a strategy with the specified attributes, which
 105  
     * will be added to serialized XML elements. These attributes 
 106  
     * are used to serialize the objects in such a way the cycles in
 107  
     * the object graph can be deserialized and used fully. 
 108  
     * 
 109  
     * @param mark this is used to mark the identity of an object
 110  
     * @param refer this is used to refer to an existing object
 111  
     * @param label this is used to specify the class for the field
 112  
     */   
 113  
    public CycleStrategy(String mark, String refer, String label){
 114  260
       this(mark, refer, label, LENGTH);
 115  260
    }
 116  
    
 117  
    /**
 118  
     * Constructor for the <code>CycleStrategy</code> object. This is
 119  
     * used to create a strategy with the specified attributes, which
 120  
     * will be added to serialized XML elements. These attributes 
 121  
     * are used to serialize the objects in such a way the cycles in
 122  
     * the object graph can be deserialized and used fully. 
 123  
     * 
 124  
     * @param mark this is used to mark the identity of an object
 125  
     * @param refer this is used to refer to an existing object
 126  
     * @param label this is used to specify the class for the field
 127  
     * @param length this is the length attribute used for arrays
 128  
     */   
 129  260
    public CycleStrategy(String mark, String refer, String label, String length){
 130  260
       this.contract = new Contract(mark, refer, label, length);
 131  260
       this.write = new WriteState(contract);
 132  260
       this.read = new ReadState(contract);
 133  260
    } 
 134  
    
 135  
    /**
 136  
     * This method is used to read an object from the specified node.
 137  
     * In order to get the root type the field and node map are 
 138  
     * specified. The field represents the annotated method or field
 139  
     * within the deserialized object. The node map is used to get
 140  
     * the attributes used to describe the objects identity, or in
 141  
     * the case of an existing object it contains an object reference.
 142  
     * 
 143  
     * @param type the method or field in the deserialized object
 144  
     * @param node this is the XML element attributes to read
 145  
     * @param map this is the session map used for deserialization
 146  
     * 
 147  
     * @return this returns an instance to insert into the object 
 148  
     */
 149  
    public Value read(Type type, NodeMap node, Map map) throws Exception {
 150  26854
       ReadGraph graph = read.find(map);
 151  
       
 152  26854
       if(graph != null) {
 153  26854
          return graph.read(type, node);
 154  
       }
 155  0
       return null;
 156  
    }
 157  
    
 158  
    /**
 159  
     * This is used to write the reference in to the XML element that 
 160  
     * is to be written. This will either insert an object identity if
 161  
     * the object has not previously been written, or, if the object
 162  
     * has already been written in a previous element, this will write
 163  
     * the reference to that object. This allows all cycles within the
 164  
     * graph to be serialized so that they can be fully deserialized. 
 165  
     * 
 166  
     * @param type the type of the field or method in the object
 167  
     * @param value this is the actual object that is to be written
 168  
     * @param node this is the XML element attribute map to use
 169  
     * @param map this is the session map used for the serialization
 170  
     * 
 171  
     * @return returns true if the object has been fully serialized
 172  
     */
 173  
    public boolean write(Type type, Object value, NodeMap node, Map map){
 174  39766
       WriteGraph graph = write.find(map);
 175  
       
 176  39766
       if(graph != null) {
 177  39766
          return graph.write(type, value, node);
 178  
       }
 179  0
       return false;
 180  
    }
 181  
 }