Move DOM methods in XidynUtils. Rewrite findHeadNode method.

This commit is contained in:
Christian P. MOMON 2013-08-01 01:30:05 +02:00
parent 9c887e6cc4
commit 8c4d84cce2
7 changed files with 237 additions and 193 deletions

View file

@ -83,7 +83,7 @@ org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_de
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=false
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true

View file

@ -8,13 +8,14 @@ import org.w3c.dom.Document;
import fr.devinsy.xidyn.data.TagDataListById;
import fr.devinsy.xidyn.data.TagDataManager;
import fr.devinsy.xidyn.utils.XidynUtils;
/**
*
*/
public class DomPresenter implements Presenter
{
static private Logger logger = LoggerFactory.getLogger(DomPresenter.class);
static private final Logger logger = LoggerFactory.getLogger(DomPresenter.class);
private Document doc;
private boolean isOutdated;
private StringBuffer defaultHtmlTarget;
@ -144,7 +145,7 @@ public class DomPresenter implements Presenter
public void setSource(final Document doc)
{
this.doc = doc;
DomPresenterCore.addMetaTag(this.doc, "generator", "XIDYN");
XidynUtils.addMetaTag(this.doc, "generator", "XIDYN");
this.isOutdated = true;
}

View file

@ -1,20 +1,11 @@
package fr.devinsy.xidyn.presenters;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Attr;
@ -23,7 +14,6 @@ import org.w3c.dom.DocumentType;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import fr.devinsy.xidyn.data.SimpleTagData;
import fr.devinsy.xidyn.data.TagAttributes;
@ -41,105 +31,6 @@ public class DomPresenterCore
static final public char INDEX_SEPARATOR = '_';
static private Logger logger = LoggerFactory.getLogger(DomPresenterCore.class);
/**
* This method adds a tag to a DOM object.
*/
static public void addMetaTag(final Document doc, final String name, final String content)
{
// Find head tag.
Node headNode = findHeadNode(doc);
Node metaNode = doc.createElement("meta");
NamedNodeMap attrMap = metaNode.getAttributes();
Node attrNode = doc.createAttribute("name");
attrMap.setNamedItem(attrNode);
attrNode.setNodeValue(name);
attrNode = doc.createAttribute("content");
attrMap.setNamedItem(attrNode);
attrNode.setNodeValue(content);
headNode.insertBefore(metaNode, headNode.getFirstChild());
}
/**
* This method build a DOM object from a source.
*/
static public Document buildDom(final InputStream source) throws Exception
{
Document result;
try
{
// Create a DocumentBuilderFactory and configure it.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Set various configuration options.
dbf.setValidating(true);
dbf.setIgnoringComments(true);
dbf.setIgnoringElementContentWhitespace(false);
dbf.setCoalescing(false);
// Keep entity references as they are.
dbf.setExpandEntityReferences(false);
// Create a DocumentBuilder that satisfies the constraints
// specified by the DocumentBuilderFactory.
DocumentBuilder db = dbf.newDocumentBuilder();
ParserErrorHandler errorHandler;
errorHandler = new ParserErrorHandler();
// Set the error handler.
db.setErrorHandler(errorHandler);
Schema schema = db.getSchema();
logger.debug("schema=" + schema);
// Parse the input file.
result = db.parse(source);
if (errorHandler.hasError())
{
// Most time, error is (with StringPresenter):
// "Error at line 1 : Document root element "html", must match DOCTYPE root "null".
// Error at line 1 : Document is invalid: no grammar found.
// We ignore it. STU
logger.debug(errorHandler.toString());
}
else
{
DomPresenterCore.addMetaTag(result, "generator", "XIDYN");
}
}
catch (ParserConfigurationException exception)
{
String errorMessage = "Parser configuration exception: " + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
catch (SAXException exception)
{
String errorMessage = "Error during SAX parsing: " + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
catch (IOException exception)
{
String errorMessage = "IOError during parsing." + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
//
return (result);
}
/**
* Dynamize a doc with data.
*/
@ -184,82 +75,6 @@ public class DomPresenterCore
dynamize(result, doc, data.getIdsDataById());
}
/**
* Define in Presenter cause <object> needs this possibility.
*/
static public Document fileToDom(final String fileName) throws Exception
{
Document result;
try
{
result = buildDom(new FileInputStream(new File(fileName)));
}
catch (IOException exception)
{
String errorMessage = "IOError during parsing." + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
//
return (result);
}
/**
* Finds the node containing the &lt;head&gt; tag.
*
* @param node
* Document node.
* @return The head tag node
*/
private static Node findHeadNode(final Node node)
{
Node headNode = null;
int type = node.getNodeType();
switch (type)
{
// print document
case Node.DOCUMENT_NODE:
{
headNode = findHeadNode(((Document) node).getDocumentElement());
break;
}
case Node.ELEMENT_NODE:
{
String tag = node.getNodeName();
if ("head".equals(tag))
{
headNode = node;
break;
}
NodeList children = node.getChildNodes();
int numChildren = 0;
if (children != null)
{
numChildren = children.getLength();
}
for (int i = 0; i < numChildren; i++)
{
headNode = findHeadNode(children.item(i));
if (headNode != null)
{
break;
}
}
break;
}
}
return headNode;
}
/**
*
*/

View file

@ -96,10 +96,10 @@ public class FilePresenter implements Presenter
else if ((this.doc == null) || (this.sourceFileTime != source.lastModified()))
{
this.sourceFileTime = source.lastModified();
this.doc = DomPresenterCore.fileToDom(this.sourceFilePathname);
this.doc = XidynUtils.fileToDom(this.sourceFilePathname);
if (this.doc != null)
{
DomPresenterCore.addMetaTag(doc, "generator", "XID 0.0");
XidynUtils.addMetaTag(doc, "generator", "XID 0.0");
}
this.doctype = getDoctype(this.sourceFilePathname);
}

View file

@ -86,7 +86,8 @@ public class StringPresenter implements Presenter
// StringBufferInputStream is deprecated so we use another solution.
// (see
// http://www.developpez.net/forums/archive/index.php/t-14101.html).
this.doc = DomPresenterCore.buildDom(new ByteArrayInputStream(sourceHtml.getBytes()));
this.doc = XidynUtils.buildDom(new ByteArrayInputStream(sourceHtml.getBytes()));
XidynUtils.addMetaTag(this.doc, "generator", "XIDYN");
}
//

View file

@ -92,10 +92,10 @@ public class URLPresenter implements Presenter
if ((this.doc == null) || (this.sourceFileTime != lastModified))
{
this.sourceFileTime = lastModified;
this.doc = DomPresenterCore.buildDom(this.sourceURL.openStream());
this.doc = XidynUtils.buildDom(this.sourceURL.openStream());
if (this.doc != null)
{
DomPresenterCore.addMetaTag(doc, "generator", "XID 0.0");
XidynUtils.addMetaTag(this.doc, "generator", "XIDYN");
}
this.doctype = "<!DOCTYPE HTML>"; // TODO Made generic.
}

View file

@ -1,15 +1,131 @@
package fr.devinsy.xidyn.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import fr.devinsy.xidyn.presenters.DomPresenterCore;
import fr.devinsy.xidyn.presenters.ParserErrorHandler;
/**
*
*/
public class XidynUtils
{
static private final Logger logger = LoggerFactory.getLogger(DomPresenterCore.class);
private static final Pattern BODY_PATTERN = Pattern.compile("^.*<[bB][oO][dD][yY]>\\s*(.*\\S)\\s*</[bB][oO][dD][yY]>.*$");
/**
* This method adds a tag to a DOM object.
*/
static public void addMetaTag(final Document doc, final String name, final String content)
{
// Find head tag.
Node headNode = findHeadNode(doc);
Node metaNode = doc.createElement("meta");
NamedNodeMap attrMap = metaNode.getAttributes();
Node attrNode = doc.createAttribute("name");
attrMap.setNamedItem(attrNode);
attrNode.setNodeValue(name);
attrNode = doc.createAttribute("content");
attrMap.setNamedItem(attrNode);
attrNode.setNodeValue(content);
headNode.insertBefore(metaNode, headNode.getFirstChild());
}
/**
* This method builds a DOM object from a source.
*/
static public Document buildDom(final InputStream source) throws Exception
{
Document result;
try
{
// Create a DocumentBuilderFactory and configure it.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Set various configuration options.
dbf.setValidating(true);
dbf.setIgnoringComments(true);
dbf.setIgnoringElementContentWhitespace(false);
dbf.setCoalescing(false);
// Keep entity references as they are.
dbf.setExpandEntityReferences(false);
// Create a DocumentBuilder that satisfies the constraints
// specified by the DocumentBuilderFactory.
DocumentBuilder db = dbf.newDocumentBuilder();
ParserErrorHandler errorHandler;
errorHandler = new ParserErrorHandler();
// Set the error handler.
db.setErrorHandler(errorHandler);
Schema schema = db.getSchema();
logger.debug("schema=" + schema);
// Parse the input file.
result = db.parse(source);
if (errorHandler.hasError())
{
// Most time, error is (with StringPresenter):
// "Error at line 1 : Document root element "html", must match DOCTYPE root "null".
// Error at line 1 : Document is invalid: no grammar found.
// We ignore it. STU
logger.debug(errorHandler.toString());
}
}
catch (ParserConfigurationException exception)
{
String errorMessage = "Parser configuration exception: " + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
catch (SAXException exception)
{
String errorMessage = "Error during SAX parsing: " + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
catch (IOException exception)
{
String errorMessage = "IOError during parsing." + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
//
return (result);
}
/**
* Good estimation of the target length able to optimize performance.
*/
@ -71,6 +187,117 @@ public class XidynUtils
return (result);
}
/**
* Define in Presenter cause <object> needs this possibility.
*/
static public Document fileToDom(final String fileName) throws Exception
{
Document result;
try
{
result = buildDom(new FileInputStream(new File(fileName)));
}
catch (IOException exception)
{
String errorMessage = "IOError during parsing." + exception.getMessage();
logger.error(errorMessage);
result = null;
throw new Exception(errorMessage, exception);
}
//
return (result);
}
/**
* Finds the node containing the &lt;head&gt; tag.
*
* @param node
* Document node.
* @return The head tag node
*/
public static Node findHeadNode(final Node node)
{
Node result;
result = findNodeByName(node, "head");
//
return result;
}
/**
* Finds the node containing the &lt;head&gt; tag.
*
* @param node
* Document node.
* @return The head tag node
*/
public static Node findNodeByName(final Node node, final String name)
{
Node result;
switch (node.getNodeType())
{
case Node.DOCUMENT_NODE:
{
result = findNodeByName(((Document) node).getDocumentElement(), name);
}
break;
case Node.ELEMENT_NODE:
{
String tag = node.getNodeName();
if ((tag != null) && tag.equals(name))
{
result = node;
}
else
{
NodeList children = node.getChildNodes();
int childrenCount;
if (children == null)
{
childrenCount = 0;
}
else
{
childrenCount = children.getLength();
}
boolean ended = false;
int childrenIndex = 0;
result = null;
while (!ended)
{
if (childrenIndex < childrenCount)
{
result = findNodeByName(children.item(childrenIndex), name);
if (result != null)
{
ended = true;
}
}
else
{
ended = true;
result = null;
}
}
}
}
break;
default:
result = null;
}
//
return result;
}
/**
* Any ampersand lt;, ampersand gt; and ampersand amp; sequences in text
* nodes get read in as symbols. This method converts them back to entities.