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.widget;
17  
18  import java.text.MessageFormat;
19  
20  import org.apache.commons.lang.StringUtils;
21  import org.kuali.rice.core.api.CoreApiServiceLocator;
22  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
23  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
24  import org.kuali.rice.krad.datadictionary.HelpDefinition;
25  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
26  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
27  import org.kuali.rice.krad.datadictionary.uif.UifDictionaryBean;
28  import org.kuali.rice.krad.uif.CssConstants;
29  import org.kuali.rice.krad.uif.UifConstants;
30  import org.kuali.rice.krad.uif.element.Action;
31  import org.kuali.rice.krad.uif.field.InputField;
32  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
33  import org.kuali.rice.krad.uif.util.ComponentFactory;
34  import org.kuali.rice.krad.uif.util.LifecycleElement;
35  import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
36  
37  /**
38   * Widget that renders help on a component
39   *
40   * <p>
41   * If help URL is specified then display help icon and/or if help summary is specified then display help tooltip.
42   * </p>
43   *
44   * @author Kuali Rice Team (rice.collab@kuali.org)
45   */
46  @BeanTag(name = "help", parent = "Uif-Help")
47  public class Help extends WidgetBase {
48  	private static final long serialVersionUID = -1514436681476297241L;
49  
50      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(Help.class);
51  
52      private Action helpAction;
53      private HelpDefinition helpDefinition;
54      private String externalHelpUrl;
55  
56      private String tooltipHelpContent;
57  
58      /**
59       * The following initialization is performed:
60       *
61       * <ul>
62       * <li>If help action not initialized and external help is configured, get the default
63       * help action component</li>
64       * </ul>
65       *
66       * {@inheritDoc}
67       */
68      @Override
69      public void performInitialization(Object model) {
70          super.performInitialization(model);
71  
72          if (helpAction == null) {
73              if(hasValueOrPropertyExpression(externalHelpUrl, this, "externalHelpUrl") ||  (
74                      helpDefinition != null &&
75                              hasValueOrPropertyExpression(helpDefinition.getParameterName(), helpDefinition, "parameterName") &&
76                              hasValueOrPropertyExpression(helpDefinition.getParameterDetailType(), helpDefinition, "parameterDetailType")
77              )){
78                  helpAction = ComponentFactory.getHelpAction();
79                  helpAction.addDataAttribute(UifConstants.DataAttributes.ROLE, "help");
80              }
81          }
82          else{
83              helpAction.addDataAttribute(UifConstants.DataAttributes.ROLE, "help");
84          }
85      }
86  
87      /**
88       * Helper function to check if value or property expression exists
89       *
90       * @param defaultValue
91       * @param dictionaryBean
92       * @param expressionName
93       * @return
94       */
95      private boolean hasValueOrPropertyExpression(String defaultValue, UifDictionaryBean dictionaryBean, String expressionName) {
96          return StringUtils.isNotBlank(defaultValue) || (dictionaryBean != null && dictionaryBean.getPropertyExpressions() != null &&
97                  StringUtils.isNotBlank(dictionaryBean.getPropertyExpression(expressionName)));
98      }
99  
100     /**
101      * Finalize the help widget for usage
102      *
103      * <p>
104      * In addition to the standard finalization the following tasks are performed:
105      * <li>Build the external help Url</li>
106      * <li>Set the javascript action which opens the external help in window</li>
107      * <li>Set render to false if help not configured</li>
108      * </p>
109      *
110      * {@inheritDoc}
111      */
112     @Override
113     public void performFinalize(Object model, LifecycleElement parent) {
114         super.performFinalize(model, parent);
115 
116         buildExternalHelp(parent);
117         buildTooltipHelp(parent);
118 
119         // if help is not configured don't render the component
120         if (StringUtils.isBlank(this.externalHelpUrl) && StringUtils.isBlank(this.tooltipHelpContent)) {
121             setRender(false);
122         }
123 
124         // Change to icon only look and feel if not associated with an input
125         if (parent != null && !(parent instanceof InputField) && helpAction != null) {
126             helpAction.getLibraryCssClasses().remove(CssConstants.Classes.BTN);
127             helpAction.getLibraryCssClasses().remove(CssConstants.Classes.BTN_DEFAULT);
128             helpAction.getLibraryCssClasses().add(CssConstants.Classes.ICON_ONLY_BUTTON);
129         }
130     }
131 
132     /**
133      * Build the external help
134      *
135      * <p>
136      * When the externalHelpUrl is blank and the helpDefinition is specified then the external help URL is
137      * looked up via the helpDefinition from the system parameters.  The namespace in the helpDefinition
138      * does not need to be specified and will default to the namespace of the view.
139      * </p>
140      *
141      * <p>
142      * Set the javascript action to open the external help in a window.
143      * </p>
144      *
145      * <p>
146      * Set the html title attribute of the help icon.
147      * </p>
148      *
149      * @param parent used to get the help title text used in the html title attribute of the help icon
150      */
151     protected void buildExternalHelp(LifecycleElement parent) {
152         if (StringUtils.isBlank(externalHelpUrl) && (helpDefinition != null)) {
153             if (StringUtils.isBlank(helpDefinition.getParameterNamespace())) {
154                 helpDefinition.setParameterNamespace(ViewLifecycle.getView().getNamespaceCode());
155             }
156 
157             String parameterNamespace = helpDefinition.getParameterNamespace();
158             String parameterDetailType = helpDefinition.getParameterDetailType();
159             String parameterName = helpDefinition.getParameterName();
160 
161             ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
162             if (parameterNamespace == null && helpDefinition.getPropertyExpression("parameterNamespace") != null) {
163                 parameterNamespace = (String) expressionEvaluator.evaluateExpression(this.getContext(),
164                         helpDefinition.getPropertyExpression("parameterNamespace"));
165             }
166 
167             if (parameterDetailType == null && helpDefinition.getPropertyExpression("parameterDetailType") != null) {
168                 parameterDetailType = (String) expressionEvaluator.evaluateExpression(this.getContext(),
169                         helpDefinition.getPropertyExpression("parameterDetailType"));
170             }
171 
172             if (parameterName == null && helpDefinition.getPropertyExpression("parameterName") != null) {
173                 parameterName = (String) expressionEvaluator.evaluateExpression(this.getContext(),
174                         helpDefinition.getPropertyExpression("parameterName"));
175             }
176 
177             if (StringUtils.isNotBlank(parameterNamespace)
178                     && StringUtils.isNotBlank(parameterDetailType)
179                     && StringUtils.isNotBlank(parameterName)) {
180                 externalHelpUrl = getParameterService().getParameterValueAsFilteredString(
181                         parameterNamespace, parameterDetailType, parameterName);
182             }
183         }
184 
185         if (StringUtils.isNotBlank(externalHelpUrl)) {
186             // set the javascript action for the external help
187             getHelpAction().setActionScript("openHelpWindow('" + externalHelpUrl + "')");
188 
189             // set the alt and title attribute of the image
190             String helpTitle;
191 
192             // make sure that we are the component's native help and not a misconfigured standalone help bean.
193             if ((parent instanceof Helpable) && (((Helpable) parent).getHelp() == this)) {
194                 helpTitle = MessageFormat.format(
195                         CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
196                                 "help.icon.title.tag.with.field.label"), ((Helpable) parent).getHelpTitle());
197             } else {
198                 helpTitle = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
199                         "help.icon.title.tag");
200             }
201 
202             getHelpAction().setTitle(helpTitle);
203         }
204     }
205 
206     /**
207      * Build the tooltip help
208      *
209      * <p>
210      * The help tooltip is set on the component.  To use the help tooltip bean definition, the help's tooltip is used
211      * as and intermediary for setting up the tooltip widget and then copied to the component.
212      * </p>
213      *
214      * @param parent used for checking misconfigurations
215      */
216     protected void buildTooltipHelp(LifecycleElement parent) {
217         if (StringUtils.isNotBlank(tooltipHelpContent) && this.isRender()) {
218             // make sure that we are the component's native help and not a misconfigured standalone help bean.
219             if (this.getToolTip() != null && (parent instanceof Helpable) 
220                     && (((Helpable) parent).getHelp() == this)) {
221                 this.getToolTip().setTooltipContent(tooltipHelpContent);
222                 ((Helpable) parent).setTooltipOfComponent(this.getToolTip());
223             }
224         }
225     }
226 
227     /**
228      * HelpActionField is used for rendering external help
229      *
230      * @return Action for external help
231      */
232     @BeanTagAttribute
233     public Action getHelpAction() {
234         return helpAction;
235     }
236 
237     /**
238      * Setter for helpAction
239      *
240      * @param helpAction
241      */
242     public void setHelpAction(Action helpAction) {
243         this.helpAction = helpAction;
244     }
245 
246     /**
247      * The help definition is used as the key to retrieve the external help Url from the parameter table of
248      * the database
249      *
250      * @return HelpDefinition
251      */
252     @BeanTagAttribute(type= BeanTagAttribute.AttributeType.DIRECTORBYTYPE)
253     public HelpDefinition getHelpDefinition() {
254         return helpDefinition;
255     }
256 
257     /**
258      * Setter for the help definition of the database.
259      *
260      * @param helpDefinition
261      */
262     public void setHelpDefinition(HelpDefinition helpDefinition) {
263         this.helpDefinition = helpDefinition;
264     }
265 
266     /**
267      * The external help Url
268      *
269      * <p>
270      * This should contain a valid URL.  When specified this URL takes precedence over the external help URL from
271      * the system parameters.
272      * </p>
273      *
274      * @return Url of the external help
275      */
276     @BeanTagAttribute
277     public String getExternalHelpUrl() {
278         return this.externalHelpUrl;
279     }
280 
281     /**
282      * Setter for externalHelpUrl
283      *
284      * @param externalHelpUrl
285      */
286     public void setExternalHelpUrl(String externalHelpUrl) {
287         this.externalHelpUrl = externalHelpUrl;
288     }
289 
290     /**
291      * TooltipHelpContent
292      *
293      * @return TooltipHelpContent
294      */
295     @BeanTagAttribute
296     public String getTooltipHelpContent() {
297         return this.tooltipHelpContent;
298     }
299 
300     /**
301      * Setter for tooltipHelpContent
302      *
303      * @param tooltipHelpContent
304      */
305     public void setTooltipHelpContent(String tooltipHelpContent) {
306         this.tooltipHelpContent = tooltipHelpContent;
307     }
308 
309     /**
310      * Retrieve the parameter service
311      *
312      * @return ParameterService
313      */
314     protected ParameterService getParameterService() {
315         return CoreFrameworkServiceLocator.getParameterService();
316     }
317 }