org.unitime.commons.ant.LowercaseTableNames.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.commons.ant.LowercaseTableNames.java

Source

/*
 * UniTime 3.2 - 3.5 (University Timetabling Application)
 * Copyright (C) 2010 - 2013, UniTime LLC, and individual contributors
 * as indicated by the @authors tag.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
*/
package org.unitime.commons.ant;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.dom4j.Attribute;
import org.dom4j.Comment;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Lower case table, column and sequence names, and foreign keys in .hbm.xml files.
 * This should negate the need to set MySQL to case insensitive mode on Linux based systems.
 * 
 * @author Tomas Muller
 *
 */
public class LowercaseTableNames extends Task {
    private SAXReader iSAXReader = null;
    private String iSource = null;
    private String iConfig = "hibernate.cfg.xml";

    public LowercaseTableNames() throws DocumentException, SAXException {
        iSAXReader = new SAXReader();
        iSAXReader.setEntityResolver(iEntityResolver);
        iSAXReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    }

    private EntityResolver iEntityResolver = new EntityResolver() {
        public InputSource resolveEntity(String publicId, String systemId) {
            if (publicId.equals("-//Hibernate/Hibernate Mapping DTD 3.0//EN")) {
                return new InputSource(
                        getClass().getClassLoader().getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
            } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD 3.0//EN")) {
                return new InputSource(getClass().getClassLoader()
                        .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
            }
            return null;
        }
    };

    public void setSource(String source) {
        iSource = source;
    }

    public void setConfig(String config) {
        iConfig = config;
    }

    protected Document read(String resource) throws IOException, DocumentException {
        if (iSource == null) {
            info("  -- reading " + resource + " ...");
            return iSAXReader.read(getClass().getClassLoader().getResourceAsStream(resource));
        } else {
            info("  -- reading " + iSource + File.separator + resource + " ...");
            return iSAXReader.read(new File(iSource + File.separator + resource));
        }
    }

    protected void write(String resource, Document document) throws IOException, DocumentException {
        File file = null;
        if (iSource == null) {
            file = new File(getClass().getClassLoader().getResource(resource).getFile());
        } else {
            file = new File(iSource + File.separator + resource);
        }
        info("  -- writing " + file + " ...");
        FileOutputStream fos = new FileOutputStream(file);
        try {
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setIndentSize(4);
            format.setPadText(false);
            new MyXMLWriter(fos, format).write(document);
        } finally {
            fos.flush();
            fos.close();
        }
    }

    protected void pretty(File f) {
    }

    public void execute() throws BuildException {
        try {
            convert();
        } catch (Exception e) {
            throw new BuildException(e);
        }
    }

    public void info(String message) {
        try {
            log(message);
        } catch (Exception e) {
            System.out.println(message);
        }
    }

    public void warn(String message) {
        try {
            log(message, Project.MSG_WARN);
        } catch (Exception e) {
            System.out.println(message);
        }
    }

    public void convert() throws IOException, DocumentException {
        info("Config: " + (iSource == null ? getClass().getClassLoader().getResource(iConfig)
                : iSource + File.separator + iConfig));
        File workDir = null;
        if (iSource == null) {
            workDir = new File(getClass().getClassLoader().getResource(iConfig).getFile());
            while (workDir.getParentFile() != null && !"WebContent".equals(workDir.getName()))
                workDir = workDir.getParentFile();
            workDir = new File(workDir.getParentFile(), "JavaSource");
            workDir.mkdirs();
        } else {
            workDir = new File(iSource);
        }
        info("Working directory: " + workDir);
        info("Reading hibernate.cfg.xml ...");
        Document document = read(iConfig);
        Element root = document.getRootElement();
        Element sessionFactoryElement = root.element("session-factory");
        for (Iterator<Element> i = sessionFactoryElement.elementIterator("mapping"); i.hasNext();) {
            Element m = i.next();
            String resource = m.attributeValue("resource");
            if (resource == null)
                continue;
            info("Processing " + resource + " ...");
            Document resDoc = read(resource);
            convert(resDoc.getRootElement());
            write(resource, resDoc);
        }
    }

    private String[] sAttributes = new String[] { "table", "sequence", "column", "foreign-key", "order-by" };

    private String[] sFormulas = new String[] { "formula", "where" };

    private String lowerFormula(String formula) {
        boolean quot = false;
        String ret = "";
        for (int i = 0; i < formula.length(); i++) {
            char ch = formula.charAt(i);
            if (ch == '\'')
                quot = !quot;
            ret += (quot ? ch : Character.toLowerCase(ch));
        }
        return ret.replace("%schema%", "%SCHEMA%").replace("/*+ rule */", "/*+ RULE */");
    }

    private void convert(Element element) {
        for (Iterator<Attribute> i = element.attributeIterator(); i.hasNext();) {
            Attribute attribute = i.next();
            for (String name : sAttributes) {
                if (name.equals(attribute.getName())) {
                    if (!attribute.getValue().equals(attribute.getValue().toLowerCase())) {
                        info("  -- converting " + name + " " + attribute.getValue() + " to "
                                + attribute.getValue().toLowerCase());
                    }
                    attribute.setValue(attribute.getValue().toLowerCase());
                }
            }
            for (String name : sFormulas) {
                if (name.equals(attribute.getName())) {
                    if (!lowerFormula(attribute.getValue()).equals(attribute.getValue())) {
                        info("  -- converting " + name + ": " + attribute.getValue());
                        info("  -- into : " + lowerFormula(attribute.getValue()));
                    }
                    attribute.setValue(lowerFormula(attribute.getValue()));
                }
            }
        }
        if (element.getName().equals("param")) {
            for (String name : sAttributes) {
                if (name.equals(element.attributeValue("name", ""))) {
                    if (!element.getText().equals(element.getText().toLowerCase())) {
                        info("  -- converting " + name + " " + element.getText() + " to "
                                + element.getText().toLowerCase());
                    }
                    element.setText(element.getText().toLowerCase());
                }
            }
        }
        for (Iterator<Element> i = element.elementIterator(); i.hasNext();) {
            convert(i.next());
        }
    }

    public static void main(String[] args) {
        try {
            LowercaseTableNames ltn = new LowercaseTableNames();
            ltn.setSource("/Users/muller/Sources/UniTime/JavaSource");
            ltn.convert();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class MyXMLWriter extends XMLWriter {
        private OutputFormat format;
        private int indentLevel = 0;

        public MyXMLWriter(OutputStream out, OutputFormat format) throws UnsupportedEncodingException {
            super(out, format);
            this.format = format;
        }

        protected void indent() throws IOException {
            String indent = format.getIndent();

            if ((indent != null) && (indent.length() > 0)) {
                for (int i = 0; i < indentLevel; i++) {
                    writer.write(indent);
                }
            }
        }

        protected void writeAttributes(Element element) throws IOException {
            for (int i = 0, size = element.attributeCount(); i < size; i++) {
                Attribute attribute = element.attribute(i);
                char quote = format.getAttributeQuoteCharacter();
                if (element.attributeCount() > 2) {
                    writePrintln();
                    indent();
                    writer.write(format.getIndent());
                } else {
                    writer.write(" ");
                }
                writer.write(attribute.getQualifiedName());
                writer.write("=");
                writer.write(quote);
                writeEscapeAttributeEntities(attribute.getValue());
                writer.write(quote);
            }
        }

        protected void writeElement(Element element) throws IOException {
            int size = element.nodeCount();
            String qualifiedName = element.getQualifiedName();

            writePrintln();
            indent();

            writer.write("<");
            writer.write(qualifiedName);

            boolean textOnly = true;

            for (int i = 0; i < size; i++) {
                Node node = element.node(i);
                if (node instanceof Element) {
                    textOnly = false;
                } else if (node instanceof Comment) {
                    textOnly = false;
                }
            }

            writeAttributes(element);

            lastOutputNodeType = Node.ELEMENT_NODE;

            if (size <= 0) {
                writeEmptyElementClose(qualifiedName);
            } else {
                writer.write(">");

                if (textOnly) {
                    // we have at least one text node so lets assume
                    // that its non-empty
                    writeElementContent(element);
                } else {
                    if (element.attributeCount() > 3)
                        writePrintln();
                    // we know it's not null or empty from above
                    ++indentLevel;

                    writeElementContent(element);

                    --indentLevel;

                    writePrintln();
                    indent();
                }

                writer.write("</");
                writer.write(qualifiedName);
                writer.write(">");
            }
            if (element.attributeCount() > 2 && indentLevel > 0)
                writePrintln();

            lastOutputNodeType = Node.ELEMENT_NODE;
        }

    }
}