All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.watertemplate.interpreter.parser.AbstractSyntaxTree Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package org.watertemplate.interpreter.parser;

import org.watertemplate.TemplateObject;
import org.watertemplate.interpreter.parser.exception.IdCouldNotBeResolvedException;

import java.util.List;
import java.util.Locale;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.watertemplate.TemplateMap.Arguments;


public abstract class AbstractSyntaxTree {

    static final AbstractSyntaxTree EMPTY = new Empty();

    public abstract String string(final Arguments arguments, final Locale locale);

    static class For extends AbstractSyntaxTree {

        private final String variableName;
        private final Id collectionId;
        private final AbstractSyntaxTree forStatements;
        private final AbstractSyntaxTree elseStatements;

        public For(final String variableName, final Id collectionId, final AbstractSyntaxTree forStatements) {
            this(variableName, collectionId, forStatements, EMPTY);
        }

        @Override
        public String string(final Arguments arguments, final Locale locale) {
            final TemplateObject.Collection collection = (TemplateObject.Collection) collectionId.templateObject(arguments);

            if (collection.isEmpty()) {
                return elseStatements.string(arguments, locale);
            }

            final Arguments forArguments = new Arguments(arguments); // Mutable
            final BiConsumer mapper = collection.getMapper();
            final StringBuilder sb = new StringBuilder();

            for (final Object item : collection.getCollection()) {
                forArguments.addMappedObject(variableName, item, mapper);
                sb.append(forStatements.string(forArguments, locale));
            }

            return sb.toString();
        }

        public For(final String variableName, final Id collectionId, final AbstractSyntaxTree forStatements, final AbstractSyntaxTree elseStatements) {
            this.variableName = variableName;
            this.collectionId = collectionId;
            this.forStatements = forStatements;
            this.elseStatements = elseStatements;
        }
    }

    static class Id extends AbstractSyntaxTree {

        private final String propertyKey;
        private final Id nestedId;

        public Id(final String propertyKey) {
            this(propertyKey, null);
        }

        public Id(final String propertyKey, final Id nestedId) {
            this.propertyKey = propertyKey;
            this.nestedId = nestedId;
        }

        public String getPropertyKey() {
            return propertyKey;
        }

        private String getFullId() {
            if (nestedId == null) {
                return propertyKey;
            }

            return propertyKey + Keywords.ACCESSOR + nestedId.getFullId();
        }

        TemplateObject templateObject(final Arguments arguments) {
            TemplateObject object = arguments.get(propertyKey);

            if (object == null) {
                throw new IdCouldNotBeResolvedException(this.getFullId());
            }

            if (nestedId == null) {
                return object;
            }

            if (!(object instanceof TemplateObject.Mapped)) {
                throw new IdCouldNotBeResolvedException(this.getFullId());
            }

            try {
                Arguments mappedProperties = ((TemplateObject.Mapped) object).map();
                return nestedId.templateObject(mappedProperties);
            } catch (IdCouldNotBeResolvedException e) {
                throw new IdCouldNotBeResolvedException(this.getFullId());
            }
        }

        @Override
        public String string(final Arguments arguments, final Locale locale) {
            return this.templateObject(arguments).evaluate(locale);
        }
    }

    static class If extends AbstractSyntaxTree {

        private final Id conditionId;
        private final AbstractSyntaxTree ifStatements;
        private final AbstractSyntaxTree elseStatements;

        public If(final Id conditionId, final AbstractSyntaxTree ifStatements) {
            this(conditionId, ifStatements, EMPTY);
        }

        public If(final Id conditionId, final AbstractSyntaxTree ifStatements, final AbstractSyntaxTree elseStatements) {
            this.conditionId = conditionId;
            this.ifStatements = ifStatements;
            this.elseStatements = elseStatements;
        }

        @Override
        public String string(final Arguments arguments, final Locale locale) {
            TemplateObject.Condition condition = (TemplateObject.Condition) conditionId.templateObject(arguments);

            if (condition.isTrue()) {
                return ifStatements.string(arguments, locale);
            } else {
                return elseStatements.string(arguments, locale);
            }
        }
    }

    static class Statements extends AbstractSyntaxTree {

        private final List abstractSyntaxTrees;

        public Statements(final List abstractSyntaxTrees) {
            this.abstractSyntaxTrees = abstractSyntaxTrees.stream()
                    .flatMap(this::flatten).collect(Collectors.toList());
        }

        private Stream flatten(final AbstractSyntaxTree ast) {
            if (ast instanceof Statements) {
                return ((Statements) ast).abstractSyntaxTrees.stream();
            } else if (ast != EMPTY) {
                return Stream.of(ast);
            } else {
                return Stream.of();
            }
        }

        @Override
        public String string(final Arguments arguments, final Locale locale) {
            final StringBuilder sb = new StringBuilder();

            for (AbstractSyntaxTree ast : abstractSyntaxTrees) {
                sb.append(ast.string(arguments, locale));
            }

            return sb.toString();
        }
    }

    static class Text extends AbstractSyntaxTree {
        private final String value;

        public Text(final String value) {
            this.value = value;
        }

        @Override
        public String string(final Arguments arguments, final Locale locale) {
            return value;
        }
    }

    private static class Empty extends AbstractSyntaxTree {
        private Empty() {
        }

        @Override
        public String string(final Arguments arguments, final Locale locale) {
            return "";
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy