001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.odf.courselist;
017
018import java.util.Arrays;
019import java.util.List;
020import java.util.Optional;
021import java.util.Set;
022import java.util.stream.Collectors;
023
024import javax.jcr.Node;
025
026import org.ametys.cms.data.ContentDataHelper;
027import org.ametys.cms.data.ContentValue;
028import org.ametys.odf.course.Course;
029import org.ametys.odf.course.CourseContainer;
030import org.ametys.odf.program.AbstractProgramPart;
031import org.ametys.odf.program.Program;
032
033/**
034 * Class representing a list of {@link Course}
035 */
036public class CourseList extends AbstractProgramPart<CourseListFactory> implements CourseContainer
037{
038    /** Constants for choice type attribute */
039    public static final String CHOICE_TYPE = "choiceType";
040    /** Constants for minimum number of courses. This attribute is valued only if type is {@link ChoiceType}.CHOICE */
041    public static final String MIN_COURSES = "min";
042    /** Constants for maximum number of courses. This attribute is valued only if type is {@link ChoiceType}.CHOICE */
043    public static final String MAX_COURSES = "max";
044    /** Constants for child courses attribute */
045    public static final String CHILD_COURSES = "courses";
046    /** Name of the attribute holding the direct parent courses */
047    public static final String PARENT_COURSES = "parentCourses";
048    
049    /**
050     * The type of the {@link CourseList}
051     */
052    public enum ChoiceType
053    {
054        /** mandatory type */
055        MANDATORY,
056        /** optional type */
057        OPTIONAL,
058        /** choice type */
059        CHOICE
060    }
061
062    /**
063     * Constructor
064     * @param node The JCR node
065     * @param parentPath The parent path
066     * @param factory the factory
067     */
068    public CourseList(Node node, String parentPath, CourseListFactory factory)
069    {
070        super(node, parentPath, factory);
071    }
072
073    @Override
074    public List<Course> getCourses()
075    {
076        return Arrays.stream(getValue(CHILD_COURSES, false, new ContentValue[0]))
077                .map(ContentValue::getContentIfExists)
078                .filter(Optional::isPresent)
079                .map(Optional::get)
080                .map(Course.class::cast)
081                .collect(Collectors.toList());
082    }
083
084    @Override
085    public boolean containsCourse(String courseId)
086    {
087        List<String> courseIds = ContentDataHelper.getContentIdsListFromMultipleContentData(this, CHILD_COURSES);
088        return courseIds.contains(courseId);
089    }
090    
091    @Override
092    public boolean hasCourses()
093    {
094        return !ContentDataHelper.isMultipleContentDataEmpty(this, CHILD_COURSES);
095    }
096    
097    // --------------------------------------------------------------------------------------//
098    // GETTERS AND SETTERS
099    // --------------------------------------------------------------------------------------//
100    /**
101     * If this set of teaching unit element is a type of choice this method
102     * return the minimum number of teaching unit elements that the student must
103     * choose else -1.
104     * 
105     * @return the minimum number of teaching unit element that the student must choose. 0 if not set
106     */
107    public long getMinNumberOfCourses()
108    {
109        return getValue(CourseList.MIN_COURSES, false, 0L);
110    }
111
112    /**
113     * If this set of teaching unit element is a type of choice this method
114     * return the maximum number of teaching unit element that this set of
115     * teaching unit element must contains else -1.
116     * 
117     * @return the maximum number of teaching unit element that this set of
118     *         teaching unit element must contains.
119     */
120    public long getMaxNumberOfCourses()
121    {
122        return getValue(CourseList.MAX_COURSES, false, 0L);
123    }
124    
125    /**
126     * Indicates whether the teaching unit elements contained are mandatory,
127     * optional or a choice.
128     * 
129     * @return the type of the teaching unit elements contained.
130     */
131    public ChoiceType getType()
132    {
133        try
134        {
135            String choiceType = getValue(CHOICE_TYPE);
136            return Optional.ofNullable(choiceType).map(ChoiceType::valueOf).orElse(null);
137        }
138        catch (IllegalArgumentException e)
139        {
140            // No corresponding choice
141            return null;
142        }
143    }
144
145    /**
146     * Get the ids of parent courses
147     * @return the ids of parent courses
148     */
149    public List<Course> getParentCourses()
150    {
151        return Arrays.stream(getValue(PARENT_COURSES, false, new ContentValue[0]))
152                .map(ContentValue::getContentIfExists)
153                .filter(Optional::isPresent)
154                .map(Optional::get)
155                .map(Course.class::cast)
156                .collect(Collectors.toList());
157    }
158        
159    @Override
160    public Set<Program> getRootPrograms()
161    {
162        Set<Program> rootPrograms = super.getRootPrograms();
163        for (Course course : getParentCourses())
164        {
165            rootPrograms.addAll(course.getRootPrograms());
166        }
167        return rootPrograms;
168    }
169    
170    // --------------------------------------------------------------------------------------//
171    // CDM-fr
172    // --------------------------------------------------------------------------------------//
173    @Override
174    protected String getCDMType()
175    {
176        return "CL";
177    }
178}