View Javadoc

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