blob: 9f9056d36857ffc26b33a459a7134f4d50e34287 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2008 IBM Corporation and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Goh KONDOH - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.model.dom.html.errorhandler;
import java.io.IOException;
import org.eclipse.actf.model.dom.html.HTMLParser;
import org.eclipse.actf.model.dom.sgml.EndTag;
import org.eclipse.actf.model.dom.sgml.ParseException;
import org.eclipse.actf.model.dom.sgml.SGMLParser;
import org.eclipse.actf.model.dom.sgml.errorhandler.IErrorHandler;
import org.eclipse.actf.model.dom.sgml.util.SgmlUtil;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* ErrorHandler implementation for illegally closed form context. Usually to add
* an error handler, you uses {@link
* org.eclipse.actf.model.dom.sgml.SGMLParser#addErrorHandler(org.eclipse.actf.model.dom.sgml.errorhandler.IErrorHandler)}.
* However, this error handler conflicts with {@link HTMLErrorHandler} installed
* to parsers by default. Thus, instead of that method use {@link
* #addTo(HTMLParser)}. And to remove this, use {@link #remove()}. Note: This
* error handler is <em>experimental</em>.
*
*/
public class FormExpander implements IErrorHandler {
private HTMLErrorHandler htmlErrorHandler;
private HTMLParser parser;
/**
* Add this error handler to <code>parser</code>
*
* @see org.eclipse.actf.model.dom.sgml.SGMLParser#addErrorHandler(org.eclipse.actf.model.dom.sgml.errorhandler.IErrorHandler)
*/
public void addTo(HTMLParser parser) {
IErrorHandler errorHandlers[] = parser.getErrorHandlers();
for (int i = 0; i < errorHandlers.length; i++) {
if (errorHandlers[i] instanceof HTMLErrorHandler) {
htmlErrorHandler = (HTMLErrorHandler) errorHandlers[i];
htmlErrorHandler.setKeepForm(false);
break;
}
}
parser.addErrorHandler(this);
}
/**
* Remove this error handler from the parser.
*/
public void remove() {
if (htmlErrorHandler != null) {
htmlErrorHandler.setKeepForm(true);
parser.removeErrorHandler(this);
}
}
/**
* Find the last <code>FORM</code> element and relink it to the lowest
* position whereas it covers its start and end tag.
*/
public boolean handleError(int code, SGMLParser parser, Node errorNode)
throws ParseException, IOException, SAXException {
String nodeName = errorNode.getNodeName();
if (code == FLOATING_ENDTAG && errorNode instanceof EndTag
&& nodeName.equalsIgnoreCase("FORM")) {
// Element context = parser.getContext();
NodeList forms = parser.getDocument().getElementsByTagName("FORM");
Element targetForm = (Element) forms.item(forms.getLength() - 1);
if (targetForm == null || parser.hasEndTag(targetForm))
return false;
// Checks if target form is under the context.
Element targetFirstNode = targetForm;
Element contexts[] = parser.getContextElements();
outer: while (targetFirstNode.getParentNode() instanceof Element) {
Element parent = (Element) targetFirstNode.getParentNode();
if (targetFirstNode.getElementsByTagName("FORM").getLength() > 1)
break;
for (int c = contexts.length - 1; c >= 0; c--) {
if (contexts[c] == parent) {
for (Node child = targetFirstNode.getNextSibling(); child != null; child = child
.getNextSibling()) {
if (child instanceof Element
&& ((Element) child).getElementsByTagName(
"FORM").getLength() > 0) {
break outer;
}
}
SgmlUtil.remove(targetForm);
SgmlUtil.add(parent, targetForm, targetFirstNode, parent
.getLastChild());
if (c != contexts.length - 1)
parser.setContext(parent);
((EndTag) errorNode).setElement(targetForm);
parser.setHasEndTag(targetForm);
parser.error(code, "Expanded " + targetForm);
return true;
}
}
targetFirstNode = parent;
}
}
return false;
}
}