/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.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 3 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, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.jai;
import com.bc.ceres.jai.operator.XmlDescriptor;
import javax.media.jai.EnumeratedParameter;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.OperationDescriptor;
import javax.media.jai.OperationRegistry;
import javax.media.jai.ParameterListDescriptor;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Array;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
public class JaiShell {
String opt;
public static void main(String[] args) {
if (args.length == 0) {
printUsage();
}
boolean interactive = false;
ArrayList<String> argList = new ArrayList<String>();
HashMap<String, String> configuration = new HashMap<String, String>(64);
Properties properties = System.getProperties();
for (String name : properties.stringPropertyNames()) {
configuration.put(name, properties.getProperty(name));
}
for (String arg : args) {
if (arg.equals("-i")) {
interactive = true;
} else if (arg.startsWith("-D")) {
String[] tokens = arg.substring(2).split("=", 2);
configuration.put(tokens[0], tokens.length == 2 ? tokens[1] : "");
} else if (arg.startsWith("-?")) {
printOpHelp(arg, 2);
} else {
argList.add(arg);
}
}
for (String arg : argList) {
File file = new File(arg);
try {
URI location = createInput(file, configuration);
XmlDescriptor.create(location, null, null).getRendering();
} catch (Throwable t) {
System.out.println("Error: " + t.getMessage());
}
}
if (interactive) {
System.out.println("Note: The interactive shell is not yet implemented. \n" +
" You can only use the '?' or '?<op>' function.");
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("\n> ");
String line;
try {
line = r.readLine();
if (line == null) {
break;
}
} catch (IOException e) {
e.printStackTrace();
break;
}
line = line.trim();
if (line.equalsIgnoreCase("exit")) {
System.out.println("Bye!");
break;
}
if (line.startsWith("?")) {
printOpHelp(line, 1);
}
}
}
}
private static URI createInput(File file, HashMap<String, String> conf) throws IOException {
String text = readText(file, conf);
// System.out.println(text);
File tempFile = File.createTempFile("jai", "xml");
// todo - I (nf) don't remember, why I need the following?!
FileWriter writer = new FileWriter(tempFile);
try {
writer.write(text);
} finally {
writer.close();
}
return tempFile.toURI();
}
private static String readText(File file, HashMap<String, String> conf) throws IOException {
return replace(read(file), conf).toString();
}
private static StringBuilder read(File file) throws IOException {
Reader reader = new BufferedReader(new FileReader(file));
try {
return readAll(reader);
} finally {
reader.close();
}
}
private static StringBuilder readAll(Reader reader) throws IOException {
StringBuilder sb = new StringBuilder(1024);
while (true) {
int i = reader.read();
if (i == -1) {
break;
}
sb.append((char) i);
}
return sb;
}
private static StringBuilder replace(StringBuilder text, HashMap<String, String> map) {
for (Map.Entry<String, String> entry : map.entrySet()) {
String p = "${" + entry.getKey() + "}";
while (true) {
int i = text.indexOf(p);
if (i == -1) {
break;
}
text.replace(i, i + p.length(), entry.getValue());
}
}
return text;
}
private static void printOpHelp(String s, int i) {
String name = s.substring(i);
if (name.equals("")) {
printOperatorList();
} else {
printOperatorHelp(name);
}
}
private static void printOperatorHelp(String name) {
OperationRegistry operationRegistry = JAI.getDefaultInstance().getOperationRegistry();
OperationDescriptor descriptor = (OperationDescriptor) operationRegistry.getDescriptor(OperationDescriptor.class, name);
if (descriptor == null) {
System.out.println("Unknown operation '" + name + "'");
return;
}
String[][] resources = descriptor.getResources(Locale.getDefault());
String globalName = resources[0][1];
String description = resources[3][1];
String[] sourceNames = descriptor.getSourceNames();
Class[] sourceTypes = descriptor.getSourceClasses("rendered");
ParameterListDescriptor parameterListDescriptor = descriptor.getParameterListDescriptor("rendered");
String[] paramNames = parameterListDescriptor.getParamNames();
Class[] paramTypes = parameterListDescriptor.getParamClasses();
StringBuilder text = new StringBuilder();
text.append("Usage: ");
text.append(globalName);
text.append('(');
StringBuilder paramListText = new StringBuilder();
if (sourceNames != null) {
for (String sourceName : sourceNames) {
if (paramListText.length() > 0) {
paramListText.append(", ");
}
paramListText.append(sourceName);
}
}
if (paramNames != null) {
for (String paramName : paramNames) {
if (paramListText.length() > 0) {
paramListText.append(", ");
}
paramListText.append(paramName);
Object defaultValue = parameterListDescriptor.getParamDefaultValue(paramName);
if (defaultValue != ParameterListDescriptor.NO_PARAMETER_DEFAULT) {
paramListText.append("=");
paramListText.append(format(defaultValue));
}
}
}
text.append(paramListText);
text.append(')');
text.append('\n');
text.append("Description: ");
text.append(description);
text.append('\n');
text.append("Arguments:\n");
if (sourceNames != null) {
for (int i = 0; i < sourceNames.length; i++) {
String sourceName = sourceNames[i];
Class sourceType = sourceTypes[i];
text.append(" ");
text.append(sourceName);
text.append(": ");
text.append("A source.");
text.append(" (" + sourceType.getName() + ")");
text.append('\n');
}
}
if (paramNames != null) {
for (int i = 0; i < paramNames.length; i++) {
String paramName = paramNames[i];
Class paramType = paramTypes[i];
text.append(" ");
text.append(paramName);
text.append(": ");
text.append(resources[6 + i][1]);
text.append(" (" + paramType.getName() + ")");
text.append('\n');
}
}
System.out.println(text);
}
private static String format(Object value) {
if (value == null) {
return "null";
}
Class<? extends Object> type = value.getClass();
if (type.isArray()) {
StringBuilder builder = new StringBuilder();
builder.append('{');
int length = Array.getLength(value);
for (int i = 0; i < length; i++) {
if (i > 0) {
builder.append(',');
}
builder.append(format(Array.get(value, i)));
}
builder.append('}');
return builder.toString();
} else if (EnumeratedParameter.class.isAssignableFrom(type)) {
return ((EnumeratedParameter) value).getName();
} else if (Interpolation.class.isAssignableFrom(type)) {
if (Interpolation.getInstance(Interpolation.INTERP_NEAREST).equals(value)) {
return "INTERP_NEAREST";
} else if (Interpolation.getInstance(Interpolation.INTERP_BILINEAR).equals(value)) {
return "INTERP_BILINEAR";
} else if (Interpolation.getInstance(Interpolation.INTERP_BICUBIC).equals(value)) {
return "INTERP_BICUBIC";
} else if (Interpolation.getInstance(Interpolation.INTERP_BICUBIC_2).equals(value)) {
return "INTERP_BICUBIC_2";
}
} else if (CharSequence.class.isAssignableFrom(type)) {
return "\"" + String.valueOf(value) + "\"";
}
return String.valueOf(value);
}
private static void printUsage() {
System.out.println("Usage: jai [-?[<op>]] [-i] {-D<param-name>=<param-value>} {<xml-file>}\n");
}
private static void printOperatorList() {
OperationRegistry operationRegistry = JAI.getDefaultInstance().getOperationRegistry();
List<OperationDescriptor> descriptors = (List<OperationDescriptor>) operationRegistry.getDescriptors(OperationDescriptor.class);
Collections.sort(descriptors, new Comparator<OperationDescriptor>() {
public int compare(OperationDescriptor descriptor1, OperationDescriptor descriptor2) {
return descriptor1.getName().compareTo(descriptor2.getName());
}
});
int columnCount = 0;
for (OperationDescriptor descriptor : descriptors) {
columnCount = Math.max(columnCount, descriptor.getName().length());
}
for (OperationDescriptor descriptor : descriptors) {
String namePart = descriptor.getName();
if (namePart.length() < columnCount) {
namePart += spaces(columnCount - namePart.length());
}
String[][] resources = descriptor.getResources(Locale.getDefault());
String description = resources[3][1];
System.out.println(namePart + " - " + description);
}
}
private static String spaces(int n) {
char[] c = new char[n];
Arrays.fill(c, ' ');
return new String(c);
}
}