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.QuaternaryVennModel;
43  
44  import org.dishevelled.venn.swing.QuaternaryVennLabel;
45  
46  /**
47   * Venn four input files.
48   *
49   * @author  Michael Heuer
50   * @version $Revision$ $Date$
51   */
52  public final class Venn4
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      /** Third input file. */
62      private final File third;
63  
64      /** Fourth input file. */
65      private final File fourth;
66  
67      /** First only output file, if any. */
68      private final File firstOnly;
69  
70      /** Second only output file, if any. */
71      private final File secondOnly;
72  
73      /** Third only output file, if any. */
74      private final File thirdOnly;
75  
76      /** Fourth only output file, if any. */
77      private final File fourthOnly;
78  
79      /** First second output file, if any. */
80      private final File firstSecond;
81  
82      /** First third output file, if any. */
83      private final File firstThird;
84  
85      /** First fourth output file, if any. */
86      private final File firstFourth;
87  
88      /** Second third output file, if any. */
89      private final File secondThird;
90  
91      /** Second fourth output file, if any. */
92      private final File secondFourth;
93  
94      /** Third fourth output file, if any. */
95      private final File thirdFourth;
96  
97      /** First second third output file, if any. */
98      private final File firstSecondThird;
99  
100     /** First second fourth output file, if any. */
101     private final File firstSecondFourth;
102 
103     /** First third fourth output file, if any. */
104     private final File firstThirdFourth;
105 
106     /** Second third fourth output file, if any. */
107     private final File secondThirdFourth;
108 
109     /** Intersection output file, if any. */
110     private final File intersection;
111 
112     /** Union output file, if any. */
113     private final File union;
114 
115     /** Usage string. */
116     private static final String USAGE = "java Venn4 [args] first second third fourth";
117 
118 
119     /**
120      * Create a new venn 4 with the specified arguments.
121      *
122      * @param count true to output count(s) only
123      * @param header true to ouput header(s)
124      * @param first first input file
125      * @param second second input file
126      * @param third third input file
127      * @param fourth fourth input file
128      * @param firstOnly first only output file
129      * @param secondOnly second only output file
130      * @param thirdOnly third only output file
131      * @param fourthOnly fourth only output file
132      * @param firstSecond first second output file
133      * @param firstThird first third output file
134      * @param firstFourth first fourth output file
135      * @param secondThird second third output file
136      * @param secondFourth second fourth output file
137      * @param thirdFourth third fourth output
138      * @param firstSecondThird first second third output file
139      * @param firstSecondFourth first second fourth output file
140      * @param firstThirdFourth first third fourth output file
141      * @param secondThirdFourth second third fourth output file
142      * @param intersection intersection output file
143      * @param union union output file
144      */
145     private Venn4(final boolean count,
146                   final boolean header,
147                   final File first,
148                   final File second,
149                   final File third,
150                   final File fourth,
151                   final File firstOnly,
152                   final File secondOnly,
153                   final File thirdOnly,
154                   final File fourthOnly,
155                   final File firstSecond,
156                   final File firstThird,
157                   final File firstFourth,
158                   final File secondThird,
159                   final File secondFourth,
160                   final File firstSecondThird,
161                   final File firstSecondFourth,
162                   final File firstThirdFourth,
163                   final File secondThirdFourth,
164                   final File thirdFourth,
165                   final File intersection,
166                   final File union)
167     {
168         super(count, header);
169         this.first = first;
170         this.second = second;
171         this.third = third;
172         this.fourth = fourth;
173 
174         // default all to stdout if none are specified
175         if ((firstOnly == null)
176             && (secondOnly == null)
177             && (thirdOnly == null)
178             && (fourthOnly == null)
179             && (firstSecond == null)
180             && (firstThird == null)
181             && (firstFourth == null)
182             && (secondThird == null)
183             && (secondFourth == null)
184             && (thirdFourth == null)
185             && (firstSecondThird == null)
186             && (firstSecondFourth == null)
187             && (firstThirdFourth == null)
188             && (secondThirdFourth == null)
189             && (intersection == null)
190             && (union == null))
191         {
192             this.firstOnly = STDOUT;
193             this.secondOnly = STDOUT;
194             this.thirdOnly = STDOUT;
195             this.fourthOnly = STDOUT;
196             this.firstSecond = STDOUT;
197             this.firstThird = STDOUT;
198             this.firstFourth = STDOUT;
199             this.secondThird = STDOUT;
200             this.secondFourth = STDOUT;
201             this.thirdFourth = STDOUT;
202             this.firstSecondThird = STDOUT;
203             this.firstSecondFourth = STDOUT;
204             this.firstThirdFourth = STDOUT;
205             this.secondThirdFourth = STDOUT;
206             this.intersection = STDOUT;
207             this.union = STDOUT;
208         }
209         else
210         {
211             this.firstOnly = firstOnly;
212             this.secondOnly = secondOnly;
213             this.thirdOnly = thirdOnly;
214             this.fourthOnly = fourthOnly;
215             this.firstSecond = firstSecond;
216             this.firstThird = firstThird;
217             this.firstFourth = firstFourth;
218             this.secondThird = secondThird;
219             this.secondFourth = secondFourth;
220             this.thirdFourth = thirdFourth;
221             this.firstSecondThird = firstSecondThird;
222             this.firstSecondFourth = firstSecondFourth;
223             this.firstThirdFourth = firstThirdFourth;
224             this.secondThirdFourth = secondThirdFourth;
225             this.intersection = intersection;
226             this.union = union;
227         }
228     }
229 
230 
231     /** {@inheritDoc} */
232     public void run()
233     {
234         QuaternaryVennLabel<String> label = new QuaternaryVennLabel<String>(first.getName(), read(first), second.getName(), read(second), third.getName(), read(third), fourth.getName(), read(fourth));
235         QuaternaryVennModel<String> model = label.getModel();
236 
237         // write individually to output files first
238         write(label.getFirstOnlyLabelText(), model.firstOnly(), firstOnly);
239         write(label.getSecondOnlyLabelText(), model.secondOnly(), secondOnly);
240         write(label.getThirdOnlyLabelText(), model.thirdOnly(), thirdOnly);
241         write(label.getFourthOnlyLabelText(), model.fourthOnly(), fourthOnly);
242         write(label.getFirstSecondLabelText(), model.firstSecond(), firstSecond);
243         write(label.getFirstThirdLabelText(), model.firstThird(), firstThird);
244         write(label.getFirstFourthLabelText(), model.firstFourth(), firstFourth);
245         write(label.getSecondThirdLabelText(), model.secondThird(), secondThird);
246         write(label.getSecondFourthLabelText(), model.secondFourth(), secondFourth);
247         write(label.getThirdFourthLabelText(), model.thirdFourth(), thirdFourth);
248         write(label.getFirstSecondThirdLabelText(), model.firstSecondThird(), firstSecondThird);
249         write(label.getFirstSecondFourthLabelText(), model.firstSecondFourth(), firstSecondFourth);
250         write(label.getFirstThirdFourthLabelText(), model.firstThirdFourth(), firstThirdFourth);
251         write(label.getSecondThirdFourthLabelText(), model.secondThirdFourth(), secondThirdFourth);
252         write(label.getIntersectionLabelText(), model.intersection(), intersection);
253         write(label.getUnionLabelText(), model.union(), union);
254 
255         // write collectively to stdout next
256         boolean fo = STDOUT.equals(firstOnly);
257         boolean so = STDOUT.equals(secondOnly);
258         boolean to = STDOUT.equals(thirdOnly);
259         boolean ro = STDOUT.equals(fourthOnly);
260         boolean fs = STDOUT.equals(firstSecond);
261         boolean ft = STDOUT.equals(firstThird);
262         boolean fr = STDOUT.equals(firstFourth);
263         boolean st = STDOUT.equals(secondThird);
264         boolean sr = STDOUT.equals(secondFourth);
265         boolean tr = STDOUT.equals(thirdFourth);
266         boolean fst = STDOUT.equals(firstSecondThird);
267         boolean fsr = STDOUT.equals(firstSecondFourth);
268         boolean ftr = STDOUT.equals(firstThirdFourth);
269         boolean str = STDOUT.equals(secondThirdFourth);
270         boolean i = STDOUT.equals(intersection);
271         boolean u = STDOUT.equals(union);
272 
273         PrintWriter stdout = null;
274         stdout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
275         if (header())
276         {
277             write(fo, label.getFirstOnlyLabelText(), stdout);
278             write(so, label.getSecondOnlyLabelText(), stdout);
279             write(to, label.getThirdOnlyLabelText(), stdout);
280             write(ro, label.getFourthOnlyLabelText(), stdout);
281             write(fs, label.getFirstSecondLabelText(), stdout);
282             write(ft, label.getFirstThirdLabelText(), stdout);
283             write(fr, label.getFirstFourthLabelText(), stdout);
284             write(st, label.getSecondThirdLabelText(), stdout);
285             write(sr, label.getSecondFourthLabelText(), stdout);
286             write(tr, label.getThirdFourthLabelText(), stdout);
287             write(fst, label.getFirstSecondThirdLabelText(), stdout);
288             write(fsr, label.getFirstSecondFourthLabelText(), stdout);
289             write(ftr, label.getFirstThirdFourthLabelText(), stdout);
290             write(str, label.getSecondThirdFourthLabelText(), stdout);
291             write(i, label.getIntersectionLabelText(), stdout);
292             write(u, label.getUnionLabelText(), stdout);
293             // todo trim extra \t
294             stdout.print("\n");
295         }
296 
297         if (count())
298         {
299             write(fo, model.firstOnly().size(), stdout);
300             write(so, model.secondOnly().size(), stdout);
301             write(to, model.thirdOnly().size(), stdout);
302             write(ro, model.fourthOnly().size(), stdout);
303             write(fs, model.firstSecond().size(), stdout);
304             write(ft, model.firstThird().size(), stdout);
305             write(fr, model.firstFourth().size(), stdout);
306             write(st, model.secondThird().size(), stdout);
307             write(sr, model.secondFourth().size(), stdout);
308             write(tr, model.thirdFourth().size(), stdout);
309             write(fst, model.firstSecondThird().size(), stdout);
310             write(fsr, model.firstSecondFourth().size(), stdout);
311             write(ftr, model.firstThirdFourth().size(), stdout);
312             write(str, model.secondThirdFourth().size(), stdout);
313             write(i, model.intersection().size(), stdout);
314             write(u, model.union().size(), stdout);
315             // todo trim extra \t
316             stdout.print("\n");
317         }
318         else
319         {
320             boolean remaining = fo || so || to || ro || fs || ft || fr || st || sr || tr || fst || fsr || ftr || str || i || u;
321             Iterator<String> foit = model.firstOnly().iterator();
322             Iterator<String> soit = model.secondOnly().iterator();
323             Iterator<String> toit = model.thirdOnly().iterator();
324             Iterator<String> roit = model.fourthOnly().iterator();
325             Iterator<String> fsit = model.firstSecond().iterator();
326             Iterator<String> ftit = model.firstThird().iterator();
327             Iterator<String> frit = model.firstFourth().iterator();
328             Iterator<String> stit = model.secondThird().iterator();
329             Iterator<String> srit = model.secondFourth().iterator();
330             Iterator<String> trit = model.thirdFourth().iterator();
331             Iterator<String> fstit = model.firstSecondThird().iterator();
332             Iterator<String> fsrit = model.firstSecondFourth().iterator();
333             Iterator<String> ftrit = model.firstThirdFourth().iterator();
334             Iterator<String> strit = model.secondThirdFourth().iterator();
335             Iterator<String> iit = model.intersection().iterator();
336             Iterator<String> uit = model.union().iterator();
337             while (remaining)
338             {
339                 write(fo, foit, stdout);
340                 write(so, soit, stdout);
341                 write(to, toit, stdout);
342                 write(ro, foit, stdout);
343                 write(fs, fsit, stdout);
344                 write(ft, ftit, stdout);
345                 write(fr, frit, stdout);
346                 write(st, stit, stdout);
347                 write(sr, srit, stdout);
348                 write(tr, trit, stdout);
349                 write(fst, fstit, stdout);
350                 write(fsr, fsrit, stdout);
351                 write(ftr, ftrit, stdout);
352                 write(str, strit, stdout);
353                 write(i, iit, stdout);
354                 write(u, uit, stdout);
355                 remaining = (fo && foit.hasNext())
356                     || (so && soit.hasNext())
357                     || (to && toit.hasNext())
358                     || (ro && roit.hasNext())
359                     || (fs && fsit.hasNext())
360                     || (ft && ftit.hasNext())
361                     || (fr && frit.hasNext())
362                     || (st && stit.hasNext())
363                     || (sr && srit.hasNext())
364                     || (tr && trit.hasNext())
365                     || (fst && fstit.hasNext())
366                     || (fsr && fsrit.hasNext())
367                     || (ftr && ftrit.hasNext())
368                     || (str && strit.hasNext())
369                     || (i && iit.hasNext())
370                     || (u && uit.hasNext());
371 
372                 // todo trim extra \t
373                 stdout.print("\n");
374             }
375         }
376         try
377         {
378             stdout.close();
379         }
380         catch (Exception e)
381         {
382             // ignore
383         }
384     }
385 
386 
387     /**
388      * Main.
389      *
390      * @param args command line arguments
391      */
392     public static void main(final String[] args)
393     {
394         CommandLine commandLine = null;
395         ArgumentList arguments = null;
396         try
397         {
398             Switch help = new Switch("h", "help", "display help message");
399             Switch count = new Switch("c", "count", "output count(s) only");
400             Switch header = new Switch("e", "header", "output header(s)");
401             FileArgument firstOnly = new FileArgument("f", "first-only", "first only output file", false);
402             FileArgument secondOnly = new FileArgument("s", "second-only", "second only output file", false);
403             FileArgument thirdOnly = new FileArgument("t", "third-only", "third only output file", false);
404             FileArgument fourthOnly = new FileArgument("r", "fourth-only", "fourth only output file", false);
405             FileArgument firstSecond = new FileArgument("j", "first-second", "first second output file", false);
406             FileArgument firstThird = new FileArgument("k", "first-third", "first third output file", false);
407             FileArgument firstFourth = new FileArgument("l", "first-fourth", "first fourth output file", false);
408             FileArgument secondThird = new FileArgument("m", "second-third", "second third output file", false);
409             FileArgument secondFourth = new FileArgument("n", "second-fourth", "second fourth output file", false);
410             FileArgument thirdFourth = new FileArgument("o", "third-fourth", "third fourth output file", false);
411             FileArgument firstSecondThird = new FileArgument("p", "first-second-third", "first second third output file", false);
412             FileArgument firstSecondFourth = new FileArgument("q", "first-second-fourth", "first second fourth output file", false);
413             FileArgument firstThirdFourth = new FileArgument("v", "first-third-fourth", "first third fourth output file", false);
414             FileArgument secondThirdFourth = new FileArgument("w", "second-third-fourth", "second third fourth output file", false);
415             FileArgument intersection = new FileArgument("i", "intersection", "intersection output file", false);
416             FileArgument union = new FileArgument("u", "union", "union output file", false);
417 
418             arguments = new ArgumentList(help, count, header, firstOnly, secondOnly, thirdOnly, fourthOnly,
419                                          firstSecond, firstThird, firstFourth, secondThird, secondFourth, thirdFourth,
420                                          firstSecondThird, firstSecondFourth, firstThirdFourth, secondThirdFourth, intersection, union);
421             commandLine = new CommandLine(args);
422             CommandLineParser.parse(commandLine, arguments);
423 
424             if (help.wasFound())
425             {
426                 Usage.usage(USAGE, null, commandLine, arguments, System.out);
427             }
428             else
429             {
430                 if (args.length < 4)
431                 {
432                     throw new IllegalArgumentException("must have at least four file arguments, first, second, third and fourth input files");
433                 }
434                 File first = new File(args[args.length - 4]);
435                 File second = new File(args[args.length - 3]);
436                 File third = new File(args[args.length - 2]);
437                 File fourth = new File(args[args.length - 1]);
438                 if (first.getName().startsWith("-") || second.getName().startsWith("-") || third.getName().startsWith("-") || fourth.getName().startsWith("-"))
439                 {
440                     throw new IllegalArgumentException("must have at least four file arguments, first, second, third and fourth input files");
441                 }
442                 File f = defaultIfFound(firstOnly, first, second, third, fourth, STDOUT);
443                 File s = defaultIfFound(secondOnly, first, second, third, fourth, STDOUT);
444                 File t = defaultIfFound(thirdOnly, first, second, third, fourth, STDOUT);
445                 File r = defaultIfFound(fourthOnly, first, second, third, fourth, STDOUT);
446                 File j = defaultIfFound(firstSecond, first, second, third, fourth, STDOUT);
447                 File k = defaultIfFound(firstThird, first, second, third, fourth, STDOUT);
448                 File l = defaultIfFound(firstFourth, first, second, third, fourth, STDOUT);
449                 File m = defaultIfFound(secondThird, first, second, third, fourth, STDOUT);
450                 File n = defaultIfFound(secondFourth, first, second, third, fourth, STDOUT);
451                 File o = defaultIfFound(thirdFourth, first, second, third, fourth, STDOUT);
452                 File p = defaultIfFound(firstSecondThird, first, second, third, fourth, STDOUT);
453                 File q = defaultIfFound(firstSecondFourth, first, second, third, fourth, STDOUT);
454                 File v = defaultIfFound(firstThirdFourth, first, second, third, fourth, STDOUT);
455                 File w = defaultIfFound(secondThirdFourth, first, second, third, fourth, STDOUT);
456                 File i = defaultIfFound(intersection, first, second, third,  fourth, STDOUT);
457                 File u = defaultIfFound(union, first, second, third, fourth, STDOUT);
458                 new Venn4(count.wasFound(), header.wasFound(), first, second, third, fourth, f, s, t, r, j, k, l, m, n, o, p, q, v, w, i, u).run();
459             }
460         }
461         catch (CommandLineParseException e)
462         {
463             Usage.usage(USAGE, e, commandLine, arguments, System.err);
464         }
465         catch (IllegalArgumentException e)
466         {
467             Usage.usage(USAGE, e, commandLine, arguments, System.err);
468         }
469     }
470 }