Coverage Report - org.kuali.rice.krad.workflow.attribute.DataDictionarySearchableAttribute
 
Classes in this File Line Coverage Branch Coverage Complexity
DataDictionarySearchableAttribute
0%
0/206
0%
0/82
4.333
 
 1  
 /**
 2  
  * Copyright 2005-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  
 package org.kuali.rice.krad.workflow.attribute;
 17  
 
 18  
 import org.apache.commons.collections.CollectionUtils;
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.apache.log4j.Logger;
 21  
 import org.apache.struts.util.MessageResources;
 22  
 import org.apache.struts.util.MessageResourcesFactory;
 23  
 import org.kuali.rice.core.api.uif.RemotableAttributeError;
 24  
 import org.kuali.rice.core.api.uif.RemotableAttributeField;
 25  
 import org.kuali.rice.kew.api.document.DocumentWithContent;
 26  
 import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
 27  
 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
 28  
 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeString;
 29  
 import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
 30  
 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
 31  
 import org.kuali.rice.kew.api.exception.WorkflowException;
 32  
 import org.kuali.rice.kew.api.extension.ExtensionDefinition;
 33  
 import org.kuali.rice.kew.framework.document.attribute.SearchableAttribute;
 34  
 import org.kuali.rice.kew.api.KewApiConstants;
 35  
 import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
 36  
 import org.kuali.rice.kns.document.MaintenanceDocument;
 37  
 import org.kuali.rice.kns.lookup.LookupUtils;
 38  
 import org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl;
 39  
 import org.kuali.rice.kns.maintenance.Maintainable;
 40  
 import org.kuali.rice.kns.service.DictionaryValidationService;
 41  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 42  
 import org.kuali.rice.kns.util.FieldUtils;
 43  
 import org.kuali.rice.kns.web.ui.Field;
 44  
 import org.kuali.rice.kns.web.ui.Row;
 45  
 import org.kuali.rice.krad.bo.BusinessObject;
 46  
 import org.kuali.rice.krad.bo.DocumentHeader;
 47  
 import org.kuali.rice.krad.bo.GlobalBusinessObject;
 48  
 import org.kuali.rice.krad.bo.PersistableBusinessObject;
 49  
 import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
 50  
 import org.kuali.rice.krad.datadictionary.DocumentEntry;
 51  
 import org.kuali.rice.krad.datadictionary.SearchingAttribute;
 52  
 import org.kuali.rice.krad.datadictionary.SearchingTypeDefinition;
 53  
 import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
 54  
 import org.kuali.rice.krad.document.Document;
 55  
 import org.kuali.rice.krad.service.DocumentService;
 56  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 57  
 import org.kuali.rice.krad.service.KRADServiceLocatorInternal;
 58  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 59  
 import org.kuali.rice.krad.util.ErrorMessage;
 60  
 import org.kuali.rice.krad.util.GlobalVariables;
 61  
 import org.kuali.rice.krad.util.KRADPropertyConstants;
 62  
 import org.kuali.rice.krad.util.MessageMap;
 63  
 import org.kuali.rice.krad.util.ObjectUtils;
 64  
 import org.kuali.rice.krad.workflow.service.WorkflowAttributePropertyResolutionService;
 65  
 
 66  
 import java.util.ArrayList;
 67  
 import java.util.LinkedHashMap;
 68  
 import java.util.List;
 69  
 import java.util.Map;
 70  
 
 71  0
 public class DataDictionarySearchableAttribute implements SearchableAttribute {
 72  
 
 73  
     private static final long serialVersionUID = 173059488280366451L;
 74  0
         private static final Logger LOG = Logger.getLogger(DataDictionarySearchableAttribute.class);
 75  
     public static final String DATA_TYPE_BOOLEAN = "boolean";
 76  
 
 77  
     @Override
 78  
     public String generateSearchContent(ExtensionDefinition extensionDefinition,
 79  
             String documentTypeName,
 80  
             WorkflowAttributeDefinition attributeDefinition) {
 81  0
         return "";
 82  
     }
 83  
 
 84  
     @Override
 85  
     public List<DocumentAttribute> extractDocumentAttributes(ExtensionDefinition extensionDefinition,
 86  
             DocumentWithContent documentWithContent) {
 87  0
         List<DocumentAttribute> attributes = new ArrayList<DocumentAttribute>();
 88  
 
 89  0
         String docId = documentWithContent.getDocument().getDocumentId();
 90  
 
 91  0
         DocumentService docService = KRADServiceLocatorWeb.getDocumentService();
 92  0
         Document doc = null;
 93  
         try  {
 94  0
             doc = docService.getByDocumentHeaderIdSessionless(docId);
 95  0
         } catch (WorkflowException we) {
 96  0
                 LOG.error( "Unable to retrieve document " + docId + " in getSearchStorageValues()", we);
 97  0
         }
 98  
 
 99  0
         String attributeValue = "";
 100  0
         if ( doc != null ) {
 101  0
                 if ( doc.getDocumentHeader() != null ) {
 102  0
                 attributeValue = doc.getDocumentHeader().getDocumentDescription();
 103  
                 } else {
 104  0
                         attributeValue = "null document header";
 105  
                 }
 106  
         } else {
 107  0
                     attributeValue = "null document";
 108  
         }
 109  0
         DocumentAttributeString attribute = DocumentAttributeFactory.createStringAttribute("documentDescription", attributeValue);
 110  0
         attributes.add(attribute);
 111  
 
 112  0
         attributeValue = "";
 113  0
         if ( doc != null ) {
 114  0
                 if ( doc.getDocumentHeader() != null ) {
 115  0
                 attributeValue = doc.getDocumentHeader().getOrganizationDocumentNumber();
 116  
                 } else {
 117  0
                         attributeValue = "null document header";
 118  
                 }
 119  
         } else {
 120  0
                     attributeValue = "null document";
 121  
         }
 122  0
         attribute = DocumentAttributeFactory.createStringAttribute("organizationDocumentNumber", attributeValue);
 123  0
         attributes.add(attribute);
 124  
 
 125  0
         if ( doc != null && doc instanceof MaintenanceDocument) {
 126  0
             final Class<? extends BusinessObject> businessObjectClass = getBusinessObjectClass(
 127  
                     documentWithContent.getDocument().getDocumentTypeName());
 128  0
             if (businessObjectClass != null) {
 129  0
                 if (GlobalBusinessObject.class.isAssignableFrom(businessObjectClass)) {
 130  0
                     final GlobalBusinessObject globalBO = retrieveGlobalBusinessObject(docId, businessObjectClass);
 131  
 
 132  0
                     if (globalBO != null) {
 133  0
                         attributes.addAll(findAllDocumentAttributesForGlobalBusinessObject(globalBO));
 134  
                     }
 135  0
                 } else {
 136  0
                     attributes.addAll(parsePrimaryKeyValuesFromDocument(businessObjectClass, (MaintenanceDocument)doc));
 137  
                 }
 138  
 
 139  
             }
 140  
         }
 141  0
         if ( doc != null ) {
 142  0
             DocumentEntry docEntry = (DocumentEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(
 143  
                     documentWithContent.getDocument().getDocumentTypeName());
 144  0
             if ( docEntry != null ) {
 145  0
                         WorkflowAttributes workflowAttributes = docEntry.getWorkflowAttributes();
 146  0
                         WorkflowAttributePropertyResolutionService waprs = KRADServiceLocatorInternal
 147  
                         .getWorkflowAttributePropertyResolutionService();
 148  0
                         attributes.addAll(waprs.resolveSearchableAttributeValues(doc, workflowAttributes));
 149  0
             } else {
 150  0
                     LOG.error("Unable to find DD document entry for document type: " + documentWithContent.getDocument()
 151  
                         .getDocumentTypeName());
 152  
             }
 153  
         }
 154  0
         return attributes;
 155  
     }
 156  
 
 157  
     @Override
 158  
     public List<RemotableAttributeField> getSearchFields(ExtensionDefinition extensionDefinition, String documentTypeName) {
 159  0
         List<Row> searchRows = getSearchingRows(documentTypeName);
 160  0
         return FieldUtils.convertRowsToAttributeFields(searchRows);
 161  
     }
 162  
 
 163  
     /**
 164  
      * Produces legacy KNS rows to use for search attributes.  This method was left intact to help ease conversion
 165  
      * until KNS is replaced with KRAD.
 166  
      */
 167  
     protected List<Row> getSearchingRows(String documentTypeName) {
 168  
 
 169  0
         List<Row> docSearchRows = new ArrayList<Row>();
 170  
 
 171  0
         Class boClass = DocumentHeader.class;
 172  
 
 173  0
         Field descriptionField = FieldUtils.getPropertyField(boClass, "documentDescription", true);
 174  0
         descriptionField.setFieldDataType(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING);
 175  
 
 176  0
         Field orgDocNumberField = FieldUtils.getPropertyField(boClass, "organizationDocumentNumber", true);
 177  0
         orgDocNumberField.setFieldDataType(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING);
 178  
 
 179  0
         List<Field> fieldList = new ArrayList<Field>();
 180  0
         fieldList.add(descriptionField);
 181  0
         docSearchRows.add(new Row(fieldList));
 182  
 
 183  0
         fieldList = new ArrayList<Field>();
 184  0
         fieldList.add(orgDocNumberField);
 185  0
         docSearchRows.add(new Row(fieldList));
 186  
 
 187  
 
 188  0
         DocumentEntry entry = (DocumentEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(documentTypeName);
 189  0
         if (entry  == null)
 190  0
             return docSearchRows;
 191  0
         if (entry instanceof MaintenanceDocumentEntry) {
 192  0
             Class<? extends BusinessObject> businessObjectClass = getBusinessObjectClass(documentTypeName);
 193  0
             Class<? extends Maintainable> maintainableClass = getMaintainableClass(documentTypeName);
 194  
 
 195  0
             KualiGlobalMaintainableImpl globalMaintainable = null;
 196  
             try {
 197  0
                 globalMaintainable = (KualiGlobalMaintainableImpl)maintainableClass.newInstance();
 198  0
                 businessObjectClass = globalMaintainable.getPrimaryEditedBusinessObjectClass();
 199  0
             } catch (Exception ie) {
 200  
                 //was not a globalMaintainable.
 201  0
             }
 202  
 
 203  0
             if (businessObjectClass != null)
 204  0
                 docSearchRows.addAll(createFieldRowsForBusinessObject(businessObjectClass));
 205  
         }
 206  
 
 207  0
         WorkflowAttributes workflowAttributes = entry.getWorkflowAttributes();
 208  0
         if (workflowAttributes != null)
 209  0
             docSearchRows.addAll(createFieldRowsForWorkflowAttributes(workflowAttributes));
 210  
 
 211  0
         return docSearchRows;
 212  
     }
 213  
 
 214  
     @Override
 215  
     public List<RemotableAttributeError> validateDocumentAttributeCriteria(ExtensionDefinition extensionDefinition,
 216  
             DocumentSearchCriteria documentSearchCriteria) {
 217  0
         List<RemotableAttributeError> validationErrors = new ArrayList<RemotableAttributeError>();
 218  0
         DictionaryValidationService validationService = KNSServiceLocator.getDictionaryValidationService();
 219  
 
 220  
         // validate the document attribute values
 221  0
         Map<String, List<String>> documentAttributeValues = documentSearchCriteria.getDocumentAttributeValues();
 222  0
         for (String key : documentAttributeValues.keySet()) {
 223  0
             List<String> values = documentAttributeValues.get(key);
 224  0
             if (CollectionUtils.isNotEmpty(values)) {
 225  0
                 for (String value : values) {
 226  0
                     if (StringUtils.isNotBlank(value)) {
 227  0
                         validationService.validateAttributeFormat(documentSearchCriteria.getDocumentTypeName(), key, value, key);
 228  
                     }
 229  
                 }
 230  
             }
 231  0
         }
 232  
 
 233  
         // can we use KualiConfigurationService?  It seemed to be used elsewhere...
 234  0
         MessageResourcesFactory factory = MessageResourcesFactory.createFactory();
 235  0
         MessageResources messageResources = factory.createResources(null);
 236  
 
 237  0
         if(GlobalVariables.getMessageMap().hasErrors()){
 238  0
                 validationErrors = new ArrayList<RemotableAttributeError>();
 239  0
                 MessageMap deepCopy = (MessageMap)ObjectUtils.deepCopy(GlobalVariables.getMessageMap());
 240  0
             for (String errorKey : deepCopy.getErrorMessages().keySet()) {
 241  0
                 List<ErrorMessage> errorMessages = deepCopy.getErrorMessages().get(errorKey);
 242  0
                 if (CollectionUtils.isNotEmpty(errorMessages)) {
 243  0
                     List<String> errors = new ArrayList<String>();
 244  0
                     for (ErrorMessage errorMessage : errorMessages) {
 245  
                         // need to materialize the message from it's parameters so we can send it back to the framework
 246  0
                         String error = messageResources.getMessage(errorMessage.getErrorKey(), errorMessage.getMessageParameters());
 247  0
                         errors.add(error);
 248  0
                     }
 249  0
                     RemotableAttributeError remotableAttributeError = RemotableAttributeError.Builder.create(errorKey, errors).build();
 250  0
                     validationErrors.add(remotableAttributeError);
 251  
                 }
 252  0
             }
 253  
                 // we should now strip the error messages from the map because they have moved to validationErrors
 254  0
                 GlobalVariables.getMessageMap().clearErrorMessages();
 255  
         }
 256  
 
 257  0
         return validationErrors;
 258  
     }
 259  
 
 260  
     protected List<Row> createFieldRowsForWorkflowAttributes(WorkflowAttributes attrs) {
 261  0
         List<Row> searchFields = new ArrayList<Row>();
 262  
 
 263  0
         List<SearchingTypeDefinition> searchingTypeDefinitions = attrs.getSearchingTypeDefinitions();
 264  0
         final WorkflowAttributePropertyResolutionService propertyResolutionService = KRADServiceLocatorInternal.getWorkflowAttributePropertyResolutionService();
 265  0
         for (SearchingTypeDefinition definition: searchingTypeDefinitions) {
 266  0
             SearchingAttribute attr = definition.getSearchingAttribute();
 267  
 
 268  0
             final String attributeName = attr.getAttributeName();
 269  0
             final String businessObjectClassName = attr.getBusinessObjectClassName();
 270  0
             Class boClass = null;
 271  0
             BusinessObject businessObject  = null;
 272  
             try {
 273  0
                 boClass = Class.forName(businessObjectClassName);
 274  0
                 businessObject = (BusinessObject)boClass.newInstance();
 275  0
             } catch (Exception e) {
 276  0
                 throw new RuntimeException(e);
 277  0
             }
 278  
 
 279  0
             Field searchField = FieldUtils.getPropertyField(boClass, attributeName, false);
 280  0
             searchField.setColumnVisible(attr.isShowAttributeInResultSet());
 281  
 
 282  
             //TODO this is a workaround to hide the Field from the search criteria.
 283  
             //This should be removed once hiding the entire Row is working
 284  0
             if (!attr.isShowAttributeInSearchCriteria()){
 285  0
                 searchField.setFieldType(Field.HIDDEN);
 286  
             }
 287  0
             String fieldDataType = propertyResolutionService.determineFieldDataType(boClass, attributeName);
 288  0
             if (fieldDataType.equals(DataDictionarySearchableAttribute.DATA_TYPE_BOOLEAN)) {
 289  0
                 fieldDataType = KewApiConstants.SearchableAttributeConstants.DATA_TYPE_STRING;
 290  
             }
 291  
 
 292  
             // Allow inline range searching on dates and numbers
 293  0
             if (fieldDataType.equals(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_FLOAT) ||
 294  
                 fieldDataType.equals(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_LONG) ||
 295  
                 fieldDataType.equals(KewApiConstants.SearchableAttributeConstants.DATA_TYPE_DATE)) {
 296  
 
 297  0
                 searchField.setAllowInlineRange(true);
 298  
             }
 299  0
             searchField.setFieldDataType(fieldDataType);
 300  0
             List displayedFieldNames = new ArrayList();
 301  0
             displayedFieldNames.add(attributeName);
 302  0
             LookupUtils.setFieldQuickfinder(businessObject, attributeName, searchField, displayedFieldNames);
 303  
 
 304  0
             List<Field> fieldList = new ArrayList<Field>();
 305  0
             fieldList.add(searchField);
 306  
 
 307  0
             Row row = new Row(fieldList);
 308  0
             if (!attr.isShowAttributeInSearchCriteria()) {
 309  0
                 row.setHidden(true);
 310  
             }
 311  0
             searchFields.add(row);
 312  0
         }
 313  
 
 314  0
         return searchFields;
 315  
     }
 316  
 
 317  
     protected List<DocumentAttribute> parsePrimaryKeyValuesFromDocument(Class<? extends BusinessObject> businessObjectClass, MaintenanceDocument document) {
 318  0
         List<DocumentAttribute> values = new ArrayList<DocumentAttribute>();
 319  
 
 320  0
         final List primaryKeyNames = KNSServiceLocator.getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(businessObjectClass);
 321  
 
 322  0
         for (Object primaryKeyNameAsObj : primaryKeyNames) {
 323  0
             final String primaryKeyName = (String)primaryKeyNameAsObj;
 324  0
             final DocumentAttribute searchableValue = parseSearchableAttributeValueForPrimaryKey(primaryKeyName, businessObjectClass, document);
 325  0
             if (searchableValue != null) {
 326  0
                 values.add(searchableValue);
 327  
             }
 328  0
         }
 329  0
         return values;
 330  
     }
 331  
 
 332  
     /**
 333  
      * Creates a searchable attribute value for the given property name out of the document XML
 334  
      * @param propertyName the name of the property to return
 335  
      * @param businessObjectClass the class of the business object maintained
 336  
      * @param document the document XML
 337  
      * @return a generated SearchableAttributeValue, or null if a value could not be created
 338  
      */
 339  
     protected DocumentAttribute parseSearchableAttributeValueForPrimaryKey(String propertyName, Class<? extends BusinessObject> businessObjectClass, MaintenanceDocument document) {
 340  
 
 341  0
         Maintainable maintainable  = document.getNewMaintainableObject();
 342  0
         PersistableBusinessObject bo = maintainable.getBusinessObject();
 343  
 
 344  0
         final Object propertyValue = ObjectUtils.getPropertyValue(bo, propertyName);
 345  0
         if (propertyValue == null) return null;
 346  
 
 347  0
         final WorkflowAttributePropertyResolutionService propertyResolutionService = KRADServiceLocatorInternal.getWorkflowAttributePropertyResolutionService();
 348  0
         DocumentAttribute value = propertyResolutionService.buildSearchableAttribute(businessObjectClass, propertyName, propertyValue);
 349  0
         return value;
 350  
     }
 351  
 
 352  
     /**
 353  
      * Returns the class of the object being maintained by the given maintenance document type name
 354  
      * @param documentTypeName the name of the document type to look up the maintained business object for
 355  
      * @return the class of the maintained business object
 356  
      */
 357  
     protected Class<? extends BusinessObject> getBusinessObjectClass(String documentTypeName) {
 358  0
         MaintenanceDocumentEntry entry = retrieveMaintenanceDocumentEntry(documentTypeName);
 359  0
         return (entry == null ? null : (Class<? extends BusinessObject>) entry.getDataObjectClass());
 360  
     }
 361  
 
 362  
     /**
 363  
      * Returns the maintainable of the object being maintained by the given maintenance document type name
 364  
      * @param documentTypeName the name of the document type to look up the maintained business object for
 365  
      * @return the Maintainable of the maintained business object
 366  
      */
 367  
     protected Class<? extends Maintainable> getMaintainableClass(String documentTypeName) {
 368  0
         MaintenanceDocumentEntry entry = retrieveMaintenanceDocumentEntry(documentTypeName);
 369  0
         return (entry == null ? null : entry.getMaintainableClass());
 370  
     }
 371  
 
 372  
 
 373  
     /**
 374  
      * Retrieves the maintenance document entry for the given document type name
 375  
      * @param documentTypeName the document type name to look up the data dictionary document entry for
 376  
      * @return the corresponding data dictionary entry for a maintenance document
 377  
      */
 378  
     protected MaintenanceDocumentEntry retrieveMaintenanceDocumentEntry(String documentTypeName) {
 379  0
         return (MaintenanceDocumentEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(documentTypeName);
 380  
     }
 381  
 
 382  
     protected GlobalBusinessObject retrieveGlobalBusinessObject(String documentNumber, Class<? extends BusinessObject> businessObjectClass) {
 383  0
         GlobalBusinessObject globalBO = null;
 384  
 
 385  0
         Map pkMap = new LinkedHashMap();
 386  0
         pkMap.put(KRADPropertyConstants.DOCUMENT_NUMBER, documentNumber);
 387  
 
 388  0
         List returnedBOs = (List) KRADServiceLocator.getBusinessObjectService().findMatching(businessObjectClass, pkMap);
 389  0
         if (returnedBOs.size() > 0) {
 390  0
             globalBO = (GlobalBusinessObject)returnedBOs.get(0);
 391  
         }
 392  
 
 393  0
         return globalBO;
 394  
     }
 395  
 
 396  
     protected List<DocumentAttribute> findAllDocumentAttributesForGlobalBusinessObject(GlobalBusinessObject globalBO) {
 397  0
         List<DocumentAttribute> searchValues = new ArrayList<DocumentAttribute>();
 398  
 
 399  0
         for (PersistableBusinessObject bo : globalBO.generateGlobalChangesToPersist()) {
 400  0
             DocumentAttribute value = generateSearchableAttributeFromChange(bo);
 401  0
             if (value != null) {
 402  0
                 searchValues.add(value);
 403  
             }
 404  0
         }
 405  
 
 406  0
         return searchValues;
 407  
     }
 408  
 
 409  
     protected DocumentAttribute generateSearchableAttributeFromChange(PersistableBusinessObject changeToPersist) {
 410  0
         List<String> primaryKeyNames = KNSServiceLocator.getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(changeToPersist.getClass());
 411  
 
 412  0
         for (Object primaryKeyNameAsObject : primaryKeyNames) {
 413  0
             String primaryKeyName = (String)primaryKeyNameAsObject;
 414  0
             Object value = ObjectUtils.getPropertyValue(changeToPersist, primaryKeyName);
 415  
 
 416  0
             if (value != null) {
 417  0
                 final WorkflowAttributePropertyResolutionService propertyResolutionService = KRADServiceLocatorInternal.getWorkflowAttributePropertyResolutionService();
 418  0
                 DocumentAttribute saValue = propertyResolutionService.buildSearchableAttribute(changeToPersist.getClass(), primaryKeyName, value);
 419  0
                 return saValue;
 420  
             }
 421  0
         }
 422  0
         return null;
 423  
     }
 424  
 
 425  
     /**
 426  
      * Creates a list of search fields, one for each primary key of the maintained business object
 427  
      * @param businessObjectClass the class of the maintained business object
 428  
      * @return a List of KEW search fields
 429  
      */
 430  
     protected List<Row> createFieldRowsForBusinessObject(Class<? extends BusinessObject> businessObjectClass) {
 431  0
         List<Row> searchFields = new ArrayList<Row>();
 432  
 
 433  0
         final List primaryKeyNamesAsObjects = KNSServiceLocator.getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(businessObjectClass);
 434  0
         final BusinessObjectEntry boEntry = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(businessObjectClass.getName());
 435  0
         final WorkflowAttributePropertyResolutionService propertyResolutionService = KRADServiceLocatorInternal.getWorkflowAttributePropertyResolutionService();
 436  0
         for (Object primaryKeyNameAsObject : primaryKeyNamesAsObjects) {
 437  
 
 438  0
             String attributeName =  (String)primaryKeyNameAsObject;
 439  0
             BusinessObject businessObject = null;
 440  
             try {
 441  0
                 businessObject = businessObjectClass.newInstance();
 442  0
             } catch (Exception e) {
 443  0
                 throw new RuntimeException(e);
 444  0
             }
 445  
 
 446  0
             Field searchField = FieldUtils.getPropertyField(businessObjectClass, attributeName, false);
 447  0
             String dataType = propertyResolutionService.determineFieldDataType(businessObjectClass, attributeName);
 448  0
             searchField.setFieldDataType(dataType);
 449  0
             List<Field> fieldList = new ArrayList<Field>();
 450  
 
 451  0
             List displayedFieldNames = new ArrayList();
 452  0
             displayedFieldNames.add(attributeName);
 453  0
             LookupUtils.setFieldQuickfinder(businessObject, attributeName, searchField, displayedFieldNames);
 454  
 
 455  0
             fieldList.add(searchField);
 456  0
             searchFields.add(new Row(fieldList));
 457  0
         }
 458  
 
 459  0
         return searchFields;
 460  
     }
 461  
 
 462  
 }