Coverage Report - org.kuali.rice.kns.web.struts.action.KualiInquiryAction
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiInquiryAction
0%
0/192
0%
0/84
3.714
 
 1  
 /*
 2  
  * Copyright 2005-2007 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.apache.struts.action.RedirectingActionForward;
 23  
 import org.kuali.rice.core.api.util.RiceConstants;
 24  
 import org.kuali.rice.core.api.util.RiceKeyConstants;
 25  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 26  
 import org.kuali.rice.kim.util.KimConstants;
 27  
 import org.kuali.rice.kns.inquiry.Inquirable;
 28  
 import org.kuali.rice.kns.util.WebUtils;
 29  
 import org.kuali.rice.kns.web.struts.form.InquiryForm;
 30  
 import org.kuali.rice.kns.web.ui.Field;
 31  
 import org.kuali.rice.kns.web.ui.Row;
 32  
 import org.kuali.rice.kns.web.ui.Section;
 33  
 import org.kuali.rice.krad.bo.Attachment;
 34  
 import org.kuali.rice.krad.bo.BusinessObject;
 35  
 import org.kuali.rice.krad.bo.Exporter;
 36  
 import org.kuali.rice.krad.bo.Note;
 37  
 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
 38  
 import org.kuali.rice.krad.exception.AuthorizationException;
 39  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 40  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 41  
 import org.kuali.rice.krad.service.ModuleService;
 42  
 import org.kuali.rice.krad.service.NoteService;
 43  
 import org.kuali.rice.krad.util.GlobalVariables;
 44  
 import org.kuali.rice.krad.util.KRADConstants;
 45  
 import org.kuali.rice.krad.util.KRADUtils;
 46  
 
 47  
 import javax.servlet.http.HttpServletRequest;
 48  
 import javax.servlet.http.HttpServletResponse;
 49  
 import java.io.ByteArrayOutputStream;
 50  
 import java.io.IOException;
 51  
 import java.lang.reflect.Method;
 52  
 import java.util.Collections;
 53  
 import java.util.List;
 54  
 import java.util.Map;
 55  
 
 56  
 /**
 57  
  * This class handles actions for inquiries of business objects.
 58  
  */
 59  0
 public class KualiInquiryAction extends KualiAction {
 60  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiInquiryAction.class);
 61  
     private NoteService noteService;
 62  
 
 63  
     @Override
 64  
     protected void checkAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
 65  0
         if (!(form instanceof InquiryForm)) {
 66  0
             super.checkAuthorization(form, methodToCall);
 67  
         } else {
 68  
             try {
 69  0
                     if(!KRADConstants.DOWNLOAD_BO_ATTACHMENT_METHOD.equals(methodToCall)){
 70  0
                             Class businessObjectClass = Class.forName(((InquiryForm) form).getBusinessObjectClassName());
 71  0
                             if (!KimApiServiceLocator.getPermissionService().isAuthorizedByTemplateName(GlobalVariables.getUserSession().getPrincipalId(), KRADConstants.KRAD_NAMESPACE, KimConstants.PermissionTemplateNames.INQUIRE_INTO_RECORDS,
 72  
                             KRADUtils.getNamespaceAndComponentSimpleName(businessObjectClass), null)) {
 73  
 
 74  0
                                     throw new AuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(), 
 75  
                                     "inquire",
 76  
                                     businessObjectClass.getSimpleName());
 77  
                             }
 78  
                     }
 79  
             }
 80  0
             catch (ClassNotFoundException e) {
 81  0
                     LOG.warn("Unable to load BusinessObject class: " + ((InquiryForm) form).getBusinessObjectClassName(), e);
 82  0
                 super.checkAuthorization(form, methodToCall);
 83  0
             }
 84  
         }
 85  0
     }
 86  
 
 87  
     @Override
 88  
         protected Map<String, String> getRoleQualification(ActionForm form,
 89  
                         String methodToCall) {
 90  0
                 Map<String, String> roleQualification = super.getRoleQualification(
 91  
                                 form, methodToCall);
 92  0
                 if (form instanceof InquiryForm) {
 93  0
                         Map<String, String> primaryKeys = ((InquiryForm) form)
 94  
                                         .getInquiryPrimaryKeys();
 95  0
                         if (primaryKeys != null) {
 96  0
                                 for (String keyName : primaryKeys.keySet()) {
 97  0
                                         roleQualification.put(keyName, primaryKeys.get(keyName));                                        
 98  
                                 }
 99  
                         }
 100  
                 }
 101  0
                 return roleQualification;
 102  
         }
 103  
 
 104  
         @Override
 105  
     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 106  0
         request.setAttribute(KRADConstants.PARAM_MAINTENANCE_VIEW_MODE, KRADConstants.PARAM_MAINTENANCE_VIEW_MODE_INQUIRY);
 107  0
         return super.execute(mapping, form, request, response);
 108  
     }
 109  
 
 110  
     /**
 111  
      * Gets an inquirable impl from the impl service name parameter. Then calls lookup service to retrieve the record from the
 112  
      * key/value parameters. Finally gets a list of Rows from the inquirable
 113  
      */
 114  
     public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 115  0
         InquiryForm inquiryForm = (InquiryForm) form;
 116  0
         if (inquiryForm.getBusinessObjectClassName() == null) {
 117  0
             LOG.error("Business object name not given.");
 118  0
             throw new RuntimeException("Business object name not given.");
 119  
         }
 120  
         
 121  0
         Class boClass = Class.forName(inquiryForm.getBusinessObjectClassName());
 122  0
         ModuleService responsibleModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(boClass);
 123  0
                 if(responsibleModuleService!=null && responsibleModuleService.isExternalizable(boClass)){
 124  0
                         String redirectUrl = responsibleModuleService.getExternalizableBusinessObjectInquiryUrl(boClass, (Map<String, String[]>) request.getParameterMap());
 125  0
                         ActionForward redirectingActionForward = new RedirectingActionForward(redirectUrl);
 126  0
                         redirectingActionForward.setModule("/");
 127  0
                         return redirectingActionForward;
 128  
                 }
 129  
 
 130  0
                 return continueWithInquiry(mapping, form, request, response);
 131  
     }
 132  
     
 133  
     
 134  
     public ActionForward downloadCustomBOAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 135  0
             String fileName = request.getParameter(KRADConstants.BO_ATTACHMENT_FILE_NAME);
 136  0
                 String contentType = request.getParameter(KRADConstants.BO_ATTACHMENT_FILE_CONTENT_TYPE);
 137  0
                 String fileContentBoField = request.getParameter(KRADConstants.BO_ATTACHMENT_FILE_CONTENT_FIELD);
 138  
             //require certain request properties
 139  0
             if (fileName != null
 140  
                             && contentType != null
 141  
                             && fileContentBoField != null) {
 142  
                     //make sure user has authorization to download attachment
 143  0
                     checkAuthorization(form, findMethodToCall(form, request));
 144  
                     
 145  0
                     fileName = StringUtils.replace(fileName, " ", "_");
 146  
                     
 147  0
                     InquiryForm inquiryForm = (InquiryForm) form;
 148  0
                 BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 149  0
                     checkBO(bo);
 150  
                     
 151  0
                     Class clazz = (bo.getClass());
 152  0
                     Method method = clazz.getMethod("get"+StringUtils.capitalize(fileContentBoField));
 153  0
                     byte[] fileContents = (byte[]) method.invoke(bo);
 154  0
                     streamToResponse(fileContents, fileName, contentType,response);
 155  0
             } else {
 156  0
                     if (fileName == null) {
 157  0
                             LOG.error("Request Parameter \""+ KRADConstants.BO_ATTACHMENT_FILE_NAME + "\" not provided.");
 158  
                     }
 159  0
                     if (contentType == null) {
 160  0
                             LOG.error("Request Parameter \""+ KRADConstants.BO_ATTACHMENT_FILE_CONTENT_TYPE + "\" not provided.");
 161  
                     }
 162  0
                     if (fileContentBoField == null) {
 163  0
                             LOG.error("Request Parameter \""+ KRADConstants.BO_ATTACHMENT_FILE_CONTENT_FIELD + "\" not provided.");
 164  
                     }
 165  
             }
 166  0
             return null;
 167  
     }
 168  
     
 169  
     
 170  
     /**
 171  
      * Downloads the selected attachment to the user's browser
 172  
      *
 173  
      * @param mapping
 174  
      * @param form
 175  
      * @param request
 176  
      * @param response
 177  
      * @return ActionForward
 178  
      * @throws Exception
 179  
      */
 180  
     public ActionForward downloadBOAttachment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 181  0
         Long noteIdentifier = Long.valueOf(request.getParameter(KRADConstants.NOTE_IDENTIFIER));
 182  
 
 183  0
         Note note = this.getNoteService().getNoteByNoteId(noteIdentifier);
 184  0
         if(note != null){
 185  0
                 Attachment attachment = note.getAttachment();
 186  0
                 if(attachment != null){
 187  
                         //make sure attachment is setup with backwards reference to note (rather then doing this we could also just call the attachment service (with a new method that took in the note)
 188  0
                         attachment.setNote(note);
 189  0
                         WebUtils.saveMimeInputStreamAsFile(response, attachment.getAttachmentMimeTypeCode(), attachment.getAttachmentContents(), attachment.getAttachmentFileName(), attachment.getAttachmentFileSize().intValue());
 190  
                 }
 191  0
                 return null;
 192  
         }
 193  
         
 194  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 195  
     }
 196  
     
 197  
     public ActionForward continueWithInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 198  0
             InquiryForm inquiryForm = (InquiryForm) form;
 199  
             
 200  0
             if (inquiryForm.getBusinessObjectClassName() == null) {
 201  0
                     LOG.error("Business object name not given.");
 202  0
                     throw new RuntimeException("Business object name not given.");
 203  
             }
 204  
             
 205  0
         BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 206  0
         checkBO(bo);
 207  
         
 208  0
         populateSections(mapping, request, inquiryForm, bo);
 209  
         
 210  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 211  
     }
 212  
     
 213  
     /**
 214  
      * Turns on (or off) the inactive record display for a maintenance collection.
 215  
      */
 216  
     public ActionForward toggleInactiveRecordDisplay(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 217  0
         InquiryForm inquiryForm = (InquiryForm) form;
 218  0
         if (inquiryForm.getBusinessObjectClassName() == null) {
 219  0
             LOG.error("Business object name not given.");
 220  0
             throw new RuntimeException("Business object name not given.");
 221  
         }
 222  
         
 223  0
         BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 224  0
         checkBO(bo);
 225  
         
 226  0
         Inquirable kualiInquirable = inquiryForm.getInquirable();
 227  
         //////////////////////////////
 228  0
         String collectionName = extractCollectionName(request, KRADConstants.TOGGLE_INACTIVE_METHOD);
 229  0
         if (collectionName == null) {
 230  0
             LOG.error("Unable to get find collection name in request.");
 231  0
             throw new RuntimeException("Unable to get find collection class in request.");
 232  
         }  
 233  0
         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 234  0
         boolean showInactive = Boolean.parseBoolean(StringUtils.substringBetween(parameterName, KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL, "."));
 235  0
         kualiInquirable.setShowInactiveRecords(collectionName, showInactive);
 236  
         //////////////////////////////
 237  
         
 238  0
         populateSections(mapping, request, inquiryForm, bo);
 239  
         
 240  0
         if (showInactive) {
 241  0
                 reopenInactiveRecords(inquiryForm, collectionName);
 242  
         }
 243  
         
 244  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 245  
     }
 246  
     
 247  
     /**
 248  
      * Attempts to reopen sub tabs which would have been closed for inactive records
 249  
      * 
 250  
      * @param inquiryForm the form to reopen records on
 251  
      * @param collectionName the name of the collection reopening
 252  
      */
 253  
     protected void reopenInactiveRecords(InquiryForm inquiryForm, String collectionName) {
 254  0
             for (Object sectionAsObject : inquiryForm.getSections()) {
 255  0
                     final Section section = (Section)sectionAsObject;
 256  0
                     for (Row row: section.getRows()) {
 257  0
                             for (Field field : row.getFields()) {
 258  0
                                     if (field.getFieldType().equals(Field.CONTAINER) && field.getContainerName().startsWith(collectionName)) {
 259  0
                                             final String tabKey = WebUtils.generateTabKey(generateCollectionSubTabName(field));
 260  0
                                             inquiryForm.getTabStates().put(tabKey, "OPEN");
 261  0
                                     }
 262  
                             }
 263  
                     }
 264  0
             }
 265  0
     }
 266  
     
 267  
     /**
 268  
      * Finds a container field's sub tab name
 269  
      * 
 270  
      * @param field the collection sub tab name to  
 271  
      * @return the sub tab name
 272  
      */
 273  
     protected String generateCollectionSubTabName(Field field) {
 274  0
             final String containerName = field.getContainerElementName();
 275  0
             final String cleanedContainerName = 
 276  
                     (containerName == null) ?
 277  
                                     "" :
 278  
                                     containerName.replaceAll("\\d+", "");
 279  0
             StringBuilder subTabName = new StringBuilder(cleanedContainerName);
 280  0
             for (Field containerField : field.getContainerDisplayFields()) {
 281  0
                     subTabName.append(containerField.getPropertyValue());
 282  
             }
 283  0
             return subTabName.toString();
 284  
     }
 285  
     
 286  
     @Override
 287  
     public ActionForward toggleTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 288  0
         InquiryForm inquiryForm = (InquiryForm) form;
 289  0
         if (inquiryForm.getBusinessObjectClassName() == null) {
 290  0
             LOG.error("Business object name not given.");
 291  0
             throw new RuntimeException("Business object name not given.");
 292  
         }
 293  
         
 294  0
         BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 295  0
         checkBO(bo);
 296  
         
 297  0
         populateSections(mapping, request, inquiryForm, bo);
 298  
         
 299  0
         Inquirable kualiInquirable = inquiryForm.getInquirable();
 300  
         
 301  0
         return super.toggleTab(mapping, form, request, response);
 302  
     }
 303  
     
 304  
     
 305  
     
 306  
     /**
 307  
          * @see org.kuali.rice.krad.web.struts.action.KualiAction#hideAllTabs(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 308  
          */
 309  
         @Override
 310  
         public ActionForward hideAllTabs(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 311  
         // KULRICE-2852: Overrides hideAllTabs() so that it also calls the populateSections() method.
 312  0
                 InquiryForm inquiryForm = (InquiryForm) form;
 313  0
         if (inquiryForm.getBusinessObjectClassName() == null) {
 314  0
             LOG.error("Business object name not given.");
 315  0
             throw new RuntimeException("Business object name not given.");
 316  
         }
 317  
         
 318  0
         BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 319  0
         checkBO(bo);
 320  
         
 321  0
         populateSections(mapping, request, inquiryForm, bo);
 322  
                 
 323  0
                 return super.hideAllTabs(mapping, form, request, response);
 324  
         }
 325  
 
 326  
         /**
 327  
          * @see org.kuali.rice.krad.web.struts.action.KualiAction#showAllTabs(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 328  
          */
 329  
         @Override
 330  
         public ActionForward showAllTabs(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 331  
         // KULRICE-2852: Overrides showAllTabs() so that it also calls the populateSections() method.
 332  0
                 InquiryForm inquiryForm = (InquiryForm) form;
 333  0
         if (inquiryForm.getBusinessObjectClassName() == null) {
 334  0
             LOG.error("Business object name not given.");
 335  0
             throw new RuntimeException("Business object name not given.");
 336  
         }
 337  
         
 338  0
         BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 339  0
         checkBO(bo);
 340  
         
 341  0
         populateSections(mapping, request, inquiryForm, bo);
 342  
                 
 343  0
                 return super.showAllTabs(mapping, form, request, response);
 344  
         }
 345  
 
 346  
         /**
 347  
      * Handles exporting the BusinessObject for this Inquiry to XML if it has a custom XML exporter available.
 348  
      */
 349  
     public ActionForward export(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 350  0
             InquiryForm inquiryForm = (InquiryForm) form;
 351  0
             if (inquiryForm.isCanExport()) {
 352  0
                     BusinessObject bo = retrieveBOFromInquirable(inquiryForm);
 353  0
                     checkBO(bo);
 354  0
                     if (bo != null) {
 355  0
                             BusinessObjectEntry businessObjectEntry = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(inquiryForm.getBusinessObjectClassName());
 356  0
                             Class<? extends Exporter> exporterClass = businessObjectEntry.getExporterClass();
 357  0
                             if (exporterClass != null) {
 358  0
                                     Exporter exporter = exporterClass.newInstance();
 359  0
                                 response.setContentType(KRADConstants.XML_MIME_TYPE);
 360  0
                                 response.setHeader("Content-disposition", "attachment; filename=export.xml");
 361  0
                                 exporter.export(businessObjectEntry.getBusinessObjectClass(), Collections.singletonList(bo), KRADConstants.XML_FORMAT, response.getOutputStream());
 362  
                         }
 363  0
                     } else {
 364  
                             //show the empty section with error
 365  0
                             populateSections(mapping, request, inquiryForm, bo);
 366  0
                             return mapping.findForward(RiceConstants.MAPPING_BASIC); 
 367  
                     }
 368  
         }
 369  
         
 370  0
         return null;
 371  
     }
 372  
 
 373  
     /**
 374  
      * Convert a Request into a Map<String,String>. Technically, Request parameters do not neatly translate into a Map of Strings,
 375  
      * because a given parameter may legally appear more than once (so a Map of String[] would be more accurate.) This method should
 376  
      * be safe for business objects, but may not be reliable for more general uses.
 377  
      */
 378  
     protected String extractCollectionName(HttpServletRequest request, String methodToCall) {
 379  
         // collection name and underlying object type from request parameter
 380  0
         String parameterName = (String) request.getAttribute(KRADConstants.METHOD_TO_CALL_ATTRIBUTE);
 381  0
         String collectionName = null;
 382  0
         if (StringUtils.isNotBlank(parameterName)) {
 383  0
             collectionName = StringUtils.substringBetween(parameterName, methodToCall + ".", ".(");
 384  
         }
 385  0
         return collectionName;
 386  
     }
 387  
     
 388  
     protected BusinessObject retrieveBOFromInquirable(InquiryForm inquiryForm) {
 389  0
             Inquirable kualiInquirable = inquiryForm.getInquirable();
 390  
         // retrieve the business object
 391  0
         BusinessObject bo = kualiInquirable.getBusinessObject(inquiryForm.retrieveInquiryDecryptedPrimaryKeys());
 392  0
         if (bo == null) {
 393  0
             LOG.error("No records found in inquiry action.");
 394  0
             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_INQUIRY);
 395  
         }
 396  0
         return bo;
 397  
     }
 398  
     
 399  
     protected void populateSections(ActionMapping mapping, HttpServletRequest request, InquiryForm inquiryForm, BusinessObject bo) {
 400  0
             Inquirable kualiInquirable = inquiryForm.getInquirable();
 401  
             
 402  0
             if (bo != null) {
 403  
                     // get list of populated sections for display
 404  0
                     List sections = kualiInquirable.getSections(bo);
 405  0
                 inquiryForm.setSections(sections);
 406  0
                 kualiInquirable.addAdditionalSections(sections, bo);
 407  0
             } else {
 408  0
                     inquiryForm.setSections(getEmptySections(kualiInquirable.getTitle()));
 409  
             }
 410  
 
 411  0
         request.setAttribute(KRADConstants.INQUIRABLE_ATTRIBUTE_NAME, kualiInquirable);
 412  0
     }
 413  
     
 414  
     /**
 415  
     *
 416  
     * Handy method to stream the byte array to response object
 417  
     * @param attachmentDataSource
 418  
     * @param response
 419  
     * @throws Exception
 420  
     */
 421  
    protected void streamToResponse(byte[] fileContents, String fileName, String fileContentType,HttpServletResponse response) throws Exception{
 422  0
        ByteArrayOutputStream baos = null;
 423  
        try{
 424  0
            baos = new ByteArrayOutputStream(fileContents.length);
 425  0
            baos.write(fileContents);
 426  0
            WebUtils.saveMimeOutputStreamAsFile(response, fileContentType, baos, fileName);
 427  
        }finally{
 428  0
            try{
 429  0
                if(baos!=null){
 430  0
                    baos.close();
 431  0
                    baos = null;
 432  
                }
 433  0
            }catch(IOException ioEx){
 434  0
                LOG.error("Error while downloading attachment");
 435  0
                throw new RuntimeException("IOException occurred while downloading attachment", ioEx);
 436  0
            }
 437  
        }
 438  0
    }
 439  
     /**
 440  
      * Returns a section list with one empty section and one row.
 441  
      * 
 442  
      * @return list of sections
 443  
      */
 444  
     private List<Section> getEmptySections(String title) {
 445  0
             final Row row = new Row(Collections.<Field>emptyList());
 446  
             
 447  0
             final Section section = new Section(Collections.singletonList(row));
 448  0
                 section.setErrorKey("*");
 449  0
                 section.setSectionTitle(title != null ? title : "");
 450  0
                 section.setNumberOfColumns(0);
 451  
                 
 452  0
                 return Collections.singletonList(section);
 453  
     }
 454  
     
 455  
     /**
 456  
      * throws an exception if BO fails the check.
 457  
      * @param bo the BusinessObject to check.
 458  
      * @throws UnsupportedOperationException if BO is null & no messages have been generated.
 459  
      */
 460  
     private void checkBO(BusinessObject bo) {
 461  0
         if (bo == null && GlobalVariables.getMessageMap().hasNoMessages()) {
 462  0
                 throw new UnsupportedOperationException("The record you have inquired on does not exist.");
 463  
         }
 464  0
     }
 465  
     
 466  
     protected NoteService getNoteService() {
 467  0
                 if ( noteService == null ) {
 468  0
                         noteService = KRADServiceLocator.getNoteService();
 469  
                 }
 470  0
                 return this.noteService;
 471  
         }
 472  
 }