/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.control;

import org.apache.groovy.util.Maps;
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
import org.codehaus.groovy.control.io.NullWriter;
import org.codehaus.groovy.control.messages.WarningMessage;
import org.objectweb.asm.Opcodes;

import java.io.File;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

import static org.apache.groovy.util.SystemUtil.getSystemPropertySafe;

/**
 * Compilation control flags and coordination stuff.
 */
public class CompilerConfiguration {

    /** This (<code>"indy"</code>) is the Optimization Option value for enabling <code>invokedynamic</code> compilation. */
    public static final String INVOKEDYNAMIC = "indy";

    /** This (<code>"groovydoc"</code>) is the Optimization Option value for enabling attaching groovydoc as AST node metadata. */
    public static final String GROOVYDOC = "groovydoc";

    /** This (<code>"runtimeGroovydoc"</code>) is the Optimization Option value for enabling attaching {@link groovy.lang.Groovydoc} annotation. */
    public static final String RUNTIME_GROOVYDOC = "runtimeGroovydoc";

    /** This (<code>"memStub"</code>) is the Joint Compilation Option value for enabling generating stubs in memory. .*/
    public static final String MEM_STUB = "memStub";

    /** This (<code>"1.4"</code>) is the value for targetBytecode to compile for a JDK 1.4. **/
    public static final String JDK4 = "1.4";
    /** This (<code>"1.5"</code>) is the value for targetBytecode to compile for a JDK 1.5. **/
    public static final String JDK5 = "1.5";
    /** This (<code>"1.6"</code>) is the value for targetBytecode to compile for a JDK 1.6. **/
    public static final String JDK6 = "1.6";
    /** This (<code>"1.7"</code>) is the value for targetBytecode to compile for a JDK 1.7. **/
    public static final String JDK7 = "1.7";
    /** This (<code>"1.8"</code>) is the value for targetBytecode to compile for a JDK 1.8. **/
    public static final String JDK8 = "1.8";
    /** This (<code>"9"</code>) is the value for targetBytecode to compile for a JDK 9. **/
    public static final String JDK9 = "9";
    /** This (<code>"10"</code>) is the value for targetBytecode to compile for a JDK 10. **/
    public static final String JDK10 = "10";
    /** This (<code>"11"</code>) is the value for targetBytecode to compile for a JDK 11. **/
    public static final String JDK11 = "11";
    /** This (<code>"12"</code>) is the value for targetBytecode to compile for a JDK 12. **/
    public static final String JDK12 = "12";
    /** This (<code>"13"</code>) is the value for targetBytecode to compile for a JDK 13. **/
    public static final String JDK13 = "13";
    /** This (<code>"14"</code>) is the value for targetBytecode to compile for a JDK 14. **/
    public static final String JDK14 = "14";

    /**
     * This constant is for comparing targetBytecode to ensure it is set to JDK 1.5 or later.
     * @deprecated
     */
    @Deprecated
    public static final String POST_JDK5 = JDK5; // for backwards compatibility

    /**
     * This constant is for comparing targetBytecode to ensure it is set to an earlier value than JDK 1.5.
     * @deprecated
     */
    @Deprecated
    public static final String PRE_JDK5 = JDK4;

    /**
     * JDK version to bytecode version mapping
     */
    public static final Map<String, Integer> JDK_TO_BYTECODE_VERSION_MAP = Maps.of(
            JDK4, Opcodes.V1_4,
            JDK5, Opcodes.V1_5,
            JDK6, Opcodes.V1_6,
            JDK7, Opcodes.V1_7,
            JDK8, Opcodes.V1_8,
            JDK9, Opcodes.V9,
            JDK10, Opcodes.V10,
            JDK11, Opcodes.V11,
            JDK12, Opcodes.V12,
            JDK13, Opcodes.V13,
            JDK14, Opcodes.V14
    );

    private static final String[] EMPTY_STRING_ARRAY = new String[0];

    /** An array of the valid targetBytecode values */
    public static final String[] ALLOWED_JDKS = JDK_TO_BYTECODE_VERSION_MAP.keySet().toArray(EMPTY_STRING_ARRAY);

    /**
     * The default source encoding
     */
    public static final String DEFAULT_SOURCE_ENCODING = "UTF-8";

