View Javadoc

1   /**
2    * Copyright 2005-2012 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.kns.web.struts.action;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.ActionForm;
20  import org.apache.struts.action.ActionForward;
21  import org.apache.struts.action.ActionMapping;
22  import org.kuali.rice.core.api.config.property.ConfigContext;
23  import org.kuali.rice.core.api.config.property.ConfigurationService;
24  import org.kuali.rice.core.api.util.RiceConstants;
25  import org.kuali.rice.core.api.util.RiceKeyConstants;
26  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
27  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
28  import org.kuali.rice.kew.api.KewApiServiceLocator;
29  import org.kuali.rice.kew.api.doctype.DocumentType;
30  import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
31  import org.kuali.rice.kns.datadictionary.HeaderNavigation;
32  import org.kuali.rice.kns.datadictionary.KNSDocumentEntry;
33  import org.kuali.rice.kns.datadictionary.LookupDefinition;
34  import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
35  import org.kuali.rice.kns.service.KNSServiceLocator;
36  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
37  import org.kuali.rice.kns.web.struts.form.KualiHelpForm;
38  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
39  import org.kuali.rice.krad.datadictionary.DataDictionary;
40  import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
41  import org.kuali.rice.krad.datadictionary.HelpDefinition;
42  import org.kuali.rice.krad.service.DataDictionaryService;
43  import org.kuali.rice.krad.service.KRADServiceLocator;
44  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
45  import org.kuali.rice.krad.util.KRADConstants;
46  
47  import javax.servlet.http.HttpServletRequest;
48  import javax.servlet.http.HttpServletResponse;
49  
50  /**
51   * This class handles requests for help text.
52   * 
53   * 
54   */
55  public class KualiHelpAction extends KualiAction {
56      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiHelpAction.class);
57  
58      private static final String VALIDATION_PATTERN_STRING = "ValidationPattern";
59      private static final String NO = "No";
60      private static final String YES = "Yes";
61      static final String DEFAULT_LOOKUP_HELP_TEXT_RESOURCE_KEY = "lookupHelpText";
62      
63      private static DataDictionaryService dataDictionaryService;
64      private static ConfigurationService kualiConfigurationService;
65      private static ParameterService parameterService;
66      private static MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
67  
68      private DataDictionaryService getDataDictionaryService() {
69          if ( dataDictionaryService == null ) {
70              dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
71          }
72          return dataDictionaryService;
73      }
74      private ConfigurationService getConfigurationService() {
75          if ( kualiConfigurationService == null ) {
76              kualiConfigurationService = KRADServiceLocator.getKualiConfigurationService();
77          }
78          return kualiConfigurationService;
79      }
80      private ParameterService getParameterService() {
81          if ( parameterService == null ) {
82              parameterService = CoreFrameworkServiceLocator.getParameterService();
83          }
84          return parameterService;
85      }
86  
87      private MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
88          if ( maintenanceDocumentDictionaryService == null ) {
89              maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
90          }
91          return maintenanceDocumentDictionaryService;
92      }
93      
94      /**
95       * Convenience method for accessing <code>{@link DataDictionaryEntry}</code> for the given business object
96       * 
97       * @param businessObjectClassName
98       * @return DataDictionaryEntry
99       */
100     private DataDictionaryEntry getDataDictionaryEntry(String businessObjectClassName) {
101         return getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(businessObjectClassName);
102     }
103 
104     /**
105      * Convenience method for accessing the <code>{@link AttributeDefinition}</code> for a specific business object attribute
106      * defined in the DataDictionary.
107      * 
108      * @param businessObjectClassName
109      * @param attributeName
110      * @return AttributeDefinition
111      */
112     private AttributeDefinition getAttributeDefinition(String businessObjectClassName, String attributeName) throws ClassNotFoundException {
113         AttributeDefinition retval = null;
114 
115         if (getDataDictionaryEntry(businessObjectClassName) != null) {
116             retval = getDataDictionaryEntry(businessObjectClassName).getAttributeDefinition(attributeName);
117         }
118         return retval;
119     }
120 
121     /**
122      * @param attribute <code>{@link AttributeDefinition}</code>
123      * @return String
124      */
125     private String getAttributeMaxLength(AttributeDefinition attribute) throws Exception {
126         return attribute.getMaxLength().toString();
127     }
128 
129     /**
130      * @param attribute <code>{@link AttributeDefinition}</code>
131      * @return String
132      */
133     private String getAttributeValidationPatternName(AttributeDefinition attribute) throws Exception {
134         String retval = new String();
135         if (attribute.getValidationPattern() != null) {
136             retval = attribute.getValidationPattern().getClass().getName();
137         }
138 
139         if (retval.indexOf(".") > 0) {
140             retval = retval.substring(retval.lastIndexOf(".") + 1);
141         }
142         if (retval.endsWith(VALIDATION_PATTERN_STRING)) {
143             retval = retval.substring(0, retval.lastIndexOf(VALIDATION_PATTERN_STRING));
144         }
145 
146         return retval;
147     }
148 
149     /**
150      * Retrieves help information from the data dictionary for the business object attribute.
151      * 
152      * @return ActionForward
153      */
154     public ActionForward getAttributeHelpText(ActionMapping mapping, KualiHelpForm helpForm, HttpServletRequest request, HttpServletResponse response) throws Exception {
155 
156         AttributeDefinition attribute;
157 
158         if (StringUtils.isBlank(helpForm.getBusinessObjectClassName()) || StringUtils.isBlank(helpForm.getAttributeName())) {
159             throw new RuntimeException("Business object and attribute name not specified.");
160         }
161         attribute = getAttributeDefinition(helpForm.getBusinessObjectClassName(), helpForm.getAttributeName());
162 
163         if ( LOG.isDebugEnabled() ) {
164             LOG.debug( "Request for help on: " + helpForm.getBusinessObjectClassName() + " -- " + helpForm.getAttributeName() );
165             LOG.debug( "  attribute: " + attribute );
166         }
167                 
168         if (attribute == null || StringUtils.isBlank(attribute.getSummary())) {
169             helpForm.setResourceKey(RiceKeyConstants.MESSAGE_NO_HELP_TEXT);
170             return getResourceHelpText(mapping, helpForm, request, response);
171         }
172 
173         boolean required = attribute.isRequired().booleanValue();
174         // KULRNE-4392 - pull the required attribute on BO maintenance documents from the document def rather than the BO
175         try {
176             Class boClass = Class.forName( helpForm.getBusinessObjectClassName() );
177             String docTypeName = getMaintenanceDocumentDictionaryService().getDocumentTypeName( boClass );
178             if (StringUtils.isNotBlank(docTypeName)) {
179                 // maybe it's not a maint doc
180                 MaintainableFieldDefinition field = getMaintenanceDocumentDictionaryService().getMaintainableField( docTypeName, helpForm.getAttributeName() );
181                 if ( field != null ) {
182                     required = field.isRequired();
183                 }
184             }
185             else {
186                 if (log.isInfoEnabled()) {
187                     log.info("BO class " + boClass.getName() + " does not have a maint doc definition.  Defaulting to using DD for definition");
188                 }
189             }
190         } catch ( ClassNotFoundException ex ) {
191             // do nothing
192             LOG.warn( "Unable to obtain maintainable field for BO property.", ex );
193         }
194         
195         helpForm.setHelpLabel(attribute.getLabel());
196         helpForm.setHelpSummary(attribute.getSummary());
197         helpForm.setHelpDescription(attribute.getDescription());
198         helpForm.setHelpRequired(required?YES:NO);
199         helpForm.setHelpMaxLength(getAttributeMaxLength(attribute));
200         helpForm.setValidationPatternName(getAttributeValidationPatternName(attribute));
201 
202         return mapping.findForward(RiceConstants.MAPPING_BASIC);
203     }
204 
205     /**
206      * Retrieves help information from the data dictionary for the business object attribute.
207      * 
208      * @return ActionForward
209      */
210     public ActionForward getAttributeHelpText(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
211         return getAttributeHelpText(mapping, (KualiHelpForm) form, request, response);
212     }
213 
214     /**
215      * Retrieves help information from the data dictionary for the document type.
216      */
217     public ActionForward getDocumentHelpText(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
218         KualiHelpForm helpForm = (KualiHelpForm) form;
219 
220         String documentTypeName = helpForm.getDocumentTypeName();
221 
222         if (StringUtils.isBlank(documentTypeName)) {
223             throw new RuntimeException("Document type name not specified.");
224         }
225 
226         DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
227         org.kuali.rice.krad.datadictionary.DocumentEntry entry = (org.kuali.rice.krad.datadictionary.DocumentEntry ) dataDictionary.getDocumentEntry(documentTypeName);
228 
229         String label = "";
230         String summary = "";
231         String description = "";
232         HelpDefinition helpDefinition = null;
233         String apcHelpUrl = null;
234         if (entry != null) {
235             DocumentType docType = KewApiServiceLocator.getDocumentTypeService().getDocumentTypeByName(entry.getDocumentTypeName());
236             label = docType.getLabel();
237             description = docType.getDescription();
238             if (StringUtils.isNotBlank(docType.getHelpDefinitionUrl())) {
239             	apcHelpUrl = ConfigContext.getCurrentContextConfig().getProperty("externalizable.help.url") + docType.getHelpDefinitionUrl();
240             }
241         }
242 
243         if ( StringUtils.isNotBlank(apcHelpUrl) ) {
244             response.sendRedirect(apcHelpUrl);
245             return null;
246         }
247 
248         helpForm.setHelpLabel(label);
249         helpForm.setHelpSummary(summary);
250         helpForm.setHelpDescription(description);
251         helpForm.setHelpDefinition(helpDefinition);
252 
253         return mapping.findForward(RiceConstants.MAPPING_BASIC);
254     }
255 
256     /**
257      * Retrieves help information from the data dictionary for the document type.
258      */
259     public ActionForward getBusinessObjectHelpText(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
260         KualiHelpForm helpForm = (KualiHelpForm) form;
261 
262         String objectClassName = helpForm.getBusinessObjectClassName();
263 
264         if (StringUtils.isBlank(objectClassName)) {
265             throw new RuntimeException("Document type name not specified.");
266         }
267 
268         DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
269         BusinessObjectEntry entry = (BusinessObjectEntry) dataDictionary.getBusinessObjectEntry(objectClassName);
270 
271         HelpDefinition helpDefinition = null;
272         String apcHelpUrl = null;
273         String label = "";
274         String objectDescription = "";
275         if (entry != null) {
276             helpDefinition = entry.getHelpDefinition();
277             label = entry.getObjectLabel();
278             objectDescription = entry.getObjectDescription();
279             if (null != helpDefinition && null != helpDefinition.getParameterNamespace() && null != helpDefinition.getParameterDetailType() && null != helpDefinition.getParameterName()) {
280                 apcHelpUrl = getHelpUrl(helpDefinition.getParameterNamespace(), helpDefinition.getParameterDetailType(), helpDefinition.getParameterName());
281                 }
282                 }
283 
284         if ( !StringUtils.isBlank(apcHelpUrl) ) {
285             response.sendRedirect(apcHelpUrl);
286             return null;
287         }
288         helpForm.setHelpLabel(label);
289         helpForm.setHelpDescription(objectDescription);
290 
291         return mapping.findForward(RiceConstants.MAPPING_BASIC);
292     }
293     
294     /**
295      * Retrieves help information from the data dictionary for the document type.
296      */
297     public ActionForward getPageHelpText(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
298         KualiHelpForm helpForm = (KualiHelpForm) form;
299 
300         String documentTypeName = helpForm.getDocumentTypeName();
301         String pageName = helpForm.getPageName();
302 
303         if (StringUtils.isBlank(documentTypeName)) {
304             throw new RuntimeException("Document type name not specified.");
305         }
306         
307         if (StringUtils.isBlank(pageName)) {
308             throw new RuntimeException("Page name not specified.");
309         }
310 
311         DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
312         KNSDocumentEntry entry = (KNSDocumentEntry) dataDictionary.getDocumentEntry(documentTypeName);
313 
314         String apcHelpUrl = null;
315         String label = "";
316         String objectDescription = "";
317         if (entry != null) {
318             for ( HeaderNavigation headerNavigation : entry.getHeaderNavigationList() ) {
319                 if (headerNavigation.getHeaderTabDisplayName().equals(pageName)) {
320                     HelpDefinition helpDefinition = headerNavigation.getHelpDefinition();
321                     if (null != helpDefinition && null != helpDefinition.getParameterNamespace() && null != helpDefinition.getParameterDetailType() && null != helpDefinition.getParameterName()) {
322                         apcHelpUrl = getHelpUrl(helpDefinition.getParameterNamespace(), helpDefinition.getParameterDetailType(), helpDefinition.getParameterName());
323                     }
324                 }
325             }
326         }
327 
328         if ( !StringUtils.isBlank(apcHelpUrl) ) {
329             response.sendRedirect(apcHelpUrl);
330             return null;
331         }
332         helpForm.setHelpLabel(pageName);
333         helpForm.setHelpDescription("No help content available.");
334 
335         return mapping.findForward(RiceConstants.MAPPING_BASIC);
336     }
337     
338     /**
339      * Retrieves help content to link to based on security group/parameter
340      */
341     public ActionForward getStoredHelpUrl(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
342         KualiHelpForm helpForm = (KualiHelpForm) form;
343         
344         String helpParameterNamespace = helpForm.getHelpParameterNamespace();
345         String helpParameterDetailType = helpForm.getHelpParameterDetailType();
346         String helpParameterName = helpForm.getHelpParameterName();
347         
348         if (StringUtils.isBlank(helpParameterNamespace)) {
349             throw new RuntimeException("Parameter Namespace not specified.");
350         }
351         
352         if (StringUtils.isBlank(helpParameterDetailType)) {
353             throw new RuntimeException("Detail Type not specified.");
354         }
355 
356         if (StringUtils.isBlank(helpParameterName)) {
357             throw new RuntimeException("Parameter Name not specified.");
358         }
359         
360         String apcHelpUrl = getHelpUrl(helpParameterNamespace, helpParameterDetailType, helpParameterName);
361         
362         if ( !StringUtils.isBlank(apcHelpUrl) ) {
363             response.sendRedirect(apcHelpUrl);
364             return null;
365         }
366         
367         helpForm.setHelpDescription("No help content available.");
368         return mapping.findForward(RiceConstants.MAPPING_BASIC);
369     }
370 
371     /**
372      * Retrieves help information from resources by key.
373      */
374     public ActionForward getResourceHelpText(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
375         KualiHelpForm helpForm = (KualiHelpForm) form;
376 
377         String resourceKey = helpForm.getResourceKey();
378         populateHelpFormForResourceText(helpForm, resourceKey);
379 
380         return mapping.findForward(RiceConstants.MAPPING_BASIC);
381     }
382     
383     /**
384      * Utility method that populates a KualiHelpForm with the description from a given resource key
385      * @param helpForm the KualiHelpForm to populate with help text
386      * @param resourceKey the resource key to use as help text
387      */
388     protected void populateHelpFormForResourceText(KualiHelpForm helpForm, String resourceKey) {
389     	if (StringUtils.isBlank(resourceKey)) {
390             throw new RuntimeException("Help resource key not specified.");
391         }
392 
393         helpForm.setHelpLabel("");
394         helpForm.setHelpSummary("");
395         helpForm.setHelpDescription(getConfigurationService().getPropertyValueAsString(resourceKey));
396     }
397     
398     /**
399      * Retrieves help for a lookup
400      */
401     public ActionForward getLookupHelpText(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
402     	KualiHelpForm helpForm = (KualiHelpForm) form;
403 
404         // handle doc search custom help urls
405     	if (!StringUtils.isEmpty(helpForm.getSearchDocumentTypeName())) {
406     	    DocumentType docType = KewApiServiceLocator.getDocumentTypeService().getDocumentTypeByName(helpForm.getSearchDocumentTypeName());
407     	    if (!StringUtils.isEmpty(docType.getDocSearchHelpUrl())) {
408     	        String docSearchHelpUrl = ConfigContext.getCurrentContextConfig().getProperty("externalizable.help.url") + docType.getDocSearchHelpUrl();
409 
410     	        if ( StringUtils.isNotBlank(docSearchHelpUrl) ) {
411     	            response.sendRedirect(docSearchHelpUrl);
412     	            return null;
413     	        }
414     	    }
415     	}
416 
417     	final String lookupBusinessObjectClassName = helpForm.getLookupBusinessObjectClassName();
418     	if (!StringUtils.isBlank(lookupBusinessObjectClassName)) {
419     		final DataDictionary dataDictionary = getDataDictionaryService().getDataDictionary();
420     		final BusinessObjectEntry entry = (BusinessObjectEntry) dataDictionary.getBusinessObjectEntry(lookupBusinessObjectClassName);
421     		final LookupDefinition lookupDefinition = entry.getLookupDefinition();
422     		
423     		if (lookupDefinition != null) {
424     			if (lookupDefinition.getHelpDefinition() != null && !StringUtils.isBlank(lookupDefinition.getHelpDefinition().getParameterNamespace()) && !StringUtils.isBlank(lookupDefinition.getHelpDefinition().getParameterDetailType()) && !StringUtils.isBlank(lookupDefinition.getHelpDefinition().getParameterName())) {
425     				final String apcHelpUrl = getHelpUrl(lookupDefinition.getHelpDefinition().getParameterNamespace(), lookupDefinition.getHelpDefinition().getParameterDetailType(), lookupDefinition.getHelpDefinition().getParameterName());
426     		        
427     		        if ( !StringUtils.isBlank(apcHelpUrl) ) {
428     		            response.sendRedirect(apcHelpUrl);
429     		            return null;
430     		        }
431     			} else if (!StringUtils.isBlank(lookupDefinition.getHelpUrl())) {
432     				final String apcHelpUrl = ConfigContext.getCurrentContextConfig().getProperty("externalizable.help.url")+lookupDefinition.getHelpUrl();
433     				response.sendRedirect(apcHelpUrl);
434     				return null;
435     			}
436     		}
437     	}
438     	
439     	// still here?  guess we're defaulting...
440     	populateHelpFormForResourceText(helpForm, getDefaultLookupHelpResourceKey());
441         return mapping.findForward(RiceConstants.MAPPING_BASIC);
442     }
443     
444     /**
445      * @return the key of the default lookup help resource text
446      */
447     protected String getDefaultLookupHelpResourceKey() {
448     	return KualiHelpAction.DEFAULT_LOOKUP_HELP_TEXT_RESOURCE_KEY;
449     }
450 
451     private String getHelpUrl(String parameterNamespace, String parameterDetailTypeCode, String parameterName) {
452         return getConfigurationService().getPropertyValueAsString(KRADConstants.EXTERNALIZABLE_HELP_URL_KEY) + getParameterService().getParameterValueAsString(parameterNamespace, parameterDetailTypeCode, parameterName);
453     }    
454     
455     /**
456      * Retrieves help content to link to based on parameterNamespace and parameterName
457      */
458     public ActionForward getHelpUrlByNamespace(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
459         KualiHelpForm helpForm = (KualiHelpForm) form;
460        return getStoredHelpUrl(mapping, form, request, response); 
461     }
462 }