src/core/net/sf/basedb/util/bfs/AnnotationWriter.java

Code
Comments
Other
Rev Date Author Line
5193 27 Nov 09 nicklas 1 /**
5193 27 Nov 09 nicklas 2   $Id$
5193 27 Nov 09 nicklas 3
5193 27 Nov 09 nicklas 4   Copyright (C) 2009 Nicklas Nordborg
5193 27 Nov 09 nicklas 5
5193 27 Nov 09 nicklas 6   This file is part of BASE - BioArray Software Environment.
5193 27 Nov 09 nicklas 7   Available at http://base.thep.lu.se/
5193 27 Nov 09 nicklas 8
5193 27 Nov 09 nicklas 9   BASE is free software; you can redistribute it and/or
5193 27 Nov 09 nicklas 10   modify it under the terms of the GNU General Public License
5193 27 Nov 09 nicklas 11   as published by the Free Software Foundation; either version 3
5193 27 Nov 09 nicklas 12   of the License, or (at your option) any later version.
5193 27 Nov 09 nicklas 13
5193 27 Nov 09 nicklas 14   BASE is distributed in the hope that it will be useful,
5193 27 Nov 09 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
5193 27 Nov 09 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5193 27 Nov 09 nicklas 17   GNU General Public License for more details.
5193 27 Nov 09 nicklas 18
5193 27 Nov 09 nicklas 19   You should have received a copy of the GNU General Public License
5193 27 Nov 09 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
5193 27 Nov 09 nicklas 21 */
5193 27 Nov 09 nicklas 22 package net.sf.basedb.util.bfs;
5193 27 Nov 09 nicklas 23
5384 13 Aug 10 nicklas 24 import java.io.FileNotFoundException;
5219 18 Jan 10 nicklas 25 import java.io.FileOutputStream;
5219 18 Jan 10 nicklas 26 import java.io.IOException;
5198 15 Dec 09 nicklas 27 import java.io.OutputStream;
5198 15 Dec 09 nicklas 28 import java.io.OutputStreamWriter;
5193 27 Nov 09 nicklas 29 import java.io.Writer;
7714 21 May 19 nicklas 30 import java.nio.charset.StandardCharsets;
5193 27 Nov 09 nicklas 31 import java.util.HashSet;
5193 27 Nov 09 nicklas 32 import java.util.Set;
5193 27 Nov 09 nicklas 33
5210 11 Jan 10 nicklas 34 import net.sf.basedb.core.File;
5193 27 Nov 09 nicklas 35 import net.sf.basedb.util.encode.TabCrLfEncoderDecoder;
5193 27 Nov 09 nicklas 36 import net.sf.basedb.util.export.TableWriter;
5193 27 Nov 09 nicklas 37
5193 27 Nov 09 nicklas 38 /**
5193 27 Nov 09 nicklas 39
5193 27 Nov 09 nicklas 40   @author Nicklas
5193 27 Nov 09 nicklas 41   @version 2.15
5193 27 Nov 09 nicklas 42   @base.modified $Date$
5193 27 Nov 09 nicklas 43 */
5193 27 Nov 09 nicklas 44 public class AnnotationWriter
5193 27 Nov 09 nicklas 45   extends TableWriter
5193 27 Nov 09 nicklas 46 {
5193 27 Nov 09 nicklas 47
5198 15 Dec 09 nicklas 48   /**
5198 15 Dec 09 nicklas 49     Utility method for creating an annotation writer when you have an
5198 15 Dec 09 nicklas 50     output stream.
5198 15 Dec 09 nicklas 51     @param out The output stream the annotation writer should print to
5198 15 Dec 09 nicklas 52     @param filename Optional, the name of the file the output stream
5198 15 Dec 09 nicklas 53       is printing to
5198 15 Dec 09 nicklas 54   */
5198 15 Dec 09 nicklas 55   public static AnnotationWriter create(OutputStream out, String filename)
5198 15 Dec 09 nicklas 56   {
5384 13 Aug 10 nicklas 57     if (out == null) throw new NullPointerException("out");
5198 15 Dec 09 nicklas 58     AnnotationWriter writer = new AnnotationWriter(
7714 21 May 19 nicklas 59         new OutputStreamWriter(out, StandardCharsets.UTF_8));
5198 15 Dec 09 nicklas 60     writer.setFilename(filename);
5198 15 Dec 09 nicklas 61     return writer;
5198 15 Dec 09 nicklas 62   }
5198 15 Dec 09 nicklas 63   
5210 11 Jan 10 nicklas 64   /**
5210 11 Jan 10 nicklas 65     Utility method for creating an annotation writer to a file in the BASE
5210 11 Jan 10 nicklas 66     file system. The character set and MIME type on the file are automatically 
5210 11 Jan 10 nicklas 67     updated.
5210 11 Jan 10 nicklas 68     @param file The file in the BASE file system
5210 11 Jan 10 nicklas 69   */
5210 11 Jan 10 nicklas 70   public static AnnotationWriter create(File file)
5210 11 Jan 10 nicklas 71   {
5384 13 Aug 10 nicklas 72     if (file == null) throw new NullPointerException("file");
5210 11 Jan 10 nicklas 73     file.setCharacterSet("UTF-8");
5210 11 Jan 10 nicklas 74     file.setMimeType("text/plain");
5210 11 Jan 10 nicklas 75     return create(file.getUploadStream(false), file.getName());
5210 11 Jan 10 nicklas 76   }
5219 18 Jan 10 nicklas 77
5219 18 Jan 10 nicklas 78   /**
5219 18 Jan 10 nicklas 79     Utility method for creating an annotation writer to a file in the native
5219 18 Jan 10 nicklas 80     file system. If the file doesn't exists, it is created.
5219 18 Jan 10 nicklas 81     @param file The file in the native file system
5219 18 Jan 10 nicklas 82   */
5219 18 Jan 10 nicklas 83   public static AnnotationWriter create(java.io.File file)
5219 18 Jan 10 nicklas 84     throws IOException
5219 18 Jan 10 nicklas 85   {
5384 13 Aug 10 nicklas 86     if (file == null) throw new NullPointerException("file");
5384 13 Aug 10 nicklas 87     if (!file.createNewFile() && !file.exists()) 
5384 13 Aug 10 nicklas 88     {
5384 13 Aug 10 nicklas 89       throw new FileNotFoundException(file.toString());
5384 13 Aug 10 nicklas 90     }
5219 18 Jan 10 nicklas 91     return create(new FileOutputStream(file), file.getName());
5219 18 Jan 10 nicklas 92   }
5219 18 Jan 10 nicklas 93
5210 11 Jan 10 nicklas 94   
5198 15 Dec 09 nicklas 95   private String filename;
5193 27 Nov 09 nicklas 96   private boolean hasPrintedHeaders;
5193 27 Nov 09 nicklas 97   private int columnCount = -1;
5193 27 Nov 09 nicklas 98   private Set<Integer> usedIds;
5193 27 Nov 09 nicklas 99   
5193 27 Nov 09 nicklas 100   public AnnotationWriter(Writer out)
5193 27 Nov 09 nicklas 101   {
5193 27 Nov 09 nicklas 102     super(out);
5193 27 Nov 09 nicklas 103     super.setDataSeparator("\t");
5193 27 Nov 09 nicklas 104     super.setNullValue("");
5193 27 Nov 09 nicklas 105     super.setEncoder(new TabCrLfEncoderDecoder(false));
5193 27 Nov 09 nicklas 106     this.usedIds = new HashSet<Integer>();
5193 27 Nov 09 nicklas 107   }
5193 27 Nov 09 nicklas 108   
5193 27 Nov 09 nicklas 109   /**
5198 15 Dec 09 nicklas 110     Get the file name that this writer is printing to.
5198 15 Dec 09 nicklas 111     @return The file name or null if not known
5198 15 Dec 09 nicklas 112   */
5198 15 Dec 09 nicklas 113   public String getFilename()
5198 15 Dec 09 nicklas 114   {
5198 15 Dec 09 nicklas 115     return filename;
5198 15 Dec 09 nicklas 116   }
5198 15 Dec 09 nicklas 117   
5198 15 Dec 09 nicklas 118   /**
5198 15 Dec 09 nicklas 119     Set the file name that this writer is printing to.
5198 15 Dec 09 nicklas 120   */
5198 15 Dec 09 nicklas 121   public void setFilename(String filename)
5198 15 Dec 09 nicklas 122   {
5198 15 Dec 09 nicklas 123     this.filename = filename;
5198 15 Dec 09 nicklas 124   }
5198 15 Dec 09 nicklas 125
5198 15 Dec 09 nicklas 126   
5198 15 Dec 09 nicklas 127   /**
5193 27 Nov 09 nicklas 128     Checks if headers has already been printed or not.
5193 27 Nov 09 nicklas 129   */
5193 27 Nov 09 nicklas 130   public boolean hasPrintedHeaders()
5193 27 Nov 09 nicklas 131   {
5193 27 Nov 09 nicklas 132     return hasPrintedHeaders;
5193 27 Nov 09 nicklas 133   }
5193 27 Nov 09 nicklas 134   
5193 27 Nov 09 nicklas 135   /**
5193 27 Nov 09 nicklas 136     Get the number of data columns. This information is only
5193 27 Nov 09 nicklas 137     available after the headers has been printed.
5193 27 Nov 09 nicklas 138     
5193 27 Nov 09 nicklas 139     @return The number of column, or -1 if the headers has not yet been
5193 27 Nov 09 nicklas 140       printed
5193 27 Nov 09 nicklas 141   */
5193 27 Nov 09 nicklas 142   public int getColumnCount()
5193 27 Nov 09 nicklas 143   {
5193 27 Nov 09 nicklas 144     return columnCount;
5193 27 Nov 09 nicklas 145   }
5193 27 Nov 09 nicklas 146   
5193 27 Nov 09 nicklas 147   /**
5193 27 Nov 09 nicklas 148     Print the header line. This method must always be called before
5193 27 Nov 09 nicklas 149     printing any data. It can only be called once. Each column header
5193 27 Nov 09 nicklas 150     must be unique and 'ID' is not allowed since it is always used for
5193 27 Nov 09 nicklas 151     the first column. Null values are not allowed. 
5193 27 Nov 09 nicklas 152     
5193 27 Nov 09 nicklas 153     @param headers The header columns, not including the ID column
5193 27 Nov 09 nicklas 154     @throws IllegalStateException If headers has already been printed
5193 27 Nov 09 nicklas 155     @throws NullPointerException If any of the header values is null
5193 27 Nov 09 nicklas 156     @throws IllegalArgumentException If a duplicate header is found
5193 27 Nov 09 nicklas 157   */
5193 27 Nov 09 nicklas 158   public void bfsPrintHeaders(String... headers)
5193 27 Nov 09 nicklas 159   {
5193 27 Nov 09 nicklas 160     if (hasPrintedHeaders())
5193 27 Nov 09 nicklas 161     {
5198 15 Dec 09 nicklas 162       throw new IllegalStateException("Headers has already been printed to file: " + 
5198 15 Dec 09 nicklas 163           getFilename());
5193 27 Nov 09 nicklas 164     }
5198 15 Dec 09 nicklas 165     if (headers == null) 
5198 15 Dec 09 nicklas 166     {
5198 15 Dec 09 nicklas 167       throw new NullPointerException("'headers' in file: " + getFilename());
5198 15 Dec 09 nicklas 168     }
5193 27 Nov 09 nicklas 169     
5193 27 Nov 09 nicklas 170     Set<String> used = new HashSet<String>();
5193 27 Nov 09 nicklas 171     used.add("ID");
5193 27 Nov 09 nicklas 172     for (int i = 0; i < headers.length; ++i)
5193 27 Nov 09 nicklas 173     {
5193 27 Nov 09 nicklas 174       String header = headers[i];
5198 15 Dec 09 nicklas 175       if (header == null) 
5198 15 Dec 09 nicklas 176       {
5198 15 Dec 09 nicklas 177         throw new NullPointerException("'headers[" + i + "]' in file: " + getFilename());
5198 15 Dec 09 nicklas 178       }
5193 27 Nov 09 nicklas 179       if (used.contains(header))
5193 27 Nov 09 nicklas 180       {
5198 15 Dec 09 nicklas 181         throw new IllegalArgumentException("Duplicate header at index " + i + 
5198 15 Dec 09 nicklas 182           " in file " + getFilename() + ": " + header);
5193 27 Nov 09 nicklas 183       }
5193 27 Nov 09 nicklas 184       used.add(header);
5193 27 Nov 09 nicklas 185     }
5193 27 Nov 09 nicklas 186     
5193 27 Nov 09 nicklas 187     print("ID\t");
5193 27 Nov 09 nicklas 188     tablePrintData((Object[])headers);
5193 27 Nov 09 nicklas 189     hasPrintedHeaders = true;
5193 27 Nov 09 nicklas 190     columnCount = headers.length;
5193 27 Nov 09 nicklas 191   }
5193 27 Nov 09 nicklas 192   
5193 27 Nov 09 nicklas 193   /**
5193 27 Nov 09 nicklas 194     Print a data line. Before this method can be used headers must have been
5193 27 Nov 09 nicklas 195     printed. The size of the data array must be exactly the same as the
5193 27 Nov 09 nicklas 196     size of the headers array.
5193 27 Nov 09 nicklas 197     
5193 27 Nov 09 nicklas 198     @param id The id of the line, must be a unique positive integer
5193 27 Nov 09 nicklas 199     @param data The data to print
5193 27 Nov 09 nicklas 200     @throws IllegalStateException If headers has not been printed
5193 27 Nov 09 nicklas 201     @throws IllegalArgumentException If the ID values is not a unique postive
5193 27 Nov 09 nicklas 202       integer or if the size of the data array doesn't match the size of the
5193 27 Nov 09 nicklas 203       header array
5193 27 Nov 09 nicklas 204     @throws NullPointerException If the data array is null
5193 27 Nov 09 nicklas 205   */
5193 27 Nov 09 nicklas 206   public void bfsPrintData(int id, Object... data)
5193 27 Nov 09 nicklas 207   {
5193 27 Nov 09 nicklas 208     if (!hasPrintedHeaders())
5193 27 Nov 09 nicklas 209     {
5198 15 Dec 09 nicklas 210       throw new IllegalStateException("Must print headers before printing data to file: " + 
5198 15 Dec 09 nicklas 211         getFilename());
5193 27 Nov 09 nicklas 212     }
5193 27 Nov 09 nicklas 213     if (id <= 0)
5193 27 Nov 09 nicklas 214     {
5198 15 Dec 09 nicklas 215       throw new IllegalArgumentException("The id must be a positive integer in file: " + 
5198 15 Dec 09 nicklas 216         getFilename());
5193 27 Nov 09 nicklas 217     }
5193 27 Nov 09 nicklas 218     if (usedIds.contains(id))
5193 27 Nov 09 nicklas 219     {
5198 15 Dec 09 nicklas 220       throw new IllegalArgumentException("Id value must be unique in file " + 
5198 15 Dec 09 nicklas 221         getFilename() + ": " + id);
5193 27 Nov 09 nicklas 222     }
5198 15 Dec 09 nicklas 223     if (data == null) throw new NullPointerException("'data' in file: " + getFilename());
5193 27 Nov 09 nicklas 224     if (data.length != columnCount)
5193 27 Nov 09 nicklas 225     {
5193 27 Nov 09 nicklas 226       throw new IllegalArgumentException("Data array has " + data.length + " columns; " +
5198 15 Dec 09 nicklas 227           "; expected " + columnCount + " in file: " + getFilename());
5193 27 Nov 09 nicklas 228     }
5193 27 Nov 09 nicklas 229     usedIds.add(id);
5193 27 Nov 09 nicklas 230     print(id);
5194 04 Dec 09 nicklas 231     if (data.length > 0)
5194 04 Dec 09 nicklas 232     {
5194 04 Dec 09 nicklas 233       print("\t");
5194 04 Dec 09 nicklas 234       tablePrintData(data);
5194 04 Dec 09 nicklas 235     }
5194 04 Dec 09 nicklas 236     else
5194 04 Dec 09 nicklas 237     {
5194 04 Dec 09 nicklas 238       print("\n");
5194 04 Dec 09 nicklas 239     }
5193 27 Nov 09 nicklas 240   }
5193 27 Nov 09 nicklas 241   
5193 27 Nov 09 nicklas 242 }