001/*
002 *  Copyright 2023 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.forms.helper;
017
018import java.util.function.Function;
019
020import org.apache.avalon.framework.component.Component;
021import org.apache.cocoon.sitemap.PatternException;
022import org.apache.commons.lang3.StringUtils;
023
024import org.ametys.runtime.plugin.component.AbstractLogEnabled;
025
026/**
027 * The parser for mail variables
028 */
029public class MailVariableParser extends AbstractLogEnabled implements Component
030{
031    /** Avalon ROLE. */
032    public static final String ROLE = MailVariableParser.class.getName();
033    
034    /**
035     * Check expression for variables inside '{}' and replace them with their processed value
036     * @param expression the epression to check
037     * @param function the function processing the variables
038     * @return the expression with replaced variable
039     * @throws PatternException exception when braces are in a wrong space
040     */
041    public String replaceText(String expression, Function<String, String> function) throws PatternException
042    {
043        if (StringUtils.isBlank(expression))
044        {
045            return null;
046        }
047        
048        StringBuilder sb = new StringBuilder();
049        boolean isOpen = false;
050        int openPos = 0;
051        for (int i = 0; i < expression.length(); i++)
052        {
053            final char c = expression.charAt(i);
054            
055            if (c == '\\')
056            {
057                i++; //next character is ignored because it's escaped
058                sb.append(expression.charAt(i));
059            }
060            else if (c == '{')
061            {
062                if (isOpen)
063                {
064                    throw new PatternException("Invalid '{' at position " + i + " in expression \"" + expression + "\"");
065                }
066                else
067                {
068                    isOpen = true;
069                    openPos = i;
070                }
071            }
072            else if (c == '}')
073            {
074                if (!isOpen)
075                {
076                    throw new PatternException("Invalid '}' at position " + i + " in expression \"" + expression + "\"");
077                }
078                else
079                {
080                    String variable = expression.substring(openPos + 1, i);
081                    String translation = function.apply(variable);
082                    if (StringUtils.isNotBlank(translation))
083                    {
084                        sb.append(translation);
085                    }
086                    isOpen = false;
087                }
088            }
089            else if (!isOpen)
090            {
091                sb.append(c);
092            }
093        }
094        
095        if (isOpen)
096        {
097            throw new PatternException("Invalid '{' at position " + openPos + " in expression \"" + expression + "\"");
098        }
099        
100        return sb.toString();
101    }
102}