fi.semantum.strategia.widget.NumberTrafficValuation.java Source code

Java tutorial

Introduction

Here is the source code for fi.semantum.strategia.widget.NumberTrafficValuation.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Ministry of Transport and Communications (Finland).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Semantum Oy - initial API and implementation
 *******************************************************************************/
package fi.semantum.strategia.widget;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DecimalFormat;

import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;

import fi.semantum.strategia.Main;

public class NumberTrafficValuation implements TrafficValuation, Serializable {

    private static final long serialVersionUID = 7573677506428373762L;

    /*
     * State is coded in limits the following way: 
     * -INCREASE3 => greenLimit > redLimit || (redLimit == null && makeThree)
     * -DECREASE3 => redLimit > greenLimit || (greenLimit == null && makeThree)
     * -INCREASE2 => redLimit = null && !makeThree
     * -DECREASE2 => greenLimit = null && !makeThree
     */
    enum State {
        INCREASE3("Kolme vri - suurempi on parempi"), DECREASE3("Kolme vri - pienempi on parempi"), INCREASE2(
                "Kaksi vri - suurempi on parempi"), DECREASE2("Kaksi vri - pienempi on parempi");
        private String description;

        private State(String description) {
            this.description = description;
        }

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

    private BigDecimal redLimit;
    private BigDecimal greenLimit;

    private transient boolean inApply = false;
    private transient boolean makeThree = false;

    public NumberTrafficValuation() {
        redLimit = BigDecimal.valueOf(0);
        greenLimit = BigDecimal.valueOf(1);
    }

    // This is for migration
    public NumberTrafficValuation(BigDecimal low, BigDecimal high) {
        this.redLimit = low;
        this.greenLimit = high;
        if (greenLimit != null && redLimit != null)
            if (greenLimit.equals(redLimit))
                redLimit = null;
    }

    private void updateMakeThree() {
        if (makeThree && redLimit != null && greenLimit != null) {
            makeThree = false;
        }
    }

    private State getRawState() {
        if (redLimit == null)
            return State.INCREASE2;
        else if (greenLimit == null)
            return State.DECREASE2;
        else if (greenLimit.compareTo(redLimit) > 0)
            return State.INCREASE3;
        else
            return State.DECREASE3;
    }

    private State getState() {
        State raw = getRawState();
        if (makeThree) {
            if (raw == State.INCREASE2)
                return State.INCREASE3;
            if (raw == State.DECREASE2)
                return State.DECREASE3;
        }
        return raw;
    }

    private boolean isIncrease() {
        State state = getState();
        return state == State.INCREASE2 || state == State.INCREASE3;
    }

    private boolean isTwo() {
        State state = getState();
        return state == State.INCREASE2 || state == State.DECREASE2;
    }

    private void swap() {
        BigDecimal temp = redLimit;
        redLimit = greenLimit;
        greenLimit = temp;
    }

    BigDecimal getLowLimit() {

        State state = getState();

        if (State.INCREASE3.equals(state)) {
            return makeThree ? greenLimit : redLimit;
        } else if (State.DECREASE3.equals(state)) {
            return makeThree ? redLimit : greenLimit;
        } else if (State.INCREASE2.equals(state)) {
            return greenLimit;
        } else {
            return redLimit;
        }

    }

    BigDecimal getHighLimit() {

        State state = getState();
        if (State.INCREASE3.equals(state)) {
            return greenLimit;
        } else if (State.DECREASE3.equals(state)) {
            return redLimit;
        } else if (State.INCREASE2.equals(state)) {
            return greenLimit;
        } else {
            return redLimit;
        }

    }