    /**
     *  A convenience for getting a default configuration.  Do not modify it!
     *  See {@link #CompilerConfiguration(Properties)} for an example on how to
     *  make a suitable copy to modify.  But if you're really starting from a
     *  default context, then you probably just want <code>new CompilerConfiguration()</code>. 
     */
    public static final CompilerConfiguration DEFAULT = new CompilerConfiguration() {
        @Override
        public List<String> getClasspath() {
            return Collections.unmodifiableList(super.getClasspath());
        }

        @Override
        public List<CompilationCustomizer> getCompilationCustomizers() {
            return Collections.unmodifiableList(super.getCompilationCustomizers());
        }

        @Override
        public Set<String> getDisabledGlobalASTTransformations() {
            return Collections.emptySet();
        }

        @Override
        public Map<String, Object> getJointCompilationOptions() {
            return Collections.unmodifiableMap(super.getJointCompilationOptions());
        }

        @Override
        public Map<String, Boolean> getOptimizationOptions() {
            return Collections.unmodifiableMap(super.getOptimizationOptions());
        }

        @Override
        public Set<String> getScriptExtensions() {
            return Collections.unmodifiableSet(super.getScriptExtensions());
        }

        @Override
        public void setBytecodePostprocessor(BytecodeProcessor bytecodePostprocessor) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setClasspath(String classpath) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setClasspathList(List<String> parts) {
            throw new UnsupportedOperationException();
        }

        @Override
        public CompilerConfiguration addCompilationCustomizers(CompilationCustomizer... customizers) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setDebug(boolean debug) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setDefaultScriptExtension(String defaultScriptExtension) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setDisabledGlobalASTTransformations(Set<String> disabledGlobalASTTransformations) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setJointCompilationOptions(Map<String, Object> options) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setMinimumRecompilationInterval(int time) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setOptimizationOptions(Map<String, Boolean> options) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setOutput(PrintWriter output) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setParameters(boolean parameters) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setPluginFactory(ParserPluginFactory pluginFactory) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setPreviewFeatures(boolean previewFeatures) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setRecompileGroovySource(boolean recompile) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setScriptBaseClass(String scriptBaseClass) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setScriptExtensions(Set<String> scriptExtensions) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setSourceEncoding(String encoding) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setTargetBytecode(String version) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setTargetDirectory(File directory) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setTargetDirectory(String directory) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setTolerance(int tolerance) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setVerbose(boolean verbose) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void setWarningLevel(int level) {
            throw new UnsupportedOperationException();
        }
    };


    /**
     * See {@link WarningMessage} for levels.
     */
    private int warningLevel;

    /**
     * Encoding for source files
     */
    private String sourceEncoding;

    /**
     * The <code>PrintWriter</code> does nothing.
     */
    private PrintWriter output;

    /**
     * Directory into which to write classes
     */
    private File targetDirectory;

    /**
     * Classpath for use during compilation
     */
    private LinkedList<String> classpath;

    /**
     * If true, the compiler should produce action information
     */
    private boolean verbose;

    /**
     * If true, debugging code should be activated
     */
    private boolean debug;

    /**
     * If true, generates metadata for reflection on method parameters
     */
    private boolean parameters = false;

    /**
     * The number of non-fatal errors to allow before bailing
     */
    private int tolerance;

    /**
     * Base class name for scripts (must derive from Script)
     */
    private String scriptBaseClass;

    private ParserPluginFactory pluginFactory;

    /**
     * extension used to find a groovy file
     */
    private String defaultScriptExtension;

    /**
     * extensions used to find a groovy files
     */
    private Set<String> scriptExtensions = new LinkedHashSet<String>();

    /**
     * if set to true recompilation is enabled
     */
    private boolean recompileGroovySource;

    /**
     * sets the minimum of time after a script can be recompiled.
     */
    private int minimumRecompilationInterval;

    /**
     * sets the bytecode version target
     */
    private String targetBytecode;

    /**
     * Whether the bytecode version has preview features enabled (JEP 12)
     */
    private boolean previewFeatures;

    /**
     * options for joint compilation (null by default == no joint compilation)
     */
    private Map<String, Object> jointCompilationOptions;

    /**
     * options for optimizations (empty map by default)
     */
    private Map<String, Boolean> optimizationOptions;

    private final List<CompilationCustomizer> compilationCustomizers = new LinkedList<CompilationCustomizer>();

    /**
     * Global AST transformations which should not be loaded even if they are
     * defined in META-INF/services/org.codehaus.groovy.transform.ASTTransformation files.
     * By default, none are disabled.
     */
    private Set<String> disabledGlobalASTTransformations;

    private BytecodeProcessor bytecodePostprocessor;

    public static final int ASM_API_VERSION = Opcodes.ASM7;

