Coverage Report - org.simpleframework.xml.core.KeyBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
KeyBuilder
94%
17/18
75%
6/8
2.111
KeyBuilder$Key
92%
12/13
75%
3/4
2.111
KeyBuilder$KeyType
100%
4/4
N/A
2.111
 
 1  
 /*
 2  
  * KeyBuilder.java April 2012
 3  
  *
 4  
  * Copyright (C) 2012, 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 java.util.Arrays;
 22  
 
 23  
 /**
 24  
  * The <code>KeyBuilder</code> is used build unique keys for labels
 25  
  * using the paths defined in those labels. Building keys in this
 26  
  * way ensures that labels can be uniquely identified. This helps in
 27  
  * constructor injection when we need to match a parameter with a
 28  
  * label to determine which constructor signature should be used.
 29  
  * 
 30  
  * @author Niall Gallagher
 31  
  */
 32  
 class KeyBuilder {
 33  
    
 34  
    /**
 35  
     * This is the label that the keys should be built with.
 36  
     */
 37  
    private final Label label;
 38  
    
 39  
    /**
 40  
     * Constructor for the <code>KeyBuilder</code> object. This is
 41  
     * used to create a builder using the provided label. A key will 
 42  
     * be unique based on the XPath options for the label. 
 43  
     * 
 44  
     * @param label this is the label to build he key for
 45  
     */
 46  6652
    public KeyBuilder(Label label) {
 47  6652
       this.label = label;
 48  6652
    }
 49  
 
 50  
    /**
 51  
     * This generates a key for the <code>Label</code> object that
 52  
     * this represents. Each key is generated based on the label type
 53  
     * and the XPath options for the label. This ensures that similar
 54  
     * labels create the same key values.
 55  
     * 
 56  
     * @return this returns a key to represent the label
 57  
     */
 58  
    public Object getKey() throws Exception {
 59  6046
       if(label.isAttribute()) {
 60  983
          return getKey(KeyType.ATTRIBUTE);
 61  
       }
 62  5063
       return getKey(KeyType.ELEMENT);
 63  
    }
 64  
    
 65  
    /**
 66  
     * This generates a key for the <code>Label</code> object that
 67  
     * this represents. Each key is generated based on the label type
 68  
     * and the XPath options for the label. This ensures that similar
 69  
     * labels create the same key values.
 70  
     * 
 71  
     * @param type this is the type that this key builder represents
 72  
     * 
 73  
     * @return this returns a key to represent the label
 74  
     */
 75  
    private Object getKey(KeyType type) throws Exception {
 76  6046
       String[] list = label.getPaths();
 77  6046
       String text = getKey(list);
 78  
       
 79  6046
       if(type == null) {
 80  0
          return text;
 81  
       }
 82  6046
       return new Key(type, text);
 83  
    }
 84  
    
 85  
    /**
 86  
     * This generates a key for the <code>Label</code> object that
 87  
     * this represents. Each key is generated based on the label type
 88  
     * and the XPath options for the label. This ensures that similar
 89  
     * labels create the same key values.
 90  
     * 
 91  
     * @param list this is the list of XPath expressions to be used
 92  
     * 
 93  
     * @return this returns a key to represent the label
 94  
     */
 95  
    private String getKey(String[] list) throws Exception { 
 96  6046
       StringBuilder builder = new StringBuilder();
 97  
       
 98  6046
       if(list.length > 0) {
 99  6046
          Arrays.sort(list);
 100  
          
 101  13200
          for(String path : list) {
 102  7154
             builder.append(path);
 103  7154
             builder.append('>');
 104  
          }
 105  
       }
 106  6046
       return builder.toString();
 107  
    }
 108  
    
 109  
    /**
 110  
     * The <code>KeyType</code> enumeration is used to differentiate
 111  
     * keys created for attributes from those created from elements.
 112  
     * This is important when determining if XML paths would clash.
 113  
     */
 114  4
    private static enum KeyType {
 115  1
       TEXT,
 116  1
       ATTRIBUTE,
 117  1
       ELEMENT;
 118  
    }
 119  
    
 120  
    /**
 121  
     * The <code>Key</code> object represents an object that can be
 122  
     * used in a hash container. The <code>hashCode</code> and the 
 123  
     * <code>equals</code> method will ensure that a label with the
 124  
     * same XPath options will hash to the same position.
 125  
     */
 126  
    private static class Key {
 127  
       
 128  
       /**
 129  
        * This is the type of key that this represents.
 130  
        */
 131  
       private final KeyType type;
 132  
       
 133  
       /**
 134  
        * This is the value that is used to provide the hash code.
 135  
        */
 136  
       private final String value;
 137  
       
 138  
       /**
 139  
        * Constructor for the <code>Key</code> object. This requires
 140  
        * the label and a key type to create a unique key. The key
 141  
        * type allows keys based on attributes to be differentiated
 142  
        * from those created for elements.
 143  
        * 
 144  
        * @param type this is the type that the key is created for
 145  
        * @param value this is the value used for the hash code
 146  
        */
 147  6046
       public Key(KeyType type, String value) throws Exception {
 148  6046
          this.value = value;
 149  6046
          this.type = type;
 150  6046
       }
 151  
       
 152  
       /**
 153  
        * This is used to compare keys and determine equality. If the
 154  
        * key value is the same and the key type is the same then the
 155  
        * key is considered equal, even if the labels are different.
 156  
        * 
 157  
        * @param value this is the value to compared to this
 158  
        * 
 159  
        * @return this returns true if the object is equal
 160  
        */
 161  
       public boolean equals(Object value) {
 162  1232
          if(value instanceof Key) {
 163  1232
             Key key = (Key)value;
 164  1232
             return equals(key);
 165  
          }
 166  0
          return false;
 167  
       }
 168  
       
 169  
       /**
 170  
        * This is used to compare keys and determine equality. If the
 171  
        * key value is the same and the key type is the same then the
 172  
        * key is considered equal, even if the labels are different.
 173  
        * 
 174  
        * @param key this is the value to compared to this
 175  
        * 
 176  
        * @return this returns true if the object is equal
 177  
        */
 178  
       public boolean equals(Key key) {
 179  1232
          if(type == key.type) {
 180  1213
             return key.value.equals(value);
 181  
          }
 182  19
          return false;
 183  
       }
 184  
       
 185  
       /**
 186  
        * This returns the hash code for the key. The hash code is
 187  
        * generated from the internal string the key represents. 
 188  
        * 
 189  
        * @return this is the hash code generated from the value
 190  
        */
 191  
       public int hashCode() {
 192  2995815
          return value.hashCode();
 193  
       }
 194  
       
 195  
       /**
 196  
        * This returns the string representation of the key. This is
 197  
        * used for debugging purposes in order to determine what the
 198  
        * key was generated from.
 199  
        * 
 200  
        * @return this returns the string representation of the key
 201  
        */
 202  
       public String toString() {
 203  4
          return value;
 204  
       }
 205  
    }
 206  
 }