001 /**
002 * Copyright 2005-2014 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 */
016 package org.kuali.rice.krad.uif.lifecycle;
017
018 import java.io.Serializable;
019 import java.util.Collections;
020 import java.util.HashMap;
021 import java.util.List;
022 import java.util.Map;
023
024 /**
025 * Holds data about a component that might be needed to handle a post request.
026 *
027 * @author Kuali Rice Team (rice.collab@kuali.org)
028 * @see ViewPostMetadata
029 */
030 public class ComponentPostMetadata implements Serializable {
031 private static final long serialVersionUID = -6090575873840392956L;
032
033 private String id;
034 private String path;
035
036 private Map<String, String> phasePathMapping;
037 private Map<String, List<String>> refreshPathMappings;
038 private boolean isDetachedComponent;
039
040 private Map<String, Object> unmodifiableData;
041 private Map<String, Object> data;
042
043 /**
044 * Constructor taking the id for the component to store metadata for.
045 *
046 * @param id component id
047 */
048 public ComponentPostMetadata(String id) {
049 this.id = id;
050 }
051
052 /**
053 * Id for the component the post metadata is associated with.
054 *
055 * <p>The id can be used to retrieve the component post metadata from the view post metadata</p>
056 *
057 * @return component id
058 */
059 public String getId() {
060 return id;
061 }
062
063 /**
064 * @see ComponentPostMetadata#getId()
065 */
066 public void setId(String id) {
067 this.id = id;
068 }
069
070 /**
071 * Path of the component within the view structure (tree).
072 *
073 * <p>This is set during the lifecycle process and used to retrieve the component for refresh calls</p>
074 *
075 * @return path from view
076 */
077 public String getPath() {
078 return path;
079 }
080
081 /**
082 * @see ComponentPostMetadata#getPath()
083 */
084 public void setPath(String path) {
085 this.path = path;
086 }
087
088 /**
089 * Map containing the path for the component at each lifecycle phase.
090 *
091 * <p>Note this is only stored if the path of the component is different from the {@link #getPath()}
092 * at any of the phases</p>
093 *
094 * @return map where key is the phase name and the value is the component's path
095 */
096 public Map<String, String> getPhasePathMapping() {
097 return phasePathMapping;
098 }
099
100 /**
101 * @see ComponentPostMetadata#getPhasePathMapping()
102 */
103 public void setPhasePathMapping(Map<String, String> phasePathMapping) {
104 this.phasePathMapping = phasePathMapping;
105 }
106
107 /**
108 * Map of property paths whose lifecycle will be run when the component is refreshed.
109 *
110 * <p>Each map entry contains a tree of paths to process for each of the lifecycle phases. This is so parents
111 * of the component (in each phase) are picked up during the refresh process</p>
112 *
113 * @return map of refresh paths
114 */
115 public Map<String, List<String>> getRefreshPathMappings() {
116 return refreshPathMappings;
117 }
118
119 /**
120 * @see ComponentPostMetadata#getRefreshPathMappings()
121 */
122 public void setRefreshPathMappings(Map<String, List<String>> refreshPathMappings) {
123 this.refreshPathMappings = refreshPathMappings;
124 }
125
126 /**
127 * Indicates whether the component is detached from the view (not in the view's structure, but an external
128 * component, for example a dialog).
129 *
130 * <p>This is used by the component refresh process to determine whether it can get the component instance
131 * by its path from the view (in the case of the component being attached), or if it must use its id (in the
132 * case of the component being detached).</p>
133 *
134 * @return boolean true if the component is detached, false if not
135 */
136 public boolean isDetachedComponent() {
137 return isDetachedComponent;
138 }
139
140 /**
141 * @see ComponentPostMetadata#isDetachedComponent
142 */
143 public void setDetachedComponent(boolean isDetachedComponent) {
144 this.isDetachedComponent = isDetachedComponent;
145 }
146
147 /**
148 * General post data that has been stored for the component.
149 *
150 * <p>Holds the general post data for a component. Any piece of data can be added to this map and then
151 * retrieved on a post call (for example in a controller method)</p>
152 *
153 * <p>Note map returned is unmodifiable. Use {@link ComponentPostMetadata#addData(java.lang.String,
154 * java.lang.Object)}
155 * to add new data entries</p>
156 *
157 * @return unmodifiable map of data
158 */
159 public Map<String, Object> getData() {
160 if (unmodifiableData == null) {
161 if (data == null) {
162 unmodifiableData = Collections.emptyMap();
163 } else {
164 unmodifiableData = Collections.unmodifiableMap(data);
165 }
166 }
167
168 return unmodifiableData;
169 }
170
171 /**
172 * @see ComponentPostMetadata#getData()
173 */
174 public void setData(Map<String, Object> data) {
175 this.unmodifiableData = null;
176 this.data = data;
177 }
178
179 /**
180 * Adds a new data entry to the components post data.
181 *
182 * @param key key for data, which is used to retrieve the data
183 * @param value data value
184 * @see ComponentPostMetadata#getData()
185 */
186 public void addData(String key, Object value) {
187 if (this.data == null) {
188 setData(new HashMap<String, Object>());
189 }
190
191 if (this.data.get(key) != value) {
192 synchronized (this.data) {
193 this.data.put(key, value);
194 }
195 }
196 }
197
198 /**
199 * Retrieves a post data value for the component.
200 *
201 * @param key key for the data value to retrieve
202 * @return data value, or null if data does not exist
203 * @see ComponentPostMetadata#getData()
204 */
205 public Object getData(String key) {
206 if (this.data != null) {
207 return this.data.get(key);
208 }
209
210 return null;
211 }
212 }