org.dishevelled.venn.tools.Venn.java Source code

Java tutorial

Introduction

Here is the source code for org.dishevelled.venn.tools.Venn.java

Source

/*
    
dsh-venn-tools  Command line tools for venn diagrams.
Copyright (c) 2010-2015 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.tools;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import org.dishevelled.bitset.MutableBitSet;
import org.dishevelled.bitset.ImmutableBitSet;

import org.dishevelled.commandline.ArgumentList;
import org.dishevelled.commandline.CommandLine;
import org.dishevelled.commandline.CommandLineParseException;
import org.dishevelled.commandline.CommandLineParser;
import org.dishevelled.commandline.Switch;
import org.dishevelled.commandline.Usage;

import org.dishevelled.commandline.argument.FileArgument;

import org.dishevelled.venn.VennModel;

import org.dishevelled.venn.model.VennModels;

/**
 * Venn an arbitrary number of input files.
 *
 * @author  Michael Heuer
 */
public final class Venn extends AbstractVennRunnable {
    /** List of input files. */
    private final List<File> inputFiles;

    /** Usage string. */
    private static final String USAGE = "java Venn [args] [input-files]";

    /**
     * Create a new venn with the specified arguments.
     *
     * @param count true to output count(s) only
     * @param header true to ouput header(s)
     * @param inputFiles list of input files, must not be null, must contain at least
     *    two input files, and must not contain more than 29 input files
     */
    private Venn(final boolean count, final boolean header, final List<File> inputFiles) {
        super(count, header);

        if (inputFiles == null) {
            throw new IllegalArgumentException("inputFiles must not be null");
        }
        if (inputFiles.size() < 2) {
            throw new IllegalArgumentException("inputFiles must contain at least two input files");
        }
        if (inputFiles.size() > 29) {
            throw new IllegalArgumentException("inputFiles must contain less than 30 input files");
        }
        this.inputFiles = inputFiles;
    }

    /** {@inheritDoc} */
    public void run() {
        int n = inputFiles.size();
        List<String> labels = new ArrayList<String>(n);
        List<Set<String>> sets = new ArrayList<Set<String>>(n);
        for (File inputFile : inputFiles) {
            labels.add(inputFile.getName());
            sets.add(read(inputFile));
        }
        VennModel<String> model = VennModels.createVennModel(sets);

        ImmutableMap.Builder<ImmutableBitSet, Set<String>> builder = ImmutableMap.builder();
        Set<Set<Integer>> powerSet = Sets.powerSet(range(n));
        for (Set<Integer> set : powerSet) {
            if (!set.isEmpty()) {
                ImmutableBitSet key = toImmutableBitSet(set);
                builder.put(key, model.exclusiveTo(first(key), additional(key)));
            }
        }
        Map<ImmutableBitSet, Set<String>> views = builder.build();

        PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        if (header()) {
            for (Map.Entry<ImmutableBitSet, Set<String>> entry : views.entrySet()) {
                write(true, buildLabel(labels, entry.getKey()), writer);
            }
            // todo trim extra \t
            writer.print("\n");
        }

        if (count()) {
            for (Map.Entry<ImmutableBitSet, Set<String>> entry : views.entrySet()) {
                write(true, entry.getValue().size(), writer);
            }
            // todo trim extra \t
            writer.print("\n");
        } else {
            List<Iterator<String>> iterators = new ArrayList<Iterator<String>>();

            for (Map.Entry<ImmutableBitSet, Set<String>> entry : views.entrySet()) {
                iterators.add(entry.getValue().iterator());
            }

            boolean done = false;
            while (!done) {
                boolean left = false;
                for (Iterator<String> iterator : iterators) {
                    if (iterator.hasNext()) {
                        writer.write(iterator.next());
                        left = true;
                    }
                    writer.write("\t");
                }
                // todo trim extra \t
                writer.print("\n");
                done = !left;
            }
        }
        try {
            writer.close();
        } catch (Exception e) {
            // ignore
        }
    }

    // copied from VennNode.java

    static String buildLabel(final List<String> labels, final ImmutableBitSet key) {
        int first = first(key);
        int[] additional = additional(key);
        StringBuilder sb = new StringBuilder();
        sb.append(labels.get(first));
        if (additional.length > 0) {
            for (int i = 0, size = additional.length - 1; i < size; i++) {
                sb.append(", ");
                sb.append(labels.get(additional[i]));
            }
            sb.append(" and ");
            sb.append(labels.get(additional[Math.max(0, additional.length - 1)]));
        }
        sb.append(" only");
        return sb.toString();
    }

    static ImmutableSet<Integer> range(final int n) {
        Set<Integer> range = Sets.newHashSet();
        for (int i = 0; i < n; i++) {
            range.add(Integer.valueOf(i));
        }
        return ImmutableSet.copyOf(range);
    }

    static int first(final ImmutableBitSet bitSet) {
        return (int) bitSet.nextSetBit(0L);
    }

    static int[] additional(final ImmutableBitSet bitSet) {
        int[] additional = new int[Math.max(0, (int) bitSet.cardinality() - 1)];
        int index = 0;
        long first = bitSet.nextSetBit(0);
        for (long value = bitSet.nextSetBit(first + 1); value >= 0L; value = bitSet.nextSetBit(value + 1)) {
            additional[index] = (int) value;
            index++;
        }
        return additional;
    }

    static int first(final Set<Integer> values) {
        if (values.isEmpty()) {
            return -1;
        }
        return values.iterator().next().intValue();
    }

    static int[] additional(final Set<Integer> values) {
        int[] additional = new int[Math.max(0, values.size() - 1)];
        int index = -1;
        for (Integer value : values) {
            if (index >= 0) {
                additional[index] = value.intValue();
            }
            index++;
        }
        return additional;
    }

    static ImmutableBitSet toImmutableBitSet(final Set<Integer> indices) {
        if (indices == null) {
            throw new IllegalArgumentException("indices must not be null");
        }
        if (indices.isEmpty()) {
            throw new IllegalArgumentException("indices must not be empty");
        }
        MutableBitSet mutableBitSet = new MutableBitSet(indices.size());
        for (Integer index : indices) {
            mutableBitSet.set(index);
        }
        mutableBitSet.trimTrailingZeros();
        return mutableBitSet.immutableCopy();
    }

    /**
     * Main.
     *
     * @param args command line arguments
     */
    public static void main(final String[] args) {
        CommandLine commandLine = null;
        ArgumentList arguments = null;
        try {
            Switch help = new Switch("h", "help", "display help message");
            Switch count = new Switch("c", "count", "output count(s) only");
            Switch header = new Switch("e", "header", "output header(s)");

            arguments = new ArgumentList(help, count, header);
            commandLine = new CommandLine(args);
            CommandLineParser.parse(commandLine, arguments);

            if (help.wasFound()) {
                Usage.usage(USAGE, null, commandLine, arguments, System.out);
            } else {
                List<File> inputFiles = new ArrayList<File>(args.length);
                for (int i = 0; i < args.length; i++) {
                    // ick.
                    if (!args[i].startsWith("-")) {
                        inputFiles.add(new File(args[i]));
                    }
                }
                new Venn(count.wasFound(), header.wasFound(), inputFiles).run();
            }
        } catch (CommandLineParseException e) {
            Usage.usage(USAGE, e, commandLine, arguments, System.err);
        } catch (IllegalArgumentException e) {
            Usage.usage(USAGE, e, commandLine, arguments, System.err);
        }
    }
}