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 */ 016 017package org.ametys.plugins.odfsync.generic.scc; 018 019import java.io.InputStream; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.Optional; 023 024import org.apache.avalon.framework.activity.Initializable; 025import org.apache.avalon.framework.component.Component; 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.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033import org.apache.excalibur.source.Source; 034import org.apache.excalibur.source.SourceResolver; 035 036import org.ametys.core.cache.AbstractCacheManager; 037import org.ametys.core.cache.Cache; 038import org.ametys.core.util.filereloader.FileReloader; 039import org.ametys.core.util.filereloader.FileReloaderUtils; 040import org.ametys.runtime.i18n.I18nizableText; 041import org.ametys.runtime.plugin.component.AbstractLogEnabled; 042import org.ametys.runtime.plugin.component.PluginAware; 043 044/** 045 * Abstract class for reading mapping files in ODF helpers. 046 * First look for a project mapping files in WEB-INF/param/odf 047 * Then look for the default mapping files in plugin.odf-sync 048 */ 049public abstract class AbstractMappingHelper extends AbstractLogEnabled implements Component, Serviceable, Configurable, PluginAware, Initializable, FileReloader 050{ 051 /** The source resolver */ 052 protected SourceResolver _srcResolver; 053 054 /** The cache manager */ 055 protected AbstractCacheManager _cacheManager; 056 057 /** The file reloader utils */ 058 protected FileReloaderUtils _fileReloaderUtils; 059 060 /** The implementation name */ 061 protected String _implementationName; 062 063 private String _id; 064 065 public void setPluginInfo(String pluginName, String featureName, String id) 066 { 067 _id = id; 068 } 069 070 @Override 071 public void configure(Configuration configuration) throws ConfigurationException 072 { 073 _implementationName = configuration.getChild("name").getValue(); 074 } 075 076 @Override 077 public void service(ServiceManager manager) throws ServiceException 078 { 079 _srcResolver = (SourceResolver) manager.lookup(SourceResolver.ROLE); 080 _cacheManager = (AbstractCacheManager) manager.lookup(AbstractCacheManager.ROLE); 081 _fileReloaderUtils = (FileReloaderUtils) manager.lookup(FileReloaderUtils.ROLE); 082 } 083 084 public void initialize() throws Exception 085 { 086 _cacheManager.createMemoryCache( 087 _getCacheId(), 088 getCacheLabel(), 089 getCacheDescription(), 090 true, 091 null 092 ); 093 } 094 095 /** 096 * Read the mapping file to convert types. 097 * @param baseUri The base uri of the file 098 * @return The mapping 099 * @throws Exception if an exception occurs 100 */ 101 protected Map<String, String> _readMapping(String baseUri) throws Exception 102 { 103 // First, search in WEB-INF/param/odf/[implementationName] 104 Map<String, String> mapping = _readMappingFrom("context://WEB-INF/param/odf/" + _implementationName + baseUri); 105 106 if (mapping == null) 107 { 108 // Then in the ODF-sync plugin conversions folder 109 mapping = _readMappingFrom("plugin:odf-sync://conversions/" + _implementationName + baseUri); 110 } 111 112 return Optional.ofNullable(mapping).orElseGet(Map::of); 113 } 114 115 private Map<String, String> _readMappingFrom(String uri) throws Exception 116 { 117 _fileReloaderUtils.updateFile(uri, !_getCache().hasKey(uri), this); 118 return _getCache().get(uri); 119 } 120 121 /** 122 * Parse the mapping file 123 * @param is The source input stream 124 * @return The mapping 125 * @throws Exception If an error occurs 126 */ 127 private Map<String, String> _parseMappingFile(InputStream is) throws Exception 128 { 129 Map<String, String> mapping = new HashMap<>(); 130 131 Configuration configuration = new DefaultConfigurationBuilder().build(is); 132 for (Configuration itemConf : configuration.getChildren()) 133 { 134 String remoteValue = itemConf.getAttribute("code"); 135 String ametysValue = itemConf.getValue(); 136 137 mapping.put(remoteValue, ametysValue); 138 } 139 140 return mapping; 141 } 142 143 public void updateFile(String sourceUrl, Source source, InputStream is) throws Exception 144 { 145 if (is != null) 146 { 147 _getCache().put(sourceUrl, _parseMappingFile(is)); 148 } 149 else 150 { 151 _getCache().invalidate(sourceUrl); 152 } 153 } 154 155 public String getId(String sourceUrl) 156 { 157 return sourceUrl; 158 } 159 160 private Cache<String, Map<String, String>> _getCache() 161 { 162 return _cacheManager.get(_getCacheId()); 163 } 164 165 private String _getCacheId() 166 { 167 return _id + "$mapping"; 168 } 169 170 /** 171 * Get the cache label. 172 * @return the cache label 173 */ 174 protected abstract I18nizableText getCacheLabel(); 175 176 /** 177 * Get the cache description. 178 * @return the cache description 179 */ 180 protected abstract I18nizableText getCacheDescription(); 181}