    /**
     * Sets the compiler flags/settings to default values.
     *
     * The following system properties are referenced when setting the configuration:
     *
     * <blockquote>
     * <table summary="Groovy Compiler Configuration Properties">
     *   <tr><th>Property Key</th><th>Related Property Getter</th></tr>
     *   <tr><td><code>groovy.source.encoding</code> (defaulting to <code>file.encoding</code>)</td><td>{@link #getSourceEncoding}</td></tr>
     *   <tr><td><code>groovy.target.bytecode</code></td><td>{@link #getTargetBytecode}</td></tr>
     *   <tr><td><code>groovy.target.directory</code></td><td>{@link #getTargetDirectory}</td></tr>
     *   <tr><td><code>groovy.parameters</code></td><td>{@link #getParameters()}</td></tr>
     *   <tr><td><code>groovy.preview.features</code></td><td>{@link #isPreviewFeatures}</td></tr>
     *   <tr><td><code>groovy.script.base</code></td><td>{@link #getScriptBaseClass}</td></tr>
     *   <tr><td><code>groovy.default.scriptExtension</code></td><td>{@link #getDefaultScriptExtension}</td></tr>
     * </table>
     * </blockquote>
     *
     * The following system properties are referenced when setting the configuration optimization options:
     *
     * <blockquote>
     * <table summary="Groovy Compiler Optimization Options Configuration Properties">
     *   <tr><th>Property Key</th><th>Related Property Getter</th></tr>
     *   <tr><td><code>groovy.target.indy</code></td><td>{@link #getOptimizationOptions}</td></tr>
     *   <tr><td><code>groovy.attach.groovydoc</code></td><td>{@link #getOptimizationOptions}</td></tr>
     *   <tr><td><code>groovy.attach.runtime.groovydoc</code></td><td>{@link #getOptimizationOptions}</td></tr>
     * </table>
     * </blockquote>
     */
    public CompilerConfiguration() {
        // Set in safe defaults
        warningLevel = WarningMessage.LIKELY_ERRORS;
        classpath = new LinkedList<String>();
        parameters = getSystemPropertySafe("groovy.parameters") != null;
        tolerance = 10;
        minimumRecompilationInterval = 100;

        setTargetBytecodeIfValid(getSystemPropertySafe("groovy.target.bytecode", getMinBytecodeVersion()));

        previewFeatures = getSystemPropertySafe("groovy.preview.features") != null;
        defaultScriptExtension = getSystemPropertySafe("groovy.default.scriptExtension", ".groovy");

        // Source file encoding
        String encoding = getSystemPropertySafe("file.encoding", DEFAULT_SOURCE_ENCODING);
        encoding = getSystemPropertySafe("groovy.source.encoding", encoding);
        setSourceEncodingOrDefault(encoding);

        setTargetDirectorySafe(getSystemPropertySafe("groovy.target.directory"));

        optimizationOptions = new HashMap<>(4);
        handleOptimizationOption(optimizationOptions, INVOKEDYNAMIC, "groovy.target.indy");
        handleOptimizationOption(optimizationOptions, GROOVYDOC, "groovy.attach.groovydoc");
        handleOptimizationOption(optimizationOptions, RUNTIME_GROOVYDOC, "groovy.attach.runtime.groovydoc");

        jointCompilationOptions = new HashMap<>(4);
        handleJointCompilationOption(jointCompilationOptions, MEM_STUB, "groovy.generate.stub.in.memory");
    }

    private void handleOptimizationOption(Map<String, Boolean> options, String optionName, String sysOptionName) {
        String propValue = getSystemPropertySafe(sysOptionName);
        boolean optionEnabled = propValue == null
                ? (DEFAULT != null && Boolean.TRUE.equals(DEFAULT.getOptimizationOptions().get(optionName)))
                : Boolean.parseBoolean(propValue);

        if (optionEnabled) {
            options.put(optionName, Boolean.TRUE);
        }
    }

    private void handleJointCompilationOption(Map<String, Object> options, String optionName, String sysOptionName) {
        String propValue = getSystemPropertySafe(sysOptionName);
        boolean optionEnabled = propValue == null
                ? (DEFAULT != null && Boolean.TRUE.equals(DEFAULT.getJointCompilationOptions().get(optionName)))
                : Boolean.parseBoolean(propValue);

        if (optionEnabled) {
            options.put(optionName, Boolean.TRUE);
        }
    }

    /**
     * Copy constructor. Use this if you have a mostly correct configuration
     * for your compilation but you want to make a some changes programmatically.
     * An important reason to prefer this approach is that your code will most
     * likely be forward compatible with future changes to this configuration API.
     * <p>
     * An example of this copy constructor at work:
     * <blockquote><pre>
     * // In all likelihood there is already a configuration in your code's context
     * // for you to copy, but for the sake of this example we'll use the global default.
     * CompilerConfiguration myConfiguration = new CompilerConfiguration(CompilerConfiguration.DEFAULT);
     * myConfiguration.setDebug(true);
     * </pre></blockquote>
     *
     * @param configuration The configuration to copy.
     */
    public CompilerConfiguration(CompilerConfiguration configuration) {
        setWarningLevel(configuration.getWarningLevel());
        setTargetDirectory(configuration.getTargetDirectory());
        setClasspathList(new LinkedList<String>(configuration.getClasspath()));
        setVerbose(configuration.getVerbose());
        setDebug(configuration.getDebug());
        setParameters(configuration.getParameters());
        setTolerance(configuration.getTolerance());
        setScriptBaseClass(configuration.getScriptBaseClass());
        setRecompileGroovySource(configuration.getRecompileGroovySource());
        setMinimumRecompilationInterval(configuration.getMinimumRecompilationInterval());
        setTargetBytecode(configuration.getTargetBytecode());
        setPreviewFeatures(configuration.isPreviewFeatures());
        setDefaultScriptExtension(configuration.getDefaultScriptExtension());
        setSourceEncoding(configuration.getSourceEncoding());
        Map<String, Object> jointCompilationOptions = configuration.getJointCompilationOptions();
        if (jointCompilationOptions != null) {
            jointCompilationOptions = new HashMap<String, Object>(jointCompilationOptions);
        }
        setJointCompilationOptions(jointCompilationOptions);
        setPluginFactory(configuration.getPluginFactory());
        setDisabledGlobalASTTransformations(configuration.getDisabledGlobalASTTransformations());
        setScriptExtensions(new LinkedHashSet<String>(configuration.getScriptExtensions()));
        setOptimizationOptions(new HashMap<String, Boolean>(configuration.getOptimizationOptions()));
        setBytecodePostprocessor(configuration.getBytecodePostprocessor());
    }

    /**
     * Sets the configuration flags/settings according to values from the supplied {@code Properties} instance
     * or if not found, supplying a default value.
     *
     * Note that unlike {@link #CompilerConfiguration()}, the "defaults" here do <em>not</em> in general
     * include checking the settings in {@link System#getProperties()}.
     * If you want to set a few flags but keep Groovy's default
     * configuration behavior then be sure to make your settings in
     * a {@code Properties} object that is backed by <code>System.getProperties()</code> (which
     * is done using this constructor). That might be done like this:
     * <blockquote><pre>
     * Properties myProperties = new Properties(System.getProperties());
     * myProperties.setProperty("groovy.output.debug", "true");
     * myConfiguration = new CompilerConfiguration(myProperties);
     * </pre></blockquote>
     * And you also have to contend with a possible {@code SecurityException} when
     * getting the system properties (See {@link System#getProperties()}).
     * A safer approach would be to copy a default
     * {@code CompilerConfiguration} and make your changes there using the setter:
     * <blockquote><pre>
     * // In all likelihood there is already a configuration for you to copy,
     * // but for the sake of this example we'll use the global default.
     * CompilerConfiguration myConfiguration = new CompilerConfiguration(CompilerConfiguration.DEFAULT);
     * myConfiguration.setDebug(true);
     * </pre></blockquote>
     *
     * The following properties are referenced when setting the configuration:
     *
     * <blockquote>
     * <table summary="Groovy Compiler Configuration Properties">
     *   <tr><th>Property Key</th><th>Related Property Getter</th></tr>
     *   <tr><td><code>groovy.warnings</code></td><td>{@link #getWarningLevel}</td></tr>
     *   <tr><td><code>groovy.source.encoding</code> (defaulting to <code>file.encoding</code>)</td><td>{@link #getSourceEncoding}</td></tr>
     *   <tr><td><code>groovy.target.directory</code></td><td>{@link #getTargetDirectory}</td></tr>
     *   <tr><td><code>groovy.target.bytecode</code></td><td>{@link #getTargetBytecode}</td></tr>
     *   <tr><td><code>groovy.parameters</code></td><td>{@link #getParameters()}</td></tr>
     *   <tr><td><code>groovy.preview.features</code></td><td>{@link #isPreviewFeatures}</td></tr>
     *   <tr><td><code>groovy.classpath</code></td><td>{@link #getClasspath}</td></tr>
     *   <tr><td><code>groovy.output.verbose</code></td><td>{@link #getVerbose}</td></tr>
     *   <tr><td><code>groovy.output.debug</code></td><td>{@link #getDebug}</td></tr>
     *   <tr><td><code>groovy.errors.tolerance</code></td><td>{@link #getTolerance}</td></tr>
     *   <tr><td><code>groovy.default.scriptExtension</code></td><td>{@link #getDefaultScriptExtension}</td></tr>
     *   <tr><td><code>groovy.script.base</code></td><td>{@link #getScriptBaseClass}</td></tr>
     *   <tr><td><code>groovy.recompile</code></td><td>{@link #getRecompileGroovySource}</td></tr>
     *   <tr><td><code>groovy.recompile.minimumInterval</code></td><td>{@link #getMinimumRecompilationInterval}</td></tr>
     *   <tr><td><code>groovy.disabled.global.ast.transformations</code></td><td>{@link #getDisabledGlobalASTTransformations}</td></tr>
     * </table>
     * </blockquote>
     *
     * @param configuration The properties to get flag values from.
     */
    public CompilerConfiguration(Properties configuration) throws ConfigurationException {
        this();
        configure(configuration);
    }

