001/* 002 * Copyright 2021 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.plugins.odfsync.pegase.scc; 017 018import java.util.List; 019import java.util.Map; 020import java.util.Objects; 021import java.util.Optional; 022import java.util.stream.Collectors; 023import java.util.stream.Stream; 024 025import org.apache.commons.lang.StringUtils; 026import org.slf4j.Logger; 027 028import org.ametys.cms.contenttype.ContentType; 029import org.ametys.odf.courselist.CourseList.ChoiceType; 030import org.ametys.odf.program.ProgramFactory; 031import org.ametys.odf.program.SubProgramFactory; 032import org.ametys.plugins.odfsync.scc.operator.AbstractODFSynchronizingContentOperator; 033import org.ametys.plugins.odfsync.utils.ContentWorkflowDescription; 034 035/** 036 * Pegase synchronizing content operator extending {@link AbstractODFSynchronizingContentOperator} because we keep some mapping mechanisms. 037 */ 038public class PegaseSynchronizingContentOperator extends AbstractODFSynchronizingContentOperator 039{ 040 @Override 041 protected String getHelperRole() 042 { 043 return "org.ametys.plugins.odfsync.pegase.scc.operator.PegaseSynchronizingContentOperatorHelper"; 044 } 045 046 @Override 047 public Map<String, List<Object>> transform(ContentType obsoleteCType, Map<String, List<Object>> remoteValues, Logger logger) 048 { 049 // Get the right content type from the category field 050 ContentType contentType = Optional.of(remoteValues) 051 .map(v -> v.get("workflowDescription")) 052 .map(l -> l.get(0)) 053 .map(ContentWorkflowDescription.class::cast) 054 .map(ContentWorkflowDescription::getContentType) 055 .map(_contentTypeEP::getExtension) 056 .orElse(null); 057 058 if (contentType == null) 059 { 060 return remoteValues; 061 } 062 063 _transformSpecificValues(contentType.getId(), remoteValues); 064 065 return super.transform(contentType, remoteValues, logger); 066 } 067 068 private void _transformSpecificValues(String contentTypeId, Map<String, List<Object>> remoteValues) 069 { 070 switch (contentTypeId) 071 { 072 case ProgramFactory.PROGRAM_CONTENT_TYPE: 073 case SubProgramFactory.SUBPROGRAM_CONTENT_TYPE: 074 _transformSpecificAbstractProgramValues(remoteValues); 075 break; 076 default: 077 // Nothing to do 078 } 079 080 // Always transform courseList values in case of we have courses not under course list 081 _transformSpecificCourseListValues(remoteValues); 082 } 083 084 private void _transformSpecificAbstractProgramValues(Map<String, List<Object>> remoteValues) 085 { 086 // Transform ects for AbstractProgram (ECTS value is a double, transform it to String with a Long appearance, 5.0 -> "5") 087 List<Object> ects = Optional.ofNullable(remoteValues.get("ects")) 088 .map(List::stream) 089 .orElseGet(Stream::empty) 090 .filter(Objects::nonNull) 091 .map(Object::toString) 092 .filter(StringUtils::isNotEmpty) 093 .map(Double::valueOf) 094 .map(Double::longValue) 095 .map(String::valueOf) 096 .collect(Collectors.toList()); 097 098 if (ects.isEmpty()) 099 { 100 remoteValues.remove("ects"); 101 } 102 else 103 { 104 remoteValues.put("ects", ects); 105 } 106 } 107 108 private void _transformSpecificCourseListValues(Map<String, List<Object>> remoteValues) 109 { 110 // Set the choiceType for CourseList 111 String choiceType = 112 Optional.ofNullable(_getFirstValueAsString(remoteValues.remove("plageDeChoix"))) 113 .map(Boolean::parseBoolean) 114 .orElse(false) 115 ? ChoiceType.CHOICE.toString() 116 : ( 117 Optional.ofNullable(_getFirstValueAsString(remoteValues.remove("obligatoire"))) 118 .map(Boolean::parseBoolean) 119 .orElse(false) 120 ? ChoiceType.MANDATORY.toString() 121 : ChoiceType.OPTIONAL.toString() 122 ); 123 124 remoteValues.put("choiceType", List.of(choiceType)); 125 } 126}