001/** 002 * Copyright 2005-2018 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.lifecycle; 017 018import java.io.Serializable; 019import java.util.Collections; 020import java.util.HashMap; 021import java.util.List; 022import 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 */ 030public class ComponentPostMetadata implements Serializable { 031 032 private static final long serialVersionUID = -6090575873840392956L; 033 034 private String id; 035 private String path; 036 037 private Map<String, String> phasePathMapping; 038 private Map<String, List<String>> refreshPathMappings; 039 private boolean isDetachedComponent; 040 041 private Map<String, Object> unmodifiableData; 042 private Map<String, Object> data; 043 044 /** 045 * Constructor taking the id for the component to store metadata for. 046 * 047 * @param id component id 048 */ 049 public ComponentPostMetadata(String id) { 050 this.id = id; 051 } 052 053 /** 054 * Id for the component the post metadata is associated with. 055 * 056 * <p>The id can be used to retrieve the component post metadata from the view post metadata</p> 057 * 058 * @return component id 059 */ 060 public String getId() { 061 return id; 062 } 063 064 /** 065 * @see ComponentPostMetadata#getId() 066 */ 067 public void setId(String id) { 068 this.id = id; 069 } 070 071 /** 072 * Path of the component within the view structure (tree). 073 * 074 * <p>This is set during the lifecycle process and used to retrieve the component for refresh calls</p> 075 * 076 * @return path from view 077 */ 078 public String getPath() { 079 return path; 080 } 081 082 /** 083 * @see ComponentPostMetadata#getPath() 084 */ 085 public void setPath(String path) { 086 this.path = path; 087 } 088 089 /** 090 * Map containing the path for the component at each lifecycle phase. 091 * 092 * <p>Note this is only stored if the path of the component is different from the {@link #getPath()} 093 * at any of the phases</p> 094 * 095 * @return map where key is the phase name and the value is the component's path 096 */ 097 public Map<String, String> getPhasePathMapping() { 098 return phasePathMapping; 099 } 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}