001/* 002 * Copyright 2020 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.odfpilotage.enumerators; 017 018import java.util.Collections; 019import java.util.Map; 020import java.util.Optional; 021import java.util.stream.Collectors; 022import java.util.stream.Stream; 023 024import org.apache.avalon.framework.configuration.Configurable; 025import org.apache.avalon.framework.configuration.Configuration; 026import org.apache.avalon.framework.configuration.ConfigurationException; 027import org.apache.avalon.framework.context.Context; 028import org.apache.avalon.framework.context.ContextException; 029import org.apache.avalon.framework.context.Contextualizable; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033import org.apache.cocoon.components.ContextHelper; 034import org.apache.commons.lang3.StringUtils; 035 036import org.ametys.cms.data.ContentValue; 037import org.ametys.cms.repository.Content; 038import org.ametys.cms.repository.ContentTypeExpression; 039import org.ametys.odf.course.Course; 040import org.ametys.odf.program.Container; 041import org.ametys.odf.program.ContainerFactory; 042import org.ametys.plugins.odfpilotage.helper.PilotageHelper; 043import org.ametys.plugins.repository.AmetysObjectIterable; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.UnknownAmetysObjectException; 046import org.ametys.plugins.repository.query.QueryHelper; 047import org.ametys.plugins.repository.query.expression.AndExpression; 048import org.ametys.plugins.repository.query.expression.Expression.Operator; 049import org.ametys.plugins.repository.query.expression.StringExpression; 050import org.ametys.runtime.i18n.I18nizableText; 051import org.ametys.runtime.model.Enumerator; 052 053/** 054 * {@link Enumerator} for the steps holder 055 */ 056public class StepHolderEnumerator implements Enumerator<ContentValue>, Serviceable, Contextualizable, Configurable, org.ametys.runtime.parameter.Enumerator 057{ 058 private Context _context; 059 private AmetysObjectResolver _resolver; 060 private PilotageHelper _pilotageHelper; 061 062 /** 063 * If <code>true</code> and the context is not an ELP, we get all the steps. 064 */ 065 private boolean _usedForSearch; 066 067 public void contextualize(Context context) throws ContextException 068 { 069 _context = context; 070 } 071 072 public void configure(Configuration configuration) throws ConfigurationException 073 { 074 Configuration customConf = configuration.getChild("enumeration").getChild("custom-enumerator"); 075 _usedForSearch = customConf.getChild("used-for-search").getValueAsBoolean(false); 076 } 077 078 public void service(ServiceManager manager) throws ServiceException 079 { 080 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 081 _pilotageHelper = (PilotageHelper) manager.lookup(PilotageHelper.ROLE); 082 } 083 084 public I18nizableText getEntry(ContentValue value) throws Exception 085 { 086 try 087 { 088 return _getDisplayName((Container) value.getContent()); 089 } 090 catch (UnknownAmetysObjectException e) 091 { 092 // Ignore. 093 } 094 095 return null; 096 } 097 098 public I18nizableText getEntry(String value) throws Exception 099 { 100 try 101 { 102 return _getDisplayName(_resolver.resolveById(value)); 103 } 104 catch (UnknownAmetysObjectException e) 105 { 106 // Ignore. 107 } 108 109 return null; 110 } 111 112 public Map<ContentValue, I18nizableText> getTypedEntries() throws Exception 113 { 114 Optional<Course> course = Optional.of(_context) 115 .map(ContextHelper::getRequest) 116 .map(r -> r.getAttribute(Content.class.getName())) 117 .filter(Course.class::isInstance) 118 .map(Course.class::cast); 119 120 // course est nul si on est hors contexte de l'édition 121 Stream<Container> containers = course.isPresent() 122 ? _pilotageHelper.getSteps(course.get()).stream() 123 : (_usedForSearch ? _getAllSteps() : Stream.empty()); 124 125 return containers 126 .collect(Collectors.toMap(ContentValue::new, this::_getDisplayName)); 127 } 128 129 @SuppressWarnings("unchecked") 130 public Map<Object, I18nizableText> getEntries() throws Exception 131 { 132 return (Map<Object, I18nizableText>) (Object) getTypedEntries(); 133 } 134 135 private Stream<Container> _getAllSteps() 136 { 137 return _pilotageHelper.getYearId() 138 .map(anneeId -> new StringExpression("nature", Operator.EQ, anneeId)) 139 .map(anneeExpression -> new AndExpression(new ContentTypeExpression(Operator.EQ, ContainerFactory.CONTAINER_CONTENT_TYPE), anneeExpression)) 140 .map(expression -> QueryHelper.getXPathQuery(null, ContainerFactory.CONTAINER_NODETYPE, expression)) 141 .map(_resolver::<Container>query) 142 .map(AmetysObjectIterable::stream) 143 .orElseGet(() -> Stream.of()); 144 } 145 146 private I18nizableText _getDisplayName(Container container) 147 { 148 StringBuilder displayName = new StringBuilder(); 149 150 // Display code 151 displayName.append("["); 152 displayName.append(container.getCode()); 153 displayName.append("] "); 154 155 // Display etpCode if it is present 156 String etpCode = container.getValue("etpCode"); 157 if (StringUtils.isNotBlank(etpCode)) 158 { 159 displayName.append("["); 160 displayName.append(etpCode); 161 displayName.append("] "); 162 } 163 164 displayName.append(container.getTitle()); 165 166 return new I18nizableText(displayName.toString()); 167 } 168 169 // TODO NEWATTRIBUTEAPI: remove this method when org.ametys.runtime.parameter.Enumerator will be removed 170 public Map<String, Object> getConfiguration() 171 { 172 return Collections.EMPTY_MAP; 173 } 174}