001/* 002 * Copyright 2019 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.ose.export.impl.odf; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Optional; 021import java.util.Set; 022import java.util.concurrent.atomic.AtomicInteger; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.commons.lang3.StringUtils; 027 028import org.ametys.odf.course.Course; 029import org.ametys.odf.coursepart.CoursePart; 030import org.ametys.odf.enumeration.OdfReferenceTableHelper; 031import org.ametys.odf.ose.db.ParameterizableQuery; 032import org.ametys.odf.ose.export.impl.odf.db.CheminPedagogiqueHelper; 033import org.ametys.odf.ose.export.impl.odf.db.EffectifsHelper; 034import org.ametys.odf.ose.export.impl.odf.db.ElementPedagogiqueHelper; 035import org.ametys.odf.ose.export.impl.odf.db.TypeInterventionEPHelper; 036import org.ametys.odf.ose.export.impl.odf.db.VolumeHoraireEnsHelper; 037import org.ametys.odf.program.Container; 038import org.ametys.plugins.odfpilotage.cost.entity.CostComputationData; 039import org.ametys.plugins.odfpilotage.cost.entity.Effectives; 040import org.ametys.plugins.odfpilotage.cost.entity.Groups; 041import org.ametys.plugins.odfpilotage.cost.entity.ProgramItemData; 042import org.ametys.runtime.model.ModelHelper; 043 044/** 045 * Exporter of courses. 046 */ 047public class CourseExporter extends AbstractProgramElementExporter<Course> 048{ 049 /** Avalon Role */ 050 public static final String ROLE = CourseExporter.class.getName(); 051 052 /** The ODF enumeration helper */ 053 protected OdfReferenceTableHelper _refTableHelper; 054 055 @Override 056 public void service(ServiceManager manager) throws ServiceException 057 { 058 super.service(manager); 059 _refTableHelper = (OdfReferenceTableHelper) manager.lookup(OdfReferenceTableHelper.ROLE); 060 } 061 062 @Override 063 protected List<ParameterizableQuery> _getQueries(Course programElement, ProgramElementData data, Long oseCatalog, CostComputationData costData) 064 { 065 String courseCode = programElement.getCode(); 066 String courseTitle = _getCourseTitle(programElement); 067 068 /* 069 * ELEMENT_PEDAGOGIQUE 070 * NOEUD 071 * Si ELP de dernier niveau (course.getCourseLists().isEmpty()) 072 * Si heures d'enseignement partagées (portées ou non) 073 * Pour chaque heures d'enseignement uniquement portées 074 * ELEMENT_PEDAGOGIQUE 075 * NOEUD 076 * CHEMIN_PEDAGOGIQUE (1 par STEP) 077 * EFFECTIFS 078 * VOLUME_HORAIRE (courseLink = coursePart) 079 * TYPE_INTERVENTION_EP (courseLink = coursePart) 080 * Sinon 081 * CHEMIN_PEDAGOGIQUE (1 par STEP) 082 * EFFECTIFS (Premier CoursePart) 083 * Pour chaque heures d'enseignement uniquement portées 084 * VOLUME_HORAIRE (courseLink = course) 085 * TYPE_INTERVENTION_EP (courseLink = course) 086 */ 087 List<ParameterizableQuery> queries = new ArrayList<>(); 088 queries.addAll(ElementPedagogiqueHelper.insertInto(courseCode, courseTitle, oseCatalog, data.getOrgUnit(), data.getStepHolder(), data.getPeriodType())); 089 090 if (programElement.getCourseLists().isEmpty()) 091 { 092 // Check if one of the course part is shared 093 List<CoursePart> courseParts = programElement.getCourseParts(); 094 boolean hasSharedCoursePart = _hasSharedCoursePart(courseParts); 095 CoursePart[] holdedCourseParts = courseParts.stream() 096 .filter(coursePart -> _isCourseHolder(coursePart, programElement)) 097 .toArray(CoursePart[]::new); 098 099 if (hasSharedCoursePart) 100 { 101 for (CoursePart coursePart : holdedCourseParts) 102 { 103 String coursePartCode = coursePart.getCode(); 104 String coursePartNature = _refTableHelper.getItemCode(coursePart.getNature()); 105 String coursePartLabel = courseTitle + " - " + coursePartNature; 106 107 queries.addAll(ElementPedagogiqueHelper.insertInto(coursePartCode, coursePartLabel, oseCatalog, data.getOrgUnit(), data.getStepHolder(), data.getPeriodType())); 108 109 queries.addAll(_getCheminPedagogiqueQueries(data.getSteps(), coursePartCode, oseCatalog)); 110 111 _getEffectifsQuery(coursePart, coursePartCode, oseCatalog, costData) 112 .ifPresent(queries::add); 113 114 queries.addAll(_getCoursePartQueries(coursePart, coursePartNature, oseCatalog, coursePart.getCode(), costData)); 115 } 116 } 117 else 118 { 119 queries.addAll(_getCheminPedagogiqueQueries(data.getSteps(), courseCode, oseCatalog)); 120 if (!courseParts.isEmpty()) 121 { 122 _getEffectifsQuery(courseParts.get(0), courseCode, oseCatalog, costData) 123 .ifPresent(queries::add); 124 125 for (CoursePart coursePart : holdedCourseParts) 126 { 127 String coursePartNature = _refTableHelper.getItemCode(coursePart.getNature()); 128 queries.addAll(_getCoursePartQueries(coursePart, coursePartNature, oseCatalog, courseCode, costData)); 129 } 130 } 131 } 132 } 133 134 return queries; 135 } 136 137 private Optional<ParameterizableQuery> _getEffectifsQuery(CoursePart coursePart, String code, Long oseCatalog, CostComputationData costData) 138 { 139 return Optional.ofNullable(coursePart) 140 .map(c -> _getNumberOfStudents(c, costData)) 141 .map(nbStudents -> EffectifsHelper.insertInto(coursePart.getCode(), nbStudents, oseCatalog, code)); 142 } 143 144 private List<ParameterizableQuery> _getCheminPedagogiqueQueries(Set<Container> steps, String code, Long oseCatalog) 145 { 146 List<ParameterizableQuery> queries = new ArrayList<>(); 147 148 AtomicInteger order = new AtomicInteger(); 149 for (Container step : steps) 150 { 151 queries.add(CheminPedagogiqueHelper.insertInto(step.getCode(), code, oseCatalog, order)); 152 } 153 154 return queries; 155 } 156 157 private List<ParameterizableQuery> _getCoursePartQueries(CoursePart coursePart, String coursePartNature, Long oseCatalog, String courseLink, CostComputationData costData) 158 { 159 String coursePartCode = coursePart.getCode(); 160 Double numberOfGroups = _getGroups(coursePart, costData); 161 return List.of( 162 VolumeHoraireEnsHelper.insertInto(coursePart, coursePartCode, coursePartNature, oseCatalog, courseLink, numberOfGroups), 163 TypeInterventionEPHelper.insertInto(coursePartCode, coursePartNature, courseLink, oseCatalog) 164 ); 165 } 166 167 private boolean _hasSharedCoursePart(List<CoursePart> courseParts) 168 { 169 return courseParts.stream() 170 .map(CoursePart::getCourses) 171 .map(List::size) 172 .anyMatch(size -> size > 2); 173 } 174 175 private boolean _isCourseHolder(CoursePart coursePart, Course currentCourse) 176 { 177 final String currentCourseId = currentCourse.getId(); 178 return Optional.of(coursePart) 179 .map(CoursePart::getCourseHolder) 180 .map(Course::getId) 181 .map(id -> id.equals(currentCourseId)) 182 .orElse(false); 183 } 184 185 private Long _getNumberOfStudents(CoursePart coursePart, CostComputationData costData) 186 { 187 return Optional.of(coursePart) 188 .map(CoursePart::getId) 189 .map(costData::get) 190 .map(ProgramItemData::getEffectives) 191 .map(Effectives::getComputedEffective) 192 .map(Double::longValue) 193 .orElse(0L); 194 } 195 196 private Double _getGroups(CoursePart coursePart, CostComputationData costData) 197 { 198 Optional<Groups> groups = Optional.of(coursePart) 199 .map(CoursePart::getId) 200 .map(costData::get) 201 .map(ProgramItemData::getGroups); 202 203 if (groups.isPresent()) 204 { 205 return groups.map(Groups::getGroupsToOpen) 206 .or(() -> groups.map(Groups::getComputedGroups)) 207 .map(Long::doubleValue) 208 .orElse(null); 209 } 210 211 return null; 212 } 213 214 private String _getCourseTitle(Course course) 215 { 216 String title = course.getTitle(); 217 if (ModelHelper.hasModelItem("elpCode", course.getModel())) 218 { 219 String apogee = course.getValue("elpCode"); 220 if (StringUtils.isNotEmpty(apogee)) 221 { 222 title += " (" + apogee + ")"; 223 } 224 } 225 226 return title; 227 } 228} 229