View Javadoc
1   /**
2    * Copyright 2005-2015 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.element;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.List;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
24  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
25  import org.kuali.rice.krad.datadictionary.parse.BeanTags;
26  import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
27  import org.kuali.rice.krad.datadictionary.validator.Validator;
28  import org.kuali.rice.krad.uif.UifConstants;
29  import org.kuali.rice.krad.uif.component.Component;
30  import org.kuali.rice.krad.uif.container.Group;
31  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction;
32  import org.kuali.rice.krad.uif.util.ComponentFactory;
33  import org.kuali.rice.krad.uif.util.ComponentUtils;
34  import org.kuali.rice.krad.uif.util.LifecycleElement;
35  import org.kuali.rice.krad.uif.view.View;
36  import org.kuali.rice.krad.uif.widget.Help;
37  import org.kuali.rice.krad.uif.util.LifecycleElement;
38  import org.kuali.rice.krad.util.KRADConstants;
39  
40  /**
41   * Content element that renders a header element and optionally a <code>Group</code> to
42   * present along with the header text
43   *
44   * <p>
45   * Generally the group is used to display content to the right of the header,
46   * such as links for the group or other information
47   * </p>
48   *
49   * @author Kuali Rice Team (rice.collab@kuali.org)
50   */
51  @BeanTags({@BeanTag(name = "header", parent = "Uif-HeaderBase"),
52          @BeanTag(name = "headerOne", parent = "Uif-HeaderOne"),
53          @BeanTag(name = "headerTwo", parent = "Uif-HeaderTwo"),
54          @BeanTag(name = "headerThree", parent = "Uif-HeaderThree"),
55          @BeanTag(name = "headerFour", parent = "Uif-HeaderFour"),
56          @BeanTag(name = "headerFive", parent = "Uif-HeaderFive"),
57          @BeanTag(name = "headerSix", parent = "Uif-HeaderSix"),
58          @BeanTag(name = "pageHeader", parent = "Uif-PageHeader"),
59          @BeanTag(name = "sectionHeader", parent = "Uif-SectionHeader"),
60          @BeanTag(name = "subSectionHeader", parent = "Uif-SubSectionHeader"),
61          @BeanTag(name = "subCollectionHeader", parent = "Uif-SubCollectionHeader")})
62  public class Header extends ContentElementBase {
63      private static final long serialVersionUID = -6950408292923393244L;
64  
65      private String headerText;
66      private String headerLevel;
67  
68      private String headerTagStyle;
69      private List<String> headerTagCssClasses;
70      private boolean headerTagOnly;
71  
72      private Message richHeaderMessage;
73      private List<Component> inlineComponents;
74  
75      private Group upperGroup;
76      private Group rightGroup;
77      private Group lowerGroup;
78  
79      private boolean renderWrapper;
80  
81      public Header() {
82          super();
83  
84          headerTagCssClasses = new ArrayList<String>();
85          renderWrapper = true;
86      }
87  
88      /**
89       * Sets up rich message content for the label, if any exists
90       *
91       * {@inheritDoc}
92       */
93      @Override
94      public void performApplyModel(Object model, LifecycleElement parent) {
95          super.performApplyModel(model, parent);
96  
97          if (richHeaderMessage == null && headerText != null && headerText.contains(
98                  KRADConstants.MessageParsing.LEFT_TOKEN) && headerText.contains(
99                  KRADConstants.MessageParsing.RIGHT_TOKEN)) {
100             Message message = ComponentFactory.getMessage();
101             message.setMessageText(headerText);
102             message.setInlineComponents(inlineComponents);
103             message.setRenderWrapperTag(false);
104             
105             this.setRichHeaderMessage(message);
106         }
107     }
108 
109     /**
110      * The following finalization is performed:
111      *
112      * <ul>
113      * <li>Set render on header group to false if no items are configured</li>
114      * </ul>
115      *
116      * {@inheritDoc}
117      */
118     @Override
119     public void performFinalize(Object model, LifecycleElement parent) {
120         super.performFinalize(model, parent);
121 
122         // don't render header groups if no items were configured
123         if ((getUpperGroup() != null) && (getUpperGroup().getItems().isEmpty())) {
124             getUpperGroup().setRender(false);
125         }
126 
127         if ((getRightGroup() != null) && (getRightGroup().getItems().isEmpty())) {
128             getRightGroup().setRender(false);
129         }
130 
131         if ((getLowerGroup() != null) && (getLowerGroup().getItems().isEmpty())) {
132             getLowerGroup().setRender(false);
133         }
134 
135         //add preset styles to header groups
136         if (getUpperGroup() != null) {
137             getUpperGroup().addStyleClass("uif-header-upperGroup");
138         }
139 
140         if (getRightGroup() != null) {
141             getRightGroup().addStyleClass("uif-header-rightGroup");
142         }
143 
144         if (getLowerGroup() != null) {
145             getLowerGroup().addStyleClass("uif-header-lowerGroup");
146         }
147     }
148 
149     /**
150      * {@inheritDoc}
151      */
152     @Override
153     public List<String> getAdditionalTemplates() {
154         List<String> additionalTemplates = super.getAdditionalTemplates();
155 
156         Object parent = getContext().get(UifConstants.ContextVariableNames.PARENT);
157         
158         Help help = null;
159         if (parent instanceof Group) {
160             help = ((Group) parent).getHelp();
161         } else if (parent instanceof View) {
162             help = ((View) parent).getHelp();
163         }
164         
165         if (help != null) {
166             String helpTemplate = help.getTemplate();
167             if (additionalTemplates.isEmpty()) {
168                 additionalTemplates = new ArrayList<String>();
169             }
170             additionalTemplates.add(helpTemplate);
171         }
172         
173         return additionalTemplates;
174     }
175 
176     /**
177      * Text that should be displayed on the header
178      *
179      * @return header text
180      */
181     @BeanTagAttribute
182     public String getHeaderText() {
183         return this.headerText;
184     }
185 
186     /**
187      * Setter for the header text
188      *
189      * @param headerText
190      */
191     public void setHeaderText(String headerText) {
192         this.headerText = headerText;
193     }
194 
195     /**
196      * HTML header level (h1 ... h6) that should be applied to the header text
197      *
198      * @return header level
199      */
200     @BeanTagAttribute
201     public String getHeaderLevel() {
202         return this.headerLevel;
203     }
204 
205     /**
206      * Setter for the header level
207      *
208      * @param headerLevel
209      */
210     public void setHeaderLevel(String headerLevel) {
211         this.headerLevel = headerLevel;
212     }
213 
214     /**
215      * Style classes that should be applied to the header text (h tag)
216      *
217      * <p>
218      * Note the style class given here applies to only the header text. The
219      * style class property inherited from the <code>Component</code> interface
220      * can be used to set the class for the whole field div (which could
221      * include a nested <code>Group</code>)
222      * </p>
223      *
224      * @return list of style classes
225      * @see org.kuali.rice.krad.uif.component.Component#getCssClasses()
226      */
227     @BeanTagAttribute
228     public List<String> getHeaderTagCssClasses() {
229         return this.headerTagCssClasses;
230     }
231 
232     /**
233      * Setter for the list of classes to apply to the header h tag
234      *
235      * @param headerTagCssClasses
236      */
237     public void setHeaderTagCssClasses(List<String> headerTagCssClasses) {
238         this.headerTagCssClasses = headerTagCssClasses;
239     }
240 
241     /**
242      * Builds the HTML class attribute string by combining the headerStyleClasses list
243      * with a space delimiter
244      *
245      * @return class attribute string
246      */
247     public String getHeaderStyleClassesAsString() {
248         if (headerTagCssClasses != null) {
249             return StringUtils.join(headerTagCssClasses, " ");
250         }
251 
252         return "";
253     }
254 
255     /**
256      * Style that should be applied to the header h tag
257      *
258      * <p>
259      * Note the style given here applies to only the header text. The style
260      * property inherited from the <code>Component</code> interface can be used
261      * to set the style for the whole header div (which could include a nested
262      * <code>Group</code>)
263      * </p>
264      *
265      * @return header style
266      * @see org.kuali.rice.krad.uif.component.Component#getStyle()
267      */
268     @BeanTagAttribute
269     public String getHeaderTagStyle() {
270         return this.headerTagStyle;
271     }
272 
273     /**
274      * Setter for the header h tag style
275      *
276      * @param headerTagStyle
277      */
278     public void setHeaderTagStyle(String headerTagStyle) {
279         this.headerTagStyle = headerTagStyle;
280     }
281 
282     @BeanTagAttribute
283     public boolean isHeaderTagOnly() {
284         return headerTagOnly;
285     }
286 
287     public void setHeaderTagOnly(boolean headerTagOnly) {
288         this.headerTagOnly = headerTagOnly;
289     }
290 
291     /**
292      * Nested group instance that can be used to render contents above the header text
293      *
294      * <p>
295      * The header group is useful for adding content such as links or actions that is presented with the header
296      * </p>
297      *
298      * @return Group instance
299      */
300     @BeanTagAttribute
301     public Group getUpperGroup() {
302         return upperGroup;
303     }
304 
305     /**
306      * Setter for the header group instance that is rendered above the header text
307      *
308      * @param upperGroup
309      */
310     public void setUpperGroup(Group upperGroup) {
311         this.upperGroup = upperGroup;
312     }
313 
314     /**
315      * Nested group instance that can be used to render contents to the right of the header text
316      *
317      * <p>
318      * The header group is useful for adding content such as links or actions that is presented with the header
319      * </p>
320      *
321      * @return Group instance
322      */
323     @BeanTagAttribute
324     public Group getRightGroup() {
325         return rightGroup;
326     }
327 
328     /**
329      * Setter for the header group instance that is rendered to the right of the header text
330      *
331      * @param rightGroup
332      */
333     public void setRightGroup(Group rightGroup) {
334         this.rightGroup = rightGroup;
335     }
336 
337     /**
338      * Nested group instance that can be used to render contents below the header text
339      *
340      * <p>
341      * The header group is useful for adding content such as links or actions that is presented with the header
342      * </p>
343      *
344      * @return Group instance
345      */
346     @BeanTagAttribute
347     public Group getLowerGroup() {
348         return lowerGroup;
349     }
350 
351     /**
352      * Setter for the header group instance that is rendered below the header text
353      *
354      * @param lowerGroup
355      */
356     public void setLowerGroup(Group lowerGroup) {
357         this.lowerGroup = lowerGroup;
358     }
359 
360     /**
361      * List of <code>Component</code> instances contained in the lower header group
362      *
363      * <p>
364      * Convenience method for configuration to get the items List from the
365      * lower header group
366      * </p>
367      *
368      * @return List<? extends Component> items
369      */
370     @ViewLifecycleRestriction
371     @BeanTagAttribute
372     public List<? extends Component> getItems() {
373         if (lowerGroup != null) {
374             return lowerGroup.getItems();
375         }
376 
377         return null;
378     }
379 
380     /**
381      * Setter for the lower group's items
382      *
383      * <p>
384      * Convenience method for configuration to set the items List for the
385      * lower header group
386      * </p>
387      *
388      * @param items
389      */
390     public void setItems(List<? extends Component> items) {
391         if (lowerGroup != null) {
392             lowerGroup.setItems(items);
393         }
394     }
395 
396     /**
397      * Gets the Message that represents the rich message content of the header if headerText is using rich message
398      * tags.
399      * <b>DO NOT set this
400      * property directly unless you need full control over the message structure.</b>
401      *
402      * @return rich message structure, null if no rich message structure
403      */
404     @BeanTagAttribute
405     public Message getRichHeaderMessage() {
406         return richHeaderMessage;
407     }
408 
409     /**
410      * Sets the Message that represents the rich message content of the header if headerText is using rich message
411      * tags.
412      * <b>DO
413      * NOT set this
414      * property directly unless you need full control over the message structure.</b>
415      *
416      * @param richHeaderMessage
417      */
418     public void setRichHeaderMessage(Message richHeaderMessage) {
419         this.richHeaderMessage = richHeaderMessage;
420     }
421 
422     /**
423      * Gets the inlineComponents used by index in a Header that has rich message component index tags in its headerText
424      *
425      * @return the Label's inlineComponents
426      */
427     @BeanTagAttribute
428     public List<Component> getInlineComponents() {
429         return inlineComponents;
430     }
431 
432     /**
433      * Sets the inlineComponents used by index in a Header that has rich message component index tags in its headerText
434      *
435      * @param inlineComponents
436      */
437     public void setInlineComponents(List<Component> inlineComponents) {
438         this.inlineComponents = inlineComponents;
439     }
440 
441     /**
442      * {@inheritDoc}
443      */
444     @Override
445     public void completeValidation(ValidationTrace tracer) {
446         tracer.addBean(this);
447 
448         // Checks that a correct header level is set
449         String headerLevel = getHeaderLevel().toUpperCase();
450         boolean correctHeaderLevel = false;
451         if (headerLevel.compareTo("H1") == 0) {
452             correctHeaderLevel = true;
453         } else if (headerLevel.compareTo("H2") == 0) {
454             correctHeaderLevel = true;
455         } else if (headerLevel.compareTo("H3") == 0) {
456             correctHeaderLevel = true;
457         } else if (headerLevel.compareTo("H4") == 0) {
458             correctHeaderLevel = true;
459         } else if (headerLevel.compareTo("H5") == 0) {
460             correctHeaderLevel = true;
461         } else if (headerLevel.compareTo("H6") == 0) {
462             correctHeaderLevel = true;
463         } else if (headerLevel.compareTo("LABEL") == 0) {
464             correctHeaderLevel = true;
465         }
466         if (!correctHeaderLevel) {
467             String currentValues[] = {"headerLevel =" + getHeaderLevel()};
468             tracer.createError("HeaderLevel must be of values h1, h2, h3, h4, h5, h6, or label", currentValues);
469         }
470 
471         // Checks that header text is set
472         if (getHeaderText() == null) {
473             if (!Validator.checkExpressions(this, "headerText")) {
474                 String currentValues[] = {"headertText =" + getHeaderText()};
475                 tracer.createWarning("HeaderText should be set", currentValues);
476             }
477         }
478 
479         super.completeValidation(tracer.getCopy());
480     }
481 }