    /**
     * Checks if the specified bytecode version string represents a JDK 1.5+ compatible
     * bytecode version.
     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
     * @return true if the bytecode version is JDK 1.5+
     */
    public static boolean isPostJDK5(String bytecodeVersion) {
        return new BigDecimal(bytecodeVersion).compareTo(new BigDecimal(JDK5)) >= 0;
    }

    /**
     * Checks if the specified bytecode version string represents a JDK 1.7+ compatible
     * bytecode version.
     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
     * @return true if the bytecode version is JDK 1.7+
     */
    public static boolean isPostJDK7(String bytecodeVersion) {
        return new BigDecimal(bytecodeVersion).compareTo(new BigDecimal(JDK7)) >= 0;
    }

    /**
     * Checks if the specified bytecode version string represents a JDK 1.8+ compatible
     * bytecode version.
     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
     * @return true if the bytecode version is JDK 1.8+
     */
    public static boolean isPostJDK8(String bytecodeVersion) {
        return new BigDecimal(bytecodeVersion).compareTo(new BigDecimal(JDK8)) >= 0;
    }

    /**
     * Checks if the specified bytecode version string represents a JDK 1.8+ compatible
     * bytecode version.
     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
     * @return true if the bytecode version is JDK 9.0+
     */
    public static boolean isPostJDK9(String bytecodeVersion) {
        return new BigDecimal(bytecodeVersion).compareTo(new BigDecimal(JDK9)) >= 0;
    }

    /**
     * Method to configure a CompilerConfiguration by using Properties.
     * For a list of available properties look at {@link #CompilerConfiguration(Properties)}.
     * @param configuration The properties to get flag values from.
     */
    public void configure(Properties configuration) throws ConfigurationException {
        String text;
        int numeric;

        numeric = getWarningLevel();
        text = configuration.getProperty("groovy.warnings", "likely errors");
        try {
            numeric = Integer.parseInt(text);
        } catch (NumberFormatException e) {
            text = text.toLowerCase();
            if (text.equals("none")) {
                numeric = WarningMessage.NONE;
            } else if (text.startsWith("likely")) {
                numeric = WarningMessage.LIKELY_ERRORS;
            } else if (text.startsWith("possible")) {
                numeric = WarningMessage.POSSIBLE_ERRORS;
            } else if (text.startsWith("paranoia")) {
                numeric = WarningMessage.PARANOIA;
            } else {
                throw new ConfigurationException("unrecognized groovy.warnings: " + text);
            }
        }
        setWarningLevel(numeric);

        text = configuration.getProperty("groovy.source.encoding");
        if (text == null) {
            text = configuration.getProperty("file.encoding", DEFAULT_SOURCE_ENCODING);
        }
        setSourceEncoding(text);

        text = configuration.getProperty("groovy.target.directory");
        if (text != null) setTargetDirectory(text);

        text = configuration.getProperty("groovy.target.bytecode");
        if (text != null) setTargetBytecode(text);

        text = configuration.getProperty("groovy.parameters");
        if (text != null) setParameters(text.equalsIgnoreCase("true"));

        text = configuration.getProperty("groovy.preview.features");
        if (text != null) setPreviewFeatures(text.equalsIgnoreCase("true"));

        text = configuration.getProperty("groovy.classpath");
        if (text != null) setClasspath(text);

        text = configuration.getProperty("groovy.output.verbose");
        if (text != null) setVerbose(text.equalsIgnoreCase("true"));

        text = configuration.getProperty("groovy.output.debug");
        if (text != null) setDebug(text.equalsIgnoreCase("true"));

        numeric = 10;
        text = configuration.getProperty("groovy.errors.tolerance", "10");
        try {
            numeric = Integer.parseInt(text);
        } catch (NumberFormatException e) {
            throw new ConfigurationException(e);
        }
        setTolerance(numeric);

        text = configuration.getProperty("groovy.default.scriptExtension");
        if (text != null) setDefaultScriptExtension(text);

        text = configuration.getProperty("groovy.script.base");
        if (text != null) setScriptBaseClass(text);

        text = configuration.getProperty("groovy.recompile");
        if (text != null) setRecompileGroovySource(text.equalsIgnoreCase("true"));

        numeric = 100;
        text = configuration.getProperty("groovy.recompile.minimumIntervall"); // legacy misspelling
        try {
            if (text == null) text = configuration.getProperty("groovy.recompile.minimumInterval");
            if (text != null) {
                numeric = Integer.parseInt(text);
            }
        } catch (NumberFormatException e) {
            throw new ConfigurationException(e);
        }
        setMinimumRecompilationInterval(numeric);

        text = configuration.getProperty("groovy.disabled.global.ast.transformations");
        if (text != null) {
            String[] classNames = text.split(",\\s*}");
            Set<String> blacklist = new HashSet<String>(Arrays.asList(classNames));
            setDisabledGlobalASTTransformations(blacklist);
        }
    }