    @Override
    public String getTrafficValue(Object value) {

        if (!(value instanceof BigDecimal))
            return TrafficValuation.RED;
        BigDecimal number = (BigDecimal) value;

        State state = getState();

        if (State.DECREASE2.equals(state))
            return number.compareTo(redLimit) < 0 ? TrafficValuation.GREEN : TrafficValuation.RED;
        else if (State.INCREASE2.equals(state))
            return number.compareTo(greenLimit) > 0 ? TrafficValuation.GREEN : TrafficValuation.RED;

        boolean less = number.compareTo(getLowLimit()) < 0;
        if (less) {
            if (State.INCREASE3.equals(state))
                return TrafficValuation.RED;
            else
                return TrafficValuation.GREEN;
        }
        boolean more = number.compareTo(getHighLimit()) > 0;
        if (more) {
            if (State.INCREASE3.equals(state))
                return TrafficValuation.GREEN;
            else
                return TrafficValuation.RED;
        }

        return TrafficValuation.YELLOW;

    }

    static final DecimalFormat df = new DecimalFormat();

    static {
        df.setGroupingUsed(false);
    }

    @Override
    public Runnable getEditor(VerticalLayout layout, final Main main, final Meter meter) {

        Indicator indicator = meter.getPossibleIndicator(main.getDatabase());
        String unit = indicator.getUnit();

        final ComboBox combo = new ComboBox("Valitse mittarin mritystapa");
        combo.addItem(State.INCREASE3);
        combo.addItem(State.DECREASE3);
        combo.addItem(State.INCREASE2);
        combo.addItem(State.DECREASE2);
        combo.setInvalidAllowed(false);
        combo.setNullSelectionAllowed(false);
        combo.setWidth("100%");
        combo.addStyleName(ValoTheme.COMBOBOX_TINY);
        layout.addComponent(combo);
        layout.setComponentAlignment(combo, Alignment.TOP_CENTER);
        layout.setExpandRatio(combo, 0.0f);

        final VerticalLayout vl1 = new VerticalLayout();
        vl1.setHeight("50px");
        vl1.setWidth("100%");
        vl1.setStyleName("redBlock");
        layout.addComponent(vl1);
        layout.setComponentAlignment(vl1, Alignment.TOP_CENTER);
        layout.setExpandRatio(vl1, 0.0f);
        final Label l1 = new Label(" > " + df.format(greenLimit.doubleValue()) + " " + unit);
        l1.setSizeUndefined();
        l1.addStyleName(ValoTheme.LABEL_LARGE);
        vl1.addComponent(l1);
        vl1.setComponentAlignment(l1, Alignment.MIDDLE_CENTER);

        HorizontalLayout hl1 = new HorizontalLayout();
        hl1.setSpacing(true);
        layout.addComponent(hl1);
        layout.setComponentAlignment(hl1, Alignment.TOP_LEFT);

        final TextField tf1 = new TextField();
        tf1.setValue(df.format(greenLimit.doubleValue()));
        tf1.setWidth("150px");
        tf1.setCaption("Suurempi raja-arvo");
        tf1.setStyleName(ValoTheme.TEXTFIELD_TINY);
        tf1.setValidationVisible(true);
        hl1.addComponent(tf1);

        Label unit1 = new Label();
        unit1.setSizeUndefined();
        unit1.setCaption("");
        unit1.setValue(unit);
        hl1.addComponent(unit1);
        hl1.setComponentAlignment(unit1, Alignment.MIDDLE_LEFT);

        final VerticalLayout vl2 = new VerticalLayout();
        vl2.setHeight("50px");
        vl2.setWidth("100%");
        vl2.addStyleName("yellowBlock");
        layout.addComponent(vl2);
        layout.setComponentAlignment(vl2, Alignment.TOP_CENTER);
        layout.setExpandRatio(vl2, 0.0f);
        final Label l2 = new Label();
        l2.setSizeUndefined();
        l2.addStyleName(ValoTheme.LABEL_LARGE);
        vl2.addComponent(l2);
        vl2.setComponentAlignment(l2, Alignment.MIDDLE_CENTER);

        HorizontalLayout hl2 = new HorizontalLayout();
        hl2.setSpacing(true);
        layout.addComponent(hl2);
        layout.setComponentAlignment(hl2, Alignment.TOP_LEFT);

        final TextField tf2 = new TextField();
        tf2.setWidth("150px");
        tf2.setCaption("Pienempi raja-arvo");
        tf2.setStyleName(ValoTheme.TEXTFIELD_TINY);
        tf2.setValidationVisible(true);
        hl2.addComponent(tf2);
        hl2.setComponentAlignment(tf2, Alignment.TOP_CENTER);

        Label unit2 = new Label();
        unit2.setSizeUndefined();
        unit2.setCaption("");
        unit2.setValue("" + unit);
        hl2.addComponent(unit2);
        hl2.setComponentAlignment(unit2, Alignment.MIDDLE_LEFT);

        final VerticalLayout vl3 = new VerticalLayout();
        vl3.setHeight("50px");
        vl3.setWidth("100%");
        vl3.addStyleName("greenBlock");
        layout.addComponent(vl3);
        layout.setComponentAlignment(vl3, Alignment.TOP_CENTER);
        layout.setExpandRatio(vl3, 0.0f);
        final Label l3 = new Label();
        l3.setSizeUndefined();
        l3.addStyleName(ValoTheme.LABEL_LARGE);
        vl3.addComponent(l3);
        vl3.setComponentAlignment(l3, Alignment.MIDDLE_CENTER);

        applyValues(main, meter, combo, vl1, l1, vl2, l2, vl3, l3, tf1, tf2);

        combo.addValueChangeListener(new ValueChangeListener() {

            private static final long serialVersionUID = 8396168732300003038L;

            @Override
            public void valueChange(ValueChangeEvent event) {

                if (inApply)
                    return;

                State currentState = getState();

                if (currentState.equals(combo.getValue()))
                    return;

                if (State.DECREASE3.equals(combo.getValue())) {
                    makeThree = true;
                    if (State.INCREASE3.equals(currentState)) {
                        swap();
                    } else if (State.INCREASE2.equals(currentState)) {
                        redLimit = greenLimit;
                        greenLimit = null;
                    }
                } else if (State.INCREASE3.equals(combo.getValue())) {
                    makeThree = true;
                    if (State.DECREASE3.equals(currentState)) {
                        swap();
                    } else if (State.DECREASE2.equals(currentState)) {
                        greenLimit = redLimit;
                        redLimit = null;
                    }
                } else if (State.INCREASE2.equals(combo.getValue())) {
                    if (State.DECREASE3.equals(currentState)) {
                        greenLimit = redLimit;
                    } else if (State.DECREASE2.equals(currentState)) {
                        greenLimit = redLimit;
                    }
                    redLimit = null;
                    makeThree = false;
                } else if (State.DECREASE2.equals(combo.getValue())) {
                    if (State.INCREASE3.equals(currentState)) {
                        redLimit = greenLimit;
                    } else if (State.INCREASE2.equals(currentState)) {
                        redLimit = greenLimit;
                    }
                    greenLimit = null;
                    makeThree = false;
                }

                updateMakeThree();

                applyValues(main, meter, combo, vl1, l1, vl2, l2, vl3, l3, tf1, tf2);

            }

        });

        tf1.addValueChangeListener(new ValueChangeListener() {

            private static final long serialVersionUID = -5484608577999300097L;

            @Override
            public void valueChange(ValueChangeEvent event) {

                if (inApply)
                    return;

                if (State.DECREASE3.equals(combo.getValue())) {
                    if (makeThree)
                        greenLimit = redLimit;
                    redLimit = new BigDecimal(tf1.getValue());
                } else if (State.INCREASE3.equals(combo.getValue())) {
                    if (makeThree)
                        redLimit = greenLimit;
                    greenLimit = new BigDecimal(tf1.getValue());
                } else if (State.INCREASE2.equals(combo.getValue())) {
                    greenLimit = new BigDecimal(tf1.getValue());
                } else if (State.DECREASE2.equals(combo.getValue())) {
                    redLimit = new BigDecimal(tf1.getValue());
                }

                updateMakeThree();

                applyValues(main, meter, combo, vl1, l1, vl2, l2, vl3, l3, tf1, tf2);

            }

        });

        tf2.addValueChangeListener(new ValueChangeListener() {

            private static final long serialVersionUID = 5825320869230527588L;

            @Override
            public void valueChange(ValueChangeEvent event) {

                if (inApply)
                    return;

                // This should not happen!
                if (State.INCREASE2.equals(combo.getValue()) || State.DECREASE2.equals(combo.getValue()))
                    return;

                if (State.DECREASE3.equals(combo.getValue())) {
                    greenLimit = new BigDecimal(tf2.getValue());
                } else if (State.INCREASE3.equals(combo.getValue())) {
                    redLimit = new BigDecimal(tf2.getValue());
                }

                updateMakeThree();

                applyValues(main, meter, combo, vl1, l1, vl2, l2, vl3, l3, tf1, tf2);

            }

        });

        return null;

    }

