From 27e8c74721184967a07ce5979348ac5510c8ab81 Mon Sep 17 00:00:00 2001 From: "Christian P. MOMON" Date: Tue, 30 Jul 2013 11:37:40 +0200 Subject: [PATCH] Improve classes organization. --- .../xidyn/presenters/DomPresenter.java | 950 +---------------- .../xidyn/presenters/DomPresenterCore.java | 954 ++++++++++++++++++ .../xidyn/presenters/FilePresenter.java | 3 +- .../devinsy/xidyn/presenters/Presenter.java | 132 +-- .../xidyn/presenters/StringPresenter.java | 5 +- .../xidyn/presenters/URLPresenter.java | 34 +- src/fr/devinsy/xidyn/utils/XidynUtils.java | 130 +++ 7 files changed, 1139 insertions(+), 1069 deletions(-) create mode 100644 src/fr/devinsy/xidyn/presenters/DomPresenterCore.java create mode 100644 src/fr/devinsy/xidyn/utils/XidynUtils.java diff --git a/src/fr/devinsy/xidyn/presenters/DomPresenter.java b/src/fr/devinsy/xidyn/presenters/DomPresenter.java index 725877d..aa04419 100644 --- a/src/fr/devinsy/xidyn/presenters/DomPresenter.java +++ b/src/fr/devinsy/xidyn/presenters/DomPresenter.java @@ -1,41 +1,18 @@ 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; /** * */ -public class DomPresenter extends Presenter +public class DomPresenter extends DomPresenterCore implements Presenter { static final public char INDEX_SEPARATOR = '_'; static private Logger logger = LoggerFactory.getLogger(DomPresenter.class); @@ -57,6 +34,13 @@ public class DomPresenter extends Presenter 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. StringWriter htmlCode = new StringWriter(); - DomPresenter.dynamize(htmlCode, this.doc, datas); + DomPresenterCore.dynamize(htmlCode, this.doc, datas); result = new StringBuffer(htmlCode.toString()); } @@ -124,7 +108,7 @@ public class DomPresenter extends Presenter * */ @Override - public boolean isOutdated() + public boolean isOutdated() throws Exception { boolean result; @@ -148,918 +132,6 @@ public class DomPresenter extends Presenter public void setSource(final Document doc) { this.doc = doc; - DomPresenter.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 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> iterator = source.entrySet().iterator(); - - while (iterator.hasNext()) - { - Map.Entry 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 = "\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(""); - - 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(" 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 mergedAttributes; - mergedAttributes = new HashMap(); - 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> iterator = dataAttributes.entrySet().iterator(); - - while (iterator.hasNext()) - { - Map.Entry 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> iterator = mergedAttributes.entrySet().iterator(); - while (iterator.hasNext()) - { - Map.Entry 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("'); - } - - 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("'); - } - } - } - 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("\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"); + DomPresenterCore.addMetaTag(this.doc, "generator", "XIDYN 1.0.0"); } } diff --git a/src/fr/devinsy/xidyn/presenters/DomPresenterCore.java b/src/fr/devinsy/xidyn/presenters/DomPresenterCore.java new file mode 100644 index 0000000..3d3f8c0 --- /dev/null +++ b/src/fr/devinsy/xidyn/presenters/DomPresenterCore.java @@ -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 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> iterator = source.entrySet().iterator(); + + while (iterator.hasNext()) + { + Map.Entry 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 = "\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(""); + + 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(" 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 mergedAttributes; + mergedAttributes = new HashMap(); + 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> iterator = dataAttributes.entrySet().iterator(); + + while (iterator.hasNext()) + { + Map.Entry 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> iterator = mergedAttributes.entrySet().iterator(); + while (iterator.hasNext()) + { + Map.Entry 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("'); + } + + 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("'); + } + } + } + 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("\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"); + } +} diff --git a/src/fr/devinsy/xidyn/presenters/FilePresenter.java b/src/fr/devinsy/xidyn/presenters/FilePresenter.java index 55c9bde..36d8b12 100644 --- a/src/fr/devinsy/xidyn/presenters/FilePresenter.java +++ b/src/fr/devinsy/xidyn/presenters/FilePresenter.java @@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; import fr.devinsy.xidyn.data.TagDataListById; 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. - StringWriter htmlCode = new StringWriter(Presenter.estimatedTargetLength(source.length())); + StringWriter htmlCode = new StringWriter(XidynUtils.estimatedTargetLength(source.length())); htmlCode.write(doctype); htmlCode.write('\n'); diff --git a/src/fr/devinsy/xidyn/presenters/Presenter.java b/src/fr/devinsy/xidyn/presenters/Presenter.java index f626bf0..2423f28 100644 --- a/src/fr/devinsy/xidyn/presenters/Presenter.java +++ b/src/fr/devinsy/xidyn/presenters/Presenter.java @@ -1,17 +1,21 @@ 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.TagDataManager; /** * */ -public abstract class Presenter +public interface Presenter { - private static final Pattern BODY_PATTERN = Pattern.compile("^.*<[bB][oO][dD][yY]>\\s*(.*\\S)\\s*.*$"); + + /** + * + * @param datas + * @return + * @throws Exception + */ + public abstract StringBuffer dynamize() throws Exception; /** * @@ -40,122 +44,4 @@ public abstract class Presenter * @return */ 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); - } } diff --git a/src/fr/devinsy/xidyn/presenters/StringPresenter.java b/src/fr/devinsy/xidyn/presenters/StringPresenter.java index ec2e868..d730637 100644 --- a/src/fr/devinsy/xidyn/presenters/StringPresenter.java +++ b/src/fr/devinsy/xidyn/presenters/StringPresenter.java @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; import fr.devinsy.xidyn.data.TagDataListById; 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())); } - StringWriter htmlCode = new StringWriter(Presenter.estimatedTargetLength(this.html.length())); + StringWriter htmlCode = new StringWriter(XidynUtils.estimatedTargetLength(this.html.length())); if ((this.html.startsWith("'))); @@ -86,7 +87,7 @@ public class StringPresenter extends DomPresenter } else { - String bodyContent = extractBodyContent(htmlTarget); + String bodyContent = XidynUtils.extractBodyContent(htmlTarget); if (bodyContent == null) { diff --git a/src/fr/devinsy/xidyn/presenters/URLPresenter.java b/src/fr/devinsy/xidyn/presenters/URLPresenter.java index 4777bd1..bdcd8ed 100644 --- a/src/fr/devinsy/xidyn/presenters/URLPresenter.java +++ b/src/fr/devinsy/xidyn/presenters/URLPresenter.java @@ -2,6 +2,7 @@ package fr.devinsy.xidyn.presenters; import java.io.BufferedReader; import java.io.FileReader; +import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; import java.net.MalformedURLException; @@ -12,6 +13,7 @@ import org.slf4j.LoggerFactory; import fr.devinsy.xidyn.data.TagDataListById; 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) @@ -53,6 +54,7 @@ public class URLPresenter extends DomPresenter /** * No need to be synchronized. */ + @Override public StringBuffer dynamize() throws Exception { StringBuffer result; @@ -106,7 +108,7 @@ public class URLPresenter extends DomPresenter } // 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('\n'); @@ -119,7 +121,7 @@ public class URLPresenter extends DomPresenter } /** - * + * {@inheritDoc} */ @Override public StringBuffer dynamize(final TagDataManager datas) throws Exception @@ -128,7 +130,7 @@ public class URLPresenter extends DomPresenter } /** - * + * {@inheritDoc} */ @Override public String getSource() @@ -141,6 +143,30 @@ public class URLPresenter extends DomPresenter 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; + } + /** * */ diff --git a/src/fr/devinsy/xidyn/utils/XidynUtils.java b/src/fr/devinsy/xidyn/utils/XidynUtils.java new file mode 100644 index 0000000..0c83e2b --- /dev/null +++ b/src/fr/devinsy/xidyn/utils/XidynUtils.java @@ -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*.*$"); + + /** + * 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); + } +}