001/** 002 * Copyright 2005-2015 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krad.uif.util; 017 018import java.io.Serializable; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.Map; 023import java.util.Set; 024 025import org.kuali.rice.krad.datadictionary.Copyable; 026 027/** 028 * Map implementation for internal use by a lifecycle element. 029 * 030 * <p>Mutability of the map will follow the semantics for the lifecycle element.</p> 031 * 032 * @author Kuali Rice Team (rice.collab@kuali.org) 033 * @param <K> map key type 034 * @param <V> map value type 035 */ 036public class LifecycleAwareMap<K, V> implements Map<K, V>, Copyable, Serializable { 037 private static final long serialVersionUID = -2872079344892779899L; 038 039 /** 040 * The lifecycle element this map is related to. 041 */ 042 private final LifecycleElement lifecycleElement; 043 044 /** 045 * Delegating map implementation. 046 */ 047 private Map<K, V> delegate; 048 049 /** 050 * Create a new map instance for use with a lifecycle element. 051 * 052 * @param lifecycleElement The lifecycle element to use for mutability checks. 053 */ 054 public LifecycleAwareMap(LifecycleElement lifecycleElement) { 055 this.lifecycleElement = lifecycleElement; 056 this.delegate = Collections.emptyMap(); 057 } 058 059 /** 060 * Create a new list instance, based on another list. 061 * 062 * @param lifecycleElement The lifecycle element to use for mutability checks. 063 * @param delegate The list to wrap. 064 */ 065 public LifecycleAwareMap(LifecycleElement lifecycleElement, Map<K, V> delegate) { 066 this.lifecycleElement = lifecycleElement; 067 this.delegate = delegate; 068 } 069 070 /** 071 * Ensure that the delegate list can be modified. 072 */ 073 private void ensureMutable() { 074 lifecycleElement.checkMutable(true); 075 076 if (delegate == Collections.EMPTY_MAP) { 077 delegate = new HashMap<K, V>(); 078 } 079 } 080 081 @Override 082 public int size() { 083 return this.delegate.size(); 084 } 085 086 @Override 087 public boolean isEmpty() { 088 return this.delegate.isEmpty(); 089 } 090 091 @Override 092 public boolean containsKey(Object key) { 093 return this.delegate.containsKey(key); 094 } 095 096 @Override 097 public boolean containsValue(Object value) { 098 return this.delegate.containsValue(value); 099 } 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 java.lang.Object#clone() 159 */ 160 @Override 161 public Object clone() throws CloneNotSupportedException { 162 return super.clone(); 163 } 164 165}