Coverage Report - org.kuali.rice.krad.uif.service.impl.AttributeQueryServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
AttributeQueryServiceImpl
0%
0/122
0%
0/82
7.5
 
 1  
 package org.kuali.rice.krad.uif.service.impl;
 2  
 
 3  
 import org.apache.commons.lang.StringUtils;
 4  
 import org.kuali.rice.core.api.config.property.ConfigurationService;
 5  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 6  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 7  
 import org.kuali.rice.krad.service.LookupService;
 8  
 import org.kuali.rice.krad.uif.UifConstants;
 9  
 import org.kuali.rice.krad.uif.container.View;
 10  
 import org.kuali.rice.krad.uif.core.MethodInvokerConfig;
 11  
 import org.kuali.rice.krad.uif.field.AttributeField;
 12  
 import org.kuali.rice.krad.uif.field.AttributeQuery;
 13  
 import org.kuali.rice.krad.uif.field.AttributeQueryResult;
 14  
 import org.kuali.rice.krad.uif.service.AttributeQueryService;
 15  
 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
 16  
 import org.kuali.rice.krad.uif.widget.Suggest;
 17  
 import org.kuali.rice.krad.util.BeanPropertyComparator;
 18  
 
 19  
 import java.text.MessageFormat;
 20  
 import java.util.ArrayList;
 21  
 import java.util.Collection;
 22  
 import java.util.Collections;
 23  
 import java.util.HashMap;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 
 27  
 /**
 28  
  * Implementation of <code>AttributeQueryService</code> that prepares the attribute queries and
 29  
  * delegates to the <code>LookupService</code>
 30  
  *
 31  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 32  
  */
 33  0
 public class AttributeQueryServiceImpl implements AttributeQueryService {
 34  
 
 35  
     private LookupService lookupService;
 36  
     private ConfigurationService configurationService;
 37  
 
 38  
     /**
 39  
      * @see org.kuali.rice.krad.uif.service.AttributeQueryService#performFieldSuggestQuery(
 40  
      *org.kuali.rice.krad.uif.container.View, java.lang.String, java.lang.String, java.util.Map<java.lang.String,
 41  
      *      java.lang.String>)
 42  
      */
 43  
     @Override
 44  
     public AttributeQueryResult performFieldSuggestQuery(View view, String fieldId, String fieldTerm,
 45  
             Map<String, String> queryParameters) {
 46  0
         AttributeQueryResult queryResult = new AttributeQueryResult();
 47  
 
 48  
         // retrieve attribute field from view index
 49  0
         AttributeField attributeField = (AttributeField) view.getViewIndex().getComponentById(fieldId);
 50  0
         if (attributeField == null) {
 51  0
             throw new RuntimeException("Unable to find attribute field instance for id: " + fieldId);
 52  
         }
 53  
 
 54  0
         Suggest fieldSuggest = attributeField.getFieldSuggest();
 55  0
         AttributeQuery suggestQuery = fieldSuggest.getSuggestQuery();
 56  
 
 57  
         // add term as a like criteria
 58  0
         Map<String, String> additionalCriteria = new HashMap<String, String>();
 59  0
         additionalCriteria.put(fieldSuggest.getSourcePropertyName(), fieldTerm + "*");
 60  
 
 61  
         // execute suggest query
 62  0
         Collection<?> results = null;
 63  0
         if (suggestQuery.hasConfiguredMethod()) {
 64  0
             Object queryMethodResult = executeAttributeQueryMethod(view, suggestQuery, queryParameters);
 65  0
             if ((queryMethodResult != null) && (queryMethodResult instanceof Collection<?>)) {
 66  0
                 results = (Collection<?>) queryMethodResult;
 67  
             }
 68  0
         } else {
 69  0
             results = executeAttributeQueryCriteria(suggestQuery, queryParameters, additionalCriteria);
 70  
         }
 71  
 
 72  
         // build list of suggest data from result records
 73  0
         if (results != null) {
 74  0
             List<String> suggestData = new ArrayList<String>();
 75  0
             for (Object result : results) {
 76  0
                 Object suggestFieldValue =
 77  
                         ObjectPropertyUtils.getPropertyValue(result, fieldSuggest.getSourcePropertyName());
 78  0
                 if (suggestFieldValue != null) {
 79  
                     // TODO: need to apply formatter for field or have method in object property utils
 80  0
                     suggestData.add(suggestFieldValue.toString());
 81  
                 }
 82  0
             }
 83  
 
 84  0
             queryResult.setResultData(suggestData);
 85  
         }
 86  
 
 87  0
         return queryResult;
 88  
     }
 89  
 
 90  
     /**
 91  
      * @see org.kuali.rice.krad.uif.service.AttributeQueryService#performFieldQuery(org.kuali.rice.krad.uif.container.View,
 92  
      *      java.lang.String, java.util.Map<java.lang.String,java.lang.String>)
 93  
      */
 94  
     @Override
 95  
     public AttributeQueryResult performFieldQuery(View view, String fieldId, Map<String, String> queryParameters) {
 96  0
         AttributeQueryResult queryResult = new AttributeQueryResult();
 97  
 
 98  
         // retrieve attribute field from view index
 99  0
         AttributeField attributeField = (AttributeField) view.getViewIndex().getComponentById(fieldId);
 100  0
         if (attributeField == null) {
 101  0
             throw new RuntimeException("Unable to find attribute field instance for id: " + fieldId);
 102  
         }
 103  
 
 104  0
         AttributeQuery fieldQuery = attributeField.getFieldAttributeQuery();
 105  0
         if (fieldQuery == null) {
 106  0
             throw new RuntimeException("Field query not defined for field instance with id: " + fieldId);
 107  
         }
 108  
 
 109  
         // execute query and get result
 110  0
         Object resultObject = null;
 111  0
         if (fieldQuery.hasConfiguredMethod()) {
 112  0
             Object queryMethodResult = executeAttributeQueryMethod(view, fieldQuery, queryParameters);
 113  0
             if (queryMethodResult != null) {
 114  
                 // if method returned the result then no further processing needed
 115  0
                 if (queryMethodResult instanceof AttributeQueryResult) {
 116  0
                     return (AttributeQueryResult) queryMethodResult;
 117  
                 }
 118  
 
 119  
                 // if method returned collection, take first record
 120  0
                 if (queryMethodResult instanceof Collection<?>) {
 121  0
                     Collection<?> methodResultCollection = (Collection<?>) queryMethodResult;
 122  0
                     if (!methodResultCollection.isEmpty()) {
 123  0
                         resultObject = methodResultCollection.iterator().next();
 124  
                     }
 125  0
                 } else {
 126  0
                     resultObject = queryMethodResult;
 127  
                 }
 128  
             }
 129  0
         } else {
 130  
             // execute field query as object lookup
 131  0
             Collection<?> results = executeAttributeQueryCriteria(fieldQuery, queryParameters, null);
 132  
 
 133  0
             if ((results != null) && !results.isEmpty()) {
 134  
                 // expect only one returned row for field query
 135  0
                 if (results.size() > 1) {
 136  0
                     throw new RuntimeException("");
 137  
                 }
 138  
 
 139  0
                 resultObject = results.iterator().next();
 140  
             }
 141  
         }
 142  
 
 143  0
         if (resultObject != null) {
 144  
             // build result field data map
 145  0
             Map<String, String> resultFieldData = new HashMap<String, String>();
 146  0
             for (String fromField : fieldQuery.getReturnFieldMapping().keySet()) {
 147  0
                 String returnField = fieldQuery.getReturnFieldMapping().get(fromField);
 148  
 
 149  0
                 String fieldValueStr = "";
 150  0
                 Object fieldValue = ObjectPropertyUtils.getPropertyValue(resultObject, fromField);
 151  0
                 if (fieldValue != null) {
 152  0
                     fieldValueStr = fieldValue.toString();
 153  
                 }
 154  0
                 resultFieldData.put(returnField, fieldValueStr);
 155  0
             }
 156  0
             queryResult.setResultFieldData(resultFieldData);
 157  
 
 158  0
             fieldQuery.setReturnMessageText("");
 159  0
         } else {
 160  
             // add data not found message
 161  0
             if (fieldQuery.isRenderNotFoundMessage()) {
 162  0
                 String messageTemplate =
 163  
                         getConfigurationService().getPropertyValueAsString(
 164  
                                 UifConstants.MessageKeys.QUERY_DATA_NOT_FOUND);
 165  0
                 String message = MessageFormat.format(messageTemplate, attributeField.getLabel());
 166  0
                 fieldQuery.setReturnMessageText(message.toLowerCase());
 167  
             }
 168  
         }
 169  
 
 170  
         // set message and message style classes on query result
 171  0
         queryResult.setResultMessage(fieldQuery.getReturnMessageText());
 172  0
         queryResult.setResultMessageStyleClasses(fieldQuery.getReturnMessageStyleClasses());
 173  
 
 174  0
         return queryResult;
 175  
     }
 176  
 
 177  
     /**
 178  
      * Prepares the method configured on the attribute query then performs the method invocation
 179  
      *
 180  
      * @param view - view instance the field is contained within
 181  
      * @param attributeQuery - attribute query instance to execute
 182  
      * @param queryParameters - map of query parameters that provide values for the method arguments
 183  
      * @return Object type depends on method being invoked, could be AttributeQueryResult in which
 184  
      *         case the method has prepared the return result, or an Object that needs to be parsed for the result
 185  
      */
 186  
     protected Object executeAttributeQueryMethod(View view, AttributeQuery attributeQuery,
 187  
             Map<String, String> queryParameters) {
 188  0
         String queryMethodToCall = attributeQuery.getQueryMethodToCall();
 189  0
         MethodInvokerConfig queryMethodInvoker = attributeQuery.getQueryMethodInvokerConfig();
 190  
 
 191  0
         if (queryMethodInvoker == null) {
 192  0
             queryMethodInvoker = new MethodInvokerConfig();
 193  
         }
 194  
 
 195  
         // if method not set on invoker, use queryMethodToCall, note staticMethod could be set(don't know since
 196  
         // there is not a getter), if so it will override the target method in prepare
 197  0
         if (StringUtils.isBlank(queryMethodInvoker.getTargetMethod())) {
 198  0
             queryMethodInvoker.setTargetMethod(queryMethodToCall);
 199  
         }
 200  
 
 201  
         // if target class or object not set, use view helper service
 202  0
         if ((queryMethodInvoker.getTargetClass() == null) && (queryMethodInvoker.getTargetObject() == null)) {
 203  0
             queryMethodInvoker.setTargetObject(view.getViewHelperService());
 204  
         }
 205  
 
 206  
         // setup query method arguments
 207  0
         Object[] arguments = null;
 208  0
         if ((attributeQuery.getQueryMethodArgumentFieldList() != null) &&
 209  
                 (!attributeQuery.getQueryMethodArgumentFieldList().isEmpty())) {
 210  
             // retrieve argument types for conversion
 211  0
             Class[] argumentTypes = queryMethodInvoker.getArgumentTypes();
 212  0
             if ((argumentTypes == null) ||
 213  
                     (argumentTypes.length != attributeQuery.getQueryMethodArgumentFieldList().size())) {
 214  0
                 throw new RuntimeException(
 215  
                         "Query method argument field list size does not match found method argument list size");
 216  
             }
 217  
 
 218  0
             arguments = new Object[attributeQuery.getQueryMethodArgumentFieldList().size()];
 219  0
             for (int i = 0; i < attributeQuery.getQueryMethodArgumentFieldList().size(); i++) {
 220  0
                 String methodArgumentFromField = attributeQuery.getQueryMethodArgumentFieldList().get(i);
 221  0
                 if (queryParameters.containsKey(methodArgumentFromField)) {
 222  0
                     arguments[i] = queryParameters.get(methodArgumentFromField);
 223  
                 } else {
 224  0
                     arguments[i] = null;
 225  
                 }
 226  
             }
 227  
         }
 228  0
         queryMethodInvoker.setArguments(arguments);
 229  
 
 230  
         try {
 231  0
             queryMethodInvoker.prepare();
 232  
 
 233  0
             return queryMethodInvoker.invoke();
 234  0
         } catch (Exception e) {
 235  0
             throw new RuntimeException("Unable to invoke query method: " + queryMethodInvoker.getTargetMethod(), e);
 236  
         }
 237  
     }
 238  
 
 239  
     /**
 240  
      * Prepares a query using the configured data object, parameters, and criteria, then executes
 241  
      * the query and returns the result Collection
 242  
      *
 243  
      * @param attributeQuery - attribute query instance to perform query for
 244  
      * @param queryParameters - map of parameters that will be used in the query criteria
 245  
      * @param additionalCriteria - map of additional name/value pairs to add to the critiera
 246  
      * @return Collection<?> results of query
 247  
      */
 248  
     protected Collection<?> executeAttributeQueryCriteria(AttributeQuery attributeQuery,
 249  
             Map<String, String> queryParameters, Map<String, String> additionalCriteria) {
 250  0
         Collection<?> results = null;
 251  
 
 252  
         // build criteria for query
 253  0
         Map<String, String> queryCriteria = new HashMap<String, String>();
 254  0
         for (String fieldName : attributeQuery.getQueryFieldMapping().keySet()) {
 255  0
             if (queryParameters.containsKey(fieldName) && StringUtils.isNotBlank(queryParameters.get(fieldName))) {
 256  0
                 queryCriteria.put(fieldName, queryParameters.get(fieldName));
 257  
             }
 258  
         }
 259  
 
 260  
         // add any static criteria
 261  0
         for (String fieldName : attributeQuery.getAdditionalCriteria().keySet()) {
 262  0
             queryCriteria.put(fieldName, attributeQuery.getAdditionalCriteria().get(fieldName));
 263  
         }
 264  
 
 265  
         // add additional criteria
 266  0
         if (additionalCriteria != null) {
 267  0
             queryCriteria.putAll(additionalCriteria);
 268  
         }
 269  
 
 270  0
         Class<?> queryClass = null;
 271  
         try {
 272  0
             queryClass = Class.forName(attributeQuery.getDataObjectClassName());
 273  0
         } catch (ClassNotFoundException e) {
 274  0
             throw new RuntimeException(
 275  
                     "Invalid data object class given for suggest query: " + attributeQuery.getDataObjectClassName(), e);
 276  0
         }
 277  
 
 278  
         // run query
 279  0
         results = getLookupService().findCollectionBySearchUnbounded(queryClass, queryCriteria);
 280  
 
 281  
         // sort results
 282  0
         if (!attributeQuery.getSortPropertyNames().isEmpty() && (results != null) && (results.size() > 1)) {
 283  0
             Collections.sort((List<?>) results, new BeanPropertyComparator(attributeQuery.getSortPropertyNames()));
 284  
         }
 285  
 
 286  0
         return results;
 287  
     }
 288  
 
 289  
     protected LookupService getLookupService() {
 290  0
         if (lookupService == null) {
 291  0
             lookupService = KRADServiceLocatorWeb.getLookupService();
 292  
         }
 293  
 
 294  0
         return lookupService;
 295  
     }
 296  
 
 297  
     public void setLookupService(LookupService lookupService) {
 298  0
         this.lookupService = lookupService;
 299  0
     }
 300  
 
 301  
     protected ConfigurationService getConfigurationService() {
 302  0
         if (configurationService == null) {
 303  0
             configurationService = KRADServiceLocator.getKualiConfigurationService();
 304  
         }
 305  
 
 306  0
         return configurationService;
 307  
     }
 308  
 
 309  
     public void setConfigurationService(ConfigurationService configurationService) {
 310  0
         this.configurationService = configurationService;
 311  0
     }
 312  
 }