001/*
002 * Copyright 2023 the original author or authors.
003 * <p>
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 * <p>
008 * https://www.apache.org/licenses/LICENSE-2.0
009 * <p>
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 de.cuioss.tools.formatting.template.lexer;
017
018import static java.util.Objects.requireNonNull;
019
020import java.lang.reflect.InvocationTargetException;
021import java.util.EnumSet;
022
023import de.cuioss.tools.formatting.template.FormatterSupport;
024import de.cuioss.tools.formatting.template.lexer.BracketLexer.Brackets;
025import de.cuioss.tools.formatting.template.lexer.Lexer.ExpressionLanguage;
026import lombok.AccessLevel;
027import lombok.NoArgsConstructor;
028
029/**
030 * @author Eugen Fischer
031 */
032@NoArgsConstructor(access = AccessLevel.PRIVATE)
033public final class LexerBuilder {
034
035    static final EnumSet<ExpressionLanguage> SIMPLE = EnumSet.of(ExpressionLanguage.SIMPLE_SQUARED_BRACKTES,
036            ExpressionLanguage.SIMPLE_CURLY_BRACKETS, ExpressionLanguage.SIMPLE_ANGLE_BRACKET);
037
038    /**
039     * @return the builder with {@link ExpressionLanguage#SIMPLE_SQUARED_BRACKTES}
040     */
041    public static Builder useSimpleElWithSquaredBrackets() {
042        return new Builder(ExpressionLanguage.SIMPLE_SQUARED_BRACKTES);
043    }
044
045    /**
046     * @param expLanguage {@link ExpressionLanguage} must not be null
047     *
048     * @return builder with the given {@link ExpressionLanguage}
049     */
050    public static Builder withExpressionLanguage(final ExpressionLanguage expLanguage) {
051        requireNonNull(expLanguage, "ExpressionLanguage must not be null.");
052        return new Builder(expLanguage);
053    }
054
055    /**
056     * The builder class
057     */
058    public static final class Builder {
059
060        private final ExpressionLanguage expl;
061
062        private boolean strict = false;
063
064        private Builder(final ExpressionLanguage expLanguage) {
065            expl = expLanguage;
066        }
067
068        private static Brackets getBracketsTypeFor(final ExpressionLanguage expl) {
069            return switch (expl) {
070            case SIMPLE_SQUARED_BRACKTES -> Brackets.SQUARED_BRACKETS;
071            case SIMPLE_CURLY_BRACKETS -> Brackets.CURLY_BRACKETS;
072            case SIMPLE_ANGLE_BRACKET -> Brackets.ANGLE_BRACKET;
073            default -> throw new IllegalArgumentException(expl + " doesn't belongs to Simple expression language.");
074            };
075        }
076
077        /**
078         * @param strict enabling the strict mode for pattern matching (only match exact
079         *               name) instead of best fitting
080         * @return The concrete {@link Builder}
081         */
082        public Builder strict(boolean strict) {
083            this.strict = strict;
084            return this;
085        }
086
087        /**
088         * Build the formatter for {@link FormatterSupport} type
089         *
090         * @param source {@link FormatterSupport} type
091         *
092         * @return created formatter
093         */
094        public <F extends FormatterSupport> Lexer<F> build(final F source) {
095            if (SIMPLE.contains(expl)) {
096                return new BracketLexer<>(source, getBracketsTypeFor(expl), strict);
097            }
098            throw new IllegalArgumentException(expl + " doesn't belongs to Simple expression language.");
099        }
100
101        /**
102         * @param sourceType bean type
103         *
104         * @return Lexer for classType
105         * @throws IllegalStateException if access to the class constructor fails or
106         *                               class isn't public
107         */
108        public <F extends FormatterSupport> Lexer<F> build(final Class<F> sourceType) {
109            try {
110                return build(sourceType.getDeclaredConstructor().newInstance());
111            } catch (final RuntimeException | InstantiationException | IllegalAccessException
112                    | InvocationTargetException | NoSuchMethodException e) {
113                throw new IllegalStateException(
114                        "Class '" + sourceType + "' should provide an accessible default constructor.", e);
115            }
116        }
117
118    }
119
120}