Package org.rendersnake.site

Source Code of org.rendersnake.site.HtmlToRenderSnakeTranslator

package org.rendersnake.site;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.io.output.ByteArrayOutputStream;
import org.w3c.tidy.Tidy;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class HtmlToRenderSnakeTranslator extends DefaultHandler {

    // http://www.elharo.com/blog/software-development/web-development/2007/01/29/all-empty-tags-in-html/
    public static String[] EMPTY_ELEMENTS = new String[]{"meta","br","hr","link","base","img","embed","param","area","col","input","frame","base","basefront","isindex"};
   
    // stats
    public static int TRANSLATIONS_OK = 0;
    public static int TRANSLATIONS_FAILED = 0;   
    public static int TRANSLATIONS_LINECOUNT = 0;   
   
    public String errorMessage = "";
    public int spaces = 4;
    private int indent = 0;
    public StringWriter out = new StringWriter();

    public static void main(String[] args) throws Exception {
        HtmlToRenderSnakeTranslator translator = new HtmlToRenderSnakeTranslator();
        translator.translate(HtmlToRenderSnakeTranslator.class.getResourceAsStream("test.html"),true);
        System.out.println(translator.toJavaSource());
        System.out.println(translator.errorMessage);
    }

    public boolean isSuccess() {
        return errorMessage.length() == 0;
    }

    public void translate(InputStream rawInput, boolean useTidy) throws Exception {
        if (rawInput.available() == 0) {
            errorMessage = "Nothing to translate";
            return;
        }
        InputStream is = useTidy ? this.tidy(rawInput) : rawInput;
        StringWriter sw = new StringWriter();
        sw.write('<');
        sw.write("rs");
        sw.write(">\n");
        this.writeContentsOn(is, sw);
        sw.write("\n</");
        sw.write("rs");
        sw.write('>');
        SAXParser p = SAXParserFactory.newInstance().newSAXParser();
        try {
            p.parse(new ByteArrayInputStream(sw.toString().getBytes()), this);
            TRANSLATIONS_OK++;
            TRANSLATIONS_LINECOUNT += this.countLinesIn(out.toString());
        } catch (org.xml.sax.SAXParseException sax) {
            TRANSLATIONS_FAILED++;
            int column = sax.getColumnNumber();
            int line = sax.getLineNumber();
            errorMessage = String.format("At line=%s,column=%s an error was detected: %s\n\n%s", line, column, sax.getMessage(), this.getHintFromTo(line, column, sw.toString()));
        }
        is.close();
    }
   
    private int countLinesIn(String content) {
        int sum = 0;
        for (int i = 0; i < content.length(); i++) {
            sum += content.charAt(i) == '\n' ? 1 : 0;           
        }
        return sum;
    }

    private String getHintFromTo(int line, int column, String content) {
        String[] lines = content.split("\n");
        String hint = lines[line - 1];
        return hint.substring(0, column - 1) + "==>" + hint.substring(column, hint.length());
    }

    private void writeContentsOn(InputStream is, StringWriter sw) throws Exception {
        while (is.available() > 0) {
            sw.write(is.read());
        }
    }

    public String toJavaSource() {
        return out.toString();
    }

    @Override
    public void startElement(String uri, String localName, String qname, Attributes attrs) throws SAXException {
        if ("rs".equals(qname))
            return;
        this.doIndent();
        out.append('.');
        out.append(this.dashToUpper(qname));
        String attrExpr = this.buildAttributeInvocations(attrs);
        if (attrExpr.length() > 0)
            out.append('(').append(attrExpr).append(')');
        else
            out.append("()");
        out.append("\n");
        indent++;
    }

    @Override
    public void endElement(String uri, String localName, String qname) throws SAXException {
        if ("rs".equals(qname))
            return;
        indent--;
        if (isEmptyElement(qname.toLowerCase())) return;
        this.doIndent();
        out.append("._");
        out.append(this.dashToUpper(qname));
        out.append("()");
        out.append("\n");
    }

    private void doIndent() {
        for (int i = 0; i < indent * spaces; i++)
            out.append(' ');
    }

    public String buildAttributeInvocations(Attributes attrs) {
        StringWriter expression = new StringWriter();
        for (int i = 0; i < attrs.getLength(); i++) {
            String aname = attrs.getLocalName(i);
            String avalue = attrs.getValue(i);
            if (i > 0)
                expression.append('.');

            // reserved words
            if ("class".equals(aname))
                aname = "class_";
            else if ("for".equals(aname))
                aname = "for_";
            aname = this.dashToUpper(aname);

            expression.append(aname).append("(\"").append(avalue).append("\")");
        }
        return expression.toString();
    }

    private String dashToUpper(String in) {
        String out = in;
        if (in.indexOf('-') != -1) {
            int dash = in.indexOf('-');
            out = in.substring(0, dash) + Character.toUpperCase(in.charAt(dash+1)) + in.substring(dash+2);
        }
        return out;
    }
   
   
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (length == 0)
            return;
        String content = new String(ch, start, length).trim();
        if (content.length() == 0)
            return;
        this.doIndent();
        // escape quotes
        content = content.replaceAll("\"", "\\\\\"");
        content = content.replace("\n", " ");
        out.append(".write(\"");
        out.append(content);
        out.append("\")\n");
    }

    @Override
    public void endDocument() throws SAXException {
        out.append(";");
    }

    @Override
    public void startDocument() throws SAXException {
        out.append("html\n");
        indent++;
    }
   
    public boolean isEmptyElement(String elm) {
        for(String each : EMPTY_ELEMENTS) {
            if (each.equals(elm)) return true;
        }
        return false;
    }
   
    public InputStream tidy(InputStream is) {
        Tidy tidy = new Tidy();
        tidy.setXHTML(false);
        tidy.setPrintBodyOnly(true);
        tidy.setDocType("loose");
        tidy.setXHTML(true);
        tidy.setForceOutput(true);
        java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(1024);
        tidy.parse(is,out);
        return new ByteArrayInputStream(out.toByteArray());
    }
}
TOP

Related Classes of org.rendersnake.site.HtmlToRenderSnakeTranslator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.