gool.generator.xml.XmlCodePrinter.java Source code

Java tutorial

Introduction

Here is the source code for gool.generator.xml.XmlCodePrinter.java

Source

/*
 * Copyright 2010 Pablo Arrighi, Alex Concha, Miguel Lezama for version 1.
 * Copyright 2013 Pablo Arrighi, Miguel Lezama, Kevin Mazet for version 2.    
 *
 * This file is part of GOOL.
 *
 * GOOL 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, version 3.
 *
 * GOOL 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 version 3 for more details.
 *
 * You should have received a copy of the GNU General Public License along with GOOL,
 * in the file COPYING.txt.  If not, see <http://www.gnu.org/licenses/>.
 */

package gool.generator.xml;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.w3c.dom.*;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import javax.xml.parsers.*;
import logger.Log;

import gool.ast.core.ClassDef;
import gool.generator.common.CodePrinter;
import gool.generator.java.JavaGenerator;

public class XmlCodePrinter extends CodePrinter {

    /**
     * list every risked methods for every node with recursion risk.
     */
    private static final java.util.HashMap<String, String[]> methexclude = new java.util.HashMap<String, String[]>();
    static {
        String[] letableau = { "getClassReference" };
        methexclude.put("gool.ast.type.TypeClass", letableau);
    }

    /**
     * list ignored getter for attribute.
     */
    private static final java.util.ArrayList<String> attrexclude = new java.util.ArrayList<String>();
    static {
        attrexclude.add("getClass");
        attrexclude.add("getAccessModifier");
        attrexclude.add("getHeader");
        attrexclude.add("getBlock");
    }

    /**
     * node counter for debugging
     */
    int nbNode = 0;

    /**
     * Authorize only one ClassDef
     */
    private boolean classdefok = true;

    public XmlCodePrinter(File outputDir, Collection<File> myF) {
        // Chose you're favorite Generator for recognized.
        super(new JavaGenerator(), outputDir, myF);
    }

    private Set<ClassDef> printedClasses = new HashSet<ClassDef>();

    @Override
    public List<File> print(ClassDef pclass) throws FileNotFoundException {
        Document document = null;
        DocumentBuilderFactory fabrique = null;
        List<File> result = new ArrayList<File>();
        // Debugging info
        // nbNode = 0;

        try {
            // creat document structure
            fabrique = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = fabrique.newDocumentBuilder();
            document = builder.newDocument();
            Element racine = (Element) document.createElement("file");
            Element el = NodeToElement(pclass, document);
            if (el != null)
                racine.appendChild(el);
            document.appendChild(racine);

            // file separator is just a slash in Unix
            // so the second argument to File() is just the directory
            // that corresponds to the package name
            // the first argument is the default output directory of the
            // platform
            // so the directory name ends up being something like
            // GOOLOUPTUTTARGET/pack/age
            File dir = new File(getOutputDir().getAbsolutePath(),
                    StringUtils.replace(pclass.getPackageName(), ".", File.separator));
            // Typically the outputdir was created before, but not the package
            // subdirs
            dir.mkdirs();
            // Create the file for the class, fill it in, close it
            File classFile = new File(dir, getFileName(pclass.getName()));
            Log.i(String.format("Writing to file %s", classFile));

            // Create formating output
            OutputFormat format = new OutputFormat(document);
            format.setEncoding("UTF-8");
            format.setLineWidth(80);
            format.setIndenting(true);
            format.setIndent(4);

            // save to output file
            Writer out = new PrintWriter(classFile);
            XMLSerializer serializer = new XMLSerializer(out, format);
            serializer.serialize(document);

            // Remember that you did the generation for this one abstract GOOL
            // class
            printedClasses.add(pclass);
            result.add(classFile);
            classdefok = true;
        } catch (Exception e) {
            Log.e(e);
            System.exit(1);
        }

        return result;
    }

