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.field; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.log4j.Logger; 020import org.kuali.rice.core.api.exception.RiceRuntimeException; 021import org.kuali.rice.krad.datadictionary.parse.BeanTag; 022import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 023import org.kuali.rice.krad.uif.UifConstants; 024import org.kuali.rice.krad.uif.component.Component; 025import org.kuali.rice.krad.uif.component.ComponentBase; 026import org.kuali.rice.krad.uif.component.ComponentSecurity; 027import org.kuali.rice.krad.uif.component.DelayedCopy; 028import org.kuali.rice.krad.uif.element.Label; 029import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; 030import org.kuali.rice.krad.uif.util.ComponentFactory; 031import org.kuali.rice.krad.uif.util.LifecycleElement; 032import org.kuali.rice.krad.uif.util.MessageStructureUtils; 033import org.kuali.rice.krad.uif.view.View; 034import org.kuali.rice.krad.util.KRADUtils; 035 036import java.util.List; 037 038/** 039 * Base class for <code>Field</code> implementations 040 * 041 * <p> 042 * Sets the component type name so that all field templates have a fixed 043 * contract 044 * </p> 045 * 046 * <p> 047 * Holds a nested <code>Label</code> with configuration for rendering the 048 * label and configuration on label placement. 049 * </p> 050 * 051 * @author Kuali Rice Team (rice.collab@kuali.org) 052 */ 053@BeanTag(name = "fieldBase", parent = "Uif-FieldBase") 054public class FieldBase extends ComponentBase implements Field { 055 private static final long serialVersionUID = -5888414844802862760L; 056 private static final Logger LOG = Logger.getLogger(FieldBase.class); 057 058 private String shortLabel; 059 060 @DelayedCopy 061 private Label fieldLabel; 062 063 private boolean labelLeft; 064 private boolean labelRendered; 065 066 public FieldBase() { 067 super(); 068 069 labelRendered = false; 070 } 071 072 /** 073 * The following finalization is performed: 074 * 075 * <ul> 076 * <li>Make sure that a label is defined for any data fields. If not then create hidden label using property 077 * name.</li> 078 * <li>If no label for a non data field then just log a warning.</li> 079 * </ul> 080 * 081 * {@inheritDoc} 082 */ 083 @Override 084 public void performApplyModel(Object model, LifecycleElement parent) { 085 super.performApplyModel(model, parent); 086 087 if (!labelRendered && fieldLabel == null) { 088 if (this instanceof DataFieldBase) { 089 LOG.warn("DataField (" 090 + this.getClass().getName() 091 + ") ID: " 092 + this.getId() 093 + ", propertyName: " 094 + ((DataFieldBase) this).getPropertyName() 095 + " has no label. A hidden default label will be created."); 096 this.setLabel(((DataFieldBase) this).getPropertyName()); 097 this.setLabelRendered(false); 098 this.setShowLabel(true); 099 } else { 100 if (this instanceof SpaceField == false) { 101 LOG.warn("Field (" + this.getClass().getName() + ") ID: " + this.getId() + " has no label."); 102 } 103 } 104 } 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override 111 public void afterEvaluateExpression() { 112 super.afterEvaluateExpression(); 113 114 if (getReadOnly() == null) { 115 Component parent = ViewLifecycle.getPhase().getParent(); 116 setReadOnly(parent == null ? null : parent.getReadOnly()); 117 } 118 } 119 120 /** 121 * The following finalization is performed: 122 * 123 * <ul> 124 * <li>Set the labelForComponentId to this component id</li> 125 * <li>Set the label text on the label field from the field's label property</li> 126 * <li>Set the render property on the label's required message field if this field is marked as required</li> 127 * </ul> 128 * 129 * {@inheritDoc} 130 */ 131 @Override 132 public void performFinalize(Object model, LifecycleElement parent) { 133 super.performFinalize(model, parent); 134 135 if (fieldLabel != null) { 136 fieldLabel.setLabelForComponentId(this.getId()); 137 138 if ((getRequired() != null) && getRequired().booleanValue()) { 139 View view = ViewLifecycle.getView(); 140 if (view.getViewTypeName() != null && view.getViewTypeName().equals( 141 UifConstants.ViewType.MAINTENANCE)) { 142 fieldLabel.setRenderRequiredIndicator(!Boolean.TRUE.equals(view.getReadOnly())); 143 } else { 144 fieldLabel.setRenderRequiredIndicator(!Boolean.TRUE.equals(getReadOnly())); 145 } 146 } else { 147 setRequired(false); 148 fieldLabel.setRenderRequiredIndicator(false); 149 } 150 151 if (labelLeft) { 152 fieldLabel.addStyleClass("uif-labelLeft"); 153 } 154 else { 155 fieldLabel.addStyleClass("uif-labelBlock"); 156 } 157 158 fieldLabel.addDataAttribute(UifConstants.DataAttributes.LABEL_FOR, this.getId()); 159 if (StringUtils.isNotBlank(this.getFieldLabel().getLabelText())) { 160 this.addDataAttribute(UifConstants.DataAttributes.LABEL, MessageStructureUtils.translateStringMessage( 161 this.getFieldLabel().getLabelText())); 162 } 163 } 164 165 // set up script to add omit data so this field will not be posted on form submit 166 if (isOmitFromFormPost()) { 167 this.addDataAttribute(UifConstants.DataAttributes.OMIT_FROM_POST, "true"); 168 } 169 } 170 171 /** 172 * Helper method for suffixing the ids of the fields nested components 173 * 174 * @param component component to adjust id for 175 * @param suffix suffix to append to id 176 */ 177 protected void setNestedComponentIdAndSuffix(Component component, String suffix) { 178 if (component != null) { 179 String fieldId = getId(); 180 fieldId += suffix; 181 182 component.setId(fieldId); 183 } 184 } 185 186 /** 187 * {@inheritDoc} 188 */ 189 @Override 190 public final String getComponentTypeName() { 191 return "field"; 192 } 193 194 /** 195 * @see org.kuali.rice.krad.uif.field.Field#getLabel 196 */ 197 @BeanTagAttribute 198 public String getLabel() { 199 if (fieldLabel != null) { 200 return fieldLabel.getLabelText(); 201 } 202 203 return ""; 204 } 205 206 /** 207 * @see org.kuali.rice.krad.uif.field.Field#setLabel(java.lang.String) 208 */ 209 public void setLabel(String labelText) { 210 if (StringUtils.isNotBlank(labelText) && this.fieldLabel == null) { 211 this.fieldLabel = ComponentFactory.getLabel(); 212 } 213 214 if (this.fieldLabel != null) { 215 this.fieldLabel.setLabelText(labelText); 216 } 217 } 218 219 /** 220 * @see org.kuali.rice.krad.uif.field.Field#getLabelStyleClasses 221 */ 222 @BeanTagAttribute 223 public List<String> getLabelStyleClasses() { 224 if (fieldLabel != null) { 225 return fieldLabel.getCssClasses(); 226 } 227 228 return null; 229 } 230 231 /** 232 * @see org.kuali.rice.krad.uif.field.Field#setLabelStyleClasses 233 */ 234 public void setLabelStyleClasses(List<String> labelStyleClasses) { 235 if (labelStyleClasses != null && this.fieldLabel == null) { 236 this.fieldLabel = ComponentFactory.getLabel(); 237 } 238 239 if (this.fieldLabel != null) { 240 this.fieldLabel.setCssClasses(labelStyleClasses); 241 } 242 } 243 244 /** 245 * @see org.kuali.rice.krad.uif.field.Field#getLabelColSpan 246 */ 247 @BeanTagAttribute 248 public int getLabelColSpan() { 249 if (fieldLabel != null) { 250 return fieldLabel.getColSpan(); 251 } 252 253 return 1; 254 } 255 256 /** 257 * @see org.kuali.rice.krad.uif.field.Field#setLabelColSpan 258 */ 259 public void setLabelColSpan(int labelColSpan) { 260 if (this.fieldLabel == null) { 261 this.fieldLabel = ComponentFactory.getLabel(); 262 } 263 264 if (this.fieldLabel != null) { 265 this.fieldLabel.setColSpan(labelColSpan); 266 } 267 } 268 269 /** 270 * @see org.kuali.rice.krad.uif.field.Field#getShortLabel() 271 */ 272 @BeanTagAttribute 273 public String getShortLabel() { 274 return this.shortLabel; 275 } 276 277 /** 278 * @see org.kuali.rice.krad.uif.field.Field#setShortLabel(java.lang.String) 279 */ 280 public void setShortLabel(String shortLabel) { 281 this.shortLabel = shortLabel; 282 } 283 284 /** 285 * Sets whether the label should be displayed 286 * 287 * <p> 288 * Convenience method for configuration that sets the hidden indicator on 289 * the fields <code>Label</code> instance. The label is not really hidden 290 * but set off screen for accessibility. 291 * </p> 292 * 293 * @param showLabel true if label should be hidden, false if the label 294 * should not be hidden 295 */ 296 public void setShowLabel(boolean showLabel) { 297 if (fieldLabel != null) { 298 fieldLabel.setHidden(showLabel); 299 } 300 } 301 302 /** 303 * @see org.kuali.rice.krad.uif.field.Field#getLabel 304 */ 305 @BeanTagAttribute 306 public Label getFieldLabel() { 307 return this.fieldLabel; 308 } 309 310 /** 311 * @see org.kuali.rice.krad.uif.field.Field#setFieldLabel 312 */ 313 public void setFieldLabel(Label fieldLabel) { 314 this.fieldLabel = fieldLabel; 315 } 316 317 /** 318 * {@inheritDoc} 319 */ 320 @Override 321 @BeanTagAttribute 322 public boolean isLabelLeft() { 323 return labelLeft; 324 } 325 326 /** 327 * {@inheritDoc} 328 */ 329 @Override 330 public void setLabelLeft(boolean labelLeft) { 331 this.labelLeft = labelLeft; 332 } 333 334 /** 335 * @see org.kuali.rice.krad.uif.field.Field#isLabelRendered() 336 */ 337 @BeanTagAttribute 338 public boolean isLabelRendered() { 339 return this.labelRendered; 340 } 341 342 /** 343 * @see org.kuali.rice.krad.uif.field.Field#setLabelRendered(boolean) 344 */ 345 public void setLabelRendered(boolean labelRendered) { 346 this.labelRendered = labelRendered; 347 } 348 349 /** 350 * @see org.kuali.rice.krad.uif.field.Field#getFieldSecurity() 351 */ 352 public FieldSecurity getFieldSecurity() { 353 return (FieldSecurity) super.getComponentSecurity(); 354 } 355 356 /** 357 * Override to assert a {@link FieldSecurity} instance is set 358 * 359 * @param componentSecurity instance of FieldSecurity 360 */ 361 @Override 362 public void setComponentSecurity(ComponentSecurity componentSecurity) { 363 if ((componentSecurity != null) && !(componentSecurity instanceof FieldSecurity)) { 364 throw new RiceRuntimeException("Component security for Field should be instance of FieldSecurity"); 365 } 366 367 super.setComponentSecurity(componentSecurity); 368 } 369 370 /** 371 * {@inheritDoc} 372 */ 373 @Override 374 protected void initializeComponentSecurity() { 375 if (getComponentSecurity() == null) { 376 setComponentSecurity(KRADUtils.createNewObjectFromClass(FieldSecurity.class)); 377 } 378 } 379 380 /** 381 * @see org.kuali.rice.krad.uif.field.FieldSecurity#isEditInLineAuthz() 382 */ 383 @BeanTagAttribute 384 public Boolean isEditInLineAuthz() { 385 initializeComponentSecurity(); 386 387 return getFieldSecurity().isEditInLineAuthz(); 388 } 389 390 /** 391 * @see org.kuali.rice.krad.uif.field.FieldSecurity#setEditInLineAuthz(Boolean) 392 */ 393 public void setEditInLineAuthz(Boolean editInLineAuthz) { 394 initializeComponentSecurity(); 395 396 getFieldSecurity().setEditInLineAuthz(editInLineAuthz); 397 } 398 399 /** 400 * @see org.kuali.rice.krad.uif.field.FieldSecurity#isViewInLineAuthz() 401 */ 402 @BeanTagAttribute 403 public Boolean isViewInLineAuthz() { 404 initializeComponentSecurity(); 405 406 return getFieldSecurity().isViewInLineAuthz(); 407 } 408 409 /** 410 * @see org.kuali.rice.krad.uif.field.FieldSecurity#setViewInLineAuthz(Boolean) 411 */ 412 public void setViewInLineAuthz(Boolean viewInLineAuthz) { 413 initializeComponentSecurity(); 414 415 getFieldSecurity().setViewInLineAuthz(viewInLineAuthz); 416 } 417 418}