001package jmri.jmrit.logixng.util.parser.functions;
002
003import java.util.ArrayList;
004import java.util.HashSet;
005import java.util.List;
006import java.util.Set;
007
008import jmri.JmriException;
009import jmri.jmrit.logixng.SymbolTable;
010import jmri.jmrit.logixng.util.parser.*;
011import jmri.util.TypeConversionUtil;
012
013import org.openide.util.lookup.ServiceProvider;
014
015/**
016 * Implementation of string functions.
017 *
018 * @author Daniel Bergqvist 2020
019 */
020@ServiceProvider(service = FunctionFactory.class)
021public class StringFunctions implements FunctionFactory {
022
023    @Override
024    public String getModule() {
025        return "String";
026    }
027
028    @Override
029    public Set<Function> getFunctions() {
030        Set<Function> functionClasses = new HashSet<>();
031
032        addFormatFunction(functionClasses);
033        addStrlenFunction(functionClasses);
034
035        return functionClasses;
036    }
037
038    @Override
039    public Set<Constant> getConstants() {
040        return new HashSet<>();
041    }
042
043    @Override
044    public String getConstantDescription() {
045        // This module doesn't define any constants
046        return null;
047    }
048
049    private void addFormatFunction(Set<Function> functionClasses) {
050        functionClasses.add(new AbstractFunction(this, "format", Bundle.getMessage("String.format_Descr")) {
051            @Override
052            public Object calculate(SymbolTable symbolTable, List<ExpressionNode> parameterList)
053                    throws CalculateException, JmriException {
054                if (parameterList.isEmpty()) {
055                    throw new WrongNumberOfParametersException(Bundle.getMessage("WrongNumberOfParameters1", getName(), 1));
056                }
057
058                String formatStr = TypeConversionUtil.convertToString(
059                        parameterList.get(0).calculate(symbolTable), false);
060
061                List<Object> list = new ArrayList<>();
062                for (int i=1; i < parameterList.size(); i++) {
063                    list.add(parameterList.get(i).calculate(symbolTable));
064                }
065
066                return String.format(formatStr, list.toArray());
067            }
068        });
069    }
070
071    private void addStrlenFunction(Set<Function> functionClasses) {
072        functionClasses.add(new AbstractFunction(this, "strlen", Bundle.getMessage("String.strlen_Descr")) {
073            @Override
074            public Object calculate(SymbolTable symbolTable, List<ExpressionNode> parameterList)
075                    throws CalculateException, JmriException {
076                if (parameterList.size() != 1) {
077                    throw new WrongNumberOfParametersException(Bundle.getMessage("WrongNumberOfParameters1", getName(), 1));
078                }
079
080                Object parameter = parameterList.get(0).calculate(symbolTable);
081
082                if (parameter == null) {
083                    throw new NullPointerException("Parameter is null");
084                } else if (parameter instanceof String) {
085                    return ((String)parameter).length();
086                }
087
088                throw new IllegalArgumentException("Parameter is not a String: "+parameter.getClass().getName());
089            }
090        });
091    }
092
093}