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 TextParameter extends AbstractSkinParameter
041{
042    private String _defaultValue;
043    private Path _xslFile;
044    
045    /**
046     * Constructor
047     * @param id the unique id
048     * @param label the label
049     * @param description the description
050     * @param xslFile the XSL file
051     * @param defaultValue the default value in the default language
052     */
053    public TextParameter(String id, I18nizableText label, I18nizableText description, Path xslFile, String defaultValue)
054    {
055        super(id, label, description);
056        _xslFile = xslFile;
057        _defaultValue = defaultValue;
058    }
059    
060    /**
061     * Get the CSS file path
062     * @return the CSS file path
063     */
064    public Path getPath ()
065    {
066        return _xslFile;
067    }
068    
069    @Override
070    public SkinParameterType getType()
071    {
072        return SkinParameterType.TEXT;
073    }
074    
075    @Override
076    public void apply(Path tempDir, Path modelDir, Object value, String lang)
077    {
078        String relPath = modelDir.relativize(_xslFile).toString();
079        Path cssFile = tempDir.resolve(relPath);
080        String string = _filetoString(cssFile);
081        
082        Pattern pattern = Pattern.compile("^[^>]*>([^<]*)<!--\\s*AMETYS\\s*\\(\\s*\"([^\"]+)\"\\s*(?:,\\s*([^,\"\\s]+|\"[^\"]*\")\\s*)?(?:,\\s*([^,\"\\s]+|\"[^\"]*\")\\s*)?\\)\\s*-->.*$$", Pattern.MULTILINE);
083        Matcher matcher = pattern.matcher(string);
084        
085        try (OutputStream os = Files.newOutputStream(cssFile))
086        {
087            int startIndex = 0;
088            
089            while (matcher.find())
090            {
091                int propertyStart = matcher.start(1);
092                
093                String beforeValue = string.substring(startIndex, propertyStart);
094                IOUtils.write(beforeValue, os, "UTF-8");
095                IOUtils.write((String) value, os, "UTF-8");
096                
097                startIndex = matcher.end(1);
098            }
099            
100            IOUtils.write(string.substring(startIndex), os, "UTF-8");
101        }
102        catch (IOException e)
103        {
104            throw new SkinParameterException ("Unable to apply text parameter '" + getId() + "'", e);
105        }
106    }
107    
108    private String _filetoString (Path file)
109    {
110        try
111        {
112            return Files.readString(file, StandardCharsets.UTF_8);
113        }
114        catch (IOException e)
115        {
116            throw new SkinParameterException ("Unable to parse file '" + file.getFileName().toString() + "'", e);
117        }
118    }
119    
120    @Override
121    public void toSAX(ContentHandler contentHandler, String modelName) throws SAXException
122    {
123        AttributesImpl attrs = new AttributesImpl();
124        attrs.addCDATAAttribute("id", getId());
125        attrs.addCDATAAttribute("type", SkinParameterType.TEXT.name().toLowerCase());
126        
127        XMLUtils.startElement(contentHandler, "parameter", attrs);
128        
129        getLabel().toSAX(contentHandler, "label");
130        getDescription().toSAX(contentHandler, "description");
131        
132        XMLUtils.endElement(contentHandler, "parameter");
133        
134    }
135    
136    @Override
137    public Map<String, Object> toJson(String modelName)
138    {
139        Map<String, Object> jsonObject = new HashMap<>();
140        
141        jsonObject.put("id", getId());
142        jsonObject.put("type", SkinParameterType.TEXT.name().toLowerCase());
143        jsonObject.put("label", getLabel());
144        jsonObject.put("description", getDescription());
145        
146        return jsonObject;
147    }
148    
149    @Override
150    public String getDefaultValue(SkinModel model)
151    {
152        return _defaultValue;
153    }
154    
155    @Override
156    public String getDefaultValue(SkinModel model, String lang)
157    {
158        return getDefaultValue(model);
159    }
160}