    /**
     * Gets the currently configured warning level. See {@link WarningMessage}
     * for level details.
     */
    public int getWarningLevel() {
        return this.warningLevel;
    }

    /**
     * Sets the warning level. See {@link WarningMessage} for level details.
     */
    public void setWarningLevel(int level) {
        if (level < WarningMessage.NONE || level > WarningMessage.PARANOIA) {
            this.warningLevel = WarningMessage.LIKELY_ERRORS;
        }
        else {
            this.warningLevel = level;
        }
    }

    /**
     * Gets the currently configured source file encoding.
     */
    public String getSourceEncoding() {
        return this.sourceEncoding;
    }

    /**
     * Sets the encoding to be used when reading source files.
     */
    public void setSourceEncoding(String encoding) {
        setSourceEncodingOrDefault(encoding);
    }

    private void setSourceEncodingOrDefault(String encoding) {
        if (encoding == null) encoding = DEFAULT_SOURCE_ENCODING;
        this.sourceEncoding = encoding;
    }

    /**
     * Gets the currently configured output writer.
     * @deprecated not used anymore
     */
    @Deprecated
    public PrintWriter getOutput() {
        return this.output;
    }

    /**
     * Sets the output writer.
     * @deprecated not used anymore, has no effect
     */
    @Deprecated
    public void setOutput(PrintWriter output) {
        if (output == null) {
            this.output = new PrintWriter(NullWriter.DEFAULT);
        } else {
            this.output = output;
        }
    }

    /**
     * Gets the target directory for writing classes.
     */
    public File getTargetDirectory() {
        return this.targetDirectory;
    }

    /**
     * Sets the target directory.
     */
    public void setTargetDirectory(String directory) {
        setTargetDirectorySafe(directory);
    }

    private void setTargetDirectorySafe(String directory) {
        if (directory != null && directory.length() > 0) {
            this.targetDirectory = new File(directory);
        } else {
            this.targetDirectory = null;
        }
    }

    /**
     * Sets the target directory.
     */
    public void setTargetDirectory(File directory) {
        this.targetDirectory = directory;
    }

    /**
     * @return the classpath
     */
    public List<String> getClasspath() {
        return this.classpath;
    }

