View Javadoc

1   /*
2   
3       dsh-venn-tools  Command line tools for venn diagrams.
4       Copyright (c) 2010-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.venn.tools;
25  
26  import java.io.BufferedWriter;
27  import java.io.File;
28  import java.io.OutputStreamWriter;
29  import java.io.PrintWriter;
30  
31  import java.util.Iterator;
32  
33  import org.dishevelled.commandline.ArgumentList;
34  import org.dishevelled.commandline.CommandLine;
35  import org.dishevelled.commandline.CommandLineParseException;
36  import org.dishevelled.commandline.CommandLineParser;
37  import org.dishevelled.commandline.Switch;
38  import org.dishevelled.commandline.Usage;
39  
40  import org.dishevelled.commandline.argument.FileArgument;
41  
42  import org.dishevelled.venn.BinaryVennModel;
43  
44  import org.dishevelled.venn.swing.BinaryVennLabel;
45  
46  /**
47   * Venn two input files.
48   *
49   * @author  Michael Heuer
50   * @version $Revision$ $Date$
51   */
52  public final class Venn2
53      extends AbstractVennRunnable
54  {
55      /** First input file. */
56      private final File first;
57  
58      /** Second input file. */
59      private final File second;
60  
61      /** First only output file, if any. */
62      private final File firstOnly;
63  
64      /** Second only output file, if any. */
65      private final File secondOnly;
66  
67      /** Intersection output file, if any. */
68      private final File intersection;
69  
70      /** Union output file, if any. */
71      private final File union;
72  
73      /** Usage string. */
74      private static final String USAGE = "java Venn2 [args] first second";
75  
76  
77      /**
78       * Create a new venn 2 with the specified arguments.
79       *
80       * @param count true to output count(s) only
81       * @param header true to ouput header(s)
82       * @param first first input file
83       * @param second second input file
84       * @param firstOnly first only output file
85       * @param secondOnly second only output file
86       * @param intersection intersection output file
87       * @param union union output file
88       */
89      private Venn2(final boolean count,
90                    final boolean header,
91                    final File first,
92                    final File second,
93                    final File firstOnly,
94                    final File secondOnly,
95                    final File intersection,
96                    final File union)
97      {
98          super(count, header);
99          this.first = first;
100         this.second = second;
101 
102         // default all to stdout if none are specified
103         if ((firstOnly == null)
104             && (secondOnly == null)
105             && (intersection == null)
106             && (union == null))
107         {
108             this.firstOnly = STDOUT;
109             this.secondOnly = STDOUT;
110             this.intersection = STDOUT;
111             this.union = STDOUT;
112         }
113         else
114         {
115             this.firstOnly = firstOnly;
116             this.secondOnly = secondOnly;
117             this.intersection = intersection;
118             this.union = union;
119         }
120     }
121 
122 
123     /** {@inheritDoc} */
124     public void run()
125     {
126         BinaryVennLabel<String> label = new BinaryVennLabel<String>(first.getName(), read(first), second.getName(), read(second));
127         BinaryVennModel<String> model = label.getModel();
128 
129         // write individually to output files first
130         write(label.getFirstOnlyLabelText(), model.firstOnly(), firstOnly);
131         write(label.getSecondOnlyLabelText(), model.secondOnly(), secondOnly);
132         write(label.getIntersectionLabelText(), model.intersection(), intersection);
133         write(label.getUnionLabelText(), model.union(), union);
134 
135         // write collectively to stdout next
136         boolean fo = STDOUT.equals(firstOnly);
137         boolean so = STDOUT.equals(secondOnly);
138         boolean i = STDOUT.equals(intersection);
139         boolean u = STDOUT.equals(union);
140 
141         PrintWriter stdout = null;
142         stdout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
143         if (header())
144         {
145             write(fo, label.getFirstOnlyLabelText(), stdout);
146             write(so, label.getSecondOnlyLabelText(), stdout);
147             write(i, label.getIntersectionLabelText(), stdout);
148             write(u, label.getUnionLabelText(), stdout);
149             // todo trim extra \t
150             stdout.print("\n");
151         }
152 
153         if (count())
154         {
155             write(fo, model.firstOnly().size(), stdout);
156             write(so, model.secondOnly().size(), stdout);
157             write(i, model.intersection().size(), stdout);
158             write(u, model.union().size(), stdout);
159             // todo trim extra \t
160             stdout.print("\n");
161         }
162         else
163         {
164             boolean remaining = fo || so || i || u;
165             Iterator<String> foit = model.firstOnly().iterator();
166             Iterator<String> soit = model.secondOnly().iterator();
167             Iterator<String> iit = model.intersection().iterator();
168             Iterator<String> uit = model.union().iterator();
169             while (remaining)
170             {
171                 write(fo, foit, stdout);
172                 write(so, soit, stdout);
173                 write(i, iit, stdout);
174                 write(u, uit, stdout);
175                 remaining = (fo && foit.hasNext())
176                     || (so && soit.hasNext())
177                     || (i && iit.hasNext())
178                     || (u && uit.hasNext());
179 
180                 // todo trim extra \t
181                 stdout.print("\n");
182             }
183         }
184         try
185         {
186             stdout.close();
187         }
188         catch (Exception e)
189         {
190             // ignore
191         }
192     }
193 
194 
195     /**
196      * Main.
197      *
198      * @param args command line arguments
199      */
200     public static void main(final String[] args)
201     {
202         CommandLine commandLine = null;
203         ArgumentList arguments = null;
204         try
205         {
206             Switch help = new Switch("h", "help", "display help message");
207             Switch count = new Switch("c", "count", "output count(s) only");
208             Switch header = new Switch("e", "header", "output header(s)");
209             FileArgument firstOnly = new FileArgument("f", "first-only", "first only output file", false);
210             FileArgument secondOnly = new FileArgument("s", "second-only", "second only output file", false);
211             FileArgument intersection = new FileArgument("i", "intersection", "intersection output file", false);
212             FileArgument union = new FileArgument("u", "union", "union output file", false);
213 
214             arguments = new ArgumentList(help, count, header, firstOnly, secondOnly, intersection, union);
215             commandLine = new CommandLine(args);
216             CommandLineParser.parse(commandLine, arguments);
217 
218             if (help.wasFound())
219             {
220                 Usage.usage(USAGE, null, commandLine, arguments, System.out);
221             }
222             else
223             {
224                 if (args.length < 2)
225                 {
226                     throw new IllegalArgumentException("must have at least two file arguments, first and second input files");
227                 }
228                 File first = new File(args[args.length - 2]);
229                 File second = new File(args[args.length - 1]);
230                 if (first.getName().startsWith("-") || second.getName().startsWith("-"))
231                 {
232                     throw new IllegalArgumentException("must have at least two file arguments, first and second input files");
233                 }
234                 File f = defaultIfFound(firstOnly, first, second, STDOUT);
235                 File s = defaultIfFound(secondOnly, first, second, STDOUT);
236                 File i = defaultIfFound(intersection, first, second, STDOUT);
237                 File u = defaultIfFound(union, first, second, STDOUT);
238                 new Venn2(count.wasFound(), header.wasFound(), first, second, f, s, i, u).run();
239             }
240         }
241         catch (CommandLineParseException e)
242         {
243             Usage.usage(USAGE, e, commandLine, arguments, System.err);
244         }
245         catch (IllegalArgumentException e)
246         {
247             Usage.usage(USAGE, e, commandLine, arguments, System.err);
248         }
249     }
250 }