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 }