Coverage Report - org.simpleframework.xml.core.CompositeKey
 
Classes in this File Line Coverage Branch Coverage Complexity
CompositeKey
87%
47/54
79%
19/24
3.857
 
 1  
 /*
 2  
  * CompositeKey.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.Position;
 25  
 import org.simpleframework.xml.stream.Style;
 26  
 
 27  
 /**
 28  
  * The <code>CompositeKey</code> object is used to convert an object
 29  
  * to an from an XML element. This accepts only composite objects and
 30  
  * will throw an exception if the <code>ElementMap</code> annotation
 31  
  * is configured to have an attribute key. If a key name is given for
 32  
  * the annotation then this will act as a parent element to the 
 33  
  * resulting XML element for the composite object. 
 34  
  * 
 35  
  * @author Niall Gallagher
 36  
  * 
 37  
  * @see org.simpleframework.xml.ElementMap
 38  
  */
 39  
 class CompositeKey implements Converter {
 40  
    
 41  
    /**
 42  
     * This is the context used to support the serialization process.
 43  
     */
 44  
    private final Context context;
 45  
    
 46  
    /**
 47  
     * This is the traverser used to read and write the composite key.
 48  
     */
 49  
    private final Traverser root;
 50  
    
 51  
    /**
 52  
     * This is the style used to style the names used for the XML.
 53  
     */
 54  
    private final Style style;
 55  
    
 56  
    /**
 57  
     * This is the entry object used to provide configuration details.
 58  
     */
 59  
    private final Entry entry;
 60  
    
 61  
    /**
 62  
     * This represents the type of object the key is written as.
 63  
     */
 64  
    private final Type type;
 65  
       
 66  
    /**
 67  
     * Constructor for the <code>CompositeKey</code> object. This will
 68  
     * create an object capable of reading an writing composite keys
 69  
     * from an XML element. This also allows a parent element to be
 70  
     * created to wrap the key object if desired.
 71  
     * 
 72  
     * @param context this is the root context for the serialization
 73  
     * @param entry this is the entry object used for configuration
 74  
     * @param type this is the type of object the key represents
 75  
     */
 76  187
    public CompositeKey(Context context, Entry entry, Type type) throws Exception {
 77  187
       this.root = new Traverser(context);
 78  187
       this.style = context.getStyle();
 79  187
       this.context = context;
 80  187
       this.entry = entry;
 81  187
       this.type = type;
 82  187
    }
 83  
    
 84  
    /**
 85  
     * This method is used to read the key value from the node. The 
 86  
     * value read from the node is resolved using the template filter.
 87  
     * If the key value can not be found according to the annotation
 88  
     * attributes then null is assumed and returned.
 89  
     * 
 90  
     * @param node this is the node to read the key value from
 91  
     * 
 92  
     * @return this returns the value deserialized from the node
 93  
     */ 
 94  
    public Object read(InputNode node) throws Exception { 
 95  111
       Position line = node.getPosition();
 96  111
       Class expect = type.getType();
 97  111
       String name = entry.getKey();
 98  
       
 99  111
       if(name == null) {
 100  99
          name = context.getName(expect);
 101  
       }
 102  111
       if(entry.isAttribute()) {
 103  0
          throw new AttributeException("Can not have %s as an attribute for %s at %s", expect, entry, line);
 104  
       }
 105  111
       return read(node, name);
 106  
    }
 107  
    
 108  
    /**
 109  
     * This method is used to read the key value from the node. The 
 110  
     * value read from the node is resolved using the template filter.
 111  
     * If the key value can not be found according to the annotation
 112  
     * attributes then null is assumed and returned.
 113  
     * 
 114  
     * @param node this is the node to read the key value from
 115  
     * @param value this is the value to deserialize in to
 116  
     * 
 117  
     * @return this returns the value deserialized from the node
 118  
     * 
 119  
     * @throws Exception if value is not null an exception is thrown
 120  
     */ 
 121  
    public Object read(InputNode node, Object value) throws Exception {
 122  0
       Position line = node.getPosition();
 123  0
       Class expect = type.getType();
 124  
       
 125  0
       if(value != null) {
 126  0
          throw new PersistenceException("Can not read key of %s for %s at %s", expect, entry, line);
 127  
       }
 128  0
       return read(node);
 129  
    }
 130  
    
 131  
    /**
 132  
     * This method is used to read the key value from the node. The 
 133  
     * value read from the node is resolved using the template filter.
 134  
     * If the key value can not be found according to the annotation
 135  
     * attributes then null is assumed and returned.
 136  
     * 
 137  
     * @param node this is the node to read the key value from
 138  
     * @param key this is the name of the key wrapper XML element
 139  
     * 
 140  
     * @return this returns the value deserialized from the node
 141  
     */ 
 142  
    private Object read(InputNode node, String key) throws Exception {
 143  111
       String name = style.getElement(key);
 144  111
       Class expect = type.getType();
 145  
       
 146  111
       if(name != null) {
 147  111
          node = node.getNext(name);
 148  
       }    
 149  111
       if(node == null) {
 150  2
          return null;
 151  
       }   
 152  109
       if(node.isEmpty()) {
 153  11
          return null;
 154  
       }
 155  98
       return root.read(node, expect);
 156  
    }
 157  
    
 158  
    /**
 159  
     * This method is used to read the key value from the node. The 
 160  
     * value read from the node is resolved using the template filter.
 161  
     * If the key value can not be found according to the annotation
 162  
     * attributes then null is assumed and the node is valid.
 163  
     * 
 164  
     * @param node this is the node to read the key value from
 165  
     * 
 166  
     * @return this returns the value deserialized from the node
 167  
     */ 
 168  
    public boolean validate(InputNode node) throws Exception { 
 169  48
       Position line = node.getPosition();
 170  48
       Class expect = type.getType();
 171  48
       String name = entry.getKey();
 172  
       
 173  48
       if(name == null) {
 174  44
          name = context.getName(expect);
 175  
       }
 176  48
       if(entry.isAttribute()) {
 177  0
          throw new ElementException("Can not have %s as an attribute for %s at %s", expect, entry, line);
 178  
       }
 179  48
       return validate(node, name);
 180  
    }
 181  
    
 182  
    /**
 183  
     * This method is used to read the key value from the node. The 
 184  
     * value read from the node is resolved using the template filter.
 185  
     * If the key value can not be found according to the annotation
 186  
     * attributes then null is assumed and the node is valid.
 187  
     * 
 188  
     * @param node this is the node to read the key value from
 189  
     * @param key this is the name of the key wrapper XML element
 190  
     * 
 191  
     * @return this returns the value deserialized from the node
 192  
     */ 
 193  
    private boolean validate(InputNode node, String key) throws Exception {
 194  48
       String name = style.getElement(key);
 195  48
       InputNode next = node.getNext(name);
 196  48
       Class expect = type.getType();
 197  
       
 198  48
       if(next == null) {
 199  1
          return true;
 200  
       }
 201  47
       if(next.isEmpty()) {
 202  14
          return true;
 203  
       }
 204  33
       return root.validate(next, expect);
 205  
    }
 206  
    
 207  
    /**
 208  
     * This method is used to write the value to the specified node.
 209  
     * The value written to the node must be a composite object and if
 210  
     * the element map annotation is configured to have a key attribute
 211  
     * then this method will throw an exception.
 212  
     * 
 213  
     * @param node this is the node that the value is written to
 214  
     * @param item this is the item that is to be written
 215  
     */
 216  
    public void write(OutputNode node, Object item) throws Exception {
 217  238
       Class expect = type.getType();
 218  238
       String key = entry.getKey();
 219  
       
 220  238
       if(entry.isAttribute()) {
 221  1
          throw new ElementException("Can not have %s as an attribute for %s", expect, entry);
 222  
       }
 223  237
       if(key == null) {
 224  217
          key = context.getName(expect);
 225  
       }      
 226  237
       String name = style.getElement(key);
 227  
       
 228  237
       root.write(node, item, expect, name);      
 229  237
    }
 230  
 }