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().getPropertyString(UifConstants.MessageKeys.QUERY_DATA_NOT_FOUND);
 164  0
                 String message = MessageFormat.format(messageTemplate, attributeField.getLabel());
 165  0
                 fieldQuery.setReturnMessageText(message.toLowerCase());
 166  
             }
 167  
         }
 168  
 
 169  
         // set message and message style classes on query result
 170  0
         queryResult.setResultMessage(fieldQuery.getReturnMessageText());
 171  0
         queryResult.setResultMessageStyleClasses(fieldQuery.getReturnMessageStyleClasses());
 172  
 
 173  0
         return queryResult;
 174  
     }
 175  
 
 176  
     /**
 177  
      * Prepares the method configured on the attribute query then performs the method invocation
 178  
      *
 179  
      * @param view - view instance the field is contained within
 180  
      * @param attributeQuery - attribute query instance to execute
 181  
      * @param queryParameters - map of query parameters that provide values for the method arguments
 182  
      * @return Object type depends on method being invoked, could be AttributeQueryResult in which
 183  
      *         case the method has prepared the return result, or an Object that needs to be parsed for the result
 184  
      */
 185  
     protected Object executeAttributeQueryMethod(View view, AttributeQuery attributeQuery,
 186  
             Map<String, String> queryParameters) {
 187  0
         String queryMethodToCall = attributeQuery.getQueryMethodToCall();
 188  0
         MethodInvokerConfig queryMethodInvoker = attributeQuery.getQueryMethodInvokerConfig();
 189  
 
 190  0
         if (queryMethodInvoker == null) {
 191  0
             queryMethodInvoker = new MethodInvokerConfig();
 192  
         }
 193  
 
 194  
         // if method not set on invoker, use queryMethodToCall, note staticMethod could be set(don't know since
 195  
         // there is not a getter), if so it will override the target method in prepare
 196  0
         if (StringUtils.isBlank(queryMethodInvoker.getTargetMethod())) {
 197  0
             queryMethodInvoker.setTargetMethod(queryMethodToCall);
 198  
         }
 199  
 
 200  
         // if target class or object not set, use view helper service
 201  0
         if ((queryMethodInvoker.getTargetClass() == null) && (queryMethodInvoker.getTargetObject() == null)) {
 202  0
             queryMethodInvoker.setTargetObject(view.getViewHelperService());
 203  
         }
 204  
 
 205  
         // setup query method arguments
 206  0
         Object[] arguments = null;
 207  0
         if ((attributeQuery.getQueryMethodArgumentFieldList() != null) &&
 208  
                 (!attributeQuery.getQueryMethodArgumentFieldList().isEmpty())) {
 209  
             // retrieve argument types for conversion
 210  0
             Class[] argumentTypes = queryMethodInvoker.getArgumentTypes();
 211  0
             if ((argumentTypes == null) ||
 212  
                     (argumentTypes.length != attributeQuery.getQueryMethodArgumentFieldList().size())) {
 213  0
                 throw new RuntimeException(
 214  
                         "Query method argument field list size does not match found method argument list size");
 215  
             }
 216  
 
 217  0
             arguments = new Object[attributeQuery.getQueryMethodArgumentFieldList().size()];
 218  0
             for (int i = 0; i < attributeQuery.getQueryMethodArgumentFieldList().size(); i++) {
 219  0
                 String methodArgumentFromField = attributeQuery.getQueryMethodArgumentFieldList().get(i);
 220  0
                 if (queryParameters.containsKey(methodArgumentFromField)) {
 221  0
                     arguments[i] = queryParameters.get(methodArgumentFromField);
 222  
                 } else {
 223  0
                     arguments[i] = null;
 224  
                 }
 225  
             }
 226  
         }
 227  0
         queryMethodInvoker.setArguments(arguments);
 228  
 
 229  
         try {
 230  0
             queryMethodInvoker.prepare();
 231  
 
 232  0
             return queryMethodInvoker.invoke();
 233  0
         } catch (Exception e) {
 234  0
             throw new RuntimeException("Unable to invoke query method: " + queryMethodInvoker.getTargetMethod(), e);
 235  
         }
 236  
     }
 237  
 
 238  
     /**
 239  
      * Prepares a query using the configured data object, parameters, and criteria, then executes
 240  
      * the query and returns the result Collection
 241  
      *
 242  
      * @param attributeQuery - attribute query instance to perform query for
 243  
      * @param queryParameters - map of parameters that will be used in the query criteria
 244  
      * @param additionalCriteria - map of additional name/value pairs to add to the critiera
 245  
      * @return Collection<?> results of query
 246  
      */
 247  
     protected Collection<?> executeAttributeQueryCriteria(AttributeQuery attributeQuery,
 248  
             Map<String, String> queryParameters, Map<String, String> additionalCriteria) {
 249  0
         Collection<?> results = null;
 250  
 
 251  
         // build criteria for query
 252  0
         Map<String, String> queryCriteria = new HashMap<String, String>();
 253  0
         for (String fieldName : attributeQuery.getQueryFieldMapping().keySet()) {
 254  0
             if (queryParameters.containsKey(fieldName) && StringUtils.isNotBlank(queryParameters.get(fieldName))) {
 255  0
                 queryCriteria.put(fieldName, queryParameters.get(fieldName));
 256  
             }
 257  
         }
 258  
 
 259  
         // add any static criteria
 260  0
         for (String fieldName : attributeQuery.getAdditionalCriteria().keySet()) {
 261  0
             queryCriteria.put(fieldName, attributeQuery.getAdditionalCriteria().get(fieldName));
 262  
         }
 263  
 
 264  
         // add additional criteria
 265  0
         if (additionalCriteria != null) {
 266  0
             queryCriteria.putAll(additionalCriteria);
 267  
         }
 268  
 
 269  0
         Class<?> queryClass = null;
 270  
         try {
 271  0
             queryClass = Class.forName(attributeQuery.getDataObjectClassName());
 272  0
         } catch (ClassNotFoundException e) {
 273  0
             throw new RuntimeException(
 274  
                     "Invalid data object class given for suggest query: " + attributeQuery.getDataObjectClassName(), e);
 275  0
         }
 276  
 
 277  
         // run query
 278  0
         results = getLookupService().findCollectionBySearchUnbounded(queryClass, queryCriteria);
 279  
 
 280  
         // sort results
 281  0
         if (!attributeQuery.getSortPropertyNames().isEmpty() && (results != null) && (results.size() > 1)) {
 282  0
             Collections.sort((List<?>) results, new BeanPropertyComparator(attributeQuery.getSortPropertyNames()));
 283  
         }
 284  
 
 285  0
         return results;
 286  
     }
 287  
 
 288  
     protected LookupService getLookupService() {
 289  0
         if (lookupService == null) {
 290  0
             lookupService = KRADServiceLocatorWeb.getLookupService();
 291  
         }
 292  
 
 293  0
         return lookupService;
 294  
     }
 295  
 
 296  
     public void setLookupService(LookupService lookupService) {
 297  0
         this.lookupService = lookupService;
 298  0
     }
 299  
 
 300  
     protected ConfigurationService getConfigurationService() {
 301  0
         if (configurationService == null) {
 302  0
             configurationService = KRADServiceLocator.getKualiConfigurationService();
 303  
         }
 304  
 
 305  0
         return configurationService;
 306  
     }
 307  
 
 308  
     public void setConfigurationService(ConfigurationService configurationService) {
 309  0
         this.configurationService = configurationService;
 310  0
     }
 311  
 }