Coverage Report - org.kuali.rice.core.api.mo.common.Attributes
 
Classes in this File Line Coverage Branch Coverage Complexity
Attributes
75%
40/53
86%
19/22
2.227
Attributes$1
N/A
N/A
2.227
Attributes$Adapter
84%
11/13
66%
8/12
2.227
Attributes$Constants
50%
1/2
N/A
2.227
 
 1  
 package org.kuali.rice.core.api.mo.common;
 2  
 
 3  
 import org.apache.commons.lang.builder.EqualsBuilder;
 4  
 import org.apache.commons.lang.builder.HashCodeBuilder;
 5  
 import org.apache.commons.lang.builder.ToStringBuilder;
 6  
 import org.kuali.rice.core.util.KeyValue;
 7  
 import org.kuali.rice.core.util.jaxb.StringMapEntry;
 8  
 import org.kuali.rice.core.util.jaxb.StringMapEntryList;
 9  
 
 10  
 import javax.xml.bind.annotation.XmlRootElement;
 11  
 import javax.xml.bind.annotation.adapters.XmlAdapter;
 12  
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 13  
 import java.io.Serializable;
 14  
 import java.util.AbstractMap;
 15  
 import java.util.ArrayList;
 16  
 import java.util.Collection;
 17  
 import java.util.Collections;
 18  
 import java.util.HashMap;
 19  
 import java.util.HashSet;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 import java.util.Set;
 23  
 
 24  
 /**
 25  
  * This is a generic attributes class in rice.  It is essentially a list of key-value
 26  
  * pairs where the key & value are strings & the keys are unique.
 27  
  */
 28  
 @XmlRootElement
 29  
 @XmlJavaTypeAdapter(Attributes.Adapter.class)
 30  5
 public final class Attributes implements Serializable {
 31  
 
 32  
     private static final long serialVersionUID = -2804341886674598357L;
 33  
 
 34  1
         private static final Attributes EMPTY = new Attributes(Collections.<String, String>emptyMap());
 35  
 
 36  
     private final Map<String, String> keyValues;
 37  
 
 38  13
     private final Object lock = new Object();
 39  
     private Set<Map.Entry<String, String>> cache;
 40  
 
 41  
     /**
 42  
      * This constructor should never be called except during JAXB unmarshalling.
 43  
      */
 44  0
     private Attributes() {
 45  0
         this.keyValues = null;
 46  0
     }
 47  
 
 48  13
     private Attributes(final Map<String, String> map) {
 49  13
         this.keyValues = new HashMap<String, String>(map);
 50  13
     }
 51  
 
 52  
     /**
 53  
      * Creates empty attributes.
 54  
      *
 55  
      * @return Attributes
 56  
      */
 57  
     public static Attributes empty() {
 58  4
         return EMPTY;
 59  
     }
 60  
 
 61  
     /**
 62  
      * Creates attributes from a {@link Map}.  Map cannot be null.
 63  
      *
 64  
      * @return Attributes
 65  
      * @throws IllegalArgumentException if map is null
 66  
      */
 67  
     public static Attributes fromMap(Map<String, String> map) {
 68  12
         if (map == null) {
 69  1
             throw new IllegalArgumentException("map is null");
 70  
         }
 71  
 
 72  11
         if (map.isEmpty()) {
 73  1
             return empty();
 74  
         }
 75  
 
 76  10
         return new Attributes(map);
 77  
     }
 78  
 
 79  
     /**
 80  
      * Creates attributes from a {@link Map.Entry}.  Map.Entry cannot be null.
 81  
      *
 82  
      * @return Attributes
 83  
      * @throws IllegalArgumentException if entry is null or entry.key is null
 84  
      */
 85  
     public static Attributes fromMapEntry(Map.Entry<String, String> entry) {
 86  3
         if (entry == null) {
 87  1
             throw new IllegalArgumentException("entry is null");
 88  
         }
 89  
 
 90  2
         if (entry.getKey() == null) {
 91  1
             throw new IllegalArgumentException("entry.key is null");
 92  
         }
 93  
 
 94  1
         return fromMap(Collections.singletonMap(entry.getKey(), entry.getValue()));
 95  
     }
 96  
 
 97  
     /**
 98  
      * Creates attributes from strings.  Key cannot be null. Value can be null
 99  
      *
 100  
      * @return Attributes
 101  
      * @throws IllegalArgumentException if key is null
 102  
      */
 103  
     public static Attributes fromStrings(String key, String value) {
 104  2
         if (key == null) {
 105  1
             throw new IllegalArgumentException("key is null");
 106  
         }
 107  
 
 108  1
         return fromMap(Collections.singletonMap(key, value));
 109  
     }
 110  
 
 111  
     /**
 112  
      * Creates attributes from a {@link KeyValue}.  KeyValue cannot be null.
 113  
      *
 114  
      * @return Attributes
 115  
      * @throws IllegalArgumentException if keyValue is null
 116  
      */
 117  
     public static Attributes fromKeyValue(KeyValue keyValue) {
 118  3
         if (keyValue == null) {
 119  1
             throw new IllegalArgumentException("keyValue is null");
 120  
         }
 121  
 
 122  2
         if (keyValue.getKey() == null) {
 123  1
             throw new IllegalArgumentException("keyValue.key is null");
 124  
         }
 125  
 
 126  1
         return fromMap(Collections.singletonMap(keyValue.getKey(), keyValue.getValue()));
 127  
     }
 128  
 
 129  
     /**
 130  
      * Converts key value to a mutable {@link Map}.
 131  
      * The map returned is disconnected from this Attributes class and is mutable.
 132  
      *
 133  
      * @return a Map
 134  
      */
 135  
     public Map<String, String> toMap() {
 136  2
         return new HashMap<String, String>(keyValues);
 137  
     }
 138  
 
 139  
     //map-like methods
 140  
 
 141  
     /**
 142  
      * Returns the amount of attributes in this data structure.
 143  
      *
 144  
      * @return the size
 145  
      */
 146  
     public int size() {
 147  0
         return keyValues.size();
 148  
     }
 149  
 
 150  
     /**
 151  
      * Whether this data structure does not contain any attributes.
 152  
      *
 153  
      * @return true if empty false if not
 154  
      */
 155  
     public boolean isEmpty() {
 156  0
         return keyValues.isEmpty();
 157  
     }
 158  
 
 159  
     /**
 160  
      * Whether this data structure contains an attribute with a given key. Key may not be null.
 161  
      *
 162  
      * @param key the key
 163  
      * @return true if the key exists false if not
 164  
      * @throws IllegalArgumentException if the key is null
 165  
      */
 166  
     public boolean containsKey(String key) {
 167  1
         validateKey(key);
 168  1
         return keyValues.containsKey(key);
 169  
     }
 170  
 
 171  
     /**
 172  
      * Whether this data structure contains an attribute with a given value. Value may be null.
 173  
      *
 174  
      * @param value the value
 175  
      * @return true if the value exists false if not
 176  
      */
 177  
     public boolean containsValue(String value) {
 178  0
         return keyValues.containsValue(value);
 179  
     }
 180  
 
 181  
     /**
 182  
      * Gets an attribute value from a key. Key may not be null.
 183  
      *
 184  
      * @param key the key
 185  
      * @return true if the value exists false if not
 186  
      */
 187  
     public String get(String key) {
 188  0
         validateKey(key);
 189  0
         return keyValues.get(key);
 190  
     }
 191  
 
 192  
     /**
 193  
      * Gets a mutable {@link Set} of all attribute keys.
 194  
      *
 195  
      * @return the set.
 196  
      */
 197  
     public Set<String> keySet() {
 198  0
         return keyValues.keySet();
 199  
     }
 200  
 
 201  
     /**
 202  
      * Gets a mutable {@link Collection} of all attribute values.  Could contain null values.
 203  
      *
 204  
      * @return the collection.
 205  
      */
 206  
     public Collection<String> values() {
 207  0
         return keyValues.values();
 208  
     }
 209  
 
 210  
     /**
 211  
      * Gets a immutable {@link Set} of immutable {@link Map.Entry} instances.
 212  
      *
 213  
      * @return the set.
 214  
      */
 215  
     public Set<Map.Entry<String, String>> entrySet() {
 216  
         //not sure if we really need caching here - but adding it
 217  
         //b/c it is easy enough to implement
 218  5
         synchronized (lock) {
 219  5
             if (cache == null) {
 220  5
                 final Set<Map.Entry<String, String>> temp = new HashSet<Map.Entry<String, String>>();
 221  5
                 for (Map.Entry<String, String> e : keyValues.entrySet()) {
 222  5
                     if (e != null) {
 223  5
                         temp.add(new AbstractMap.SimpleImmutableEntry<String, String>(e.getKey(), e.getValue()));
 224  
                     }
 225  
                 }
 226  5
                 cache = Collections.unmodifiableSet(temp);
 227  
             }
 228  5
         }
 229  5
         return cache;
 230  
     }
 231  
 
 232  
     private static void validateKey(String key) {
 233  1
         if (key == null) {
 234  0
             throw new IllegalArgumentException("key is null");
 235  
         }
 236  1
     }
 237  
 
 238  
     @Override
 239  
     public int hashCode() {
 240  0
         return HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE);
 241  
     }
 242  
 
 243  
     @Override
 244  
     public boolean equals(Object obj) {
 245  2
         return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE);
 246  
     }
 247  
 
 248  
     @Override
 249  
     public String toString() {
 250  0
         return ToStringBuilder.reflectionToString(this);
 251  
     }
 252  
 
 253  
     /**
 254  
      * Defines some internal constants used on this class.
 255  
      */
 256  0
     static class Constants {
 257  1
         final static String[] HASH_CODE_EQUALS_EXCLUDE = {"cache", "lock"};
 258  
     }
 259  
     
 260  5
     public static class Adapter extends XmlAdapter<StringMapEntryList, Attributes> {
 261  
 
 262  
             @Override
 263  
             public StringMapEntryList marshal(Attributes attributes) throws Exception {
 264  1
                     if (attributes == null || attributes.keyValues == null) {
 265  0
                             return null;
 266  
                     }
 267  1
                     List<StringMapEntry> entries = new ArrayList<StringMapEntry>(attributes.keyValues.size());
 268  1
                     for (Map.Entry<String, String> entry : attributes.keyValues.entrySet()) {
 269  1
                             entries.add(new StringMapEntry(entry));
 270  
                     }
 271  1
                     return new StringMapEntryList(entries);
 272  
             }
 273  
 
 274  
             @Override
 275  
             public Attributes unmarshal(StringMapEntryList entries) throws Exception {
 276  2
                     if (entries == null || entries.getEntries() == null) {
 277  0
                             return null;
 278  
                     }
 279  2
                     Map<String, String> resultMap = new HashMap<String, String>();
 280  2
                     for (StringMapEntry entry : entries.getEntries()) {
 281  2
                             resultMap.put(entry.getKey(), entry.getValue());
 282  
                     }
 283  2
                     return new Attributes(resultMap);
 284  
             }
 285  
 
 286  
     }
 287  
 
 288  
 }