    /**
     * Sets the classpath.
     */
    public void setClasspath(String classpath) {
        this.classpath = new LinkedList<String>();
        StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator);
        while (tokenizer.hasMoreTokens()) {
            this.classpath.add(tokenizer.nextToken());
        }
    }

    /**
     * sets the classpath using a list of Strings
     * @param parts list of strings containing the classpath parts
     */
    public void setClasspathList(List<String> parts) {
        this.classpath = new LinkedList<String>(parts);
    }

    /**
     * Returns true if verbose operation has been requested.
     */
    public boolean getVerbose() {
        return this.verbose;
    }

    /**
     * Turns verbose operation on or off.
     */
    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    /**
     * Returns true if debugging operation has been requested.
     */
    public boolean getDebug() {
        return this.debug;
    }

    /**
     * Turns debugging operation on or off.
     */
    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    /**
     * Returns true if parameter metadata generation has been enabled.
     */
    public boolean getParameters() {
        return this.parameters;
    }

    /**
     * Turns parameter metadata generation on or off.
     */
    public void setParameters(boolean parameters) {
        this.parameters = parameters;
    }

    /**
     * Returns the requested error tolerance.
     */
    public int getTolerance() {
        return this.tolerance;
    }

    /**
     * Sets the error tolerance, which is the number of
     * non-fatal errors (per unit) that should be tolerated before
     * compilation is aborted.
     */
    public void setTolerance(int tolerance) {
        this.tolerance = tolerance;
    }

    /**
     * Gets the name of the base class for scripts.  It must be a subclass
     * of Script.
     */
    public String getScriptBaseClass() {
        return this.scriptBaseClass;
    }

    /**
     * Sets the name of the base class for scripts.  It must be a subclass
     * of Script.
     */
    public void setScriptBaseClass(String scriptBaseClass) {
        this.scriptBaseClass = scriptBaseClass;
    }

    public ParserPluginFactory getPluginFactory() {
        if (pluginFactory == null) {
            pluginFactory = ParserPluginFactory.antlr4(this);
        }
        return pluginFactory;
    }

    public void setPluginFactory(ParserPluginFactory pluginFactory) {
        this.pluginFactory = pluginFactory;
    }

    public void setScriptExtensions(Set<String> scriptExtensions) {
        if(scriptExtensions == null) scriptExtensions = new LinkedHashSet<String>();
        this.scriptExtensions = scriptExtensions;
    }

    public Set<String> getScriptExtensions() {
        if(scriptExtensions == null || scriptExtensions.isEmpty()) {
            /*
             *  this happens
             *  *    when groovyc calls FileSystemCompiler in forked mode, or
             *  *    when FileSystemCompiler is run from the command line directly, or
             *  *    when groovy was not started using groovyc or FileSystemCompiler either
             */
            scriptExtensions = SourceExtensionHandler.getRegisteredExtensions(
                    this.getClass().getClassLoader());
        }
        return scriptExtensions;
    }

    public String getDefaultScriptExtension() {
        return defaultScriptExtension;
    }


    public void setDefaultScriptExtension(String defaultScriptExtension) {
        this.defaultScriptExtension = defaultScriptExtension;
    }

    public void setRecompileGroovySource(boolean recompile) {
        recompileGroovySource = recompile;
    }

    public boolean getRecompileGroovySource(){
        return recompileGroovySource;
    }

    public void setMinimumRecompilationInterval(int time) {
        minimumRecompilationInterval = Math.max(0,time);
    }

    public int getMinimumRecompilationInterval() {
        return minimumRecompilationInterval;
    }

    /**
     * Allow setting the bytecode compatibility level. The parameter can take
     * one of the values in {@link #ALLOWED_JDKS}.
     *
     * @param version the bytecode compatibility level
     */
    public void setTargetBytecode(String version) {
        setTargetBytecodeIfValid(version);
    }

    private void setTargetBytecodeIfValid(String version) {
        if (JDK_TO_BYTECODE_VERSION_MAP.keySet().contains(version)) {
            this.targetBytecode = version;
        }
    }

    /**
     * Retrieves the compiler bytecode compatibility level.
     * Defaults to the minimum officially supported bytecode
     * version for any particular Groovy version.
     *
     * @return bytecode compatibility level
     */
    public String getTargetBytecode() {
        return this.targetBytecode;
    }

    /**
     * Whether the bytecode version has preview features enabled (JEP 12)
     *
     * @return preview features
     */
    public boolean isPreviewFeatures() {
        return previewFeatures;
    }

    /**
     * Sets whether the bytecode version has preview features enabled (JEP 12).
     *
     * @param previewFeatures whether to support preview features
     */
    public void setPreviewFeatures(boolean previewFeatures) {
        this.previewFeatures = previewFeatures;
    }

    private static String getMinBytecodeVersion() {
        return JDK8;
    }

    /**
     * Gets the joint compilation options for this configuration.
     * @return the options
     */
    public Map<String, Object> getJointCompilationOptions() {
        return jointCompilationOptions;
    }

    /**
     * Sets the joint compilation options for this configuration.
     * Using null will disable joint compilation.
     * @param options the options
     */
    public void setJointCompilationOptions(Map<String, Object> options) {
        jointCompilationOptions = options;
    }

    /**
     * Gets the optimization options for this configuration.
     * @return the options (always not null)
     */
    public Map<String, Boolean> getOptimizationOptions() {
        return optimizationOptions;
    }

    /**
     * Sets the optimization options for this configuration.
     * No entry or a true for that entry means to enable that optimization,
     * a false means the optimization is disabled.
     * Valid keys are "all" and "int".
     * @param options the options.
     * @throws IllegalArgumentException if the options are null
     */
    public void setOptimizationOptions(Map<String, Boolean> options) {
        if (options == null) throw new IllegalArgumentException("provided option map must not be null");
        optimizationOptions = options;
    }

    /**
     * Adds compilation customizers to the compilation process. A compilation customizer is a class node
     * operation which performs various operations going from adding imports to access control.
     * @param customizers the list of customizers to be added
     * @return this configuration instance
     */
    public CompilerConfiguration addCompilationCustomizers(CompilationCustomizer... customizers) {
        if (customizers == null) throw new IllegalArgumentException("provided customizers list must not be null");
        compilationCustomizers.addAll(Arrays.asList(customizers));
        return this;
    }

    /**
     * Returns the list of compilation customizers.
     * @return the customizers (always not null)
     */
    public List<CompilationCustomizer> getCompilationCustomizers() {
        return compilationCustomizers;
    }

    /**
     * Returns the list of disabled global AST transformation class names.
     * @return a list of global AST transformation fully qualified class names
     */
    public Set<String> getDisabledGlobalASTTransformations() {
        return disabledGlobalASTTransformations;
    }

    /**
     * Disables the specified global AST transformations. In order to avoid class loading side effects,
     * it is not recommended to use MyASTTransformation.class.getName() but instead directly use the class
     * name as a string. Disabled AST transformations only apply to automatically loaded global AST
     * transformations, that is to say transformations defined in a
     * META-INF/services/org.codehaus.groovy.transform.ASTTransformation file.
     * If you explicitly add a global AST transformation in your compilation process,
     * for example using the {@link org.codehaus.groovy.control.customizers.ASTTransformationCustomizer} or
     * using a {@link org.codehaus.groovy.control.CompilationUnit.PrimaryClassNodeOperation},
     * then nothing will prevent the transformation from being loaded.
     *
     * @param disabledGlobalASTTransformations a set of fully qualified class names of global AST transformations
     * which should not be loaded.
     */
    public void setDisabledGlobalASTTransformations(final Set<String> disabledGlobalASTTransformations) {
        this.disabledGlobalASTTransformations = disabledGlobalASTTransformations;
    }

    public BytecodeProcessor getBytecodePostprocessor() {
        return bytecodePostprocessor;
    }

    public void setBytecodePostprocessor(final BytecodeProcessor bytecodePostprocessor) {
        this.bytecodePostprocessor = bytecodePostprocessor;
    }

    /**
     * Check whether invoke dynamic enabled
     * @return the result
     */
    public boolean isIndyEnabled() {
        Boolean indyEnabled = this.getOptimizationOptions().get(INVOKEDYNAMIC);

        if (null == indyEnabled) {
            return false;
        }

        return indyEnabled;
    }

    /**
     * Check whether groovydoc enabled
     * @return the result
     */
    public boolean isGroovydocEnabled() {
        Boolean groovydocEnabled = this.getOptimizationOptions().get(GROOVYDOC);

        if (null == groovydocEnabled) {
            return false;
        }

        return groovydocEnabled;
    }

    /**
     * Check whether runtime groovydoc enabled
     * @return the result
     */
    public boolean isRuntimeGroovydocEnabled() {
        Boolean runtimeGroovydocEnabled = this.getOptimizationOptions().get(RUNTIME_GROOVYDOC);

        if (null == runtimeGroovydocEnabled) {
            return false;
        }

        return runtimeGroovydocEnabled;
    }

    /**
     * Check whether mem stub enabled
     * @return the result
     */
    public boolean isMemStubEnabled() {
        Object memStubEnabled = this.getJointCompilationOptions().get(MEM_STUB);

        if (null == memStubEnabled) {
            return false;
        }

        return "true".equals(memStubEnabled.toString());
    }


