// This file is part of PleoCommand:
// Interactively control Pleo with psychobiological parameters
//
// Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Boston, USA.
package pleocmd.pipe.out;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import pleocmd.Log;
import pleocmd.RunnableWithArgument;
import pleocmd.StringManip;
import pleocmd.cfg.ConfigEnum;
import pleocmd.cfg.ConfigPath;
import pleocmd.cfg.ConfigPath.PathType;
import pleocmd.exc.ConfigurationException;
import pleocmd.exc.InternalException;
import pleocmd.exc.OutputException;
import pleocmd.pipe.data.Data;
import pleocmd.pipe.in.FileInput;
import pleocmd.pipe.in.Input;
public final class FileOutput extends Output { // NO_UCD
private final ConfigPath cfgFile;
private final ConfigEnum<PrintType> cfgType;
private DataOutputStream out;
private Data lastRoot;
public FileOutput() {
addConfig(cfgFile = new ConfigPath("File", PathType.FileForWriting));
addConfig(cfgType = new ConfigEnum<PrintType>(PrintType.class));
cfgFile.setFileFilter(Arrays.asList(new FileFilter[] {
new FileNameExtensionFilter("ASCII-Textfiles", "txt"),
new FileNameExtensionFilter("Pleo ASCII Data", "pad"),
new FileNameExtensionFilter("Pleo Binary Data", "pbd") }));
cfgFile.setChangingContent(new RunnableWithArgument() {
@Override
public Object run(final Object... args) {
final String path = (String) args[0];
switch (getCfgType().getEnumGUI()) {
case Ascii:
case AsciiOriginal:
case PleoMonitorCommands:
if (path.endsWith(".pbd"))
getCfgType().setEnumGUI(PrintType.Binary);
break;
case Binary:
case BinaryOriginal:
if (!path.endsWith(".pbd"))
getCfgType().setEnumGUI(PrintType.Ascii);
break;
}
return null;
}
});
cfgType.setChangingContent(new RunnableWithArgument() {
@Override
public Object run(final Object... args) {
final String path = getCfgFile().getContentGUI().getPath();
switch (PrintType.valueOf((String) args[0])) {
case Ascii:
case AsciiOriginal:
case PleoMonitorCommands:
if (path.endsWith(".pbd")) getCfgFile().clearContentGUI();
break;
case Binary:
case BinaryOriginal:
if (!path.endsWith(".pbd")) getCfgFile().clearContentGUI();
break;
}
return null;
}
});
constructed();
}
public FileOutput(final File file, final PrintType type)
throws ConfigurationException {
this();
cfgFile.setContent(file);
cfgType.setEnum(type);
}
@Override
protected void init0() throws IOException {
Log.detail("Opening file '%s' for output of type '%s'",
cfgFile.getContent(), cfgType.getEnum());
out = new DataOutputStream(new FileOutputStream(cfgFile.getContent()));
}
@Override
protected void close0() throws IOException {
Log.detail("Closing file '%s'", cfgFile.getContent());
out.close();
out = null;
lastRoot = null;
}
@Override
public String getInputDescription() {
return "";
}
@Override
protected String getShortConfigDescr0() {
return String.format("\"%s\"", cfgFile.getContent().getName());
}
@Override
protected boolean write0(final Data data) throws OutputException,
IOException {
Data root;
switch (cfgType.getEnum()) {
case Ascii:
data.writeToAscii(out, true);
if (Log.canLogDetail())
Log.detail("<html>Written to file: %s",
StringManip.printSyntaxHighlightedAscii(data));
break;
case Binary:
data.writeToBinary(out);
if (Log.canLogDetail())
Log.detail("<html>Written to file: %s",
StringManip.printSyntaxHighlightedBinary(data));
break;
case AsciiOriginal:
if (lastRoot != (root = data.getRoot())) {
lastRoot = root;
root.writeToAscii(out, true);
if (Log.canLogDetail())
Log.detail("<html>Written to file: %s",
StringManip.printSyntaxHighlightedAscii(root));
}
break;
case BinaryOriginal:
if (lastRoot != (root = data.getRoot())) {
lastRoot = root;
root.writeToBinary(out);
if (Log.canLogDetail())
Log.detail("<html>Written to file: %s",
StringManip.printSyntaxHighlightedBinary(root));
}
break;
case PleoMonitorCommands:
if ("PMC".equals(data.getSafe(0).asString()))
Log.consoleOut(data.get(1).asString());
break;
default:
throw new InternalException(cfgType.getEnum());
}
return true;
}
public static String help(final HelpKind kind) { // NO_UCD
switch (kind) {
case Name:
return "File Output";
case Description:
return "Writes Data blocks to external files";
case Config1:
return "Path to an external file to which commands should "
+ "be written in either ASCII or binary form";
case Config2:
return "'Ascii' if Data blocks will be in ASCII format or\n"
+ " 'Binary' if Data blocks will be written as binary";
default:
return null;
}
}
@Override
public String isConfigurationSane() {
final File file = cfgFile.getContent();
if (isConnected())
for (final Input in : getPipe().getInputList())
if (in instanceof FileInput
&& ((FileInput) in).getCfgFile().getContent()
.equals(file))
return String.format(
"Same file has already been specified by '%s'", in);
if (file.exists())
return file.canWrite() ? null : String.format(
"Cannot write to '%s'", file);
return file.getParentFile() != null && file.getParentFile().canWrite() ? null
: String.format("Cannot create a file in '%s'",
file.getParentFile());
}
@Override
protected int getVisualizeDataSetCount() {
return 0;
}
public ConfigPath getCfgFile() {
return cfgFile;
}
protected ConfigEnum<PrintType> getCfgType() {
return cfgType;
}
}