    /**
     * Translate GOOL node to XML Element.
     * 
     * @param node
     *            GOOL node
     * @param document
     *            XML Document
     * @return XML Element
     */
    private Element NodeToElement(Object node, Document document) {
        // element create for return
        Element newElement = null;

        // check if the parameter does not cause trouble
        if (node == null || node.getClass().getName().equals("gool.generator.xml.XmlPlatform"))
            return null;
        if (node.getClass().isAssignableFrom(gool.ast.core.Node.class)) {
            return null;
        }
        if (node.getClass().getName().equals("gool.ast.core.ClassDef")) {
            if (classdefok)
                classdefok = false;
            else
                return null;
        }

        // Create the new Element
        newElement = document.createElement(node.getClass().getName().substring(9));

        // find every method to find every child node
        Method[] meths = node.getClass().getMethods();
        for (Method meth : meths) {
            Class<?> laCl = meth.getReturnType();
            // check if the method return type is a node.
            if (gool.ast.core.Node.class.isAssignableFrom(laCl)
                    && (meth.getParameterTypes().length == 0) /* && nbNode<1000 */) {
                // Debug for recursion
                // nbNode++;
                // Log.d(laCl.getName() + "\n" + nbNode);
                try {
                    gool.ast.core.Node newNode = (gool.ast.core.Node) meth.invoke(node);
                    // detect recursion risk.
                    boolean recursionRisk = (newNode == node) ? true : false;
                    if (methexclude.containsKey(node.getClass().getName())) {
                        for (String exmeth : methexclude.get(node.getClass().getName())) {
                            if (newNode == null || meth.getName().equals(exmeth))
                                recursionRisk = true;
                        }
                    }
                    if (recursionRisk) {
                        Element newElement2 = document.createElement(node.getClass().getName().substring(9));
                        newElement2.setTextContent("recursion risk detected!");
                        newElement.appendChild(newElement2);
                    } else {
                        Element el = NodeToElement(newNode, document);
                        if (el != null) {
                            el.setAttribute("getterName", meth.getName());
                            newElement.appendChild(el);
                        }
                    }
                } catch (Exception e) {
                    Log.e(e);
                    System.exit(1);
                }
            }
            // if the method return node list.
            else if (java.util.List.class.isAssignableFrom(laCl)) {
                try {
                    java.util.List<Object> listObj = (java.util.List<Object>) meth.invoke(node);
                    for (Object o : listObj) {
                        Element el = NodeToElement(o, document);
                        if (el != null) {
                            el.setAttribute("getterName", meth.getName());
                            newElement.appendChild(el);
                        }
                    }
                } catch (Exception e) {
                    Log.e(e);
                    System.exit(1);
                }

            }
            // generate XML attribute for getter
            else if (meth.getName().startsWith("get") && !meth.getName().equals("getCode")
                    && (meth.getParameterTypes().length == 0)) {
                try {
                    if (!attrexclude.contains(meth.getName()))
                        newElement.setAttribute(meth.getName().substring(3),
                                meth.invoke(node) == null ? "null" : meth.invoke(node).toString());
                } catch (Exception e) {
                    Log.e(e);
                    System.exit(1);
                }
            }
            // generate XML attribute for iser
            else if (meth.getName().startsWith("is") && (meth.getParameterTypes().length == 0)) {
                try {
                    if (!attrexclude.contains(meth.getName()))
                        newElement.setAttribute(meth.getName().substring(2),
                                meth.invoke(node) == null ? "null" : meth.invoke(node).toString());
                } catch (Exception e) {
                    Log.e(e);
                    System.exit(1);
                }
            }
        }
        return newElement;
    }

    @Override
    public Collection<File> print(Collection<ClassDef> generatedClassDefs, boolean isGool)
            throws FileNotFoundException {
        return super.print(generatedClassDefs, isGool);
    }

    @Override
    public String getFileName(String className) {
        return className + ".xml";
    }

    @Override
    public String getTemplateDir() {
        return "";
    }

}