001 /* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005 package org.kuali.student.r2.lum.lrc.service.impl; 006 007 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 008 import org.kuali.student.r2.common.dto.ContextInfo; 009 import org.kuali.student.r2.common.dto.RichTextInfo; 010 import org.kuali.student.r2.common.exceptions.*; 011 import org.kuali.student.r2.lum.lrc.dto.ResultValueInfo; 012 import org.kuali.student.r2.lum.lrc.dto.ResultValueRangeInfo; 013 import org.kuali.student.r2.lum.lrc.dto.ResultValuesGroupInfo; 014 import org.kuali.student.r2.lum.lrc.service.LRCService; 015 import org.kuali.student.r2.lum.lrc.service.LrcServiceBusinessLogic; 016 import org.kuali.student.r2.lum.util.constants.LrcServiceConstants; 017 018 import javax.xml.namespace.QName; 019 import java.util.ArrayList; 020 import java.util.Date; 021 import java.util.List; 022 023 /** 024 * 025 * @author nwright 026 */ 027 public class LrcServiceBusinessLogicImpl implements LrcServiceBusinessLogic { 028 029 private LRCService lrcService; 030 031 public LRCService getLrcService() { 032 if(lrcService == null){ 033 lrcService = GlobalResourceLoader.getService(new QName(LrcServiceConstants.NAMESPACE, 034 "LearningResultService")); // dyak's response to KSCM-2247/KSLAB-2636 - instead of LrcServiceConstants.SERVICE_NAME_LOCAL_PART 035 } 036 return lrcService; 037 } 038 039 public void setLrcService(LRCService lrcService) { 040 this.lrcService = lrcService; 041 } 042 043 /** 044 * Calculate the result values group key for the fixed credit value 045 * @param creditValue 046 * @param scaleKey 047 * @return 048 * @throws InvalidParameterException 049 */ 050 protected String calcFixedCreditRvgKey(String creditValue, 051 String scaleKey, 052 ContextInfo contextInfo) 053 throws InvalidParameterException { 054 055 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_DEGREE)) { 056 return LrcServiceConstants.RESULT_GROUP_KEY_KUALI_CREDITTYPE_CREDIT_BASE + creditValue; 057 } 058 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_REMEDIAL)) { 059 return LrcServiceConstants.RESULT_GROUP_KEY_CREDIT_REMEDIAL_FIXED_BASE + creditValue; 060 } 061 throw new InvalidParameterException("unknown/unhandled credit type scale key " + scaleKey); 062 } 063 064 /** 065 * Calculate the result values group key for the range credit value 066 * @param value 067 * @param scaleKey 068 * @return 069 * @throws InvalidParameterException 070 */ 071 protected String calcFixedCreditRvgName(String value, 072 String scaleKey, 073 ContextInfo contextInfo) 074 throws InvalidParameterException { 075 StringBuilder sb = new StringBuilder(); 076 sb.append("Credits"); 077 sb.append(value); 078 return sb.toString(); 079 } 080 081 /** 082 * Calculate the fixed credit value key to use that matches the specified value 083 * @param creditValue 084 * @param scaleKey 085 * @return 086 * @throws InvalidParameterException 087 */ 088 protected String calcCreditValueKey(String creditValue, 089 String scaleKey, 090 ContextInfo contextInfo) 091 throws InvalidParameterException { 092 093 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_DEGREE)) { 094 return "kuali.result.value.credit.degree." + creditValue; 095 } 096 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_REMEDIAL)) { 097 return "kuali.result.value.credit.remedial." + creditValue; 098 } 099 throw new InvalidParameterException("unknown/unhandled credit type scale key " + scaleKey); 100 } 101 102 @Override 103 public ResultValuesGroupInfo getCreateFixedCreditResultValuesGroup(String creditValue, 104 String scaleKey, 105 ContextInfo contextInfo) 106 throws InvalidParameterException, 107 MissingParameterException, 108 OperationFailedException, 109 PermissionDeniedException { 110 String rvgKey = calcFixedCreditRvgKey(creditValue, scaleKey, contextInfo); 111 String valueKey = this.calcCreditValueKey(creditValue, scaleKey, contextInfo); 112 try { 113 ResultValuesGroupInfo rvg = getLrcService().getResultValuesGroup(rvgKey, contextInfo); 114 if (!rvg.getTypeKey().equals(LrcServiceConstants.RESULT_VALUES_GROUP_TYPE_KEY_FIXED)) { 115 throw new OperationFailedException("Calculated key does not point to a FIXED RVG: " + rvgKey); 116 } 117 if (!rvg.getResultScaleKey().equals(scaleKey)) { 118 throw new OperationFailedException("Calculated key does not point to an RVG of the expected scale key: " + rvgKey); 119 } 120 if (rvg.getResultValueKeys().size() != 1) { 121 throw new OperationFailedException("Calculated key does not point to an RVG with a single value: " + rvgKey); 122 } 123 if (!rvg.getResultValueKeys().get(0).equals(valueKey)) { 124 throw new OperationFailedException("Calculated key does not point to an RVG with the expected value key : " + 125 rvgKey); 126 } 127 return rvg; 128 } catch (DoesNotExistException ex) { 129 // ok then create 130 } 131 // find/create value 132 ResultValueInfo value = null; 133 try { 134 value = getLrcService().getResultValue(valueKey, contextInfo); 135 } catch (DoesNotExistException ex) { 136 value = new ResultValueInfo(); 137 value.setKey(valueKey); 138 value.setTypeKey(LrcServiceConstants.RESULT_VALUE_TYPE_KEY_VALUE); 139 value.setStateKey(LrcServiceConstants.RESULT_VALUE_STATE_APPROVED); 140 value.setName(creditValue); 141 value.setValue(creditValue); 142 value.setNumericValue(creditValue); 143 value.setResultScaleKey(scaleKey); 144 value.setEffectiveDate(new Date()); 145 try { 146 value = lrcService.createResultValue(value.getResultScaleKey(), value.getTypeKey(), value, contextInfo); 147 } catch (AlreadyExistsException ex1) { 148 throw new OperationFailedException("unexpected", ex); 149 } catch (DataValidationErrorException ex1) { 150 throw new OperationFailedException("unexpected", ex); 151 } catch (DoesNotExistException ex1) { 152 throw new OperationFailedException("unexpected", ex); 153 } 154 } 155 156 // not found so create it 157 ResultValuesGroupInfo rvg = new ResultValuesGroupInfo(); 158 rvg.setKey(rvgKey); 159 rvg.setTypeKey(LrcServiceConstants.RESULT_VALUES_GROUP_TYPE_KEY_FIXED); 160 rvg.setStateKey(LrcServiceConstants.RESULT_GROUPS_STATE_APPROVED); 161 rvg.setName("Fixed Credit Value " + creditValue); 162 rvg.setEffectiveDate(new Date()); 163 rvg.setResultScaleKey(scaleKey); 164 rvg.getResultValueKeys().add(valueKey); 165 try { 166 rvg = getLrcService().createResultValuesGroup(rvg.getResultScaleKey(), rvg.getTypeKey(), rvg, contextInfo); 167 } catch (AlreadyExistsException ex) { 168 throw new OperationFailedException("unexpected", ex); 169 } catch (DataValidationErrorException ex) { 170 throw new OperationFailedException("unexpected", ex); 171 } 172 return rvg; 173 } 174 175 /** 176 * Calculate the result values group key for the range credit value 177 * @param creditValueMin 178 * @param creditValueMax 179 * @param creditValueIncrement 180 * @param scaleKey 181 * @param contextInfo 182 * @return 183 * @throws InvalidParameterException 184 */ 185 protected String calcRangeCreditRvgKey(String creditValueMin, 186 String creditValueMax, 187 String creditValueIncrement, 188 String scaleKey, 189 ContextInfo contextInfo) 190 throws InvalidParameterException { 191 192 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_DEGREE)) { 193 StringBuilder sb = new StringBuilder(); 194 sb.append(LrcServiceConstants.RESULT_GROUP_KEY_KUALI_CREDITTYPE_CREDIT_BASE); 195 sb.append(creditValueMin).append("-").append(creditValueMax); 196 if (!creditValueIncrement.equals("1")) { 197 sb.append(".by.").append(creditValueIncrement); 198 } 199 return sb.toString(); 200 } 201 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_REMEDIAL)) { 202 StringBuilder sb = new StringBuilder(); 203 //TODO this needs to be a constant and the DB needs to match these values. 204 sb.append("kuali.result.group.credit.remedial.range.").append(creditValueMin).append("-").append(creditValueMax); 205 if (creditValueIncrement.equals("1")) { 206 sb.append(".by.").append(creditValueIncrement); 207 } 208 return sb.toString(); 209 } 210 throw new InvalidParameterException("unknown/unhandled credit type scale key " + scaleKey); 211 } 212 213 /** 214 * Calculate the result values group key for the range credit value 215 * @param creditValueMin 216 * @param creditValueMax 217 * @param creditValueIncrement 218 * @param scaleKey 219 * @param contextInfo 220 * @return 221 * @throws InvalidParameterException 222 */ 223 protected String calcRangeCreditRvgName(String creditValueMin, 224 String creditValueMax, 225 String creditValueIncrement, 226 String scaleKey, 227 ContextInfo contextInfo) 228 throws InvalidParameterException { 229 230 StringBuilder sb = new StringBuilder(); 231 sb.append(creditValueMin).append(" - ").append(creditValueMax); 232 if (!creditValueIncrement.equals("1")) { 233 sb.append(" by ").append(creditValueIncrement); 234 } 235 return sb.toString(); 236 } 237 238 @Override 239 public ResultValuesGroupInfo getCreateRangeCreditResultValuesGroup(String creditValueMin, 240 String creditValueMax, 241 String creditValueIncrement, 242 String scaleKey, 243 ContextInfo contextInfo) 244 throws InvalidParameterException, 245 MissingParameterException, 246 OperationFailedException, 247 PermissionDeniedException { 248 String rvgKey = calcRangeCreditRvgKey(creditValueMin, creditValueMax, creditValueIncrement, scaleKey, contextInfo); 249 try { 250 ResultValuesGroupInfo rvg = getLrcService().getResultValuesGroup(rvgKey, contextInfo); 251 if (!rvg.getTypeKey().equals(LrcServiceConstants.RESULT_VALUES_GROUP_TYPE_KEY_RANGE)) { 252 throw new OperationFailedException("Calculated key does not point to a RANGE RVG: " + rvgKey); 253 } 254 if (!rvg.getResultScaleKey().equals(scaleKey)) { 255 throw new OperationFailedException("Calculated key does not point to an RVG of the expected scale key: " + rvgKey); 256 } 257 if (rvg.getResultValueRange() == null) { 258 throw new OperationFailedException("Calculated key does not point to an RVG with a range: " + rvgKey); 259 } 260 if (!stringNumberEquals(rvg.getResultValueRange().getMinValue(),creditValueMin)) { 261 throw new OperationFailedException("Calculated key does not point to an RVG with a range with the same min value: " + 262 rvgKey); 263 } 264 if (!stringNumberEquals(rvg.getResultValueRange().getMaxValue(), creditValueMax)) { 265 throw new OperationFailedException("Calculated key does not point to an RVG with a range with the same max value: " + 266 rvgKey); 267 } 268 if (!stringNumberEquals(rvg.getResultValueRange().getIncrement(),creditValueIncrement)) { 269 throw new OperationFailedException("Calculated key does not point to an RVG with a range with the same increment value: " + 270 rvgKey); 271 } 272 return rvg; 273 } catch (DoesNotExistException ex) { 274 // ok then create 275 } 276 277 // not found so create it 278 ResultValuesGroupInfo rvg = new ResultValuesGroupInfo(); 279 rvg.setKey(rvgKey); 280 rvg.setTypeKey(LrcServiceConstants.RESULT_VALUES_GROUP_TYPE_KEY_RANGE); 281 rvg.setStateKey(LrcServiceConstants.RESULT_GROUPS_STATE_APPROVED); 282 rvg.setName(this.calcRangeCreditRvgName(creditValueMin, creditValueMax, creditValueIncrement, scaleKey, contextInfo)); 283 rvg.setEffectiveDate(new Date()); 284 rvg.setResultScaleKey(scaleKey); 285 ResultValueRangeInfo range = new ResultValueRangeInfo(); 286 range.setMinValue(creditValueMin); 287 range.setMaxValue(creditValueMax); 288 range.setIncrement(creditValueIncrement); 289 rvg.setResultValueRange(range); 290 try { 291 rvg = getLrcService().createResultValuesGroup(rvg.getResultScaleKey(), rvg.getTypeKey(), rvg, contextInfo); 292 } catch (AlreadyExistsException ex) { 293 throw new OperationFailedException("unexpected", ex); 294 } catch (DataValidationErrorException ex) { 295 throw new OperationFailedException("unexpected", ex); 296 } 297 return rvg; 298 } 299 300 /** 301 * This method converts the two input strings into floats and returns true if they're equal, false otherwise. 302 * 303 * This is needed because getCreateRangeCreditResultValuesGroup was throwing errors saying strings 304 * 1.0 != 1. 305 * 306 * @param value1 307 * @param value2 308 * @return 309 */ 310 protected static boolean stringNumberEquals(String value1, String value2){ 311 Float f1 = new Float(value1); 312 Float f2 = new Float(value2); 313 return f1.equals(f2); 314 } 315 316 /** 317 * Calculate the result values group key for the range credit value 318 * @param values 319 * @param scaleKey 320 * @param contextInfo 321 * @return 322 * @throws InvalidParameterException 323 */ 324 protected String calcMultipleCreditRvgKey(List<String> values, 325 String scaleKey, 326 ContextInfo contextInfo) 327 throws InvalidParameterException { 328 329 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_DEGREE)) { 330 StringBuilder sb = new StringBuilder(); 331 332 // so the base string has a "." at the end... remove it 333 String baseType = LrcServiceConstants.RESULT_GROUP_KEY_KUALI_CREDITTYPE_CREDIT_BASE.substring(0, 334 LrcServiceConstants.RESULT_GROUP_KEY_KUALI_CREDITTYPE_CREDIT_BASE.length() - 1); 335 336 sb.append(baseType); 337 338 for (String value : values) { 339 sb.append("."); 340 sb.append(value); 341 } 342 return sb.toString(); 343 } 344 if (scaleKey.equals(LrcServiceConstants.RESULT_SCALE_KEY_CREDIT_REMEDIAL)) { 345 StringBuilder sb = new StringBuilder(); 346 sb.append("kuali.result.group.credit.remedial.multiple"); 347 for (String value : values) { 348 sb.append("."); 349 sb.append(value); 350 } 351 return sb.toString(); 352 } 353 throw new InvalidParameterException("unknown/unhandled credit type scale key " + scaleKey); 354 } 355 356 /** 357 * Calculate the result values group key for the range credit value 358 * @param values 359 * @param scaleKey 360 * @param contextInfo 361 * @return 362 * @throws InvalidParameterException 363 */ 364 protected String calcMultipleCreditRvgName(List<String> values, 365 String scaleKey, 366 ContextInfo contextInfo) 367 throws InvalidParameterException { 368 StringBuilder sb = new StringBuilder(); 369 sb.append("Mulitple credits "); 370 String comma = ""; 371 for (String value : values) { 372 sb.append(comma); 373 sb.append(value); 374 comma = ", "; 375 } 376 return sb.toString(); 377 } 378 379 /** 380 * Calculate the multiple credit value keys to use that matches the specified value 381 * @param creditValues 382 * @param scaleKey 383 * @return 384 * @throws InvalidParameterException 385 */ 386 protected List<String> calcMultipleCreditValueKey(List<String> creditValues, 387 String scaleKey, 388 ContextInfo contextInfo) 389 throws InvalidParameterException { 390 List<String> list = new ArrayList<String>(); 391 for (String value : creditValues) { 392 list.add(this.calcCreditValueKey(value, scaleKey, contextInfo)); 393 } 394 return list; 395 } 396 397 @Override 398 public ResultValuesGroupInfo getCreateMultipleCreditResultValuesGroup(List<String> creditValues, 399 String scaleKey, 400 ContextInfo contextInfo) 401 throws InvalidParameterException, 402 MissingParameterException, 403 OperationFailedException, 404 PermissionDeniedException { 405 String rvgKey = calcMultipleCreditRvgKey(creditValues, scaleKey, contextInfo); 406 List<String> valueKeys = this.calcMultipleCreditValueKey(creditValues, scaleKey, contextInfo); 407 try { 408 ResultValuesGroupInfo rvg = getLrcService().getResultValuesGroup(rvgKey, contextInfo); 409 if (!rvg.getTypeKey().equals(LrcServiceConstants.RESULT_VALUES_GROUP_TYPE_KEY_MULTIPLE)) { 410 throw new OperationFailedException("Calculated key does not point to a MULTIPLE RVG: " + rvgKey); 411 } 412 if (!rvg.getResultScaleKey().equals(scaleKey)) { 413 throw new OperationFailedException("Calculated key does not point to an RVG of the expected scale key: " + rvgKey); 414 } 415 if (rvg.getResultValueKeys().size() != valueKeys.size()) { 416 throw new OperationFailedException("Calculated key does not point to an RVG with the expected number of credit values: " + 417 rvgKey); 418 } 419 for (String valueKey : valueKeys) { 420 if (!rvg.getResultValueKeys().contains(valueKey)) { 421 throw new OperationFailedException("Calculated key does not point to an RVG with the expected value key : " + 422 rvgKey + " " + valueKey); 423 } 424 } 425 return rvg; 426 } catch (DoesNotExistException ex) { 427 // ok then create 428 } 429 // find/create values first 430 int i = 0; 431 for (String valueKey : valueKeys) { 432 String creditValue = creditValues.get(i); 433 i++; 434 ResultValueInfo value = null; 435 try { 436 value = getLrcService().getResultValue(valueKey, contextInfo); 437 } catch (DoesNotExistException ex) { 438 value = new ResultValueInfo(); 439 value.setKey(valueKey); 440 value.setTypeKey(LrcServiceConstants.RESULT_VALUE_TYPE_KEY_VALUE); 441 value.setStateKey(LrcServiceConstants.RESULT_VALUE_STATE_APPROVED); 442 value.setName(creditValue); 443 value.setValue(creditValue); 444 value.setNumericValue(creditValue); 445 value.setResultScaleKey(scaleKey); 446 value.setEffectiveDate(new Date()); 447 try { 448 value = getLrcService().createResultValue(value.getResultScaleKey(), value.getTypeKey(), value, contextInfo); 449 } catch (AlreadyExistsException ex1) { 450 throw new OperationFailedException("unexpected", ex); 451 } catch (DataValidationErrorException ex1) { 452 throw new OperationFailedException("unexpected", ex); 453 } catch (DoesNotExistException ex1) { 454 throw new OperationFailedException("unexpected", ex); 455 } 456 } 457 } 458 459 // not found so create it 460 ResultValuesGroupInfo rvg = new ResultValuesGroupInfo(); 461 rvg.setKey(rvgKey); 462 rvg.setTypeKey(LrcServiceConstants.RESULT_VALUES_GROUP_TYPE_KEY_MULTIPLE); 463 rvg.setStateKey(LrcServiceConstants.RESULT_GROUPS_STATE_APPROVED); 464 rvg.setName(calcMultipleCreditRvgName(creditValues, scaleKey, contextInfo)); 465 rvg.setEffectiveDate(new Date()); 466 rvg.setResultScaleKey(scaleKey); 467 rvg.getResultValueKeys().addAll(valueKeys); 468 try { 469 rvg = getLrcService().createResultValuesGroup(rvg.getResultScaleKey(), rvg.getTypeKey(), rvg, contextInfo); 470 } catch (AlreadyExistsException ex) { 471 throw new OperationFailedException("unexpected", ex); 472 } catch (DataValidationErrorException ex) { 473 throw new OperationFailedException("unexpected", ex); 474 } 475 return rvg; 476 } 477 478 /** 479 * Calculate key to use for the result value 480 * @param resultValue the value of the result 481 * @param scaleKey key used for getting the proper scale. 482 * @param contextInfo context 483 * @return the calculated value 484 */ 485 protected String calcResultValueKey(String resultValue, 486 String scaleKey, 487 ContextInfo contextInfo) { 488 StringBuilder sb = new StringBuilder(); 489 sb.append(scaleKey.replace(".scale.", ".value.")); 490 sb.append("."); 491 if(resultValue.contains(sb.toString())){ 492 return resultValue; 493 } 494 sb.append(resultValue); 495 return sb.toString(); 496 } 497 498 /** 499 * Calculate key to use for the result value 500 * @param resultValueKey the value key 501 * @param scaleKey key used for getting the proper scale. 502 * @param contextInfo context 503 * @return the calculated value 504 */ 505 private String calcResultValueFromKeyAndScale(String resultValueKey, 506 String scaleKey, 507 ContextInfo contextInfo) { 508 StringBuilder sb = new StringBuilder(); 509 sb.append(scaleKey.replace(".scale.", ".value.")); 510 sb.append("."); 511 return resultValueKey.replace(sb.toString(), ""); 512 } 513 514 @Override 515 public ResultValueInfo getCreateResultValueForScale(String resultValue, 516 String scaleKey, 517 ContextInfo contextInfo) 518 throws InvalidParameterException, 519 MissingParameterException, 520 OperationFailedException, 521 PermissionDeniedException { 522 String resultValueKey = this.calcResultValueKey(resultValue, scaleKey, contextInfo); 523 if(resultValue.equals(resultValueKey)){ 524 resultValue = calcResultValueFromKeyAndScale(resultValue, scaleKey, contextInfo); 525 } 526 try { 527 ResultValueInfo info = this.getLrcService().getResultValue(resultValueKey, contextInfo); 528 return info; 529 } catch (DoesNotExistException ex) { 530 // ok so we create it 531 } 532 // create the value 533 ResultValueInfo value = new ResultValueInfo(); 534 value.setKey(resultValueKey); 535 value.setTypeKey(LrcServiceConstants.RESULT_VALUE_TYPE_KEY_VALUE); 536 value.setStateKey(LrcServiceConstants.RESULT_VALUE_STATE_APPROVED); 537 value.setDescr(new RichTextInfo(resultValue,resultValue)); 538 value.setName(resultValue); 539 value.setValue(resultValue); 540 try { 541 Float.parseFloat(resultValue); 542 value.setNumericValue(resultValue); 543 } catch (NumberFormatException ex) { 544 // ok not a floating point number 545 } 546 value.setResultScaleKey(scaleKey); 547 value.setEffectiveDate(new Date()); 548 try { 549 value = getLrcService().createResultValue(value.getResultScaleKey(), value.getTypeKey(), value, contextInfo); 550 } catch (AlreadyExistsException ex) { 551 throw new OperationFailedException("unexpected", ex); 552 } catch (DataValidationErrorException ex) { 553 throw new OperationFailedException("unexpected", ex); 554 } catch (DoesNotExistException ex) { 555 throw new OperationFailedException("unexpected", ex); 556 } 557 return value; 558 } 559 }