View Javadoc
1   /**
2    * Copyright 2014 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   * This class is a term resolver for checking the total course attempts against
16   * the max repeatability rules for that course.
17   *
18   * Returns a string indicating error, warning, or success
19   *
20   * Created by Paul Richardson on 8/19/14
21   */
22  package org.kuali.student.enrollment.class2.courseoffering.krms.termresolver;
23  
24  import org.joda.time.DateTime;
25  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
26  import org.kuali.rice.krms.api.KrmsConstants;
27  import org.kuali.rice.krms.api.engine.TermResolutionException;
28  import org.kuali.rice.krms.api.engine.TermResolver;
29  import org.kuali.rice.krms.api.repository.RuleManagementService;
30  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
31  import org.kuali.rice.krms.api.repository.reference.ReferenceObjectBinding;
32  import org.kuali.student.common.util.krms.RulesExecutionConstants;
33  import org.kuali.student.enrollment.courseoffering.dto.RegistrationGroupInfo;
34  import org.kuali.student.enrollment.registration.engine.util.RegEnginePerformanceUtil;
35  import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants;
36  import org.kuali.student.r2.core.constants.KSKRMSServiceConstants;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  import javax.xml.namespace.QName;
41  import java.util.Collections;
42  import java.util.HashSet;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.Set;
46  
47  /**
48   * Returns String based on:
49   * -- total times the course has been attempted (prereq)
50   * -- max repeatability for this course (prereq)
51   * <p/>
52   * If total attempts >= max repeats, return an error string
53   * If total attempts < max repeats and total attempts >= (max repeats - 1), return a warning string
54   * Otherwise return a success string
55   *
56   * In addition, if there is a repeatability rule on the course offering, the result will always be a
57   * success string
58   *
59   * @author Kuali Student Team
60   */
61  public class CourseRepeatabilityTermResolver implements TermResolver<String> {
62  
63      private static final Logger LOGGER = LoggerFactory.getLogger(CourseRepeatabilityTermResolver.class);
64  
65      public final static String MAX_REPEATABILITY_ERROR = "kuali.max.repeatability.error";
66      public final static String MAX_REPEATABILITY_WARNING = "kuali.max.repeatability.warning";
67      public final static String MAX_REPEATABILITY_SUCCESS = "kuali.max.repeatability.success";
68  
69      public static final String KRMS_COURSE_CONTEXT = "10000";
70      public static final String KRMS_REPEATABILITY_TYPE = "10003";
71      public static final String KRMS_AGENDA = "Agenda";
72  
73      private RuleManagementService ruleManagementService;
74  
75      @Override
76      public String getOutput() {
77          return KSKRMSServiceConstants.TERM_RESOLVER_COURSE_REPEATABILITY;
78      }
79  
80      @Override
81      public Set<String> getParameterNames() {
82          return Collections.emptySet();
83      }
84  
85      @Override
86      public Set<String> getPrerequisites() {
87          Set<String> prereqs = new HashSet<>(2);
88          prereqs.add(RulesExecutionConstants.TOTAL_COURSE_ATTEMPTS_TERM.getName());
89          prereqs.add(RulesExecutionConstants.MAX_REPEATABILITY_TERM.getName());
90          prereqs.add(RulesExecutionConstants.REGISTRATION_GROUP_TERM.getName());
91          return Collections.unmodifiableSet(prereqs);
92      }
93  
94      @Override
95      public int getCost() {
96          return 3;
97      }
98  
99      @Override
100     public String resolve(Map<String, Object> resolvedPrereqs, Map<String, String> parameters) throws TermResolutionException {
101 
102         DateTime startTime = new DateTime();
103 
104         Integer maxRepeats = (Integer) resolvedPrereqs.get(RulesExecutionConstants.MAX_REPEATABILITY_TERM.getName());
105         Integer totalAttempts = (Integer) resolvedPrereqs.get(RulesExecutionConstants.TOTAL_COURSE_ATTEMPTS_TERM.getName());
106 
107         String errorLevel = MAX_REPEATABILITY_SUCCESS;
108 
109         if (totalAttempts != null && maxRepeats != null) {
110             if (totalAttempts >= maxRepeats) {
111                 errorLevel = MAX_REPEATABILITY_ERROR;
112             } else if (maxRepeats > 1 && totalAttempts >= maxRepeats - 1) {
113                 errorLevel = MAX_REPEATABILITY_WARNING;
114             }
115         }
116 
117         //Check if the course has a custom repeatability rule on it.
118 
119         //Grab prereqs
120         RegistrationGroupInfo rg = (RegistrationGroupInfo) resolvedPrereqs.get(RulesExecutionConstants.REGISTRATION_GROUP_TERM.getName());
121 
122         //See if the course has any custom rules on it
123         List<ReferenceObjectBinding> bindings = getRuleManagementService().findReferenceObjectBindingsByReferenceObject(CourseOfferingServiceConstants.REF_OBJECT_URI_COURSE_OFFERING, rg.getCourseOfferingId());
124         for (ReferenceObjectBinding binding : bindings) {
125             //Grab agenda definitions of a specific type
126             if (KRMS_AGENDA.equals(binding.getKrmsDiscriminatorType())) {
127                 AgendaDefinition agendaDefinition = getRuleManagementService().getAgenda(binding.getKrmsObjectId());
128                 //Check that the agenda is of type "kuali.krms.agenda.type.course.creditConstraints"
129                 if (KRMS_COURSE_CONTEXT.equals(agendaDefinition.getContextId()) && KRMS_REPEATABILITY_TYPE.equals(agendaDefinition.getTypeId())) {
130                     //If there is a repeatability rule, exclude this course from repeatability by always returning success
131                     errorLevel = MAX_REPEATABILITY_SUCCESS;
132                 }
133             }
134         }
135 
136         if (!errorLevel.equals(MAX_REPEATABILITY_SUCCESS)) {
137             LOGGER.warn("Max Repeatability check for was not successful -- Total Attempts: {}, Max Repeats: {}, Error Level: {}", totalAttempts, maxRepeats, errorLevel);
138         }
139 
140         DateTime endTime = new DateTime();
141         RegEnginePerformanceUtil.putStatistics(RegEnginePerformanceUtil.TERMS, getOutput(), startTime, endTime);
142 
143         return errorLevel;
144     }
145 
146     public RuleManagementService getRuleManagementService() {
147         if (ruleManagementService == null) {
148             ruleManagementService = GlobalResourceLoader.getService(new QName(KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0, "ruleManagementService"));
149         }
150         return ruleManagementService;
151     }
152 
153     public void setRuleManagementService(RuleManagementService ruleManagementService) {
154         this.ruleManagementService = ruleManagementService;
155     }
156 
157 }