View Javadoc
1   package org.kuali.student.enrollment.class2.courseregistration.service.impl;
2   
3   import org.apache.activemq.command.ActiveMQMapMessage;
4   import org.kuali.rice.core.api.criteria.PredicateFactory;
5   import org.kuali.rice.core.api.criteria.QueryByCriteria;
6   import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
7   import org.kuali.rice.core.api.util.type.KualiDecimal;
8   import org.kuali.student.enrollment.class2.courseregistration.service.transformer.RegistrationRequestTransformer;
9   import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
10  import org.kuali.student.enrollment.courseregistration.dto.ActivityRegistrationInfo;
11  import org.kuali.student.enrollment.courseregistration.dto.CourseRegistrationInfo;
12  import org.kuali.student.enrollment.courseregistration.dto.RegistrationRequestInfo;
13  import org.kuali.student.enrollment.courseregistration.dto.RegistrationRequestItemInfo;
14  import org.kuali.student.enrollment.courseregistration.service.CourseRegistrationService;
15  import org.kuali.student.enrollment.lpr.dto.LprInfo;
16  import org.kuali.student.enrollment.lpr.dto.LprTransactionInfo;
17  import org.kuali.student.enrollment.lpr.service.LprService;
18  import org.kuali.student.enrollment.registration.engine.service.CourseRegistrationConstants;
19  import org.kuali.student.r2.common.dto.ContextInfo;
20  import org.kuali.student.r2.common.dto.StatusInfo;
21  import org.kuali.student.r2.common.exceptions.AlreadyExistsException;
22  import org.kuali.student.r2.common.exceptions.DataValidationErrorException;
23  import org.kuali.student.r2.common.exceptions.DoesNotExistException;
24  import org.kuali.student.r2.common.exceptions.InvalidParameterException;
25  import org.kuali.student.r2.common.exceptions.MissingParameterException;
26  import org.kuali.student.r2.common.exceptions.OperationFailedException;
27  import org.kuali.student.r2.common.exceptions.PermissionDeniedException;
28  import org.kuali.student.r2.common.exceptions.ReadOnlyException;
29  import org.kuali.student.r2.common.exceptions.VersionMismatchException;
30  import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants;
31  import org.kuali.student.r2.common.util.constants.LprServiceConstants;
32  import org.kuali.student.r2.lum.util.constants.LrcServiceConstants;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  import org.springframework.jms.core.JmsTemplate;
36  import org.springframework.transaction.annotation.Transactional;
37  
38  import javax.jms.JMSException;
39  import javax.jms.MapMessage;
40  import javax.xml.namespace.QName;
41  import java.util.ArrayList;
42  import java.util.HashMap;
43  import java.util.List;
44  import java.util.Map;
45  
46  public class CourseRegistrationServiceImpl extends AbstractCourseRegistrationService implements CourseRegistrationService {
47      public static final Logger LOG = LoggerFactory.getLogger(CourseRegistrationServiceImpl.class);
48      private LprService lprService;
49      private CourseOfferingService courseOfferingService;
50      private RegistrationRequestTransformer registrationRequestTransformer;
51  
52  
53      private JmsTemplate jmsTemplate;  // needed to call ActiveMQ based Registration Engine
54  
55      /**
56       * For this implementation we are using ActiveMQ as our request engine.
57       * So, all this method does is send a message to the first node in the
58       * registration engine, kicking off the process.
59       *
60       * @param registrationRequestId an identifier for a RegistrationRequest
61       * @param contextInfo           information containing the principalId and
62       *                              locale information about the caller of the service
63       *                              operation
64       * @return Registration Response
65       * @throws AlreadyExistsException
66       * @throws DoesNotExistException
67       * @throws InvalidParameterException
68       * @throws MissingParameterException
69       * @throws OperationFailedException
70       * @throws PermissionDeniedException
71       */
72      @Override
73      public RegistrationRequestInfo submitRegistrationRequest(String registrationRequestId, ContextInfo contextInfo)
74              throws AlreadyExistsException, DoesNotExistException, InvalidParameterException,
75              MissingParameterException, OperationFailedException, PermissionDeniedException {
76  
77          LOG.info("Submitting Registration Request for id:" + registrationRequestId);
78  
79          // had to create transactional helper methods
80          RegistrationRequestInfo regRequestInfo = getRegistrationRequestToSubmit(registrationRequestId,contextInfo);
81  
82          //Check that this is a new item
83          if (!LprServiceConstants.LPRTRANS_NEW_STATE_KEY.equals(regRequestInfo.getStateKey())) {
84              throw new RuntimeException("Cannot submit request that is already initialized requestId:" + regRequestInfo.getId());
85          }
86          if (regRequestInfo.getRegistrationRequestItems().isEmpty()) {
87              throw new RuntimeException("Registration request must have registration request items:" + regRequestInfo.getId());
88          }
89          for (RegistrationRequestItemInfo requestItemInfo:regRequestInfo.getRegistrationRequestItems()) {
90              if (!LprServiceConstants.LPRTRANS_ITEM_NEW_STATE_KEY.equals(requestItemInfo.getStateKey())) {
91                  throw new RuntimeException("Cannot submit request item that is already initialized requestId:" + regRequestInfo.getId() +" itemId:" + requestItemInfo.getId());
92              }
93          }
94  
95          try {
96              MapMessage mapMessage = new ActiveMQMapMessage();
97              mapMessage.setString(CourseRegistrationConstants.REGISTRATION_QUEUE_MESSAGE_USER_ID, regRequestInfo.getRequestorId());
98              mapMessage.setString(CourseRegistrationConstants.REGISTRATION_QUEUE_MESSAGE_REG_REQ_ID, regRequestInfo.getId());
99              jmsTemplate.convertAndSend(CourseRegistrationConstants.REGISTRATION_INITIALIZATION_QUEUE, mapMessage);
100         } catch (JMSException jmsEx) {
101             throw new RuntimeException("Error submitting registration request.", jmsEx);
102         }
103 
104         return regRequestInfo;
105     }
106 
107     protected RegistrationRequestInfo getRegistrationRequestToSubmit(String registrationRequestId, ContextInfo contextInfo) throws PermissionDeniedException, MissingParameterException, InvalidParameterException, OperationFailedException, DoesNotExistException, AlreadyExistsException {
108         RegistrationRequestInfo regRequestInfo =
109                 getRegistrationRequest(registrationRequestId, contextInfo);
110 
111         if (LprServiceConstants.LPRTRANS_REG_CART_TYPE_KEY.equals(regRequestInfo.getTypeKey())) {
112             regRequestInfo = convertRegCartToRegRequest(regRequestInfo, contextInfo);
113         }
114         return regRequestInfo;
115 
116     }
117 
118     /**
119      *
120      * @param cartInfo Same as a reg request ID.  Refers to a RegistrationRequestInfo/LPRTransactionInfo
121      *                           object (with type
122      * @param contextInfo The context info
123      */
124     private RegistrationRequestInfo convertRegCartToRegRequest(RegistrationRequestInfo cartInfo, ContextInfo contextInfo)
125             throws PermissionDeniedException, MissingParameterException, InvalidParameterException,
126             OperationFailedException, DoesNotExistException, AlreadyExistsException {
127 
128         try {
129             // Create a copy of the registration request
130             RegistrationRequestInfo copy = new RegistrationRequestInfo(cartInfo);
131             // Change the type to standard
132             copy.setTypeKey(LprServiceConstants.LPRTRANS_REGISTRATION_TYPE_KEY);
133             // Remove IDs and meta
134             copy.setId(null);
135             copy.setMeta(null);
136 
137             // Empty out original cart so it can be reused
138             cartInfo.setRegistrationRequestItems(new ArrayList<RegistrationRequestItemInfo>());
139             updateRegistrationRequest(cartInfo.getId(), cartInfo, contextInfo);
140 
141             // persist this and return the copy
142             return createRegistrationRequest(copy.getTypeKey(), copy, contextInfo);
143         } catch (ReadOnlyException|DataValidationErrorException|VersionMismatchException ex) {
144             throw new OperationFailedException("Exception: " + ex.getMessage(), ex);
145         }
146     }
147     /**
148      * If the registration request type key is LPRTRANS_REG_CART_TYPE_KEY, then it will check the types
149      * of the operations of the transaction items to make sure they are "add" operations.
150      * @param registrationRequestTypeKey Type of the registration request
151      * @param regRequest The reg request to be created
152      *
153      */
154     private void verifyRegRequestCartTypeKey(String registrationRequestTypeKey, RegistrationRequestInfo regRequest)
155             throws InvalidParameterException {
156         if (LprServiceConstants.LPRTRANS_REG_CART_TYPE_KEY.equals(registrationRequestTypeKey)) {
157             for (RegistrationRequestItemInfo item: regRequest.getRegistrationRequestItems()) {
158                 // Throw exception if any item is not an "add"
159                 if (!LprServiceConstants.REQ_ITEM_ADD_TYPE_KEY.equals(item.getTypeKey())) {
160                     throw new InvalidParameterException("Only add item keys permitted for reg cart type");
161                 }
162             }
163         }
164     }
165 
166     @Override
167     @Transactional
168     public RegistrationRequestInfo createRegistrationRequest(String registrationRequestTypeKey,
169                                                              RegistrationRequestInfo registrationRequestInfo,
170                                                              ContextInfo contextInfo)
171             throws DataValidationErrorException, DoesNotExistException, InvalidParameterException,
172             MissingParameterException, OperationFailedException, PermissionDeniedException, ReadOnlyException {
173         // Check reg request of type "cart" only has add items
174         verifyRegRequestCartTypeKey(registrationRequestTypeKey, registrationRequestInfo);
175         // There is no Reg Request table. the reg request is converted to an LPR and stored.
176         LprTransactionInfo lprTransactionInfo = getRegistrationRequestTransformer().regRequest2LprTransaction(registrationRequestInfo, contextInfo);
177 
178         LprTransactionInfo newLprTransaction = getLprService().createLprTransaction(lprTransactionInfo.getTypeKey(), lprTransactionInfo, contextInfo);
179 
180         return getRegistrationRequestTransformer().lprTransaction2RegRequest(newLprTransaction, contextInfo);
181 
182     }
183 
184     @Override
185     @Transactional
186     public RegistrationRequestInfo updateRegistrationRequest(String registrationRequestId,
187                                                              RegistrationRequestInfo registrationRequestInfo,
188                                                              ContextInfo contextInfo)
189             throws DataValidationErrorException, DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, ReadOnlyException, VersionMismatchException {
190         // Check reg request of type "cart" only has add items
191         verifyRegRequestCartTypeKey(registrationRequestInfo.getTypeKey(), registrationRequestInfo);
192         // There is no Reg Request table. the reg request is converted to an LPR and stored.
193         LprTransactionInfo lprTransactionInfo
194                 = getRegistrationRequestTransformer().regRequest2LprTransaction(registrationRequestInfo, contextInfo);
195         LprTransactionInfo updated
196             = getLprService().updateLprTransaction(lprTransactionInfo.getId(), lprTransactionInfo, contextInfo);
197         return getRegistrationRequestTransformer().lprTransaction2RegRequest(updated, contextInfo);
198     }
199 
200     @Override
201     @Transactional(readOnly = true)
202     public RegistrationRequestInfo getRegistrationRequest(String registrationRequestId, ContextInfo contextInfo)
203             throws DoesNotExistException, InvalidParameterException, MissingParameterException,
204             OperationFailedException, PermissionDeniedException {
205         LprTransactionInfo lprTransaction = getLprService().getLprTransaction(registrationRequestId, contextInfo);
206         return getRegistrationRequestTransformer().lprTransaction2RegRequest(lprTransaction, contextInfo);
207     }
208 
209     @Override
210     @Transactional
211     public StatusInfo changeRegistrationRequestState(String registrationRequestId, String nextStateKey,
212                                                      ContextInfo contextInfo)
213             throws DoesNotExistException, InvalidParameterException, MissingParameterException,
214             OperationFailedException, PermissionDeniedException {
215         // Need a validation decorator to check for valid nextStateKey
216         getLprService().changeLprTransactionState(registrationRequestId, nextStateKey, contextInfo);
217         StatusInfo status = new StatusInfo();
218         status.setSuccess(Boolean.TRUE);
219         return status;
220     }
221 
222     @Override
223     public List<CourseRegistrationInfo> getCourseRegistrationsByStudent(String studentId, ContextInfo contextInfo) throws MissingParameterException, InvalidParameterException, OperationFailedException, PermissionDeniedException {
224         // Do a query for all lprs that have a matching person id. Limit to RG and CO Lprs that are in state
225         // registrant(might want to change to active in future)
226         QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
227         qbcBuilder.setPredicates(PredicateFactory.equal("personId", studentId),
228                 PredicateFactory.in("personRelationTypeId", LprServiceConstants.REGISTRANT_CO_LPR_TYPE_KEY, LprServiceConstants.REGISTRANT_RG_LPR_TYPE_KEY),
229                 PredicateFactory.equal("personRelationStateId", LprServiceConstants.ACTIVE_STATE_KEY));
230         QueryByCriteria lprCriteria = qbcBuilder.build();
231         List<LprInfo> lprs = getLprService().searchForLprs(lprCriteria, contextInfo);
232 
233         return getCourseRegistrationsFromLprs(lprs);
234     }
235 
236     @Override
237     public List<CourseRegistrationInfo> getCourseRegistrationsByStudentAndTerm(String studentId, String termId, ContextInfo contextInfo)
238             throws InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
239 
240         //Do a query for all lprs that have matching person and atp ids. Limit to RG and CO Lprs that are in state
241         // registrant(might want to change to active in future)
242         QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
243         qbcBuilder.setPredicates(PredicateFactory.equal("personId", studentId),
244                 PredicateFactory.equal("atpId", termId),
245                 PredicateFactory.in("personRelationTypeId", LprServiceConstants.REGISTRANT_CO_LPR_TYPE_KEY, LprServiceConstants.REGISTRANT_RG_LPR_TYPE_KEY),
246                 PredicateFactory.equal("personRelationStateId", LprServiceConstants.ACTIVE_STATE_KEY));
247         QueryByCriteria lprCriteria = qbcBuilder.build();
248         List<LprInfo> lprs = getLprService().searchForLprs(lprCriteria, contextInfo);
249 
250         return getCourseRegistrationsFromLprs(lprs);
251     }
252 
253     @Override
254     public List<ActivityRegistrationInfo> getActivityRegistrationsForCourseRegistration(String courseRegistrationId, ContextInfo contextInfo)
255             throws InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException {
256         //Do a search for AO lprs with the masterLPR matching the course registration
257         QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
258         qbcBuilder.setPredicates(PredicateFactory.equal("masterLprId", courseRegistrationId),
259                 PredicateFactory.in("personRelationTypeId", LprServiceConstants.REGISTRANT_AO_LPR_TYPE_KEY),
260                 PredicateFactory.equal("personRelationStateId", LprServiceConstants.ACTIVE_STATE_KEY));
261         QueryByCriteria lprCriteria = qbcBuilder.build();
262         List<LprInfo> lprs = getLprService().searchForLprs(lprCriteria, contextInfo);
263 
264         //Convert these lprs to ActivityRegistrationInfos
265         List<ActivityRegistrationInfo> activityRegistrations = new ArrayList<>(lprs.size());
266         for(LprInfo lpr:lprs){
267             ActivityRegistrationInfo activityRegistration = new ActivityRegistrationInfo();
268             activityRegistration.setTypeKey(lpr.getTypeKey());
269             activityRegistration.setStateKey(lpr.getStateKey());
270             activityRegistration.setId(lpr.getId());
271             activityRegistration.setEffectiveDate(lpr.getEffectiveDate());
272             activityRegistration.setExpirationDate(lpr.getExpirationDate());
273             activityRegistration.setTermId(lpr.getAtpId());
274             activityRegistration.setAttributes(lpr.getAttributes());
275             activityRegistration.setActivityOfferingId(lpr.getLuiId());
276             activityRegistration.setPersonId(lpr.getPersonId());
277             activityRegistration.setCourseRegistrationId(lpr.getMasterLprId());
278             activityRegistration.setMeta(lpr.getMeta());
279             activityRegistrations.add(activityRegistration);
280         }
281         return activityRegistrations;
282     }
283 
284     private List<CourseRegistrationInfo> getCourseRegistrationsFromLprs(List<LprInfo> lprs) {
285         // Get a mapping from the master lprid to the COid since CourseRegistrationInfo has both CO and RG ids
286         Map<String,String> masterLprIdToCoIdMap = new HashMap<>();
287         for (LprInfo lpr:lprs) {
288             if (LprServiceConstants.REGISTRANT_CO_LPR_TYPE_KEY.equals(lpr.getTypeKey())) {
289                 masterLprIdToCoIdMap.put(lpr.getMasterLprId(), lpr.getLuiId());
290             }
291         }
292 
293         // For each RG lpr, create a new courseRegistrationInfo and lookup the corresponding CO id
294         List<CourseRegistrationInfo> courseRegistrations = new ArrayList<>(lprs.size());
295         for (LprInfo lpr:lprs) {
296             if (LprServiceConstants.REGISTRANT_RG_LPR_TYPE_KEY.equals(lpr.getTypeKey())) {
297                 courseRegistrations.add(toCourseRegistration(lpr, masterLprIdToCoIdMap.get(lpr.getMasterLprId())));
298             }
299         }
300 
301         return courseRegistrations;
302     }
303 
304     private CourseRegistrationInfo toCourseRegistration(LprInfo rgLpr, String courseOfferingId) {
305         CourseRegistrationInfo courseRegistration = new CourseRegistrationInfo();
306         for (String rvgKey:rgLpr.getResultValuesGroupKeys()) {
307             if (rvgKey.startsWith(LrcServiceConstants.RESULT_GROUP_KEY_GRADE_BASE)) {
308                 courseRegistration.setGradingOptionId(rvgKey);
309             } else if (rvgKey.startsWith(LrcServiceConstants.RESULT_GROUP_KEY_KUALI_CREDITTYPE_CREDIT_BASE)) {
310                 //This will be replaced with just the key in the future
311                 courseRegistration.setCredits(new KualiDecimal(rvgKey.substring(LrcServiceConstants.RESULT_GROUP_KEY_KUALI_CREDITTYPE_CREDIT_BASE.length())));
312             }
313         }
314 
315         courseRegistration.setId(rgLpr.getId());
316         courseRegistration.setStateKey(rgLpr.getStateKey());
317         courseRegistration.setTypeKey(rgLpr.getTypeKey());
318         courseRegistration.setRegistrationGroupId(rgLpr.getLuiId());
319         courseRegistration.setCourseOfferingId(courseOfferingId);
320         courseRegistration.setPersonId(rgLpr.getPersonId());
321         courseRegistration.setTermId(rgLpr.getAtpId());
322         courseRegistration.setCrossListedCode(rgLpr.getCrossListedCode());
323         courseRegistration.setAttributes(rgLpr.getAttributes());
324         courseRegistration.setMeta(rgLpr.getMeta());
325         courseRegistration.setEffectiveDate(rgLpr.getEffectiveDate());
326         courseRegistration.setExpirationDate(rgLpr.getExpirationDate());
327         return courseRegistration;
328     }
329 
330     public void setJmsTemplate(JmsTemplate jmsTemplate) {
331         this.jmsTemplate = jmsTemplate;
332     }
333 
334     public LprService getLprService() {
335         if (lprService == null) {
336             lprService = GlobalResourceLoader.getService(new QName(LprServiceConstants.NAMESPACE, LprServiceConstants.SERVICE_NAME_LOCAL_PART));
337         }
338         return lprService;
339     }
340 
341     public void setLprService(LprService lprService) {
342         this.lprService = lprService;
343     }
344 
345     public CourseOfferingService getCourseOfferingService() {
346         if (courseOfferingService == null) {
347             courseOfferingService = GlobalResourceLoader.getService(new QName(CourseOfferingServiceConstants.NAMESPACE, CourseOfferingServiceConstants.SERVICE_NAME_LOCAL_PART));
348         }
349         return courseOfferingService;
350     }
351 
352     public void setCourseOfferingService(CourseOfferingService courseOfferingService) {
353         this.courseOfferingService = courseOfferingService;
354     }
355 
356     public RegistrationRequestTransformer getRegistrationRequestTransformer() {
357         return registrationRequestTransformer;
358     }
359 
360     public void setRegistrationRequestTransformer(RegistrationRequestTransformer registrationRequestTransformer) {
361         this.registrationRequestTransformer = registrationRequestTransformer;
362     }
363 }