001/* 002 * Copyright 2011 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.skinfactory.parameters; 017 018import java.io.IOException; 019import java.io.OutputStream; 020import java.nio.charset.StandardCharsets; 021import java.nio.file.Files; 022import java.nio.file.Path; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.regex.Matcher; 026import java.util.regex.Pattern; 027 028import org.apache.cocoon.xml.AttributesImpl; 029import org.apache.cocoon.xml.XMLUtils; 030import org.apache.commons.io.IOUtils; 031import org.xml.sax.ContentHandler; 032import org.xml.sax.SAXException; 033 034import org.ametys.runtime.i18n.I18nizableText; 035import org.ametys.web.skin.SkinModel; 036 037/** 038 * Implementation of {@link AbstractSkinParameter} for a i18niable text 039 */ 040public class I18nizableTextParameter extends AbstractSkinParameter 041{ 042 private String _i18nKey; 043 private Map<String, String> _defaultValues; 044 045 /** 046 * Constructor 047 * @param id the unique id 048 * @param label the label 049 * @param description the description 050 * @param i18nKey the i18n key 051 * @param defaultValues the default values 052 */ 053 public I18nizableTextParameter(String id, I18nizableText label, I18nizableText description, String i18nKey, Map<String, String> defaultValues) 054 { 055 super(id, label, description); 056 _i18nKey = i18nKey; 057 _defaultValues = defaultValues; 058 } 059 060 @Override 061 public SkinParameterType getType() 062 { 063 return SkinParameterType.I18N; 064 } 065 066 /** 067 * Get the i18n key 068 * @return the i18n key 069 */ 070 public String geti18nKey() 071 { 072 return _i18nKey; 073 } 074 075 /** 076 * Set the i18n key 077 * @param i18nKey the i18n key to set 078 */ 079 public void setKey (String i18nKey) 080 { 081 _i18nKey = i18nKey; 082 } 083 084 @Override 085 public void apply(Path tempDir, Path modelDir, Object value, String lang) 086 { 087 Path i18nFile = tempDir.resolve("i18n/messages.xml"); 088 if (lang != null) 089 { 090 Path f = tempDir.resolve("i18n/messages_" + lang + ".xml"); 091 if (Files.exists(f)) 092 { 093 i18nFile = f; 094 } 095 } 096 097 String string = _filetoString (i18nFile); 098 099 Pattern pattern = null; 100 if (i18nFile.getFileName().toString().equals("messages.xml")) 101 { 102 pattern = Pattern.compile("^\\s*<message key=\"" + geti18nKey() + "\">([^<]*)<!--\\s*AMETYS\\s*\\(\\s*\"([^\"]+)\"\\s*(?:,\\s*([^,\"\\s]+|\"[^\"]*\")\\s*)?(?:,\\s*([^,\"\\s]+|\"[^\"]*\")\\s*)?\\)\\s*--></message>\\s*$", Pattern.MULTILINE); 103 104 } 105 else 106 { 107 pattern = Pattern.compile("^\\s*<message key=\"" + geti18nKey() + "\">([^<]*)</message>\\s*$", Pattern.MULTILINE); 108 } 109 110 Matcher matcher = pattern.matcher(string); 111 112 try (OutputStream os = Files.newOutputStream(i18nFile)) 113 { 114 int startIndex = 0; 115 116 while (matcher.find()) 117 { 118 int propertyStart = matcher.start(1); 119 120 String beforeValue = string.substring(startIndex, propertyStart); 121 IOUtils.write(beforeValue, os, "UTF-8"); 122 IOUtils.write((String) value, os, "UTF-8"); 123 124 startIndex = matcher.end(1); 125 } 126 127 IOUtils.write(string.substring(startIndex), os, "UTF-8"); 128 } 129 catch (IOException e) 130 { 131 throw new SkinParameterException ("Unable to apply css parameter '" + getId() + "'", e); 132 } 133 } 134 135 private String _filetoString(Path file) 136 { 137 try 138 { 139 return Files.readString(file, StandardCharsets.UTF_8); 140 } 141 catch (IOException e) 142 { 143 throw new SkinParameterException ("Unable to parse file '" + file.getFileName().toString() + "'", e); 144 } 145 } 146 147 @Override 148 public void toSAX(ContentHandler contentHandler, String modelName) throws SAXException 149 { 150 AttributesImpl attrs = new AttributesImpl(); 151 attrs.addCDATAAttribute("id", getId()); 152 attrs.addCDATAAttribute("type", SkinParameterType.I18N.name().toLowerCase()); 153 154 XMLUtils.startElement(contentHandler, "parameter", attrs); 155 156 getLabel().toSAX(contentHandler, "label"); 157 getDescription().toSAX(contentHandler, "description"); 158 XMLUtils.createElement(contentHandler, "i18nkey", geti18nKey()); 159 160 XMLUtils.endElement(contentHandler, "parameter"); 161 } 162 163 @Override 164 public Map<String, Object> toJson(String modelName) 165 { 166 Map<String, Object> jsonObject = new HashMap<>(); 167 168 jsonObject.put("id", getId()); 169 jsonObject.put("type", SkinParameterType.I18N.name().toLowerCase()); 170 jsonObject.put("label", getLabel()); 171 jsonObject.put("description", getDescription()); 172 jsonObject.put("i18nkey", geti18nKey()); 173 174 return jsonObject; 175 } 176 177 /** 178 * Get default values 179 * @return The default values 180 */ 181 public Map<String, String> getDefaultValues () 182 { 183 return _defaultValues; 184 } 185 186 @Override 187 public String getDefaultValue(SkinModel model) 188 { 189 return getDefaultValue (model, null); 190 } 191 192 @Override 193 public String getDefaultValue (SkinModel model, String lang) 194 { 195 if (lang != null && _defaultValues.containsKey(lang)) 196 { 197 return _defaultValues.get(lang); 198 } 199 200 return _defaultValues.entrySet().iterator().next().getValue(); 201 } 202}