View Javadoc
1   /*                                                                                invoiceNumber
2    * Copyright 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.ole.select.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.ole.select.businessobject.*;
20  import org.kuali.ole.select.document.service.OleLineItemReceivingService;
21  import org.kuali.ole.select.document.service.impl.OleLineItemReceivingServiceImpl;
22  import org.kuali.ole.select.service.OleDocStoreLookupService;
23  import org.kuali.ole.select.service.OleDocStoreSearchService;
24  import org.kuali.ole.sys.context.SpringContext;
25  import org.kuali.ole.sys.service.NonTransactional;
26  import org.kuali.rice.core.api.config.property.ConfigurationService;
27  import org.kuali.rice.core.api.search.SearchOperator;
28  import org.kuali.rice.kns.service.DataDictionaryService;
29  import org.kuali.rice.kns.service.KNSServiceLocator;
30  import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
31  import org.kuali.rice.krad.bo.PersistableBusinessObject;
32  import org.kuali.rice.krad.dao.LookupDao;
33  import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
34  import org.kuali.rice.krad.datadictionary.DataDictionaryEntry;
35  import org.kuali.rice.krad.datadictionary.PrimitiveAttributeDefinition;
36  import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
37  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
38  import org.kuali.rice.krad.service.ModuleService;
39  import org.kuali.rice.krad.service.PersistenceStructureService;
40  
41  import java.lang.reflect.Method;
42  import java.util.*;
43  
44  /**
45   * This is the implementation class for OleDocStoreLookupService to integrate Docstore search.
46   */
47  @NonTransactional
48  public class OleDocStoreLookupServiceImpl implements OleDocStoreLookupService {
49      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OleDocStoreLookupServiceImpl.class);
50  
51      private OleDocStoreSearchService lookupDao;
52      private LookupDao lookupDaoOjb;
53      private ConfigurationService kualiConfigurationService;
54      private DataDictionaryService dataDictionaryService;
55      private PersistenceStructureService persistenceStructureService;
56  
57      /**
58       * Returns a collection of objects without any bounded value, based on the given search parameters.
59       *
60       * @return Collection returned from the search
61       */
62      @Override
63      public Collection findCollectionBySearchUnbounded(Class example, Map formProps) {
64          LOG.debug("Inside findCollectionBySearchUnbounded of OleDocStoreLookupServiceImpl");
65          return findCollectionBySearchHelper(example, formProps, true);
66      }
67  
68      /**
69       * Returns a collection of objects based on the given search parameters.
70       *
71       * @return Collection returned from the search
72       */
73      @Override
74      public Collection findCollectionBySearch(Class example, Map formProps) {
75          LOG.debug("Inside findCollectionBySearch of OleDocStoreLookupServiceImpl");
76          try {
77              return getResult(example, formProps, true);
78          } catch (Exception e) {
79              throw new RuntimeException(e);
80          }
81      }
82  
83      /**
84       * Returns a collection of objects without any bounded value, based on the given search parameters.
85       *
86       * @return Collection returned from the search
87       */
88      @Override
89      public Collection findCollectionBySearchHelper(Class example, Map formProps, boolean unbounded) {
90          LOG.debug("Inside findCollectionBySearchHelper of OleDocStoreLookupServiceImpl");
91          try {
92              return getResult(example, formProps, true);
93          } catch (Exception e) {
94              throw new RuntimeException(e);
95          }
96      }
97  
98      /**
99       * Retrieves a Object based on the search criteria, which should uniquely identify a record.
100      *
101      * @return Object returned from the search
102      */
103     @Override
104     public Object findObjectBySearch(Class example, Map formProps) {
105         LOG.debug("Inside findObjectBySearch of OleDocStoreLookupServiceImpl");
106         if (example == null || formProps == null) {
107             throw new IllegalArgumentException("Object and Map must not be null");
108         }
109 
110         PersistableBusinessObject obj = null;
111         try {
112             obj = (PersistableBusinessObject) example.newInstance();
113         } catch (IllegalAccessException e) {
114             throw new RuntimeException("Cannot get new instance of " + example.getName(), e);
115         } catch (InstantiationException e) {
116             throw new RuntimeException("Cannot instantiate " + example.getName(), e);
117         }
118 
119         return lookupDaoOjb.findObjectByMap(obj, formProps);
120     }
121 
122 
123     @Override
124     public boolean allPrimaryKeyValuesPresentAndNotWildcard(Class boClass, Map formProps) {
125         List pkFields = KNSServiceLocator.getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(boClass);
126         Iterator pkIter = pkFields.iterator();
127         boolean returnVal = true;
128         while (returnVal && pkIter.hasNext()) {
129             String pkName = (String) pkIter.next();
130             String pkValue = (String) formProps.get(pkName);
131 
132             if (StringUtils.isBlank(pkValue)) {
133                 returnVal = false;
134             } else if (StringUtils.indexOfAny(pkValue, SearchOperator.QUERY_CHARACTERS.toArray().toString()) != -1) {
135                 returnVal = false;
136             }
137         }
138         return returnVal;
139     }
140 
141     /**
142      * @return Returns the lookupDao.
143      */
144     public OleDocStoreSearchService getLookupDao() {
145         return lookupDao;
146     }
147 
148     /**
149      * @param lookupDao The lookupDao to set.
150      */
151     public void setLookupDao(OleDocStoreSearchService lookupDao) {
152         this.lookupDao = lookupDao;
153     }
154 
155 
156     /**
157      * @return Returns the kualiConfigurationService.
158      */
159     public ConfigurationService getConfigurationService() {
160         return kualiConfigurationService;
161     }
162 
163     /**
164      * @param kualiConfigurationService The kualiConfigurationService to set.
165      */
166     public void setConfigurationService(ConfigurationService kualiConfigurationService) {
167         this.kualiConfigurationService = kualiConfigurationService;
168     }
169 
170     /**
171      * @param dataDictionaryService The dataDictionaryService to set.
172      */
173     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
174         this.dataDictionaryService = dataDictionaryService;
175     }
176 
177     /**
178      * @return Returns the lookupDao.
179      */
180     public LookupDao getLookupDaoOjb() {
181         return lookupDaoOjb;
182     }
183 
184 
185     /**
186      * @param lookupDao The lookupDao to set.
187      */
188     public void setLookupDaoOjb(LookupDao lookupDaoOjb) {
189         this.lookupDaoOjb = lookupDaoOjb;
190     }
191 
192 
193     public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
194         this.persistenceStructureService = persistenceStructureService;
195     }
196 
197     /**
198      * This method integrates database search with docstore search for the businessObject class passed as input
199      *
200      * @param businessObjectClass
201      * @param criterValues
202      * @param unbounded
203      * @return
204      * @throws Exception
205      */
206     private List getResult(Class businessObjectClass, Map criterValues, boolean unbounded) throws Exception {
207         LOG.debug("Inside getResult of OleDocStoreLookupServiceImpl");
208         List result = new ArrayList();
209         Map dbCrit = new HashMap();
210         Map docCrit = new HashMap();
211         Map<String, List<String>> docData = getDDRelationship(businessObjectClass);
212         if (docData != null && docData.size() > 0) {
213             for (String key : (java.util.Set<String>) criterValues.keySet()) {
214                 boolean found = false;
215                 for (String key1 : docData.keySet()) {
216                     {
217                         if (key.contains(key1) && key.contains(".")) {
218                             found = true;
219                             String val = key.split("\\.")[key.split("\\.").length - 1];
220                             docCrit.put(val, criterValues.get(key));//dbCrit = null;
221                             break;
222                         }
223                     }
224                     if (!found) {
225                         dbCrit.put(key, criterValues.get(key));//dbCrit = null;
226                     }
227                 }
228             }
229         }
230         if (ExternalizableBusinessObject.class.isAssignableFrom(businessObjectClass)) {
231 
232             ModuleService eboModuleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(businessObjectClass);
233             BusinessObjectEntry ddEntry = eboModuleService.getExternalizableBusinessObjectDictionaryEntry(businessObjectClass);
234             Map<String, String> filteredFieldValues = new HashMap<String, String>();
235             for (String fieldName : (java.util.Set<String>) dbCrit.keySet()) {
236                 if (ddEntry.getAttributeNames().contains(fieldName)) {
237                     filteredFieldValues.put(fieldName, (String) dbCrit.get(fieldName));
238                 }
239             }
240 
241             result = eboModuleService.getExternalizableBusinessObjectsListForLookup(businessObjectClass,
242                     (Map) filteredFieldValues, unbounded);
243 
244         } else if (!org.kuali.ole.select.lookup.DocStoreData.class.isAssignableFrom(businessObjectClass)) {
245             result = (List) this.getLookupDaoOjb().findCollectionBySearchHelper(businessObjectClass, dbCrit, unbounded,
246                     allPrimaryKeyValuesPresentAndNotWildcard(businessObjectClass, dbCrit));
247         }
248 
249         if (businessObjectClass.equals(OleLineItemReceivingItem.class)) {
250             List<OleLineItemReceivingItem> resultList = result;
251             for (OleLineItemReceivingItem item : resultList) {
252                 Integer receivingItemIdentifier = item.getReceivingItemIdentifier();
253                 OleLineItemReceivingService oleLineItemReceivingService = SpringContext.getBean(OleLineItemReceivingServiceImpl.class);
254                 OleLineItemReceivingDoc oleLineItemReceivingDoc = oleLineItemReceivingService.getOleLineItemReceivingDoc(receivingItemIdentifier);
255                 item.setItemTitleId(oleLineItemReceivingDoc.getItemTitleId());
256             }
257             result = resultList;
258         }
259         if (businessObjectClass.equals(OleCorrectionReceivingItem.class)) {
260             List<OleCorrectionReceivingItem> resultList = result;
261             for (OleCorrectionReceivingItem item : resultList) {
262                 Integer receivingItemIdentifier = item.getReceivingItemIdentifier();
263                 OleLineItemReceivingService oleLineItemReceivingService = SpringContext.getBean(OleLineItemReceivingServiceImpl.class);
264                 OleLineItemCorrectionReceivingDoc oleLineItemCorrectionReceivingDoc = oleLineItemReceivingService.getOleLineItemCorrectionReceivingDoc(receivingItemIdentifier);
265                 item.setItemTitleId(oleLineItemCorrectionReceivingDoc.getItemTitleId());
266             }
267             result = resultList;
268         }
269 
270         Class cla = null;
271         for (String key : docData.keySet()) {
272             List<String> data = docData.get(key);
273 
274             try {
275                 cla = Class.forName(data.get(0));
276             } catch (Exception e) {
277                 throw new RuntimeException(e);
278             }
279             String attrs = data.get(1);
280             String[] ff = attrs.split(":")[0].split(",");
281             String sourAtt = null, targetAtt = null;
282             if (ff.length == 2) {
283                 sourAtt = ff[0];
284                 targetAtt = ff[1];
285             }
286             boolean isDBCrit = dbCrit == null || dbCrit.size() < 3;
287             boolean isDocCrit = docCrit == null || docCrit.size() < 2;
288             //retrieves the list of source/database attribute values
289             List dbSourceAttrib = getSourceData(result, sourAtt, businessObjectClass);
290             //retrieves the list of document store data for the corresponding source/database attribute values
291             List docStoreResult = this.getLookupDao().getResult(cla, targetAtt, dbSourceAttrib, docCrit);//docStoreResult.remove(2)
292             //merges both docstore and database data
293             result = mergeResult(result, sourAtt, businessObjectClass, docStoreResult, "uniqueId", cla, docData.keySet().iterator().next(), isDBCrit, isDocCrit);
294         }
295         if (org.kuali.ole.select.lookup.DocStoreData.class.isAssignableFrom(businessObjectClass)) {
296             result = (List) this.getLookupDaoOjb().findCollectionBySearchHelper(businessObjectClass, criterValues, true, true);
297         }
298 
299         LOG.debug("Leaving getResult of OleDocStoreLookupServiceImpl");
300         if (businessObjectClass.equals(OleRequisitionItem.class)) {
301             result = setBibUUID(result);
302         }
303         return result;
304     }
305 
306     /**
307      * This method invokes getter method for the attribute in the specified class
308      *
309      * @param c
310      * @param attr
311      * @param objectAttributes
312      * @return
313      * @throws Exception
314      */
315     private Method getMethod(Class c, String attr, Class[] objectAttributes) throws Exception {
316         LOG.debug("Inside getMethod of OleDocStoreLookupServiceImpl");
317         Method met = c.getMethod("get" + StringUtils.capitalize(attr), objectAttributes);
318         LOG.debug("Leaving getMethod of OleDocStoreLookupServiceImpl");
319         return met;
320     }
321 
322     /**
323      * This method invokes setter method for the attribute in the specified class
324      *
325      * @param c
326      * @param attr
327      * @param objectAttributes
328      * @return
329      * @throws Exception
330      */
331     private Method getSetMethod(Class c, String attr, Class[] objectAttributes) throws Exception {
332         LOG.debug("Inside getSetMethod of OleDocStoreLookupServiceImpl");
333         attr = "docData";
334         Method met = c.getMethod("set" + StringUtils.capitalize(attr), objectAttributes);
335         LOG.debug("Leaving getSetMethod of OleDocStoreLookupServiceImpl");
336         return met;
337     }
338 
339     /**
340      * This method merges database search result with docstore search result
341      *
342      * @param result
343      * @param sourAtt
344      * @param sourClass
345      * @param dres
346      * @param targetAtt
347      * @param targeClass
348      * @param attt
349      * @param isDBCrit
350      * @param isDocCrit
351      * @return
352      * @throws Exception
353      */
354     private List mergeResult(List result, String sourAtt, Class sourClass, List dres, String targetAtt, Class targeClass,
355                              String attt, boolean isDBCrit, boolean isDocCrit)
356             throws Exception {
357         LOG.debug("Inside mergeResult of OleDocStoreLookupServiceImpl");
358         List resul = new ArrayList();
359         List resut = new ArrayList();
360         Class[] ptyeps = {targeClass};
361         Method srcm = this.getMethod(sourClass, sourAtt, null);
362         Method tcm = this.getMethod(targeClass, targetAtt, null);
363         Method sem = this.getSetMethod(sourClass, attt, ptyeps);
364         for (Object val : result) {
365             for (Object dval : dres) {
366                 Object sval = srcm.invoke(val, (Object[]) null);
367                 Object dvall = tcm.invoke(dval, (Object[]) null);
368                 if ((!isDocCrit && sval != null && sval.equals(dvall)) || (isDocCrit && dvall != null && dvall.equals(sval))) {
369                     //if(isDocCrit && dvall != null && dvall.equals(sval)){
370                     Object[] arr = {dval};
371                     sem.invoke(val, arr);
372                     resul.add(val);
373                     //}
374                 }
375             }
376         }
377         LOG.debug("Leaving mergeResult of OleDocStoreLookupServiceImpl");
378         return resul;
379 
380     }
381 
382     /**
383      * This method returns the list of document uuids retrieved from database search
384      *
385      * @param result
386      * @param objectAttribute
387      * @param clas
388      * @return
389      * @throws Exception
390      */
391     private List<Object> getSourceData(List result, String objectAttribute, Class clas) throws Exception {
392         LOG.debug("Inside getSourceData of OleDocStoreLookupServiceImpl");
393         List<Object> resul = new ArrayList<Object>(0);
394         Method met = clas.getMethod("get" + StringUtils.capitalize(objectAttribute), (Class[]) null);
395         for (Object data : result) {
396             Object res = met.invoke(data, (Object[]) null);
397             if (res != null) {
398                 resul.add(res);
399             }
400         }
401         LOG.debug("Leaving getSourceData of OleDocStoreLookupServiceImpl");
402         return resul;
403     }
404 
405     /**
406      * This method returns the class which stores Docstore data
407      *
408      * @param clas
409      * @param objectAttribute
410      * @return
411      */
412     public Class getDocClass(Class clas, String objectAttribute) {
413         LOG.debug("Inside getDocClass of OleDocStoreLookupServiceImpl");
414         boolean result = false;
415         Method met = null;
416         try {
417             met = clas.getMethod("get" + StringUtils.capitalize(objectAttribute), (Class[]) null);
418         } catch (Exception e) {
419             return null;
420         }
421         return org.kuali.ole.select.lookup.DocStoreData.class.isAssignableFrom(met.getReturnType()) ?
422                 met.getReturnType() : null;
423     }
424 
425     /**
426      * This method returns relationships in datadictionary
427      *
428      * @param c
429      * @return
430      */
431     public Map<String, List<String>> getDDRelationship(Class c) {
432         LOG.debug("Inside getDDRelationship of OleDocStoreLookupServiceImpl");
433         Map<String, List<String>> result = new HashMap<String, List<String>>(0);
434         DataDictionaryEntry entryBase = SpringContext.getBean(DataDictionaryService.class)
435                 .getDataDictionary().getDictionaryObjectEntry(c.getName());
436         if (entryBase == null) {
437             return null;
438         }
439 
440         List<RelationshipDefinition> ddRelationships = entryBase
441                 .getRelationships();
442         RelationshipDefinition relationship = null;
443         int minKeys = Integer.MAX_VALUE;
444         for (RelationshipDefinition def : ddRelationships) {
445             // favor key sizes of 1 first
446             if (def.getPrimitiveAttributes().size() == 1) {
447                 for (PrimitiveAttributeDefinition primitive : def
448                         .getPrimitiveAttributes()) {
449                     if (def.getObjectAttributeName() != null) {
450                         List<String> data = new ArrayList<String>(0);
451                         Class cc = getDocClass(c, def.getObjectAttributeName());//cc= null;data.remove("java.lang.String");
452                         if (cc != null) {
453                             data.add(cc.getName());
454                             StringBuffer sb = new StringBuffer();
455                             List<PrimitiveAttributeDefinition> res = def.getPrimitiveAttributes();
456                             for (PrimitiveAttributeDefinition pdef : res) {
457                                 sb.append(pdef.getSourceName() + "," + pdef.getTargetName() + ":");
458                             }
459                             sb.deleteCharAt(sb.length() - 1);
460                             data.add(sb.toString());
461                             result.put(def.getObjectAttributeName(), data);
462                         }
463                     }
464                 }
465             }
466         }
467         LOG.debug("Leaving getDDRelationship of OleDocStoreLookupServiceImpl");
468         return result;
469     }
470 
471     public List<OleRequisitionItem> setBibUUID(List<OleRequisitionItem> items) {
472         List<OleRequisitionItem> itemList = new ArrayList<OleRequisitionItem>();
473         OleRequisitionItem item;
474         String uuid;
475         for (int i = 0; i < items.size(); i++) {
476             item = items.get(i);
477             uuid = lookupDao.getBibUUID(item.getItemTitleId());
478             items.get(i).setBibUUID(uuid);
479             itemList.add(item);
480         }
481         return itemList;
482     }
483 
484     @Override
485     public <T> Collection<T> findCollectionBySearchHelper(Class<T> example, Map<String, String> formProperties, boolean unbounded, Integer searchResultsLimit) {
486         return null;  //To change body of implemented methods use File | Settings | File Templates.
487     }
488 }
489