001/* 002 * Copyright 2020 Anyware Services 003 * 004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 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.ametys.runtime.model.type; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Locale; 021import java.util.Optional; 022 023import org.apache.commons.lang3.StringUtils; 024 025import org.ametys.runtime.model.ModelItem; 026import org.ametys.runtime.model.ViewItem; 027 028/** 029 * Object that gives some context for data manipulation 030 */ 031public class DataContext 032{ 033 private Locale _locale; 034 private List<String> _fullDataPath = new ArrayList<>(); 035 private List<String> _dataPath = new ArrayList<>(); 036 private Optional<String> _objectId = Optional.empty(); 037 private Optional<String> _rootObjectId = Optional.empty(); 038 private boolean _renderEmptyValues = true; 039 private Optional<ModelItem> _modelItem = Optional.empty(); 040 private Optional<ViewItem> _viewItem = Optional.empty(); 041 042 /** 043 * Creates a new instance of a {@link DataContext} 044 */ 045 protected DataContext() 046 { 047 // Empty private constructor 048 } 049 050 /** 051 * Creates a new instance of a {@link DataContext} from another {@link DataContext} 052 * @param context the data context to copy 053 */ 054 protected DataContext(DataContext context) 055 { 056 withLocale(context.getLocale()); 057 withDataPath(context.getDataPath()); 058 withFullDataPath(context.getFullDataPath()); 059 withObjectId(context.getObjectId().orElse(null)); 060 withRootObjectId(context.getRootObjectId().orElse(null)); 061 withEmptyValues(context.renderEmptyValues()); 062 withModelItem(context.getModelItem().orElse(null)); 063 withViewItem(context.getViewItem().orElse(null)); 064 } 065 066 /** 067 * Creates a new instance of a {@link DataContext} 068 * @return the created instance 069 */ 070 public static DataContext newInstance() 071 { 072 return new DataContext(); 073 } 074 075 /** 076 * Creates a new instance of a {@link DataContext} from another {@link DataContext}. 077 * It can be the same implementation or another one, but it will be casted to the current implementation. 078 * @param context the data context to copy 079 * @return the created instance 080 */ 081 public static DataContext newInstance(DataContext context) 082 { 083 return new DataContext(context); 084 } 085 086 /** 087 * Creates a new instance of a {@link DataContext}, with the current context values 088 * @return the created instance 089 */ 090 public DataContext cloneContext() 091 { 092 return newInstance(this); 093 } 094 095 /** 096 * Retrieves the locale to use for localized data 097 * @return the locale, or null if no local has been set 098 */ 099 public Locale getLocale() 100 { 101 return _locale; 102 } 103 104 /** 105 * Sets the locale to use for localized data. 106 * Do not set {@link Locale} to use all existing ones. 107 * @param locale the locale to set 108 * @return the current {@link DataContext} 109 */ 110 @SuppressWarnings("unchecked") 111 public <T extends DataContext> T withLocale(Locale locale) 112 { 113 _locale = locale; 114 return (T) this; 115 } 116 117 /** 118 * Retrieves the data path 119 * @return the dataPath 120 */ 121 public String getDataPath() 122 { 123 return StringUtils.join(_dataPath, ModelItem.ITEM_PATH_SEPARATOR); 124 } 125 126 /** 127 * Retrieves the last segment of the data path 128 * @return the last segment of the data path 129 */ 130 public String getDataPathLastSegment() 131 { 132 return _dataPath.get(_dataPath.size() - 1); 133 } 134 135 /** 136 * Sets the data path 137 * @param dataPath the data path to set 138 * @return the current {@link DataContext} 139 */ 140 @SuppressWarnings("unchecked") 141 public <T extends DataContext> T withDataPath(String dataPath) 142 { 143 _dataPath = new ArrayList<>(); 144 if (StringUtils.isNotEmpty(dataPath)) 145 { 146 _dataPath.add(dataPath); 147 _fullDataPath.add(dataPath); 148 } 149 return (T) this; 150 } 151 152 /** 153 * Retrieves the full data path 154 * @return the fullDataPath 155 */ 156 public String getFullDataPath() 157 { 158 return StringUtils.join(_fullDataPath, ModelItem.ITEM_PATH_SEPARATOR); 159 } 160 161 /** 162 * Sets the full data path 163 * @param fullDataPath the full data path to set 164 * @return the current {@link DataContext} 165 */ 166 @SuppressWarnings("unchecked") 167 public <T extends DataContext> T withFullDataPath(String fullDataPath) 168 { 169 _fullDataPath = new ArrayList<>(); 170 if (StringUtils.isNotEmpty(fullDataPath)) 171 { 172 _fullDataPath.add(fullDataPath); 173 } 174 return (T) this; 175 } 176 177 /** 178 * Add a segment to the data path 179 * @param segment the segment to add to the data path 180 * @return the current {@link DataContext} 181 */ 182 @SuppressWarnings("unchecked") 183 public <T extends DataContext> T addSegmentToDataPath(String segment) 184 { 185 _dataPath.add(segment); 186 _fullDataPath.add(segment); 187 return (T) this; 188 } 189 190 /** 191 * Add a suffix to the last segment of the data path 192 * @param suffix the suffix to add to the last segment 193 * @return the current {@link DataContext} 194 */ 195 @SuppressWarnings("unchecked") 196 public <T extends DataContext> T addSuffixToLastSegment(String suffix) 197 { 198 int segmentIndex = _dataPath.size() - 1; 199 _dataPath.set(segmentIndex, _dataPath.get(segmentIndex) + suffix); 200 201 segmentIndex = _fullDataPath.size() - 1; 202 _fullDataPath.set(segmentIndex, _fullDataPath.get(segmentIndex) + suffix); 203 204 return (T) this; 205 } 206 207 /** 208 * Retrieves the identifier of the object from which the data path is computed 209 * @return the object identifier 210 */ 211 public Optional<String> getObjectId() 212 { 213 return _objectId; 214 } 215 216 /** 217 * Set the identifier of the object from which the data path is computed 218 * @param objectId the object identifier to set 219 * @return the current {@link DataContext} 220 */ 221 @SuppressWarnings("unchecked") 222 public <T extends DataContext> T withObjectId(String objectId) 223 { 224 _objectId = Optional.ofNullable(objectId) 225 .filter(StringUtils::isNotEmpty); 226 if (_rootObjectId.isEmpty()) 227 { 228 _rootObjectId = _objectId; 229 } 230 return (T) this; 231 } 232 233 /** 234 * Retrieves the identifier of the object from which the full data path is computed 235 * @return the root object identifier 236 */ 237 public Optional<String> getRootObjectId() 238 { 239 return _rootObjectId; 240 } 241 242 /** 243 * Set the identifier of the object from which the full data path is computed 244 * @param rootObjectId the root object identifier to set 245 * @return the current {@link DataContext} 246 */ 247 @SuppressWarnings("unchecked") 248 public <T extends DataContext> T withRootObjectId(String rootObjectId) 249 { 250 _rootObjectId = Optional.ofNullable(rootObjectId) 251 .filter(StringUtils::isNotEmpty); 252 return (T) this; 253 } 254 255 /** 256 * Determines if the empty values have to be rendered 257 * @return <code>true</code> if empty values must be rendered (default), <code>false</code> otherwise 258 */ 259 public boolean renderEmptyValues() 260 { 261 return _renderEmptyValues; 262 } 263 264 /** 265 * Set to <code>false</code> to not render empty values (default to <code>true</code>) 266 * @param renderEmptyValues <code>true</code> to render the empty values, <code>false</code> otherwise 267 * @return the current {@link DataContext} 268 */ 269 @SuppressWarnings("unchecked") 270 public <T extends DataContext> T withEmptyValues(boolean renderEmptyValues) 271 { 272 _renderEmptyValues = renderEmptyValues; 273 return (T) this; 274 } 275 276 /** 277 * Retrieves the model item 278 * @return the model item 279 */ 280 public Optional<ModelItem> getModelItem() 281 { 282 return _modelItem; 283 } 284 285 /** 286 * Sets the model item 287 * @param modelItem the model item to set 288 * @return the current {@link DataContext} 289 */ 290 @SuppressWarnings("unchecked") 291 public <T extends DataContext> T withModelItem(ModelItem modelItem) 292 { 293 _modelItem = Optional.ofNullable(modelItem); 294 return (T) this; 295 } 296 297 /** 298 * Retrieves the view item 299 * @return the view item 300 */ 301 public Optional<ViewItem> getViewItem() 302 { 303 return _viewItem; 304 } 305 306 /** 307 * Sets the view item 308 * @param viewItem the view item to set 309 * @return the current {@link DataContext} 310 */ 311 @SuppressWarnings("unchecked") 312 public <T extends DataContext> T withViewItem(ViewItem viewItem) 313 { 314 _viewItem = Optional.ofNullable(viewItem); 315 return (T) this; 316 } 317}