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.plugins.odfpilotage.manager; 017 018import java.io.File; 019import java.io.FileInputStream; 020import java.io.InputStream; 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.avalon.framework.configuration.Configurable; 027import org.apache.avalon.framework.configuration.Configuration; 028import org.apache.avalon.framework.configuration.ConfigurationException; 029import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 030import org.apache.avalon.framework.context.ContextException; 031import org.apache.avalon.framework.context.Contextualizable; 032import org.apache.avalon.framework.service.ServiceException; 033import org.apache.avalon.framework.service.ServiceManager; 034import org.apache.avalon.framework.service.Serviceable; 035import org.apache.cocoon.Constants; 036import org.apache.cocoon.environment.Context; 037import org.apache.commons.lang.StringUtils; 038 039import org.ametys.cms.contenttype.MetadataDefinition; 040import org.ametys.cms.repository.Content; 041import org.ametys.odf.ProgramItem; 042import org.ametys.odf.contenttype.ODFContentTypeMetadataManager; 043import org.ametys.odf.program.Program; 044import org.ametys.plugins.odfpilotage.helper.PilotageStatusHelper; 045import org.ametys.plugins.odfpilotage.helper.PilotageStatusHelper.PilotageStatus; 046import org.ametys.plugins.repository.AmetysRepositoryException; 047 048/** 049 * The odf content type metadata manager for pilotage 050 */ 051public class ODFPilotageContentTypeMetadataManager extends ODFContentTypeMetadataManager implements Configurable, Contextualizable, Serviceable 052{ 053 private static String _METADATA_FILE_PATH = "/org/ametys/plugins/odfpilotage/manager/restrictions.xml"; 054 private static String _METADATA_FILE_PATH_TO_OVERRIDE = "/WEB-INF/param/odf/pilotage/restrictions.xml"; 055 056 /** The Cocoon context */ 057 protected Context _cocoonContext; 058 059 /** The pilotage status helper */ 060 protected PilotageStatusHelper _pilotageStatusHelper; 061 062 /** The map of disabled metadatas for each content type and each pilotage status */ 063 protected Map<String, Map<PilotageStatus, List<String>>> _disabledMetadata; 064 065 @Override 066 public void service(ServiceManager manager) throws ServiceException 067 { 068 _pilotageStatusHelper = (PilotageStatusHelper) manager.lookup(PilotageStatusHelper.ROLE); 069 } 070 071 @Override 072 public void contextualize(org.apache.avalon.framework.context.Context context) throws ContextException 073 { 074 _cocoonContext = (Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 075 } 076 077 @Override 078 public void configure(Configuration configuration) throws ConfigurationException 079 { 080 _disabledMetadata = new HashMap<>(); 081 082 try 083 { 084 File metadataXml = new File(_cocoonContext.getRealPath(_METADATA_FILE_PATH_TO_OVERRIDE)); 085 if (!metadataXml.isFile()) 086 { 087 try (InputStream is = getClass().getResourceAsStream(_METADATA_FILE_PATH)) 088 { 089 Configuration cfg = new DefaultConfigurationBuilder().build(is); 090 _fillDisableMetadataMap(cfg); 091 } 092 } 093 else 094 { 095 try (InputStream is = new FileInputStream(metadataXml)) 096 { 097 Configuration cfg = new DefaultConfigurationBuilder().build(is); 098 _fillDisableMetadataMap(cfg); 099 } 100 } 101 } 102 catch (Exception e) 103 { 104 throw new ConfigurationException("Error while parsing metadata.xml", e); 105 } 106 } 107 108 /** 109 * Fill the disabled metadata from the configuration 110 * @param cfg the configuration 111 * @throws ConfigurationException if an error occurred 112 */ 113 protected void _fillDisableMetadataMap(Configuration cfg) throws ConfigurationException 114 { 115 for (Configuration contentTypeConf : cfg.getChildren("content-type")) 116 { 117 Map<PilotageStatus, List<String>> metadataByState = new HashMap<>(); 118 for (Configuration statusConf : contentTypeConf.getChildren("status")) 119 { 120 List<String> metadatas = new ArrayList<>(); 121 for (Configuration metadataConf : statusConf.getChildren("metadata")) 122 { 123 metadatas.add(metadataConf.getAttribute("path")); 124 } 125 126 String statusName = statusConf.getAttribute("name"); 127 PilotageStatus pilotageStatus = StringUtils.isNotBlank(statusName) ? PilotageStatus.valueOf(statusName.toUpperCase()) : PilotageStatus.NONE; 128 129 metadataByState.put(pilotageStatus, metadatas); 130 } 131 132 _disabledMetadata.put(contentTypeConf.getAttribute("id"), metadataByState); 133 } 134 } 135 136 @Override 137 public boolean canWrite(Content content, MetadataDefinition metadataDef) throws AmetysRepositoryException 138 { 139 if (content == null || !(content instanceof ProgramItem)) 140 { 141 return super.canWrite(content, metadataDef); 142 } 143 144 String metadataPath = metadataDef.getId(); 145 Program parentProgramWithHigherPilotageStatus = _pilotageStatusHelper.getParentProgramWithHigherPilotageStatus((ProgramItem) content); 146 if (parentProgramWithHigherPilotageStatus != null && !_pilotageStatusHelper.hasSuperRight(parentProgramWithHigherPilotageStatus)) 147 { 148 PilotageStatus pilotageStatus = _pilotageStatusHelper.getPilotageStatus(parentProgramWithHigherPilotageStatus); 149 boolean canWrite = super.canWrite(content, metadataDef); 150 if (canWrite) 151 { 152 for (String type : content.getTypes()) 153 { 154 if (_disabledMetadata.containsKey(type)) 155 { 156 Map<PilotageStatus, List<String>> pilotageStatusMetadata = _disabledMetadata.get(type); 157 for (PilotageStatus status : _getStatusToCheck(pilotageStatus)) 158 { 159 if (pilotageStatusMetadata.containsKey(status)) 160 { 161 List<String> metadata = pilotageStatusMetadata.get(status); 162 if (metadata.contains(metadataPath)) 163 { 164 return false; 165 } 166 } 167 } 168 } 169 } 170 } 171 172 return canWrite; 173 } 174 175 return true; 176 } 177 178 /** 179 * Get the list of pilotage status to check 180 * @param pilotageStatus the pilotage status of the content 181 * @return the list of pilotage status to check 182 */ 183 protected List<PilotageStatus> _getStatusToCheck(PilotageStatus pilotageStatus) 184 { 185 List<PilotageStatus> statusToCheck = new ArrayList<>(); 186 switch (pilotageStatus) 187 { 188 case MENTION_VALIDATED: 189 statusToCheck.add(PilotageStatus.MENTION_VALIDATED); 190 break; 191 case ORGUNIT_VALIDATED: 192 statusToCheck.add(PilotageStatus.MENTION_VALIDATED); 193 statusToCheck.add(PilotageStatus.ORGUNIT_VALIDATED); 194 break; 195 case CFVU_VALIDATED: 196 statusToCheck.add(PilotageStatus.MENTION_VALIDATED); 197 statusToCheck.add(PilotageStatus.ORGUNIT_VALIDATED); 198 statusToCheck.add(PilotageStatus.CFVU_VALIDATED); 199 break; 200 case CFVU_MCC_VALIDATED: 201 statusToCheck.add(PilotageStatus.MENTION_VALIDATED); 202 statusToCheck.add(PilotageStatus.ORGUNIT_VALIDATED); 203 statusToCheck.add(PilotageStatus.CFVU_VALIDATED); 204 statusToCheck.add(PilotageStatus.CFVU_MCC_VALIDATED); 205 break; 206 default: 207 break; 208 } 209 return statusToCheck; 210 } 211}