Source Code Cross Referenced for SectionManagerImpl.java in  » ERP-CRM-Financial » sakai » org » sakaiproject » component » section » sakai » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » sakai » org.sakaiproject.component.section.sakai 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**********************************************************************************
0002:         * $URL: https://source.sakaiproject.org/svn/sections/tags/sakai_2-4-1/sections-impl/sakai/impl/src/java/org/sakaiproject/component/section/sakai/SectionManagerImpl.java $
0003:         * $Id: SectionManagerImpl.java 22202 2007-03-05 23:42:44Z jholtzman@berkeley.edu $
0004:         ***********************************************************************************
0005:         *
0006:         * Copyright (c) 2005, 2006 The Regents of the University of California and The Regents of the University of Michigan
0007:         * 
0008:         * Licensed under the Educational Community License, Version 1.0 (the "License"); 
0009:         * you may not use this file except in compliance with the License. 
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         *      http://www.opensource.org/licenses/ecl1.php
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software 
0015:         * distributed under the License is distributed on an "AS IS" BASIS, 
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
0017:         * See the License for the specific language governing permissions and 
0018:         * limitations under the License.
0019:         *
0020:         **********************************************************************************/package org.sakaiproject.component.section.sakai;
0021:
0022:        import java.sql.Time;
0023:        import java.util.ArrayList;
0024:        import java.util.Arrays;
0025:        import java.util.Collection;
0026:        import java.util.HashSet;
0027:        import java.util.Iterator;
0028:        import java.util.List;
0029:        import java.util.Locale;
0030:        import java.util.Set;
0031:
0032:        import org.apache.commons.lang.StringUtils;
0033:        import org.apache.commons.logging.Log;
0034:        import org.apache.commons.logging.LogFactory;
0035:        import org.sakaiproject.tool.api.SessionManager;
0036:        import org.sakaiproject.section.api.SectionAwareness;
0037:        import org.sakaiproject.section.api.SectionManager;
0038:        import org.sakaiproject.section.api.coursemanagement.Course;
0039:        import org.sakaiproject.section.api.coursemanagement.CourseSection;
0040:        import org.sakaiproject.section.api.coursemanagement.EnrollmentRecord;
0041:        import org.sakaiproject.section.api.coursemanagement.Meeting;
0042:        import org.sakaiproject.section.api.coursemanagement.ParticipationRecord;
0043:        import org.sakaiproject.section.api.coursemanagement.SectionEnrollments;
0044:        import org.sakaiproject.section.api.coursemanagement.User;
0045:        import org.sakaiproject.section.api.exception.MembershipException;
0046:        import org.sakaiproject.section.api.exception.RoleConfigurationException;
0047:        import org.sakaiproject.section.api.facade.Role;
0048:        import org.sakaiproject.component.cover.ComponentManager;
0049:        import org.sakaiproject.component.section.sakai.facade.SakaiUtil;
0050:        import org.sakaiproject.coursemanagement.api.CourseManagementService;
0051:        import org.sakaiproject.coursemanagement.api.Section;
0052:        import org.sakaiproject.coursemanagement.api.exception.IdNotFoundException;
0053:        import org.sakaiproject.exception.IdUnusedException;
0054:        import org.sakaiproject.exception.PermissionException;
0055:        import org.sakaiproject.authz.api.AuthzGroup;
0056:        import org.sakaiproject.authz.api.AuthzGroupService;
0057:        import org.sakaiproject.authz.api.AuthzPermissionException;
0058:        import org.sakaiproject.authz.api.GroupNotDefinedException;
0059:        import org.sakaiproject.authz.api.GroupProvider;
0060:        import org.sakaiproject.authz.api.Member;
0061:        import org.sakaiproject.entity.api.EntityManager;
0062:        import org.sakaiproject.entity.api.Reference;
0063:        import org.sakaiproject.entity.api.ResourceProperties;
0064:        import org.sakaiproject.event.api.Event;
0065:        import org.sakaiproject.event.api.EventTrackingService;
0066:        import org.sakaiproject.authz.api.SecurityService;
0067:        import org.sakaiproject.site.api.Group;
0068:        import org.sakaiproject.site.api.Site;
0069:        import org.sakaiproject.site.api.SiteAdvisor;
0070:        import org.sakaiproject.site.api.SiteService;
0071:        import org.sakaiproject.user.api.UserDirectoryService;
0072:        import org.sakaiproject.user.api.UserNotDefinedException;
0073:
0074:        /**
0075:         * A sakai-based implementation of the Section Management API, using the
0076:         * new grouping capability of the framework.
0077:         * 
0078:         * @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a>
0079:         *
0080:         */
0081:        public abstract class SectionManagerImpl implements  SectionManager,
0082:                SiteAdvisor {
0083:
0084:            private static final Log log = LogFactory
0085:                    .getLog(SectionManagerImpl.class);
0086:
0087:            // Sakai services set by method injection
0088:            protected abstract SiteService siteService();
0089:
0090:            // Sakai services set by dependency injection
0091:            protected AuthzGroupService authzGroupService;
0092:            protected GroupProvider groupProvider;
0093:            protected SecurityService securityService;
0094:            protected UserDirectoryService userDirectoryService;
0095:            protected SessionManager sessionManager;
0096:            protected EntityManager entityManager;
0097:            protected EventTrackingService eventTrackingService;
0098:            protected CourseManagementService courseManagementService;
0099:
0100:            // Configuration setting
0101:            protected ExternalIntegrationConfig config;
0102:
0103:            /**
0104:             * Initialization called once all dependencies are set.
0105:             */
0106:            public void init() {
0107:                if (log.isInfoEnabled())
0108:                    log.info("init()");
0109:                siteService().addSiteAdvisor(this );
0110:
0111:                // A group provider may not exist, so we can't use spring to inject it
0112:                groupProvider = (GroupProvider) ComponentManager
0113:                        .get(GroupProvider.class);
0114:            }
0115:
0116:            /**
0117:             * Cleans up any resources in use before destroying this service.
0118:             */
0119:            public void destroy() {
0120:                if (log.isInfoEnabled())
0121:                    log.info("destroy()");
0122:                siteService().removeSiteAdvisor(this );
0123:            }
0124:
0125:            // SiteAdvisor methods
0126:
0127:            /**
0128:             * {@inheritDoc}
0129:             */
0130:            public void update(Site site) {
0131:                // NOTE: This code will be called any time a site is saved (including site creation).
0132:                // Be very careful...
0133:
0134:                // If we're on a non-course site, do nothing
0135:                if (!"course".equalsIgnoreCase(site.getType())) {
0136:                    if (log.isDebugEnabled())
0137:                        log.debug("SiteAdvisor "
0138:                                + this .getClass().getCanonicalName()
0139:                                + " ignoring site " + site.getTitle()
0140:                                + ", which is not a course site");
0141:                    return;
0142:                }
0143:
0144:                // Get our app config and the site properties
0145:                ExternalIntegrationConfig appConfig = getConfiguration(null);
0146:                ResourceProperties siteProps = site.getProperties();
0147:
0148:                // If we're configured to be mandatory auto or mandatory manual, handle those conditions and return
0149:                if (handlingMandatoryConfigs(appConfig, site)) {
0150:                    if (log.isDebugEnabled())
0151:                        log.debug(this .getClass().getCanonicalName()
0152:                                + " finished decorating site "
0153:                                + site.getTitle() + " for " + appConfig);
0154:                    return;
0155:                }
0156:
0157:                // Set the defaults for non-mandatory sites
0158:                setSiteDefaults(site, appConfig, siteProps);
0159:
0160:                // If this site is manually managed, it could have been just changed to be manual.
0161:                // In that case, we flip the formerly "provided" users to be non-provided so they stay in the section.
0162:                if ("false".equals(siteProps
0163:                        .getProperty(CourseImpl.EXTERNALLY_MAINTAINED))) {
0164:                    if (log.isDebugEnabled())
0165:                        log
0166:                                .debug("SiteAdvisor "
0167:                                        + this .getClass().getCanonicalName()
0168:                                        + " stripping provider IDs from all sections in site "
0169:                                        + site.getTitle()
0170:                                        + ".  The site is internally managed.");
0171:                    for (Iterator iter = site.getGroups().iterator(); iter
0172:                            .hasNext();) {
0173:                        Group group = (Group) iter.next();
0174:                        if (group.getProviderGroupId() == null) {
0175:                            // This wasn't provided, so skip it
0176:                            continue;
0177:                        }
0178:                        group.setProviderGroupId(null);
0179:
0180:                        // Add members to the groups based on the current (provided) memberships
0181:                        Set members = group.getMembers();
0182:                        for (Iterator memberIter = members.iterator(); memberIter
0183:                                .hasNext();) {
0184:                            Member member = (Member) memberIter.next();
0185:                            if (member.isProvided()) {
0186:                                group.addMember(member.getUserId(), member
0187:                                        .getRole().getId(), member.isActive(),
0188:                                        false);
0189:                            }
0190:                        }
0191:                    }
0192:                } else {
0193:                    // This is an externally managed site, so remove any groups without a category and without a providerId
0194:                    for (Iterator<Group> iter = site.getGroups().iterator(); iter
0195:                            .hasNext();) {
0196:                        Group group = iter.next();
0197:                        ResourceProperties props = group.getProperties();
0198:                        if (group.getProviderGroupId() == null
0199:                                && (props != null && props
0200:                                        .getProperty(CourseSectionImpl.CATEGORY) != null)) {
0201:                            // This is a section, and it doesn't have a provider id
0202:                            iter.remove();
0203:                        }
0204:                    }
0205:                    // Update the sections from CM.
0206:                    syncSections(site);
0207:                }
0208:            }
0209:
0210:            private boolean handlingMandatoryConfigs(
0211:                    ExternalIntegrationConfig appConfig, Site site) {
0212:                ResourceProperties siteProps = site.getProperties();
0213:
0214:                switch (appConfig) {
0215:                case MANUAL_MANDATORY:
0216:                    // If we're configured to treat all sites as manual, set the site to manual control
0217:                    siteProps.addProperty(CourseImpl.EXTERNALLY_MAINTAINED,
0218:                            Boolean.FALSE.toString());
0219:                    return true;
0220:
0221:                case AUTOMATIC_MANDATORY:
0222:                    // If we're configured to treat all sites as automatic, set the site to external control and update the sections
0223:                    siteProps.addProperty(CourseImpl.EXTERNALLY_MAINTAINED,
0224:                            Boolean.TRUE.toString());
0225:                    siteProps.addProperty(
0226:                            CourseImpl.STUDENT_REGISTRATION_ALLOWED,
0227:                            Boolean.FALSE.toString());
0228:                    siteProps.addProperty(CourseImpl.STUDENT_SWITCHING_ALLOWED,
0229:                            Boolean.FALSE.toString());
0230:                    syncSections(site);
0231:                    return true;
0232:
0233:                default:
0234:                    return false;
0235:                }
0236:            }
0237:
0238:            private void setSiteDefaults(Site site,
0239:                    ExternalIntegrationConfig appConfig,
0240:                    ResourceProperties siteProps) {
0241:                // If the site doesn't have a property set for "Externally Maintained", it's either a new site or one
0242:                // that was created before this SiteAdvisor was registered.
0243:                if (siteProps.getProperty(CourseImpl.EXTERNALLY_MAINTAINED) == null) {
0244:                    // Set this property to external if the app config is AUTOMATIC_DEFAULT, else make it internally managed
0245:                    // FIXME -- This might have unforseen consequences...
0246:                    if (log.isDebugEnabled())
0247:                        log.debug("Site '" + site.getTitle()
0248:                                + "' has no EXTERNALLY_MAINTAINED flag.");
0249:                    if (appConfig == ExternalIntegrationConfig.AUTOMATIC_DEFAULT) {
0250:                        siteProps.addProperty(CourseImpl.EXTERNALLY_MAINTAINED,
0251:                                Boolean.TRUE.toString());
0252:                        siteProps.addProperty(
0253:                                CourseImpl.STUDENT_REGISTRATION_ALLOWED,
0254:                                Boolean.FALSE.toString());
0255:                        siteProps.addProperty(
0256:                                CourseImpl.STUDENT_SWITCHING_ALLOWED,
0257:                                Boolean.FALSE.toString());
0258:                    } else if (appConfig == ExternalIntegrationConfig.MANUAL_DEFAULT) {
0259:                        siteProps.addProperty(CourseImpl.EXTERNALLY_MAINTAINED,
0260:                                Boolean.FALSE.toString());
0261:                        return;
0262:                    }
0263:                }
0264:            }
0265:
0266:            /**
0267:             * Replaces all existing sections (whether internally or externally defined) with
0268:             * sections that are externally defined.
0269:             * 
0270:             * @param site
0271:             * @param appConfig
0272:             */
0273:            private void syncSections(Site site) {
0274:                if (log.isInfoEnabled())
0275:                    log
0276:                            .info("Synchronizing internal sections with externally defined sections in site "
0277:                                    + site.getId());
0278:
0279:                // Use the group provider to split the complex string
0280:                if (groupProvider == null) {
0281:                    log
0282:                            .warn("SectionManager can not automatically generate sections without"
0283:                                    + "a properly configured GroupProvider");
0284:                    return;
0285:                }
0286:
0287:                // Get the provider Ids associated with this site.  We can't use
0288:                // authzGroupService.getProviderIds(), since we're inspecting the provider IDs
0289:                // on the in-memory object, not what's in persistence
0290:                String siteProviderId = site.getProviderGroupId();
0291:                List<String> providerIdList;
0292:                if (StringUtils.trimToNull(siteProviderId) == null) {
0293:                    providerIdList = new ArrayList<String>();
0294:                } else {
0295:                    String[] providerIdArray = groupProvider
0296:                            .unpackId(siteProviderId);
0297:                    providerIdList = Arrays.asList(providerIdArray);
0298:                }
0299:
0300:                Set<Group> sectionsToSync = new HashSet<Group>();
0301:
0302:                // Remove any formerly provided sections that are no longer in the list of provider ids,
0303:                // and sync existing sections if they are still listed in the provider ids.
0304:                if (site.getGroups() != null) {
0305:                    for (Iterator<Group> iter = site.getGroups().iterator(); iter
0306:                            .hasNext();) {
0307:                        Group group = iter.next();
0308:                        String providerId = group.getProviderGroupId();
0309:                        if (providerId == null) {
0310:                            // This wasn't provided, so skip it
0311:                            continue;
0312:                        }
0313:                        if (group.getProperties() == null
0314:                                || StringUtils
0315:                                        .trimToNull(group
0316:                                                .getProperties()
0317:                                                .getProperty(
0318:                                                        CourseSectionImpl.CATEGORY)) == null) {
0319:                            // This isn't a section, so skip it
0320:                            continue;
0321:                        }
0322:                        if (providerIdList.contains(providerId)) {
0323:                            if (log.isDebugEnabled())
0324:                                log.debug("Synchronizing section "
0325:                                        + group.getReference());
0326:                            sectionsToSync.add(group);
0327:                        } else {
0328:                            if (log.isDebugEnabled())
0329:                                log.debug("Removing section "
0330:                                        + group.getReference());
0331:                            iter.remove();
0332:                        }
0333:                    }
0334:                }
0335:
0336:                // Sync existing sections
0337:                Set<String> sectionProviderIdsToSync = new HashSet<String>();
0338:                for (Iterator<Group> iter = sectionsToSync.iterator(); iter
0339:                        .hasNext();) {
0340:                    Group group = iter.next();
0341:                    sectionProviderIdsToSync.add(group.getProviderGroupId());
0342:                    syncExternalCourseSectionWithSite(group);
0343:                }
0344:
0345:                // Add provided sections that we're not synchronizing
0346:                for (Iterator<String> iter = providerIdList.iterator(); iter
0347:                        .hasNext();) {
0348:                    String providerId = iter.next();
0349:                    if (!sectionProviderIdsToSync.contains(providerId)) {
0350:                        addExternalCourseSectionToSite(site, providerId);
0351:                    }
0352:                }
0353:            }
0354:
0355:            /**
0356:             * Synchronizes the state of an internal CourseSection with the state of an externally
0357:             * defined (CM) section.  This is done so meeting times, locations, etc are kept
0358:             * in sync with changes made to these data outside Sakai.
0359:             * 
0360:             * @param group
0361:             */
0362:            private void syncExternalCourseSectionWithSite(Group group) {
0363:                String providerId = group.getProviderGroupId();
0364:                Section officialSection = null;
0365:                try {
0366:                    officialSection = courseManagementService
0367:                            .getSection(providerId);
0368:                } catch (IdNotFoundException ide) {
0369:                    log.error("Site " + group.getContainingSite().getId()
0370:                            + " has a provider id, " + providerId
0371:                            + ", that has no matching section in CM.");
0372:                    return;
0373:                }
0374:                decorateGroupWithCmSection(group, officialSection);
0375:            }
0376:
0377:            private CourseSection decorateGroupWithCmSection(Group group,
0378:                    Section officialSection) {
0379:                CourseSectionImpl section = new CourseSectionImpl(group);
0380:
0381:                section.setTitle(officialSection.getTitle());
0382:                section.setCategory(officialSection.getCategory());
0383:                section.setMaxEnrollments(officialSection.getMaxSize());
0384:                Set officialMeetings = officialSection.getMeetings();
0385:                if (officialMeetings != null) {
0386:                    List<Meeting> meetings = new ArrayList<Meeting>();
0387:                    for (Iterator meetingIter = officialMeetings.iterator(); meetingIter
0388:                            .hasNext();) {
0389:                        org.sakaiproject.coursemanagement.api.Meeting officialMeeting = (org.sakaiproject.coursemanagement.api.Meeting) meetingIter
0390:                                .next();
0391:                        MeetingImpl meeting = new MeetingImpl(officialMeeting
0392:                                .getLocation(), officialMeeting.getStartTime(),
0393:                                officialMeeting.getFinishTime(),
0394:                                officialMeeting.isMonday(), officialMeeting
0395:                                        .isTuesday(), officialMeeting
0396:                                        .isWednesday(), officialMeeting
0397:                                        .isThursday(), officialMeeting
0398:                                        .isFriday(), officialMeeting
0399:                                        .isSaturday(), officialMeeting
0400:                                        .isSunday());
0401:                        meetings.add(meeting);
0402:                    }
0403:                    section.setMeetings(meetings);
0404:                }
0405:                // Ensure that the group is decorated properly, so the group properties are
0406:                // persisted with the correct section metadata
0407:                section.decorateGroup(group);
0408:
0409:                return section;
0410:            }
0411:
0412:            /**
0413:             * Adds an externally managed CourseSection (a decorated group) to a site.  The CourseSection is
0414:             * constructed by finding the official section from CM and converting it to a CourseSection.
0415:             * 
0416:             * @param site The site in which we are adding a CourseSection 
0417:             * @param sectionId The Enterprise ID of the section to add.
0418:             * 
0419:             * @return The CourseSection that was added to the site
0420:             */
0421:            private CourseSection addExternalCourseSectionToSite(Site site,
0422:                    String sectionEid) {
0423:                if (log.isDebugEnabled())
0424:                    log.debug("Adding section " + sectionEid + " to site "
0425:                            + site.getId());
0426:
0427:                // Create a new sakai section (group) for this providerId
0428:                Section officialSection = null;
0429:                try {
0430:                    officialSection = courseManagementService
0431:                            .getSection(sectionEid);
0432:                } catch (IdNotFoundException ide) {
0433:                    log.error("Site " + site.getId() + " has a provider id, "
0434:                            + sectionEid
0435:                            + ", that has no matching section in CM.");
0436:                    return null;
0437:                }
0438:                Group group = site.addGroup();
0439:                group.setProviderGroupId(sectionEid);
0440:                return decorateGroupWithCmSection(group, officialSection);
0441:            }
0442:
0443:            // SectionManager Methods
0444:
0445:            /**
0446:             * Filters out framework groups that do not have a category.  A section's
0447:             * category is determined by 
0448:             * 
0449:             */
0450:            public List<CourseSection> getSections(String siteContext) {
0451:                if (log.isDebugEnabled())
0452:                    log.debug("Getting sections for context " + siteContext);
0453:                List<CourseSection> sectionList = new ArrayList<CourseSection>();
0454:                Collection sections;
0455:                try {
0456:                    sections = siteService().getSite(siteContext).getGroups();
0457:                } catch (IdUnusedException e) {
0458:                    log.error("No site with id = " + siteContext);
0459:                    return new ArrayList<CourseSection>();
0460:                }
0461:                for (Iterator iter = sections.iterator(); iter.hasNext();) {
0462:                    Group group = (Group) iter.next();
0463:                    // Only use groups with a category defined.  If there is no category,
0464:                    // it is not a section.
0465:                    if (StringUtils.trimToNull(group.getProperties()
0466:                            .getProperty(CourseSectionImpl.CATEGORY)) != null) {
0467:                        sectionList.add(new CourseSectionImpl(group));
0468:                    }
0469:                }
0470:                return sectionList;
0471:            }
0472:
0473:            /**
0474:             * {@inheritDoc}
0475:             */
0476:            public List<CourseSection> getSectionsInCategory(
0477:                    String siteContext, String categoryId) {
0478:                if (log.isDebugEnabled())
0479:                    log.debug("Getting " + categoryId
0480:                            + " sections for context " + siteContext);
0481:                List<CourseSection> sectionList = new ArrayList<CourseSection>();
0482:                Collection sections;
0483:                try {
0484:                    sections = siteService().getSite(siteContext).getGroups();
0485:                } catch (IdUnusedException e) {
0486:                    log.error("No site with id = " + siteContext);
0487:                    return new ArrayList<CourseSection>();
0488:                }
0489:                for (Iterator iter = sections.iterator(); iter.hasNext();) {
0490:                    Group group = (Group) iter.next();
0491:                    if (categoryId.equals(group.getProperties().getProperty(
0492:                            CourseSectionImpl.CATEGORY))) {
0493:                        sectionList.add(new CourseSectionImpl(group));
0494:                    }
0495:                }
0496:                return sectionList;
0497:            }
0498:
0499:            /**
0500:             * {@inheritDoc}
0501:             */
0502:            public CourseSection getSection(String sectionUuid) {
0503:                Group group;
0504:                group = siteService().findGroup(sectionUuid);
0505:                if (group == null) {
0506:                    log.error("Unable to find section " + sectionUuid);
0507:                    return null;
0508:                }
0509:                return new CourseSectionImpl(group);
0510:            }
0511:
0512:            /**
0513:             * {@inheritDoc}
0514:             */
0515:            public List<ParticipationRecord> getSiteInstructors(
0516:                    String siteContext) {
0517:                CourseImpl course = (CourseImpl) getCourse(siteContext);
0518:                if (course == null) {
0519:                    return new ArrayList<ParticipationRecord>();
0520:                }
0521:                Site site = course.getSite();
0522:                Set sakaiUserIds = site
0523:                        .getUsersIsAllowed(SectionAwareness.INSTRUCTOR_MARKER);
0524:                List sakaiMembers = userDirectoryService.getUsers(sakaiUserIds);
0525:                List<ParticipationRecord> membersList = new ArrayList<ParticipationRecord>();
0526:                for (Iterator iter = sakaiMembers.iterator(); iter.hasNext();) {
0527:                    org.sakaiproject.user.api.User sakaiUser = (org.sakaiproject.user.api.User) iter
0528:                            .next();
0529:                    User user = SakaiUtil.convertUser(sakaiUser);
0530:                    InstructorRecordImpl record = new InstructorRecordImpl(
0531:                            course, user);
0532:                    membersList.add(record);
0533:                }
0534:                return membersList;
0535:            }
0536:
0537:            /**
0538:             * {@inheritDoc}
0539:             */
0540:            public List<ParticipationRecord> getSiteTeachingAssistants(
0541:                    String siteContext) {
0542:                CourseImpl course = (CourseImpl) getCourse(siteContext);
0543:                if (course == null) {
0544:                    return new ArrayList<ParticipationRecord>();
0545:                }
0546:                Site site = course.getSite();
0547:                Set sakaiUserIds = site
0548:                        .getUsersIsAllowed(SectionAwareness.TA_MARKER);
0549:                List sakaiMembers = userDirectoryService.getUsers(sakaiUserIds);
0550:                List<ParticipationRecord> membersList = new ArrayList<ParticipationRecord>();
0551:                for (Iterator iter = sakaiMembers.iterator(); iter.hasNext();) {
0552:                    org.sakaiproject.user.api.User sakaiUser = (org.sakaiproject.user.api.User) iter
0553:                            .next();
0554:                    User user = SakaiUtil.convertUser(sakaiUser);
0555:                    TeachingAssistantRecordImpl record = new TeachingAssistantRecordImpl(
0556:                            course, user);
0557:                    membersList.add(record);
0558:                }
0559:                return membersList;
0560:            }
0561:
0562:            /**
0563:             * {@inheritDoc}
0564:             */
0565:            public List<EnrollmentRecord> getSiteEnrollments(String siteContext) {
0566:                CourseImpl course = (CourseImpl) getCourse(siteContext);
0567:                if (course == null) {
0568:                    return new ArrayList<EnrollmentRecord>();
0569:                }
0570:                Site site = course.getSite();
0571:                Set sakaiUserIds = site
0572:                        .getUsersIsAllowed(SectionAwareness.STUDENT_MARKER);
0573:                List sakaiMembers = userDirectoryService.getUsers(sakaiUserIds);
0574:                List<EnrollmentRecord> membersList = new ArrayList<EnrollmentRecord>();
0575:                for (Iterator iter = sakaiMembers.iterator(); iter.hasNext();) {
0576:                    org.sakaiproject.user.api.User sakaiUser = (org.sakaiproject.user.api.User) iter
0577:                            .next();
0578:                    User user = SakaiUtil.convertUser(sakaiUser);
0579:                    EnrollmentRecordImpl record = new EnrollmentRecordImpl(
0580:                            course, null, user);
0581:                    membersList.add(record);
0582:                }
0583:                return membersList;
0584:            }
0585:
0586:            /**
0587:             * {@inheritDoc}
0588:             */
0589:            public List<ParticipationRecord> getSectionTeachingAssistants(
0590:                    String sectionUuid) {
0591:                Group group = siteService().findGroup(sectionUuid);
0592:                CourseSection section = getSection(sectionUuid);
0593:                if (section == null) {
0594:                    return new ArrayList<ParticipationRecord>();
0595:                }
0596:                if (log.isDebugEnabled())
0597:                    log.debug("Getting section enrollments in " + sectionUuid);
0598:                String taRole;
0599:                try {
0600:                    taRole = getSectionTaRole(group);
0601:                } catch (RoleConfigurationException rce) {
0602:                    return new ArrayList<ParticipationRecord>();
0603:                }
0604:                Set sakaiUserUids = group.getUsersHasRole(taRole);
0605:                List sakaiUsers = userDirectoryService.getUsers(sakaiUserUids);
0606:
0607:                List<ParticipationRecord> membersList = new ArrayList<ParticipationRecord>();
0608:                for (Iterator iter = sakaiUsers.iterator(); iter.hasNext();) {
0609:                    User user = SakaiUtil
0610:                            .convertUser((org.sakaiproject.user.api.User) iter
0611:                                    .next());
0612:                    TeachingAssistantRecordImpl record = new TeachingAssistantRecordImpl(
0613:                            section, user);
0614:                    membersList.add(record);
0615:                }
0616:                return membersList;
0617:            }
0618:
0619:            /**
0620:             * {@inheritDoc}
0621:             */
0622:            public List<EnrollmentRecord> getSectionEnrollments(
0623:                    String sectionUuid) {
0624:                Group group = siteService().findGroup(sectionUuid);
0625:                CourseSection section = getSection(sectionUuid);
0626:                if (section == null) {
0627:                    return new ArrayList<EnrollmentRecord>();
0628:                }
0629:                if (log.isDebugEnabled())
0630:                    log.debug("Getting section enrollments in " + sectionUuid);
0631:                String studentRole;
0632:                try {
0633:                    studentRole = getSectionStudentRole(group);
0634:                } catch (RoleConfigurationException rce) {
0635:                    log.error(rce);
0636:                    return new ArrayList<EnrollmentRecord>();
0637:                }
0638:
0639:                Set sakaiUserUids = group.getUsersHasRole(studentRole);
0640:                List sakaiUsers = userDirectoryService.getUsers(sakaiUserUids);
0641:
0642:                List<EnrollmentRecord> membersList = new ArrayList<EnrollmentRecord>();
0643:                for (Iterator iter = sakaiUsers.iterator(); iter.hasNext();) {
0644:                    User user = SakaiUtil
0645:                            .convertUser((org.sakaiproject.user.api.User) iter
0646:                                    .next());
0647:                    EnrollmentRecordImpl record = new EnrollmentRecordImpl(
0648:                            section, null, user);
0649:                    membersList.add(record);
0650:                }
0651:                return membersList;
0652:            }
0653:
0654:            /**
0655:             * {@inheritDoc}
0656:             */
0657:            public List<EnrollmentRecord> findSiteEnrollments(
0658:                    String siteContext, String pattern) {
0659:                List<EnrollmentRecord> fullList = getSiteEnrollments(siteContext);
0660:                List<EnrollmentRecord> filteredList = new ArrayList<EnrollmentRecord>();
0661:                for (Iterator iter = fullList.iterator(); iter.hasNext();) {
0662:                    EnrollmentRecord record = (EnrollmentRecord) iter.next();
0663:                    User user = record.getUser();
0664:                    if (user.getDisplayName().toLowerCase().startsWith(
0665:                            pattern.toLowerCase())
0666:                            || user.getSortName().toLowerCase().startsWith(
0667:                                    pattern.toLowerCase())
0668:                            || user.getDisplayId().toLowerCase().startsWith(
0669:                                    pattern.toLowerCase())) {
0670:                        filteredList.add(record);
0671:                    }
0672:                }
0673:                return filteredList;
0674:            }
0675:
0676:            /**
0677:             * {@inheritDoc}
0678:             */
0679:            public String getCategoryName(String categoryId, Locale locale) {
0680:                return courseManagementService
0681:                        .getSectionCategoryDescription(categoryId);
0682:            }
0683:
0684:            /**
0685:             * {@inheritDoc}
0686:             */
0687:            public List<String> getSectionCategories(String siteContext) {
0688:                return courseManagementService.getSectionCategories();
0689:            }
0690:
0691:            /**
0692:             * {@inheritDoc}
0693:             */
0694:            public Course getCourse(String siteContext) {
0695:                if (log.isDebugEnabled())
0696:                    log.debug("Getting course for context " + siteContext);
0697:                Site site;
0698:                try {
0699:                    site = siteService().getSite(siteContext);
0700:                } catch (IdUnusedException e) {
0701:                    log.error("Could not find site with id = " + siteContext);
0702:                    return null;
0703:                }
0704:                return new CourseImpl(site);
0705:            }
0706:
0707:            /**
0708:             * {@inheritDoc}
0709:             */
0710:            public SectionEnrollments getSectionEnrollmentsForStudents(
0711:                    String siteContext, Set studentUids) {
0712:                if (studentUids == null || studentUids.isEmpty()) {
0713:                    if (log.isDebugEnabled())
0714:                        log
0715:                                .debug("Null or empty set of student Uids passed to getSectionEnrollmentsForStudents");
0716:                    return new SectionEnrollmentsImpl(new ArrayList());
0717:                }
0718:                // Get all sections
0719:                List allSections = getSections(siteContext);
0720:
0721:                // Get all student enrollments in each section, and combine them into a single collection
0722:                List<ParticipationRecord> allSectionEnrollments = new ArrayList<ParticipationRecord>();
0723:                for (Iterator sectionIter = allSections.iterator(); sectionIter
0724:                        .hasNext();) {
0725:                    CourseSection section = (CourseSection) sectionIter.next();
0726:                    List sectionEnrollments = getSectionEnrollments(section
0727:                            .getUuid());
0728:                    for (Iterator enrollmentIter = sectionEnrollments
0729:                            .iterator(); enrollmentIter.hasNext();) {
0730:                        EnrollmentRecord enr = (EnrollmentRecord) enrollmentIter
0731:                                .next();
0732:                        if (studentUids.contains(enr.getUser().getUserUid())) {
0733:                            allSectionEnrollments.add(enr);
0734:                        }
0735:                    }
0736:                }
0737:
0738:                return new SectionEnrollmentsImpl(allSectionEnrollments);
0739:            }
0740:
0741:            /**
0742:             * Posts an event to Sakai's event tracking service.  only posts events
0743:             * that modify some object.  Read-only events are not tracked.
0744:             * 
0745:             * @param message The message to post
0746:             * @param objectReference The object that was modified in the event
0747:             */
0748:            private void postEvent(String message, String objectReference) {
0749:                Event event = eventTrackingService.newEvent(message,
0750:                        objectReference, true);
0751:                eventTrackingService.post(event);
0752:            }
0753:
0754:            /**
0755:             * {@inheritDoc}
0756:             */
0757:            public EnrollmentRecord joinSection(String sectionUuid)
0758:                    throws RoleConfigurationException {
0759:                // Disallow if we're in an externally managed site
0760:                ensureInternallyManaged(getSection(sectionUuid).getCourse()
0761:                        .getUuid());
0762:
0763:                Group group = siteService().findGroup(sectionUuid);
0764:
0765:                // It's possible that this section has been deleted
0766:                if (group == null) {
0767:                    log.error("Section " + sectionUuid
0768:                            + " has been deleted, so it can't be joined.");
0769:                    return null;
0770:                }
0771:
0772:                String role = getSectionStudentRole(group);
0773:                try {
0774:                    authzGroupService.joinGroup(sectionUuid, role);
0775:                    postEvent("section.student.join", sectionUuid);
0776:                } catch (AuthzPermissionException e) {
0777:                    log
0778:                            .error(
0779:                                    "access denied while attempting to join authz group: ",
0780:                                    e);
0781:                    return null;
0782:                } catch (GroupNotDefinedException e) {
0783:                    log
0784:                            .error(
0785:                                    "can not find group while attempting to join authz group: ",
0786:                                    e);
0787:                    return null;
0788:                }
0789:
0790:                // Return the membership record that the app understands
0791:                String userUid = sessionManager.getCurrentSessionUserId();
0792:                User user = SakaiUtil.getUserFromSakai(userUid);
0793:                CourseSection section = getSection(sectionUuid);
0794:
0795:                return new EnrollmentRecordImpl(section, null, user);
0796:            }
0797:
0798:            private String getSectionStudentRole(AuthzGroup group)
0799:                    throws RoleConfigurationException {
0800:                Set roleStrings = group
0801:                        .getRolesIsAllowed(SectionAwareness.STUDENT_MARKER);
0802:                if (roleStrings.size() != 1) {
0803:                    if (log.isDebugEnabled())
0804:                        log
0805:                                .debug("Group "
0806:                                        + group
0807:                                        + " must have one and only one role with permission "
0808:                                        + SectionAwareness.STUDENT_MARKER);
0809:                    throw new RoleConfigurationException(
0810:                            "Can't add a user to a section as a student, since there is no student-flagged role");
0811:                }
0812:                return (String) roleStrings.iterator().next();
0813:            }
0814:
0815:            private String getSectionTaRole(Group group)
0816:                    throws RoleConfigurationException {
0817:                Set roleStrings = group
0818:                        .getRolesIsAllowed(SectionAwareness.TA_MARKER);
0819:                if (roleStrings.size() != 1) {
0820:                    if (log.isDebugEnabled())
0821:                        log
0822:                                .debug("Group "
0823:                                        + group
0824:                                        + " must have one and only one role with permission "
0825:                                        + SectionAwareness.TA_MARKER);
0826:                    throw new RoleConfigurationException(
0827:                            "Can't add a user to a section as a TA, since there is no TA-flagged role");
0828:                }
0829:                return (String) roleStrings.iterator().next();
0830:            }
0831:
0832:            /**
0833:             * {@inheritDoc}
0834:             */
0835:            public void switchSection(String newSectionUuid)
0836:                    throws RoleConfigurationException {
0837:                // Disallow if we're in an externally managed site
0838:                ensureInternallyManaged(getSection(newSectionUuid).getCourse()
0839:                        .getUuid());
0840:
0841:                CourseSection newSection = getSection(newSectionUuid);
0842:
0843:                // It's possible that this section has been deleted
0844:                if (newSection == null) {
0845:                    return;
0846:                }
0847:
0848:                // Disallow if we're in an externally managed site
0849:                if (isExternallyManaged(newSection.getCourse().getUuid())) {
0850:                    log
0851:                            .warn("Can not switch sections in an externally managed site");
0852:                    return;
0853:                }
0854:
0855:                String userUid = sessionManager.getCurrentSessionUserId();
0856:
0857:                // Remove any section membership for a section of the same category.
0858:                // We can not use dropEnrollmentFromCategory because security checks won't
0859:                // allow a student to update the authZ groups directly.
0860:                List categorySections = getSectionsInCategory(newSection
0861:                        .getCourse().getSiteContext(), newSection.getCategory());
0862:
0863:                boolean errorDroppingSection = false;
0864:
0865:                String oldSectionUuid = null;
0866:                for (Iterator iter = categorySections.iterator(); iter
0867:                        .hasNext();) {
0868:                    CourseSection section = (CourseSection) iter.next();
0869:                    // Skip the current section
0870:                    if (section.getUuid().equals(newSectionUuid)) {
0871:                        continue;
0872:                    }
0873:                    if (this .isMember(userUid, section)) {
0874:                        oldSectionUuid = section.getUuid();
0875:                        try {
0876:                            authzGroupService.unjoinGroup(section.getUuid());
0877:                            oldSectionUuid = section.getUuid();
0878:                        } catch (GroupNotDefinedException e) {
0879:                            errorDroppingSection = true;
0880:                            log.error("There is not authzGroup with id "
0881:                                    + section.getUuid());
0882:                        } catch (AuthzPermissionException e) {
0883:                            errorDroppingSection = true;
0884:                            log.error("Permission denied while " + userUid
0885:                                    + " attempted to unjoin authzGroup "
0886:                                    + section.getUuid());
0887:                        }
0888:                    }
0889:                }
0890:
0891:                // Only allow the user to join the new section if there were no errors dropping section(s)
0892:                if (!errorDroppingSection) {
0893:                    // Join the new section
0894:                    joinSection(newSectionUuid);
0895:
0896:                    // Post the events
0897:                    postEvent("section.student.unjoin", oldSectionUuid);
0898:                    postEvent("section.student.switch", newSectionUuid);
0899:                }
0900:
0901:            }
0902:
0903:            private boolean isMember(String userUid, CourseSection section) {
0904:                return authzGroupService
0905:                        .getUserRole(userUid, section.getUuid()) != null;
0906:            }
0907:
0908:            /**
0909:             * {@inheritDoc}
0910:             */
0911:            public ParticipationRecord addSectionMembership(String userUid,
0912:                    Role role, String sectionUuid) throws MembershipException,
0913:                    RoleConfigurationException {
0914:                if (role.isStudent()) {
0915:                    // Disallow if we're in an externally managed site
0916:                    ensureInternallyManaged(getSection(sectionUuid).getCourse()
0917:                            .getUuid());
0918:                    return addStudentToSection(userUid, sectionUuid);
0919:                } else if (role.isTeachingAssistant()) {
0920:                    return addTaToSection(userUid, sectionUuid);
0921:                } else {
0922:                    throw new RuntimeException(
0923:                            "Adding a user to a section with role instructor or none is not supported");
0924:                }
0925:            }
0926:
0927:            private ParticipationRecord addTaToSection(String userUid,
0928:                    String sectionUuid) throws RoleConfigurationException {
0929:                CourseSectionImpl section = (CourseSectionImpl) getSection(sectionUuid);
0930:
0931:                // It's possible that this section has been deleted
0932:                if (section == null) {
0933:                    return null;
0934:                }
0935:
0936:                Group group = section.getGroup();
0937:                User user = SakaiUtil.getUserFromSakai(userUid);
0938:
0939:                // Add the membership to the framework
0940:                String role = getSectionTaRole(group);
0941:
0942:                group.addMember(userUid, role, true, false);
0943:
0944:                try {
0945:                    siteService()
0946:                            .saveGroupMembership(group.getContainingSite());
0947:                    postEvent("section.add.ta", sectionUuid);
0948:                } catch (IdUnusedException e) {
0949:                    log.error("unable to find site: ", e);
0950:                    return null;
0951:                } catch (PermissionException e) {
0952:                    log.error("access denied while attempting to save site: ",
0953:                            e);
0954:                    return null;
0955:                }
0956:
0957:                // Return the enrollment record
0958:                return new TeachingAssistantRecordImpl(section, user);
0959:            }
0960:
0961:            private EnrollmentRecord addStudentToSection(String userUid,
0962:                    String sectionUuid) throws RoleConfigurationException {
0963:                User user = SakaiUtil.getUserFromSakai(userUid);
0964:
0965:                CourseSectionImpl newSection = (CourseSectionImpl) getSection(sectionUuid);
0966:
0967:                // It's possible that this section has been deleted
0968:                if (newSection == null) {
0969:                    return null;
0970:                }
0971:
0972:                Group group = newSection.getGroup();
0973:
0974:                String studentRole = getSectionStudentRole(group);
0975:
0976:                // Remove any section membership for a section of the same category.
0977:                dropEnrollmentFromCategory(userUid, newSection.getCourse()
0978:                        .getSiteContext(), newSection.getCategory());
0979:
0980:                // Add the membership to the framework
0981:                if (studentRole == null) {
0982:                    throw new RoleConfigurationException(
0983:                            "Can't add a student to a section, since there is no student-flgagged role");
0984:                }
0985:                group.addMember(userUid, studentRole, true, false);
0986:
0987:                try {
0988:                    siteService()
0989:                            .saveGroupMembership(group.getContainingSite());
0990:                    postEvent("section.add.student", sectionUuid);
0991:                } catch (IdUnusedException e) {
0992:                    log.error("unable to find site: ", e);
0993:                    return null;
0994:                } catch (PermissionException e) {
0995:                    log.error("access denied while attempting to save site: ",
0996:                            e);
0997:                    return null;
0998:                }
0999:
1000:                // Return the enrollment record
1001:                return new EnrollmentRecordImpl(newSection, null, user);
1002:            }
1003:
1004:            /**
1005:             * {@inheritDoc}
1006:             */
1007:            public void setSectionMemberships(Set userUids, Role role,
1008:                    String sectionUuid) throws RoleConfigurationException {
1009:                if (role.isStudent()) {
1010:                    // Disallow if we're in an externally managed site
1011:                    ensureInternallyManaged(getSection(sectionUuid).getCourse()
1012:                            .getUuid());
1013:                }
1014:
1015:                CourseSectionImpl section = (CourseSectionImpl) getSection(sectionUuid);
1016:
1017:                // It's possible that this section has been deleted
1018:                if (section == null) {
1019:                    return;
1020:                }
1021:
1022:                Group group = section.getGroup();
1023:                String sakaiRoleString;
1024:                if (role.isTeachingAssistant()) {
1025:                    sakaiRoleString = getSectionTaRole(group);
1026:                } else if (role.isStudent()) {
1027:                    sakaiRoleString = getSectionStudentRole(group);
1028:                } else {
1029:                    String str = "Only students and TAs can be added to sections";
1030:                    log.error(str);
1031:                    throw new RuntimeException(str);
1032:                }
1033:
1034:                if (sakaiRoleString == null) {
1035:                    throw new RoleConfigurationException(
1036:                            "Can't set memberships for role "
1037:                                    + role
1038:                                    + ".  No sakai role string can be found for this role.");
1039:                }
1040:
1041:                // Remove the current members in this role
1042:                Set currentUserIds = group.getUsersHasRole(sakaiRoleString);
1043:                for (Iterator iter = currentUserIds.iterator(); iter.hasNext();) {
1044:                    String userUid = (String) iter.next();
1045:                    group.removeMember(userUid);
1046:                }
1047:
1048:                // Add the new members (sure would be nice to have transactions here!)
1049:                for (Iterator iter = userUids.iterator(); iter.hasNext();) {
1050:                    String userUid = (String) iter.next();
1051:                    group.addMember(userUid, sakaiRoleString, true, false);
1052:                }
1053:
1054:                try {
1055:                    siteService()
1056:                            .saveGroupMembership(group.getContainingSite());
1057:                    postEvent("section.members.reset", sectionUuid);
1058:                } catch (IdUnusedException e) {
1059:                    log.error("unable to find site: ", e);
1060:                } catch (PermissionException e) {
1061:                    log
1062:                            .error(
1063:                                    "access denied while attempting to save authz group: ",
1064:                                    e);
1065:                }
1066:            }
1067:
1068:            /**
1069:             * {@inheritDoc}
1070:             */
1071:            public void dropSectionMembership(String userUid, String sectionUuid) {
1072:
1073:                CourseSectionImpl section = (CourseSectionImpl) getSection(sectionUuid);
1074:                Group group = section.getGroup();
1075:
1076:                // If we're trying to drop a student, ensure that we're not automatically managed
1077:                Member member = group.getMember(userUid);
1078:                String studentRole = null;
1079:                try {
1080:                    studentRole = getSectionStudentRole(group);
1081:                } catch (RoleConfigurationException e1) {
1082:                    log.error("Can't find the student role for section"
1083:                            + sectionUuid);
1084:                }
1085:                if (studentRole != null && studentRole.equals(member.getRole())) {
1086:                    // We can not drop students from a section in externally managed sites
1087:                    ensureInternallyManaged(section.getCourse().getUuid());
1088:                }
1089:
1090:                group.removeMember(userUid);
1091:                try {
1092:                    siteService()
1093:                            .saveGroupMembership(group.getContainingSite());
1094:                    postEvent("section.student.drop", sectionUuid);
1095:                } catch (IdUnusedException e) {
1096:                    log.error("unable to find site: ", e);
1097:                } catch (PermissionException e) {
1098:                    log.error("access denied while attempting to save site: ",
1099:                            e);
1100:                }
1101:            }
1102:
1103:            /**
1104:             * {@inheritDoc}
1105:             */
1106:            public void dropEnrollmentFromCategory(String studentUid,
1107:                    String siteContext, String category) {
1108:                // Disallow if we're in an externally managed site
1109:                ensureInternallyManaged(getCourse(siteContext).getUuid());
1110:
1111:                if (log.isDebugEnabled())
1112:                    log.debug("Dropping " + studentUid
1113:                            + " from all sections in category " + category
1114:                            + " in site " + siteContext);
1115:                // Get the sections in this category
1116:                Site site;
1117:                try {
1118:                    site = siteService().getSite(siteContext);
1119:                } catch (IdUnusedException ide) {
1120:                    log.error("Unable to find site " + siteContext);
1121:                    return;
1122:                }
1123:                Collection groups = site.getGroups();
1124:                for (Iterator iter = groups.iterator(); iter.hasNext();) {
1125:                    // Drop the user from this section if they are enrolled
1126:                    Group group = (Group) iter.next();
1127:                    CourseSectionImpl section = new CourseSectionImpl(group);
1128:                    // Don't drop someone from a non-section groups
1129:                    if (section.getCategory() == null) {
1130:                        continue;
1131:                    }
1132:                    if (section.getCategory().equals(category)) {
1133:                        group.removeMember(studentUid);
1134:                    }
1135:                }
1136:                try {
1137:                    siteService().saveGroupMembership(site);
1138:                    postEvent("section.student.drop.category", site
1139:                            .getReference());
1140:                } catch (IdUnusedException e) {
1141:                    log.error("unable to find site: ", e);
1142:                    return;
1143:                } catch (PermissionException e) {
1144:                    log.error("access denied while attempting to save site: ",
1145:                            e);
1146:                    return;
1147:                }
1148:            }
1149:
1150:            /**
1151:             * {@inheritDoc}
1152:             */
1153:            public int getTotalEnrollments(String learningContextUuid) {
1154:                AuthzGroup authzGroup;
1155:                try {
1156:                    authzGroup = authzGroupService
1157:                            .getAuthzGroup(learningContextUuid);
1158:                } catch (GroupNotDefinedException e) {
1159:                    log.error("learning context " + learningContextUuid
1160:                            + " is neither a site nor a section");
1161:                    return 0;
1162:                }
1163:                String studentRole;
1164:                try {
1165:                    studentRole = getSectionStudentRole(authzGroup);
1166:                } catch (RoleConfigurationException rce) {
1167:                    log
1168:                            .warn("Can't get total enrollments, since there is no single student-flagged role in "
1169:                                    + learningContextUuid);
1170:                    return 0;
1171:                }
1172:                Set users = authzGroup.getUsersHasRole(studentRole);
1173:                return users.size();
1174:            }
1175:
1176:            /**
1177:             * {@inheritDoc}
1178:             */
1179:            public CourseSection addSection(String courseUuid, String title,
1180:                    String category, Integer maxEnrollments, String location,
1181:                    Time startTime, Time endTime, boolean monday,
1182:                    boolean tuesday, boolean wednesday, boolean thursday,
1183:                    boolean friday, boolean saturday, boolean sunday) {
1184:
1185:                // Get the site
1186:                Reference ref = entityManager.newReference(courseUuid);
1187:                Site site;
1188:                try {
1189:                    site = siteService().getSite(ref.getId());
1190:                } catch (IdUnusedException e) {
1191:                    log.error("Unable to find site " + courseUuid);
1192:                    return null;
1193:                }
1194:
1195:                CourseSection section = new CourseSectionImpl(getCourse(site
1196:                        .getId()), title, null, category, maxEnrollments,
1197:                        location, startTime, endTime, monday, tuesday,
1198:                        wednesday, thursday, friday, saturday, sunday);
1199:
1200:                List<CourseSection> sections = new ArrayList<CourseSection>();
1201:                sections.add(section);
1202:
1203:                addSections(courseUuid, sections);
1204:
1205:                return section;
1206:            }
1207:
1208:            /**
1209:             * Throws a SecurityException if an attempt is made to modify a section or its
1210:             * student memberships when the site is configured for external management.
1211:             */
1212:            private void ensureInternallyManaged(String courseUuid) {
1213:                if (isExternallyManaged(courseUuid)) {
1214:                    throw new SecurityException(
1215:                            "Can not make changes to sections or student memberships in site "
1216:                                    + courseUuid
1217:                                    + ".  It is externally managed.");
1218:                }
1219:            }
1220:
1221:            private List<Meeting> filterMeetings(List<Meeting> meetings) {
1222:                // Remove any empty meetings
1223:                List<Meeting> filteredMeetings = new ArrayList<Meeting>();
1224:                for (Iterator<Meeting> iter = meetings.iterator(); iter
1225:                        .hasNext();) {
1226:                    Meeting meeting = iter.next();
1227:                    if (!meeting.isEmpty()) {
1228:                        filteredMeetings.add(meeting);
1229:                    }
1230:                }
1231:                return filteredMeetings;
1232:            }
1233:
1234:            private CourseSection addSectionToSite(Site site, String title,
1235:                    String category, Integer maxEnrollments,
1236:                    List<Meeting> meetings) {
1237:                Group group = site.addGroup();
1238:
1239:                // Construct a CourseSection for this group
1240:                CourseSectionImpl courseSection = new CourseSectionImpl(group);
1241:
1242:                // Set the fields of the course section
1243:                courseSection.setTitle(title);
1244:                courseSection.setCategory(category);
1245:                courseSection.setMaxEnrollments(maxEnrollments);
1246:                courseSection.setMeetings(filterMeetings(meetings));
1247:
1248:                // Decorate the framework group
1249:                courseSection.decorateGroup(group);
1250:
1251:                return courseSection;
1252:            }
1253:
1254:            public Collection<CourseSection> addSections(String courseUuid,
1255:                    Collection<CourseSection> sections) {
1256:                // Disallow if we're in an externally managed site
1257:                ensureInternallyManaged(courseUuid);
1258:
1259:                // Get the site
1260:                Reference ref = entityManager.newReference(courseUuid);
1261:                Site site;
1262:                try {
1263:                    site = siteService().getSite(ref.getId());
1264:                } catch (IdUnusedException e) {
1265:                    log.error("Unable to find site " + courseUuid);
1266:                    return null;
1267:                }
1268:
1269:                List<CourseSection> addedSections = new ArrayList<CourseSection>();
1270:
1271:                // Add the decorated groups to the site
1272:                for (Iterator<CourseSection> iter = sections.iterator(); iter
1273:                        .hasNext();) {
1274:                    CourseSection section = iter.next();
1275:                    addedSections
1276:                            .add(addSectionToSite(site, section.getTitle(),
1277:                                    section.getCategory(), section
1278:                                            .getMaxEnrollments(), section
1279:                                            .getMeetings()));
1280:                }
1281:
1282:                // Save the site, along with the new section
1283:                try {
1284:                    siteService().save(site);
1285:                    for (Iterator<CourseSection> iter = sections.iterator(); iter
1286:                            .hasNext();) {
1287:                        postEvent("section.add", iter.next().getUuid());
1288:                    }
1289:                    return addedSections;
1290:                } catch (IdUnusedException ide) {
1291:                    log.error("Error saving site... could not find site "
1292:                            + site.getId(), ide);
1293:                } catch (PermissionException pe) {
1294:                    log.error(
1295:                            "Error saving site... permission denied for site "
1296:                                    + site.getId(), pe);
1297:                }
1298:                return null;
1299:            }
1300:
1301:            /**
1302:             * {@inheritDoc}
1303:             */
1304:            public void updateSection(String sectionUuid, String title,
1305:                    Integer maxEnrollments, String location, Time startTime,
1306:                    Time endTime, boolean monday, boolean tuesday,
1307:                    boolean wednesday, boolean thursday, boolean friday,
1308:                    boolean saturday, boolean sunday) {
1309:                // Create a list of meetings with a single meeting
1310:                List<Meeting> meetings = new ArrayList<Meeting>();
1311:                MeetingImpl meeting = new MeetingImpl(location, startTime,
1312:                        endTime, monday, tuesday, wednesday, thursday, friday,
1313:                        saturday, sunday);
1314:                meetings.add(meeting);
1315:
1316:                // Update the section with a single meeting
1317:                updateSection(sectionUuid, title, maxEnrollments, meetings);
1318:            }
1319:
1320:            public void updateSection(String sectionUuid, String title,
1321:                    Integer maxEnrollments, List<Meeting> meetings) {
1322:                // Disallow if we're in an externally managed site
1323:                ensureInternallyManaged(getSection(sectionUuid).getCourse()
1324:                        .getUuid());
1325:
1326:                CourseSectionImpl section = (CourseSectionImpl) getSection(sectionUuid);
1327:
1328:                if (section == null) {
1329:                    throw new RuntimeException("Unable to find section "
1330:                            + sectionUuid);
1331:                }
1332:
1333:                // Set the decorator's fields
1334:                section.setTitle(title);
1335:                section.setMaxEnrollments(maxEnrollments);
1336:                section.setMeetings(filterMeetings(meetings));
1337:
1338:                // Decorate the framework section
1339:                Group group = siteService().findGroup(sectionUuid);
1340:                section.decorateGroup(group);
1341:
1342:                // Save the site with its new section
1343:                try {
1344:                    siteService().save(group.getContainingSite());
1345:                    postEvent("section.update", sectionUuid);
1346:                } catch (IdUnusedException ide) {
1347:                    log.error(
1348:                            "Error saving site... could not find site for section "
1349:                                    + group, ide);
1350:                } catch (PermissionException pe) {
1351:                    log.error(
1352:                            "Error saving site... permission denied for section "
1353:                                    + group, pe);
1354:                }
1355:            }
1356:
1357:            /**
1358:             * {@inheritDoc}
1359:             */
1360:            public void disbandSection(String sectionUuid) {
1361:                Set<String> set = new HashSet<String>();
1362:                set.add(sectionUuid);
1363:                disbandSections(set);
1364:            }
1365:
1366:            /**
1367:             * {@inheritDoc}
1368:             */
1369:            public void disbandSections(Set<String> sectionUuids) {
1370:                if (sectionUuids == null || sectionUuids.isEmpty()) {
1371:                    return;
1372:                }
1373:
1374:                // Determine the course (site) we're in
1375:                String firstSectionUuid = sectionUuids.iterator().next();
1376:                CourseSection firstSection = getSection(firstSectionUuid);
1377:                if (firstSection == null) {
1378:                    if (log.isDebugEnabled())
1379:                        log.debug("Unable to remove section "
1380:                                + firstSectionUuid);
1381:                    return;
1382:                }
1383:                Course course = firstSection.getCourse();
1384:
1385:                // Disallow if we're in an externally managed site
1386:                ensureInternallyManaged(course.getUuid());
1387:
1388:                Site site = null;
1389:                for (Iterator<String> iter = sectionUuids.iterator(); iter
1390:                        .hasNext();) {
1391:                    String sectionUuid = iter.next();
1392:                    if (log.isDebugEnabled())
1393:                        log.debug("Disbanding section " + sectionUuid);
1394:                    Group group = siteService().findGroup(sectionUuid);
1395:
1396:                    // TODO Add token in UI to intercept double clicks in action buttons
1397:                    // SAK-3553 (Clicking remove button twice during section remove operation results in blank iframe.)
1398:                    if (group == null) {
1399:                        log.warn("Unable to find group with uuid "
1400:                                + sectionUuid);
1401:                        return;
1402:                    }
1403:                    if (site == null) {
1404:                        site = group.getContainingSite();
1405:                    }
1406:                    site.removeGroup(group);
1407:                }
1408:
1409:                try {
1410:                    siteService().save(site);
1411:                    for (Iterator<String> iter = sectionUuids.iterator(); iter
1412:                            .hasNext();) {
1413:                        String sectionUuid = iter.next();
1414:                        postEvent("section.disband", sectionUuid);
1415:                    }
1416:                } catch (IdUnusedException e) {
1417:                    log.error(
1418:                            "Cound not disband section (can't find section): ",
1419:                            e);
1420:                } catch (PermissionException e) {
1421:                    log.error("Cound not disband section (access denied): ", e);
1422:                }
1423:            }
1424:
1425:            public boolean isExternallyManaged(String courseUuid) {
1426:                Reference ref = entityManager.newReference(courseUuid);
1427:                String siteId = ref.getId();
1428:                Site site;
1429:                try {
1430:                    site = siteService().getSite(siteId);
1431:                } catch (IdUnusedException e) {
1432:                    throw new RuntimeException("Can not find site "
1433:                            + courseUuid, e);
1434:                }
1435:                ResourceProperties props = site.getProperties();
1436:                return Boolean.toString(true).equals(
1437:                        props.getProperty(CourseImpl.EXTERNALLY_MAINTAINED));
1438:            }
1439:
1440:            public void setExternallyManaged(String courseUuid,
1441:                    boolean externallyManaged) {
1442:                // Disallow if the service is configured to be mandatory
1443:                ExternalIntegrationConfig appConfig = getConfiguration(null);
1444:                if (appConfig == ExternalIntegrationConfig.AUTOMATIC_MANDATORY
1445:                        || appConfig == ExternalIntegrationConfig.MANUAL_MANDATORY) {
1446:                    throw new SecurityException(
1447:                            "Can not change the external management of a site, since this service is configured to be "
1448:                                    + appConfig);
1449:                }
1450:
1451:                Reference ref = entityManager.newReference(courseUuid);
1452:                String siteId = ref.getId();
1453:                Site site;
1454:                try {
1455:                    site = siteService().getSite(siteId);
1456:                } catch (IdUnusedException e) {
1457:                    throw new RuntimeException("Can not find site "
1458:                            + courseUuid, e);
1459:                }
1460:                ResourceProperties props = site.getProperties();
1461:
1462:                // Update the site
1463:                props.addProperty(CourseImpl.EXTERNALLY_MAINTAINED, Boolean
1464:                        .toString(externallyManaged));
1465:                if (externallyManaged) {
1466:                    // Also set the self join/switch to false
1467:                    props.addProperty(CourseImpl.STUDENT_REGISTRATION_ALLOWED,
1468:                            Boolean.toString(false));
1469:                    props.addProperty(CourseImpl.STUDENT_SWITCHING_ALLOWED,
1470:                            Boolean.toString(false));
1471:                }
1472:
1473:                try {
1474:                    siteService().save(site);
1475:                    if (log.isDebugEnabled())
1476:                        log.debug("Saved site " + site.getTitle());
1477:                    postEvent("section.external=" + externallyManaged, site
1478:                            .getReference());
1479:                } catch (IdUnusedException ide) {
1480:                    log.error("Error saving site... could not find site "
1481:                            + site, ide);
1482:                } catch (PermissionException pe) {
1483:                    log.error("Error saving site... permission denied for "
1484:                            + site, pe);
1485:                }
1486:            }
1487:
1488:            /**
1489:             * {@inheritDoc}
1490:             */
1491:            public boolean isSelfRegistrationAllowed(String courseUuid) {
1492:                Reference ref = entityManager.newReference(courseUuid);
1493:                String siteId = ref.getId();
1494:                Site site;
1495:                try {
1496:                    site = siteService().getSite(siteId);
1497:                } catch (IdUnusedException e) {
1498:                    throw new RuntimeException("Can not find site "
1499:                            + courseUuid, e);
1500:                }
1501:                ResourceProperties props = site.getProperties();
1502:                return Boolean
1503:                        .toString(true)
1504:                        .equals(
1505:                                props
1506:                                        .getProperty(CourseImpl.STUDENT_REGISTRATION_ALLOWED));
1507:            }
1508:
1509:            public void setJoinOptions(String courseUuid, boolean joinAllowed,
1510:                    boolean switchAllowed) {
1511:                // Disallow if we're in an externally managed site
1512:                ensureInternallyManaged(courseUuid);
1513:
1514:                Reference ref = entityManager.newReference(courseUuid);
1515:                String siteId = ref.getId();
1516:                Site site;
1517:                try {
1518:                    site = siteService().getSite(siteId);
1519:                } catch (IdUnusedException e) {
1520:                    throw new RuntimeException("Can not find site "
1521:                            + courseUuid, e);
1522:                }
1523:                ResourceProperties props = site.getProperties();
1524:
1525:                // Get the existing join and switch settings, so we know what's changed
1526:                boolean oldJoin = new Boolean(props
1527:                        .getProperty(CourseImpl.STUDENT_REGISTRATION_ALLOWED))
1528:                        .booleanValue();
1529:                boolean oldSwitch = new Boolean(props
1530:                        .getProperty(CourseImpl.STUDENT_SWITCHING_ALLOWED))
1531:                        .booleanValue();
1532:
1533:                props.addProperty(CourseImpl.STUDENT_REGISTRATION_ALLOWED,
1534:                        Boolean.toString(joinAllowed));
1535:                props.addProperty(CourseImpl.STUDENT_SWITCHING_ALLOWED, Boolean
1536:                        .toString(switchAllowed));
1537:                try {
1538:                    siteService().save(site);
1539:                    if (joinAllowed != oldJoin) {
1540:                        postEvent("section.student.reg=" + joinAllowed, site
1541:                                .getReference());
1542:                    }
1543:                    if (switchAllowed != oldSwitch) {
1544:                        postEvent("section.student.switch=" + switchAllowed,
1545:                                site.getReference());
1546:                    }
1547:
1548:                } catch (IdUnusedException ide) {
1549:                    log.error("Error saving site... could not find site "
1550:                            + site, ide);
1551:                } catch (PermissionException pe) {
1552:                    log.error("Error saving site... permission denied for "
1553:                            + site, pe);
1554:                }
1555:            }
1556:
1557:            /**
1558:             * {@inheritDoc}
1559:             */
1560:            public boolean isSelfSwitchingAllowed(String courseUuid) {
1561:                Reference ref = entityManager.newReference(courseUuid);
1562:                String siteId = ref.getId();
1563:                Site site;
1564:                try {
1565:                    site = siteService().getSite(siteId);
1566:                } catch (IdUnusedException e) {
1567:                    throw new RuntimeException("Can not find site "
1568:                            + courseUuid, e);
1569:                }
1570:                ResourceProperties props = site.getProperties();
1571:                return Boolean
1572:                        .toString(true)
1573:                        .equals(
1574:                                props
1575:                                        .getProperty(CourseImpl.STUDENT_SWITCHING_ALLOWED));
1576:            }
1577:
1578:            /**
1579:             * {@inheritDoc}
1580:             */
1581:            public List<EnrollmentRecord> getUnsectionedEnrollments(
1582:                    String courseUuid, String category) {
1583:                Reference siteRef = entityManager.newReference(courseUuid);
1584:                String siteId = siteRef.getId();
1585:
1586:                // Get all of the sections and userUids of enrolled students
1587:                List siteEnrollments = getSiteEnrollments(siteId);
1588:
1589:                // Get all userUids of students enrolled in sections of this category
1590:                List<String> sectionedStudentUids = new ArrayList<String>();
1591:                List categorySections = getSectionsInCategory(siteId, category);
1592:                for (Iterator sectionIter = categorySections.iterator(); sectionIter
1593:                        .hasNext();) {
1594:                    CourseSection section = (CourseSection) sectionIter.next();
1595:                    List sectionUsers = getSectionEnrollments(section.getUuid());
1596:
1597:                    if (log.isDebugEnabled())
1598:                        log.debug("There are " + sectionUsers.size()
1599:                                + " students in section " + section.getUuid());
1600:
1601:                    for (Iterator userIter = sectionUsers.iterator(); userIter
1602:                            .hasNext();) {
1603:                        ParticipationRecord record = (ParticipationRecord) userIter
1604:                                .next();
1605:                        sectionedStudentUids.add(record.getUser().getUserUid());
1606:                    }
1607:                }
1608:
1609:                // Now generate the list of unsectioned enrollments by subtracting the two collections
1610:                // Since the APIs return different kinds of objects, we need to iterate
1611:                List<EnrollmentRecord> unsectionedEnrollments = new ArrayList<EnrollmentRecord>();
1612:                for (Iterator iter = siteEnrollments.iterator(); iter.hasNext();) {
1613:                    EnrollmentRecord record = (EnrollmentRecord) iter.next();
1614:                    if (!sectionedStudentUids.contains(record.getUser()
1615:                            .getUserUid())) {
1616:                        unsectionedEnrollments.add(record);
1617:                    }
1618:                }
1619:                return unsectionedEnrollments;
1620:            }
1621:
1622:            /**
1623:             * {@inheritDoc}
1624:             */
1625:            public Set<EnrollmentRecord> getSectionEnrollments(String userUid,
1626:                    String courseUuid) {
1627:                // Get the user
1628:                org.sakaiproject.user.api.User sakaiUser;
1629:                try {
1630:                    sakaiUser = userDirectoryService.getUser(userUid);
1631:                } catch (UserNotDefinedException ide) {
1632:                    log.error("Can not find user with id " + userUid);
1633:                    return new HashSet<EnrollmentRecord>();
1634:                }
1635:                User sectionUser = SakaiUtil.convertUser(sakaiUser);
1636:
1637:                // Get all of the sections
1638:                Reference siteRef = entityManager.newReference(courseUuid);
1639:                String siteId = siteRef.getId();
1640:                List sections = getSections(siteId);
1641:
1642:                // Generate a set of sections for which this user is enrolled
1643:                Set<EnrollmentRecord> sectionEnrollments = new HashSet<EnrollmentRecord>();
1644:                for (Iterator sectionIter = sections.iterator(); sectionIter
1645:                        .hasNext();) {
1646:                    CourseSectionImpl section = (CourseSectionImpl) sectionIter
1647:                            .next();
1648:                    Group group = section.getGroup();
1649:                    Member member = group.getMember(userUid);
1650:                    if (member == null) {
1651:                        continue;
1652:                    }
1653:                    if (member.getRole().isAllowed(
1654:                            SectionAwareness.STUDENT_MARKER)) {
1655:                        sectionEnrollments.add(new EnrollmentRecordImpl(
1656:                                section, null, sectionUser));
1657:                    }
1658:                }
1659:                return sectionEnrollments;
1660:            }
1661:
1662:            /**
1663:             * {@inheritDoc}
1664:             */
1665:            public User getSiteEnrollment(String siteContext, String studentUid) {
1666:                return SakaiUtil.getUserFromSakai(studentUid);
1667:            }
1668:
1669:            public ExternalIntegrationConfig getConfiguration(Object obj) {
1670:                if (config == null) {
1671:                    log
1672:                            .warn("No integration configuration property has been set.  Using "
1673:                                    + ExternalIntegrationConfig.MANUAL_DEFAULT);
1674:                    config = ExternalIntegrationConfig.MANUAL_DEFAULT;
1675:                }
1676:                return config;
1677:            }
1678:
1679:            // Dependency injection
1680:
1681:            public void setAuthzGroupService(AuthzGroupService authzGroupService) {
1682:                this .authzGroupService = authzGroupService;
1683:            }
1684:
1685:            public void setSessionManager(SessionManager sessionManager) {
1686:                this .sessionManager = sessionManager;
1687:            }
1688:
1689:            public void setEntityManager(EntityManager entityManager) {
1690:                this .entityManager = entityManager;
1691:            }
1692:
1693:            public void setSecurityService(SecurityService securityService) {
1694:                this .securityService = securityService;
1695:            }
1696:
1697:            public void setUserDirectoryService(
1698:                    UserDirectoryService userDirectoryService) {
1699:                this .userDirectoryService = userDirectoryService;
1700:            }
1701:
1702:            public void setEventTrackingService(
1703:                    EventTrackingService eventTrackingService) {
1704:                this .eventTrackingService = eventTrackingService;
1705:            }
1706:
1707:            public void setConfig(String config) {
1708:                if (ExternalIntegrationConfig.AUTOMATIC_MANDATORY.toString()
1709:                        .equals(config)) {
1710:                    this .config = ExternalIntegrationConfig.AUTOMATIC_MANDATORY;
1711:                } else if (ExternalIntegrationConfig.AUTOMATIC_DEFAULT
1712:                        .toString().equals(config)) {
1713:                    this .config = ExternalIntegrationConfig.AUTOMATIC_DEFAULT;
1714:                } else if (ExternalIntegrationConfig.MANUAL_DEFAULT.toString()
1715:                        .equals(config)) {
1716:                    this .config = ExternalIntegrationConfig.MANUAL_DEFAULT;
1717:                } else if (ExternalIntegrationConfig.MANUAL_MANDATORY
1718:                        .toString().equals(config)) {
1719:                    this .config = ExternalIntegrationConfig.MANUAL_MANDATORY;
1720:                } else {
1721:                    log.warn("Unknown section integration config specified: "
1722:                            + config + ".  Using "
1723:                            + ExternalIntegrationConfig.MANUAL_DEFAULT);
1724:                }
1725:            }
1726:
1727:            public void setCourseManagementService(
1728:                    CourseManagementService courseManagementService) {
1729:                this .courseManagementService = courseManagementService;
1730:            }
1731:
1732:            public void setGroupProvider(GroupProvider groupProvider) {
1733:                this.groupProvider = groupProvider;
1734:            }
1735:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.