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.lifecycle;
17  
18  import java.io.Serializable;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  /**
25   * Holds data about a component that might be needed to handle a post request.
26   *
27   * @author Kuali Rice Team (rice.collab@kuali.org)
28   * @see ViewPostMetadata
29   */
30  public class ComponentPostMetadata implements Serializable {
31  
32      private static final long serialVersionUID = -6090575873840392956L;
33  
34      private String id;
35      private String path;
36  
37      private Map<String, String> phasePathMapping;
38      private Map<String, List<String>> refreshPathMappings;
39      private boolean isDetachedComponent;
40  
41      private Map<String, Object> unmodifiableData;
42      private Map<String, Object> data;
43  
44      /**
45       * Constructor taking the id for the component to store metadata for.
46       *
47       * @param id component id
48       */
49      public ComponentPostMetadata(String id) {
50          this.id = id;
51      }
52  
53      /**
54       * Id for the component the post metadata is associated with.
55       *
56       * <p>The id can be used to retrieve the component post metadata from the view post metadata</p>
57       *
58       * @return component id
59       */
60      public String getId() {
61          return id;
62      }
63  
64      /**
65       * @see ComponentPostMetadata#getId()
66       */
67      public void setId(String id) {
68          this.id = id;
69      }
70  
71      /**
72       * Path of the component within the view structure (tree).
73       *
74       * <p>This is set during the lifecycle process and used to retrieve the component for refresh calls</p>
75       *
76       * @return path from view
77       */
78      public String getPath() {
79          return path;
80      }
81  
82      /**
83       * @see ComponentPostMetadata#getPath()
84       */
85      public void setPath(String path) {
86          this.path = path;
87      }
88  
89      /**
90       * Map containing the path for the component at each lifecycle phase.
91       *
92       * <p>Note this is only stored if the path of the component is different from the {@link #getPath()}
93       * at any of the phases</p>
94       *
95       * @return map where key is the phase name and the value is the component's path
96       */
97      public Map<String, String> getPhasePathMapping() {
98          return phasePathMapping;
99      }
100 
101     /**
102      * @see ComponentPostMetadata#getPhasePathMapping()
103      */
104     public void setPhasePathMapping(Map<String, String> phasePathMapping) {
105         this.phasePathMapping = phasePathMapping;
106     }
107 
108     /**
109      * Map of property paths whose lifecycle will be run when the component is refreshed.
110      *
111      * <p>Each map entry contains a tree of paths to process for each of the lifecycle phases. This is so parents
112      * of the component (in each phase) are picked up during the refresh process</p>
113      *
114      * @return map of refresh paths
115      */
116     public Map<String, List<String>> getRefreshPathMappings() {
117         return refreshPathMappings;
118     }
119 
120     /**
121      * @see ComponentPostMetadata#getRefreshPathMappings()
122      */
123     public void setRefreshPathMappings(Map<String, List<String>> refreshPathMappings) {
124         this.refreshPathMappings = refreshPathMappings;
125     }
126 
127     /**
128      * Indicates whether the component is detached from the view (not in the view's structure, but an external
129      * component, for example a dialog).
130      *
131      * <p>This is used by the component refresh process to determine whether it can get the component instance
132      * by its path from the view (in the case of the component being attached), or if it must use its id (in the
133      * case of the component being detached).</p>
134      *
135      * @return boolean true if the component is detached, false if not
136      */
137     public boolean isDetachedComponent() {
138         return isDetachedComponent;
139     }
140 
141     /**
142      * @see ComponentPostMetadata#isDetachedComponent
143      */
144     public void setDetachedComponent(boolean isDetachedComponent) {
145         this.isDetachedComponent = isDetachedComponent;
146     }
147 
148     /**
149      * General post data that has been stored for the component.
150      *
151      * <p>Holds the general post data for a component. Any piece of data can be added to this map and then
152      * retrieved on a post call (for example in a controller method)</p>
153      *
154      * <p>Note map returned is unmodifiable. Use {@link ComponentPostMetadata#addData(java.lang.String,
155      * java.lang.Object)}
156      * to add new data entries</p>
157      *
158      * @return unmodifiable map of data
159      */
160     public Map<String, Object> getData() {
161         if (unmodifiableData == null) {
162             if (data == null) {
163                 unmodifiableData = Collections.emptyMap();
164             } else {
165                 unmodifiableData = Collections.unmodifiableMap(data);
166             }
167         }
168 
169         return unmodifiableData;
170     }
171 
172     /**
173      * @see ComponentPostMetadata#getData()
174      */
175     public void setData(Map<String, Object> data) {
176         this.unmodifiableData = null;
177         this.data = data;
178     }
179 
180     /**
181      * Adds a new data entry to the components post data.
182      *
183      * @param key key for data, which is used to retrieve the data
184      * @param value data value
185      * @see ComponentPostMetadata#getData()
186      */
187     public void addData(String key, Object value) {
188         if (this.data == null) {
189             setData(new HashMap<String, Object>());
190         }
191 
192         if (this.data.get(key) != value) {
193             synchronized (this.data) {
194                 this.data.put(key, value);
195             }
196         }
197     }
198 
199     /**
200      * Retrieves a post data value for the component.
201      *
202      * @param key key for the data value to retrieve
203      * @return data value, or null if data does not exist
204      *
205      * @see ComponentPostMetadata#getData()
206      */
207     public Object getData(String key) {
208         if (this.data != null) {
209             return this.data.get(key);
210         }
211 
212         return null;
213     }
214 
215     /**
216      * Get the path of the first object in this components path.
217      *
218      * @return the top most parent object's path for this component
219      */
220     public String getRootObjectPath() {
221         if (this.getPath() == null || !this.getPath().contains(".")) {
222             return this.getPath();
223         }
224 
225         return this.getPath().substring(0, this.getPath().indexOf('.'));
226     }
227 }