//       See http://groovy.329449.n5.nabble.com/What-the-static-compile-by-default-tt5750118.html
//           https://issues.apache.org/jira/browse/GROOVY-8543
//
//    {
//        // this object initializer assures that `enableCompileStaticByDefault` must be invoked no matter which constructor called.
//        if (getBooleanSafe("groovy.compile.static")) {
//            enableCompileStaticByDefault();
//        }
//    }
//
//
//    private void enableCompileStaticByDefault() {
//        compilationCustomizers.add(
//            new CompilationCustomizer(CompilePhase.CONVERSION) {
//                @Override
//                public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
//                    for (ClassNode cn : source.getAST().getClasses()) {
//                        newClassCodeVisitor(source).visitClass(cn);
//                    }
//                }
//
//                private ClassCodeVisitorSupport newClassCodeVisitor(SourceUnit source) {
//                    return new ClassCodeVisitorSupport() {
//                        @Override
//                        public void visitClass(ClassNode node) {
//                            enableCompileStatic(node);
//                        }
//
//                        private void enableCompileStatic(ClassNode classNode) {
//                            if (!classNode.getAnnotations(ClassHelper.make(GROOVY_TRANSFORM_COMPILE_STATIC)).isEmpty()) {
//                                return;
//                            }
//                            if (!classNode.getAnnotations(ClassHelper.make(GROOVY_TRANSFORM_COMPILE_DYNAMIC)).isEmpty()) {
//                                return;
//                            }
//
//                            classNode.addAnnotation(new AnnotationNode(ClassHelper.make(GROOVY_TRANSFORM_COMPILE_STATIC)));
//                        }
//
//                        @Override
//                        protected SourceUnit getSourceUnit() {
//                            return source;
//                        }
//
//                        private static final String GROOVY_TRANSFORM_COMPILE_STATIC = "groovy.transform.CompileStatic";
//                        private static final String GROOVY_TRANSFORM_COMPILE_DYNAMIC = "groovy.transform.CompileDynamic";
//                    };
//                }
//            }
//        );
//    }
}
