eu.lp0.cursus.ui.component.EnumDatabaseColumn.java Source code

Java tutorial

Introduction

Here is the source code for eu.lp0.cursus.ui.component.EnumDatabaseColumn.java

Source

/*
   cursus - Race series management program
   Copyright 2011-2014  Simon Arlott
    
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
    
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.
    
   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package eu.lp0.cursus.ui.component;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.persistence.Transient;
import javax.swing.JComboBox;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.eventbus.Subscribe;

import eu.lp0.cursus.db.dao.EntityDAO;
import eu.lp0.cursus.db.data.Entity;
import eu.lp0.cursus.i18n.LocaleChangeEvent;
import eu.lp0.cursus.i18n.Messages;
import eu.lp0.cursus.i18n.TranslatedEnum;

public abstract class EnumDatabaseColumn<T extends Entity, V extends Enum<?>> extends DatabaseColumn<T, Object> {
    private final MutableListComboBoxModel<Object> values;
    private final Class<V> type;
    private final boolean nullable;

    public EnumDatabaseColumn(String name, Class<V> type, boolean nullable) {
        super(name);
        this.type = type;
        this.nullable = nullable;
        values = new MutableListComboBoxModel<Object>(generateValues());
        cellRenderer = new StringDatabaseTableCellRenderer<T, Object>(this);
    }

    public EnumDatabaseColumn(String name, DatabaseWindow win, EntityDAO<T> dao, Class<V> type, boolean nullable) {
        super(name, win, dao);
        this.type = type;
        this.nullable = nullable;
        values = new MutableListComboBoxModel<Object>(generateValues());
        cellRenderer = new StringDatabaseTableCellRenderer<T, Object>(this);
        cellEditor = new DatabaseTableCellEditor<T, Object>(this, new JComboBox(values));
    }

    // Uses DatabaseTableModel's EventBus
    @Subscribe
    public final void updateEnumValues(LocaleChangeEvent lce) {
        if (TranslatedEnum.class.isAssignableFrom(type)) {
            values.replaceAll(generateValues());
        }
    }

    private List<Object> generateValues() {
        Iterable<Object> constants = Iterables
                .transform(Iterables.filter(Arrays.asList(type.getEnumConstants()), new Predicate<V>() {
                    @Override
                    public boolean apply(V input) {
                        return !isTransient(input);
                    }
                }), new Function<V, Object>() {
                    @Override
                    public Object apply(V input) {
                        return new WrappedEnum(input);
                    }
                });

        if (nullable) {
            return Lists.<Object>newArrayList(Iterables.concat(Collections.singletonList(""), constants)); //$NON-NLS-1$
        } else {
            return Lists.<Object>newArrayList(constants);
        }
    }

    public static boolean isTransient(Enum<?> value) {
        try {
            return value.getClass().getField(value.name()).isAnnotationPresent(Transient.class);
        } catch (SecurityException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected final Object getValue(T row, boolean editing) {
        V value = getEnumValue(row);
        if (value == null) {
            assert (nullable);
            return ""; //$NON-NLS-1$
        } else {
            return new WrappedEnum(value);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    protected final boolean setValue(T row, Object value) {
        if (value.equals("")) { //$NON-NLS-1$
            assert (nullable);
            value = null;
        } else {
            value = ((WrappedEnum) value).getValue();
        }
        return setEnumValue(row, (V) value);
    }

    protected abstract V getEnumValue(T row);

    protected abstract boolean setEnumValue(T row, V value);

    class WrappedEnum {
        private V value;

        public WrappedEnum(V value) {
            this.value = value;
        }

        public V getValue() {
            return value;
        }

        @Override
        public String toString() {
            if (value instanceof TranslatedEnum) {
                return Messages.getString(((TranslatedEnum) value).getMessagesKey());
            } else {
                return value.toString();
            }
        }
    }
}