org.decisiondeck.jlp.LpVariable.java Source code

Java tutorial

Introduction

Here is the source code for org.decisiondeck.jlp.LpVariable.java

Source

/**
 * Copyright  2010-2011 cole Centrale Paris
 *
 *    This file is part of JLP.
 *
 *    JLP is free software: you can redistribute it and/or modify it under the
 *    terms of the GNU Lesser General Public License version 3 as published by
 *    the Free Software Foundation.
 *
 *    JLP 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 Lesser General Public License for
 *    more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with JLP. If not, see <http://www.gnu.org/licenses/>.
 */
package org.decisiondeck.jlp;

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

import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;

/**
 * <p>
 * An object which may be used to refer to a variable in a linear programming context. A variable in a linear program
 * often refers to other objects from some set. Consider for example the set of variables x_i with i being taken from
 * some set I. The indice i may refer to, e.g., a product, and x refer to the cost of that product. In such a case the
 * variable category could be the element "COST" from some enum type, and the reference object would be a product. Such
 * a variable {@link #equals(Object)} an other one when both categories are equal and the list of reference objects are
 * equal and in the same order. Equality tests for the category and reference object use their {@link #equals(Object)}
 * method.
 * </p>
 * <p>
 * Immutable if the category type and objects used as references are immutable. It is strongly suggested to use
 * immutable types as this object does not build defensive copies. As an exception to the immutability of this object,
 * it provides a setter for the string description of the variable. As it is intended to be used only for description
 * (e.g. debugging) purposes in the {@link #toString()} method, it is deemed acceptable to be less strict on the
 * immutability of the string parameter. However the recommanded practice is to set the string description right after
 * creation of the object, before doing anything else with it, and never change it afterwards. This has the effect of
 * defining this object as practically immutable.
 * </p>
 * <p>
 * A <code>null</code> variable category is <em>not</em> allowed (a simpler object could be created for that use case if
 * deemed useful). An empty reference set is allowed.
 * </p>
 * 
 * @author Olivier Cailloux
 * 
 * @param <T>
 *            a type used to describe the category an instance variable belongs to. Typically, an enum type. Should most
 *            preferably be immutable.
 */
public class LpVariable<T> {

    /** Not <code>null</code>. */
    private final T m_category;

    /**
     * May be <code>null</code> (no manual description, switch to automatic), may be empty (an empty description).
     */
    private String m_descr;

    /** Does not contain <code>null</code>. */
    private final List<Object> m_refs;

    /**
     * Builds a variable of the given category and with the provided references.
     * 
     * @param category
     *            not <code>null</code>.
     * @param references
     *            not <code>null</code>, no <code>null</code> reference inside. May be empty.
     */
    public LpVariable(T category, Object... references) {
        Preconditions.checkNotNull(category);
        Preconditions.checkNotNull(references);
        final List<Object> asList = Arrays.asList(references);
        final boolean hasNull = Iterables.any(asList, Predicates.isNull());
        if (hasNull) {
            throw new NullPointerException("Given references contain a null reference.");
        }
        m_category = category;
        m_refs = Collections.unmodifiableList(asList);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof LpVariable)) {
            return false;
        }
        LpVariable<?> other = (LpVariable<?>) obj;
        if (!m_category.equals(other.m_category)) {
            return false;
        }
        if (!m_refs.equals(other.m_refs)) {
            return false;
        }
        return true;
    }

    /**
     * @return not <code>null</code>.
     */
    public T getCategory() {
        return m_category;
    }

    /**
     * Retrieves the string set as a description of this object.
     * 
     * @return may be <code>null</code>, but not empty.
     */
    public String getDescription() {
        return m_descr;
    }

    /**
     * Retrieves a copy, or read-only view, of the references associated to the variable.
     * 
     * @return not <code>null</code>, may be empty. Contain no <code>null</code> references.
     */
    public List<Object> getReferences() {
        return m_refs;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (m_category.hashCode());
        result = prime * result + (m_refs.hashCode());
        return result;
    }

    /**
     * Sets the description to be used for this variable by the {@link #toString()} method. An empty string is accepted
     * and will produce an empty answer by the {@link #toString()} method. It is recommended to avoid empty strings and
     * strings empty after {@link String#trim()}ming.
     * 
     * @param description
     *            <code>null</code> to remove the manual description (use automatic description).
     */
    public void setDescription(String description) {
        m_descr = description;
    }

    /**
     * Returns a string description of this variable, using the description set by {@link #setDescription(String)} if it
     * is not <code>null</code> or auto-generated from the category and the references otherwise.
     */
    @Override
    public String toString() {
        if (m_descr != null) {
            return m_descr;
        }
        final ToStringHelper stringHelper = Objects.toStringHelper(this);
        stringHelper.add("Category", m_category);
        stringHelper.add("References", Arrays.toString(m_refs.toArray()));
        return stringHelper.toString();
    }

}