/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Ant", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.tools.ant.taskdefs.optional.metamata;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.EmptyStackException;
import java.util.Enumeration;
import java.util.Stack;
import java.util.Vector;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
import org.apache.tools.ant.util.DateUtils;

/**
 * A handy metrics handler. Most of this code was done only with the
 * screenshots on the documentation since the evaluation version as
 * of this writing does not allow to save metrics or to run it via
 * command line.
 * <p>
 * This class can be used to transform a text file or to process the
 * output stream directly.
 *
 * @author  <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
 */
public class MMetricsStreamHandler implements ExecuteStreamHandler {

    /** CLASS construct, it should be named something like 'MyClass' */
    private static final String CLASS = "class";

    /** package construct, it should be look like 'com.mycompany.something' */
    private static final String PACKAGE = "package";

    /** FILE construct, it should look like something 'MyClass.java' or 'MyClass.class' */
    private static final String FILE = "file";

    /** METHOD construct, it should looke like something 'doSomething(...)' or 'doSomething()' */
    private static final String METHOD = "method";

    private static final String[] ATTRIBUTES = {
        "name", "vg", "loc", "dit", "noa", "nrm", "nlm", "wmc",
        "rfc", "dac", "fanout", "cbo", "lcom", "nocl"};

    /** reader for stdout */
    private InputStream metricsOutput;

    /**
     * this is where the XML output will go, should mostly be a file
     * the caller is responsible for flushing and closing this stream
     */
    private OutputStream xmlOutputStream;

    /** metrics handler */
    private TransformerHandler metricsHandler;

    /** the task */
    private Task task;

    /**
     * the stack where are stored the metrics element so that they we can
     * know if we have to close an element or not.
     */
    private Stack stack = new Stack();

    /** initialize this handler */
    MMetricsStreamHandler(Task task, OutputStream xmlOut) {
        this.task = task;
        this.xmlOutputStream = xmlOut;
    }

    /** Ignore. */
    public void setProcessInputStream(OutputStream p1) throws IOException {
    }

    /** Ignore. */
    public void setProcessErrorStream(InputStream p1) throws IOException {
    }

    /** Set the inputstream */
    public void setProcessOutputStream(InputStream is) throws IOException {
        metricsOutput = is;
    }

    public void start() throws IOException {
        // create the transformer handler that will be used to serialize
        // the output.
        TransformerFactory factory = TransformerFactory.newInstance();
        if (!factory.getFeature(SAXTransformerFactory.FEATURE)) {
            throw new IllegalStateException("Invalid Transformer factory feature");
        }
        try {
            metricsHandler = ((SAXTransformerFactory) factory).newTransformerHandler();
            metricsHandler.setResult(new StreamResult(new OutputStreamWriter(xmlOutputStream, "UTF-8")));
            Transformer transformer = metricsHandler.getTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");

            // start the document with a 'metrics' root
            final Date now = new Date();
            metricsHandler.startDocument();
            AttributesImpl attr = new AttributesImpl();
            attr.addAttribute("", "company", "company", "CDATA", "metamata");
            attr.addAttribute("", "snapshot_created", "snapshot_created", "CDATA",
                    DateUtils.format(now, DateUtils.ISO8601_DATETIME_PATTERN));
//            attr.addAttribute("", "elapsed_time", "elapsed_time", "CDATA", String.valueOf(now.getTime() - program_start.getTime()));
            attr.addAttribute("", "program_start", "program_start", "CDATA",
                    DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN));
            metricsHandler.startElement("", "metrics", "metrics", attr);

            // now parse the whole thing
            parseOutput();

        } catch (Exception e) {
            throw new BuildException(e);
        }
    }

    /**
     * Pretty dangerous business here.
     */
    public void stop() {
        try {
            // we need to pop everything and close elements that have not been
            // closed yet.
            while (stack.size() > 0) {
                ElementEntry elem = (ElementEntry) stack.pop();
                metricsHandler.endElement("", elem.getType(), elem.getType());
            }
            // close the root
            metricsHandler.endElement("", "metrics", "metrics");
            // document is finished for good
            metricsHandler.endDocument();
        } catch (SAXException e) {
            e.printStackTrace();
            throw new IllegalStateException(e.getMessage());
        }
    }

    /** read each line and process it */
    protected void parseOutput() throws IOException, SAXException {
        BufferedReader br = new BufferedReader(new InputStreamReader(metricsOutput));
        String line = null;
        while ((line = br.readLine()) != null) {
            processLine(line);
        }
    }

    /**
     * Process a metrics line. If the metrics is invalid and that this is not
     * the header line, it is display as info.
     * @param line the line to process, it is normally a line full of metrics.
     */
    protected void processLine(String line) throws SAXException {
        if (line.startsWith("Construct\tV(G)\tLOC\tDIT\tNOA\tNRM\tNLM\tWMC\tRFC\tDAC\tFANOUT\tCBO\tLCOM\tNOCL")) {
            return;
        }
        try {
            MetricsElement elem = MetricsElement.parse(line);
            startElement(elem);
        } catch (ParseException e) {
            //e.printStackTrace();
            // invalid lines are sent to the output as information, it might be anything,
            task.log(line, Project.MSG_INFO);
        }
    }

    /**
     * Start a new construct. Elements are popped until we are on the same
     * parent node, then the element type is guessed and pushed on the
     * stack.
     * @param elem the element to process.
     * @throws SAXException thrown if there is a problem when sending SAX events.
     */
    protected void startElement(MetricsElement elem) throws SAXException {
        // if there are elements in the stack we possibly need to close one or
        // more elements previous to this one until we got its parent
        int indent = elem.getIndent();
        if (stack.size() > 0) {
            ElementEntry previous = (ElementEntry) stack.peek();
            // close nodes until you got the parent.
            try {
                while (indent <= previous.getIndent() && stack.size() > 0) {
                    stack.pop();
                    metricsHandler.endElement("", previous.getType(), previous.getType());
                    previous = (ElementEntry) stack.peek();
                }
            } catch (EmptyStackException ignored) {
            }
        }

        // ok, now start the new construct
        String type = getConstructType(elem);
        Attributes attrs = createAttributes(elem);
        metricsHandler.startElement("", type, type, attrs);

        // make sure we keep track of what we did, that's history
        stack.push(new ElementEntry(type, indent));
    }

    /**
     * return the construct type of the element. We can hardly recognize the
     * type of a metrics element, so we are kind of forced to do some black
     * magic based on the name and indentation to recognize the type.
     * @param elem  the metrics element to guess for its type.
     * @return the type of the metrics element, either PACKAGE, FILE, CLASS or
     * METHOD.
     */
    protected String getConstructType(MetricsElement elem) {
        // ok no doubt, it's a file
        if (elem.isCompilationUnit()) {
            return FILE;
        }

        // same, we're sure it's a method
        if (elem.isMethod()) {
            return METHOD;
        }

        // if it's empty, and none of the above it should be a package
        if (stack.size() == 0) {
            return PACKAGE;
        }

        // ok, this is now black magic time, we will guess the type based on
        // the previous type and its indent...
        final ElementEntry previous = (ElementEntry) stack.peek();
        final String prevType = previous.getType();
        final int prevIndent = previous.getIndent();
        final int indent = elem.getIndent();
        // we're just under a file with a bigger indent so it's a class
        if (prevType.equals(FILE) && indent > prevIndent) {
            return CLASS;
        }

        // we're just under a class with a greater or equals indent, it's a class
        // (there might be several classes in a compilation unit and inner classes as well)
        if (prevType.equals(CLASS) && indent >= prevIndent) {
            return CLASS;
        }

        // we assume the other are package
        return PACKAGE;
    }


    /**
     * Create all attributes of a MetricsElement skipping those who have an
     * empty string
     */
    protected Attributes createAttributes(MetricsElement elem) {
        AttributesImpl impl = new AttributesImpl();
        int i = 0;
        String name = ATTRIBUTES[i++];
        impl.addAttribute("", name, name, "CDATA", elem.getName());
        Enumeration metrics = elem.getMetrics();
        for (; metrics.hasMoreElements(); i++) {
            String value = (String) metrics.nextElement();
            if (value.length() > 0) {
                name = ATTRIBUTES[i];
                impl.addAttribute("", name, name, "CDATA", value);
            }
        }
        return impl;
    }

    /**
     * helper class to keep track of elements via its type and indent
     * that's all we need to guess a type.
     */
    private static final class ElementEntry {
        private String type;
        private int indent;

        ElementEntry(String type, int indent) {
            this.type = type;
            this.indent = indent;
        }

        public String getType() {
            return type;
        }

        public int getIndent() {
            return indent;
        }
    }
}

