package edu.colostate.vchill.color;
import edu.colostate.vchill.ChillDefines.ColorType;
import edu.colostate.vchill.Loader;
import edu.colostate.vchill.ScaleManager;
import edu.colostate.vchill.chill.ChillMomentFieldScale;
import javax.xml.parsers.SAXParserFactory;
import java.awt.*;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* Main/Control class for VCHILL's color module
*
* @author Jochen Deyke
* @author Alexander Deyke
* @version 2007-03-15
*/
public class XMLControl {
private static final ScaleManager sm = ScaleManager.getInstance();
private final ColorMap activeColorMap;
public XMLControl() {
this(true);
}
public XMLControl(final boolean interpolateable) {
this.activeColorMap = new ColorMap(interpolateable);
}
/**
* Get the Colors to render a plot of the specified data type
*
* @param type the data type to get the Colors for
* @return the requested Listof Color
*/
public List<Color> getType(final String type) {
return activeColorMap.getType(translate(type));
}
/**
* Get the Colors of a certain color type
*
* @param type the color type to get the Colors for
* @return the requested Color[]
*/
public List<Color> getType(final ColorType type) {
return activeColorMap.getType(type);
}
/**
* Set the Colors to render a plot of the specified data type
*
* @param type the data type to set the Colors for
*/
public void setType(final String type, final List<Color> colors) {
activeColorMap.addType(translate(type), colors);
}
/**
* Set the Colors of a certain color type
*
* @param type the data type to set the Colors for
*/
public void setType(final ColorType type, final List<Color> colors) {
activeColorMap.addType(type, colors);
}
/**
* Translate an old-style text identifier into the new XML name
*
* @param type the data type to translate
* @return the corresponding ColorType
*/
public static ColorType translate(final String type) {
ChillMomentFieldScale scale = sm.getScale(type);
if (scale == null) return null;
return scale.colorMapType;
}
/**
* Load color definitions from the specified file.
* If the specified file exists, it is loaded from the local filesystem.
* In that case, the parser is determined by the suffix -
* anything other than ".xml" is treated as old-style text format.
* If the file does not exist on the local filesystem, it is presumed to be an
* XML file to be retrieved from the resource jar.
*
* @param filename the name of the file to parse
*/
public void load(final String filename) {
this.activeColorMap.clear();
File file = new File(filename);
if (!file.exists()) { //not on local filesys; get from resource jar
try {
ClassLoader cl = Loader.class.getClassLoader();
JarInputStream jar_in = new JarInputStream(cl.getResourceAsStream("colors.jar"));
JarEntry curr_entry = jar_in.getNextJarEntry();
while (true) {
if (curr_entry == null) return;
if (curr_entry.getName().equals(filename)) break;
curr_entry = jar_in.getNextJarEntry();
}
SAXParserFactory.newInstance().newSAXParser().parse(jar_in, new XMLColorMapHandler(activeColorMap));
} catch (Exception e) {
System.err.println("Exception while loading colors: " + e);
e.printStackTrace();
}
} else { //file DOES exist on local filesystem
try {
if (filename.endsWith(".xml")) {
SAXParserFactory.newInstance().newSAXParser().parse(file, new XMLColorMapHandler(activeColorMap));
} else { //assume old-school text file -- not for release use
new ColorMapTextParser(activeColorMap).parse(file.getCanonicalPath());
}
} catch (Exception e) {
System.err.println("Exception while loading colors: " + e);
e.printStackTrace();
}
}
}
/**
* Save the currently active color definitions to the specified file.
* Output is in XML format.
*
* @param filename the name of the file to save as.
* It is <b><em>*highly*</em></b> recommended this name end in ".xml" so load() will use the correct parser.
* Failure to follow this guideline will render the file unuseable by VCHILL until manually renamed.
*/
public void save(final String filename) {
PrintStream file;
try {
file = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(filename))), false, "UTF-8");
} catch (Exception e) {
throw new Error(e);
}
file.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
file.println("<colormap name=\"" + filename + "\">");
for (ColorType type : ColorType.values()) {
file.println(" <type>");
file.println(" <name>" + type + "</name>");
List<Color> colors = activeColorMap.getType(type);
for (int j = 0; j < colors.size(); ++j) {
file.println(" <color><!-- level " + j + " -->");
file.println(" <red>" + colors.get(j).getRed() + "</red>");
file.println(" <green>" + colors.get(j).getGreen() + "</green>");
file.println(" <blue>" + colors.get(j).getBlue() + "</blue>");
file.println(" </color>");
}
file.println(" </type>");
}
file.println("</colormap>");
file.flush();
file.close();
}
/**
* Get the list of all available XML color definition files
*
* @return a List of available filenames
*/
public static List<String> getListOfFiles() {
try {
ClassLoader cl = Loader.class.getClassLoader();
JarInputStream jar_in = new JarInputStream(cl.getResourceAsStream("colors.jar"));
LinkedList<String> names = new LinkedList<String>();
while (jar_in.available() > 0) {
JarEntry entry = jar_in.getNextJarEntry();
if (entry == null) break;
String name = (entry).getName();
if (name.endsWith(".xml")) {
names.add(name);
}
}
return Collections.unmodifiableList(names);
} catch (Exception e) {
e.printStackTrace();
return Collections.unmodifiableList(new LinkedList<String>());
}
}
/**
* Test method for XML module - translates args[0] to args[1]
*
* @param args file to load - default is defclrs.txt,
* file to save - default is defclrs.xml
*/
public static void main(final String[] args) //test method
{
XMLControl x = new XMLControl();
System.out.println("Loading...");
x.load((args.length > 0) ? args[0] : "defclrs.txt");
System.out.println("Saving...");
x.save((args.length > 1) ? args[1] : "defclrs.xml");
System.out.println("Done!");
}
}