001/* 002 * Copyright 2024 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.data; 017 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.List; 021import java.util.Objects; 022import java.util.stream.Collectors; 023import java.util.stream.Stream; 024 025import org.apache.commons.lang3.StringUtils; 026 027import org.ametys.odf.ProgramItem; 028import org.ametys.plugins.repository.AmetysObjectResolver; 029 030/** 031 * Class representing an educational path of a {@link ProgramItem} 032 */ 033public class EducationalPath 034{ 035 /** The program items identifier */ 036 public static final String PATH_SEGMENTS_IDENTIFIER = "programItemIds"; 037 038 /** The separator for path segment */ 039 public static final String PATH_SEGMENT_SEPARATOR = ";"; 040 041 private List<String> _programItemIds; 042 private List<ProgramItem> _programItems; 043 044 /** 045 * Constructs a EducationalPath 046 * @param programItemIds the ids of program items 047 */ 048 EducationalPath(List<String> programItemIds) 049 { 050 _programItemIds = programItemIds; 051 } 052 053 /** 054 * Constructs a EducationalPath 055 * @param programItemsIds the ids of program items 056 */ 057 EducationalPath(String[] programItemsIds) 058 { 059 _programItemIds = Arrays.asList(programItemsIds); 060 } 061 062 /** 063 * Constructs a EducationalPath 064 * @param programItems the program items 065 */ 066 EducationalPath(ProgramItem[] programItems) 067 { 068 _programItems = Arrays.asList(programItems); 069 } 070 071 /** 072 * Build a educational path 073 * @param programItemIds the ids of program items 074 * @return the educational path 075 */ 076 public static EducationalPath of(String... programItemIds) 077 { 078 return new EducationalPath(programItemIds); 079 } 080 081 /** 082 * Build a educational path from a parent education path 083 * @param parentPath The parent educational path 084 * @param programItemIds the ids of program items 085 * @return the educational path 086 */ 087 @SuppressWarnings("unchecked") 088 public static EducationalPath of(EducationalPath parentPath, String... programItemIds) 089 { 090 List<String> parentProgramItemIds = new ArrayList(parentPath.getProgramItemIds()); 091 parentProgramItemIds.addAll(Arrays.asList(programItemIds)); 092 return new EducationalPath(parentProgramItemIds); 093 } 094 095 /** 096 * Build a educational path from a parent education path 097 * @param parentPath The parent educational path 098 * @param programItem the program items 099 * @return the educational path 100 */ 101 public static EducationalPath of(EducationalPath parentPath, ProgramItem... programItem) 102 { 103 List<ProgramItem> parentProgramItems = parentPath._programItems; 104 if (parentProgramItems != null) 105 { 106 List<ProgramItem> programItems = new ArrayList<>(parentProgramItems); 107 programItems.addAll(Arrays.asList(programItem)); 108 return new EducationalPath(programItems.toArray(ProgramItem[]::new)); 109 } 110 else 111 { 112 List<String> parentProgramItemIds = new ArrayList<>(parentPath.getProgramItemIds()); 113 parentProgramItemIds.addAll(Stream.of(programItem).map(ProgramItem::getId).collect(Collectors.toList())); 114 return new EducationalPath(parentProgramItemIds); 115 } 116 } 117 118 /** 119 * Build a educational path 120 * @param programItems the program items 121 * @return the educational path 122 */ 123 public static EducationalPath of(ProgramItem... programItems) 124 { 125 return new EducationalPath(programItems); 126 } 127 128 /** 129 * Retrieves the program item ids that are the segment of this path 130 * @return the program item ids 131 */ 132 public List<String> getProgramItemIds() 133 { 134 if (_programItemIds != null) 135 { 136 return _programItemIds; 137 } 138 else 139 { 140 return _programItems.stream().map(ProgramItem::getId).collect(Collectors.toList()); 141 } 142 } 143 144 /** 145 * Get {@link ProgramItem}s that composed this educational path as an unmodifiable list 146 * @param resolver the ametys object resolver 147 * @return the {@link ProgramItem}s of this path 148 */ 149 public List<ProgramItem> getProgramItems(AmetysObjectResolver resolver) 150 { 151 if (_programItems != null) 152 { 153 return _programItems; 154 } 155 else 156 { 157 return resolveProgramItems(resolver).toList(); 158 } 159 } 160 161 /** 162 * Resolve {@link ProgramItem}s that composed this educational path 163 * @param resolver the ametys object resolver 164 * @return the {@link ProgramItem}s of this path 165 */ 166 public Stream<ProgramItem> resolveProgramItems(AmetysObjectResolver resolver) 167 { 168 if (_programItems != null) 169 { 170 return _programItems.stream(); 171 } 172 else 173 { 174 return _programItemIds 175 .stream() 176 .map(id -> (ProgramItem) resolver.resolveById(id)); 177 } 178 } 179 180 @Override 181 public String toString() 182 { 183 return StringUtils.join(getProgramItemIds(), PATH_SEGMENT_SEPARATOR); 184 } 185 186 @Override 187 public int hashCode() 188 { 189 return Objects.hash(getProgramItemIds()); 190 } 191 192 @Override 193 public boolean equals(Object obj) 194 { 195 if (this == obj) 196 { 197 return true; 198 } 199 if (!(obj instanceof EducationalPath other)) 200 { 201 return false; 202 } 203 204 return Objects.equals(getProgramItemIds(), other.getProgramItemIds()); 205 } 206}