/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.course.nodes.en; import static org.olat.restapi.security.RestSecurityHelper.isAuthor; import static org.olat.restapi.security.RestSecurityHelper.isAuthorEditor; import static org.olat.restapi.support.ObjectFactory.get; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import org.olat.core.CoreSpringFactory; import org.olat.core.util.StringHelper; import org.olat.course.ICourse; import org.olat.course.nodes.CourseNode; import org.olat.course.nodes.ENCourseNode; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.group.BusinessGroupShort; import org.olat.modules.ModuleConfiguration; import org.olat.restapi.repository.course.AbstractCourseNodeWebService; import org.olat.restapi.repository.course.CoursesWebService; import org.olat.restapi.support.vo.GroupVO; /** * * Description:<br> * This handles the enrollment building block. * * <P> * Initial Date: 10 mai 2010 <br> * @author srosse, stephane.rosse@frentix.com */ @Path("repo/courses/{courseId}/elements/enrollment") public class ENWebService extends AbstractCourseNodeWebService { /** * This attaches an enrollment element onto a given course, the element will be * inserted underneath the supplied parentNodeId * @response.representation.mediaType application/x-www-form-urlencoded * @response.representation.doc The course node metadatas * @response.representation.200.qname {http://www.example.com}courseNodeVO * @response.representation.200.mediaType application/xml, application/json * @response.representation.200.doc The course node metadatas * @response.representation.200.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_COURSENODEVO} * @response.representation.401.doc The roles of the authenticated user are not sufficient * @response.representation.404.doc The course or parentNode not found * @param courseId The course resourceable's id * @param parentNodeId The node's id which will be the parent of this structure * @param position The node's position relative to its sibling nodes (optional) * @param shortTitle The node short title * @param longTitle The node long title * @param objectives The node learning objectives * @param visibilityExpertRules The rules to view the node (optional) * @param accessExpertRules The rules to access the node (optional) * @param groups A list of learning groups (list of keys) * @param cancelEnabled cancel enrollment enabled or not * @param request The HTTP request * @return The persisted contact element (fully populated) */ @PUT @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response attachEnrolmment(@PathParam("courseId") Long courseId, @QueryParam("parentNodeId") String parentNodeId, @QueryParam("position") Integer position, @QueryParam("shortTitle") @DefaultValue("undefined") String shortTitle, @QueryParam("longTitle") @DefaultValue("undefined") String longTitle, @QueryParam("objectives") @DefaultValue("undefined") String objectives, @QueryParam("visibilityExpertRules") String visibilityExpertRules, @QueryParam("accessExpertRules") String accessExpertRules, @QueryParam("groups") String groups, @QueryParam("cancelEnabled") @DefaultValue("false") boolean cancelEnabled, @Context HttpServletRequest request) { EnrollmentConfigDelegate config = new EnrollmentConfigDelegate(groups, cancelEnabled); return attach(courseId, parentNodeId, "en", position, shortTitle, longTitle, objectives, visibilityExpertRules, accessExpertRules, config, request); } /** * This attaches an enrollment element onto a given course, the element will be * inserted underneath the supplied parentNodeId * @response.representation.mediaType application/x-www-form-urlencoded * @response.representation.doc The course node metadatas * @response.representation.200.qname {http://www.example.com}courseNodeVO * @response.representation.200.mediaType application/xml, application/json * @response.representation.200.doc The course node metadatas * @response.representation.200.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_COURSENODEVO} * @response.representation.401.doc The roles of the authenticated user are not sufficient * @response.representation.404.doc The course or parentNode not found * @param courseId The course resourceable's id * @param parentNodeId The node's id which will be the parent of this * structure * @param position The node's position relative to its sibling nodes (optional) * @param shortTitle The node short title * @param longTitle The node long title * @param objectives The node learning objectives * @param visibilityExpertRules The rules to view the node (optional) * @param accessExpertRules The rules to access the node (optional) * @param groups send the message to the specified groups * @param cancelEnabled cancel enrollment enabled or not * @param request The HTTP request * @return The persisted contact element (fully populated) */ @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response attachEnrollmenetPost(@PathParam("courseId") Long courseId, @FormParam("parentNodeId") String parentNodeId, @FormParam("position") Integer position, @FormParam("shortTitle") @DefaultValue("undefined") String shortTitle, @FormParam("longTitle") @DefaultValue("undefined") String longTitle, @FormParam("objectives") @DefaultValue("undefined") String objectives, @FormParam("visibilityExpertRules") String visibilityExpertRules, @FormParam("accessExpertRules") String accessExpertRules, @FormParam("groups") String groups, @FormParam("cancelEnabled") @DefaultValue("false") boolean cancelEnabled, @Context HttpServletRequest request) { EnrollmentConfigDelegate config = new EnrollmentConfigDelegate(groups, cancelEnabled); return attach(courseId, parentNodeId, "en", position, shortTitle, longTitle, objectives, visibilityExpertRules, accessExpertRules, config, request); } /** * Retrieves the groups where the enrollment happens * @response.representation.200.qname {http://www.example.com}groupVO * @response.representation.200.mediaType application/xml, application/json * @response.representation.200.doc The groups * @response.representation.200.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_GROUPVO} * @response.representation.401.doc The roles of the authenticated user are not sufficient * @response.representation.404.doc The course or course node not found * @param nodeId The node's id * @param httpRequest The HTTP request * @return An array of groups */ @GET @Path("{nodeId}/groups") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response getGroups(@PathParam("courseId") Long courseId, @PathParam("nodeId") String nodeId, @Context HttpServletRequest httpRequest) { if(!isAuthor(httpRequest)) { return Response.serverError().status(Status.UNAUTHORIZED).build(); } ICourse course = CoursesWebService.loadCourse(courseId); if(course == null) { return Response.serverError().status(Status.NOT_FOUND).build(); } else if (!isAuthorEditor(course, httpRequest)) { return Response.serverError().status(Status.UNAUTHORIZED).build(); } BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class); CourseNode node = getParentNode(course, nodeId); ModuleConfiguration config = node.getModuleConfiguration(); String groupNames = (String)config.get(ENCourseNode.CONFIG_GROUPNAME); @SuppressWarnings("unchecked") List<Long> groupKeys = (List<Long>)config.get(ENCourseNode.CONFIG_GROUP_IDS); if(groupKeys == null && StringHelper.containsNonWhitespace(groupNames)) { groupKeys = bgs.toGroupKeys(groupNames, course.getCourseEnvironment().getCourseGroupManager().getCourseEntry()); } if(groupKeys == null || groupKeys.isEmpty()) { return Response.ok(new GroupVO[0]).build(); } List<GroupVO> voes = new ArrayList<GroupVO>(); List<BusinessGroup> groups = bgs.loadBusinessGroups(groupKeys); for(BusinessGroup group:groups) { voes.add(get(group)); } GroupVO[] voArr = new GroupVO[voes.size()]; voes.toArray(voArr); return Response.ok(voArr).build(); } private class EnrollmentConfigDelegate implements CustomConfigDelegate { private final boolean cancelEnabled; private final List<String> groups; public EnrollmentConfigDelegate(String groups, boolean cancelEnabled) { this.groups = getGroupNames(groups); this.cancelEnabled = cancelEnabled; } @Override public boolean isValid() { return groups != null && !groups.isEmpty(); } @Override public void configure(ICourse course, CourseNode newNode, ModuleConfiguration moduleConfig) { moduleConfig.set(ENCourseNode.CONFIG_GROUPNAME, getGroupNamesToString()); moduleConfig.set(ENCourseNode.CONF_CANCEL_ENROLL_ENABLED, cancelEnabled); } //fxdiff private String getGroupNamesToString() { StringBuffer buffer = new StringBuffer(); for(String groupName:groups) { if(buffer.length() > 0) { buffer.append(','); } buffer.append(groupName); } return buffer.toString(); } private List<String> getGroupNames(String groupIds) { List<String> groupNames = new ArrayList<String>(); if(StringHelper.containsNonWhitespace(groupIds)) { String[] groupIdArr = groupIds.split(";"); BusinessGroupService bgm = CoreSpringFactory.getImpl(BusinessGroupService.class); List<Long> keys = new ArrayList<Long>(); for(String groupId:groupIdArr) { Long groupKey = new Long(groupId); keys.add(groupKey); } List<BusinessGroupShort> groupsShort = bgm.loadShortBusinessGroups(keys); for(BusinessGroupShort bg:groupsShort) { groupNames.add(bg.getName()); } } return groupNames; } } }