001/*
002 *  Copyright 2018 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.coursepart;
017
018import java.util.Arrays;
019import java.util.HashSet;
020import java.util.List;
021import java.util.Optional;
022import java.util.Set;
023import java.util.stream.Collectors;
024
025import javax.jcr.Node;
026
027import org.apache.commons.lang3.StringUtils;
028
029import org.ametys.cms.data.ContentDataHelper;
030import org.ametys.cms.data.ContentValue;
031import org.ametys.cms.repository.ModifiableDefaultContent;
032import org.ametys.odf.course.Course;
033import org.ametys.odf.program.Program;
034import org.ametys.plugins.repository.AmetysRepositoryException;
035
036/**
037 * Class representing a {@link CoursePart}
038 */
039public class CoursePart extends ModifiableDefaultContent<CoursePartFactory>
040{
041    /** The attribute holding the catalog */
042    public static final String CATALOG = "catalog";
043    
044    /** The attribute holding the code */
045    public static final String CODE = "code";
046    
047    /** Constants for attribute 'nature' */
048    public static final String NATURE = "nature";
049
050    /** Constants for attribute 'nbHours' */
051    public static final String NB_HOURS = "nbHours";
052
053    /** Name of attribute for course holder */
054    public static final String COURSE_HOLDER = "courseHolder";
055
056    /** Name of attribute for parent courses */
057    public static final String PARENT_COURSES = "courses";
058    
059    /**
060     * Constructor.
061     * @param node the JCR Node.
062     * @param parentPath the parent path
063     * @param factory the corresponding factory.
064     */
065    public CoursePart(Node node, String parentPath, CoursePartFactory factory)
066    {
067        super(node, parentPath, factory);
068    }
069    
070    /**
071     * Get the catalog.
072     * @return the catalog
073     */
074    public String getCatalog()
075    {
076        return getValue(CATALOG);
077    }
078    
079    /**
080     * Set the catalog.
081     * @param catalog The catalog
082     * @throws AmetysRepositoryException if an error occurs
083     */
084    public void setCatalog(String catalog) throws AmetysRepositoryException
085    {
086        setValue(CATALOG, catalog);
087    }
088
089    /**
090     * Get the code.
091     * @return the code
092     */
093    public String getCode()
094    {
095        return getValue(CODE, false, StringUtils.EMPTY);
096    }
097
098    /**
099     * Set the code.
100     * @param code The code
101     * @throws AmetysRepositoryException if an error occurs
102     */
103    public void setCode(String code) throws AmetysRepositoryException
104    {
105        setValue(CODE, code);
106    }
107
108    /**
109     * Get the nature.
110     * @return the nature
111     */
112    public String getNature()
113    {
114        return ContentDataHelper.getContentIdFromContentData(this,  NATURE);
115    }
116
117    /**
118     * Get the number of hours
119     * @return the number of hours
120     */
121    public double getNumberOfHours()
122    {
123        return getValue(NB_HOURS, false, 0D);
124    }
125
126    /**
127     * Get the course holder
128     * @return the course holder
129     */
130    public Course getCourseHolder()
131    {
132        return Optional.ofNullable((ContentValue) getValue(COURSE_HOLDER))
133                                .flatMap(ContentValue::getContentIfExists)
134                                .map(Course.class::cast)
135                                .orElse(null);
136    }
137    
138    /**
139     * Get the parent courses.
140     * @return The {@link List} of parent {@link Course}s
141     */
142    public List<Course> getCourses()
143    {
144        return Arrays.stream(getValue(PARENT_COURSES, false, new ContentValue[0]))
145                .map(ContentValue::getContentIfExists)
146                .filter(Optional::isPresent)
147                .map(Optional::get)
148                .map(Course.class::cast)
149                .collect(Collectors.toList());
150    }
151    
152    /**
153     * Returns the programs holding this course part through the courses
154     * @return the root programs
155     */
156    public Set<Program> getRootPrograms()
157    {
158        Set<Program> programs = new HashSet<>();
159        for (Course course : getCourses())
160        {
161            programs.addAll(course.getRootPrograms());
162        }
163        return programs;
164    }
165}