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.element;
017
018import java.util.List;
019
020import org.apache.commons.lang.StringUtils;
021import org.kuali.rice.krad.datadictionary.parse.BeanTag;
022import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
023import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
024import org.kuali.rice.krad.datadictionary.validator.Validator;
025import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
026import org.kuali.rice.krad.uif.UifConstants;
027import org.kuali.rice.krad.uif.component.Component;
028import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction;
029import org.kuali.rice.krad.uif.util.ComponentFactory;
030import org.kuali.rice.krad.uif.util.LifecycleElement;
031import org.kuali.rice.krad.util.KRADConstants;
032
033/**
034 * Content element that renders a label
035 *
036 * <p>
037 * Contains options for adding a colon to the label along with a required message
038 * </p>
039 *
040 * @author Kuali Rice Team (rice.collab@kuali.org)
041 */
042@BeanTag(name = "label", parent = "Uif-Label")
043public class Label extends ContentElementBase {
044    private static final long serialVersionUID = -6491546893195180114L;
045
046    private String labelText;
047    private String labelForComponentId;
048
049    private boolean renderColon;
050
051    private String requiredIndicator;
052    private boolean renderRequiredIndicator;
053
054    private Message richLabelMessage;
055    private List<Component> inlineComponents;
056
057    public Label() {
058        renderColon = true;
059    }
060
061    /**
062     * Sets up rich message content for the label, if any exists
063     *
064     * {@inheritDoc}
065     */
066    @Override
067    public void performApplyModel(Object model, LifecycleElement parent) {
068        super.performApplyModel(model, parent);
069
070        if (richLabelMessage == null && labelText != null &&
071                labelText.contains(KRADConstants.MessageParsing.LEFT_TOKEN) &&
072                labelText.contains(KRADConstants.MessageParsing.RIGHT_TOKEN)) {
073            Message message = ComponentFactory.getMessage();
074            message.setMessageText(labelText);
075            message.setInlineComponents(inlineComponents);
076            message.setRenderWrapperTag(false);
077
078            this.setRichLabelMessage(message);
079        }
080
081    }
082
083    /**
084     * The following finalization is performed:
085     *
086     * <ul>
087     * <li>If label text is blank, set render to false for field</li>
088     * <li>Set the requiredIndicator</li>
089     * <li>Set the label text on the label field from the field's label property</li>
090     * <li>Set the render property on the label's required message field if this field is marked as required</li>
091     * <li>If the label is hidden then add CSS class to render off screen for accessibility</li>
092     * </ul>
093     *
094     * {@inheritDoc}
095     */
096    @Override
097    public void performFinalize(Object model, LifecycleElement parent) {
098        super.performFinalize(model, parent);
099
100        if (StringUtils.isBlank(getLabelText())) {
101            setRender(false);
102        }
103
104        String defaultRequiredIndicator = (String) KRADServiceLocatorWeb.getDataDictionaryService().getDictionaryBean(
105                UifConstants.REQUIRED_INDICATOR_ID);
106
107        if (requiredIndicator != null && !requiredIndicator.equals(defaultRequiredIndicator)) {
108            this.addDataAttribute(UifConstants.DataAttributes.REQ_INDICATOR, requiredIndicator);
109        } else if (requiredIndicator == null) {
110            requiredIndicator = defaultRequiredIndicator;
111        }
112
113        if ((getRequired() != null) && getRequired().booleanValue()) {
114            setRenderRequiredIndicator(true);
115        }
116
117        // if hidden then add CSS class to render label off screen for accessibility
118        if (this.isHidden()) {
119            this.addStyleClass("sr-only");
120        }
121    }
122
123    /**
124     * Indicates the id for the component the label applies to
125     * <p>
126     * Used for setting the labelFor attribute of the corresponding HTML
127     * element. Note this gets set automatically by the framework during the
128     * initialize phase
129     * </p>
130     *
131     * @return component id
132     */
133    @BeanTagAttribute
134    public String getLabelForComponentId() {
135        return this.labelForComponentId;
136    }
137
138    /**
139     * Setter for the component id the label applies to
140     *
141     * @param labelForComponentId
142     */
143    public void setLabelForComponentId(String labelForComponentId) {
144        this.labelForComponentId = labelForComponentId;
145    }
146
147    /**
148     * Text that will display as the label
149     *
150     * @return label text
151     */
152    @BeanTagAttribute
153    public String getLabelText() {
154        return this.labelText;
155    }
156
157    /**
158     * Setter for the label text
159     *
160     * @param labelText
161     */
162    public void setLabelText(String labelText) {
163        this.labelText = labelText;
164    }
165
166    /**
167     * Indicates whether a colon should be rendered after the label text,
168     * generally used when the label appears to the left of the field's control
169     * or value
170     *
171     * @return true if a colon should be rendered, false if it should not be
172     */
173    @BeanTagAttribute
174    public boolean isRenderColon() {
175        return this.renderColon;
176    }
177
178    /**
179     * Setter for the render colon indicator
180     *
181     * @param renderColon
182     */
183    public void setRenderColon(boolean renderColon) {
184        this.renderColon = renderColon;
185    }
186
187    /**
188     * True if the indicator will be displayed when this label is first render, false otherwise.
189     *
190     * <p>This is set by the framework based on required constraint state, and generally should NOT
191     * be set in most cases.</p>
192     *
193     * @return true if rendering, false otherwise
194     */
195    public boolean isRenderRequiredIndicator() {
196        return renderRequiredIndicator;
197    }
198
199    /**
200     * @see org.kuali.rice.krad.uif.element.Label#isRenderRequiredIndicator()
201     *
202     * @param renderRequiredIndicator
203     */
204    public void setRenderRequiredIndicator(boolean renderRequiredIndicator) {
205        this.renderRequiredIndicator = renderRequiredIndicator;
206    }
207
208    /**
209     * String indicator that will be displayed as a required indicator
210     *
211     * <p>
212     * To indicate a field must have a value (required input) the required
213     * indicator can be set to display an indicator or text along with
214     * the label.
215     * </p>
216     *
217     * @return the required indicator String to display
218     */
219    @BeanTagAttribute
220    public String getRequiredIndicator() {
221        return requiredIndicator;
222    }
223
224    /**
225     * @see org.kuali.rice.krad.uif.element.Label#getRequiredIndicator()
226     *
227     * @param requiredIndicator
228     */
229    public void setRequiredIndicator(String requiredIndicator) {
230        this.requiredIndicator = requiredIndicator;
231    }
232
233    /**
234     * Gets the Message that represents the rich message content of the label if labelText is using rich message tags.
235     * <b>DO NOT set this
236     * property directly unless you need full control over the message structure.</b>
237     *
238     * @return rich message structure, null if no rich message structure
239     */
240    @BeanTagAttribute
241    public Message getRichLabelMessage() {
242        return richLabelMessage;
243    }
244
245    /**
246     * Sets the Message that represents the rich message content of the label if it is using rich message tags.  <b>DO
247     * NOT set this
248     * property directly unless you need full control over the message structure.</b>
249     *
250     * @param richLabelMessage
251     */
252    public void setRichLabelMessage(Message richLabelMessage) {
253        this.richLabelMessage = richLabelMessage;
254    }
255
256    /**
257     * Gets the inlineComponents used by index in a Label that has rich message component index tags in its labelText
258     *
259     * @return the Label's inlineComponents
260     */
261    @ViewLifecycleRestriction
262    @BeanTagAttribute
263    public List<Component> getInlineComponents() {
264        return inlineComponents;
265    }
266
267    /**
268     * Sets the inlineComponents used by index in a Label that has rich message component index tags in its labelText
269     *
270     * @param inlineComponents
271     */
272    public void setInlineComponents(List<Component> inlineComponents) {
273        this.inlineComponents = inlineComponents;
274    }
275
276    /**
277     * {@inheritDoc}
278     */
279    @Override
280    public void completeValidation(ValidationTrace tracer){
281        tracer.addBean(this);
282
283        if(tracer.getValidationStage()== ValidationTrace.BUILD){
284            // Checks that text is set if the component is rendered
285            if(isRender() && getLabelText()==null){
286                if(!Validator.checkExpressions(this, "labelText")) {
287                    String currentValues [] = {"render = "+isRender(),"labelText ="+getLabelText()};
288                    tracer.createError("LabelText should be set if render is true",currentValues);
289                }
290            }
291        }
292
293        super.completeValidation(tracer.getCopy());
294    }
295}