| 1 |  |  package org.kuali.student.core.subjectcode.service.impl; | 
  | 2 |  |   | 
  | 3 |  |  import java.text.DateFormat; | 
  | 4 |  |  import java.text.SimpleDateFormat; | 
  | 5 |  |  import java.util.ArrayList; | 
  | 6 |  |  import java.util.Collections; | 
  | 7 |  |  import java.util.Comparator; | 
  | 8 |  |  import java.util.Date; | 
  | 9 |  |  import java.util.HashMap; | 
  | 10 |  |  import java.util.List; | 
  | 11 |  |  import java.util.Map; | 
  | 12 |  |   | 
  | 13 |  |  import javax.jws.WebService; | 
  | 14 |  |  import javax.jws.soap.SOAPBinding; | 
  | 15 |  |  import javax.xml.namespace.QName; | 
  | 16 |  |   | 
  | 17 |  |  import org.kuali.rice.core.resourceloader.GlobalResourceLoader; | 
  | 18 |  |  import org.kuali.rice.core.util.MaxAgeSoftReference; | 
  | 19 |  |  import org.kuali.rice.core.util.MaxSizeMap; | 
  | 20 |  |  import org.kuali.rice.kns.service.BusinessObjectService; | 
  | 21 |  |  import org.kuali.rice.kns.service.KNSServiceLocator; | 
  | 22 |  |  import org.kuali.rice.kns.service.LookupService; | 
  | 23 |  |  import org.kuali.student.common.exceptions.DoesNotExistException; | 
  | 24 |  |  import org.kuali.student.common.exceptions.InvalidParameterException; | 
  | 25 |  |  import org.kuali.student.common.exceptions.MissingParameterException; | 
  | 26 |  |  import org.kuali.student.common.exceptions.OperationFailedException; | 
  | 27 |  |  import org.kuali.student.common.search.dto.SearchCriteriaTypeInfo; | 
  | 28 |  |  import org.kuali.student.common.search.dto.SearchParam; | 
  | 29 |  |  import org.kuali.student.common.search.dto.SearchRequest; | 
  | 30 |  |  import org.kuali.student.common.search.dto.SearchResult; | 
  | 31 |  |  import org.kuali.student.common.search.dto.SearchResultCell; | 
  | 32 |  |  import org.kuali.student.common.search.dto.SearchResultRow; | 
  | 33 |  |  import org.kuali.student.common.search.dto.SearchResultTypeInfo; | 
  | 34 |  |  import org.kuali.student.common.search.dto.SearchTypeInfo; | 
  | 35 |  |  import org.kuali.student.common.search.service.SearchManager; | 
  | 36 |  |  import org.kuali.student.core.organization.service.OrganizationService; | 
  | 37 |  |  import org.kuali.student.core.subjectcode.bo.SubjectCode; | 
  | 38 |  |  import org.kuali.student.core.subjectcode.bo.SubjectCodeJoinOrg; | 
  | 39 |  |  import org.kuali.student.core.subjectcode.service.SubjectCodeService; | 
  | 40 |  |  import org.springframework.beans.factory.InitializingBean; | 
  | 41 |  |  import org.kuali.student.common.util.DateFormatThread; | 
  | 42 |  |   | 
  | 43 |  |  @WebService(endpointInterface = "org.kuali.student.core.subjectcode.service.SubjectCodeService", serviceName = "SubjectCodeService", portName = "SubjectCodeService", targetNamespace = "http://student.kuali.org/wsdl/subjectCode") | 
  | 44 |  |  @SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) | 
  | 45 | 0 |  public class SubjectCodeServiceImpl implements SubjectCodeService, InitializingBean{ | 
  | 46 |  |   | 
  | 47 |  |          private static OrganizationService organizationService; | 
  | 48 |  |          private static LookupService lookupService; | 
  | 49 |  |          private BusinessObjectService businessObjectService; | 
  | 50 |  |          private SearchManager searchManager; | 
  | 51 | 0 |          private static DateFormat format = new SimpleDateFormat("yyyy-MM-dd"); | 
  | 52 |  |           | 
  | 53 | 0 |          protected boolean cachingEnabled = false; | 
  | 54 | 0 |          protected int searchCacheMaxSize = 20; | 
  | 55 | 0 |          protected int searchCacheMaxAgeSeconds = 90; | 
  | 56 |  |          protected Map<String,MaxAgeSoftReference<SearchResult>> searchCache; | 
  | 57 |  |   | 
  | 58 |  |          @Override | 
  | 59 |  |          public List<SearchTypeInfo> getSearchTypes() | 
  | 60 |  |                          throws OperationFailedException { | 
  | 61 | 0 |                  return searchManager.getSearchTypes(); | 
  | 62 |  |          } | 
  | 63 |  |   | 
  | 64 |  |          @Override | 
  | 65 |  |          public SearchTypeInfo getSearchType(String searchTypeKey) | 
  | 66 |  |                          throws DoesNotExistException, InvalidParameterException, | 
  | 67 |  |                          MissingParameterException, OperationFailedException { | 
  | 68 | 0 |                  return searchManager.getSearchType(searchTypeKey); | 
  | 69 |  |          } | 
  | 70 |  |   | 
  | 71 |  |          @Override | 
  | 72 |  |          public List<SearchTypeInfo> getSearchTypesByResult( | 
  | 73 |  |                          String searchResultTypeKey) throws DoesNotExistException, | 
  | 74 |  |                          InvalidParameterException, MissingParameterException, | 
  | 75 |  |                          OperationFailedException { | 
  | 76 | 0 |                  return searchManager.getSearchTypesByResult(searchResultTypeKey); | 
  | 77 |  |          } | 
  | 78 |  |   | 
  | 79 |  |          @Override | 
  | 80 |  |          public List<SearchTypeInfo> getSearchTypesByCriteria( | 
  | 81 |  |                          String searchCriteriaTypeKey) throws DoesNotExistException, | 
  | 82 |  |                          InvalidParameterException, MissingParameterException, | 
  | 83 |  |                          OperationFailedException { | 
  | 84 | 0 |                  return searchManager.getSearchTypesByCriteria(searchCriteriaTypeKey); | 
  | 85 |  |          } | 
  | 86 |  |   | 
  | 87 |  |          @Override | 
  | 88 |  |          public List<SearchResultTypeInfo> getSearchResultTypes() | 
  | 89 |  |                          throws OperationFailedException { | 
  | 90 | 0 |                  return searchManager.getSearchResultTypes(); | 
  | 91 |  |          } | 
  | 92 |  |   | 
  | 93 |  |          @Override | 
  | 94 |  |          public SearchResultTypeInfo getSearchResultType(String searchResultTypeKey) | 
  | 95 |  |                          throws DoesNotExistException, InvalidParameterException, | 
  | 96 |  |                          MissingParameterException, OperationFailedException { | 
  | 97 | 0 |                  return searchManager.getSearchResultType(searchResultTypeKey); | 
  | 98 |  |          } | 
  | 99 |  |   | 
  | 100 |  |          @Override | 
  | 101 |  |          public List<SearchCriteriaTypeInfo> getSearchCriteriaTypes() | 
  | 102 |  |                          throws OperationFailedException { | 
  | 103 | 0 |                  return searchManager.getSearchCriteriaTypes(); | 
  | 104 |  |          } | 
  | 105 |  |   | 
  | 106 |  |          @Override | 
  | 107 |  |          public SearchCriteriaTypeInfo getSearchCriteriaType( | 
  | 108 |  |                          String searchCriteriaTypeKey) throws DoesNotExistException, | 
  | 109 |  |                          InvalidParameterException, MissingParameterException, | 
  | 110 |  |                          OperationFailedException { | 
  | 111 | 0 |                  return searchManager.getSearchCriteriaType(searchCriteriaTypeKey); | 
  | 112 |  |          } | 
  | 113 |  |   | 
  | 114 |  |          @Override | 
  | 115 |  |          public SearchResult search(SearchRequest searchRequest) | 
  | 116 |  |                          throws MissingParameterException { | 
  | 117 | 0 |                  String searchKey = searchRequest.getSearchKey(); | 
  | 118 |  |                   | 
  | 119 | 0 |                  if(searchKey==null||searchKey.isEmpty()){ | 
  | 120 | 0 |                          throw new MissingParameterException("searchRequest parameter is required."); | 
  | 121 |  |                  } | 
  | 122 |  |                   | 
  | 123 |  |                   | 
  | 124 | 0 |                  Map<String,Object> paramMap = new HashMap<String,Object>(); | 
  | 125 | 0 |                  for(SearchParam param:searchRequest.getParams()){ | 
  | 126 | 0 |                          paramMap.put(param.getKey(), param.getValue()); | 
  | 127 |  |                  } | 
  | 128 |  |                   | 
  | 129 | 0 |                  SearchResult searchResult = null; | 
  | 130 |  |                   | 
  | 131 | 0 |              if(cachingEnabled){ | 
  | 132 |  |                       | 
  | 133 | 0 |                      MaxAgeSoftReference<SearchResult> ref = searchCache.get(searchRequest.toString()); | 
  | 134 | 0 |                      if ( ref != null ) { | 
  | 135 | 0 |                              searchResult = ref.get(); | 
  | 136 | 0 |                              if(searchResult != null){ | 
  | 137 | 0 |                                      return searchResult; | 
  | 138 |  |                              } | 
  | 139 |  |                      } | 
  | 140 |  |                  } | 
  | 141 |  |                   | 
  | 142 |  |                   | 
  | 143 | 0 |              if("subjectCode.search.subjectCodeGeneric".equals(searchKey)){ | 
  | 144 | 0 |                          searchResult = doSubjectCodeGenericSearch(paramMap); | 
  | 145 | 0 |                  }else if("subjectCode.search.orgsForSubjectCode".equals(searchKey)){ | 
  | 146 | 0 |                          searchResult = doOrgsForSubjectCodeSearch(paramMap); | 
  | 147 |  |                  } | 
  | 148 |  |   | 
  | 149 |  |                   | 
  | 150 | 0 |              if(cachingEnabled){ | 
  | 151 |  |                       | 
  | 152 | 0 |                      searchCache.put(searchRequest.toString(), new MaxAgeSoftReference<SearchResult>( searchCacheMaxAgeSeconds, searchResult) ); | 
  | 153 |  |              } | 
  | 154 |  |               | 
  | 155 | 0 |                  return searchResult; | 
  | 156 |  |          } | 
  | 157 |  |           | 
  | 158 |  |      private SearchResult doOrgsForSubjectCodeSearch(Map<String, Object> paramMap) throws MissingParameterException { | 
  | 159 | 0 |                  SearchResult searchResult = new SearchResult(); | 
  | 160 | 0 |                  Map<String,Object> queryMap = new HashMap<String,Object>(); | 
  | 161 | 0 |                  String codeParam = (String) paramMap.get("subjectCode.queryParam.code"); | 
  | 162 | 0 |                  if(codeParam!=null){  | 
  | 163 | 0 |                          queryMap.put("subjectCode.code", codeParam); | 
  | 164 |  |                  } | 
  | 165 | 0 |                  String orgIdParam = (String) paramMap.get("subjectCode.queryParam.optionalOrgId"); | 
  | 166 | 0 |                  if(orgIdParam!=null){  | 
  | 167 | 0 |                          queryMap.put("orgId", orgIdParam); | 
  | 168 |  |                  } | 
  | 169 |  |                   | 
  | 170 |  |                   | 
  | 171 | 0 |                  List<SubjectCodeJoinOrg> subjectCodeJoinOrgs = (List<SubjectCodeJoinOrg>) getBusinessObjectService().findMatching(SubjectCodeJoinOrg.class, queryMap); | 
  | 172 | 0 |          Map<String,List<SearchResultRow>> orgIdToRowMapping = new HashMap<String,List<SearchResultRow>> (); | 
  | 173 |  |           | 
  | 174 |  |           | 
  | 175 | 0 |                  for(SubjectCodeJoinOrg subjectCodeJoinOrg:subjectCodeJoinOrgs){ | 
  | 176 |  |                           | 
  | 177 | 0 |                          if(orgIdParam!=null || subjectCodeJoinOrg.isActive()){ | 
  | 178 | 0 |                          SearchResultRow row = new SearchResultRow(); | 
  | 179 | 0 |                          row.addCell("subjectCode.resultColumn.code", subjectCodeJoinOrg.getSubjectCode().getCode()); | 
  | 180 | 0 |                          row.addCell("subjectCode.resultColumn.type", subjectCodeJoinOrg.getSubjectCode().getTypeId()); | 
  | 181 | 0 |                          row.addCell("subjectCode.resultColumn.activeFrom", subjectCodeJoinOrg.getActiveFromDate()==null?null:DateFormatThread.format(new Date(subjectCodeJoinOrg.getActiveFromDate().getTime()))); | 
  | 182 | 0 |                          row.addCell("subjectCode.resultColumn.activeTo", subjectCodeJoinOrg.getActiveToDate()==null?null:format.format(new Date(subjectCodeJoinOrg.getActiveToDate().getTime()))); | 
  | 183 | 0 |                          row.addCell("subjectCode.resultColumn.orgId", subjectCodeJoinOrg.getOrgId()); | 
  | 184 |  |                           | 
  | 185 | 0 |                          List<SearchResultRow> rowList = orgIdToRowMapping.get(subjectCodeJoinOrg.getOrgId()); | 
  | 186 | 0 |                          if(rowList==null){ | 
  | 187 | 0 |                                  rowList = new ArrayList<SearchResultRow>(); | 
  | 188 | 0 |                                  orgIdToRowMapping.put(subjectCodeJoinOrg.getOrgId(), rowList); | 
  | 189 |  |                          } | 
  | 190 | 0 |                          rowList.add(row); | 
  | 191 |  |           | 
  | 192 | 0 |                          searchResult.getRows().add(row); | 
  | 193 | 0 |                          } | 
  | 194 |  |          } | 
  | 195 |  |                   | 
  | 196 |  |                   | 
  | 197 |  |                   | 
  | 198 | 0 |                  if(!orgIdToRowMapping.isEmpty()){ | 
  | 199 |  |                           | 
  | 200 | 0 |                          SearchRequest orgIdTranslationSearchRequest = new SearchRequest("org.search.generic"); | 
  | 201 | 0 |                          orgIdTranslationSearchRequest.addParam("org.queryParam.orgOptionalIds", new ArrayList<String>(orgIdToRowMapping.keySet())); | 
  | 202 | 0 |                          SearchResult orgIdTranslationSearchResult = getOrganizationService().search(orgIdTranslationSearchRequest); | 
  | 203 |  |                           | 
  | 204 |  |                           | 
  | 205 | 0 |                          for(SearchResultRow row:orgIdTranslationSearchResult.getRows()){ | 
  | 206 |  |                                   | 
  | 207 | 0 |                                  String orgId = null; | 
  | 208 | 0 |                                  String orgShortName = null; | 
  | 209 | 0 |                                  String orgLongName = null; | 
  | 210 | 0 |                                  String orgType = null;  | 
  | 211 | 0 |                                  for(SearchResultCell cell:row.getCells()){ | 
  | 212 | 0 |                                          if("org.resultColumn.orgId".equals(cell.getKey())){ | 
  | 213 | 0 |                                                  orgId = cell.getValue(); | 
  | 214 | 0 |                                          }else if("org.resultColumn.orgShortName".equals(cell.getKey())){ | 
  | 215 | 0 |                                                  orgShortName = cell.getValue(); | 
  | 216 | 0 |                                          }else if("org.resultColumn.orgOptionalLongName".equals(cell.getKey())){ | 
  | 217 | 0 |                                                  orgLongName = cell.getValue(); | 
  | 218 | 0 |                                          }else if("org.resultColumn.orgType".equals(cell.getKey())){ | 
  | 219 | 0 |                                                  orgType = cell.getValue(); | 
  | 220 |  |                                          } | 
  | 221 |  |                                  } | 
  | 222 |  |                                   | 
  | 223 | 0 |                                  for(SearchResultRow rowToUpdate:orgIdToRowMapping.get(orgId)){ | 
  | 224 | 0 |                                          rowToUpdate.addCell("subjectCode.resultColumn.orgShortName", orgShortName); | 
  | 225 | 0 |                                          rowToUpdate.addCell("subjectCode.resultColumn.orgLongName", orgLongName); | 
  | 226 | 0 |                                          rowToUpdate.addCell("subjectCode.resultColumn.orgType", orgType); | 
  | 227 |  |                                  } | 
  | 228 | 0 |                          } | 
  | 229 |  |                  } | 
  | 230 | 0 |                  return searchResult; | 
  | 231 |  |          } | 
  | 232 |  |   | 
  | 233 |  |          private SearchResult doSubjectCodeGenericSearch(Map<String, Object> paramMap) { | 
  | 234 | 0 |                  SearchResult searchResult = new SearchResult(); | 
  | 235 | 0 |                  Map<String,Object> queryMap = new HashMap<String,Object>(); | 
  | 236 | 0 |                  String code = (String) paramMap.get("subjectCode.queryParam.code"); | 
  | 237 | 0 |                  if(code!=null){  | 
  | 238 | 0 |                          queryMap.put("code", "*" + paramMap.get("subjectCode.queryParam.code") + "*"); | 
  | 239 |  |                  } | 
  | 240 |  |   | 
  | 241 |  |                   | 
  | 242 | 0 |                  List<SubjectCode> subjectCodes = (List<SubjectCode>) getLookupService().findCollectionBySearchHelper(SubjectCode.class, queryMap, true); | 
  | 243 |  |   | 
  | 244 |  |                   | 
  | 245 | 0 |                  Collections.sort(subjectCodes,new Comparator<SubjectCode>(){ | 
  | 246 |  |                          @Override | 
  | 247 |  |                          public int compare(SubjectCode o1, SubjectCode o2) { | 
  | 248 | 0 |                                  if(o1==null && o2==null){ | 
  | 249 | 0 |                                          return 0; | 
  | 250 |  |                                  } | 
  | 251 | 0 |                                  return o1.getCode().compareTo(o2.getCode()); | 
  | 252 |  |                  }}); | 
  | 253 |  |                   | 
  | 254 |  |                   | 
  | 255 | 0 |          for(SubjectCode subjectCode:subjectCodes){ | 
  | 256 | 0 |                  SearchResultRow row = new SearchResultRow(); | 
  | 257 | 0 |                  row.addCell("subjectCode.resultColumn.id", subjectCode.getId()); | 
  | 258 | 0 |                  row.addCell("subjectCode.resultColumn.code", subjectCode.getCode()); | 
  | 259 | 0 |                  row.addCell("subjectCode.resultColumn.name", subjectCode.getName()); | 
  | 260 | 0 |                  row.addCell("subjectCode.resultColumn.type", subjectCode.getTypeId()); | 
  | 261 | 0 |                  searchResult.getRows().add(row); | 
  | 262 | 0 |          } | 
  | 263 | 0 |          return searchResult; | 
  | 264 |  |          } | 
  | 265 |  |   | 
  | 266 |  |          protected BusinessObjectService getBusinessObjectService() { | 
  | 267 | 0 |          if (businessObjectService == null) { | 
  | 268 | 0 |              businessObjectService = KNSServiceLocator.getBusinessObjectService(); | 
  | 269 |  |          } | 
  | 270 | 0 |          return  businessObjectService; | 
  | 271 |  |      } | 
  | 272 |  |          protected LookupService getLookupService() { | 
  | 273 | 0 |          if (lookupService == null) { | 
  | 274 | 0 |                  lookupService = KNSServiceLocator.getLookupService(); | 
  | 275 |  |          } | 
  | 276 | 0 |          return lookupService; | 
  | 277 |  |      } | 
  | 278 |  |       | 
  | 279 |  |          protected static OrganizationService getOrganizationService() { | 
  | 280 | 0 |                  if (organizationService == null) { | 
  | 281 | 0 |                          organizationService = (OrganizationService) GlobalResourceLoader | 
  | 282 |  |                                          .getService(new QName( | 
  | 283 |  |                                                          "http://student.kuali.org/wsdl/organization", | 
  | 284 |  |                                                          "OrganizationService")); | 
  | 285 |  |                  } | 
  | 286 | 0 |                  return organizationService; | 
  | 287 |  |          } | 
  | 288 |  |           | 
  | 289 |  |          @Override | 
  | 290 |  |          public void afterPropertiesSet() throws Exception { | 
  | 291 | 0 |                  if(cachingEnabled){ | 
  | 292 | 0 |                          searchCache = Collections.synchronizedMap( new MaxSizeMap<String,MaxAgeSoftReference<SearchResult>>( searchCacheMaxSize ) ); | 
  | 293 |  |                  } | 
  | 294 | 0 |          } | 
  | 295 |  |           | 
  | 296 |  |          public void setCachingEnabled(boolean cachingEnabled) { | 
  | 297 | 0 |                  this.cachingEnabled = cachingEnabled; | 
  | 298 | 0 |          } | 
  | 299 |  |   | 
  | 300 |  |          public void setSearchCacheMaxSize(int searchCacheMaxSize) { | 
  | 301 | 0 |                  this.searchCacheMaxSize = searchCacheMaxSize; | 
  | 302 | 0 |          } | 
  | 303 |  |   | 
  | 304 |  |          public void setSearchCacheMaxAgeSeconds(int searchCacheMaxAgeSeconds) { | 
  | 305 | 0 |                  this.searchCacheMaxAgeSeconds = searchCacheMaxAgeSeconds; | 
  | 306 | 0 |          } | 
  | 307 |  |   | 
  | 308 |  |          public void setSearchManager(SearchManager searchManager) { | 
  | 309 | 0 |                  this.searchManager = searchManager; | 
  | 310 | 0 |          } | 
  | 311 |  |  } |