class MetricsElement {

    private static final NumberFormat METAMATA_NF;

    private static final NumberFormat NEUTRAL_NF;

    static {
        METAMATA_NF = NumberFormat.getInstance();
        METAMATA_NF.setMaximumFractionDigits(1);
        NEUTRAL_NF = NumberFormat.getInstance();
        if (NEUTRAL_NF instanceof DecimalFormat) {
            ((DecimalFormat) NEUTRAL_NF).applyPattern("###0.###;-###0.###");
        }
        NEUTRAL_NF.setMaximumFractionDigits(1);
    }

    private int indent;

    private String construct;

    private Vector metrics;

    MetricsElement(int indent, String construct, Vector metrics) {
        this.indent = indent;
        this.construct = construct;
        this.metrics = metrics;
    }

    public int getIndent() {
        return indent;
    }

    public String getName() {
        return construct;
    }

    public Enumeration getMetrics() {
        return metrics.elements();
    }

    public boolean isCompilationUnit() {
        return (construct.endsWith(".java") || construct.endsWith(".class"));
    }

    public boolean isMethod() {
        return (construct.endsWith("(...)") || construct.endsWith("()"));
    }

    public static MetricsElement parse(String line) throws ParseException {
        final Vector metrics = new Vector();
        int pos;

        // i'm using indexOf since I need to know if there are empty strings
        // between tabs and I find it easier than with StringTokenizer
        while ((pos = line.indexOf('\t')) != -1) {
            String token = line.substring(0, pos);
            // only parse what coudl be a valid number. ie not constructs nor no value
            /*if (metrics.size() != 0 || token.length() != 0){
                Number num = METAMATA_NF.parse(token); // parse with Metamata NF
                token = NEUTRAL_NF.format(num.doubleValue()); // and format with a neutral NF
            }*/
            metrics.addElement(token);
            line = line.substring(pos + 1);
        }
        metrics.addElement(line);

        // there should be exactly 14 tokens (1 name + 13 metrics), if not, there is a problem !
        if (metrics.size() != 14) {
            throw new ParseException("Could not parse the following line as a metrics: -->" + line + "<--", -1);
        }

        // remove the first token it's made of the indentation string and the
        // construct name, we'll need all this to figure out what type of
        // construct it is since we lost all semantics :(
        // (#indent[/]*)(#construct.*)
        String name = (String) metrics.elementAt(0);
        metrics.removeElementAt(0);
        int indent = 0;
        pos = name.lastIndexOf('/');
        if (pos != -1) {
            name = name.substring(pos + 1);
            indent = pos + 1; // indentation is last position of token + 1
        }
        return new MetricsElement(indent, name, metrics);
    }
}

