package com.occamlab.te;
import java.awt.BorderLayout;
import java.net.URL;
import java.net.URLDecoder;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.FormView;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.occamlab.te.util.DomUtils;
/**
* Swing-based form created from the content of a <ctl:form> element. This is
* produced when not running the test harness in a web application context.
*/
public class SwingForm extends JFrame implements HyperlinkListener {
static final long serialVersionUID = 7907599307261079944L;
public static final String CTL_NS = "http://www.occamlab.com/ctl";
private static SwingForm mainForm = null;
private static SwingForm popupForm = null;
private static TECore core;
private static String popupName = Thread.currentThread().getName();
private JEditorPane jedit;
private ArrayList<String> fileFields = new ArrayList<String>();
private static class Invoker implements Runnable {
String name;
int width;
int height;
public void run() {
if (mainForm == null) {
mainForm = new SwingForm(name);
}
String html = core.getFormHtml();
core.setFormHtml(null);
// For some reason, the <meta http-equiv="Content-Type"
// content="text/html"> tag generated by SAXON screws up the
// JEditorPane, so replace it with a dummy tag.
int i = html.indexOf("<meta");
if (i > 0) {
html = html.substring(0, i + 1) + "blah"
+ html.substring(i + 5);
}
mainForm.jedit.setText(html);
mainForm.setSize(width, height);
mainForm.validate();
mainForm.setVisible(true);
}
}
private class CustomFormView extends FormView {
public CustomFormView(javax.swing.text.Element elem) {
super(elem);
}
protected void submitData(String data) {
if (SwingForm.this == popupForm) {
return;
}
// System.out.println("data: "+data);
try {
String kvps = data + "&=";
int start = 0;
int end = data.length();
DocumentBuilder db = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = db.newDocument();
Element root = doc.createElement("values");
doc.appendChild(root);
do {
String key;
String value;
int eq = kvps.indexOf("=", start);
int amp = kvps.indexOf("&", start);
if (amp > eq) {
key = kvps.substring(start, eq);
value = kvps.substring(eq + 1, amp);
} else {
key = kvps.substring(start, amp);
value = "";
}
Element valueElement = doc.createElement("value");
valueElement.setAttribute("key", key);
// Special case for file inputs
if (fileFields.contains(key)) {
File f = new File(URLDecoder.decode(value, "UTF-8"));
if (f != null) {
if (core.formParsers.containsKey(key)) {
Element parser = core.formParsers.get(key);
URL url = f.toURI().toURL();
Element response = core.parse(
url.openConnection(), parser, doc);
Element content = DomUtils.getElementByTagName(
response, "content");
if (content != null) {
Element child = DomUtils
.getChildElement(content);
if (child != null) {
valueElement.appendChild(child);
}
}
} else {
// value = Core.saveFileToWorkingDir(value); //
// What does copying the file to a new dir
// accomplish?
Element fileEntry = doc.createElementNS(CTL_NS,
"file-entry");
fileEntry.setAttribute("full-path",
URLDecoder.decode(value, "UTF-8")
.replace('\\', '/'));
valueElement.appendChild(fileEntry);
}
}
} else {
valueElement.appendChild(doc.createTextNode(URLDecoder
.decode(value, "UTF-8")));
}
root.appendChild(valueElement);
start = amp + 1;
// System.out.println("key|value: "+key+"|"+value);
} while (start < end);
core.setFormResults(doc);
if (popupForm != null) {
popupForm.setVisible(false);
}
} catch (Throwable t) {
t.printStackTrace(System.out);
}
mainForm.setVisible(false);
}
}
private class CustomViewFactory extends HTMLEditorKit.HTMLFactory {
public javax.swing.text.View create(javax.swing.text.Element elem) {
AttributeSet as = elem.getAttributes();
HTML.Tag tag = (HTML.Tag) (as
.getAttribute(StyleConstants.NameAttribute));
if (tag == HTML.Tag.INPUT) {
String type = "";
String name = "";
Enumeration e = as.getAttributeNames();
while (e.hasMoreElements()) {
Object key = e.nextElement();
if (key == HTML.Attribute.TYPE) {
type = as.getAttribute(key).toString();
}
if (key == HTML.Attribute.NAME) {
name = as.getAttribute(key).toString();
}
}
if (type.equalsIgnoreCase("submit")) {
return new CustomFormView(elem);
}
if (type.equalsIgnoreCase("file")) {
fileFields.add(name);
}
}
return super.create(elem);
}
}
private class CustomHTMLEditorKit extends HTMLEditorKit {
static final long serialVersionUID = 5742710765916499050L;
public javax.swing.text.ViewFactory getViewFactory() {
return new CustomViewFactory();
}
}
private SwingForm(String name) {
setTitle(name);
// setBackground(Color.gray);
getContentPane().setLayout(new BorderLayout());
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel, BorderLayout.CENTER);
jedit = new JEditorPane();
jedit.setEditorKit(new CustomHTMLEditorKit());
jedit.setEditable(false);
jedit.addHyperlinkListener(this);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport().add(jedit, BorderLayout.CENTER);
topPanel.add(scrollPane, BorderLayout.CENTER);
}
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
JEditorPane pane = (JEditorPane) e.getSource();
if (e instanceof HTMLFrameHyperlinkEvent) {
HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
HTMLDocument doc = (HTMLDocument) pane.getDocument();
doc.processHTMLFrameHyperlinkEvent(evt);
} else {
try {
URL target = e.getURL();
if (target == null) {
target = new URL(new URL(core.opts.baseURI),
e.getDescription());
}
if (this == popupForm) {
pane.setPage(target);
} else {
if (popupForm == null) {
popupForm = new SwingForm(popupName);
popupForm.setSize(700, 500);
popupForm.setLocation(this.getX() + 30,
this.getY() + 30);
}
popupForm.jedit.setPage(target);
popupForm.setVisible(true);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
public static void create(String name, int width, int height, TECore core) {
Invoker invoker = new Invoker();
invoker.name = name;
invoker.width = width;
invoker.height = height;
SwingForm.core = core;
SwingUtilities.invokeLater(invoker);
}
public static void destroy() {
if (popupForm != null) {
popupForm.dispose();
popupForm = null;
}
if (mainForm != null) {
mainForm.dispose();
mainForm = null;
}
}
}