View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.util;
17  
18  import java.io.Serializable;
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.Map;
23  import java.util.Set;
24  
25  import org.kuali.rice.krad.datadictionary.Copyable;
26  
27  /**
28   * Map implementation for internal use by a lifecycle element.
29   *
30   * <p>Mutability of the map will follow the semantics for the lifecycle element.</p>
31   *
32   * @author Kuali Rice Team (rice.collab@kuali.org)
33   * @param <K> map key type
34   * @param <V> map value type
35   */
36  public class LifecycleAwareMap<K, V> implements Map<K, V>, UifCloneable, Copyable, Serializable {
37      private static final long serialVersionUID = -2872079344892779899L;
38  
39      /**
40       * The lifecycle element this map is related to.
41       */
42      private final LifecycleElement lifecycleElement;
43  
44      /**
45       * Delegating map implementation.
46       */
47      private Map<K, V> delegate;
48  
49      /**
50       * Create a new map instance for use with a lifecycle element.
51       *
52       * @param lifecycleElement The lifecycle element to use for mutability checks.
53       */
54      public LifecycleAwareMap(LifecycleElement lifecycleElement) {
55          this.lifecycleElement = lifecycleElement;
56          this.delegate = Collections.emptyMap();
57      }
58  
59      /**
60       * Create a new list instance, based on another list.
61       *
62       * @param lifecycleElement The lifecycle element to use for mutability checks.
63       * @param delegate The list to wrap.
64       */
65      public LifecycleAwareMap(LifecycleElement lifecycleElement, Map<K, V> delegate) {
66          this.lifecycleElement = lifecycleElement;
67          this.delegate = delegate;
68      }
69  
70      /**
71       * Ensure that the delegate list can be modified.
72       */
73      private void ensureMutable() {
74          lifecycleElement.checkMutable(true);
75  
76          if (delegate == Collections.EMPTY_MAP) {
77              delegate = new HashMap<K, V>();
78          }
79      }
80  
81      @Override
82      public int size() {
83          return this.delegate.size();
84      }
85  
86      @Override
87      public boolean isEmpty() {
88          return this.delegate.isEmpty();
89      }
90  
91      @Override
92      public boolean containsKey(Object key) {
93          return this.delegate.containsKey(key);
94      }
95  
96      @Override
97      public boolean containsValue(Object value) {
98          return this.delegate.containsValue(value);
99      }
100 
101     @Override
102     public V get(Object key) {
103         return this.delegate.get(key);
104     }
105 
106     @Override
107     public V put(K key, V value) {
108         ensureMutable();
109         return this.delegate.put(key, value);
110     }
111 
112     @Override
113     public V remove(Object key) {
114         lifecycleElement.checkMutable(true);
115         return delegate == Collections.EMPTY_MAP ? null : this.delegate.remove(key);
116     }
117 
118     @Override
119     public void putAll(Map<? extends K, ? extends V> m) {
120         ensureMutable();
121         this.delegate.putAll(m);
122     }
123 
124     @Override
125     public void clear() {
126         if (delegate != Collections.EMPTY_MAP) {
127             this.delegate.clear();
128         }
129     }
130 
131     @Override
132     public Set<K> keySet() {
133         return this.delegate.keySet();
134     }
135 
136     @Override
137     public Collection<V> values() {
138         return this.delegate.values();
139     }
140 
141     @Override
142     public Set<java.util.Map.Entry<K, V>> entrySet() {
143         // TODO: Return entrySet wrapper
144         return this.delegate.entrySet();
145     }
146 
147     @Override
148     public boolean equals(Object o) {
149         return this.delegate.equals(o);
150     }
151 
152     @Override
153     public int hashCode() {
154         return this.delegate.hashCode();
155     }
156 
157     /**
158      * @see org.kuali.rice.krad.datadictionary.Copyable#copy()
159      */
160     @SuppressWarnings("unchecked")
161     @Override
162     public <T> T copy() {
163         try {
164             return (T) clone();
165         } catch (CloneNotSupportedException e) {
166             throw new IllegalStateException("Unexpected error in clone()", e);
167         }
168     }
169 
170     /**
171      * Modification is not controlled at this level.
172      * 
173      * @see Copyable#preventModification()
174      */
175     @Override
176     public void preventModification() {}
177 
178     /**
179      * @see java.lang.Object#clone()
180      */
181     @Override
182     public Object clone() throws CloneNotSupportedException {
183         return super.clone();
184     }
185 
186     /**
187      * {@inheritDoc}
188      */
189     @Override
190     public Copyable unwrap() {
191         return this;
192     }
193 
194 }