    private void applyValues(Main main, Meter meter, ComboBox combo, VerticalLayout vl1, Label l1,
            VerticalLayout vl2, Label l2, VerticalLayout vl3, Label l3, TextField tf1, TextField tf2) {

        inApply = true;

        Indicator indicator = meter.getPossibleIndicator(main.getDatabase());
        String unit = indicator.getUnit();

        combo.select(getState());

        final double highDouble = getHighLimit().doubleValue();
        final double lowDouble = getLowLimit().doubleValue();

        String highLimit = df.format(highDouble);
        String lowLimit = df.format(lowDouble);

        tf1.setValue(highLimit);
        l1.setValue(highLimit + " < arvo " + unit);

        if (isIncrease()) {
            vl1.setStyleName("greenBlock");
        } else {
            vl1.setStyleName("redBlock");
        }

        tf1.removeAllValidators();
        tf1.addValidator(new Validator() {

            private static final long serialVersionUID = 5929569929930454714L;

            @Override
            public void validate(Object value) throws InvalidValueException {
                try {
                    double d = Double.parseDouble((String) value);
                    if (d < lowDouble)
                        throw new InvalidValueException("Value is too small");
                } catch (NumberFormatException e) {
                    throw new InvalidValueException(e.getMessage());
                }
            }

        });

        if (isTwo()) {

            l3.setVisible(false);
            vl3.setVisible(false);
            tf2.setVisible(false);
            tf1.setCaption("Raja-arvo");

            if (isIncrease()) {
                vl2.setStyleName("redBlock");
            } else {
                vl2.setStyleName("greenBlock");
            }

            l2.setValue("arvo < " + lowLimit + " " + unit);

        } else {

            vl3.setVisible(true);
            l3.setVisible(true);
            tf2.setVisible(true);
            tf1.setCaption("Suurempi raja-arvo");
            tf2.setCaption("Pienempi raja-arvo");
            vl2.setStyleName("yellowBlock");

            l2.setValue(lowLimit + " < arvo < " + highLimit + " " + unit);
            l3.setValue("arvo < " + lowLimit + " " + unit);
            tf2.setValue(lowLimit);

            if (isIncrease()) {
                vl3.setStyleName("redBlock");
            } else {
                vl3.setStyleName("greenBlock");
            }

            tf2.removeAllValidators();
            tf2.addValidator(new Validator() {

                private static final long serialVersionUID = 5929569929930454714L;

                @Override
                public void validate(Object value) throws InvalidValueException {
                    try {
                        double d = Double.parseDouble((String) value);
                        if (d > highDouble)
                            throw new InvalidValueException("Value is too large");
                    } catch (NumberFormatException e) {
                        throw new InvalidValueException(e.getMessage());
                    }
                }

            });

        }

        inApply = false;

    }

}