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 */ 016 017package org.ametys.web.skin; 018 019import java.io.File; 020import java.io.FileInputStream; 021import java.io.IOException; 022import java.util.ArrayList; 023import java.util.Collection; 024import java.util.List; 025import java.util.Map; 026 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.Context; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.cocoon.ProcessingException; 033import org.slf4j.LoggerFactory; 034import org.xml.sax.SAXException; 035 036import org.ametys.runtime.model.CategorizedElementDefinitionHelper; 037import org.ametys.runtime.model.CategorizedElementDefinitionProxy; 038import org.ametys.runtime.model.ElementDefinition; 039import org.ametys.runtime.model.Enumerator; 040import org.ametys.runtime.model.Model; 041import org.ametys.runtime.model.ModelItem; 042import org.ametys.runtime.model.exception.UndefinedItemPathException; 043import org.ametys.runtime.model.type.ElementType; 044import org.ametys.runtime.parameter.Validator; 045import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; 046import org.ametys.runtime.plugin.component.ThreadSafeComponentManager; 047 048/** 049 * Model for Skin (do not mistake this with {@link SkinModel} ) 050 */ 051public class SkinParametersModel implements Model 052{ 053 private String _skinName; 054 private File _skinDir; 055 private AbstractThreadSafeComponentExtensionPoint<? extends ElementType> _skinParameterTypeEP; 056 private Context _context; 057 private ServiceManager _manager; 058 059 private List<ModelItem> _modelItems; 060 private Map<String, ElementDefinition> _flatDefinitions; 061 062 private List<CategorizedElementDefinitionProxy> _skinParams; 063 064 /** 065 * Create an instance of a model, based on the skin directory 066 * @param skinName name of the skin (must be unique) 067 * @param skinDir the skin directory where the configuration will be read 068 * @param skinParameterTypeEP the skin parameter type extension point 069 * @param context the current context 070 * @param manager the service manager 071 * @throws ProcessingException something went wrong while parsing the file 072 */ 073 public SkinParametersModel(String skinName, File skinDir, SkinParameterTypeExtensionPoint skinParameterTypeEP, Context context, ServiceManager manager) throws ProcessingException 074 { 075 _skinName = skinName; 076 _skinDir = skinDir; 077 _skinParameterTypeEP = skinParameterTypeEP; 078 _context = context; 079 _manager = manager; 080 _initialize(); 081 } 082 083 public ModelItem getModelItem(String itemPath) throws UndefinedItemPathException 084 { 085 for (ModelItem modelItem : _modelItems) 086 { 087 if (modelItem.getPath().equals(itemPath)) 088 { 089 return modelItem; 090 } 091 } 092 093 throw new UndefinedItemPathException("The parameter '" + itemPath + "' is not defined in skins."); 094 } 095 096 public Collection<? extends ModelItem> getModelItems() 097 { 098 return _modelItems; 099 } 100 101 public String getId() 102 { 103 return _skinName; 104 } 105 106 public String getFamilyId() 107 { 108 return this.getClass().getName(); 109 } 110 111 /** 112 * Get a flat map of {@link ElementDefinition} 113 * @return a flat map of {@link ElementDefinition} 114 * @throws ProcessingException something went wrong when reading the configuration file 115 */ 116 public Map<String, ElementDefinition> getFlatDefinitions() throws ProcessingException 117 { 118 return _flatDefinitions; 119 } 120 121 private void _initialize() throws ProcessingException 122 { 123 List<CategorizedElementDefinitionProxy> skinParams = _getParameters(); 124 _flatDefinitions = CategorizedElementDefinitionHelper.getFlatDefinitions(skinParams); 125 _modelItems = CategorizedElementDefinitionHelper.categorize(skinParams); 126 } 127 128 /** 129 * Read the {@link CategorizedElementDefinitionProxy} from the skin dir 130 * @return a list of {@link CategorizedElementDefinitionProxy} 131 * @throws ProcessingException error while reading the XML 132 */ 133 private List<CategorizedElementDefinitionProxy> _getParameters() throws ProcessingException 134 { 135 if (_skinParams != null) 136 { 137 return _skinParams; 138 } 139 List<CategorizedElementDefinitionProxy> skinParams = new ArrayList<>(); 140 141 ThreadSafeComponentManager<Validator> validatorManager = new ThreadSafeComponentManager<>(); 142 ThreadSafeComponentManager<Enumerator> enumeratorManager = new ThreadSafeComponentManager<>(); 143 144 try 145 { 146 validatorManager.setLogger(LoggerFactory.getLogger(getClass())); 147 validatorManager.contextualize(_context); 148 validatorManager.service(_manager); 149 150 enumeratorManager.setLogger(LoggerFactory.getLogger(getClass())); 151 enumeratorManager.contextualize(_context); 152 enumeratorManager.service(_manager); 153 154 SkinParameterParser parser = new SkinParameterParser(_skinParameterTypeEP, enumeratorManager, validatorManager, new File (_skinDir, "i18n").toURI().toString()); 155 Configuration configuration = _getConfigurationModel(_skinDir); 156 157 if (configuration != null) 158 { 159 Configuration[] parameterConfigs = configuration.getChild("parameters").getChildren("parameter"); 160 for (Configuration parameterConfig : parameterConfigs) 161 { 162 CategorizedElementDefinitionProxy parameter = parser.parse(_manager, "tempskin", parameterConfig, this, null); 163 skinParams.add(parameter); 164 } 165 166 try 167 { 168 parser.lookupComponents(); 169 } 170 catch (Exception e) 171 { 172 throw new ConfigurationException("Unable to lookup parameter local components", configuration, e); 173 } 174 } 175 176 _skinParams = skinParams; 177 return _skinParams; 178 } 179 catch (ConfigurationException | SAXException | IOException e) 180 { 181 throw new ProcessingException(e); 182 } 183 } 184 185 private Configuration _getConfigurationModel(File skinDir) throws ConfigurationException, SAXException, IOException 186 { 187 File configFile = new File(skinDir, "stylesheets" + File.separator + "config" + File.separator + "config-model.xml"); 188 189 if (configFile.exists()) 190 { 191 try (FileInputStream is = new FileInputStream(configFile)) 192 { 193 DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); 194 return builder.build(is); 195 } 196 } 197 198 // There is no parameter 199 return null; 200 } 201}