Skip to content
Snippets Groups Projects
SVFormat.java 5.41 KiB
package tap.formatter;

/*
 * This file is part of TAPLibrary.
 * 
 * TAPLibrary 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.
 * 
 * TAPLibrary is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without 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 TAPLibrary.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
 */

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

import cds.savot.writer.SavotWriter;
import adql.db.DBColumn;
import tap.ServiceConnection;
import tap.TAPException;
import tap.TAPExecutionReport;

public abstract class SVFormat< R > implements OutputFormat<R> {

	/** Indicates whether a format report (start and end date/time) must be printed in the log output.  */
	private boolean logFormatReport;

	public static final char COMMA_SEPARATOR = ',';
	public static final char SEMI_COLON_SEPARATOR = ';';
	public static final char TAB_SEPARATOR = '\t';

	protected final ServiceConnection<R> service;

	protected final String separator;
	protected final boolean delimitStr;

	public SVFormat(final ServiceConnection<R> service, char colSeparator){
		this(service, colSeparator, true);
	}

	public SVFormat(final ServiceConnection<R> service, char colSeparator, boolean delimitStrings){
		this(service, colSeparator, delimitStrings, false);
	}

	public SVFormat(final ServiceConnection<R> service, char colSeparator, boolean delimitStrings, final boolean logFormatReport){
		separator = "" + colSeparator;
		delimitStr = delimitStrings;
		this.service = service;
		this.logFormatReport = logFormatReport;
	}

	public SVFormat(final ServiceConnection<R> service, String colSeparator){
		this(service, colSeparator, true);
	}

	public SVFormat(final ServiceConnection<R> service, String colSeparator, boolean delimitStrings){
		separator = (colSeparator == null) ? ("" + COMMA_SEPARATOR) : colSeparator;
		delimitStr = delimitStrings;
		this.service = service;
	}
	public String getMimeType(){
		switch(separator.charAt(0)){
			case COMMA_SEPARATOR:
			case SEMI_COLON_SEPARATOR:
				return "text/csv";
			case TAB_SEPARATOR:
				return "text/tsv";
			default:
				return "text/plain";
		}
	}

	public String getShortMimeType(){
		switch(separator.charAt(0)){
			case COMMA_SEPARATOR:
			case SEMI_COLON_SEPARATOR:
				return "csv";
			case TAB_SEPARATOR:
				return "tsv";
			default:
				return "text";
		}
	}

	public String getDescription(){
		return null;
	}

	public String getFileExtension(){
		switch(separator.charAt(0)){
			case COMMA_SEPARATOR:
			case SEMI_COLON_SEPARATOR:
				return "csv";
			case TAB_SEPARATOR:
				return "tsv";
			default:
				return "txt";
		}
	}

	@Override
	public void writeResult(R queryResult, OutputStream output, TAPExecutionReport execReport, Thread thread) throws TAPException, InterruptedException{
		try{
			final long startTime = System.currentTimeMillis();

			final PrintWriter writer = new PrintWriter(output);

			// Write header:
			DBColumn[] columns = writeMetadata(queryResult, writer, execReport, thread);

			// Write data:
			int nbRows = writeData(queryResult, columns, writer, execReport, thread);

			writer.flush();

			if (logFormatReport)
				service.getLogger().info("JOB " + execReport.jobID + " WRITTEN\tResult formatted (in SV[" + delimitStr + "] ; " + nbRows + " rows ; " + columns.length + " columns) in " + (System.currentTimeMillis() - startTime) + " ms !");

		}catch(Exception ex){
			service.getLogger().error("While formatting in (T/C)SV !", ex);
		}
	}

	protected abstract DBColumn[] writeMetadata(R queryResult, PrintWriter writer, TAPExecutionReport execReport, Thread thread) throws IOException, TAPException, InterruptedException;

	protected abstract int writeData(R queryResult, DBColumn[] selectedColumns, PrintWriter writer, TAPExecutionReport execReport, Thread thread) throws IOException, TAPException, InterruptedException;

	/**
	 * <p>Writes the given field value in the given OutputStream.</p>
	 * 
	 * <p>
	 * 	The given value will be encoded as an XML element (see {@link SavotWriter#encodeElement(String)}.
	 * 	Besides, if the given value is <code>null</code> and if the column datatype is <code>int</code>,
	 * 	<code>short</code> or <code>long</code>, the NULL values declared in the field metadata will be written.</p>
	 * 
	 * @param value				The value to write.
	 * @param column			The corresponding column metadata.
	 * @param out				The stream in which the field value must be written.
	 * 
	 * @throws IOException		If there is an error while writing the given field value in the given stream.
	 * @throws TAPException		If there is any other error (by default: never happen).
	 */
	protected void writeFieldValue(final Object value, final DBColumn column, final PrintWriter writer) throws IOException, TAPException{
		if (value != null){
			if ((delimitStr && value instanceof String) || value.toString().contains(separator)){
				writer.print('"');
				writer.print(value.toString().replaceAll("\"", "'"));
				writer.print('"');
			}else
				writer.print(value.toString());
		}
	}
}