1087 lines
23 KiB
Java
1087 lines
23 KiB
Java
package xid;
|
|
|
|
import java.util.*;
|
|
import java.io.*;
|
|
import javax.xml.parsers.*;
|
|
import javax.xml.transform.stream.StreamSource;
|
|
import javax.xml.validation.Schema;
|
|
import org.xml.sax.*;
|
|
import org.w3c.dom.*;
|
|
/**
|
|
*
|
|
*/
|
|
public class Presenter
|
|
{
|
|
static protected org.apache.log4j.Logger log;
|
|
|
|
static
|
|
{
|
|
log = org.apache.log4j.Logger.getLogger (Presenter.class.getName ());
|
|
}
|
|
|
|
protected String webappPath;
|
|
protected String sourceFileName;
|
|
protected long sourceFileTime;
|
|
protected Document doc;
|
|
|
|
/*
|
|
*
|
|
*/
|
|
public Presenter ()
|
|
{
|
|
this.webappPath = null;
|
|
this.sourceFileName = null;
|
|
this.sourceFileTime = 0;
|
|
this.doc = null;
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
public Presenter (String webappPath, String fileName)
|
|
{
|
|
this.webappPath = webappPath;
|
|
this.sourceFileName = fileName;
|
|
this.sourceFileTime = 0;
|
|
this.doc = null;
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
public String getWebappPath ()
|
|
{
|
|
String result;
|
|
|
|
result = this.webappPath;
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
public void setSource (String fileName)
|
|
{
|
|
this.sourceFileName = fileName;
|
|
this.sourceFileTime = 0;
|
|
this.doc = null;
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
public String getSource ()
|
|
{
|
|
String result;
|
|
|
|
result = this.sourceFileName;
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
public StringBuffer doXid (TagsDataById datas, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
|
|
String sourceFilePath = this.webappPath + File.separator + this.sourceFileName;
|
|
|
|
// Get the good tree.
|
|
File source = new File (sourceFilePath);
|
|
|
|
if (source == null)
|
|
{
|
|
String errorMessage = "source file not defined";
|
|
errorOutput.append (errorMessage);
|
|
log.error (errorMessage);
|
|
result = null;
|
|
}
|
|
else if (!source.exists ())
|
|
{
|
|
String errorMessage = "source file defined but not found (" + sourceFilePath + ")";
|
|
errorOutput.append (errorMessage);
|
|
log.error (errorMessage);
|
|
result = null;
|
|
}
|
|
else if ((this.doc == null) ||
|
|
(this.sourceFileTime != source.lastModified ()))
|
|
{
|
|
this.sourceFileTime = source.lastModified ();
|
|
this.doc = Presenter.fileToTree (sourceFilePath, errorOutput);
|
|
|
|
if (this.doc != null)
|
|
{
|
|
Presenter.addMetaTag (doc, "generator", "XID 0.0");
|
|
}
|
|
}
|
|
|
|
// Build the web page.
|
|
result = Presenter.doXid (doc, datas, this.webappPath, errorOutput);
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
* Xid a file without data.
|
|
*/
|
|
static public StringBuffer doXid (String fileName, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
|
|
Document doc = Presenter.fileToTree (fileName, errorOutput);
|
|
|
|
if (doc == null)
|
|
{
|
|
result = null;
|
|
}
|
|
else
|
|
{
|
|
Presenter.addMetaTag (doc, "generator", "XID 0.0");
|
|
|
|
result = Presenter.doXid (doc, null, webappPath, errorOutput);
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
* Xid a string with html in.
|
|
*/
|
|
static public StringBuffer doXid (String html, TagsDataById datas, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
|
|
String htmlSource;
|
|
if ((html.startsWith ("<!DOCTYPE")) ||
|
|
(html.startsWith ("<!doctype")) ||
|
|
(html.startsWith ("<html>")) ||
|
|
(html.startsWith ("<HTML>")))
|
|
{
|
|
htmlSource = html;
|
|
}
|
|
else
|
|
{
|
|
htmlSource = "<html><head></head><body>\n" + html + "</body></html>";
|
|
}
|
|
|
|
Document doc = null;
|
|
|
|
// StringBufferInputStream is deprecated so we use another solution.
|
|
// (see http://www.developpez.net/forums/archive/index.php/t-14101.html).
|
|
doc = buildTree (new ByteArrayInputStream (htmlSource.getBytes ()), errorOutput);
|
|
|
|
StringBuffer htmlTarget;
|
|
htmlTarget = Presenter.process (doc, datas, webappPath, errorOutput);
|
|
|
|
if (htmlTarget == null)
|
|
{
|
|
result = null;
|
|
}
|
|
else if ((html.startsWith ("<!DOCTYPE")) ||
|
|
(html.startsWith ("<!doctype")) ||
|
|
(html.startsWith ("<html>")) ||
|
|
(html.startsWith ("<HTML>")))
|
|
{
|
|
result = htmlTarget;
|
|
}
|
|
else
|
|
{
|
|
String bodyContent = extractBodyContent (htmlTarget);
|
|
|
|
if (bodyContent == null)
|
|
{
|
|
result = null;
|
|
}
|
|
else
|
|
{
|
|
result = new StringBuffer (bodyContent);
|
|
}
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
* Xid a file with data.
|
|
*/
|
|
static public StringBuffer doXid (Document doc, TagsDataById datas, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
|
|
result = Presenter.process (doc, datas, webappPath, errorOutput);
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static public String getClassAttributeValue (Node node)
|
|
{
|
|
String result;
|
|
|
|
NamedNodeMap attributes = node.getAttributes ();
|
|
if (attributes == null)
|
|
{
|
|
result = null;
|
|
}
|
|
else
|
|
{
|
|
Node nameAttribute = attributes.getNamedItem ("class");
|
|
|
|
if (nameAttribute == null)
|
|
{
|
|
result = null;
|
|
}
|
|
else
|
|
{
|
|
result = nameAttribute.getNodeValue ();
|
|
}
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static protected StringBuffer processChildren (Node node, TagsDataById datas, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
|
|
result = new StringBuffer ();
|
|
|
|
NodeList children = node.getChildNodes();
|
|
|
|
if (children == null)
|
|
{
|
|
result.append (" ");
|
|
}
|
|
else
|
|
{
|
|
int childrenCount = children.getLength ();
|
|
|
|
for (int i = 0; i < childrenCount; i++)
|
|
{
|
|
result.append (process (children.item(i), datas, webappPath, errorOutput));
|
|
}
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Includes another HSP file into the current page.
|
|
*
|
|
* @param node
|
|
* @param attrMap
|
|
* @param idAttr
|
|
*/
|
|
static protected StringBuffer processObjectTag (Node node, NamedNodeMap attrMap, Node idAttr, TagsDataById datas, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
|
|
result = new StringBuffer ();
|
|
|
|
// Find codetype.
|
|
String codetype;
|
|
if (attrMap == null)
|
|
{
|
|
codetype = null;
|
|
}
|
|
else if (attrMap.getNamedItem ("codetype") == null)
|
|
{
|
|
codetype = null;
|
|
}
|
|
else
|
|
{
|
|
codetype = attrMap.getNamedItem ("codetype").getNodeValue ();
|
|
}
|
|
|
|
|
|
// Check tag requirements.
|
|
if ((attrMap == null) ||
|
|
(codetype == null) ||
|
|
(!codetype.equals ("application/xid")) ||
|
|
(attrMap.getNamedItem ("data") == null))
|
|
{
|
|
// STU: do default action.
|
|
Presenter.processElementBasically (node, datas, webappPath, errorOutput);
|
|
}
|
|
else
|
|
{
|
|
log.debug ("object action");
|
|
result.append ("<!-- STARTING INCLUDE XID FILE " + attrMap.getNamedItem ("data") + " -->");
|
|
|
|
// Build the file name.
|
|
String htmlFileName = webappPath + attrMap.getNamedItem ("data").getNodeValue ();
|
|
|
|
|
|
// Load file in tree.
|
|
Document childDoc = null;
|
|
try
|
|
{
|
|
childDoc = fileToTree (htmlFileName, errorOutput);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result.append ("unable to build the file tree");
|
|
log.debug ("unable to build the file tree");
|
|
}
|
|
|
|
// Extract the 'body' section.
|
|
Node body = null;
|
|
try
|
|
{
|
|
NodeList nodes = childDoc.getElementsByTagName ("body");
|
|
|
|
if (nodes.getLength () == 0)
|
|
{
|
|
result.append ("no body tag in include html");
|
|
log.debug ("no body tag in include html");
|
|
}
|
|
else
|
|
{
|
|
body = nodes.item(0);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
result.append ("error getting child");
|
|
log.debug ("error getting child");
|
|
}
|
|
|
|
// Process the body child as part of the primary tree.
|
|
NodeList bodyChildren = body.getChildNodes ();
|
|
|
|
if (bodyChildren != null)
|
|
{
|
|
int childCount = bodyChildren.getLength ();
|
|
for (int childCounter = 0; childCounter < childCount; childCounter++)
|
|
{
|
|
result.append (process (bodyChildren.item (childCounter), datas, webappPath, errorOutput));
|
|
}
|
|
}
|
|
|
|
//
|
|
result.append ("<!-- ENDING INCLUDE XID FILE " + attrMap.getNamedItem ("data") + " -->");
|
|
}
|
|
log.debug ("end of object action");
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Processes a node that has dynamic content. Calls the appropriate code
|
|
* generator method, depending on the tag.
|
|
*
|
|
* @param node
|
|
* Current node.
|
|
* @param attrs
|
|
* The tag attributes.
|
|
* @param idAttr
|
|
* The ID.
|
|
*/
|
|
static protected StringBuffer processElementWithId (Node node,
|
|
NamedNodeMap attrs,
|
|
Node idAttr,
|
|
TagsDataById datas,
|
|
String webappPath,
|
|
StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
result = new StringBuffer ();
|
|
|
|
String tag = node.getNodeName();
|
|
String idValue = idAttr.getNodeValue();
|
|
|
|
log.debug ("tag=" + tag);
|
|
|
|
// Get data of this id.
|
|
TagDataCore dataCore = datas.get (idAttr.getNodeValue ());
|
|
|
|
if (dataCore == null)
|
|
{
|
|
result.append (Presenter.processElementBasically (node, datas, webappPath, errorOutput));
|
|
}
|
|
else if (dataCore instanceof TagData)
|
|
{
|
|
TagData data = (TagData) dataCore;
|
|
|
|
String theClass;
|
|
if (data == null)
|
|
{
|
|
theClass = null;
|
|
}
|
|
else
|
|
{
|
|
theClass = data.getAttributes ().getAttribute ("class");
|
|
}
|
|
|
|
if ((theClass == null) ||
|
|
(!theClass.equals ("xid:nodisplay")))
|
|
{
|
|
// Open the tag.
|
|
result.append ("<");
|
|
result.append (node.getNodeName());
|
|
|
|
// Build attributes.
|
|
result.append (processAttributes (attrs, data));
|
|
|
|
if ((node.getChildNodes () == null) &&
|
|
((data == null) || data.display ().equals ("")))
|
|
{
|
|
// Close the tag.
|
|
result.append (" />");
|
|
}
|
|
else
|
|
{
|
|
result.append ('>');
|
|
|
|
// Insert data.
|
|
if ((data == null) ||
|
|
(data.display ().equals ("")))
|
|
{
|
|
result.append (processChildren (node, datas, webappPath, errorOutput));
|
|
}
|
|
else
|
|
{
|
|
result.append (data.display ());
|
|
}
|
|
|
|
// Close the tag.
|
|
result.append ("</");
|
|
result.append (node.getNodeName());
|
|
result.append ('>');
|
|
}
|
|
}
|
|
}
|
|
else if (dataCore instanceof TagsData)
|
|
{
|
|
TagsData data = (TagsData) dataCore;
|
|
}
|
|
else if (dataCore instanceof TagsDataById)
|
|
{
|
|
TagsDataById data = (TagsDataById) dataCore;
|
|
}
|
|
else
|
|
{
|
|
log.warn ("Unknow type of TagDataId");
|
|
}
|
|
|
|
//
|
|
log.debug ("Exit");
|
|
return (result);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Recursive method that processes a node and any child nodes.
|
|
*
|
|
*/
|
|
static protected StringBuffer process (Node node, TagsDataById datas, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
log.debug ("Enter");
|
|
String TRANSITIONAL_DTD = "xhtml1-transitional.dtd";
|
|
String TRANSITIONAL_DOCTYPE = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 "
|
|
+ "Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
|
|
|
|
StringBuffer result;
|
|
result = new StringBuffer ();
|
|
|
|
// Is there anything to do?
|
|
if (node != null)
|
|
{
|
|
log.debug ("nodeName=" + node.getNodeName ());
|
|
|
|
// Find the name attribute value.
|
|
String name;
|
|
name = getClassAttributeValue (node);
|
|
|
|
if ((name == null) ||
|
|
((name != null) &&
|
|
(!name.equals ("xid:nodisplay"))))
|
|
{
|
|
int type = node.getNodeType();
|
|
switch (type)
|
|
{
|
|
case Node.DOCUMENT_NODE:
|
|
{
|
|
log.debug ("case Node.DOCUMENT_NODE");
|
|
DocumentType dt = ((Document) node).getDoctype();
|
|
|
|
if (dt != null)
|
|
{
|
|
String publicId = dt.getPublicId();
|
|
String systemId = dt.getSystemId();
|
|
|
|
if (systemId.equals(TRANSITIONAL_DTD))
|
|
{
|
|
result.append(TRANSITIONAL_DOCTYPE);
|
|
}
|
|
|
|
// Log.write(Log.TRACE,"publicId = " + publicId);
|
|
// Log.write(Log.TRACE,"systemId = " + systemId);
|
|
}
|
|
|
|
result.append (Presenter.process (((Document) node).getDocumentElement(), datas, webappPath, errorOutput));
|
|
|
|
break;
|
|
}
|
|
|
|
case Node.ELEMENT_NODE:
|
|
{
|
|
log.debug ("case Node.ELEMENT_NODE");
|
|
|
|
NamedNodeMap attrs = node.getAttributes ();
|
|
Node idAttr = attrs.getNamedItem ("id");
|
|
|
|
if (idAttr != null)
|
|
{
|
|
result.append (Presenter.processElementWithId (node, attrs, idAttr, datas, webappPath, errorOutput));
|
|
}
|
|
else
|
|
{
|
|
result.append (Presenter.processElementBasically (node, datas, webappPath, errorOutput));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// handle entity reference nodes
|
|
case Node.ENTITY_REFERENCE_NODE:
|
|
{
|
|
log.debug ("case Node.ENTITY_REFERENCE_NODE");
|
|
|
|
result.append ('&');
|
|
result.append (node.getNodeName());
|
|
result.append (';');
|
|
break;
|
|
}
|
|
|
|
// print cdata sections
|
|
case Node.CDATA_SECTION_NODE:
|
|
{
|
|
log.debug ("case Node.CDATA_SECTION_NODE");
|
|
|
|
result.append ("<![CDATA[");
|
|
result.append (node.getNodeValue());
|
|
result.append ("]]>");
|
|
|
|
break;
|
|
}
|
|
|
|
// print text
|
|
case Node.TEXT_NODE:
|
|
{
|
|
log.debug ("case Node.TEXTE_NODE");
|
|
result.append (restoreEntities (new StringBuffer(node.getNodeValue())));
|
|
break;
|
|
}
|
|
|
|
// print processing instruction
|
|
case Node.PROCESSING_INSTRUCTION_NODE:
|
|
{
|
|
log.debug ("Node.PROCESSING_INSTRUCTION_NODE");
|
|
|
|
result.append ("<?");
|
|
result.append (node.getNodeName());
|
|
String data = node.getNodeValue();
|
|
if ((data != null) && (data.length () > 0))
|
|
{
|
|
result.append (' ');
|
|
result.append (data);
|
|
}
|
|
result.append ("?>");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
//log.info ("result=" + result);
|
|
log.debug ("Exit");
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*/
|
|
static StringBuffer processElementBasically (Node node, TagsDataById datas, String webappPath, StringBuffer errorOutput)
|
|
{
|
|
StringBuffer result;
|
|
result = new StringBuffer ();
|
|
|
|
// Open the tag.
|
|
result.append ('<');
|
|
result.append (node.getNodeName());
|
|
|
|
// Build the tag attributes.
|
|
NamedNodeMap attrs = node.getAttributes ();
|
|
if (attrs != null)
|
|
{
|
|
for (int i = 0; i < attrs.getLength(); i++)
|
|
{
|
|
Attr attr = (Attr) attrs.item(i);
|
|
result.append (' ');
|
|
result.append (attr.getNodeName());
|
|
result.append ("=\"");
|
|
result.append (restoreEntities(new StringBuffer(attr.getNodeValue())));
|
|
result.append ("\"");
|
|
}
|
|
|
|
|
|
//
|
|
NodeList children = node.getChildNodes();
|
|
if (children == null)
|
|
{
|
|
result.append(" />");
|
|
}
|
|
else
|
|
{
|
|
int childrenCount = children.getLength ();
|
|
|
|
if (childrenCount == 0)
|
|
{
|
|
result.append(" />");
|
|
}
|
|
else
|
|
{
|
|
result.append('>');
|
|
|
|
for (int i = 0; i < childrenCount; i++)
|
|
{
|
|
result.append (process (children.item(i), datas, webappPath, errorOutput));
|
|
}
|
|
|
|
result.append("</");
|
|
result.append(node.getNodeName());
|
|
result.append('>');
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static protected Document buildTree (InputStream source, StringBuffer errorOutput)
|
|
{
|
|
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 ();
|
|
log.debug ("schema=" + schema);
|
|
|
|
// Parse the input file.
|
|
result = db.parse (source);
|
|
|
|
if (errorHandler.hasError ())
|
|
{
|
|
errorOutput.append (errorHandler.toString ());
|
|
}
|
|
}
|
|
catch (ParserConfigurationException exception)
|
|
{
|
|
String errorMessage = "Parser configuration exception: " + exception.getMessage ();
|
|
errorOutput.append (errorMessage);
|
|
log.error (errorMessage);
|
|
result = null;
|
|
}
|
|
catch (SAXException exception)
|
|
{
|
|
String errorMessage = "Error during SAX parsing: " + exception.getMessage ();
|
|
errorOutput.append (errorMessage);
|
|
log.error (errorMessage);
|
|
result = null;
|
|
}
|
|
catch (IOException exception)
|
|
{
|
|
String errorMessage = "IOError during parsing." + exception.getMessage ();
|
|
errorOutput.append (errorMessage);
|
|
log.error (errorMessage);
|
|
result = null;
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static protected Document fileToTree (String fileName, StringBuffer errorOutput)
|
|
{
|
|
Document result;
|
|
|
|
try
|
|
{
|
|
result = buildTree (new FileInputStream (new File (fileName)), errorOutput);
|
|
}
|
|
catch (IOException exception)
|
|
{
|
|
String errorMessage = "IOError during parsing." + exception.getMessage ();
|
|
errorOutput.append (errorMessage);
|
|
log.error (errorMessage);
|
|
result = null;
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static protected void addMetaTag (Document doc, String name, String content)
|
|
{
|
|
// Find head tag.
|
|
|
|
Node headNode = Presenter.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());
|
|
}
|
|
|
|
|
|
/**
|
|
* Finds the node containing the <head> tag.
|
|
*
|
|
* @param node
|
|
* Document node.
|
|
* @return The head tag node
|
|
*/
|
|
static protected Node findHeadNode (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;
|
|
}
|
|
|
|
|
|
/**
|
|
* Any ampersand lt;, ampersand gt; and ampersand amp; sequences in text
|
|
* nodes get read in as symbols. This method converts them back to entities.
|
|
*
|
|
* @param s String that is to have the entities restored..
|
|
* @return The processed string.
|
|
*/
|
|
static public String restoreEntities (StringBuffer s)
|
|
{
|
|
String result;
|
|
|
|
if (s == null)
|
|
{
|
|
result = null;
|
|
}
|
|
else
|
|
{
|
|
StringBuffer str = new StringBuffer();
|
|
|
|
int len = (s != null) ? s.length() : 0;
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
char ch = s.charAt(i);
|
|
switch (ch)
|
|
{
|
|
case '<':
|
|
{
|
|
str.append("<");
|
|
break;
|
|
}
|
|
|
|
case '>':
|
|
{
|
|
str.append(">");
|
|
break;
|
|
}
|
|
|
|
case '&':
|
|
{
|
|
str.append("&");
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
str.append(ch);
|
|
}
|
|
}
|
|
}
|
|
result = str.toString ();
|
|
}
|
|
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the text for an element. Converts new lines to spaces.
|
|
*
|
|
* @param node
|
|
*/
|
|
static protected String getElementText (Node node)
|
|
{
|
|
String result;
|
|
result = ""; // Grrrr, Java ...
|
|
|
|
NodeList children = node.getChildNodes();
|
|
if (children == null)
|
|
{
|
|
result = "";
|
|
}
|
|
else
|
|
{
|
|
boolean ended = false;
|
|
int childCounter = 0;
|
|
int childCount = children.getLength ();
|
|
while (!ended)
|
|
{
|
|
if (childCounter >= childCount)
|
|
{
|
|
ended = true;
|
|
result = "";
|
|
}
|
|
else
|
|
{
|
|
Node child = children.item (childCounter);
|
|
if (child.getNodeType () == Node.TEXT_NODE)
|
|
{
|
|
result = newLinesToSpaces (child.getNodeValue ()); // STU (+=, newLines...)
|
|
ended = true;
|
|
}
|
|
else
|
|
{
|
|
childCounter += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/**
|
|
* Converts New Line characters to spaces. This is used when for example
|
|
* the text in a div tag goes over serveral lines.
|
|
*
|
|
* @param text String
|
|
* @return String
|
|
*/
|
|
static protected String newLinesToSpaces (String text)
|
|
{
|
|
StringBuffer result = new StringBuffer (text);
|
|
|
|
for (int i = 0; i < result.length(); i++)
|
|
{
|
|
if (result.charAt (i) == '\n')
|
|
{
|
|
result.setCharAt (i,' ');
|
|
}
|
|
}
|
|
|
|
//
|
|
return (result.toString());
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static protected StringBuffer processAttributes (NamedNodeMap attrs, TagData model)
|
|
{
|
|
StringBuffer result;
|
|
|
|
result = new StringBuffer ();
|
|
|
|
// Build the original attributes list.
|
|
HashMap<String, String> mergedAttributes;
|
|
mergedAttributes = new HashMap<String, String> ();
|
|
for (int attributeCounter = 0; attributeCounter < attrs.getLength(); attributeCounter++)
|
|
{
|
|
Attr attr = (Attr) attrs.item (attributeCounter);
|
|
mergedAttributes.put (attr.getNodeName(), attr.getNodeValue ());
|
|
}
|
|
|
|
|
|
// Put model attributes in the merged attributes list.
|
|
if (model != null)
|
|
{
|
|
Attributes modelAttributes = model.getAttributes();
|
|
|
|
if (modelAttributes != null)
|
|
{
|
|
Iterator iterator = modelAttributes.entrySet().iterator();
|
|
|
|
while (iterator.hasNext())
|
|
{
|
|
Map.Entry<String, String> attribute = (Map.Entry<String, String>) iterator.next();
|
|
|
|
if (mergedAttributes.containsKey (attribute.getKey ()))
|
|
{
|
|
if (attribute.getKey ().equalsIgnoreCase ("style"))
|
|
{
|
|
mergedAttributes.put (attribute.getKey (), mergedAttributes.get (attribute.getKey ()) + attribute.getValue ());
|
|
}
|
|
else
|
|
{
|
|
mergedAttributes.put (attribute.getKey (), attribute.getValue ());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mergedAttributes.put (attribute.getKey (), attribute.getValue ());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Display the attributes
|
|
Iterator iterator = mergedAttributes.entrySet().iterator();
|
|
while (iterator.hasNext ())
|
|
{
|
|
Map.Entry<String, String> attribute = (Map.Entry<String, String>) iterator.next();
|
|
result.append(" " + attribute.getKey () + "=\"" + attribute.getValue ()+ "\"");
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static public String extractBodyContent (StringBuffer data)
|
|
{
|
|
String result = null;
|
|
|
|
// Extract the body content.
|
|
String dataLowerCase = data.toString ().toLowerCase ();
|
|
|
|
int startBody = dataLowerCase.indexOf ("<body>");
|
|
int endBody = dataLowerCase.indexOf ("</body>");
|
|
|
|
// Note: as failed search is improbable, no care about complexity
|
|
// in failed search case.
|
|
if ((startBody == -1) || (endBody == -1))
|
|
{
|
|
result = null;
|
|
}
|
|
else
|
|
{
|
|
result = data.substring (startBody + 6, endBody).trim ();
|
|
}
|
|
|
|
//
|
|
return (result);
|
|
}
|
|
}
|