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

org.dishevelled.venn.model.QuaternaryVennModelImpl Maven / Gradle / Ivy

There is a newer version: 1.2
Show newest version
/*

    dsh-venn  Lightweight components for venn diagrams.
    Copyright (c) 2009-2013 held jointly by the individual authors.

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 3 of the License, or (at
    your option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; with out 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 this library;  if not, write to the Free Software Foundation,
    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.

    > http://www.fsf.org/licensing/licenses/lgpl.html
    > http://www.opensource.org/licenses/lgpl-license.php

*/
package org.dishevelled.venn.model;

import java.util.HashSet;
import java.util.Set;

import java.util.HashMap;
import java.util.Map;

import com.google.common.collect.Sets;

import org.dishevelled.bitset.ImmutableBitSet;

import org.dishevelled.observable.ObservableSet;

import org.dishevelled.observable.impl.ObservableSetImpl;

import org.dishevelled.venn.QuaternaryVennModel;

import static org.dishevelled.venn.model.VennModelUtils.toImmutableBitSet;

/**
 * Immutable implementation of QuaternaryVennModel.
 *
 * @param  value type
 * @author  Michael Heuer
 * @version $Revision$ $Date$
 */
public final class QuaternaryVennModelImpl
    implements QuaternaryVennModel
{
    /** First view. */
    private final ObservableSet first;

    /** Second view. */
    private final ObservableSet second;

    /** Third view. */
    private final ObservableSet third;

    /** Fourth view. */
    private final ObservableSet fourth;

    /** First only view. */
    private final Set firstOnly;

    /** Second only view. */
    private final Set secondOnly;

    /** Third only view. */
    private final Set thirdOnly;

    /** Fourth only view. */
    private final Set fourthOnly;

    /** First second view. */
    private final Set firstSecond;

    /** First third view. */
    private final Set firstThird;

    /** First fourth view. */
    private final Set firstFourth;

    /** Second third view. */
    private final Set secondThird;

    /** Second fourth view. */
    private final Set secondFourth;

    /** Third fourth view. */
    private final Set thirdFourth;

    /** First second third view. */
    private final Set firstSecondThird;

    /** First second fourth view. */
    private final Set firstSecondFourth;

    /** First third fourth view. */
    private final Set firstThirdFourth;

    /** Second third fourth view. */
    private final Set secondThirdFourth;

    /** Intersection view. */
    private final Set intersection;

    /** Union view. */
    private final Set union;

    /** Selection view. */
    private final ObservableSet selection;

    /** Map of exclusive set views keyed by bit set. */
    private final Map> exclusives;


    /**
     * Create a new empty quaternary venn model.
     */
    public QuaternaryVennModelImpl()
    {
        this(new HashSet(), new HashSet(), new HashSet(), new HashSet());
    }

    /**
     * Create a new quaternary venn model with the specified sets.
     *
     * @param first first set, must not be null
     * @param second second set, must not be null
     * @param third third set, must not be null
     * @param fourth fourth set, must not be null
     */
    public QuaternaryVennModelImpl(final Set first,
                                    final Set second,
                                    final Set third,
                                    final Set fourth)
    {
        if (first == null)
        {
            throw new IllegalArgumentException("first must not be null");
        }
        if (second == null)
        {
            throw new IllegalArgumentException("second must not be null");
        }
        if (third == null)
        {
            throw new IllegalArgumentException("third must not be null");
        }
        if (fourth == null)
        {
            throw new IllegalArgumentException("fourth must not be null");
        }

        // todo  defensive copy?
        this.first = new ObservableSetImpl(first);
        this.second = new ObservableSetImpl(second);
        this.third = new ObservableSetImpl(third);
        this.fourth = new ObservableSetImpl(fourth);

        // alias
        ObservableSet f = this.first;
        ObservableSet s = this.second;
        ObservableSet t = this.third;
        ObservableSet r = this.fourth;
        firstOnly = Sets.difference(Sets.difference(Sets.difference(f, s), t), r); // f - s - t - r
        secondOnly = Sets.difference(Sets.difference(Sets.difference(s, f), t), r); // s - f - t - r
        thirdOnly = Sets.difference(Sets.difference(Sets.difference(t, f), s), r); // t - f - s - r
        fourthOnly = Sets.difference(Sets.difference(Sets.difference(r, f), s), t); // r - f - s - t
        firstSecond = Sets.difference(Sets.difference(Sets.intersection(f, s), t), r); // f n s - t - r
        firstThird = Sets.difference(Sets.difference(Sets.intersection(f, t), s), r); // f n t - s - r
        firstFourth = Sets.difference(Sets.difference(Sets.intersection(f, r), s), t); // f n r - s - t
        secondThird = Sets.difference(Sets.difference(Sets.intersection(s, t), f), r); // s n t - f - r
        secondFourth = Sets.difference(Sets.difference(Sets.intersection(s, r), f), t); // s n r - f - t
        thirdFourth = Sets.difference(Sets.difference(Sets.intersection(t, r), f), s); // t n r - f - s
        firstSecondThird = Sets.difference(Sets.intersection(f, Sets.intersection(s, t)), r); // f n s n t - r
        firstSecondFourth = Sets.difference(Sets.intersection(f, Sets.intersection(s, r)), t); // f n s n r - t
        firstThirdFourth = Sets.difference(Sets.intersection(f, Sets.intersection(t, r)), s); // f n t n r - s
        secondThirdFourth = Sets.difference(Sets.intersection(s, Sets.intersection(t, r)), f); // s n t n r - f
        intersection = Sets.intersection(f, Sets.intersection(s, Sets.intersection(t, r))); // f n s n t n r
        union = Sets.union(f, Sets.union(s, Sets.union(t, r))); // f u s u t u r
        selection = new SelectionView(union, f, s, t, r);

        exclusives = new HashMap>(15);

        exclusives.put(toImmutableBitSet(0), firstOnly);
        exclusives.put(toImmutableBitSet(1), secondOnly);
        exclusives.put(toImmutableBitSet(2), thirdOnly);
        exclusives.put(toImmutableBitSet(3), fourthOnly);

        exclusives.put(toImmutableBitSet(0, 1), firstSecond);
        exclusives.put(toImmutableBitSet(0, 2), firstThird);
        exclusives.put(toImmutableBitSet(0, 3), firstFourth);
        exclusives.put(toImmutableBitSet(1, 2), secondThird);
        exclusives.put(toImmutableBitSet(1, 3), secondFourth);
        exclusives.put(toImmutableBitSet(2, 3), thirdFourth);

        exclusives.put(toImmutableBitSet(0, 1, 2), firstSecondThird);
        exclusives.put(toImmutableBitSet(0, 1, 3), firstSecondFourth);
        exclusives.put(toImmutableBitSet(0, 2, 3), firstThirdFourth);
        exclusives.put(toImmutableBitSet(1, 2, 3), secondThirdFourth);

        exclusives.put(toImmutableBitSet(0, 1, 2, 3), intersection);
    }


    /** {@inheritDoc} */
    public int size()
    {
        return 4;
    }

    /** {@inheritDoc} */
    public ObservableSet first()
    {
        return first;
    }

    /** {@inheritDoc} */
    public ObservableSet second()
    {
        return second;
    }

    /** {@inheritDoc} */
    public ObservableSet third()
    {
        return third;
    }

    /** {@inheritDoc} */
    public ObservableSet fourth()
    {
        return fourth;
    }

    /** {@inheritDoc} */
    public Set get(final int index)
    {
        if (index < 0 || index > 3)
        {
            throw new IndexOutOfBoundsException("index out of bounds");
        }
        switch (index)
        {
        case 0:
            return first;
        case 1:
            return second;
        case 2:
            return third;
        case 3:
            return fourth;
        default:
            break;
        }
        throw new IllegalStateException("invalid index " + index);
    }

    /** {@inheritDoc} */
    public Set firstOnly()
    {
        return firstOnly;
    }

    /** {@inheritDoc} */
    public Set secondOnly()
    {
        return secondOnly;
    }

    /** {@inheritDoc} */
    public Set thirdOnly()
    {
        return thirdOnly;
    }

    /** {@inheritDoc} */
    public Set fourthOnly()
    {
        return fourthOnly;
    }

    /** {@inheritDoc} */
    public Set firstSecond()
    {
        return firstSecond;
    }

    /** {@inheritDoc} */
    public Set firstThird()
    {
        return firstThird;
    }

    /** {@inheritDoc} */
    public Set firstFourth()
    {
        return firstFourth;
    }

    /** {@inheritDoc} */
    public Set secondThird()
    {
        return secondThird;
    }

    /** {@inheritDoc} */
    public Set secondFourth()
    {
        return secondFourth;
    }

    /** {@inheritDoc} */
    public Set thirdFourth()
    {
        return thirdFourth;
    }

    /** {@inheritDoc} */
    public Set firstSecondThird()
    {
        return firstSecondThird;
    }

    /** {@inheritDoc} */
    public Set firstSecondFourth()
    {
        return firstSecondFourth;
    }

    /** {@inheritDoc} */
    public Set firstThirdFourth()
    {
        return firstThirdFourth;
    }

    /** {@inheritDoc} */
    public Set secondThirdFourth()
    {
        return secondThirdFourth;
    }

    /** {@inheritDoc} */
    public Set intersection()
    {
        return intersection;
    }

    /** {@inheritDoc} */
    public Set exclusiveTo(final int index, final int... additional)
    {
        int maxIndex = size() - 1;
        if (index < 0 || index > maxIndex)
        {
            throw new IndexOutOfBoundsException("index out of bounds");
        }
        if (additional != null && additional.length > 0)
        {
            if (additional.length > maxIndex)
            {
                throw new IndexOutOfBoundsException("too many indices provided");
            }
            for (int i = 0, size = additional.length; i < size; i++)
            {
                if (additional[i] < 0 || additional[i] > maxIndex)
                {
                    throw new IndexOutOfBoundsException("additional index [" + i + "] out of bounds");
                }
            }
        }
        return exclusives.get(toImmutableBitSet(index, additional));
    }

    /** {@inheritDoc} */
    public Set union()
    {
        return union;
    }

    /** {@inheritDoc} */
    public ObservableSet selection()
    {
        return selection;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy