Improve classes organization.

This commit is contained in:
Christian P. MOMON 2013-07-30 11:37:40 +02:00
parent bc26b40750
commit 27e8c74721
7 changed files with 1139 additions and 1069 deletions

View file

@ -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 &lt;head&gt; tag.
*
* @param node
* Document node.
* @return The head tag node
*/
private static Node findHeadNode(final Node node)
{
Node headNode = null;
int type = node.getNodeType();
switch (type)
{
// print document
case Node.DOCUMENT_NODE:
{
headNode = findHeadNode(((Document) node).getDocumentElement());
break;
}
case Node.ELEMENT_NODE:
{
String tag = node.getNodeName();
if ("head".equals(tag))
{
headNode = node;
break;
}
NodeList children = node.getChildNodes();
int numChildren = 0;
if (children != null)
{
numChildren = children.getLength();
}
for (int i = 0; i < numChildren; i++)
{
headNode = findHeadNode(children.item(i));
if (headNode != null)
{
break;
}
}
break;
}
}
return headNode;
}
/**
*
*/
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");
} }
} }

View 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 &lt;head&gt; tag.
*
* @param node
* Document node.
* @return The head tag node
*/
private static Node findHeadNode(final Node node)
{
Node headNode = null;
int type = node.getNodeType();
switch (type)
{
// print document
case Node.DOCUMENT_NODE:
{
headNode = findHeadNode(((Document) node).getDocumentElement());
break;
}
case Node.ELEMENT_NODE:
{
String tag = node.getNodeName();
if ("head".equals(tag))
{
headNode = node;
break;
}
NodeList children = node.getChildNodes();
int numChildren = 0;
if (children != null)
{
numChildren = children.getLength();
}
for (int i = 0; i < numChildren; i++)
{
headNode = findHeadNode(children.item(i));
if (headNode != null)
{
break;
}
}
break;
}
}
return headNode;
}
/**
*
*/
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");
}
}

View file

@ -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');

View file

@ -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("&lt;");
break;
}
case '>':
{
buffer.append("&gt;");
break;
}
case '&':
{
buffer.append("&amp;");
break;
}
default:
{
buffer.append(letter);
}
}
}
result = buffer.toString();
}
//
return (result);
}
} }

View file

@ -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)
{ {

View file

@ -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;
}
/** /**
* *
*/ */

View 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("&lt;");
break;
}
case '>':
{
buffer.append("&gt;");
break;
}
case '&':
{
buffer.append("&amp;");
break;
}
default:
{
buffer.append(letter);
}
}
}
result = buffer.toString();
}
//
return (result);
}
}