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

ru.curs.celesta.score.SequenceElement Maven / Gradle / Ivy

The newest version!
package ru.curs.celesta.score;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Sequence object in metadata.
 */
public final class SequenceElement extends GrainElement {

    private static final String DUPLICATE_ENTRANCE_TEMPLATE = "Duplicate entrance of %s was detected for sequence %s";

    private final Map arguments = new LinkedHashMap<>();

    SequenceElement(GrainPart grainPart, String name) throws ParseException {
        super(grainPart, name);
        getGrain().addElement(this);
    }

    /**
     * Sets value for {@code START_WITH} argument of the sequence.
     *
     * @param startWith  value of {@code START_WITH} argument
     * @throws ParseException
     */
    void startWith(Long startWith) throws ParseException {
        if (arguments.putIfAbsent(Argument.START_WITH, startWith) != null) {
            throw new ParseException(
                    String.format(DUPLICATE_ENTRANCE_TEMPLATE, Argument.START_WITH, getName())
            );
        }
    }

    /**
     * Sets value for {@code INCREMENT_BY} argument of the sequence.
     *
     * @param incrementBy  value of {@code INCREMENT_BY} argument
     * @throws ParseException
     */
    void incrementBy(Long incrementBy) throws ParseException {
        if (incrementBy == 0) {
            throw new ParseException(
                    String.format("Sequence %s has illegal value 0 for INCREMENT BY expression.", getName())
            );
        }
        if (arguments.putIfAbsent(Argument.INCREMENT_BY, incrementBy) != null) {
            throw new ParseException(
                    String.format(DUPLICATE_ENTRANCE_TEMPLATE, Argument.INCREMENT_BY, getName())
            );
        }
    }

    /**
     * Sets value for {@code MINVALUE} argument of the sequence.
     *
     * @param minValue  value of {@code MINVALUE} argument
     * @throws ParseException
     */
    void minValue(Long minValue) throws ParseException {
        if (arguments.containsKey(Argument.MAXVALUE) && (Long) arguments.get(Argument.MAXVALUE) <= minValue) {
            throw new ParseException(
                    String.format("MINVALUE for sequence %s must be less than MAXVALUE", getName())
            );
        }

        if (arguments.putIfAbsent(Argument.MINVALUE, minValue) != null) {
            throw new ParseException(
                    String.format(DUPLICATE_ENTRANCE_TEMPLATE, Argument.MINVALUE, getName())
            );
        }
    }

    /**
     * Sets value for {@code MAXVALUE} argument of the sequence.
     *
     * @param maxValue value of {@code MAXVALUE} argument
     * @throws ParseException
     */
    void maxValue(Long maxValue) throws ParseException {
        if (arguments.containsKey(Argument.MINVALUE) && ((Long) arguments.get(Argument.MINVALUE)) >= maxValue) {
            throw new ParseException(
                    String.format("MAXVALUE for sequence %s must be greater than MINVALUE", getName())
            );
        }

        if (arguments.putIfAbsent(Argument.MAXVALUE, maxValue) != null) {
            throw new ParseException(
                    String.format(DUPLICATE_ENTRANCE_TEMPLATE, Argument.MINVALUE, getName())
            );
        }
    }

    /**
     * Sets value for {@code CYCLE} argument of the sequence.
     *
     * @param isCycle  value of {@code CYCLE} argument
     * @throws ParseException
     */
    void setIsCycle(Boolean isCycle) throws ParseException {
        if (arguments.putIfAbsent(Argument.CYCLE, isCycle) != null) {
            throw new ParseException(
                    String.format(DUPLICATE_ENTRANCE_TEMPLATE, Argument.CYCLE, getName())
            );
        }
    }

    void finalizeParsing() throws ParseException {
        arguments.putIfAbsent(Argument.START_WITH, 1L);
        arguments.putIfAbsent(Argument.INCREMENT_BY, 1L);

        Long startWith = getStartWith();
        Long incrementBy = getIncrementBy();

        if (!hasArgument(Argument.MINVALUE)) {
            minValue(startWith);
        }

        Long minValue = (Long) getArgument(Argument.MINVALUE);
        if (startWith < minValue) {
            throw new ParseException(
                    String.format("MINVALUE for sequence %s can't be greater than START WITH", getName())
            );
        }

        if (!hasArgument(Argument.MAXVALUE)) {
            maxValue(Long.MAX_VALUE);
        }

        Long maxValue = (Long) getArgument(Argument.MAXVALUE);
        if (startWith > maxValue) {
            throw new ParseException(
                    String.format("MAXVALUE for sequence %s must be greater or equals START WITH", getName())
            );
        }

        if (!hasArgument(Argument.CYCLE)) {
            setIsCycle(false);
        }

        if (incrementBy < 0) {
            if (startWith > 0 && (startWith + incrementBy) < minValue) {
                throw new ParseException(
                        String.format("Sum of arguments START WITH AND INCREMENT BY must be greater or equals MINVALUE "
                                + "for sequence %s  in case of descending increment", getName())
                );
            }

            if (Math.abs(incrementBy) >= Math.abs(maxValue - minValue)) {
                throw new ParseException(
                        String.format("Absolute value of 'INCREMENT BY' must be less than "
                                + "absolute value of subtraction of MAXVALUE and MINVALUE "
                                + "for sequence %s in case of descending increment", getName())
                );
            }
        }

    }

    /**
     * Returns a map of all arguments with values for the sequence.
     *
     */
    public Map getArguments() {
        return arguments;
    }

    /**
     * Whether the sequence contains the specified argument.
     *
     * @param argument  argument
     */
    public boolean hasArgument(Argument argument) {
        return arguments.containsKey(argument);
    }

    /**
     * Returns value of the specified argument.
     *
     * @param argument  argument
     */
    private Object getArgument(Argument argument) {
        return arguments.get(argument);
    }

    /**
     * Returns STARTS WITH parameter for this SEQUENCE.
     */
    public Long getStartWith() {
        return (Long) arguments.get(Argument.START_WITH);
    }

    /**
     * Returns MINVALUE parameter for this SEQUENCE.
     */
    public Long getMinValue() {
        return (Long) arguments.get(Argument.MINVALUE);
    }

    /**
     * Returns MAXVALUE parameter for this SEQUENCE.
     */
    public Long getMaxValue() {
        return (Long) arguments.get(Argument.MAXVALUE);
    }

    /**
     * Returns INCREMENT BY parameter for this SEQUENCE.
     */
    public Long getIncrementBy() {
        return (Long) arguments.get(Argument.INCREMENT_BY);
    }

    /**
     * Returns CYCLE parameter for this SEQUENCE.
     */
    public Boolean isCycle() {
        return (Boolean) arguments.get(Argument.CYCLE);
    }

    /**
     * Sequence arguments.
     */
    public enum Argument {
        /**
         * {@code START_WITH} argument.
         */
        START_WITH("START WITH", "START WITH %s "),
        /**
         * {@code INCREMENT_BY} argument.
         */
        INCREMENT_BY("INCREMENT BY", "INCREMENT BY %s "),
        /**
         * {@code MINVALUE} argument.
         */
        MINVALUE("MINVALUE", "MINVALUE %s "),
        /**
         * {@code MAXVALUE} argument.
         */
        MAXVALUE("MAXVALUE", "MAXVALUE %s "),
        /**
         * {@code CYCLE} argument.
         */
        CYCLE("CYCLE", "CYCLE ");

        private final String type;
        private final String sqlTemplate;

        Argument(String type, String sqlTemplate) {
            this.type = type;
            this.sqlTemplate = sqlTemplate;
        }

        /**
         * Returns SQL for argument with the specified {@code value}.
         *
         * @param value  argument value
         */
        public String getSql(Object value) {

            if (this == CYCLE && Objects.equals(false, value)) {
                return "";
            }

            return String.format(sqlTemplate, value);
        }

        @Override
        public String toString() {
            return type;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy