View Javadoc
1   /*
2    * Copyright 2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may	obtain a copy of the License at
7    *
8    * 	http://www.osedu.org/licenses/ECL-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.student.enrollment.class2.courseoffering.service.impl;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.kuali.rice.core.api.criteria.QueryByCriteria;
20  import org.kuali.student.common.mock.MockService;
21  import org.kuali.student.enrollment.courseoffering.dto.AOClusterVerifyResultsInfo;
22  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingClusterInfo;
23  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingDisplayInfo;
24  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingInfo;
25  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingSetInfo;
26  import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingDisplayInfo;
27  import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo;
28  import org.kuali.student.enrollment.courseoffering.dto.FormatOfferingInfo;
29  import org.kuali.student.enrollment.courseoffering.dto.OfferingInstructorInfo;
30  import org.kuali.student.enrollment.courseoffering.dto.RegistrationGroupInfo;
31  import org.kuali.student.enrollment.courseoffering.dto.SeatPoolDefinitionInfo;
32  import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
33  import org.kuali.student.enrollment.courseofferingset.dto.SocRolloverResultItemInfo;
34  import org.kuali.student.r2.common.dto.BulkStatusInfo;
35  import org.kuali.student.r2.common.dto.ContextInfo;
36  import org.kuali.student.r2.common.dto.KeyNameInfo;
37  import org.kuali.student.r2.common.dto.MetaInfo;
38  import org.kuali.student.r2.common.dto.StatusInfo;
39  import org.kuali.student.r2.common.dto.TimeOfDayInfo;
40  import org.kuali.student.r2.common.dto.ValidationResultInfo;
41  import org.kuali.student.r2.common.exceptions.AlreadyExistsException;
42  import org.kuali.student.r2.common.exceptions.DataValidationErrorException;
43  import org.kuali.student.r2.common.exceptions.DependentObjectsExistException;
44  import org.kuali.student.r2.common.exceptions.DoesNotExistException;
45  import org.kuali.student.r2.common.exceptions.InvalidParameterException;
46  import org.kuali.student.r2.common.exceptions.MissingParameterException;
47  import org.kuali.student.r2.common.exceptions.OperationFailedException;
48  import org.kuali.student.r2.common.exceptions.PermissionDeniedException;
49  import org.kuali.student.r2.common.exceptions.ReadOnlyException;
50  import org.kuali.student.r2.common.exceptions.VersionMismatchException;
51  import org.kuali.student.r2.common.infc.ValidationResult;
52  import org.kuali.student.r2.common.util.constants.CourseOfferingSetServiceConstants;
53  import org.kuali.student.r2.core.class1.type.dto.TypeInfo;
54  import org.kuali.student.r2.core.scheduling.dto.ScheduleComponentDisplayInfo;
55  import org.kuali.student.r2.core.scheduling.dto.ScheduleDisplayInfo;
56  import org.kuali.student.r2.core.scheduling.dto.TimeSlotInfo;
57  import javax.jws.WebParam;
58  import java.util.ArrayList;
59  import java.util.Collection;
60  import java.util.Collections;
61  import java.util.Date;
62  import java.util.HashMap;
63  import java.util.HashSet;
64  import java.util.LinkedHashMap;
65  import java.util.List;
66  import java.util.Map;
67  import java.util.Set;
68  import org.kuali.student.common.UUIDHelper;
69  import org.slf4j.Logger;
70  import org.slf4j.LoggerFactory;
71  
72  public class CourseOfferingServiceMapImpl implements CourseOfferingService,
73          MockService {
74  
75      private static final Logger log = LoggerFactory.getLogger(CourseOfferingServiceMapImpl.class);
76  
77      @Override
78      public void clear() {
79  
80          this.activityOfferingMap.clear();
81          this.courseOfferingMap.clear();
82          this.formatOfferingMap.clear();
83          this.registrationGroupMap.clear();
84          this.seatPoolDefinitionMap.clear();
85  
86          activityOfferingToSeatPoolMap.clear();
87  
88          this.activityOfferingClusterMap.clear();
89  
90      }
91  
92  
93      @Override
94      public TypeInfo getCourseOfferingType(String courseOfferingTypeKey,
95              ContextInfo context) throws DoesNotExistException,
96              InvalidParameterException,
97              MissingParameterException,
98              OperationFailedException,
99              PermissionDeniedException {
100         return new TypeInfo ();
101     }
102 
103     @Override
104     public List<TypeInfo> getCourseOfferingTypes(ContextInfo context)
105             throws InvalidParameterException,
106             MissingParameterException,
107             OperationFailedException,
108             PermissionDeniedException {
109         throw new UnsupportedOperationException("Not supported yet");
110     }
111 
112     @Override
113     public List<TypeInfo> getInstructorTypesForCourseOfferingType(
114             String courseOfferingTypeKey, ContextInfo context)
115             throws DoesNotExistException,
116             InvalidParameterException,
117             MissingParameterException,
118             OperationFailedException,
119             PermissionDeniedException {
120         throw new UnsupportedOperationException("Not supported yet");
121     }
122 
123     @Override
124     public StatusInfo deleteCourseOfferingCascaded(String courseOfferingId,
125             ContextInfo context) throws DoesNotExistException,
126             InvalidParameterException,
127             MissingParameterException,
128             OperationFailedException,
129             PermissionDeniedException {
130 
131 
132         List<FormatOfferingInfo> fos = getFormatOfferingsByCourseOffering(courseOfferingId, context);
133 
134         for (FormatOfferingInfo formatOfferingInfo : fos) {
135 
136             StatusInfo status = deleteFormatOfferingCascaded(formatOfferingInfo.getId(), context);
137 
138             if (!status.getIsSuccess()) {
139                 throw new OperationFailedException("deleteFormatOfferingCascaded(): failed for id = " + formatOfferingInfo.getId());
140             }
141         }
142 
143         StatusInfo status;
144         try {
145             status = deleteCourseOffering(courseOfferingId, context);
146         } catch (DependentObjectsExistException e) {
147             throw new OperationFailedException(
148                     "deleteFormatOfferingCascaded(): failed because dependant objects still exist for courseOfferingId = " + courseOfferingId,
149                     e);
150         }
151 
152         return status;
153     }
154 
155     @Override
156     public StatusInfo deleteFormatOfferingCascaded(String formatOfferingId,
157             ContextInfo context) throws DoesNotExistException,
158             InvalidParameterException,
159             MissingParameterException,
160             OperationFailedException,
161             PermissionDeniedException {
162 
163         List<ActivityOfferingInfo> aos = getActivityOfferingsByFormatOffering(formatOfferingId, context);
164 
165         for (ActivityOfferingInfo activityOfferingInfo : aos) {
166 
167             deleteActivityOfferingCascaded(activityOfferingInfo.getId(), context);
168         }
169 
170 
171         try {
172             deleteFormatOffering(formatOfferingId, context);
173         } catch (DependentObjectsExistException e) {
174             // should never fire since we deleted the dependencies
175             throw new OperationFailedException("failed to delete format offering for id = " + formatOfferingId, e);
176         }
177 
178         return successStatus();
179     }
180 
181     @Override
182     public RegistrationGroupInfo createRegistrationGroup(
183             String formatOfferingId, String activityOfferingClusterId, String registrationGroupType,
184             RegistrationGroupInfo registrationGroupInfo,
185             ContextInfo context)
186             throws DoesNotExistException,
187             DataValidationErrorException,
188             InvalidParameterException,
189             MissingParameterException,
190             OperationFailedException,
191             PermissionDeniedException,
192             ReadOnlyException {
193         // create
194         if (!registrationGroupType.equals(registrationGroupInfo.getTypeKey())) {
195             throw new InvalidParameterException(
196                     "The type parameter does not match the type on the info object");
197         }
198         RegistrationGroupInfo copy = new RegistrationGroupInfo(
199                 registrationGroupInfo);
200         if (copy.getId() == null) {
201             copy.setId(UUIDHelper.genStringUUID());
202         }
203         copy.setMeta(newMeta(context));
204         registrationGroupMap.put(copy.getId(), copy);
205         return new RegistrationGroupInfo(copy);
206     }
207 
208     @Override
209     public CourseOfferingInfo getCourseOffering(String courseOfferingId,
210             ContextInfo context) throws DoesNotExistException,
211             InvalidParameterException,
212             MissingParameterException,
213             OperationFailedException,
214             PermissionDeniedException {
215         if (!this.courseOfferingMap.containsKey(courseOfferingId)) {
216             throw new DoesNotExistException(courseOfferingId);
217         }
218         return this.courseOfferingMap.get(courseOfferingId);
219     }
220 
221     @Override
222     public List<CourseOfferingInfo> getCourseOfferingsByIds(
223             List<String> courseOfferingIds, ContextInfo context)
224             throws DoesNotExistException,
225             InvalidParameterException,
226             MissingParameterException,
227             OperationFailedException,
228             PermissionDeniedException {
229         List<CourseOfferingInfo> list = new ArrayList<CourseOfferingInfo>();
230         for (String id : courseOfferingIds) {
231             list.add(this.getCourseOffering(id, context));
232         }
233         return list;
234     }
235 
236     @Override
237     public List<CourseOfferingInfo> getCourseOfferingsByCourse(String courseId,
238             ContextInfo context) throws DoesNotExistException,
239             InvalidParameterException,
240             MissingParameterException,
241             OperationFailedException,
242             PermissionDeniedException {
243         List<CourseOfferingInfo> list = new ArrayList<CourseOfferingInfo>();
244         for (CourseOfferingInfo info : courseOfferingMap.values()) {
245             if (courseId.equals(info.getCourseId())) {
246                 list.add(info);
247             }
248         }
249         return list;
250     }
251 
252     @Override
253     public List<CourseOfferingInfo> getCourseOfferingsByCourseAndTerm(
254             String courseId, String termId, ContextInfo context)
255             throws DoesNotExistException,
256             InvalidParameterException,
257             MissingParameterException,
258             OperationFailedException,
259             PermissionDeniedException {
260         List<CourseOfferingInfo> list = new ArrayList<CourseOfferingInfo>();
261         for (CourseOfferingInfo info : courseOfferingMap.values()) {
262             if (courseId.equals(info.getCourseId())) {
263                 if (termId.equals(info.getTermId())) {
264                     list.add(info);
265                 }
266             }
267         }
268         return list;
269     }
270 
271     @Override
272     public List<String> getCourseOfferingIdsByTerm(String termId,
273             Boolean useIncludedTerm, ContextInfo context)
274             throws DoesNotExistException,
275             InvalidParameterException,
276             MissingParameterException,
277             OperationFailedException,
278             PermissionDeniedException {
279         List<String> list = new ArrayList<String>();
280         for (CourseOfferingInfo info : courseOfferingMap.values()) {
281             if (termId.equals(info.getTermId())) {
282                 list.add(info.getId());
283             }
284             // Perhaps we should check for included terms
285         }
286         return list;
287     }
288 
289     @Override
290     public CourseOfferingInfo createCourseOffering(String courseId, String termId, String courseOfferingTypeKey,
291             CourseOfferingInfo courseOfferingInfo,
292             List<String> optionKeys, ContextInfo context)
293             throws DoesNotExistException,
294             DataValidationErrorException,
295             InvalidParameterException,
296             MissingParameterException,
297             OperationFailedException,
298             PermissionDeniedException,
299             ReadOnlyException {
300         // create
301         if (!courseOfferingTypeKey.equals(courseOfferingInfo.getTypeKey())) {
302             throw new InvalidParameterException("The type parameter does not match the type on the info object");
303         }
304         // Might want to check the rest of the readonly fields that are specified on the create to make sure they match the info object
305         CourseOfferingInfo copy = new CourseOfferingInfo(courseOfferingInfo);
306         if (copy.getId() == null) {
307             copy.setId(UUIDHelper.genStringUUID());
308         }
309         copy.setMeta(newMeta(context));
310         copy.setHasWaitlist(true);
311         courseOfferingMap.put(copy.getId(), copy);
312         log.info(
313                 "CourseOfferingMakImpl: created course offering: {} term={} for course ={}",
314                 copy.getId(), copy.getTermId(), copy.getCourseId());
315         return new CourseOfferingInfo(copy);
316     }
317 
318     @Override
319     public List<CourseOfferingInfo> getCourseOfferingsByTermAndInstructor(
320             String termId, String instructorId, ContextInfo context)
321             throws DoesNotExistException,
322             InvalidParameterException,
323             MissingParameterException,
324             OperationFailedException,
325             PermissionDeniedException {
326         List<CourseOfferingInfo> list = new ArrayList<CourseOfferingInfo>();
327         for (CourseOfferingInfo info : courseOfferingMap.values()) {
328             if (termId.equals(info.getTermId())) {
329                 if (matches(instructorId, info.getInstructors())) {
330                     list.add(info);
331                 }
332             }
333         }
334         return list;
335     }
336 
337     private boolean matches(String personId,
338             List<OfferingInstructorInfo> instructors) {
339         for (OfferingInstructorInfo instructor : instructors) {
340             if (personId.equals(instructor.getPersonId())) {
341                 return true;
342             }
343         }
344         return false;
345     }
346 
347     @Override
348     public List<String> getCourseOfferingIdsByTermAndUnitsContentOwner(
349             String termId, String unitsContentOwnerId, ContextInfo context)
350             throws DoesNotExistException,
351             InvalidParameterException,
352             MissingParameterException,
353             OperationFailedException,
354             PermissionDeniedException {
355         List<String> list = new ArrayList<String>();
356         for (CourseOfferingInfo info : courseOfferingMap.values()) {
357             if (termId.equals(info.getTermId())) {
358                 if (info.getUnitsContentOwnerOrgIds().contains(
359                         unitsContentOwnerId)) {
360                     list.add(info.getId());
361                 }
362             }
363         }
364         return list;
365     }
366 
367     @Override
368     public List<String> getCourseOfferingIdsByType(String typeKey,
369             ContextInfo context) throws DoesNotExistException,
370             InvalidParameterException,
371             MissingParameterException,
372             OperationFailedException,
373             PermissionDeniedException {
374         List<String> list = new ArrayList<String>();
375         for (CourseOfferingInfo info : courseOfferingMap.values()) {
376             if (typeKey.equals(info.getTypeKey())) {
377                 list.add(info.getId());
378             }
379         }
380         return list;
381     }
382     // cache variable
383     // The LinkedHashMap is just so the values come back in a predictable order
384     protected Map<String, CourseOfferingInfo> courseOfferingMap = new LinkedHashMap<String, CourseOfferingInfo>();
385 
386     @Override
387     public CourseOfferingInfo updateCourseOffering(String courseOfferingId,
388             CourseOfferingInfo courseOfferingInfo, ContextInfo context)
389             throws DataValidationErrorException,
390             DoesNotExistException,
391             InvalidParameterException,
392             MissingParameterException,
393             OperationFailedException,
394             PermissionDeniedException,
395             ReadOnlyException,
396             VersionMismatchException {
397         // update
398         if (!courseOfferingId.equals(courseOfferingInfo.getId())) {
399             throw new InvalidParameterException(
400                     "The id parameter does not match the id on the info object");
401         }
402         CourseOfferingInfo copy = new CourseOfferingInfo(courseOfferingInfo);
403         CourseOfferingInfo old = this.getCourseOffering(
404                 courseOfferingInfo.getId(), context);
405         if (!old.getMeta().getVersionInd()
406                 .equals(copy.getMeta().getVersionInd())) {
407             throw new VersionMismatchException(old.getMeta().getVersionInd());
408         }
409         copy.setMeta(updateMeta(copy.getMeta(), context));
410         this.courseOfferingMap.put(courseOfferingInfo.getId(), copy);
411         return new CourseOfferingInfo(copy);
412     }
413 
414     @Override
415     public CourseOfferingInfo updateCourseOfferingFromCanonical(
416             String courseOfferingId, List<String> optionKeys,
417             ContextInfo context) throws DataValidationErrorException,
418             DoesNotExistException,
419             InvalidParameterException,
420             MissingParameterException,
421             OperationFailedException,
422             PermissionDeniedException,
423             VersionMismatchException {
424         return this.getCourseOffering(courseOfferingId, context);
425     }
426 
427     @Override
428     public StatusInfo deleteCourseOffering(String courseOfferingId,
429             ContextInfo context) throws DoesNotExistException,
430             InvalidParameterException,
431             MissingParameterException,
432             OperationFailedException,
433             PermissionDeniedException,
434             DependentObjectsExistException {
435 
436         for (FormatOfferingInfo fo : formatOfferingMap.values()) {
437             // See if any format offerings are still connected to COs
438             if (fo.getCourseOfferingId().equals(courseOfferingId)) {
439                 throw new DependentObjectsExistException("Format offering still attached to CO (" + courseOfferingId + ")");
440             }
441         }
442         if (this.courseOfferingMap.remove(courseOfferingId) == null) {
443             throw new DoesNotExistException(courseOfferingId);
444         }
445         return successStatus();
446     }
447 
448     @Override
449     public List<ValidationResultInfo> validateCourseOffering(
450             String validationType, CourseOfferingInfo courseOfferingInfo,
451             ContextInfo context) throws DoesNotExistException,
452             InvalidParameterException,
453             MissingParameterException,
454             OperationFailedException {
455         // validate
456         return new ArrayList<ValidationResultInfo>();
457     }
458 
459     @Override
460     public List<ValidationResultInfo> validateCourseOfferingFromCanonical(
461             CourseOfferingInfo courseOfferingInfo, List<String> optionKeys,
462             ContextInfo context) throws DoesNotExistException,
463             InvalidParameterException,
464             MissingParameterException,
465             OperationFailedException,
466             PermissionDeniedException {
467         List<ValidationResultInfo> list = new ArrayList<ValidationResultInfo> ();
468         return list;
469     }
470 
471     @Override
472     public FormatOfferingInfo getFormatOffering(String formatOfferingId,
473             ContextInfo context) throws DoesNotExistException,
474             InvalidParameterException,
475             MissingParameterException,
476             OperationFailedException,
477             PermissionDeniedException {
478         if (!this.formatOfferingMap.containsKey(formatOfferingId)) {
479             throw new DoesNotExistException(formatOfferingId);
480         }
481         return this.formatOfferingMap.get(formatOfferingId);
482     }
483 
484     @Override
485     public List<FormatOfferingInfo> getFormatOfferingsByCourseOffering(
486             String courseOfferingId, ContextInfo context)
487             throws DoesNotExistException,
488             InvalidParameterException,
489             MissingParameterException,
490             OperationFailedException,
491             PermissionDeniedException {
492         List<FormatOfferingInfo> list = new ArrayList<FormatOfferingInfo>();
493         for (FormatOfferingInfo info : formatOfferingMap.values()) {
494             if (courseOfferingId.equals(info.getCourseOfferingId())) {
495                 list.add(info);
496             }
497         }
498         return list;
499     }
500     // cache variable
501     // The LinkedHashMap is just so the values come back in a predictable order
502     private Map<String, FormatOfferingInfo> formatOfferingMap = new LinkedHashMap<String, FormatOfferingInfo>();
503 
504     @Override
505     public FormatOfferingInfo createFormatOffering(String courseOfferingId,
506             String formatId, String formatOfferingType,
507             FormatOfferingInfo formatOfferingInfo, ContextInfo context)
508             throws DoesNotExistException,
509             DataValidationErrorException,
510             InvalidParameterException,
511             MissingParameterException,
512             OperationFailedException,
513             PermissionDeniedException,
514             ReadOnlyException {
515         CourseOfferingInfo co = this.getCourseOffering(courseOfferingId,
516                 context);
517         // create
518         if (!courseOfferingId.equals(formatOfferingInfo.getCourseOfferingId())) {
519             throw new InvalidParameterException(
520                     "The course offering id parameter does not match the course offering id on the info object");
521         }
522         if (!formatId.equals(formatOfferingInfo.getFormatId())) {
523             throw new InvalidParameterException(
524                     "The format id parameter does not match the format id on the info object");
525         }
526         if (!formatOfferingType.equals(formatOfferingInfo.getTypeKey())) {
527             throw new InvalidParameterException(
528                     "The type parameter does not match the type on the info object");
529         }
530         // Might want to check the rest of the readonly fields that are specified on the
531         // create to make sure they match the info object
532         FormatOfferingInfo copy = new FormatOfferingInfo(formatOfferingInfo);
533         if (copy.getId() == null) {
534             copy.setId(UUIDHelper.genStringUUID());
535         }
536         copy.setTermId(co.getTermId());
537         copy.setMeta(newMeta(context));
538         formatOfferingMap.put(copy.getId(), copy);
539         log.debug("CourseOfferingMockImpl: created format offering: {} term={} for format={} and course offering={}",
540                 copy.getId(), copy.getTermId(), copy.getFormatId(), copy.getCourseOfferingId());
541         return new FormatOfferingInfo(copy);
542     }
543 
544     @Override
545     public FormatOfferingInfo updateFormatOffering(String formatOfferingId,
546             FormatOfferingInfo formatOfferingInfo, ContextInfo context)
547             throws DataValidationErrorException,
548             DoesNotExistException,
549             InvalidParameterException,
550             MissingParameterException,
551             OperationFailedException,
552             PermissionDeniedException,
553             ReadOnlyException,
554             VersionMismatchException {
555         // update
556         if (!formatOfferingId.equals(formatOfferingInfo.getId())) {
557             throw new InvalidParameterException(
558                     "The id parameter does not match the id on the info object");
559         }
560         FormatOfferingInfo copy = new FormatOfferingInfo(formatOfferingInfo);
561         FormatOfferingInfo old = this.getFormatOffering(
562                 formatOfferingInfo.getId(), context);
563         if (!old.getMeta().getVersionInd()
564                 .equals(copy.getMeta().getVersionInd())) {
565             throw new VersionMismatchException(old.getMeta().getVersionInd());
566         }
567         copy.setMeta(updateMeta(copy.getMeta(), context));
568         this.formatOfferingMap.put(formatOfferingInfo.getId(), copy);
569         return new FormatOfferingInfo(copy);
570     }
571 
572     @Override
573     public List<ValidationResultInfo> validateFormatOffering(
574             String validationType, FormatOfferingInfo formatOfferingInfo,
575             ContextInfo context) throws DoesNotExistException,
576             InvalidParameterException,
577             MissingParameterException,
578             OperationFailedException {
579         // validate
580         return new ArrayList<ValidationResultInfo>();
581     }
582 
583     @Override
584     public StatusInfo deleteFormatOffering(String formatOfferingId,
585             ContextInfo context) throws DoesNotExistException,
586             InvalidParameterException,
587             MissingParameterException,
588             OperationFailedException,
589             PermissionDeniedException,
590             DependentObjectsExistException {
591         for (ActivityOfferingInfo aoInfo : activityOfferingMap.values()) {
592             // test if AOs still attached to FO, if so, throw dependent object exists exception
593             if (aoInfo.getFormatOfferingId().equals(formatOfferingId)) {
594                 throw new DependentObjectsExistException("Activity offerings still attached to FO (" + formatOfferingId + ")");
595             }
596         }
597         if (this.formatOfferingMap.remove(formatOfferingId) == null) {
598             throw new DoesNotExistException(formatOfferingId);
599         }
600         return successStatus();
601     }
602 
603     @Override
604     public TypeInfo getActivityOfferingType(String activityOfferingTypeKey,
605             ContextInfo context) throws DoesNotExistException,
606             InvalidParameterException,
607             MissingParameterException,
608             OperationFailedException,
609             PermissionDeniedException {
610         TypeInfo info = new TypeInfo();
611         info.setKey(activityOfferingTypeKey);
612         info.setName(activityOfferingTypeKey + " name");
613         return info;
614     }
615 
616     @Override
617     public List<TypeInfo> getActivityOfferingTypes(ContextInfo context)
618             throws InvalidParameterException,
619             MissingParameterException,
620             OperationFailedException,
621             PermissionDeniedException {
622         List<TypeInfo> list = new ArrayList<TypeInfo>();
623         return list;
624     }
625 
626     @Override
627     public List<TypeInfo> getActivityOfferingTypesForActivityType(
628             String activityTypeKey, ContextInfo context)
629             throws DoesNotExistException,
630             InvalidParameterException,
631             MissingParameterException,
632             OperationFailedException,
633             PermissionDeniedException {
634         List<TypeInfo> list = new ArrayList<TypeInfo>();
635         return list;
636     }
637 
638     @Override
639     public List<TypeInfo> getInstructorTypesForActivityOfferingType(
640             String activityOfferingTypeKey, ContextInfo context)
641             throws DoesNotExistException,
642             InvalidParameterException,
643             MissingParameterException,
644             OperationFailedException,
645             PermissionDeniedException {
646         throw new OperationFailedException("not implemented");
647     }
648 
649     @Override
650     public ActivityOfferingInfo getActivityOffering(String activityOfferingId,
651             ContextInfo context) throws DoesNotExistException,
652             InvalidParameterException,
653             MissingParameterException,
654             OperationFailedException,
655             PermissionDeniedException {
656         if (!this.activityOfferingMap.containsKey(activityOfferingId)) {
657             throw new DoesNotExistException(activityOfferingId);
658         }
659         return this.activityOfferingMap.get(activityOfferingId);
660     }
661 
662     @Override
663     public List<ActivityOfferingInfo> getActivityOfferingsByIds(
664             List<String> activityOfferingIds, ContextInfo context)
665             throws DoesNotExistException,
666             InvalidParameterException,
667             MissingParameterException,
668             OperationFailedException,
669             PermissionDeniedException {
670         List<ActivityOfferingInfo> list = new ArrayList<ActivityOfferingInfo>();
671         for (String id : activityOfferingIds) {
672             list.add(this.getActivityOffering(id, context));
673         }
674         return list;
675     }
676 
677     @Override
678     public List<ActivityOfferingInfo> getActivityOfferingsByCourseOffering(
679             String courseOfferingId, ContextInfo context)
680             throws DoesNotExistException,
681             InvalidParameterException,
682             MissingParameterException,
683             OperationFailedException,
684             PermissionDeniedException {
685         List<ActivityOfferingInfo> list = new ArrayList<ActivityOfferingInfo>();
686         for (ActivityOfferingInfo info : activityOfferingMap.values()) {
687 
688             if (courseOfferingId.equals(info.getCourseOfferingId())) {
689                 list.add(info);
690             }
691         }
692 
693         return list;
694     }
695 
696     @Override
697     public List<ActivityOfferingInfo> getActivityOfferingsByFormatOffering(
698             String formatOfferingId, ContextInfo contextInfo)
699             throws DoesNotExistException,
700             InvalidParameterException,
701             MissingParameterException,
702             OperationFailedException,
703             PermissionDeniedException {
704         List<ActivityOfferingInfo> list = new ArrayList<ActivityOfferingInfo>();
705         for (ActivityOfferingInfo info : activityOfferingMap.values()) {
706             if (formatOfferingId.equals(info.getFormatOfferingId())) {
707                 list.add(info);
708             }
709         }
710         return list;
711     }
712 
713     @Override
714     public List<ActivityOfferingInfo> getActivityOfferingsWithoutClusterByFormatOffering(String formatOfferingId,
715             ContextInfo contextInfo) throws DoesNotExistException,
716             InvalidParameterException,
717             MissingParameterException,
718             OperationFailedException,
719             PermissionDeniedException {
720 
721         List<ActivityOfferingInfo> aos = getActivityOfferingsByFormatOffering(formatOfferingId, contextInfo);
722 
723         Map<String, ActivityOfferingInfo> aoMap = new HashMap<String, ActivityOfferingInfo>();
724 
725         for (ActivityOfferingInfo activityOfferingInfo : aos) {
726 
727             aoMap.put(activityOfferingInfo.getId(), activityOfferingInfo);
728 
729         }
730 
731         List<ActivityOfferingClusterInfo> aocs = getActivityOfferingClustersByFormatOffering(formatOfferingId, contextInfo);
732 
733         for (ActivityOfferingClusterInfo activityOfferingClusterInfo : aocs) {
734 
735             for (ActivityOfferingSetInfo aoSet : activityOfferingClusterInfo.getActivityOfferingSets()) {
736 
737                 for (String aoId : aoSet.getActivityOfferingIds()) {
738 
739                     aoMap.remove(aoId);
740                 }
741             }
742         }
743 
744         return new ArrayList<ActivityOfferingInfo>(aoMap.values());
745     }
746 
747     @Override
748     public List<ActivityOfferingInfo> getActivityOfferingsByFormatOfferingWithoutRegGroup(String formatOfferingId,
749             ContextInfo context) throws DoesNotExistException,
750             InvalidParameterException,
751             MissingParameterException,
752             OperationFailedException,
753             PermissionDeniedException {
754         throw new OperationFailedException("unsupported");
755     }
756 
757     @Override
758     public List<String> getAllowedTimeSlotIdsForActivityOffering(@WebParam(name = "activityOfferingId") String activityOfferingId,
759             @WebParam(name = "contextInfo") ContextInfo contextInfo) throws DoesNotExistException,
760             InvalidParameterException,
761             MissingParameterException,
762             OperationFailedException,
763             PermissionDeniedException {
764         throw new OperationFailedException("unsupported");
765     }
766 
767     @Override
768     public List<TimeSlotInfo> getAllowedTimeSlotsForActivityOffering(
769             @WebParam(name = "activityOfferingId") String activityOfferingId,
770             @WebParam(name = "contextInfo") ContextInfo contextInfo) throws DoesNotExistException,
771             InvalidParameterException,
772             MissingParameterException,
773             OperationFailedException,
774             PermissionDeniedException {
775         throw new OperationFailedException("unsupported");
776     }
777 
778     @Override
779     public List<TimeSlotInfo> getAllowedTimeSlotsByDaysAndStartTimeForActivityOffering(
780             @WebParam(name = "activityOfferingId") String activityOfferingId,
781             @WebParam(name = "daysOfWeek") List<Integer> daysOfWeek, @WebParam(name = "startTime") TimeOfDayInfo startTime,
782             @WebParam(name = "contextInfo") ContextInfo contextInfo) throws DoesNotExistException,
783             InvalidParameterException,
784             MissingParameterException,
785             OperationFailedException,
786             PermissionDeniedException {
787         throw new OperationFailedException("unsupported");
788     }
789     // cache variable
790     // The LinkedHashMap is just so the values come back in a predictable order
791     private Map<String, ActivityOfferingInfo> activityOfferingMap = new LinkedHashMap<String, ActivityOfferingInfo>();
792 
793     @Override
794     public ActivityOfferingInfo createActivityOffering(String formatOfferingId,
795             String activityId, String activityOfferingTypeKey,
796             ActivityOfferingInfo activityOfferingInfo, ContextInfo context)
797             throws DoesNotExistException,
798             DataValidationErrorException,
799             InvalidParameterException,
800             MissingParameterException,
801             OperationFailedException,
802             PermissionDeniedException,
803             ReadOnlyException {
804         FormatOfferingInfo fo = this.getFormatOffering(formatOfferingId,
805                 context);
806         // create
807         if (!formatOfferingId
808                 .equals(activityOfferingInfo.getFormatOfferingId())) {
809             throw new InvalidParameterException(
810                     "The format offering id parameter does not match the format offering id on the info object");
811         }
812         if (!activityId.equals(activityOfferingInfo.getActivityId())) {
813             throw new InvalidParameterException(
814                     "The activity id parameter does not match the activity id on the info object");
815         }
816         if (!activityOfferingTypeKey.equals(activityOfferingInfo.getTypeKey())) {
817             throw new InvalidParameterException(
818                     "The type parameter does not match the type on the info object");
819         }
820         // Might want to check the rest of the readonly fields that are specified on the
821         // create to make sure they match the info object
822         ActivityOfferingInfo copy = new ActivityOfferingInfo(
823                 activityOfferingInfo);
824         if (copy.getId() == null) {
825             copy.setId(UUIDHelper.genStringUUID());
826         }
827         copy.setTermId(fo.getTermId());
828         copy.setMeta(newMeta(context));
829         activityOfferingMap.put(copy.getId(), copy);
830         log.debug("CourseOfferingMockImpl: created activity offering: {} term={} for activity={} and format offering={}",
831                 copy.getId(), copy.getTermId(), copy.getActivityId(), copy.getFormatOfferingId());
832         return new ActivityOfferingInfo(copy);
833     }
834 
835     @Override
836     public ActivityOfferingInfo copyActivityOffering(String activityOfferingId,
837             ContextInfo context) throws DoesNotExistException,
838             DataValidationErrorException,
839             InvalidParameterException,
840             MissingParameterException,
841             OperationFailedException,
842             PermissionDeniedException,
843             ReadOnlyException {
844         throw new OperationFailedException(
845                 "copyActivityOffering has not been implemented");
846     }
847 
848     @Override
849     public List<ActivityOfferingInfo> generateActivityOfferings(
850             String formatOfferingId, String activityOfferingType,
851             Integer quantity, ContextInfo context)
852             throws InvalidParameterException,
853             MissingParameterException,
854             OperationFailedException,
855             PermissionDeniedException {
856         throw new OperationFailedException(
857                 "generateActivityOfferings has not been implemented");
858     }
859 
860     @Override
861     public ActivityOfferingInfo updateActivityOffering(
862             String activityOfferingId,
863             ActivityOfferingInfo activityOfferingInfo, ContextInfo context)
864             throws DataValidationErrorException,
865             DoesNotExistException,
866             InvalidParameterException,
867             MissingParameterException,
868             OperationFailedException,
869             PermissionDeniedException,
870             VersionMismatchException,
871             ReadOnlyException {
872         // update
873         if (!activityOfferingId.equals(activityOfferingInfo.getId())) {
874             throw new InvalidParameterException(
875                     "The id parameter does not match the id on the info object");
876         }
877         ActivityOfferingInfo copy = new ActivityOfferingInfo(
878                 activityOfferingInfo);
879         ActivityOfferingInfo old = this.getActivityOffering(
880                 activityOfferingInfo.getId(), context);
881         if (!old.getMeta().getVersionInd()
882                 .equals(copy.getMeta().getVersionInd())) {
883             throw new VersionMismatchException(old.getMeta().getVersionInd());
884         }
885         copy.setMeta(updateMeta(copy.getMeta(), context));
886         this.activityOfferingMap.put(activityOfferingInfo.getId(), copy);
887         return new ActivityOfferingInfo(copy);
888     }
889 
890     @Override
891     public StatusInfo deleteActivityOffering(String activityOfferingId,
892             ContextInfo context) throws DoesNotExistException,
893             InvalidParameterException,
894             MissingParameterException,
895             OperationFailedException,
896             PermissionDeniedException,
897             DependentObjectsExistException {
898 
899         for (RegistrationGroupInfo rg : this.registrationGroupMap.values()) {
900 
901             if (rg.getActivityOfferingIds().contains(activityOfferingId)) {
902                 throw new DependentObjectsExistException("Registration Groups Exist for Activity id = " + activityOfferingId);
903             }
904         }
905 
906         List<String> seatpoolIds = activityOfferingToSeatPoolMap.get(activityOfferingId);
907         if (seatpoolIds != null && !seatpoolIds.isEmpty()) {
908             throw new DependentObjectsExistException("Seatpools exists for Activity id = " + activityOfferingId);
909         }
910 
911         if (this.activityOfferingMap.remove(activityOfferingId) == null) {
912             throw new DoesNotExistException(activityOfferingId);
913         }
914         return successStatus();
915     }
916 
917     @Override
918     public StatusInfo deleteActivityOfferingCascaded(String activityOfferingId,
919             ContextInfo context) throws DoesNotExistException,
920             InvalidParameterException,
921             MissingParameterException,
922             OperationFailedException,
923             PermissionDeniedException {
924 
925         // delete seat pool registrations
926 
927         List<SeatPoolDefinitionInfo> spls = getSeatPoolDefinitionsForActivityOffering(activityOfferingId, context);
928         List<String> seatpoolIds = new ArrayList<String>();
929         for (SeatPoolDefinitionInfo spInfo : spls) {
930             seatpoolIds.add(spInfo.getId());
931         }
932         // Delete the attachments from AOs to seatpools
933         List<String> fetchedIds = activityOfferingToSeatPoolMap.get(activityOfferingId);
934         if (fetchedIds != null) {
935             fetchedIds.removeAll(seatpoolIds); // Get rid of seatpool IDs in this association
936         }
937 
938         for (SeatPoolDefinitionInfo spl : spls) {
939 
940             StatusInfo status = deleteSeatPoolDefinition(spl.getId(), context);
941 
942             if (!status.getIsSuccess()) {
943                 throw new OperationFailedException(status.getMessage());
944             }
945 
946         }
947 
948 
949         // delete registration groups
950 
951         // intentionally separated to avoid a concurrent modification exception on delete.
952         ArrayList<RegistrationGroupInfo> rgs = new ArrayList<RegistrationGroupInfo>(this.registrationGroupMap.values());
953 
954         for (RegistrationGroupInfo rg : rgs) {
955 
956             if (rg.getActivityOfferingIds().contains(activityOfferingId)) {
957                 StatusInfo status = deleteRegistrationGroup(rg.getId(), context);
958 
959                 if (!status.getIsSuccess()) {
960                     throw new OperationFailedException(status.getMessage());
961                 }
962             }
963         }
964 
965         // Remove the AO from the AOC
966         for (ActivityOfferingClusterInfo cluster : this.activityOfferingClusterMap.values()) {
967             for (ActivityOfferingSetInfo set : cluster.getActivityOfferingSets()) {
968                 if (set.getActivityOfferingIds().contains(activityOfferingId)) {
969                     set.getActivityOfferingIds().remove(activityOfferingId);
970                 }
971             }
972         }
973 
974         // delete activity offering
975         try {
976             return deleteActivityOffering(activityOfferingId, context);
977         } catch (DependentObjectsExistException e) {
978             throw new OperationFailedException(
979                     "Dependent object still exists for Activity Offering with id = " + activityOfferingId, e);
980         }
981     }
982 
983     @Override
984     public StatusInfo scheduleActivityOffering(String activityOfferingId,
985             ContextInfo contextInfo) throws DoesNotExistException,
986             InvalidParameterException,
987             MissingParameterException,
988             OperationFailedException,
989             PermissionDeniedException {
990         throw new OperationFailedException("implement for M5");
991     }
992 
993     @Override
994     public List<ValidationResultInfo> validateActivityOffering(
995             String validationType, ActivityOfferingInfo activityOfferingInfo,
996             ContextInfo context) throws DoesNotExistException,
997             InvalidParameterException,
998             MissingParameterException,
999             OperationFailedException {
1000         // validate
1001         return new ArrayList<ValidationResultInfo>();
1002     }
1003 
1004     @Override
1005     public Float calculateInClassContactHoursForTerm(String activityOfferingId,
1006             ContextInfo context) throws DoesNotExistException,
1007             InvalidParameterException,
1008             MissingParameterException,
1009             OperationFailedException,
1010             PermissionDeniedException {
1011         throw new OperationFailedException(
1012                 "calculateInClassContactHoursForTerm has not been implemented");
1013     }
1014 
1015     @Override
1016     public Float calculateOutofClassContactHoursForTerm(
1017             String activityOfferingId, ContextInfo context)
1018             throws DoesNotExistException,
1019             InvalidParameterException,
1020             MissingParameterException,
1021             OperationFailedException,
1022             PermissionDeniedException {
1023         throw new OperationFailedException(
1024                 "calculateOutofClassContactHoursForTerm has not been implemented");
1025     }
1026 
1027     @Override
1028     public Float calculateTotalContactHoursForTerm(String activityOfferingId,
1029             ContextInfo context) throws DoesNotExistException,
1030             InvalidParameterException,
1031             MissingParameterException,
1032             OperationFailedException,
1033             PermissionDeniedException {
1034         throw new OperationFailedException(
1035                 "calculateTotalContactHoursForTerm has not been implemented");
1036     }
1037 
1038     @Override
1039     public RegistrationGroupInfo getRegistrationGroup(
1040             String registrationGroupId, ContextInfo context)
1041             throws DoesNotExistException,
1042             InvalidParameterException,
1043             MissingParameterException,
1044             OperationFailedException,
1045             PermissionDeniedException {
1046         if (!this.registrationGroupMap.containsKey(registrationGroupId)) {
1047             throw new DoesNotExistException(registrationGroupId);
1048         }
1049         return this.registrationGroupMap.get(registrationGroupId);
1050     }
1051 
1052     @Override
1053     public List<RegistrationGroupInfo> getRegistrationGroupsByIds(
1054             List<String> registrationGroupIds, ContextInfo context)
1055             throws DoesNotExistException,
1056             InvalidParameterException,
1057             MissingParameterException,
1058             OperationFailedException,
1059             PermissionDeniedException {
1060         List<RegistrationGroupInfo> list = new ArrayList<RegistrationGroupInfo>();
1061         for (String id : registrationGroupIds) {
1062             list.add(this.getRegistrationGroup(id, context));
1063         }
1064         return list;
1065     }
1066 
1067     @Override
1068     public List<RegistrationGroupInfo> getRegistrationGroupsForCourseOffering(
1069             String courseOfferingId, ContextInfo context)
1070             throws DoesNotExistException,
1071             InvalidParameterException,
1072             MissingParameterException,
1073             OperationFailedException,
1074             PermissionDeniedException {
1075 
1076         List<RegistrationGroupInfo> regGroupList = new ArrayList<RegistrationGroupInfo>();
1077 
1078         for (RegistrationGroupInfo rg : this.registrationGroupMap.values()) {
1079             if (rg.getCourseOfferingId().equals(courseOfferingId)) {
1080                 regGroupList.add(rg);
1081             }
1082         }
1083 
1084         return regGroupList;
1085     }
1086 
1087     @Override
1088     public List<RegistrationGroupInfo> getRegistrationGroupsWithActivityOfferings(
1089             List<String> activityOfferingIds, ContextInfo context)
1090             throws DoesNotExistException,
1091             InvalidParameterException,
1092             MissingParameterException,
1093             OperationFailedException,
1094             PermissionDeniedException {
1095 
1096         List<RegistrationGroupInfo> regGroupList = new ArrayList<RegistrationGroupInfo>();
1097 
1098         for (RegistrationGroupInfo rg : this.registrationGroupMap.values()) {
1099             if (CollectionUtils.isSubCollection(activityOfferingIds,
1100                     rg.getActivityOfferingIds())) {
1101                 regGroupList.add(rg);
1102             }
1103         }
1104 
1105         return regGroupList;
1106 
1107     }
1108 
1109     @Override
1110     public List<RegistrationGroupInfo> getRegistrationGroupsByActivityOffering(
1111             @WebParam(name = "activityOfferingId") String activityOfferingId, @WebParam(name = "context") ContextInfo context)
1112             throws DoesNotExistException,
1113             InvalidParameterException,
1114             MissingParameterException,
1115             OperationFailedException,
1116             PermissionDeniedException {
1117         List<RegistrationGroupInfo> regGroupList = new ArrayList<RegistrationGroupInfo>();
1118 
1119         for (RegistrationGroupInfo rg : this.registrationGroupMap.values()) {
1120             if (rg.getActivityOfferingIds().contains(activityOfferingId)) {
1121                 regGroupList.add(rg);
1122             }
1123         }
1124 
1125         return regGroupList;
1126     }
1127 
1128     @Override
1129     public List<RegistrationGroupInfo> getRegistrationGroupsByFormatOffering(
1130             String formatOfferingId, ContextInfo context)
1131             throws DoesNotExistException,
1132             InvalidParameterException,
1133             MissingParameterException,
1134             OperationFailedException,
1135             PermissionDeniedException {
1136 
1137         List<RegistrationGroupInfo> regGroupList = new ArrayList<RegistrationGroupInfo>();
1138 
1139         for (RegistrationGroupInfo rg : this.registrationGroupMap.values()) {
1140 
1141             if (rg.getFormatOfferingId().equals(formatOfferingId)) {
1142                 regGroupList.add(rg);
1143             }
1144         }
1145 
1146         return regGroupList;
1147 
1148     }
1149     // cache variable
1150     // The LinkedHashMap is just so the values come back in a predictable order
1151     private Map<String, RegistrationGroupInfo> registrationGroupMap = new LinkedHashMap<String, RegistrationGroupInfo>();
1152 
1153     @Override
1154     public RegistrationGroupInfo updateRegistrationGroup(
1155             String registrationGroupId,
1156             RegistrationGroupInfo registrationGroupInfo, ContextInfo context)
1157             throws DataValidationErrorException,
1158             DoesNotExistException,
1159             InvalidParameterException,
1160             MissingParameterException,
1161             OperationFailedException,
1162             PermissionDeniedException,
1163             ReadOnlyException,
1164             VersionMismatchException {
1165         // update
1166         if (!registrationGroupId.equals(registrationGroupInfo.getId())) {
1167             throw new InvalidParameterException(
1168                     "The id parameter does not match the id on the info object");
1169         }
1170         RegistrationGroupInfo copy = new RegistrationGroupInfo(
1171                 registrationGroupInfo);
1172         RegistrationGroupInfo old = this.getRegistrationGroup(
1173                 registrationGroupInfo.getId(), context);
1174         if (!old.getMeta().getVersionInd()
1175                 .equals(copy.getMeta().getVersionInd())) {
1176             throw new VersionMismatchException(old.getMeta().getVersionInd());
1177         }
1178         copy.setMeta(updateMeta(copy.getMeta(), context));
1179         this.registrationGroupMap.put(registrationGroupInfo.getId(), copy);
1180         return new RegistrationGroupInfo(copy);
1181     }
1182 
1183     @Override
1184     public StatusInfo deleteRegistrationGroup(String registrationGroupId,
1185             ContextInfo context) throws DoesNotExistException,
1186             InvalidParameterException,
1187             MissingParameterException,
1188             OperationFailedException,
1189             PermissionDeniedException {
1190         if (this.registrationGroupMap.remove(registrationGroupId) == null) {
1191             throw new DoesNotExistException(registrationGroupId);
1192         }
1193         return successStatus();
1194     }
1195 
1196     private BulkStatusInfo bulkDeleteRegistrationGroup(RegistrationGroupInfo regGroup, ContextInfo context) throws
1197             DoesNotExistException,
1198             InvalidParameterException,
1199             MissingParameterException,
1200             OperationFailedException,
1201             PermissionDeniedException {
1202 
1203         StatusInfo status = deleteRegistrationGroup(regGroup.getId(), context);
1204 
1205         BulkStatusInfo bulkStatus = new BulkStatusInfo();
1206 
1207         bulkStatus.setId(regGroup.getId());
1208         bulkStatus.setSuccess(status.getIsSuccess());
1209         bulkStatus.setMessage("Registration Group Deleted");
1210 
1211         return bulkStatus;
1212     }
1213 
1214     @Override
1215     public List<BulkStatusInfo> deleteRegistrationGroupsByFormatOffering(
1216             String formatOfferingId, ContextInfo context)
1217             throws InvalidParameterException,
1218             MissingParameterException,
1219             OperationFailedException,
1220             PermissionDeniedException {
1221 
1222         List<BulkStatusInfo> rgChanges = new ArrayList<BulkStatusInfo>();
1223         List<RegistrationGroupInfo> rgs;
1224         try {
1225             rgs = getRegistrationGroupsByFormatOffering(formatOfferingId, context);
1226 
1227             for (RegistrationGroupInfo rg : rgs) {
1228 
1229                 rgChanges.add(bulkDeleteRegistrationGroup(rg, context));
1230             }
1231 
1232         } catch (DoesNotExistException e) {
1233             throw new OperationFailedException(
1234                     "deleteRegistrationGroupsByFormatOffering (formatOfferingId=" + formatOfferingId + "): failed.", e);
1235         }
1236 
1237         return rgChanges;
1238     }
1239 
1240     @Override
1241     public List<BulkStatusInfo> deleteGeneratedRegistrationGroupsByFormatOffering(
1242             String formatOfferingId, ContextInfo context)
1243             throws InvalidParameterException,
1244             MissingParameterException,
1245             OperationFailedException,
1246             PermissionDeniedException {
1247 
1248         List<RegistrationGroupInfo> rgs;
1249         List<BulkStatusInfo> rgChanges = new ArrayList<BulkStatusInfo>();
1250 
1251 
1252         try {
1253             rgs = getRegistrationGroupsByFormatOffering(formatOfferingId, context);
1254 
1255             for (RegistrationGroupInfo rg : rgs) {
1256 
1257                 if (rg.getIsGenerated()) {
1258                     rgChanges.add(bulkDeleteRegistrationGroup(rg, context));
1259                 }
1260 
1261             }
1262 
1263         } catch (DoesNotExistException e) {
1264             throw new OperationFailedException(
1265                     "deleteGeneratedRegistrationGroupsByFormatOffering (formatOfferingId=" + formatOfferingId + "): failed", e);
1266         }
1267 
1268 
1269         return rgChanges;
1270     }
1271 
1272     @Override
1273     public List<BulkStatusInfo> deleteRegistrationGroupsForCluster(String activityOfferingClusterId, ContextInfo contextInfo)
1274             throws InvalidParameterException,
1275             MissingParameterException,
1276             OperationFailedException,
1277             PermissionDeniedException {
1278 
1279         // copy list to avoid concurrent modification exceptions
1280         Collection<RegistrationGroupInfo> groups = new ArrayList<RegistrationGroupInfo>(this.registrationGroupMap.values());
1281 
1282         List<BulkStatusInfo> rgChanges = new ArrayList<BulkStatusInfo>();
1283 
1284         for (RegistrationGroupInfo rg : groups) {
1285 
1286             if (rg.getActivityOfferingClusterId().equals(activityOfferingClusterId)) {
1287 
1288                 try {
1289                     rgChanges.add(bulkDeleteRegistrationGroup(rg, contextInfo));
1290                 } catch (DoesNotExistException e) {
1291                     throw new OperationFailedException("Bulk Delete Failed", e);
1292                 }
1293             }
1294         }
1295 
1296         return rgChanges;
1297 
1298 
1299     }
1300 
1301     @Override
1302     public List<ValidationResultInfo> verifyRegistrationGroup(String registrationGroupId, ContextInfo contextInfo) throws
1303             DoesNotExistException,
1304             InvalidParameterException,
1305             MissingParameterException,
1306             OperationFailedException {
1307         return Collections.emptyList();
1308     }
1309 
1310     @Override
1311     public List<ValidationResultInfo> validateRegistrationGroup(
1312             String validationType, String activityOfferingClusterId, String registrationGroupType,
1313             RegistrationGroupInfo registrationGroupInfo,
1314             ContextInfo context) throws DoesNotExistException,
1315             InvalidParameterException,
1316             MissingParameterException,
1317             OperationFailedException {
1318         // validate
1319         // this is actually done at the ValidationDecorator layer
1320         return new ArrayList<ValidationResultInfo>();
1321     }
1322 
1323     @Override
1324     public ActivityOfferingClusterInfo getActivityOfferingCluster(
1325             String activityOfferingClusterId, ContextInfo contextInfo)
1326             throws DoesNotExistException,
1327             InvalidParameterException,
1328             MissingParameterException,
1329             OperationFailedException,
1330             PermissionDeniedException {
1331 
1332         ActivityOfferingClusterInfo aoc = this.activityOfferingClusterMap
1333                 .get(activityOfferingClusterId);
1334 
1335         if (aoc == null) {
1336             throw new DoesNotExistException(
1337                     "No ActivityOfferingCluster for id = "
1338                     + activityOfferingClusterId);
1339         }
1340 
1341         return new ActivityOfferingClusterInfo(aoc);
1342 
1343     }
1344 
1345     @Override
1346     public List<ActivityOfferingClusterInfo> getActivityOfferingClustersByIds(List<String> activityOfferingClusterIds,
1347             ContextInfo context) throws DoesNotExistException,
1348             InvalidParameterException,
1349             MissingParameterException,
1350             OperationFailedException,
1351             PermissionDeniedException {
1352         List<ActivityOfferingClusterInfo> results = new ArrayList<ActivityOfferingClusterInfo>();
1353 
1354         if (activityOfferingClusterIds != null && !activityOfferingClusterIds.isEmpty()) {
1355             for (String id : activityOfferingClusterIds) {
1356                 results.add(getActivityOfferingCluster(id, context));
1357             }
1358         }
1359 
1360         return results;
1361     }
1362 
1363     @Override
1364     public List<ActivityOfferingClusterInfo> getActivityOfferingClustersByFormatOffering(String formatOfferingId,
1365             ContextInfo contextInfo) throws DoesNotExistException,
1366             InvalidParameterException,
1367             MissingParameterException,
1368             OperationFailedException,
1369             PermissionDeniedException {
1370         List<ActivityOfferingClusterInfo> clusters = new ArrayList<ActivityOfferingClusterInfo>();
1371         for (ActivityOfferingClusterInfo info : this.activityOfferingClusterMap.values()) {
1372             if (info.getFormatOfferingId().equals(formatOfferingId)) {
1373                 clusters.add(info);
1374             }
1375         }
1376         return clusters;
1377     }
1378 
1379     @Override
1380     public List<ValidationResultInfo> validateActivityOfferingCluster(
1381             String validationTypeKey,
1382             String formatOfferingId,
1383             ActivityOfferingClusterInfo activityOfferingClusterInfo,
1384             ContextInfo contextInfo)
1385             throws DoesNotExistException,
1386             InvalidParameterException,
1387             MissingParameterException,
1388             OperationFailedException {
1389         // Note: validation is handled in the CourseOfferingServiceValidationDecorator
1390         return new ArrayList<ValidationResultInfo>();
1391     }
1392 
1393     @Override
1394     public StatusInfo deleteActivityOfferingClusterCascaded(
1395             String activityOfferingClusterId,
1396             ContextInfo contextInfo)
1397             throws DoesNotExistException,
1398             InvalidParameterException,
1399             MissingParameterException,
1400             OperationFailedException,
1401             PermissionDeniedException {
1402 
1403         List<RegistrationGroupInfo> rgList = getRegistrationGroupsByActivityOfferingCluster(activityOfferingClusterId, contextInfo);
1404 
1405         for (RegistrationGroupInfo rg : rgList) {
1406             deleteRegistrationGroup(rg.getId(), contextInfo);
1407         }
1408 
1409         try {
1410             deleteActivityOfferingCluster(activityOfferingClusterId, contextInfo);
1411         } catch (DependentObjectsExistException e) {
1412             throw new OperationFailedException(
1413                     "unexpected reg group exists for activityOfferingCluster = " + activityOfferingClusterId);
1414         }
1415 
1416         return successStatus();
1417     }
1418     private Map<String, ActivityOfferingClusterInfo> activityOfferingClusterMap = new LinkedHashMap<String, ActivityOfferingClusterInfo>();
1419 
1420     private void _createAOSets(FormatOfferingInfo foInfo, ActivityOfferingClusterInfo clusterInfo) {
1421         if (clusterInfo.getActivityOfferingSets() == null) {
1422             // Shouldn't be necessary, but just in case.
1423             clusterInfo.setActivityOfferingSets(new ArrayList<ActivityOfferingSetInfo>());
1424         }
1425         List<ActivityOfferingSetInfo> setInfos = clusterInfo.getActivityOfferingSets();
1426         List<String> aoTypeKeys = foInfo.getActivityOfferingTypeKeys();
1427         if (aoTypeKeys != null) {
1428             for (String aoTypeKey : aoTypeKeys) {
1429                 // Create an AOSetInfo
1430                 ActivityOfferingSetInfo setInfo = new ActivityOfferingSetInfo();
1431                 setInfo.setActivityOfferingType(aoTypeKey);
1432                 setInfo.setActivityOfferingIds(new ArrayList<String>()); // leave it empty for now
1433                 // Add it to the list
1434                 setInfos.add(setInfo);
1435             }
1436         }
1437     }
1438 
1439     @Override
1440     public ActivityOfferingClusterInfo createActivityOfferingCluster(String formatOfferingId,
1441             String activityOfferingClusterTypeKey, ActivityOfferingClusterInfo activityOfferingClusterInfo,
1442             ContextInfo contextInfo)
1443             throws DataValidationErrorException,
1444             DoesNotExistException,
1445             InvalidParameterException,
1446             MissingParameterException,
1447             OperationFailedException,
1448             PermissionDeniedException,
1449             ReadOnlyException {
1450 
1451         ActivityOfferingClusterInfo copy = new ActivityOfferingClusterInfo(
1452                 activityOfferingClusterInfo);
1453 
1454         if (copy.getActivityOfferingSets().isEmpty()) {
1455             FormatOfferingInfo foInfo = getFormatOffering(formatOfferingId, contextInfo);
1456             _createAOSets(foInfo, copy);
1457         }
1458 
1459         if (copy.getId() == null) {
1460             copy.setId(UUIDHelper.genStringUUID());
1461         }
1462 
1463         copy.setMeta(newMeta(contextInfo));
1464 
1465         activityOfferingClusterMap.put(copy.getId(), copy);
1466 
1467         return copy;
1468 
1469     }
1470 
1471     @Override
1472     public AOClusterVerifyResultsInfo verifyActivityOfferingClusterForGeneration(String activityOfferingClusterId,
1473             ContextInfo contextInfo) throws DoesNotExistException,
1474             InvalidParameterException,
1475             MissingParameterException,
1476             OperationFailedException,
1477             PermissionDeniedException {
1478         // This is the same implementation as the CourseOfferingServiceImpl.  (It had been unimplemented).
1479         // Might want Find some way to resuse the COSI impl.
1480         AOClusterVerifyResultsInfo aoClusterVerifyResultsInfo = new AOClusterVerifyResultsInfo();
1481         List<ValidationResultInfo> validationResultInfos = new ArrayList<ValidationResultInfo>();
1482         ValidationResultInfo validationResultInfo = new ValidationResultInfo();
1483 
1484         try {
1485             ActivityOfferingClusterInfo aoCInfo = getActivityOfferingCluster(activityOfferingClusterId, contextInfo);
1486             List<ActivityOfferingSetInfo> aoSetInfos = aoCInfo.getActivityOfferingSets();
1487 
1488             for (ActivityOfferingSetInfo aoSetInfo : aoSetInfos) {
1489                 List<String> aoIdList = aoSetInfo.getActivityOfferingIds();
1490                 if (aoIdList == null || aoIdList.isEmpty()) {
1491                     //invalidValidationInfo.setError("");
1492                     validationResultInfo.setLevel(ValidationResult.ErrorLevel.ERROR);
1493                     validationResultInfos.add(validationResultInfo);
1494                     aoClusterVerifyResultsInfo.setValidationResults(validationResultInfos);
1495 
1496                     return aoClusterVerifyResultsInfo;
1497                 }
1498             }
1499         } catch (Exception ex) {
1500             throw new OperationFailedException("unexpected", ex);
1501         }
1502 
1503         validationResultInfo.setLevel(ValidationResult.ErrorLevel.OK);
1504         validationResultInfos.add(validationResultInfo);
1505         aoClusterVerifyResultsInfo.setValidationResults(validationResultInfos);
1506 
1507         return aoClusterVerifyResultsInfo;
1508     }
1509 
1510     @Override
1511     public ActivityOfferingClusterInfo updateActivityOfferingCluster(String formatOfferingId, String activityOfferingClusterId,
1512             ActivityOfferingClusterInfo activityOfferingClusterInfo, ContextInfo contextInfo)
1513             throws DataValidationErrorException,
1514             DoesNotExistException,
1515             InvalidParameterException,
1516             MissingParameterException,
1517             OperationFailedException,
1518             PermissionDeniedException,
1519             ReadOnlyException,
1520             VersionMismatchException {
1521 
1522         // update
1523         if (!activityOfferingClusterId.equals(activityOfferingClusterInfo.getId())) {
1524             throw new InvalidParameterException(
1525                     "The id parameter does not match the id on the info object");
1526         }
1527         ActivityOfferingClusterInfo copy = new ActivityOfferingClusterInfo(activityOfferingClusterInfo);
1528         ActivityOfferingClusterInfo old = this.getActivityOfferingCluster(
1529                 activityOfferingClusterId, contextInfo);
1530         // Figure out IDs that appear in old, but not in copy.
1531         Set<String> oldIds = new HashSet<String>(); // First the old Ids
1532         for (ActivityOfferingSetInfo set : old.getActivityOfferingSets()) {
1533             oldIds.addAll(set.getActivityOfferingIds());
1534         }
1535         Set<String> copyIds = new HashSet<String>(); // First the old Ids
1536         for (ActivityOfferingSetInfo set : copy.getActivityOfferingSets()) {
1537             copyIds.addAll(set.getActivityOfferingIds());
1538         }
1539         oldIds.removeAll(copyIds);
1540         for (String aoId : oldIds) {
1541             // Find any RGs that contain these aoIds
1542             for (Map.Entry<String, RegistrationGroupInfo> entry : this.registrationGroupMap.entrySet()) {
1543                 if (entry.getValue().getFormatOfferingId().equals(formatOfferingId)
1544                         && entry.getValue().getActivityOfferingIds().contains(aoId)) {
1545                     // Delete RG with this ao id
1546                     this.registrationGroupMap.remove(entry.getKey());
1547                 }
1548             }
1549         }
1550 
1551         if (!old.getMeta().getVersionInd()
1552                 .equals(copy.getMeta().getVersionInd())) {
1553             throw new VersionMismatchException(old.getMeta().getVersionInd());
1554         }
1555         copy.setMeta(updateMeta(copy.getMeta(), contextInfo));
1556         this.activityOfferingClusterMap.put(activityOfferingClusterInfo.getId(), copy);
1557 
1558         return new ActivityOfferingClusterInfo(copy);
1559 
1560     }
1561 
1562     @Override
1563     public StatusInfo deleteActivityOfferingCluster(
1564             String activityOfferingClusterId, ContextInfo context)
1565             throws DoesNotExistException,
1566             InvalidParameterException,
1567             MissingParameterException,
1568             OperationFailedException,
1569             PermissionDeniedException,
1570             DependentObjectsExistException {
1571 
1572         // note validation is in the validation decorator.
1573         ActivityOfferingClusterInfo aoc = this.activityOfferingClusterMap.remove(activityOfferingClusterId);
1574 
1575         if (aoc == null) {
1576             throw new DoesNotExistException("No ActivityOfferingCluster for Id = " + activityOfferingClusterId);
1577         }
1578 
1579         return successStatus();
1580 
1581     }
1582 
1583     @Override
1584     public SeatPoolDefinitionInfo getSeatPoolDefinition(
1585             String seatPoolDefinitionId, ContextInfo context)
1586             throws DoesNotExistException,
1587             InvalidParameterException,
1588             MissingParameterException,
1589             OperationFailedException,
1590             PermissionDeniedException {
1591         if (!this.seatPoolDefinitionMap.containsKey(seatPoolDefinitionId)) {
1592             throw new DoesNotExistException(seatPoolDefinitionId);
1593         }
1594         return this.seatPoolDefinitionMap.get(seatPoolDefinitionId);
1595     }
1596 
1597     @Override
1598     public List<SeatPoolDefinitionInfo> getSeatPoolDefinitionsForActivityOffering(
1599             String activityOfferingId, ContextInfo context)
1600             throws DoesNotExistException,
1601             InvalidParameterException,
1602             MissingParameterException,
1603             OperationFailedException,
1604             PermissionDeniedException {
1605 
1606         // will throw does not exist exception if there is no matching activity id
1607         ActivityOfferingInfo ao = getActivityOffering(activityOfferingId, context);
1608 
1609         List<String> seatPoolIds = activityOfferingToSeatPoolMap.get(activityOfferingId);
1610 
1611         if (seatPoolIds == null) {
1612             return new ArrayList<SeatPoolDefinitionInfo>();
1613         }
1614 
1615         List<SeatPoolDefinitionInfo> seatPoolInfos = new ArrayList<SeatPoolDefinitionInfo>(seatPoolIds.size());
1616 
1617         for (String spId : seatPoolIds) {
1618 
1619             SeatPoolDefinitionInfo sp = getSeatPoolDefinition(spId, context);
1620 
1621             seatPoolInfos.add(sp);
1622         }
1623 
1624         return seatPoolInfos;
1625 
1626 
1627     }
1628     // cache variable
1629     // The LinkedHashMap is just so the values come back in a predictable order
1630     private Map<String, SeatPoolDefinitionInfo> seatPoolDefinitionMap = new LinkedHashMap<String, SeatPoolDefinitionInfo>();
1631 
1632     @Override
1633     public SeatPoolDefinitionInfo createSeatPoolDefinition(
1634             SeatPoolDefinitionInfo seatPoolDefinitionInfo, ContextInfo context)
1635             throws DataValidationErrorException,
1636             InvalidParameterException,
1637             MissingParameterException,
1638             OperationFailedException,
1639             PermissionDeniedException,
1640             ReadOnlyException {
1641         // create
1642         SeatPoolDefinitionInfo copy = new SeatPoolDefinitionInfo(
1643                 seatPoolDefinitionInfo);
1644         if (copy.getId() == null) {
1645             copy.setId(UUIDHelper.genStringUUID());
1646         }
1647         copy.setMeta(newMeta(context));
1648         seatPoolDefinitionMap.put(copy.getId(), copy);
1649         return new SeatPoolDefinitionInfo(copy);
1650     }
1651 
1652     @Override
1653     public SeatPoolDefinitionInfo updateSeatPoolDefinition(
1654             String seatPoolDefinitionId,
1655             SeatPoolDefinitionInfo seatPoolDefinitionInfo, ContextInfo context)
1656             throws DataValidationErrorException,
1657             DoesNotExistException,
1658             InvalidParameterException,
1659             MissingParameterException,
1660             OperationFailedException,
1661             PermissionDeniedException,
1662             ReadOnlyException,
1663             VersionMismatchException {
1664         // update
1665         if (!seatPoolDefinitionId.equals(seatPoolDefinitionInfo.getId())) {
1666             throw new InvalidParameterException(
1667                     "The id parameter does not match the id on the info object");
1668         }
1669         SeatPoolDefinitionInfo copy = new SeatPoolDefinitionInfo(
1670                 seatPoolDefinitionInfo);
1671         SeatPoolDefinitionInfo old = this.getSeatPoolDefinition(
1672                 seatPoolDefinitionInfo.getId(), context);
1673         if (!old.getMeta().getVersionInd()
1674                 .equals(copy.getMeta().getVersionInd())) {
1675             throw new VersionMismatchException(old.getMeta().getVersionInd());
1676         }
1677         copy.setMeta(updateMeta(copy.getMeta(), context));
1678         this.seatPoolDefinitionMap.put(seatPoolDefinitionInfo.getId(), copy);
1679         return new SeatPoolDefinitionInfo(copy);
1680     }
1681 
1682     @Override
1683     public List<ValidationResultInfo> validateSeatPoolDefinition(
1684             String validationTypeKey,
1685             SeatPoolDefinitionInfo seatPoolDefinitionInfo, ContextInfo context)
1686             throws DoesNotExistException,
1687             InvalidParameterException,
1688             MissingParameterException,
1689             OperationFailedException,
1690             PermissionDeniedException {
1691         // validate
1692         return new ArrayList<ValidationResultInfo>();
1693     }
1694 
1695     @Override
1696     public StatusInfo deleteSeatPoolDefinition(String seatPoolDefinitionId,
1697             ContextInfo context) throws DoesNotExistException,
1698             InvalidParameterException,
1699             MissingParameterException,
1700             OperationFailedException,
1701             PermissionDeniedException {
1702         if (this.seatPoolDefinitionMap.remove(seatPoolDefinitionId) == null) {
1703             throw new DoesNotExistException(seatPoolDefinitionId);
1704         }
1705         return successStatus();
1706     }
1707 
1708     @Override
1709     public List<CourseOfferingInfo> searchForCourseOfferings(
1710             QueryByCriteria criteria, ContextInfo context)
1711             throws InvalidParameterException,
1712             MissingParameterException,
1713             OperationFailedException,
1714             PermissionDeniedException {
1715 
1716         throw new OperationFailedException(
1717                 "searchForCourseOfferings has not been implemented");
1718     }
1719 
1720     @Override
1721     public List<String> searchForCourseOfferingIds(QueryByCriteria criteria,
1722             ContextInfo context) throws InvalidParameterException,
1723             MissingParameterException,
1724             OperationFailedException,
1725             PermissionDeniedException {
1726         throw new OperationFailedException(
1727                 "searchForCourseOfferingIds has not been implemented");
1728     }
1729 
1730     @Override
1731     public List<ActivityOfferingInfo> searchForActivityOfferings(
1732             QueryByCriteria criteria, ContextInfo context)
1733             throws InvalidParameterException,
1734             MissingParameterException,
1735             OperationFailedException,
1736             PermissionDeniedException {
1737         throw new OperationFailedException(
1738                 "searchForActivityOfferings has not been implemented");
1739     }
1740 
1741     @Override
1742     public List<String> searchForActivityOfferingIds(QueryByCriteria criteria,
1743             ContextInfo context) throws InvalidParameterException,
1744             MissingParameterException,
1745             OperationFailedException,
1746             PermissionDeniedException {
1747         throw new OperationFailedException(
1748                 "searchForActivityOfferingIds has not been implemented");
1749     }
1750 
1751     @Override
1752     public List<RegistrationGroupInfo> searchForRegistrationGroups(
1753             QueryByCriteria criteria, ContextInfo context)
1754             throws InvalidParameterException,
1755             MissingParameterException,
1756             OperationFailedException,
1757             PermissionDeniedException {
1758         throw new OperationFailedException(
1759                 "searchForRegistrationGroups has not been implemented");
1760     }
1761 
1762     @Override
1763     public List<String> searchForRegistrationGroupIds(QueryByCriteria criteria,
1764             ContextInfo context) throws InvalidParameterException,
1765             MissingParameterException,
1766             OperationFailedException,
1767             PermissionDeniedException {
1768         throw new OperationFailedException(
1769                 "searchForRegistrationGroupIds has not been implemented");
1770     }
1771 
1772     @Override
1773     public List<SeatPoolDefinitionInfo> searchForSeatpoolDefinitions(
1774             QueryByCriteria criteria, ContextInfo context)
1775             throws InvalidParameterException,
1776             MissingParameterException,
1777             OperationFailedException,
1778             PermissionDeniedException {
1779         throw new OperationFailedException(
1780                 "searchForSeatpoolDefinitions has not been implemented");
1781     }
1782 
1783     @Override
1784     public List<String> searchForSeatpoolDefinitionIds(
1785             QueryByCriteria criteria, ContextInfo context)
1786             throws InvalidParameterException,
1787             MissingParameterException,
1788             OperationFailedException,
1789             PermissionDeniedException {
1790         throw new OperationFailedException(
1791                 "searchForSeatpoolDefinitionIds has not been implemented");
1792     }
1793 
1794     @Override
1795     public CourseOfferingDisplayInfo getCourseOfferingDisplay(
1796             String courseOfferingId, ContextInfo context)
1797             throws DoesNotExistException,
1798             InvalidParameterException,
1799             MissingParameterException,
1800             OperationFailedException,
1801             PermissionDeniedException {
1802         CourseOfferingInfo co = this.getCourseOffering(courseOfferingId, context);
1803         CourseOfferingDisplayInfo info = new CourseOfferingDisplayInfo();
1804         info.setId(co.getId());
1805         info.setTypeKey(co.getTypeKey());
1806         info.setStateKey(co.getStateKey());
1807         info.setDescr(co.getDescr());
1808         info.setCourseId(co.getCourseId());
1809         info.setTermId(co.getTermId());
1810         info.setCourseOfferingCode(co.getCourseOfferingCode());
1811         info.setCourseOfferingTitle(co.getCourseOfferingTitle());
1812         info.setSubjectArea(co.getSubjectArea());
1813         info.setTermName(co.getTermId() + " name");
1814         info.setTermCode(co.getTermId());
1815         info.setGradingOption(new KeyNameInfo(co.getGradingOptionId(), co.getGradingOptionName()));
1816         info.setCreditOption(new KeyNameInfo(co.getCreditOptionId(), co.getCreditOptionName()));
1817         info.setTypeName(co.getTypeKey() + " name");
1818         info.setStateName(co.getStateKey() + " name");
1819         info.setMeta(co.getMeta());
1820         info.setAttributes(co.getAttributes());
1821         return info;
1822     }
1823 
1824     private List<String> calcActivityOfferingTypes(CourseOfferingInfo co, ContextInfo context)
1825             throws DoesNotExistException,
1826             InvalidParameterException,
1827             MissingParameterException,
1828             OperationFailedException,
1829             PermissionDeniedException {
1830         List<String> list = new ArrayList<String>();
1831         for (FormatOfferingInfo fo : this.getFormatOfferingsByCourseOffering(co.getId(), context)) {
1832             list.addAll(fo.getActivityOfferingTypeKeys());
1833         }
1834         return list;
1835     }
1836 
1837     @Override
1838     public List<CourseOfferingDisplayInfo> getCourseOfferingDisplaysByIds(
1839             List<String> courseOfferingIds, ContextInfo context)
1840             throws DoesNotExistException,
1841             InvalidParameterException,
1842             MissingParameterException,
1843             OperationFailedException,
1844             PermissionDeniedException {
1845         throw new OperationFailedException(
1846                 "getCourseOfferingDisplayByIds has not been implemented");
1847     }
1848 
1849     @Override
1850     public ActivityOfferingDisplayInfo getActivityOfferingDisplay(
1851             String activityOfferingId, ContextInfo contextInfo)
1852             throws DoesNotExistException,
1853             InvalidParameterException,
1854             MissingParameterException,
1855             OperationFailedException,
1856             PermissionDeniedException {
1857         ActivityOfferingInfo ao = this.getActivityOffering(activityOfferingId, contextInfo);
1858         ActivityOfferingDisplayInfo info = new ActivityOfferingDisplayInfo();
1859         info.setId(ao.getId());
1860         info.setTypeKey(ao.getTypeKey());
1861         info.setStateKey(ao.getStateKey());
1862         info.setName(ao.getName());
1863         info.setDescr(ao.getDescr());
1864         info.setTypeName(ao.getTypeKey() + " name");
1865         info.setStateName(ao.getStateKey() + " name");
1866         info.setCourseOfferingTitle(ao.getCourseOfferingTitle());
1867         info.setCourseOfferingCode(ao.getCourseOfferingCode());
1868         info.setFormatOfferingId(ao.getFormatOfferingId());
1869         info.setFormatOfferingName(ao.getFormatOfferingName());
1870         info.setActivityOfferingCode(ao.getActivityCode());
1871 
1872         info.setInstructorId(ao.getInstructors().get(0).getPersonId());
1873         info.setInstructorName(ao.getInstructors().get(0).getPersonName());
1874 
1875         info.setIsHonorsOffering(ao.getIsHonorsOffering());
1876         info.setMaximumEnrollment(ao.getMaximumEnrollment());
1877         //  Get the schedule components from all schedules and put them in a single ScheduleDisplayInfo.
1878         if (ao.getScheduleIds() != null && !ao.getScheduleIds().isEmpty()) {
1879             List<ScheduleDisplayInfo> scheduleDisplays = new ArrayList<ScheduleDisplayInfo>();
1880             List<ScheduleComponentDisplayInfo> scheduleComponentDisplayInfos = new ArrayList<ScheduleComponentDisplayInfo>();
1881             for (ScheduleDisplayInfo sdi : scheduleDisplays) {
1882                 scheduleComponentDisplayInfos.addAll((List<ScheduleComponentDisplayInfo>) sdi.getScheduleComponentDisplays());
1883             }
1884             ScheduleDisplayInfo sdiAggregate = new ScheduleDisplayInfo();
1885             sdiAggregate.setScheduleComponentDisplays(scheduleComponentDisplayInfos);
1886             info.setScheduleDisplay(sdiAggregate);
1887         }
1888         info.setMeta(ao.getMeta());
1889         info.setAttributes(ao.getAttributes());
1890         return info;
1891     }
1892 
1893     @Override
1894     public List<ActivityOfferingDisplayInfo> getActivityOfferingDisplaysByIds(
1895             List<String> activityOfferingIds, ContextInfo contextInfo)
1896             throws DoesNotExistException,
1897             InvalidParameterException,
1898             MissingParameterException,
1899             OperationFailedException,
1900             PermissionDeniedException {
1901         throw new UnsupportedOperationException("Not supported yet");
1902     }
1903 
1904     @Override
1905     public List<ActivityOfferingDisplayInfo> getActivityOfferingDisplaysForCourseOffering(
1906             String courseOfferingId, ContextInfo contextInfo)
1907             throws DoesNotExistException,
1908             InvalidParameterException,
1909             MissingParameterException,
1910             OperationFailedException,
1911             PermissionDeniedException {
1912         throw new UnsupportedOperationException("Not supported yet");
1913     }
1914 
1915     @Override
1916     public List<String> getValidCanonicalCourseToCourseOfferingOptionKeys(
1917             ContextInfo context) throws InvalidParameterException,
1918             MissingParameterException,
1919             OperationFailedException,
1920             PermissionDeniedException,
1921             ReadOnlyException {
1922         List<String> options = new ArrayList();
1923         options.add(CourseOfferingSetServiceConstants.NOT_COURSE_TITLE_OPTION_KEY);
1924         options.add(CourseOfferingSetServiceConstants.CREDITS_MATCH_SCHEDULED_HOURS_OPTION_KEY);
1925         return options;
1926     }
1927 
1928     @Override
1929     public List<String> getValidRolloverOptionKeys(ContextInfo context)
1930             throws InvalidParameterException,
1931             MissingParameterException,
1932             OperationFailedException,
1933             PermissionDeniedException,
1934             ReadOnlyException {
1935         List<String> options = new ArrayList();
1936         // what courses
1937         options.add(CourseOfferingSetServiceConstants.STILL_OFFERABLE_OPTION_KEY);
1938         options.add(CourseOfferingSetServiceConstants.IF_NO_NEW_VERSION_OPTION_KEY);
1939         options.add(CourseOfferingSetServiceConstants.IGNORE_CANCELLED_OPTION_KEY);
1940         options.add(CourseOfferingSetServiceConstants.SKIP_IF_ALREADY_EXISTS_OPTION_KEY);
1941         // what data
1942         options.add(CourseOfferingSetServiceConstants.USE_CANONICAL_OPTION_KEY);
1943         options.add(CourseOfferingSetServiceConstants.NO_INSTRUCTORS_OPTION_KEY);
1944         options.add(CourseOfferingSetServiceConstants.NO_SCHEDULE_OPTION_KEY);
1945         return options;
1946     }
1947 
1948     @Override
1949     public SocRolloverResultItemInfo rolloverCourseOffering(
1950             String sourceCourseOfferingId, String targetTermId,
1951             List<String> optionKeys, ContextInfo context)
1952             throws AlreadyExistsException,
1953             DataValidationErrorException,
1954             DoesNotExistException,
1955             DataValidationErrorException,
1956             InvalidParameterException,
1957             MissingParameterException,
1958             OperationFailedException,
1959             PermissionDeniedException,
1960             ReadOnlyException {
1961         throw new UnsupportedOperationException("Not supported yet.");
1962     }
1963 
1964     private MetaInfo newMeta(ContextInfo context) {
1965         MetaInfo meta = new MetaInfo();
1966         meta.setCreateId(context.getPrincipalId());
1967         meta.setCreateTime(new Date());
1968         meta.setUpdateId(context.getPrincipalId());
1969         meta.setUpdateTime(meta.getCreateTime());
1970         meta.setVersionInd("0");
1971         return meta;
1972     }
1973 
1974     private StatusInfo successStatus() {
1975         StatusInfo status = new StatusInfo();
1976         status.setSuccess(Boolean.TRUE);
1977         return status;
1978     }
1979 
1980     private StatusInfo failStatus() {
1981         StatusInfo status = new StatusInfo();
1982         status.setMessage("Operation Failed");
1983         status.setSuccess(Boolean.FALSE);
1984         return status;
1985     }
1986 
1987     private MetaInfo updateMeta(MetaInfo old, ContextInfo context) {
1988         MetaInfo meta = new MetaInfo(old);
1989         meta.setUpdateId(context.getPrincipalId());
1990         meta.setUpdateTime(new Date());
1991         meta.setVersionInd((Integer.parseInt(meta.getVersionInd()) + 1) + "");
1992         return meta;
1993     }
1994     private Map<String, List<String>> activityOfferingToSeatPoolMap = new HashMap<String, List<String>>();
1995 
1996     @Override
1997     public StatusInfo addSeatPoolDefinitionToActivityOffering(
1998             String seatPoolDefinitionId, String activityOfferingId,
1999             ContextInfo contextInfo) throws AlreadyExistsException,
2000             DoesNotExistException,
2001             InvalidParameterException,
2002             MissingParameterException,
2003             OperationFailedException,
2004             PermissionDeniedException {
2005 
2006         // first check that both the reg group and seat pool exist
2007         // these will throw does not exist exceptions
2008         ActivityOfferingInfo ao = getActivityOffering(activityOfferingId, contextInfo);
2009 
2010         SeatPoolDefinitionInfo spd = getSeatPoolDefinition(seatPoolDefinitionId, contextInfo);
2011 
2012         // now check for an existing association
2013         List<String> seatPoolIds = activityOfferingToSeatPoolMap.get(activityOfferingId);
2014 
2015         if (seatPoolIds == null) {
2016             seatPoolIds = new ArrayList<String>();
2017             activityOfferingToSeatPoolMap.put(activityOfferingId, seatPoolIds);
2018         }
2019 
2020         if (seatPoolIds.contains(seatPoolDefinitionId)) {
2021             throw new AlreadyExistsException(
2022                     "registration group (" + activityOfferingId + ") is already associated to seat pool definition (" + seatPoolDefinitionId + ")");
2023         }
2024 
2025         seatPoolIds.add(seatPoolDefinitionId);
2026 
2027         return successStatus();
2028     }
2029 
2030     @Override
2031     public StatusInfo removeSeatPoolDefinitionFromActivityOffering(
2032             String seatPoolDefinitionId, String activityOfferingId,
2033             ContextInfo contextInfo) throws DoesNotExistException,
2034             InvalidParameterException,
2035             MissingParameterException,
2036             OperationFailedException,
2037             PermissionDeniedException {
2038 
2039         // first check that both the reg group and seat pool exist
2040         // these will throw does not exist exceptions
2041         ActivityOfferingInfo ao = getActivityOffering(activityOfferingId, contextInfo);
2042 
2043         SeatPoolDefinitionInfo spd = getSeatPoolDefinition(seatPoolDefinitionId, contextInfo);
2044 
2045         getSeatPoolDefinitionsForActivityOffering(activityOfferingId, contextInfo);
2046 
2047         List<String> seatPoolIds = activityOfferingToSeatPoolMap.get(activityOfferingId);
2048 
2049         if (seatPoolIds.remove(seatPoolDefinitionId)) {
2050             return successStatus();
2051         } else {
2052             throw new DoesNotExistException(
2053                     "no seatpool association for spId=" + seatPoolDefinitionId + " and activityOfferingId = " + activityOfferingId);
2054         }
2055 
2056     }
2057 
2058     @Override
2059     public List<BulkStatusInfo> generateRegistrationGroupsForFormatOffering(
2060             String formatOfferingId, ContextInfo context)
2061             throws DoesNotExistException,
2062             InvalidParameterException,
2063             MissingParameterException,
2064             OperationFailedException,
2065             PermissionDeniedException,
2066             DataValidationErrorException {
2067         throw new UnsupportedOperationException("Not supported yet.");
2068     }
2069 
2070     @Override
2071     public List<String> getCourseOfferingIdsByTermAndSubjectArea(String termId,
2072             String subjectArea, ContextInfo context)
2073             throws DoesNotExistException,
2074             InvalidParameterException,
2075             MissingParameterException,
2076             OperationFailedException,
2077             PermissionDeniedException {
2078         List<String> list = new ArrayList<String>();
2079         for (CourseOfferingInfo info : courseOfferingMap.values()) {
2080             if (termId.equals(info.getTermId())) {
2081                 if (subjectArea.equals(info.getSubjectArea())) {
2082                     list.add(info.getId());
2083                 }
2084             }
2085         }
2086         return list;
2087     }
2088 
2089     @Override
2090     public StatusInfo changeCourseOfferingState(
2091             String courseOfferingId,
2092             String nextStateKey,
2093             ContextInfo contextInfo)
2094             throws DoesNotExistException,
2095             MissingParameterException,
2096             OperationFailedException,
2097             PermissionDeniedException {
2098 
2099         try {
2100             /*
2101              * get won't work because it doesn't return the map bound instance.
2102              * We need to get that instance ourselves manually.
2103              */
2104             CourseOfferingInfo co = this.courseOfferingMap.get(courseOfferingId);
2105 
2106             if (co == null) {
2107                 throw new DoesNotExistException("No CourseOffering for id= " + courseOfferingId);
2108             }
2109 
2110             co.setStateKey(nextStateKey);
2111 
2112             return successStatus();
2113 
2114         } catch (Exception e) {
2115             throw new OperationFailedException(
2116                     "changeCourseOfferingState (id=" + courseOfferingId + ", nextStateKey=" + nextStateKey, e);
2117         }
2118     }
2119 
2120     @Override
2121     public StatusInfo changeFormatOfferingState(
2122             String formatOfferingId,
2123             String nextStateKey,
2124             ContextInfo contextInfo)
2125             throws DoesNotExistException,
2126             MissingParameterException,
2127             OperationFailedException {
2128         try {
2129             /*
2130              * get won't work because it doesn't return the map bound instance.
2131              * We need to get that instance ourselves manually.
2132              */
2133             FormatOfferingInfo fo = this.formatOfferingMap.get(formatOfferingId);
2134 
2135             if (fo == null) {
2136                 throw new DoesNotExistException("No FormatOffering for id= " + formatOfferingId);
2137             }
2138 
2139             fo.setStateKey(nextStateKey);
2140 
2141             return successStatus();
2142 
2143         } catch (Exception e) {
2144             throw new OperationFailedException(
2145                     "changeFormatOfferingState (id=" + formatOfferingId + ", nextStateKey=" + nextStateKey, e);
2146         }
2147     }
2148 
2149     @Override
2150     public StatusInfo changeActivityOfferingState(
2151             String activityOfferingId,
2152             String nextStateKey,
2153             ContextInfo contextInfo)
2154             throws DoesNotExistException,
2155             MissingParameterException,
2156             OperationFailedException,
2157             PermissionDeniedException {
2158 
2159         try {
2160             /*
2161              * get won't work because it doesn't return the map bound instance.
2162              * We need to get that instance ourselves manually.
2163              */
2164             ActivityOfferingInfo ao = this.activityOfferingMap.get(activityOfferingId);
2165 
2166             if (ao == null) {
2167                 throw new DoesNotExistException("No ActivityOffering for id= " + activityOfferingId);
2168             }
2169 
2170             ao.setStateKey(nextStateKey);
2171 
2172             return successStatus();
2173 
2174         } catch (Exception e) {
2175             throw new OperationFailedException(
2176                     "changeActivityOfferingState (id=" + activityOfferingId + ", nextStateKey=" + nextStateKey, e);
2177         }
2178     }
2179 
2180     @Override
2181     public StatusInfo changeRegistrationGroupState(
2182             String registrationGroupId,
2183             String nextStateKey,
2184             ContextInfo contextInfo)
2185             throws DoesNotExistException,
2186             MissingParameterException,
2187             OperationFailedException,
2188             PermissionDeniedException {
2189         try {
2190             /*
2191              * get won't work because it doesn't return the map bound instance.
2192              * We need to get that instance ourselves manually.
2193              */
2194             RegistrationGroupInfo rg = this.registrationGroupMap.get(registrationGroupId);
2195 
2196             if (rg == null) {
2197                 throw new DoesNotExistException("No RegistrationGroup for id= " + registrationGroupId);
2198             }
2199 
2200             rg.setStateKey(nextStateKey);
2201 
2202             return successStatus();
2203 
2204         } catch (Exception e) {
2205             throw new OperationFailedException(
2206                     "changeRegistrationGroupState (id=" + registrationGroupId + ", nextStateKey=" + nextStateKey, e);
2207         }
2208     }
2209 
2210     @Override
2211     public StatusInfo changeActivityOfferingClusterState(
2212             String activityOfferingClusterId,
2213             String nextStateKey,
2214             ContextInfo contextInfo)
2215             throws DoesNotExistException,
2216             MissingParameterException,
2217             OperationFailedException,
2218             PermissionDeniedException {
2219         try {
2220             /*
2221              * get won't work because it doesn't return the map bound instance.
2222              * We need to get that instance ourselves manually.
2223              */
2224             ActivityOfferingClusterInfo aoc = this.activityOfferingClusterMap.get(activityOfferingClusterId);
2225 
2226             if (aoc == null) {
2227                 throw new DoesNotExistException("No ActivityOfferingCluster for id= " + activityOfferingClusterId);
2228             }
2229 
2230             aoc.setStateKey(nextStateKey);
2231 
2232             return successStatus();
2233 
2234         } catch (Exception e) {
2235             throw new OperationFailedException(
2236                     "changeActivityOfferingClusterState (id=" + activityOfferingClusterId + ", nextStateKey=" + nextStateKey, e);
2237         }
2238     }
2239 
2240     @Override
2241     public StatusInfo changeSeatPoolDefinitionState(
2242             String seatPoolDefinitionId,
2243             String nextStateKey,
2244             ContextInfo contextInfo)
2245             throws DoesNotExistException,
2246             MissingParameterException,
2247             OperationFailedException,
2248             PermissionDeniedException {
2249         try {
2250             /*
2251              * get won't work because it doesn't return the map bound instance.
2252              * We need to get that instance ourselves manually.
2253              */
2254             SeatPoolDefinitionInfo spd = this.seatPoolDefinitionMap.get(seatPoolDefinitionId);
2255 
2256             if (spd == null) {
2257                 throw new DoesNotExistException("No SeatPoolDefinition for id= " + seatPoolDefinitionId);
2258             }
2259 
2260             spd.setStateKey(nextStateKey);
2261 
2262             return successStatus();
2263 
2264         } catch (Exception e) {
2265             throw new OperationFailedException(
2266                     "changeSeatPoolDefinitionState (id=" + seatPoolDefinitionId + ", nextStateKey=" + nextStateKey, e);
2267         }
2268     }
2269 
2270     @Override
2271     public List<RegistrationGroupInfo> getRegistrationGroupsByActivityOfferingCluster(
2272             String activityOfferingClusterId,
2273             ContextInfo contextInfo)
2274             throws DoesNotExistException,
2275             InvalidParameterException,
2276             MissingParameterException,
2277             OperationFailedException,
2278             PermissionDeniedException {
2279 
2280         List<RegistrationGroupInfo> regGroups = new ArrayList<RegistrationGroupInfo>();
2281 
2282         for (RegistrationGroupInfo regGroup : this.registrationGroupMap.values()) {
2283 
2284             if (regGroup.getActivityOfferingClusterId().equals(activityOfferingClusterId)) {
2285                 regGroups.add(regGroup);
2286             }
2287         }
2288 
2289         return regGroups;
2290     }
2291 
2292     @Override
2293     public List<ActivityOfferingInfo> getActivityOfferingsByCluster(
2294             String activityOfferingClusterId,
2295             ContextInfo contextInfo)
2296             throws DoesNotExistException,
2297             InvalidParameterException,
2298             MissingParameterException,
2299             OperationFailedException,
2300             PermissionDeniedException {
2301 
2302         List<ActivityOfferingInfo> aoList = new ArrayList<ActivityOfferingInfo>();
2303 
2304         ActivityOfferingClusterInfo aoc = getActivityOfferingCluster(activityOfferingClusterId, contextInfo);
2305 
2306         for (ActivityOfferingSetInfo aocSet : aoc.getActivityOfferingSets()) {
2307 
2308             List<ActivityOfferingInfo> setAos = getActivityOfferingsByIds(aocSet.getActivityOfferingIds(), contextInfo);
2309 
2310             aoList.addAll(setAos);
2311         }
2312 
2313         return aoList;
2314     }
2315 
2316     @Override
2317     public List<String> getActivityOfferingClustersIdsByFormatOffering(
2318             String formatOfferingId,
2319             ContextInfo contextInfo)
2320             throws DoesNotExistException,
2321             InvalidParameterException,
2322             MissingParameterException,
2323             OperationFailedException,
2324             PermissionDeniedException {
2325 
2326         List<String> aocIdList = new ArrayList<String>();
2327 
2328         for (ActivityOfferingClusterInfo aoc : this.activityOfferingClusterMap.values()) {
2329 
2330             if (aoc.getFormatOfferingId().equals(formatOfferingId)) {
2331                 aocIdList.add(aoc.getId());
2332             }
2333         }
2334         return aocIdList;
2335 
2336     }
2337 
2338     @Override
2339     public List<BulkStatusInfo> generateRegistrationGroupsForCluster(
2340             String activityOfferingClusterId,
2341             ContextInfo contextInfo)
2342             throws DoesNotExistException,
2343             DataValidationErrorException,
2344             InvalidParameterException,
2345             MissingParameterException,
2346             OperationFailedException,
2347             PermissionDeniedException {
2348         throw new UnsupportedOperationException("Not supported yet.");
2349     }
2350 
2351     @Override
2352     public List<String> searchForActivityOfferingClusterIds(QueryByCriteria criteria, ContextInfo contextInfo) throws
2353             InvalidParameterException,
2354             MissingParameterException,
2355             OperationFailedException,
2356             PermissionDeniedException {
2357         throw new UnsupportedOperationException("Not supported yet.");
2358     }
2359 
2360     @Override
2361     public List<ActivityOfferingClusterInfo> searchForActivityOfferingClusters(QueryByCriteria criteria, ContextInfo contextInfo)
2362             throws InvalidParameterException,
2363             MissingParameterException,
2364             OperationFailedException,
2365             PermissionDeniedException {
2366         throw new UnsupportedOperationException("Not supported yet.");
2367     }
2368 
2369     @Override
2370     public List<String> searchForFormatOfferingIds(QueryByCriteria criteria, ContextInfo contextInfo) throws
2371             InvalidParameterException,
2372             MissingParameterException,
2373             OperationFailedException,
2374             PermissionDeniedException {
2375         throw new UnsupportedOperationException("Not supported yet.");
2376     }
2377 
2378     @Override
2379     public List<FormatOfferingInfo> searchForFormatOfferings(QueryByCriteria criteria, ContextInfo contextInfo) throws
2380             InvalidParameterException,
2381             MissingParameterException,
2382             OperationFailedException,
2383             PermissionDeniedException {
2384         throw new UnsupportedOperationException("Not supported yet.");
2385     }
2386 
2387     @Override
2388     public List<ActivityOfferingInfo> getActivityOfferingsForSeatPoolDefinition(
2389             String seatPoolDefinitionId,
2390             ContextInfo context)
2391             throws DoesNotExistException,
2392             InvalidParameterException,
2393             MissingParameterException,
2394             OperationFailedException,
2395             PermissionDeniedException {
2396 
2397         List<String> activityOfferingIds = this.activityOfferingToSeatPoolMap.get(seatPoolDefinitionId);
2398 
2399         return getActivityOfferingsByIds(activityOfferingIds, context);
2400     }
2401 
2402     public List<CourseOfferingInfo> getFormatOfferingsByIds(
2403             List<String> formatOfferingIds, ContextInfo contextInfo) throws DoesNotExistException,
2404             InvalidParameterException,
2405             MissingParameterException,
2406             OperationFailedException,
2407             PermissionDeniedException {
2408         throw new UnsupportedOperationException("Not supported yet.");
2409     }
2410 
2411     public List<CourseOfferingInfo> getSeatPoolDefinitionsByIds(
2412             List<String> seatPoolDefinitionIds, ContextInfo contextInfo) throws DoesNotExistException,
2413             InvalidParameterException,
2414             MissingParameterException,
2415             OperationFailedException,
2416             PermissionDeniedException {
2417         throw new UnsupportedOperationException("Not supported yet.");
2418     }
2419     
2420     
2421 }