Improve classes organization.
This commit is contained in:
parent
bc26b40750
commit
27e8c74721
7 changed files with 1139 additions and 1069 deletions
|
@ -1,41 +1,18 @@
|
||||||
package fr.devinsy.xidyn.presenters;
|
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.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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.w3c.dom.Attr;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
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;
|
|
||||||
import fr.devinsy.xidyn.data.TagData;
|
|
||||||
import fr.devinsy.xidyn.data.TagDataListById;
|
import fr.devinsy.xidyn.data.TagDataListById;
|
||||||
import fr.devinsy.xidyn.data.TagDataListByIndex;
|
|
||||||
import fr.devinsy.xidyn.data.TagDataManager;
|
import fr.devinsy.xidyn.data.TagDataManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DomPresenter extends Presenter
|
public class DomPresenter extends DomPresenterCore implements Presenter
|
||||||
{
|
{
|
||||||
static final public char INDEX_SEPARATOR = '_';
|
static final public char INDEX_SEPARATOR = '_';
|
||||||
static private Logger logger = LoggerFactory.getLogger(DomPresenter.class);
|
static private Logger logger = LoggerFactory.getLogger(DomPresenter.class);
|
||||||
|
@ -57,6 +34,13 @@ public class DomPresenter extends Presenter
|
||||||
setSource(doc);
|
setSource(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringBuffer dynamize() throws Exception
|
||||||
|
{
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -76,7 +60,7 @@ public class DomPresenter extends Presenter
|
||||||
{
|
{
|
||||||
// Build the web page.
|
// Build the web page.
|
||||||
StringWriter htmlCode = new StringWriter();
|
StringWriter htmlCode = new StringWriter();
|
||||||
DomPresenter.dynamize(htmlCode, this.doc, datas);
|
DomPresenterCore.dynamize(htmlCode, this.doc, datas);
|
||||||
result = new StringBuffer(htmlCode.toString());
|
result = new StringBuffer(htmlCode.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +108,7 @@ public class DomPresenter extends Presenter
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isOutdated()
|
public boolean isOutdated() throws Exception
|
||||||
{
|
{
|
||||||
boolean result;
|
boolean result;
|
||||||
|
|
||||||
|
@ -148,918 +132,6 @@ public class DomPresenter extends Presenter
|
||||||
public void setSource(final Document doc)
|
public void setSource(final Document doc)
|
||||||
{
|
{
|
||||||
this.doc = doc;
|
this.doc = doc;
|
||||||
DomPresenter.addMetaTag(this.doc, "generator", "XIDYN 1.0.0");
|
DomPresenterCore.addMetaTag(this.doc, "generator", "XIDYN 1.0.0");
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
{
|
|
||||||
DomPresenter.addMetaTag(result, "generator", "XID 0.0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Xidyn a file with data.
|
|
||||||
*/
|
|
||||||
static public StringBuffer dynamize(final Document doc, final TagDataListById datas) throws Exception
|
|
||||||
{
|
|
||||||
StringBuffer result;
|
|
||||||
|
|
||||||
StringWriter htmlCode = new StringWriter();
|
|
||||||
DomPresenter.dynamize(htmlCode, doc, datas);
|
|
||||||
result = htmlCode.getBuffer();
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dynamize a file with data.
|
|
||||||
*/
|
|
||||||
static public void dynamize(final Writer result, final Document doc, final TagDataListById data) throws Exception
|
|
||||||
{
|
|
||||||
process(result, doc, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 <head> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static String getClassAttributeValue(final 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the text for an element. Converts new lines to spaces.
|
|
||||||
*
|
|
||||||
* @param node
|
|
||||||
*/
|
|
||||||
static private String getElementText(final Node node)
|
|
||||||
{
|
|
||||||
String result;
|
|
||||||
|
|
||||||
NodeList children = node.getChildNodes();
|
|
||||||
if ((children == null) || (children.getLength() == 0))
|
|
||||||
{
|
|
||||||
result = "";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
boolean ended = false;
|
|
||||||
result = ""; // Grrrr, Java ...
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// STU (+=, newLines...)
|
|
||||||
result = newLinesToSpaces(child.getNodeValue());
|
|
||||||
ended = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
childCounter += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private TagAttributes mergeAttributes(final TagAttributes target, final TagAttributes source)
|
|
||||||
{
|
|
||||||
TagAttributes result;
|
|
||||||
|
|
||||||
//
|
|
||||||
if (target == null)
|
|
||||||
{
|
|
||||||
result = source;
|
|
||||||
}
|
|
||||||
else if (source == null)
|
|
||||||
{
|
|
||||||
result = target;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = new TagAttributes(target);
|
|
||||||
|
|
||||||
Iterator<Map.Entry<String, String>> iterator = source.entrySet().iterator();
|
|
||||||
|
|
||||||
while (iterator.hasNext())
|
|
||||||
{
|
|
||||||
Map.Entry<String, String> attribute = iterator.next();
|
|
||||||
|
|
||||||
String currentValue = target.get(attribute.getKey());
|
|
||||||
|
|
||||||
if (currentValue == null)
|
|
||||||
{
|
|
||||||
result.put(attribute.getKey(), attribute.getValue());
|
|
||||||
}
|
|
||||||
else if (attribute.getKey().equals("style"))
|
|
||||||
{
|
|
||||||
result.put(attribute.getKey(), currentValue + attribute.getValue());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.put(attribute.getKey(), attribute.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts New Line characters to spaces. This is used when for example the
|
|
||||||
* text in a div tag goes over several lines.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* String
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
static private String newLinesToSpaces(final 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static void process(final Writer result, final Node node, final TagDataListById datas) throws Exception
|
|
||||||
{
|
|
||||||
DomPresenter.process(result, node, datas, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursive method that processes a node and any child nodes.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private void process(final Writer result, final Node node, final TagDataListById datas, final String suffix) throws Exception
|
|
||||||
{
|
|
||||||
logger.debug("process - started");
|
|
||||||
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";
|
|
||||||
|
|
||||||
// Is there anything to do?
|
|
||||||
if (node != null)
|
|
||||||
{
|
|
||||||
logger.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:
|
|
||||||
{
|
|
||||||
logger.debug("case Node.DOCUMENT_NODE");
|
|
||||||
DocumentType dt = ((Document) node).getDoctype();
|
|
||||||
|
|
||||||
if (dt != null)
|
|
||||||
{
|
|
||||||
// String publicId = dt.getPublicId();
|
|
||||||
String systemId = dt.getSystemId();
|
|
||||||
|
|
||||||
if ((systemId != null) && (systemId.equals(TRANSITIONAL_DTD)))
|
|
||||||
{
|
|
||||||
result.append(TRANSITIONAL_DOCTYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log.write(Log.TRACE,"publicId = " + publicId);
|
|
||||||
// Log.write(Log.TRACE,"systemId = " + systemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
DomPresenter.process(result, ((Document) node).getDocumentElement(), datas, suffix);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Node.ELEMENT_NODE:
|
|
||||||
{
|
|
||||||
logger.debug("case Node.ELEMENT_NODE [{}]", node.getNodeName());
|
|
||||||
|
|
||||||
NamedNodeMap attrs = node.getAttributes();
|
|
||||||
Node idAttr = attrs.getNamedItem("id");
|
|
||||||
|
|
||||||
if (idAttr != null)
|
|
||||||
{
|
|
||||||
DomPresenter.processElementWithId(result, node, attrs, idAttr, datas, suffix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DomPresenter.processElementBasically(result, node, datas, suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle entity reference nodes
|
|
||||||
case Node.ENTITY_REFERENCE_NODE:
|
|
||||||
{
|
|
||||||
logger.debug("case Node.ENTITY_REFERENCE_NODE");
|
|
||||||
|
|
||||||
result.append('&');
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
result.append(';');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print cdata sections
|
|
||||||
case Node.CDATA_SECTION_NODE:
|
|
||||||
{
|
|
||||||
logger.debug("case Node.CDATA_SECTION_NODE");
|
|
||||||
|
|
||||||
result.append("<![CDATA[");
|
|
||||||
result.append(node.getNodeValue());
|
|
||||||
result.append("]]>");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print text
|
|
||||||
case Node.TEXT_NODE:
|
|
||||||
{
|
|
||||||
logger.debug("case Node.TEXTE_NODE");
|
|
||||||
result.append(Presenter.restoreEntities(new StringBuffer(node.getNodeValue())));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print processing instruction
|
|
||||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
|
||||||
{
|
|
||||||
logger.debug("Node.PROCESSING_INSTRUCTION_NODE");
|
|
||||||
|
|
||||||
result.append("<?");
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
String value = node.getNodeValue();
|
|
||||||
if ((value != null) && (value.length() > 0))
|
|
||||||
{
|
|
||||||
result.append(' ');
|
|
||||||
result.append(value);
|
|
||||||
}
|
|
||||||
result.append("?>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// logger.info ("result=" + result);
|
|
||||||
logger.debug("process - ended");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private StringBuffer processAttributes(final NamedNodeMap attrs)
|
|
||||||
{
|
|
||||||
StringBuffer result;
|
|
||||||
|
|
||||||
result = processAttributes(attrs, null, null, "");
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private StringBuffer processAttributes(final NamedNodeMap attrs, final TagAttributes dataAttributes)
|
|
||||||
{
|
|
||||||
StringBuffer result;
|
|
||||||
|
|
||||||
result = processAttributes(attrs, dataAttributes, "");
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private StringBuffer processAttributes(final NamedNodeMap attrs, final TagAttributes dataAttributes, final String suffix)
|
|
||||||
{
|
|
||||||
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 (dataAttributes != null)
|
|
||||||
{
|
|
||||||
Iterator<Map.Entry<String, String>> iterator = dataAttributes.entrySet().iterator();
|
|
||||||
|
|
||||||
while (iterator.hasNext())
|
|
||||||
{
|
|
||||||
Map.Entry<String, String> attribute = 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<Map.Entry<String, String>> iterator = mergedAttributes.entrySet().iterator();
|
|
||||||
while (iterator.hasNext())
|
|
||||||
{
|
|
||||||
Map.Entry<String, String> attribute = iterator.next();
|
|
||||||
|
|
||||||
if ((attribute.getKey().equals("id")) && (suffix.length() != 0))
|
|
||||||
{
|
|
||||||
result.append(" " + attribute.getKey() + "=\"" + attribute.getValue() + INDEX_SEPARATOR + suffix + "\"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append(" " + attribute.getKey() + "=\"" + attribute.getValue() + "\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private StringBuffer processAttributes(final NamedNodeMap attrs, final TagAttributes dataAttributes, final TagAttributes namedDataAttributes, final String suffix)
|
|
||||||
{
|
|
||||||
StringBuffer result;
|
|
||||||
|
|
||||||
result = processAttributes(attrs, mergeAttributes(dataAttributes, namedDataAttributes), suffix);
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static private void processChildren(final Writer result, final Node node, final TagDataListById datas) throws Exception
|
|
||||||
{
|
|
||||||
processChildren(result, node, datas, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static void processChildren(final Writer result, final Node node, final TagDataListById datas, final String suffix) throws Exception
|
|
||||||
{
|
|
||||||
// Get the iteration strategy.
|
|
||||||
SimpleTagData.IterationStrategy strategy;
|
|
||||||
|
|
||||||
NamedNodeMap attributes = node.getAttributes();
|
|
||||||
if (attributes == null)
|
|
||||||
{
|
|
||||||
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Node id = attributes.getNamedItem("id");
|
|
||||||
|
|
||||||
if (id == null)
|
|
||||||
{
|
|
||||||
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TagData dataCore = datas.getId(id.getNodeValue());
|
|
||||||
if (dataCore == null)
|
|
||||||
{
|
|
||||||
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
|
||||||
}
|
|
||||||
else if (dataCore instanceof SimpleTagData)
|
|
||||||
{
|
|
||||||
SimpleTagData data = (SimpleTagData) dataCore;
|
|
||||||
strategy = data.iterationStrategy();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate.
|
|
||||||
NodeList children = node.getChildNodes();
|
|
||||||
int childrenCount = children.getLength();
|
|
||||||
|
|
||||||
switch (strategy)
|
|
||||||
{
|
|
||||||
case ONLY_FIRST_ROW:
|
|
||||||
int lineCounter = 0;
|
|
||||||
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
|
||||||
{
|
|
||||||
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
|
||||||
{
|
|
||||||
lineCounter += 1;
|
|
||||||
if (lineCounter == 1)
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ONLY_FIRST_TWO_ROWS:
|
|
||||||
lineCounter = 0;
|
|
||||||
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
|
||||||
{
|
|
||||||
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
|
||||||
{
|
|
||||||
lineCounter += 1;
|
|
||||||
|
|
||||||
if ((lineCounter == 1) || (lineCounter == 2))
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ONLY_ROWS_WITH_ID:
|
|
||||||
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
|
||||||
{
|
|
||||||
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
|
||||||
{
|
|
||||||
NamedNodeMap attrs2 = children.item(childIndex).getAttributes();
|
|
||||||
|
|
||||||
if ((attrs2 != null) && (attrs2.getNamedItem("id") != null))
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ONLY_ROWS_WITHOUT_ID:
|
|
||||||
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
|
||||||
{
|
|
||||||
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
|
||||||
{
|
|
||||||
NamedNodeMap attrs2 = children.item(childIndex).getAttributes();
|
|
||||||
if ((attrs2 == null) || (attrs2.getNamedItem("id") == null))
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ALL_ROWS:
|
|
||||||
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
|
||||||
{
|
|
||||||
process(result, children.item(childIndex), datas, suffix);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO remove?
|
|
||||||
*/
|
|
||||||
private static void processElementBasically(final Writer result, final Node node, final TagDataListById datas) throws Exception
|
|
||||||
{
|
|
||||||
processElementBasically(result, node, datas, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static void processElementBasically(final Writer result, final Node node, final TagDataListById datas, final String suffix) throws Exception
|
|
||||||
{
|
|
||||||
logger.debug("processElementBasically - started [{}]", node.getNodeName());
|
|
||||||
|
|
||||||
// Open the tag.
|
|
||||||
result.append('<');
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
|
|
||||||
// Build the tag attributes.
|
|
||||||
// Attributes tagAttributes;
|
|
||||||
|
|
||||||
result.append(processAttributes(node.getAttributes(), null, suffix));
|
|
||||||
|
|
||||||
//
|
|
||||||
if ((node.getChildNodes() == null) || (node.getChildNodes().getLength() == 0))
|
|
||||||
{
|
|
||||||
result.append(" />");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append('>');
|
|
||||||
|
|
||||||
processChildren(result, node, datas, suffix);
|
|
||||||
|
|
||||||
result.append("</");
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
result.append('>');
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("processElementBasically - ended");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 private void processElementWithId(final Writer result, final Node node, final NamedNodeMap attrs, final Node idAttr, final TagDataListById datas) throws Exception
|
|
||||||
|
|
||||||
{
|
|
||||||
processElementWithId(result, node, attrs, idAttr, datas, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 private void processElementWithId(final Writer result, final Node node, final NamedNodeMap attrs, final Node idAttr, final TagDataListById datas, final String suffix) throws Exception
|
|
||||||
{
|
|
||||||
String tag = node.getNodeName();
|
|
||||||
|
|
||||||
// String idValue = idAttr.getNodeValue();
|
|
||||||
|
|
||||||
logger.debug("tag=" + tag);
|
|
||||||
|
|
||||||
// Get data of this id.
|
|
||||||
TagData dataCore = datas.get(idAttr.getNodeValue());
|
|
||||||
|
|
||||||
if (dataCore == null)
|
|
||||||
{
|
|
||||||
DomPresenter.processElementBasically(result, node, datas, suffix);
|
|
||||||
}
|
|
||||||
else if (dataCore instanceof SimpleTagData)
|
|
||||||
{
|
|
||||||
SimpleTagData data = (SimpleTagData) dataCore;
|
|
||||||
|
|
||||||
String theClass = data.attributes().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.attributes(), suffix));
|
|
||||||
|
|
||||||
if (((node.getChildNodes() == null) || (node.getChildNodes().getLength() == 0)) && ((data == null) || (data.display() == null)))
|
|
||||||
{
|
|
||||||
// Close the tag.
|
|
||||||
result.append(" />");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append('>');
|
|
||||||
|
|
||||||
// CHANGED, cpm:
|
|
||||||
|
|
||||||
// Insert data.
|
|
||||||
if ((data == null) || (data.display() == null))
|
|
||||||
{
|
|
||||||
processChildren(result, node, datas, suffix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append(data.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the tag.
|
|
||||||
result.append("</");
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
result.append('>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dataCore instanceof TagDataListByIndex)
|
|
||||||
{
|
|
||||||
TagDataListByIndex tags = (TagDataListByIndex) dataCore;
|
|
||||||
|
|
||||||
int nbLines = tags.size();
|
|
||||||
for (int nLine = 0; nLine < nbLines; nLine++)
|
|
||||||
{
|
|
||||||
if (tags.elementAt(nLine) instanceof SimpleTagData)
|
|
||||||
{
|
|
||||||
SimpleTagData data = (SimpleTagData) tags.elementAt(nLine);
|
|
||||||
|
|
||||||
// Open the tag.
|
|
||||||
result.append("<");
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
|
|
||||||
result.append(processAttributes(attrs, data.attributes(), Integer.toString(nLine)));
|
|
||||||
|
|
||||||
if (((node.getChildNodes() == null) || (node.getChildNodes().getLength() == 0)) && ((data == null) || (data.display() == null)))
|
|
||||||
{
|
|
||||||
// Close the tag.
|
|
||||||
result.append(" />\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append('>');
|
|
||||||
|
|
||||||
// CHANGED, cpm
|
|
||||||
|
|
||||||
// Insert data.
|
|
||||||
if ((data == null) || (data.display() == null))
|
|
||||||
{
|
|
||||||
processChildren(result, node, datas, suffix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.append(data.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the tag.
|
|
||||||
result.append("</");
|
|
||||||
result.append(node.getNodeName());
|
|
||||||
result.append(">\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Manage a Hashmap.
|
|
||||||
TagDataListById data = (TagDataListById) tags.elementAt(nLine);
|
|
||||||
|
|
||||||
DomPresenter.processElementWithId(result, node, attrs, idAttr, data, Integer.toString(nLine));
|
|
||||||
result.append('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.warn("Unknow type of IdDataId");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
logger.debug("Exit");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
954
src/fr/devinsy/xidyn/presenters/DomPresenterCore.java
Normal file
954
src/fr/devinsy/xidyn/presenters/DomPresenterCore.java
Normal file
|
@ -0,0 +1,954 @@
|
||||||
|
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;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
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;
|
||||||
|
import fr.devinsy.xidyn.data.TagData;
|
||||||
|
import fr.devinsy.xidyn.data.TagDataListById;
|
||||||
|
import fr.devinsy.xidyn.data.TagDataListByIndex;
|
||||||
|
import fr.devinsy.xidyn.data.TagDataManager;
|
||||||
|
import fr.devinsy.xidyn.utils.XidynUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DomPresenterCore
|
||||||
|
{
|
||||||
|
static final public char INDEX_SEPARATOR = '_';
|
||||||
|
static private Logger logger = LoggerFactory.getLogger(DomPresenterCore.class);
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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", "XID 0.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Xidyn a file with data.
|
||||||
|
*/
|
||||||
|
static public StringBuffer dynamize(final Document doc, final TagDataListById datas) throws Exception
|
||||||
|
{
|
||||||
|
StringBuffer result;
|
||||||
|
|
||||||
|
StringWriter htmlCode = new StringWriter();
|
||||||
|
DomPresenterCore.dynamize(htmlCode, doc, datas);
|
||||||
|
result = htmlCode.getBuffer();
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamize a file with data.
|
||||||
|
*/
|
||||||
|
static public void dynamize(final Writer result, final Document doc, final TagDataListById data) throws Exception
|
||||||
|
{
|
||||||
|
process(result, doc, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 <head> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static String getClassAttributeValue(final 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text for an element. Converts new lines to spaces.
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
*/
|
||||||
|
static private String getElementText(final Node node)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
NodeList children = node.getChildNodes();
|
||||||
|
if ((children == null) || (children.getLength() == 0))
|
||||||
|
{
|
||||||
|
result = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boolean ended = false;
|
||||||
|
result = ""; // Grrrr, Java ...
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// STU (+=, newLines...)
|
||||||
|
result = newLinesToSpaces(child.getNodeValue());
|
||||||
|
ended = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
childCounter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private TagAttributes mergeAttributes(final TagAttributes target, final TagAttributes source)
|
||||||
|
{
|
||||||
|
TagAttributes result;
|
||||||
|
|
||||||
|
//
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
result = source;
|
||||||
|
}
|
||||||
|
else if (source == null)
|
||||||
|
{
|
||||||
|
result = target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = new TagAttributes(target);
|
||||||
|
|
||||||
|
Iterator<Map.Entry<String, String>> iterator = source.entrySet().iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry<String, String> attribute = iterator.next();
|
||||||
|
|
||||||
|
String currentValue = target.get(attribute.getKey());
|
||||||
|
|
||||||
|
if (currentValue == null)
|
||||||
|
{
|
||||||
|
result.put(attribute.getKey(), attribute.getValue());
|
||||||
|
}
|
||||||
|
else if (attribute.getKey().equals("style"))
|
||||||
|
{
|
||||||
|
result.put(attribute.getKey(), currentValue + attribute.getValue());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.put(attribute.getKey(), attribute.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts New Line characters to spaces. This is used when for example the
|
||||||
|
* text in a div tag goes over several lines.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* String
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
static private String newLinesToSpaces(final 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static void process(final Writer result, final Node node, final TagDataListById datas) throws Exception
|
||||||
|
{
|
||||||
|
DomPresenterCore.process(result, node, datas, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive method that processes a node and any child nodes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private void process(final Writer result, final Node node, final TagDataListById datas, final String suffix) throws Exception
|
||||||
|
{
|
||||||
|
logger.debug("process - started");
|
||||||
|
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";
|
||||||
|
|
||||||
|
// Is there anything to do?
|
||||||
|
if (node != null)
|
||||||
|
{
|
||||||
|
logger.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:
|
||||||
|
{
|
||||||
|
logger.debug("case Node.DOCUMENT_NODE");
|
||||||
|
DocumentType dt = ((Document) node).getDoctype();
|
||||||
|
|
||||||
|
if (dt != null)
|
||||||
|
{
|
||||||
|
// String publicId = dt.getPublicId();
|
||||||
|
String systemId = dt.getSystemId();
|
||||||
|
|
||||||
|
if ((systemId != null) && (systemId.equals(TRANSITIONAL_DTD)))
|
||||||
|
{
|
||||||
|
result.append(TRANSITIONAL_DOCTYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.write(Log.TRACE,"publicId = " + publicId);
|
||||||
|
// Log.write(Log.TRACE,"systemId = " + systemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
DomPresenterCore.process(result, ((Document) node).getDocumentElement(), datas, suffix);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Node.ELEMENT_NODE:
|
||||||
|
{
|
||||||
|
logger.debug("case Node.ELEMENT_NODE [{}]", node.getNodeName());
|
||||||
|
|
||||||
|
NamedNodeMap attrs = node.getAttributes();
|
||||||
|
Node idAttr = attrs.getNamedItem("id");
|
||||||
|
|
||||||
|
if (idAttr != null)
|
||||||
|
{
|
||||||
|
DomPresenterCore.processElementWithId(result, node, attrs, idAttr, datas, suffix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DomPresenterCore.processElementBasically(result, node, datas, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle entity reference nodes
|
||||||
|
case Node.ENTITY_REFERENCE_NODE:
|
||||||
|
{
|
||||||
|
logger.debug("case Node.ENTITY_REFERENCE_NODE");
|
||||||
|
|
||||||
|
result.append('&');
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
result.append(';');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print cdata sections
|
||||||
|
case Node.CDATA_SECTION_NODE:
|
||||||
|
{
|
||||||
|
logger.debug("case Node.CDATA_SECTION_NODE");
|
||||||
|
|
||||||
|
result.append("<![CDATA[");
|
||||||
|
result.append(node.getNodeValue());
|
||||||
|
result.append("]]>");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print text
|
||||||
|
case Node.TEXT_NODE:
|
||||||
|
{
|
||||||
|
logger.debug("case Node.TEXTE_NODE");
|
||||||
|
result.append(XidynUtils.restoreEntities(new StringBuffer(node.getNodeValue())));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print processing instruction
|
||||||
|
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||||
|
{
|
||||||
|
logger.debug("Node.PROCESSING_INSTRUCTION_NODE");
|
||||||
|
|
||||||
|
result.append("<?");
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
String value = node.getNodeValue();
|
||||||
|
if ((value != null) && (value.length() > 0))
|
||||||
|
{
|
||||||
|
result.append(' ');
|
||||||
|
result.append(value);
|
||||||
|
}
|
||||||
|
result.append("?>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// logger.info ("result=" + result);
|
||||||
|
logger.debug("process - ended");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private StringBuffer processAttributes(final NamedNodeMap attrs)
|
||||||
|
{
|
||||||
|
StringBuffer result;
|
||||||
|
|
||||||
|
result = processAttributes(attrs, null, null, "");
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private StringBuffer processAttributes(final NamedNodeMap attrs, final TagAttributes dataAttributes)
|
||||||
|
{
|
||||||
|
StringBuffer result;
|
||||||
|
|
||||||
|
result = processAttributes(attrs, dataAttributes, "");
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private StringBuffer processAttributes(final NamedNodeMap attrs, final TagAttributes dataAttributes, final String suffix)
|
||||||
|
{
|
||||||
|
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 (dataAttributes != null)
|
||||||
|
{
|
||||||
|
Iterator<Map.Entry<String, String>> iterator = dataAttributes.entrySet().iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry<String, String> attribute = 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<Map.Entry<String, String>> iterator = mergedAttributes.entrySet().iterator();
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
Map.Entry<String, String> attribute = iterator.next();
|
||||||
|
|
||||||
|
if ((attribute.getKey().equals("id")) && (suffix.length() != 0))
|
||||||
|
{
|
||||||
|
result.append(" " + attribute.getKey() + "=\"" + attribute.getValue() + INDEX_SEPARATOR + suffix + "\"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append(" " + attribute.getKey() + "=\"" + attribute.getValue() + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private StringBuffer processAttributes(final NamedNodeMap attrs, final TagAttributes dataAttributes, final TagAttributes namedDataAttributes, final String suffix)
|
||||||
|
{
|
||||||
|
StringBuffer result;
|
||||||
|
|
||||||
|
result = processAttributes(attrs, mergeAttributes(dataAttributes, namedDataAttributes), suffix);
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static private void processChildren(final Writer result, final Node node, final TagDataListById datas) throws Exception
|
||||||
|
{
|
||||||
|
processChildren(result, node, datas, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static void processChildren(final Writer result, final Node node, final TagDataListById datas, final String suffix) throws Exception
|
||||||
|
{
|
||||||
|
// Get the iteration strategy.
|
||||||
|
SimpleTagData.IterationStrategy strategy;
|
||||||
|
|
||||||
|
NamedNodeMap attributes = node.getAttributes();
|
||||||
|
if (attributes == null)
|
||||||
|
{
|
||||||
|
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Node id = attributes.getNamedItem("id");
|
||||||
|
|
||||||
|
if (id == null)
|
||||||
|
{
|
||||||
|
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TagData dataCore = datas.getId(id.getNodeValue());
|
||||||
|
if (dataCore == null)
|
||||||
|
{
|
||||||
|
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
||||||
|
}
|
||||||
|
else if (dataCore instanceof SimpleTagData)
|
||||||
|
{
|
||||||
|
SimpleTagData data = (SimpleTagData) dataCore;
|
||||||
|
strategy = data.iterationStrategy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strategy = SimpleTagData.IterationStrategy.ALL_ROWS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate.
|
||||||
|
NodeList children = node.getChildNodes();
|
||||||
|
int childrenCount = children.getLength();
|
||||||
|
|
||||||
|
switch (strategy)
|
||||||
|
{
|
||||||
|
case ONLY_FIRST_ROW:
|
||||||
|
int lineCounter = 0;
|
||||||
|
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
||||||
|
{
|
||||||
|
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
lineCounter += 1;
|
||||||
|
if (lineCounter == 1)
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ONLY_FIRST_TWO_ROWS:
|
||||||
|
lineCounter = 0;
|
||||||
|
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
||||||
|
{
|
||||||
|
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
lineCounter += 1;
|
||||||
|
|
||||||
|
if ((lineCounter == 1) || (lineCounter == 2))
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ONLY_ROWS_WITH_ID:
|
||||||
|
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
||||||
|
{
|
||||||
|
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
NamedNodeMap attrs2 = children.item(childIndex).getAttributes();
|
||||||
|
|
||||||
|
if ((attrs2 != null) && (attrs2.getNamedItem("id") != null))
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ONLY_ROWS_WITHOUT_ID:
|
||||||
|
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
||||||
|
{
|
||||||
|
if (children.item(childIndex).getNodeType() == Node.ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
NamedNodeMap attrs2 = children.item(childIndex).getAttributes();
|
||||||
|
if ((attrs2 == null) || (attrs2.getNamedItem("id") == null))
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ALL_ROWS:
|
||||||
|
for (int childIndex = 0; childIndex < childrenCount; childIndex++)
|
||||||
|
{
|
||||||
|
process(result, children.item(childIndex), datas, suffix);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO remove?
|
||||||
|
*/
|
||||||
|
private static void processElementBasically(final Writer result, final Node node, final TagDataListById datas) throws Exception
|
||||||
|
{
|
||||||
|
processElementBasically(result, node, datas, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static void processElementBasically(final Writer result, final Node node, final TagDataListById datas, final String suffix) throws Exception
|
||||||
|
{
|
||||||
|
logger.debug("processElementBasically - started [{}]", node.getNodeName());
|
||||||
|
|
||||||
|
// Open the tag.
|
||||||
|
result.append('<');
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
|
||||||
|
// Build the tag attributes.
|
||||||
|
// Attributes tagAttributes;
|
||||||
|
|
||||||
|
result.append(processAttributes(node.getAttributes(), null, suffix));
|
||||||
|
|
||||||
|
//
|
||||||
|
if ((node.getChildNodes() == null) || (node.getChildNodes().getLength() == 0))
|
||||||
|
{
|
||||||
|
result.append(" />");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append('>');
|
||||||
|
|
||||||
|
processChildren(result, node, datas, suffix);
|
||||||
|
|
||||||
|
result.append("</");
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
result.append('>');
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("processElementBasically - ended");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 private void processElementWithId(final Writer result, final Node node, final NamedNodeMap attrs, final Node idAttr, final TagDataListById datas) throws Exception
|
||||||
|
|
||||||
|
{
|
||||||
|
processElementWithId(result, node, attrs, idAttr, datas, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 private void processElementWithId(final Writer result, final Node node, final NamedNodeMap attrs, final Node idAttr, final TagDataListById datas, final String suffix) throws Exception
|
||||||
|
{
|
||||||
|
String tag = node.getNodeName();
|
||||||
|
|
||||||
|
// String idValue = idAttr.getNodeValue();
|
||||||
|
|
||||||
|
logger.debug("tag=" + tag);
|
||||||
|
|
||||||
|
// Get data of this id.
|
||||||
|
TagData dataCore = datas.get(idAttr.getNodeValue());
|
||||||
|
|
||||||
|
if (dataCore == null)
|
||||||
|
{
|
||||||
|
DomPresenterCore.processElementBasically(result, node, datas, suffix);
|
||||||
|
}
|
||||||
|
else if (dataCore instanceof SimpleTagData)
|
||||||
|
{
|
||||||
|
SimpleTagData data = (SimpleTagData) dataCore;
|
||||||
|
|
||||||
|
String theClass = data.attributes().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.attributes(), suffix));
|
||||||
|
|
||||||
|
if (((node.getChildNodes() == null) || (node.getChildNodes().getLength() == 0)) && ((data == null) || (data.display() == null)))
|
||||||
|
{
|
||||||
|
// Close the tag.
|
||||||
|
result.append(" />");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append('>');
|
||||||
|
|
||||||
|
// CHANGED, cpm:
|
||||||
|
|
||||||
|
// Insert data.
|
||||||
|
if ((data == null) || (data.display() == null))
|
||||||
|
{
|
||||||
|
processChildren(result, node, datas, suffix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append(data.display());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the tag.
|
||||||
|
result.append("</");
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
result.append('>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dataCore instanceof TagDataListByIndex)
|
||||||
|
{
|
||||||
|
TagDataListByIndex tags = (TagDataListByIndex) dataCore;
|
||||||
|
|
||||||
|
int nbLines = tags.size();
|
||||||
|
for (int nLine = 0; nLine < nbLines; nLine++)
|
||||||
|
{
|
||||||
|
if (tags.elementAt(nLine) instanceof SimpleTagData)
|
||||||
|
{
|
||||||
|
SimpleTagData data = (SimpleTagData) tags.elementAt(nLine);
|
||||||
|
|
||||||
|
// Open the tag.
|
||||||
|
result.append("<");
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
|
||||||
|
result.append(processAttributes(attrs, data.attributes(), Integer.toString(nLine)));
|
||||||
|
|
||||||
|
if (((node.getChildNodes() == null) || (node.getChildNodes().getLength() == 0)) && ((data == null) || (data.display() == null)))
|
||||||
|
{
|
||||||
|
// Close the tag.
|
||||||
|
result.append(" />\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append('>');
|
||||||
|
|
||||||
|
// CHANGED, cpm
|
||||||
|
|
||||||
|
// Insert data.
|
||||||
|
if ((data == null) || (data.display() == null))
|
||||||
|
{
|
||||||
|
processChildren(result, node, datas, suffix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.append(data.display());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the tag.
|
||||||
|
result.append("</");
|
||||||
|
result.append(node.getNodeName());
|
||||||
|
result.append(">\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Manage a Hashmap.
|
||||||
|
TagDataListById data = (TagDataListById) tags.elementAt(nLine);
|
||||||
|
|
||||||
|
DomPresenterCore.processElementWithId(result, node, attrs, idAttr, data, Integer.toString(nLine));
|
||||||
|
result.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("Unknow type of IdDataId");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
logger.debug("Exit");
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import fr.devinsy.xidyn.data.TagDataListById;
|
import fr.devinsy.xidyn.data.TagDataListById;
|
||||||
import fr.devinsy.xidyn.data.TagDataManager;
|
import fr.devinsy.xidyn.data.TagDataManager;
|
||||||
|
import fr.devinsy.xidyn.utils.XidynUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -87,7 +88,7 @@ public class FilePresenter extends DomPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the web page.
|
// Build the web page.
|
||||||
StringWriter htmlCode = new StringWriter(Presenter.estimatedTargetLength(source.length()));
|
StringWriter htmlCode = new StringWriter(XidynUtils.estimatedTargetLength(source.length()));
|
||||||
htmlCode.write(doctype);
|
htmlCode.write(doctype);
|
||||||
htmlCode.write('\n');
|
htmlCode.write('\n');
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
package fr.devinsy.xidyn.presenters;
|
package fr.devinsy.xidyn.presenters;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import fr.devinsy.xidyn.data.TagDataListById;
|
import fr.devinsy.xidyn.data.TagDataListById;
|
||||||
import fr.devinsy.xidyn.data.TagDataManager;
|
import fr.devinsy.xidyn.data.TagDataManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class Presenter<E>
|
public interface Presenter
|
||||||
{
|
{
|
||||||
private static final Pattern BODY_PATTERN = Pattern.compile("^.*<[bB][oO][dD][yY]>\\s*(.*\\S)\\s*</[bB][oO][dD][yY]>.*$");
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param datas
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public abstract StringBuffer dynamize() throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -40,122 +44,4 @@ public abstract class Presenter<E>
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public abstract boolean isOutdated() throws Exception;
|
public abstract boolean isOutdated() throws Exception;
|
||||||
|
|
||||||
/**
|
|
||||||
* Good estimation of the target length able to optimize performance.
|
|
||||||
*/
|
|
||||||
public static int estimatedTargetLength(final long sourceLength)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (sourceLength < 1000)
|
|
||||||
{
|
|
||||||
result = (int) (sourceLength * 5);
|
|
||||||
}
|
|
||||||
else if (sourceLength < 50000)
|
|
||||||
{
|
|
||||||
result = (int) (sourceLength * 2);
|
|
||||||
}
|
|
||||||
else if (sourceLength < 800000)
|
|
||||||
{
|
|
||||||
result = (1000000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = (int) (sourceLength + 30000);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static public String extractBodyContent(final CharSequence source)
|
|
||||||
{
|
|
||||||
String result;
|
|
||||||
|
|
||||||
if (source == null)
|
|
||||||
{
|
|
||||||
result = "";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Matcher matcher = BODY_PATTERN.matcher(source);
|
|
||||||
if ((matcher.find()) && (matcher.groupCount() == 1))
|
|
||||||
{
|
|
||||||
// for (int i = 0; i <= matcher.groupCount(); i++)
|
|
||||||
// {
|
|
||||||
// System.out.println(i + " " + matcher.group(i));
|
|
||||||
// }
|
|
||||||
|
|
||||||
result = matcher.group(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @param source
|
|
||||||
* String that is to have the entities restored..
|
|
||||||
* @return The processed string.
|
|
||||||
*/
|
|
||||||
static public String restoreEntities(final StringBuffer source)
|
|
||||||
{
|
|
||||||
String result;
|
|
||||||
|
|
||||||
if (source == null)
|
|
||||||
{
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StringBuffer buffer = new StringBuffer(source.length() * 2);
|
|
||||||
|
|
||||||
int len = (source != null) ? source.length() : 0;
|
|
||||||
for (int index = 0; index < len; index++)
|
|
||||||
{
|
|
||||||
char letter = source.charAt(index);
|
|
||||||
switch (letter)
|
|
||||||
{
|
|
||||||
case '<':
|
|
||||||
{
|
|
||||||
buffer.append("<");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case '>':
|
|
||||||
{
|
|
||||||
buffer.append(">");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case '&':
|
|
||||||
{
|
|
||||||
buffer.append("&");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
buffer.append(letter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import fr.devinsy.xidyn.data.TagDataListById;
|
import fr.devinsy.xidyn.data.TagDataListById;
|
||||||
import fr.devinsy.xidyn.data.TagDataManager;
|
import fr.devinsy.xidyn.data.TagDataManager;
|
||||||
|
import fr.devinsy.xidyn.utils.XidynUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -68,7 +69,7 @@ public class StringPresenter extends DomPresenter
|
||||||
doc = DomPresenter.buildDom(new ByteArrayInputStream(htmlSource.getBytes()));
|
doc = DomPresenter.buildDom(new ByteArrayInputStream(htmlSource.getBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
StringWriter htmlCode = new StringWriter(Presenter.estimatedTargetLength(this.html.length()));
|
StringWriter htmlCode = new StringWriter(XidynUtils.estimatedTargetLength(this.html.length()));
|
||||||
if ((this.html.startsWith("<!DOCTYPE")) || (this.html.startsWith("<!doctype")))
|
if ((this.html.startsWith("<!DOCTYPE")) || (this.html.startsWith("<!doctype")))
|
||||||
{
|
{
|
||||||
htmlCode.write(this.html.substring(0, this.html.indexOf('>')));
|
htmlCode.write(this.html.substring(0, this.html.indexOf('>')));
|
||||||
|
@ -86,7 +87,7 @@ public class StringPresenter extends DomPresenter
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String bodyContent = extractBodyContent(htmlTarget);
|
String bodyContent = XidynUtils.extractBodyContent(htmlTarget);
|
||||||
|
|
||||||
if (bodyContent == null)
|
if (bodyContent == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@ package fr.devinsy.xidyn.presenters;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
@ -12,6 +13,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import fr.devinsy.xidyn.data.TagDataListById;
|
import fr.devinsy.xidyn.data.TagDataListById;
|
||||||
import fr.devinsy.xidyn.data.TagDataManager;
|
import fr.devinsy.xidyn.data.TagDataManager;
|
||||||
|
import fr.devinsy.xidyn.utils.XidynUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -34,7 +36,6 @@ public class URLPresenter extends DomPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws MalformedURLException
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public URLPresenter(final String source)
|
public URLPresenter(final String source)
|
||||||
|
@ -53,6 +54,7 @@ public class URLPresenter extends DomPresenter
|
||||||
/**
|
/**
|
||||||
* No need to be synchronized.
|
* No need to be synchronized.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public StringBuffer dynamize() throws Exception
|
public StringBuffer dynamize() throws Exception
|
||||||
{
|
{
|
||||||
StringBuffer result;
|
StringBuffer result;
|
||||||
|
@ -106,7 +108,7 @@ public class URLPresenter extends DomPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the web page.
|
// Build the web page.
|
||||||
StringWriter htmlCode = new StringWriter(Presenter.estimatedTargetLength(sourceURL.openConnection().getContentLength()));
|
StringWriter htmlCode = new StringWriter(XidynUtils.estimatedTargetLength(sourceURL.openConnection().getContentLength()));
|
||||||
htmlCode.write(doctype);
|
htmlCode.write(doctype);
|
||||||
htmlCode.write('\n');
|
htmlCode.write('\n');
|
||||||
|
|
||||||
|
@ -119,7 +121,7 @@ public class URLPresenter extends DomPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public StringBuffer dynamize(final TagDataManager datas) throws Exception
|
public StringBuffer dynamize(final TagDataManager datas) throws Exception
|
||||||
|
@ -128,7 +130,7 @@ public class URLPresenter extends DomPresenter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getSource()
|
public String getSource()
|
||||||
|
@ -141,6 +143,30 @@ public class URLPresenter extends DomPresenter
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isOutdated() throws IOException
|
||||||
|
{
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
long lastModified = this.sourceURL.openConnection().getLastModified();
|
||||||
|
if (this.sourceFileTime == lastModified)
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
130
src/fr/devinsy/xidyn/utils/XidynUtils.java
Normal file
130
src/fr/devinsy/xidyn/utils/XidynUtils.java
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
package fr.devinsy.xidyn.utils;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XidynUtils
|
||||||
|
{
|
||||||
|
private static final Pattern BODY_PATTERN = Pattern.compile("^.*<[bB][oO][dD][yY]>\\s*(.*\\S)\\s*</[bB][oO][dD][yY]>.*$");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Good estimation of the target length able to optimize performance.
|
||||||
|
*/
|
||||||
|
public static int estimatedTargetLength(final long sourceLength)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (sourceLength < 1000)
|
||||||
|
{
|
||||||
|
result = (int) (sourceLength * 5);
|
||||||
|
}
|
||||||
|
else if (sourceLength < 50000)
|
||||||
|
{
|
||||||
|
result = (int) (sourceLength * 2);
|
||||||
|
}
|
||||||
|
else if (sourceLength < 800000)
|
||||||
|
{
|
||||||
|
result = (1000000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = (int) (sourceLength + 30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static public String extractBodyContent(final CharSequence source)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Matcher matcher = BODY_PATTERN.matcher(source);
|
||||||
|
if ((matcher.find()) && (matcher.groupCount() == 1))
|
||||||
|
{
|
||||||
|
// for (int i = 0; i <= matcher.groupCount(); i++)
|
||||||
|
// {
|
||||||
|
// System.out.println(i + " " + matcher.group(i));
|
||||||
|
// }
|
||||||
|
|
||||||
|
result = matcher.group(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* String that is to have the entities restored..
|
||||||
|
* @return The processed string.
|
||||||
|
*/
|
||||||
|
static public String restoreEntities(final StringBuffer source)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuffer buffer = new StringBuffer(source.length() * 2);
|
||||||
|
|
||||||
|
int len = (source != null) ? source.length() : 0;
|
||||||
|
for (int index = 0; index < len; index++)
|
||||||
|
{
|
||||||
|
char letter = source.charAt(index);
|
||||||
|
switch (letter)
|
||||||
|
{
|
||||||
|
case '<':
|
||||||
|
{
|
||||||
|
buffer.append("<");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '>':
|
||||||
|
{
|
||||||
|
buffer.append(">");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
{
|
||||||
|
buffer.append("&");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
buffer.append(letter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue