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