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

fr.ird.observe.client.form.table.ContentTableMeta Maven / Gradle / Ivy

/*
 * #%L
 * ObServe Toolkit :: Common Client
 * %%
 * Copyright (C) 2008 - 2017 IRD, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
package fr.ird.observe.client.form.table;

import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.util.Set;
import java.util.function.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.util.ObjectUtil;
import org.nuiton.util.beans.BeanUtil;

/**
 * La définition d'une méta donnée d'un tableau, i.e la définition d'une
 * colonne.
 *
 * @param  le type de la donnée encapsulée par la colonne
 * @author Tony Chemit - [email protected]
 * @since 1.0
 */
public class ContentTableMeta implements Serializable {

    /** Logger. */
    private static final Log log = LogFactory.getLog(ContentTableMeta.class);

    private static final long serialVersionUID = 1L;

    /** le lastName de la meta (c'est le nom de la colonne) */
    protected final String name;

    /** le type de la meta (c'estle type de la colonne) */
    public final Class klass;

    /**
     * un drapeau pour savoir si on peut modifier cette méta lorsque l'objet
     * encapsulé existe déjà en base (pour pouvoir gérer les clefs métiers non
     * mutable)
     */
    protected final boolean unmodiableWhenExisting;

    /**
     * le descripteur de la méta (pour pouvoir récupérer et modifier la
     * colonne)
     */
    protected transient PropertyDescriptor propertyDescriptor;

    public ContentTableMeta(Class klass,
                            String name,
                            boolean unmodiableWhenExisting) {
        this.name = name;
        this.klass = klass;
        this.unmodiableWhenExisting = unmodiableWhenExisting;
        if (log.isDebugEnabled()) {
            log.debug(this + " : " + name + " : " + getType().getName());
        }
    }

    /** @return the name of this meta (will be used as columnName) */
    public String getName() {
        return name;
    }

    /** @return the type of this meta (will be used as columnClass) */
    public Class getType() {
        return getPropertyDescriptor().getPropertyType();
    }

    /**
     * @param model le modele qui contient la meta
     * @param bean  the bean to request
     * @param row   the current row
     * @return the value of the property of the given bean
     */
    public Object getValue(ContentTableModel model,
                           B bean,
                           int row) {
        try {
            return getPropertyDescriptor().getReadMethod().invoke(bean);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param model  the currentmodel
     * @param bean   the bean to modifiy
     * @param aValue the new value to set
     * @param row    the current row modified
     * @return {@code true} if bean data has changed, {@code false}
     * otherwise
     */
    public boolean setValue(ContentTableModel model,
                            B bean,
                            Object aValue,
                            int row) {
        Object oldValue = getValue(model, bean, row);
        /*try {
        getPropertyDescriptor().getWriteMethod().invoke(bean, aValue);
        } catch (Exception e) {
        throw new RuntimeException(e);
        }*/
        return oldValue == null && aValue != null ||
                oldValue != null && !oldValue.equals(aValue);
    }

    /**
     * Test if the property of a given bean is null.
     *
     * @param model le modele qui contient la meta
     * @param bean  the current bean to test
     * @param row   the current row
     * @return {@code true} if data is null for the given meta,
     * {@code false} otherwise.
     */
    public boolean isNullValue(ContentTableModel model,
                               B bean,
                               int row) {
        Object value = getValue(model, bean, row);
        return ObjectUtil.isNullValue(value);
    }

    /** @return the property descriptor of the meta */
    protected PropertyDescriptor getPropertyDescriptor() {
        if (propertyDescriptor == null) {
            Predicate predicate =
                    input -> BeanUtil.IS_READ_DESCRIPTOR.apply(input)
                            && name.equals(input.getName());
            Set descriptors = BeanUtil.getDescriptors(klass, predicate::test);
            Preconditions.checkState(!descriptors.isEmpty(),
                                     "could not find readable property " + name + " for bean " + klass);
            propertyDescriptor = Iterables.get(descriptors, 0);
        }
        return propertyDescriptor;
    }
}