/*
 *
 *  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.apache.flex.compiler.config;

import java.io.*;
import java.text.DateFormat;
import java.util.*;
import java.util.regex.Pattern;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.flex.compiler.common.IPathResolver;
import org.apache.flex.compiler.common.VersionInfo;
import org.apache.flex.compiler.exceptions.ConfigurationException;
import org.apache.flex.compiler.exceptions.ConfigurationException.*;
import org.apache.flex.compiler.filespecs.FileSpecification;
import org.apache.flex.compiler.filespecs.IFileSpecification;
import org.apache.flex.compiler.internal.config.*;
import org.apache.flex.compiler.internal.config.annotations.*;
import org.apache.flex.compiler.internal.config.localization.LocalizationManager;
import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping;
import org.apache.flex.compiler.mxml.IMXMLTypeConstants;
import org.apache.flex.compiler.problems.*;
import org.apache.flex.swc.catalog.XMLFormatter;
import org.apache.flex.utils.FileUtils;
import org.apache.flex.utils.FilenameNormalization;

import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

/**
 * The model for all the configuration options supported by the compiler. Each option is stored in a private field. It
 * usually has a getter method, a setter method and a configuration method (started with "cfg"). The configuration
 * methods are used by the configurators to set the values of a given option name.
 * <p>
 * This class is currently being reviewed and refactored. See CMP-471 as the master bug for the tasks.
 * <p>
 * Steps to refactor:
 * <ol>
 * <li>Check "mxmlc" manual (http://adobe.ly/bffN8A) and copy documents to Javadoc on setters of options.</li>
 * <li>Check "configuration support" WIKI (http://bit.ly/oAI8gj) to see if an option should be deprecated.</li>
 * <li>Merge {@code cfgXXX} to {@code setXXX}, and annotate the setter.</li>
 * <li>Remove {@code getXXXInfo()} static method.</li>
 * </ol>
 * 
 * @see "http://bugs.adobe.com/jira/browse/CMP-471"
 */
public class Configuration
{
    private static final int DEFAULT_HEIGHT_MAX = 4096;
    private static final int DEFAULT_HEIGHT_MIN = 1;
    private static final int DEFAULT_WIDTH_MAX = 4096;
    private static final int DEFAULT_WIDTH_MIN = 1;

    public static final String DEFAULT_OUTPUT_DIRECTORY_TOKEN = "org.apache.flex.default.output.directory";

    public static final String SWC_AIRGLOBAL = "airglobal.swc";

    /**
     * Singleton empty string list. All getters returning a list of string should return this object when the field is
     * null.
     */
    private static final List<String> EMPTY_STRING_LIST = Collections.emptyList();

    private static final List<String> compcOnlyOptions = new ArrayList<String>(9);

    static
    {
        compcOnlyOptions.add("directory");
        compcOnlyOptions.add("include-classes");
        compcOnlyOptions.add("include-file");
        compcOnlyOptions.add("include-lookup-only");
        compcOnlyOptions.add("include-namespaces");
        compcOnlyOptions.add("include-sources");
        compcOnlyOptions.add("include-stylesheet");
        compcOnlyOptions.add("include-inheritance-dependencies-only");
    }

    /**
     * Validate configuration options values.
     * 
     * @param configurationBuffer Configuration buffer.
     * @throws ConfigurationException Error.
     */
    public void validate(ConfigurationBuffer configurationBuffer) throws ConfigurationException
    {
        // process the merged configuration buffer. right, can't just process the args.
        processDeprecatedAndRemovedOptions(configurationBuffer);

        validateDumpConfig(configurationBuffer);
    }

    private String[] removeNativeJSLibrariesIfNeeded(String[] libraryPaths)
    {
        List<String> libraryPathList = new ArrayList<String>(Arrays.asList(libraryPaths));
        String appHome = System.getProperty("application.home");
        if (appHome == null)
            return libraryPaths;
        appHome = appHome.replace("\\", "/");

        if (isExcludeNativeJSLibraries)
        {
            Iterator<String> pathIterator = libraryPathList.iterator();

            while (pathIterator.hasNext())
            {
                final String path = pathIterator.next().replace("\\", "/");
                final boolean isNativeJS = path.contains(appHome + "/js/libs")
                        && path.lastIndexOf(".swc") == path.length() - ".swc".length();

                if (isNativeJS)
                {
                    pathIterator.remove();
                }
            }
        }

        return libraryPathList.toArray(new String[libraryPathList.size()]);
    }

    /**
     * Validate that no compc-only options are used in a given configuration buffer. Use this method to verify no
     * compc-only args are used in mxmlc.
     * 
     * @param configurationBuffer the configuration buffer to check for compc-only options.
     * 
     * @throws ConfigurationException if a compc-only option is found in the configuration buffer.
     */
    public static void validateNoCompcOnlyOptions(ConfigurationBuffer configurationBuffer) throws ConfigurationException
    {
        for (String option : compcOnlyOptions)
        {
            List<ConfigurationValue> values = configurationBuffer.getVar(option);
            if (values != null && values.size() > 0)
                throw new ConfigurationException.UnknownVariable(values.get(0).getVar(), values.get(0).getSource(),
                        values.get(0).getLine());
        }
    }

    /**
     * The path of a given file name based on the context of the configuration value or the default output directory
     * token.
     * 
     * @param cv
     * @param fileName
     * @return the full path of the file.
     */
    protected String getOutputPath(ConfigurationValue cv, String fileName)
    {
        String result = fileName;

        if (fileName != null)
        {
            File file = new File(fileName);
            if (!FileUtils.isAbsolute(file))
            {
                String directory = cv.getBuffer().getToken(DEFAULT_OUTPUT_DIRECTORY_TOKEN);

                // if no default output directory, then use the configuration context.
                if (directory == null)
                {
                    directory = cv.getContext();
                }

                if (directory != null)
                {
                    result = FileUtils.addPathComponents(directory, fileName, File.separatorChar);
                }
            }
        }

        return pathResolver.resolve(result).getAbsolutePath();
    }

    private static Map<String, String> aliases = null;

    public static Map<String, String> getAliases()
    {
        if (aliases == null)
        {
            aliases = new HashMap<String, String>();

            aliases.put("l", "compiler.library-path");
            aliases.put("el", "compiler.external-library-path");
            aliases.put("fb", "use-flashbuilder-project-files");
            aliases.put("is", "include-sources");
            aliases.put("sp", "compiler.source-path");
            aliases.put("rsl", "runtime-shared-libraries");
            aliases.put("keep", "compiler.keep-generated-actionscript");
            aliases.put("o", "output");
            aliases.put("rslp", "runtime-shared-library-path");
            aliases.put("static-rsls", "static-link-runtime-shared-libraries");
        }
        return aliases;
    }

    //
    // PathResolver
    //
    private IPathResolver pathResolver;

    /**
     * Set a path resolver to resolver files relative to a configuration. Files inside of configuration files are
     * resolved relative to those configuration files and files on the command line are resolved relative to the root
     * directory of the compile.
     * 
     * @param pathResolver a path resolver for this configuration. May not be null.
     */
    public void setPathResolver(IPathResolver pathResolver)
    {
        this.pathResolver = pathResolver;
    }

    //
    // mainDefinition
    //
    private String mainDefinition;

    /**
     * Main definition is the root class of a SWF. {@code mxmlc} only takes one file in the source list. The main
     * definition name is the main source file name.
     * 
     * @return main definition
     */
    public String getMainDefinition()
    {
        return mainDefinition;
    }

    public void setMainDefinition(String mainDefinition)
    {
        assert mainDefinition != null : "main definition can't be null";
        assert!"".equals(mainDefinition) : "main definition can't be empty";

        this.mainDefinition = mainDefinition;
    }

    //
    // 'benchmark' option
    //
    @Config(removed = true)
    @Mapping("benchmark")
    public void setBenchmark(ConfigurationValue cv, boolean b)
    {
    }

    //
    // 'debug-password' option
    //

    private String debugPassword;

    /**
     * Lets you engage in remote debugging sessions with the Flash IDE.
     */
    public String getDebugPassword()
    {
        return debugPassword;
    }

    @Config(advanced = true)
    @Mapping("debug-password")
    @DefaultArgumentValue("")
    public void setDebugPassword(ConfigurationValue cv, String debugPassword)
    {
        this.debugPassword = debugPassword;
    }

    //
    // 'default-background-color' option
    //

    private int backgroundColor = 0x50727E;

    public int getDefaultBackgroundColor()
    {
        return this.backgroundColor;
    }

    @Config(advanced = true)
    @Mapping("default-background-color")
    public void setDefaultBackgroundColor(ConfigurationValue cv, int backgroundColor)
    {
        this.backgroundColor = backgroundColor;
    }

    //
    // 'default-frame-rate' option
    //

    private int frameRate = 24;

    public int getDefaultFrameRate()
    {
        return frameRate;
    }

    @Config(advanced = true)
    @Mapping("default-frame-rate")
    public void setDefaultFrameRate(ConfigurationValue cv, int rate) throws ConfigurationException
    {
        if (rate <= 0)
            throw new ConfigurationException.GreaterThanZero(cv.getVar(), cv.getSource(), cv.getLine());
        frameRate = rate;
    }

    //
    // 'default-script-limits' option
    //

    private int scriptLimit = 60;
    private int scriptRecursionLimit = 1000;
    private boolean scriptLimitsSet = false;

    public int getScriptTimeLimit()
    {
        return scriptLimit;
    }

    public int getScriptRecursionLimit()
    {
        return scriptRecursionLimit;
    }

    public boolean scriptLimitsSet()
    {
        return scriptLimitsSet;
    }

    @Config(advanced = true)
    @Mapping("default-script-limits")
    @Arguments({ "max-recursion-depth", "max-execution-time" })
    public void setDefaultScriptLimits(ConfigurationValue cv, int scriptLimit, int scriptRecursionLimit)
            throws ConfigurationException
    {
        if (scriptLimit <= 0)
            throw new ConfigurationException.GreaterThanZero(cv.getVar(), cv.getSource(), cv.getLine());

        if (scriptRecursionLimit <= 0)
            throw new ConfigurationException.GreaterThanZero(cv.getVar(), cv.getSource(), cv.getLine());

        this.scriptLimitsSet = true;
        this.scriptLimit = scriptRecursionLimit;
        this.scriptRecursionLimit = scriptLimit;
    }

    //
    // 'default-size' option
    //

    private int defaultWidth = 500;
    private int defaultHeight = 375;

    public int getDefaultWidth()
    {
        return defaultWidth;
    }

    public int getDefaultHeight()
    {
        return defaultHeight;
    }

    @Config(advanced = true)
    @Arguments({ "width", "height" })
    @Mapping("default-size")
    public void setDefaultSize(ConfigurationValue cv, int width, int height) throws ConfigurationException
    {
        if (width < DEFAULT_WIDTH_MIN || width > DEFAULT_WIDTH_MAX || height < DEFAULT_HEIGHT_MIN
                || height > DEFAULT_HEIGHT_MAX)
            throw new ConfigurationException.IllegalDimensions(width, height, cv.getVar(), cv.getSource(),
                    cv.getLine());

        this.defaultWidth = width;
        this.defaultHeight = height;
    }

    //
    // 'externs' option
    //

    private final Set<String> externs = new LinkedHashSet<String>();

    public Set<String> getExterns()
    {
        return externs;
    }

    /**
     * Sets a list of classes to exclude from linking when compiling a SWF file. This option provides compile-time link
     * checking for external references that are dynamically linked.
     */
    @Config(advanced = true, allowMultiple = true)
    @Mapping("externs")
    @Arguments("symbol")
    @InfiniteArguments
    public void setExterns(ConfigurationValue cfgval, List<String> vals)
    {
        externs.addAll(QNameNormalization.normalize(vals));
    }

    //
    // 'includes' option
    //

    private final Set<String> includes = new LinkedHashSet<String>();

    public Set<String> getIncludes()
    {
        return includes;
    }

    /**
     * Links one or more classes to the resulting application SWF file, whether or not those classes are required at
     * compile time. To link an entire SWC file rather than individual classes, use the include-libraries option.
     */
    @Config(allowMultiple = true, advanced = true)
    @Mapping("includes")
    @Arguments("symbol")
    @InfiniteArguments
    public void setIncludes(ConfigurationValue cfgval, List<String> vals)
    {
        includes.addAll(QNameNormalization.normalize(vals));
    }

    //
    // 'framework' option
    //
    //
    @Config(allowMultiple = true, advanced = true, removed = true)
    @Mapping("framework")
    public void setFramework(ConfigurationValue cfgval, String value)
    {
    }

    // 'link-report' option
    //

    private String linkReportFileName = null;

    public File getLinkReport()
    {
        return linkReportFileName != null ? new File(linkReportFileName) : null;
    }

    /**
     * Prints linking information to the specified output file. This file is an XML file that contains {@code def} tags,
     * {@code pre} tags and {@code ext} tags showing linker dependencies in the final SWF file. The file format output
     * by this command can be used to write a file for input to the {@code load-externs} option.
     */
    @Config(advanced = true)
    @Mapping("link-report")
    @Arguments("filename")
    public void setLinkReport(ConfigurationValue cv, String filename)
    {
        this.linkReportFileName = getOutputPath(cv, filename);
    }

    //
    // 'size-report' option
    //

    private String sizeReportFileName = null;

    public File getSizeReport()
    {
        return sizeReportFileName != null ? new File(sizeReportFileName) : null;
    }

    @Config(advanced = true)
    @Mapping("size-report")
    @Arguments("filename")
    public void setSizeReport(ConfigurationValue cv, String filename)
    {
        this.sizeReportFileName = getOutputPath(cv, filename);
    }

    //
    // 'load-externs' option
    //

    /**
     * Specifies the location of an XML file that contains def, pre, and ext symbols to omit from linking when compiling
     * a SWF file. The XML file uses the same syntax as the one produced by the link-report option.
     * <p>
     * This option provides compile-time link checking for external components that are dynamically linked.
     */
    @Config(allowMultiple = true, advanced = true)
    @Mapping("load-externs")
    @Arguments("filename")
    public void setLoadExterns(ConfigurationValue cfgval, String filename) throws ConfigurationException
    {
        final String path = resolvePathStrict(filename, cfgval);
        final FileSpecification f = new FileSpecification(path);
        final List<String> externsFromFile = LoadExternsParser.collectExterns(cfgval, f);
        externs.addAll(externsFromFile);
    }

    //
    // 'raw-metadata' option
    //

    private String metadata = null;

    public String getRawMetadata()
    {
        if (metadata != null)
            return metadata;

        return generateMetadata();
    }

    private static final String RDF_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
    private static final String DC_URI = "http://purl.org/dc/elements/1.1";

    /**
     * @return Metadata XML string.
     */
    private final String generateMetadata()
    {
        final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
        assert xmlOutputFactory != null : "Expect XMLOutputFactory implementation.";
        final StringWriter stringWriter = new StringWriter();
        XMLStreamWriter xmlWriter = null;

        try
        {
            xmlWriter = new XMLFormatter(xmlOutputFactory.createXMLStreamWriter(stringWriter));
            xmlWriter.writeStartDocument();

            xmlWriter.writeStartElement("rdf", "RDF", RDF_URI);
            xmlWriter.setPrefix("rdf", RDF_URI);
            xmlWriter.writeNamespace("rdf", RDF_URI);

            // write rdf:Description
            xmlWriter.writeStartElement(RDF_URI, "Description");
            xmlWriter.setPrefix("dc", DC_URI);
            xmlWriter.setPrefix(VersionInfo.COMPILER_NAMESPACE_PREFIX, VersionInfo.COMPILER_NAMESPACE_URI);
            xmlWriter.writeNamespace("dc", DC_URI);
            xmlWriter.writeNamespace(VersionInfo.COMPILER_NAMESPACE_PREFIX, VersionInfo.COMPILER_NAMESPACE_URI);

            // write dc:format
            xmlWriter.writeStartElement(DC_URI, "format");
            xmlWriter.writeCharacters("application/x-shockwave-flash");
            xmlWriter.writeEndElement();

            if (isFlex())
            {
                // write localizedTitles
                writeMap(xmlWriter, DC_URI, "description", localizedDescriptions);

                // write localizedDescription
                writeMap(xmlWriter, DC_URI, "title", localizedTitles);

                // write publisher
                writeCollection(xmlWriter, DC_URI, "publisher", publishers);

                // write creators
                writeCollection(xmlWriter, DC_URI, "creator", creators);

                // write contributor
                writeCollection(xmlWriter, DC_URI, "contributor", contributors);

                // write language
                writeCollection(xmlWriter, DC_URI, "language", langs);

                // write date
                writeDate(xmlWriter);
            }

            // write compiledBy
            writeCompiledBy(xmlWriter);

            // write
            xmlWriter.writeEndElement(); // Description
            xmlWriter.writeEndDocument();
        }
        catch (XMLStreamException e)
        {
            return "";
        }

        return stringWriter.toString();
    }

    /**
     * Write information about the compiler that compiled the swf.
     * 
     * @param writer
     * @throws XMLStreamException
     */
    private void writeCompiledBy(XMLStreamWriter writer) throws XMLStreamException
    {
        writer.writeEmptyElement(VersionInfo.COMPILER_NAMESPACE_URI, VersionInfo.COMPILER_ELEMENT);
        writer.writeAttribute(VersionInfo.COMPILER_NAME_ATTRIBUTE, VersionInfo.getCompilerName());
        writer.writeAttribute(VersionInfo.COMPILER_VERSION_ATTRIBUTE, VersionInfo.getCompilerVersion());
        writer.writeAttribute(VersionInfo.COMPILER_BUILD_ATTRIBUTE, VersionInfo.getCompilerBuild());

        writer.writeEndElement(); // compiledBy
    }

    /**
     * Write the data to rdf/xml
     * 
     * @param writer
     * @throws XMLStreamException
     */
    private void writeDate(XMLStreamWriter writer) throws XMLStreamException
    {
        if (date == null)
        {
            date = DateFormat.getDateInstance().format(new Date());
        }

        writer.writeStartElement(DC_URI, "date");
        writer.writeCharacters(date);
        writer.writeEndElement();
    }

    /**
     * Write a map of values to rdf/xml
     * 
     * @param writer
     * @param namespaceURI
     * @param localName
     * @param mapData
     * @throws XMLStreamException
     */
    private void writeMap(XMLStreamWriter writer, String namespaceURI, String localName, Map<String, String> mapData)
            throws XMLStreamException
    {
        if (mapData.size() > 0)
        {
            writer.writeStartElement(namespaceURI, localName);
            if ((mapData.size() == 1) && (mapData.get("x-default") != null))
            {
                String data = mapData.get("x-default");
                writer.writeCharacters(data);
            }
            else
            {
                writer.writeStartElement(RDF_URI, "Alt");
                for (final String key : mapData.keySet())
                {
                    final String value = mapData.get(key);
                    writer.writeStartElement(RDF_URI, "li");
                    writer.writeAttribute("xml", "", "lang", key);
                    writer.writeCharacters(value);
                    writer.writeEndElement();
                }
                writer.writeEndElement();
            }

            writer.writeEndElement();
        }

    }

    /**
     * Write a collection values to rdf/xml.
     * 
     * @param writer
     * @param namespaceURI
     * @param localName
     * @param values
     * @throws XMLStreamException
     */
    private void writeCollection(XMLStreamWriter writer, String namespaceURI, String localName,
            Collection<String> values) throws XMLStreamException
    {
        if (values.isEmpty())
            return;

        writer.writeStartElement(namespaceURI, localName);

        if (values.size() > 1)
            writer.writeStartElement(RDF_URI, "Bag");

        for (String value : values)
        {
            writer.writeCharacters(value);
        }

        if (values.size() > 1)
            writer.writeEndElement();

        writer.writeEndElement();

    }

    /**
     * Defines the metadata for the resulting SWF file. The value of this option overrides any metadata-related compiler
     * options such as contributor, creator, date, and description.
     */
    @Config(advanced = true)
    @Mapping("raw-metadata")
    @Arguments("text")
    public void setRawMetadata(ConfigurationValue cv, String xml) throws ConfigurationException
    {
        if (metadata != null)
        {
            throw new ConfigurationException.BadMetadataCombo(cv.getVar(), cv.getSource(), cv.getLine());
        }

        this.metadata = xml;
    }

    //
    // 'resource-bundle-list' option
    //

    private String rbListFileName = null;

    public String getResourceBundleList()
    {
        return rbListFileName;
    }

    //
    // 'include-resource-bundles' option
    //

    /**
     * include-resource-bundles [...]
     */
    private List<String> includeResourceBundles = new ArrayList<String>();

    /**
     * @return a list of resource bundles to include in the swc
     */
    public List<String> getIncludeResourceBundles()
    {
        return includeResourceBundles;
    }

    /**
     * Sets the resource bundles that should be included in this SWC or SWF. This list can have locale independent
     * qualified name for property files (with the name not including the suffix) or qualified name for classes that
     * extend ResourceBundle.
     * <p>
     * Qualified name of a properties file is determined by its relative path to its parent source folder. Such as:
     * <p>
     * Source path: locale/{locale}
     * <p>
     * Path of properties file 1: locale/en_US/A.properties Qualified name of properties file 1: A
     * <p>
     * Path of properties file 2: locale/en_US/com/resources/B.properties Qualified name of properties file 1:
     * com.resources.B
     * <p>
     * Note: Source folders of all the properties files passed using this argument should be in the project's source
     * path list.
     * 
     * @param cv configuration value objects
     * @param values list of resource bundles to include in the swc or swf
     */
    @Config(allowMultiple = true)
    @Mapping("include-resource-bundles")
    @Arguments("bundle")
    @FlexOnly
    public void setIncludeResourceBundles(ConfigurationValue cv, List<String> values)
    {
        includeResourceBundles.addAll(values);
    }

    /**
     * Prints a list of resource bundles that are used by the current application to a file named with the filename
     * argument. You then use this list as input that you specify with the include-resource-bundles option to create a
     * resource module.
     */
    @Config(advanced = true)
    @Mapping("resource-bundle-list")
    @Arguments("filename")
    @FlexOnly
    public void setResourceBundleList(ConfigurationValue cv, String filename)
    {
        this.rbListFileName = getOutputPath(cv, filename);
    }

    //
    // 'runtime-shared-libraries' option
    //

    private List<String> rslList = new LinkedList<String>();

    public List<String> getRuntimeSharedLibraries()
    {
        return rslList;
    }

    /**
     * Specifies a list of runtime shared libraries (RSLs) to use for this application. RSLs are dynamically-linked at
     * run time. The compiler externalizes the contents of the application that you are compiling that overlap with the
     * RSL.
     * <p>
     * You specify the location of the SWF file relative to the deployment location of the application. For example, if
     * you store a file named library.swf file in the web_root/libraries directory on the web server, and the
     * application in the web root, you specify libraries/library.swf.
     */
    @Config(allowMultiple = true)
    @Mapping("runtime-shared-libraries")
    @Arguments("url")
    @InfiniteArguments
    @FlexOnly
    public void setRuntimeSharedLibraries(ConfigurationValue cfgval, List<String> urls) throws ConfigurationException
    {
        rslList.addAll(urls);
    }

    //
    // 'use-network' option
    //

    private boolean useNetwork = true;

    public boolean getUseNetwork()
    {
        return useNetwork;
    }

    /**
     * Specifies that the current application uses network services.
     * <p>
     * The default value is true.
     * <p>
     * When the use-network property is set to false, the application can access the local filesystem (for example, use
     * the XML.load() method with file: URLs) but not network services. In most circumstances, the value of this
     * property should be true.
     */
    @Config
    @Mapping("use-network")
    public void setUseNetwork(ConfigurationValue cv, boolean b)
    {
        this.useNetwork = b;
    }

    //
    // runtime-shared-library-path
    //

    private List<RuntimeSharedLibraryPathInfo> rslPathInfoList;

    /**
     * @return List of of all the -runtime-shared-libraries-path options. Each-runtime-shared-libraries-path option
     *         supplied results in a RslPathInfo object. Each object in the list is of type RslPathInfo.
     *         <p>
     *         The list will be empty if -static-link-runtime-shared-libraries=true.
     *         <p>
     *         TODO Verify if this is still true and make the code do what it says.
     */
    public List<RuntimeSharedLibraryPathInfo> getRslPathInfo()
    {
        if (rslPathInfoList == null)
            return Collections.emptyList();
        else
            return rslPathInfoList;
    }

    public List<File> getRslExcludedLibraries()
    {
        if (rslPathInfoList == null || getStaticLinkRsl())
            return Collections.emptyList();

        return Lists.transform(rslPathInfoList, new Function<RuntimeSharedLibraryPathInfo, File>()
        {
            @Override
            public File apply(RuntimeSharedLibraryPathInfo info)
            {
                return info.getSWCFile();
            }
        });
    }

    /**
     * Specifies the location of a runtime shared library (RSL). The compiler externalizes the contents of the
     * application that you are compiling that overlap with the RSL.
     * <p>
     * The path-element argument is the location of the SWC file or open directory to compile against. For example,
     * c:\flexsdk\frameworks\libs\framework.swc. This is the equivalent of the using the external-library-path option
     * when compiling against an RSL using the runtime-shared-libraries option.
     * <p>
     * The rsl-url argument is the URL of the RSL that will be used to load the RSL at runtime. The compiler does not
     * verify the existence of the SWF file at this location at compile time. It does store this string in the
     * application, however, and uses it at run time. As a result, the SWF file must be available at run time but
     * necessarily not at compile time.
     * <p>
     * The policy-file-url is the location of the crossdomain.xml file that gives permission to read the RSL from the
     * server. This might be necessary because the RSL can be on a separate server as the application. For example,
     * http://www.mydomain.com/rsls/crossdomain.xml.
     * <p>
     * The failover-url and second policy-file-url arguments specify the location of the secondary RSL and
     * crossdomain.xml file if the first RSL cannot be loaded. This most commonly happens when the client Player version
     * does not support cross-domain RSLs. You can add any number of failover RSLs, but must include a policy file URL
     * for each one.
     * <p>
     * Do not include spaces between the comma-separated values. The following example shows how to use this option:
     * 
     * <pre>
     * mxmlc -o=../lib/app.swf -runtime-shared-library-path=../lib/mylib.swc,../bin/myrsl.swf Main.mxml
     * </pre>
     * 
     * You can specify more than one library file to be used as an RSL. You do this by adding additional
     * runtime-shared-library-path options.
     * <p>
     * You can also use the runtime-shared-libraries command to use RSLs with your applications. However, the
     * runtime-shared-library-path option lets you also specify the location of the policy file and failover RSL.
     * <p>
     */
    // NOTE: if the annotations are modified, then also modify the annotations
    // in COMPCConfiguration.
    @Config(allowMultiple = true)
    @Mapping({ "runtime-shared-library-path" })
    @SoftPrerequisites({ "static-link-runtime-shared-libraries" })
    @ArgumentNameGenerator(RSLArgumentNameGenerator.class)
    @InfiniteArguments
    @FlexOnly
    public void setRuntimeSharedLibraryPath(ConfigurationValue cfgval, List<String> urls) throws ConfigurationException
    {

        if (urls.isEmpty())
            return;

        // Usage rule: if you use -rslp on the command line
        // it will take effect unless you also specify -static-rsls=true on the command line.
        if (CommandLineConfigurator.SOURCE_COMMAND_LINE.equals(cfgval.getSource()))
        {
            setOverrideStaticLinkRsl(false);
        }

        // ignore rsl if told to
        if (getStaticLinkRsl())
        {
            return;
        }

        if (urls.size() < 2)
        {
            // insufficent arguments
            throw new ConfigurationException.MissingArgument("rsl-url", "runtime-shared-library-path",
                    cfgval.getSource(), cfgval.getLine());
        }

        RuntimeSharedLibraryPathInfo info = new RuntimeSharedLibraryPathInfo();

        // validate the first argument, the swc or open directory, required.
        String include = resolvePathStrict(urls.get(0), cfgval, true);
        info.setSWCPath(urls.get(0));
        info.setSWCFile(new File(include));

        // the rest of the args are: rsl-url, policy-file-url, rsl-url, policy-file-url,... 
        for (int i = 1; i < urls.size(); ++i)
        {
            final String url = urls.get(i);
            if ((i + 1) % 2 == 0)
            {
                if ("".equals(url.length()))
                {
                    // rsl urls is required
                    throw new ConfigurationException.MissingArgument("rsl-url", "runtime-shared-library-path",
                            cfgval.getSource(), cfgval.getLine());
                }
                info.addRSLURL(url);
            }
            else
            {
                info.addPolicyFileURL(url);
            }
        }

        // if the last policy file was not specified, then add an empty one so
        // there are always the same number of rsls and policy files.
        if ((urls.size() % 2) == 0)
        {
            info.addPolicyFileURL("");
        }

        // take local variables and add to overall arguments.
        if (rslPathInfoList == null)
        {
            rslPathInfoList = new ArrayList<RuntimeSharedLibraryPathInfo>();
        }

        rslPathInfoList.add(info);
    }

    //
    // 'static-link-runtime-shared-libraries' option
    // 

    private boolean staticLinkRsl = true;
    private String staticLinkRslSource;

    /**
     * @return true if -cd-rsl option should be used. False otherwise.
     */
    public boolean getStaticLinkRsl()
    {
        return staticLinkRsl;
    }

    /**
     * Allow another option, namely -rslp to override the value of static-rsls. But you can not override a -static-rsls
     * option that came from the command line.
     * 
     * @param staticLinkRsl
     */
    protected void setOverrideStaticLinkRsl(boolean staticLinkRsl)
    {
        if (CommandLineConfigurator.SOURCE_COMMAND_LINE.equals(staticLinkRslSource))
        {
            return;
        }

        this.staticLinkRsl = staticLinkRsl;
    }

    /**
     * Determines whether to compile against libraries statically or use RSLs. Set this option to true to ignore the
     * RSLs specified by the runtime-shared-library-path option. Set this option to false to use the RSLs.
     * <p>
     * This option is useful so that you can quickly switch between a statically and dynamically linked application
     * without having to change the runtime-shared-library-path option, which can be verbose, or edit the configuration
     * files.
     */
    @Config
    @Mapping("static-link-runtime-shared-libraries")
    @FlexOnly
    public void setStaticLinkRuntimeSharedLibraries(ConfigurationValue cv, boolean b)
    {
        staticLinkRsl = b;
        staticLinkRslSource = cv.getSource();
    }

    //
    // 'use-flashbuilder-project-files' option
    //
    private Boolean useFlashBuilderProjectFiles = false;

    public Boolean getUseFlashBuilderProjectFiles()
    {
        return useFlashBuilderProjectFiles;
    }

    @Config
    @Mapping({ "use-flashbuilder-project-files" })
    @FlexOnly
    public void setUseFlashBuilderProjectFiles(ConfigurationValue cv, Boolean useFiles) throws ConfigurationException
    {
        useFlashBuilderProjectFiles = useFiles;
    }

    //
    // 'verify-digests' options
    // 

    private boolean verifyDigests = true;

    /**
     * @return true if digest information associated with the -cd-rsl option is used by the application at runtime.
     *         False otherwise.
     */
    public boolean getVerifyDigests()
    {
        return verifyDigests;
    }

    /**
     * Instructs the application to check the digest of the RSL SWF file against the digest that was compiled into the
     * application at compile time. This is a security measure that lets you load RSLs from remote domains or different
     * sub-domains. It also lets you enforce versioning of your RSLs by forcing an application's digest to match the
     * RSL's digest. If the digests are out of sync, you must recompile your application or load a different RSL SWF
     * file.
     */
    @Config(advanced = true)
    @FlexOnly
    public void setVerifyDigests(ConfigurationValue cv, boolean b)
    {
        verifyDigests = b;
    }

    //
    // 'remove-unused-rsls' option
    // 

    private boolean removeUnusedRSLs = false;

    /**
     * @return true if the user wants to remove unused RSLs. Otherwise false.
     */
    public boolean getRemoveUnusedRsls()
    {
        return removeUnusedRSLs;
    }

    @Config(advanced = true)
    @FlexOnly
    public void setRemoveUnusedRsls(ConfigurationValue cv, boolean b)
    {
        removeUnusedRSLs = b;
    }

    //
    // '-include-inheritance-dependencies-only' option
    // 

    private boolean includeInheritanceDependenciesOnly = false;

    /**
     * @return true if the user want to include inheritance dependencies only.
     */
    public boolean getIncludeInheritanceDependenciesOnly()
    {
        return includeInheritanceDependenciesOnly;
    }

    @Config(advanced = true)
    public void setIncludeInheritanceDependenciesOnly(ConfigurationValue cv, boolean b)
    {
        includeInheritanceDependenciesOnly = b;
    }

    //
    // 'target-player' option
    // 

    // targeted player version (also set in DefaultsConfigurator)
    private int majorVersionTarget = 11;
    private int minorVersionTarget = 1;
    private int revisionTarget = 0;

    /**
     * The major part the earliest player version that this compiler can target. The code generator generates bytecode
     * which will not pass verification on players earlier than 10.1.
     */
    public static final int TARGET_PLAYER_MAJOR_VERSION_MIN = 10;

    /**
     * The minor part the earliest player version that this compiler can target. The code generator generates bytecode
     * which will not pass verification on players earlier than 10.1.
     */
    public static final int TARGET_PLAYER_MINOR_VERSION_MIN = 1;

    /**
     * @return The major version of the player targeted by this application. The returned value will be greater to or
     *         equal to 9.
     */
    public int getTargetPlayerMajorVersion()
    {
        return majorVersionTarget;
    }

    /**
     * @return The minor version of the player targeted by this application. The returned value will be greater to or
     *         equal to 0.
     */
    public int getTargetPlayerMinorVersion()
    {
        return minorVersionTarget;
    }

    /**
     * @return The revision of the player targeted by this application. The returned value will be greater to or equal
     *         to 0.
     */
    public int getTargetPlayerRevision()
    {
        return revisionTarget;
    }

    /**
     * Specifies the version of Flash Player that you want to target with the application. Features requiring a later
     * version of Flash Player are not compiled into the application.
     * <p>
     * The player_version parameter has the following format:<br>
     * <code>major_version.minor_version.revision</code>
     * <p>
     * The major_version is required while minor_version and revision are optional. The minimum value is 10.0.0. If you
     * do not specify the minor_version or revision, then the compiler uses zeros.
     * <p>
     * The value of major_version is also used by the {targetPlayerMajorVersion} token in the flex-config.xml file. This
     * token can be used in any <path-element> element.
     * <p>
     * If you do not explicitly set the value of this option, the compiler uses the default from the flex-config.xml
     * file. The value in flex-config.xml is the version of Flash Player that shipped with the SDK.
     * <p>
     * This option is useful if your application's audience has a specific player and cannot upgrade. You can use this
     * to "downgrade" your application for that audience.
     */
    @Config
    @Arguments("version")
    public void setTargetPlayer(ConfigurationValue cv, String version) throws ConfigurationException
    {
        if (version == null || version.equals(""))
            return;

        final String[] results = Iterables.toArray(Splitter.on(".").omitEmptyStrings().trimResults().split(version),
                String.class);

        // major.minor.revision
        // major is required, minor and revision are optional
        if (results.length < 1 || results.length > 3)
            throw new ConfigurationException.BadVersion(version, "target-player");

        final String majorVersion = results[0];

        final String minorVersion;
        if (results.length > 1)
            minorVersion = results[1];
        else
            minorVersion = "0";

        final String revision;
        if (results.length > 2)
            revision = results[2];
        else
            revision = "0";

        try
        {
            majorVersionTarget = Integer.parseInt(majorVersion);
            minorVersionTarget = Integer.parseInt(minorVersion);
            revisionTarget = Integer.parseInt(revision);
        }
        catch (NumberFormatException e)
        {
            throw new ConfigurationException.BadVersion(version, "target-player");
        }

        if (majorVersionTarget < TARGET_PLAYER_MAJOR_VERSION_MIN
                || majorVersionTarget == TARGET_PLAYER_MAJOR_VERSION_MIN
                        && minorVersionTarget < TARGET_PLAYER_MINOR_VERSION_MIN)
        {
            throw new ConfigurationException.BadVersion(version, "target-player");
        }
    }

    //
    // 'swf-version' option
    //

    // swf version 13 is what shipped with player 11, and is the min version for
    // LZMA compression
    private static final Map<String, Integer> targetPlayerToSWFVersionMap = getSwfVersionMap();

    private static Map<String, Integer> getSwfVersionMap()
    {
        // Player 9 and below are not supported.
        // 10.0 -> 10
        // 10.1 -> 10
        // 10.2 -> 11
        // 10.3 -> 12
        // 11.0 -> 13
        // 11.1 -> 14
        // 11.2 -> 15
        // 11.3 -> 16
        // 11.4 -> 17 
        // 11.5 -> 18
        // 11.6 -> 19
        // 11.7 -> 20
        // 11.8 -> 21
        // 11.9 -> 22

        Map<String, Integer> map = new HashMap<String, Integer>(10);

        map.put("10.0", 10);
        map.put("10.1", 10);
        map.put("10.2", 11);
        map.put("10.3", 12);
        map.put("11.0", 13);
        map.put("11.1", 14);
        map.put("11.2", 15);
        map.put("11.3", 16);
        map.put("11.4", 17);
        map.put("11.5", 18);
        map.put("11.6", 19);
        map.put("11.7", 20);
        map.put("11.8", 21);
        map.put("11.9", 22);

        return map;
    }

    private int lookupSwfVersion()
    {
        int swfVersion = DEFAULT_SWF_VERSION;
        Integer lookupVersion = targetPlayerToSWFVersionMap.get(Integer.toString(getTargetPlayerMajorVersion()) + "."
                + Integer.toString(getTargetPlayerMinorVersion()));
        if (lookupVersion != null)
            swfVersion = lookupVersion;

        return swfVersion;
    }

    private final int UNSET_SWF_VERSION = -1;
    private final int DEFAULT_SWF_VERSION = 14; // matches default target-player
    private final int MINIMUM_SWF_VERSION = 10; // matches minimum target-player

    private int swfVersion = UNSET_SWF_VERSION;

    public int getSwfVersion()
    {
        if (swfVersion == UNSET_SWF_VERSION)
            swfVersion = lookupSwfVersion();
        return swfVersion;
    }

    @Config
    @Mapping("swf-version")
    public void setSwfVersion(ConfigurationValue cv, int version) throws ConfigurationException
    {
        if (version < MINIMUM_SWF_VERSION)
            throw new ConfigurationException.BadVersion(Integer.toString(version), "swf-version");

        swfVersion = version;
    }

    //
    // 'use-direct-blit' option
    //

    private boolean useDirectBlit = true;

    public boolean getUseDirectBlit()
    {
        return useDirectBlit;
    }

    @Config
    public void setUseDirectBlit(ConfigurationValue cv, boolean value)
    {
        useDirectBlit = value;
    }

    //
    // 'use-gpu' option
    //

    private boolean useGpu = true;

    public boolean getUseGpu()
    {
        return useGpu;
    }

    @Config
    public void setUseGpu(ConfigurationValue cv, boolean value)
    {
        useGpu = value;
    }

    //
    // 'tools-locale' options
    // 

    private Locale toolsLocale = null;

    /**
     * @return locale to use when reporting compile time errors, or <code>null</code> if not specified. In that case,
     *         system's locale is used.
     */
    public Locale getToolsLocale()
    {
        return toolsLocale;
    }

    /**
     * Configures the LocalizationManager's locale, which is used when reporting compile time errors, warnings, and
     * info.
     * 
     * @param toolsLocale A locale in Java format. For example, "en" or "ja_JP".
     * @throws ConfigurationException When the specified toolsLocale is not available a ToolsLocaleNotAvailable error is
     *         reported.
     */
    @Config
    @Mapping("tools-locale")
    public void setToolsLocale(ConfigurationValue cv, String toolsLocale) throws ConfigurationException
    {
        Locale[] locales = Locale.getAvailableLocales();

        for (int i = 0; i < locales.length; i++)
        {
            if (locales[i].toString().equals(toolsLocale))
            {
                this.toolsLocale = locales[i];

                LocalizationManager.get().setLocale(locales[i]);
                return;
            }
        }

        throw new ConfigurationException.ToolsLocaleNotAvailable(cv.getVar(), cv.getSource(), cv.getLine());
    }

    //
    // 'compiler.accessible' option
    //

    private boolean accessible = false;

    public boolean getCompilerAccessible()
    {
        return accessible;
    }

    /**
     * Enables accessibility features when compiling the application or SWC file.
     */
    @Config
    @Mapping({ "compiler", "accessible" })
    @FlexOnly
    public void setCompilerAccessible(ConfigurationValue cv, boolean accessible)
    {
        this.accessible = accessible;
    }

    //
    // 'compiler.actionscript-file-encoding' option
    //

    private String actionscriptFileEncoding = null;

    public String getCompilerActionscriptFileEncoding()
    {
        return actionscriptFileEncoding;
    }

    /**
     * Sets the file encoding for ActionScript files.
     */
    @Config
    @Mapping({ "compiler", "actionscript-file-encoding" })
    public void setCompilerActionscriptFileEncoding(ConfigurationValue cv, String encoding)
    {
        actionscriptFileEncoding = encoding;
    }

    //
    // 'compiler.adjust-opdebugline' option (hidden)
    //

    private boolean adjustOpDebugLine = true;

    public boolean getAdjustOpDebugLine()
    {
        return adjustOpDebugLine;
    }

    /**
     * For internal use only. Set it to false so that debugging mxmlc auto-generated code is easier.
     */
    @Config(advanced = true, hidden = true)
    public void setCompilerAdjustOpdebugline(ConfigurationValue cv, boolean b)
    {
        adjustOpDebugLine = b;
    }

    //
    // 'compiler.allow-source-path-overlap' option
    //

    private boolean allowSourcePathOverlap = false;

    public boolean getAllowSourcePathOverlap()
    {
        return allowSourcePathOverlap;
    }

    /**
     * Checks if a source-path entry is a sub-directory of another source-path entry. It helps make the package names of
     * MXML components unambiguous.
     */
    @Config(advanced = true)
    public void setCompilerAllowSourcePathOverlap(ConfigurationValue cv, boolean b)
    {
        allowSourcePathOverlap = b;
    }

    //
    // 'compiler.binding-value-change-event' option
    //

    private String bindingValueChangeEvent = "mx.events.PropertyChangeEvent";

    public String getBindingValueChangeEvent()
    {
        return bindingValueChangeEvent;
    }

    /**
     * The change event class for generated binding code
     */
    @Config(advanced = true)
    public void setCompilerBindingValueChangeEvent(ConfigurationValue cv, String b)
    {
        bindingValueChangeEvent = b;
    }

    //
    // 'compiler.binding-value-change-event-kind' option
    //

    private String bindingValueChangeEventKind = "mx.events.PropertyChangeEventKind";

    public String getBindingValueChangeEventKind()
    {
        return bindingValueChangeEventKind;
    }

    /**
     * The change event kind for generated binding code
     */
    @Config(advanced = true)
    public void setCompilerBindingValueChangeEventKind(ConfigurationValue cv, String b)
    {
        bindingValueChangeEventKind = b;
    }

    //
    // 'compiler.binding-value-change-event-type' option
    //

    private String bindingValueChangeEventType = "propertyChange";

    public String getBindingValueChangeEventType()
    {
        return bindingValueChangeEventType;
    }

    /**
     * The change event type for generated binding code
     */
    @Config(advanced = true)
    public void setCompilerBindingValueChangeEventType(ConfigurationValue cv, String b)
    {
        bindingValueChangeEventType = b;
    }

    //
    // 'compiler.binding-event-handler-event' option
    //

    private String bindingEventHandlerEvent = "flash.events.Event";

    public String getBindingEventHandlerEvent()
    {
        return bindingEventHandlerEvent;
    }

    /**
     * The event handler event for generated binding code
     */
    @Config(advanced = true)
    public void setCompilerBindingEventHandlerEvent(ConfigurationValue cv, String b)
    {
        bindingEventHandlerEvent = b;
    }

    //
    // 'compiler.binding-event-handler-class' option
    //

    private String bindingEventHandlerClass = "flash.events.EventDispatcher";

    public String getBindingEventHandlerClass()
    {
        return bindingEventHandlerClass;
    }

    /**
     * The event handler class for generated binding code
     */
    @Config(advanced = true)
    public void setCompilerBindingEventHandlerClass(ConfigurationValue cv, String b)
    {
        bindingEventHandlerClass = b;
    }

    //
    // 'compiler.binding-event-handler-interface' option
    //

    private String bindingEventHandlerInterface = "flash.events.IEventDispatcher";

    public String getBindingEventHandlerInterface()
    {
        return bindingEventHandlerInterface;
    }

    /**
     * The event handler interface for generated binding code
     */
    @Config(advanced = true)
    public void setCompilerBindingEventHandlerInterface(ConfigurationValue cv, String b)
    {
        bindingEventHandlerInterface = b;
    }

    //
    // 'compiler.byte-array-embed-class' option
    //

    private String byteArrayEmbedClass = "mx.core.ByteArrayAsset";

    public String getByteArrayEmbedClass()
    {
        return byteArrayEmbedClass;
    }

    /**
     * The class for embedded byte arrays
     */
    @Config(advanced = true)
    public void setCompilerByteArrayEmbedClass(ConfigurationValue cv, String b)
    {
    	byteArrayEmbedClass = b;
    }

    //
    // 'compiler.states-class' option
    //

    private String statesClass = "mx.states.State";

    public String getStatesClass()
    {
        return statesClass;
    }

    /**
     * The class for states
     */
    @Config(advanced = true)
    public void setCompilerStatesClass(ConfigurationValue cv, String b)
    {
        statesClass = b;
    }

    //
    // 'compiler.states-instance-override-class' option
    //

    private String statesInstanceOverrideClass = "mx.states.AddItems";

    public String getStatesInstanceOverrideClass()
    {
        return statesInstanceOverrideClass;
    }

    /**
     * The class for state-dependent instances
     */
    @Config(advanced = true)
    public void setCompilerStatesInstanceOverrideClass(ConfigurationValue cv, String b)
    {
        statesInstanceOverrideClass = b;
    }

    //
    // 'compiler.states-property-override-class' option
    //

    private String statesPropertyOverrideClass = "mx.states.SetProperty";

    public String getStatesPropertyOverrideClass()
    {
        return statesPropertyOverrideClass;
    }

    /**
     * The class for state-dependent properties
     */
    @Config(advanced = true)
    public void setCompilerStatesPropertyOverrideClass(ConfigurationValue cv, String b)
    {
        statesPropertyOverrideClass = b;
    }

    //
    // 'compiler.states-event-override-class' option
    //

    private String statesEventOverrideClass = "mx.states.SetEventHandler";

    public String getStatesEventOverrideClass()
    {
        return statesEventOverrideClass;
    }

    /**
     * The class for state-dependent events
     */
    @Config(advanced = true)
    public void setCompilerStatesEventOverrideClass(ConfigurationValue cv, String b)
    {
        statesEventOverrideClass = b;
    }

    //
    // 'compiler.states-style-override-class' option
    //

    private String statesStyleOverrideClass = "mx.states.SetStyle";

    public String getStatesStyleOverrideClass()
    {
        return statesStyleOverrideClass;
    }

    /**
     * The class for state-dependent styles
     */
    @Config(advanced = true)
    public void setCompilerStatesStyleOverrideClass(ConfigurationValue cv, String b)
    {
        statesStyleOverrideClass = b;
    }

    //
    // 'compiler.proxy-base-class' option
    //

    private String proxyBaseClass = "org.apache.flex.utils.Proxy";

    public String getProxyBaseClass()
    {
        return proxyBaseClass;
    }

    /**
     * The class for proxy code generation
     */
    @Config(advanced = true)
    public void setCompilerProxyBaseClass(ConfigurationValue cv, String b)
    {
        proxyBaseClass = b;
    }

    //
    // 'compiler.component-factory-class' option
    //

    private String componentFactoryClass = "mx.core.ClassFactory";

    public String getComponentFactoryClass()
    {
        return componentFactoryClass;
    }

    /**
     * The class for inline component factories
     */
    @Config(advanced = true)
    public void setCompilerComponentFactoryClass(ConfigurationValue cv, String b)
    {
        componentFactoryClass = b;
    }

    //
    // 'compiler.component-factory-interface' option
    //

    private String componentFactoryInterface = "mx.core.IFactory";

    public String getComponentFactoryInterface()
    {
        return componentFactoryInterface;
    }

    /**
     * The interface for inline component factories
     */
    @Config(advanced = true)
    public void setCompilerComponentFactoryInterface(ConfigurationValue cv, String b)
    {
        componentFactoryInterface = b;
    }

    /**
     * Syntax:<br/>
     * <code>-define=&lt;name&gt;,&lt;value&gt;</code> where name is <code>NAMESPACE::name</code> and value is a legal
     * definition value (e.g. <code>true</code> or <code>1</code> or <code>!CONFIG::debugging</code>)
     *
     * Example: <code>-define=CONFIG::debugging,true</code>
     *
     * In <code>flex-config.xml</code>:<br/>
     * 
     * <pre>
     * <flex-config>
     *    <compiler>
     *       <define>
     *          <name>CONFIG::debugging</name>
     *          <value>true</value>
     *       </define>
     *       ...
     *    </compile>
     * </flex-config>
     * </pre>
     *
     * Values:<br/>
     * Values are ActionScript expressions that must coerce and evaluate to constants at compile-time. Effectively, they
     * are replaced in AS code, verbatim, so <code>-define=TEST::oneGreaterTwo,"1>2"</code> will getCompiler coerced and
     * evaluated, at compile-time, to <code>false</code>.
     *
     * It is good practice to wrap values with double-quotes, so that MXMLC correctly parses them as a single argument:
     * <br/>
     * <code>-define=TEST::oneShiftRightTwo,"1 >> 2"</code>
     *
     * Values may contain compile-time constants and other configuration values:<br/>
     * <code>-define=CONFIG::bool2,false -define=CONFIG::and1,"CONFIG::bool2 && false" TestApp.mxml</code>
     *
     * String values on the command-line <i>must</i> be surrounded by double-quotes, and either escape-quoted (
     * <code>"\"foo\""</code> or <code>"\'foo\'"</code>) or single-quoted (<code>"'foo'"</code>).
     *
     * String values in configuration files need only be single- or double- quoted:<br/>
     * 
     * <pre>
     * <flex-config>
     *    <compiler>
     *       <define>
     *          <name>NAMES::Organization</name>
     *          <value>'Apache Software Foundation'</value>
     *       </define>
     *       <define>
     *          <name>NAMES::Application</name>
     *          <value>"Flex 4.8.0"</value>
     *       </define>
     *       ...
     *    </compile>
     * </flex-config>
     * </pre>
     *
     * Empty strings <i>must</i> be passed as <code>"''"</code> on the command-line, and <code>''</code> or
     * <code>""</code> in configuration files.
     * 
     * Finally, if you have existing definitions in a configuration file, and you would like to add to them with the
     * command-line (let's say most of your build setCompilertings are in the configuration, and that you are adding one
     * temporarily using the command-line), you use the following syntax: <code>-define+=TEST::temporary,false</code>
     * (noting the plus sign)
     * 
     * Note that definitions can be overridden/redefined if you use the append ("+=") syntax (on the commandline or in a
     * user config file, for instance) with the same namespace and name, and a new value.
     * 
     * Definitions cannot be removed/undefined. You can undefine ALL existing definitions from (e.g. from
     * flex-config.xml) if you do not use append syntax ("=" or append="false").
     * 
     * IMPORTANT FOR FLEXBUILDER If you are using "Additional commandline arguments" to "-define", don't use the
     * following syntax though I suggest it above: -define+=CONFIG::foo,"'value'" The trouble is that FB parses the
     * double quotes incorrectly as <"'value'> -- the trailing double-quote is dropped. The solution is to avoid inner
     * double-quotes and put them around the whole expression: -define+="CONFIG::foo,'value'"
     */
    private Map<String, String> configVars;

    /**
     * @return A list of ConfigVars
     */

    public Map<String, String> getCompilerDefine()
    {
        return configVars;
    }

    @Config(advanced = true, allowMultiple = true)
    @Arguments({ "name", "value" })
    public void setCompilerDefine(ConfigurationValue cv, String name, String value) throws ConfigurationException
    {
        if (configVars == null)
            configVars = new LinkedHashMap<String, String>();

        configVars.put(name, value);
    }

    //
    // 'compiler.conservative' option (hidden)
    //

    private boolean useConservativeAlgorithm = false;

    public boolean useConservativeAlgorithm()
    {
        return useConservativeAlgorithm;
    }

    @Config(advanced = true, hidden = true)
    @Mapping({ "compiler", "conservative" })
    public void setCompilerConservative(ConfigurationValue cv, boolean c)
    {
        useConservativeAlgorithm = c;
    }

    //
    // 'compiler.context-root' option
    //

    private String contextRoot = null;

    public String getCompilerContextRoot()
    {
        return contextRoot;
    }

    /**
     * "Context root" is used to resolve {context.root} tokens in services configuration files to improve portability.
     */
    @Config
    @Mapping({ "compiler", "context-root" })
    @Arguments("context-path")
    @FlexOnly
    public void setCompilerContextRoot(ConfigurationValue cv, String contextRoot)
    {
        this.contextRoot = contextRoot;
    }

    //
    // 'compiler.debug' option
    //

    private boolean generateDebugTags = false;

    public boolean isDebuggingEnabled()
    {
        return generateDebugTags;
    }

    protected void setDebug(boolean value)
    {
        generateDebugTags = value;
    }

    @Config
    @Mapping({ "compiler", "debug" })
    public void setCompilerDebug(ConfigurationValue cv, boolean generateDebugTags)
    {
        this.generateDebugTags = generateDebugTags;
    }

    //
    // 'compiler.defaults-css-url' option
    //

    /**
     * Location of defaults stylesheet.
     */
    private String defaultsCssUrl;

    public String getCompilerDefaultsCssUrl()
    {
        return defaultsCssUrl;
    }

    /**
     * Defines the location of the default style sheet. Setting this option overrides the implicit use of the
     * defaults.css style sheet in the framework.swc file.
     */
    @Config(advanced = true)
    @Mapping({ "compiler", "defaults-css-url" })
    @FlexOnly
    public void setCompilerDefaultsCssUrl(ConfigurationValue cv, String defaultsCssUrlPath) throws CannotOpen
    {
        defaultsCssUrl = resolvePathStrict(defaultsCssUrlPath, cv);
    }

    //
    // 'compiler.doc' option (hidden)
    //

    private boolean doc = false;

    public boolean getCompilerDoc()
    {
        return this.doc;
    }

    @Config(advanced = true, hidden = true)
    @Mapping({ "compiler", "doc" })
    public void setCompilerDoc(ConfigurationValue cv, boolean doc)
    {
        this.doc = doc;
    }

    //
    // 'compiler.external-library-path' option
    //

    private final List<String> externalLibraryPath = new ArrayList<String>();

    public List<String> getCompilerExternalLibraryPath()
    {
        return externalLibraryPath;
    }

    private boolean compilingForAIR = false;

    /**
     * @return True if AIR libraries are included in the {@code external-library-path}.
     */
    public boolean getCompilingForAIR()
    {
        return compilingForAIR;
    }

    @Config(allowMultiple = true, isPath = true)
    @Mapping({ "compiler", "external-library-path" })
    @Arguments(Arguments.PATH_ELEMENT)
    @SoftPrerequisites({ "target-player", "exclude-native-js-libraries" })
    @InfiniteArguments
    public void setCompilerExternalLibraryPath(ConfigurationValue cv, String[] pathlist) throws ConfigurationException
    {
        pathlist = removeNativeJSLibrariesIfNeeded(pathlist);

        final ImmutableList<String> pathElements = ImmutableList.copyOf(pathlist);
        final ImmutableList<String> resolvedPaths = expandTokens(pathElements, locales, cv,
                !reportMissingCompilerLibraries);
        externalLibraryPath.addAll(resolvedPaths);

        // TODO: Review usages of "compilingForAIR", because only looking at path elements
        // on library path isn't enough. There might be a folder on the library path that
        // contains AIR libraries.
        compilingForAIR = containsAIRLibraries(pathElements);
    }

    /**
     * Returns true if there's AIR libraries on the library paths.
     * 
     * @param libraryPaths Library paths.
     * @return True if there's AIR libraries on the library paths.
     */
    private static boolean containsAIRLibraries(final ImmutableList<String> libraryPaths)
    {
        for (final String path : libraryPaths)
        {
            if (path.equals(SWC_AIRGLOBAL) || path.endsWith("/" + SWC_AIRGLOBAL) || path.endsWith("\\" + SWC_AIRGLOBAL))
            {
                return true;
            }
        }
        return false;
    }

    //
    // 'compiler.generated-directory' option
    // This can only be configured using getter and setter.
    //

    private String generatedDir = null;

    public String getCompilerGeneratedDirectory()
    {
        return generatedDir;
    }

    public void setCompilerGeneratedDirectory(String generatedDir)
    {
        this.generatedDir = generatedDir;
    }

    //
    // 'compiler.headless-server' option
    //

    private boolean headlessServer;

    public boolean isHeadlessServer()
    {
        return headlessServer;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "headless-server" })
    @FlexOnly
    public void setCompilerHeadlessServer(ConfigurationValue cv, boolean headlessServer)
    {
        this.headlessServer = headlessServer;
    }

    //
    // 'compiler.include-libraries' option
    //

    private final List<String> includeLibraries = new ArrayList<String>();

    public List<String> getCompilerIncludeLibraries()
    {
        return includeLibraries;
    }

    /**
     * Links all classes inside a SWC file to the resulting application SWF file, regardless of whether or not they are
     * used.
     * <p>
     * Contrast this option with the library-path option that includes only those classes that are referenced at compile
     * time.
     * <p>
     * To link one or more classes whether or not they are used and not an entire SWC file, use the includes option.
     * <p>
     * This option is commonly used to specify resource bundles.
     */
    @Config(allowMultiple = true, isPath = true)
    @Mapping({ "compiler", "include-libraries" })
    @Arguments("library")
    @InfiniteArguments
    public void setCompilerIncludeLibraries(ConfigurationValue cv, String[] pathlist) throws CannotOpen
    {
        final ImmutableList<String> resolvedPaths = expandTokens(Arrays.asList(pathlist), locales, cv,
                !reportMissingCompilerLibraries);
        includeLibraries.addAll(resolvedPaths);
    }

    //
    // 'compiler.incremental' option
    //

    @Config(removed = true)
    @Mapping({ "compiler", "incremental" })
    public void setCompilerIncremental(ConfigurationValue cv, boolean b)
    {
    }

    //
    // 'compiler.keep-all-type-selectors' option.  

    /**
     * This was initially used by Flex Builder when building design view, but they no longer use it.
     */
    private boolean keepAllTypeSelectors;

    public boolean keepAllTypeSelectors()
    {
        return keepAllTypeSelectors;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "keep-all-type-selectors" })
    @FlexOnly
    public void setCompilerKeepAllTypeSelectors(ConfigurationValue cv, boolean keepAllTypeSelectors)
    {
        this.keepAllTypeSelectors = keepAllTypeSelectors;
    }

    //
    // 'compiler.keep-as3-metadata' option
    //

    private Set<String> as3metadata = null;

    public Set<String> getCompilerKeepAs3Metadata()
    {
        return as3metadata == null ? Collections.<String> emptySet() : as3metadata;
    }

    @Config(advanced = true, allowMultiple = true)
    @Mapping({ "compiler", "keep-as3-metadata" })
    @Arguments("name")
    @InfiniteArguments
    public void setCompilerKeepAs3Metadata(ConfigurationValue cv, List<String> values)
    {
        if (as3metadata == null)
            as3metadata = new HashSet<String>();
        as3metadata.addAll(values);
    }

    //
    // 'compiler.keep-generated-actionscript' option (removed)
    //

    @Config(removed = true)
    @Mapping({ "compiler", "keep-generated-actionscript" })
    public void setCompilerKeepGeneratedActionscript(ConfigurationValue cv, boolean keep)
    {
    }

    //
    // 'compiler.keep-generated-signatures' option (removed)
    //

    @Config(removed = true)
    @Mapping({ "compiler", "keep-generated-signatures" })
    public void setCompilerKeepGeneratedSignatures(ConfigurationValue cv, boolean keep)
    {
    }

    //
    // 'compiler.enable-runtime-design-layers' option
    //

    private boolean enableRuntimeDesignLayers = true;

    public boolean getEnableRuntimeDesignLayers()
    {
        return enableRuntimeDesignLayers;
    }

    @Config
    @Mapping({ "compiler", "enable-runtime-design-layers" })
    @FlexOnly
    public void setCompilerEnableRuntimeDesignLayers(ConfigurationValue cv, boolean enable)
    {
        enableRuntimeDesignLayers = enable;
    }

    //
    // 'compiler.enable-swc-version-filtering' option
    //

    private boolean enableSwcVersionFiltering = true;

    public boolean getEnableSwcVersionFiltering()
    {
        return enableSwcVersionFiltering;
    }

    @Config(advanced = true, hidden = true)
    @Mapping({ "compiler", "enable-swc-version-filtering" })
    public void setCompilerEnableSwcVersionFiltering(ConfigurationValue cv, boolean enable)
    {
        this.enableSwcVersionFiltering = enable;
    }

    //
    // 'compiler.library-path' option
    //

    private final List<String> libraryPath = new ArrayList<String>();
    private boolean reportMissingCompilerLibraries = true;

    /**
     * Sets whether to report missing libraries in the configuration. If this is false any missing libraries will not be
     * warned about, and the filename will also be added to list of libraries in the project when it doesn't exist. If
     * reportMissingCompilerLibraries is true, any missing libraries will not be added to the project.
     * 
     * @param reportMissingCompilerLibraries true to report missing libraries
     */
    public void setReportMissingCompilerLibraries(boolean reportMissingCompilerLibraries)
    {
        this.reportMissingCompilerLibraries = reportMissingCompilerLibraries;
    }

    public List<String> getCompilerLibraryPath()
    {
        return libraryPath;
    }

    /**
     * Links SWC files to the resulting application SWF file. The compiler only links in those classes for the SWC file
     * that are required. You can specify a directory or individual SWC files.
     */
    @Config(allowMultiple = true, isPath = true)
    @Mapping({ "compiler", "library-path" })
    @Arguments(Arguments.PATH_ELEMENT)
    @InfiniteArguments
    @SoftPrerequisites({ "locale", "target-player", "exclude-native-js-libraries" })
    public void setCompilerLibraryPath(ConfigurationValue cv, String[] pathlist) throws CannotOpen
    {
        pathlist = removeNativeJSLibrariesIfNeeded(pathlist);
        final ImmutableList<String> resolvedPaths = expandTokens(Arrays.asList(pathlist), locales, cv,
                !reportMissingCompilerLibraries);
        libraryPath.addAll(resolvedPaths);
    }

    //
    // 'compiler.locale' option
    //

    private final List<String> locales = new ArrayList<String>();

    public List<String> getCompilerLocales()
    {
        return locales;
    }

    /**
     * Specifies one or more locales to be compiled into the SWF file. If you do not specify a locale, then the compiler
     * uses the default locale from the flex-config.xml file. The default value is en_US. You can append additional
     * locales to the default locale by using the += operator. If you remove the default locale from the flex-config.xml
     * file, and do not specify one on the command line, then the compiler will use the machine's locale.
     */
    @Config(allowMultiple = true)
    @Mapping({ "compiler", "locale" })
    @Arguments("locale-element")
    @InfiniteArguments
    @FlexOnly
    public void setCompilerLocale(ConfigurationValue cv, String[] newLocales)
    {
        locales.addAll(Arrays.asList(newLocales));
    }

    //
    // 'compiler.metadata-export' option (incomplete)
    //

    private boolean metadataExport;

    public boolean metadataExport()
    {
        return metadataExport;
    }

    // metadataExport does not have the normal configuration setCompilerter because it is not
    // a normal configuration value but rather something setCompiler by the compiler
    public void setCompilerMetadataExport(boolean metadataExport)
    {
        this.metadataExport = metadataExport;
    }

    //
    // 'compiler.mxml.children-as-data' option
    //
    private Boolean childrenAsData = false;

    public Boolean getCompilerMxmlChildrenAsData()
    {
        return childrenAsData;
    }

    @Config
    @Mapping({ "compiler", "mxml", "children-as-data" })
    @FlexOnly
    public void setCompilerMxmlChildrenAsData(ConfigurationValue cv, Boolean asData) throws ConfigurationException
    {
        childrenAsData = asData;
    }

    //
    // 'compiler.info.flex' option
    // used to suppress some of info() fields
    //
    private Boolean infoFlex = true;

    public Boolean getCompilerInfoFlex()
    {
        return infoFlex;
    }

    @Config
    @Mapping({ "compiler", "info", "flex" })
    @FlexOnly
    public void setCompilerInfoFlex(ConfigurationValue cv, Boolean asData) throws ConfigurationException
    {
    	infoFlex = asData;
    }

    //
    // 'compiler.allow-subclass-overrides' option
    //
    private Boolean allowSubclassOverrides = false;

    public Boolean getCompilerAllowSubclassOverrides()
    {
        return allowSubclassOverrides;
    }

    @Config
    @Mapping({ "compiler", "allow-subclass-overrides" })
    @FlexOnly
    public void setCompilerAllowSubclassOverrides(ConfigurationValue cv, Boolean allow) throws ConfigurationException
    {
        allowSubclassOverrides = allow;
    }

    //
    // 'compiler.mxml.implicitImports' option
    //
    private String[] implicitImports;

    public String[] getCompilerMxmlImplicitImports()
    {
        return implicitImports;
    }

    @Config(allowMultiple = true)
    @Mapping({ "compiler", "mxml", "imports" })
    @Arguments("implicit-import")
    @InfiniteArguments
    @FlexOnly
    public void setCompilerMxmlImplicitImports(ConfigurationValue cv, String[] imports) throws ConfigurationException
    {
        implicitImports = imports;
    }

    //
    // 'compiler.mxml.compatibility-version' option
    //

    public String getCompilerCompatibilityVersionString()
    {
        return getCompilerMxmlCompatibilityVersionString();
    }

    public int getCompilerCompatibilityVersion()
    {
        return getCompilerMxmlCompatibilityVersion();
    }

    //
    // 'compiler.mxml.minimum-supported-version' option
    //

    public String getCompilerMinimumSupportedVersionString()
    {
        return getCompilerMxmlMinimumSupportedVersionString();
    }

    public int getCompilerMinimumSupportedVersion()
    {
        return getCompilerMxmlMinimumSupportedVersion();
    }

    @Config
    @Mapping({ "compiler", "minimum-supported-version" })
    @FlexOnly
    public void setCompilerMinimumSupportedVersion(ConfigurationValue cv, String version) throws ConfigurationException
    {
        setCompilerMxmlMinimumSupportedVersion(cv, version);
    }

    //
    // 'qualified-type-selectors' option
    //
    @Config(advanced = true, removed = true)
    @Mapping({ "compiler", "mxml", "qualified-type-selectors" })
    public void setCompilerMxmlQualifiedTypeSelectors(ConfigurationValue cv, boolean b)
    {
    }

    //
    // 'compiler.omit-trace-statements' option
    //

    private boolean omitTraceStatements = true;

    public boolean omitTraceStatements()
    {
        return omitTraceStatements;
    }

    @Config
    @Mapping({ "compiler", "omit-trace-statements" })
    public void setCompilerOmitTraceStatements(ConfigurationValue cv, boolean b)
    {
        omitTraceStatements = b;
    }

    //
    // 'compiler.optimize' option
    //

    private boolean optimize = false;

    public boolean optimize()
    {
        return optimize;
    }

    public boolean getCompilerOptimize()
    {
        return optimize;
    }

    @Config
    @Mapping({ "compiler", "optimize" })
    public void setCompilerOptimize(ConfigurationValue cv, boolean b)
    {
        optimize = b;
    }

    //
    // 'compiler.preloader' option
    //

    private String preloader = null;

    /**
     * 
     * @return Returns the preloader class configured by the user. If the user did not configure a preloader, the
     *         "mx.preloader.DownloaderProgressBar" preloader will be returned if the compatibility version is less than
     *         4.0. Otherwise the "mx.preloaders.SparkDownloadProgressBar" preloader will be returned.
     */
    public String getPreloader()
    {
        if (preloader != null)
            return preloader;

        if (getCompilerMxmlCompatibilityVersion() < MXML_VERSION_4_0)
            return IMXMLTypeConstants.DownloadProgressBar;
        else
            return IMXMLTypeConstants.SparkDownloadProgressBar;
    }

    public String getCompilerPreloader()
    {
        return preloader;
    }

    @Config
    @Mapping({ "compiler", "preloader" })
    @FlexOnly
    public void setCompilerPreloader(ConfigurationValue cv, String value)
    {
        preloader = value;
    }

    //
    // 'compiler.services' option
    //

    private File servicesConfigFile;

    //protected ServicesDependencies servicesDependencies;

    public File getCompilerServices()
    {
        return servicesConfigFile;
    }

    /**
     * Used by the compiler to record the client dependencies from the Flex Data Services configuration file.
     */
    /*
     * public ServicesDependencies getCompilerServicesDependencies() { if
     * (servicesDependencies == null && servicesConfigFile != null) { String
     * servicesPath = servicesConfigFile.getName(); servicesDependencies = new
     * ServicesDependencies(servicesPath, null, getCompilerContextRoot()); }
     * return servicesDependencies; } public void
     * setCompilerServicesDependencies(ServicesDependencies deps) {
     * servicesDependencies = deps; }
     */

    @Config
    @Mapping({ "compiler", "services" })
    @Arguments("filename")
    @FlexOnly
    public void setCompilerServices(ConfigurationValue cv, String servicesPath) throws ConfigurationException
    {
        try
        {
            servicesConfigFile = new File(resolvePathStrict(servicesPath, cv));
        }
        catch (Exception e)
        {
            throw new ConfigurationException.CannotOpen(servicesPath, cv.getVar(), cv.getSource(), cv.getLine());
        }
    }

    //
    // 'compiler.show-actionscript-warnings' option
    //

    /**
     * Enable asc -warnings
     */
    private boolean ascWarnings;

    public boolean warnings()
    {
        return this.ascWarnings;
    }

    @Config
    @Mapping({ "compiler", "show-actionscript-warnings" })
    public void setCompilerShowActionscriptWarnings(ConfigurationValue cv, boolean ascWarnings)
    {
        this.ascWarnings = ascWarnings;
    }

    //
    // 'compiler.show-binding-warnings' option
    //

    /**
     * Controls whether binding warnings are displayed.
     */
    private boolean showBindingWarnings = true;

    public boolean showBindingWarnings()
    {
        return showBindingWarnings;
    }

    @Config
    @Mapping({ "compiler", "show-binding-warnings" })
    public void setCompilerShowBindingWarnings(ConfigurationValue cv, boolean show)
    {
        this.showBindingWarnings = show;
    }

    @Config
    @Mapping({ "compiler", "show-multiple-definition-warnings" })
    public void setCompilerShowMultipleDefinitionWarnings(ConfigurationValue cv, boolean show)
    {
        this.showMultipleDefinitionWarnings = show;
    }
    //
    // 'compiler.show-dependency-warnings' option (hidden)
    //

    private boolean showDependencyWarnings = false;

    public boolean showDependencyWarnings()
    {
        return showDependencyWarnings;
    }

    @Config(advanced = true, hidden = true)
    @Mapping({ "compiler", "show-dependency-warnings" })
    public void setCompilerShowDependencyWarnings(ConfigurationValue cv, boolean show)
    {
        this.showDependencyWarnings = show;
    }

    //
    // 'compiler.report-invalid-styles-as-warnings' option
    //

    /**
     * Controls whether invalid styles are report as errors or warnings.
     */
    private boolean reportInvalidStylesAsWarnings = false;

    /**
     * Get value of {@code compiler.report-invalid-styles-as-warnings} option value.
     * <p>
     * <h2>What's "invalid styles"?</h2> The term "invalid style" only applies to MXML style specifier (a.k.a. inline
     * style). If a style of a component is defined with "theme" attribute, the style is only effective with such theme.
     * If a theme-specific style is used in an application who doesn't use the required theme, the style is considered
     * invalid.
     * <p>
     * For example, style "fooStyle" is defined to used only with theme called "fooTheme":
     * 
     * <pre>
     * [Style(name="fooStyle", type="uint", format="Color", inherit="yes", theme="fooTheme")]
     * public class MyComponent extends UIComponent
     * </pre>
     * 
     * If "fooTheme" isn't used by the current application, the following style specifier is considered "invalid styles"
     * . <br>
     * {@code <local:MyComponent fooStyle="white" />}
     * 
     * @return True if invalid styles are reported as warnings instead of errors.
     */
    public boolean getReportInvalidStylesAsWarnings()
    {
        return reportInvalidStylesAsWarnings;
    }

    @Config
    @Mapping({ "compiler", "report-invalid-styles-as-warnings" })
    @FlexOnly
    public void setCompilerReportInvalidStylesAsWarnings(ConfigurationValue cv, boolean show)
    {
        this.reportInvalidStylesAsWarnings = show;
    }

    //
    // 'compiler.report-missing-required-skin-parts-as-warnings' option
    //

    private boolean reportMissingRequiredSkinPartsAsWarnings = false;

    /**
     * Allow the user to configure whether it should be considered an error to not create a required skin part or if it
     * should just be a warning.
     */
    public boolean reportMissingRequiredSkinPartsAsWarnings()
    {
        return reportMissingRequiredSkinPartsAsWarnings;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "report-missing-required-skin-parts-as-warnings" })
    @FlexOnly
    public void setCompilerReportMissingRequiredSkinPartsAsWarnings(ConfigurationValue cv, boolean b)
    {
        reportMissingRequiredSkinPartsAsWarnings = b;
    }

    //
    // 'compiler.show-invalid-css-property-warnings' option
    //

    private boolean showInvalidCSSPropertyWarnings = true;

    /**
     * Controls whether warnings are displayed when styles, which don't apply to the current theme(s), are used in CSS.
     * <p>
     * See {@link #getReportInvalidStylesAsWarnings()} for definition of "invalid style".
     * <p>
     * This option applies to <i>invalid styles</i> in a {@code <fx:Style>} block.
     */
    public boolean getShowInvalidCSSPropertyWarnings()
    {
        return showInvalidCSSPropertyWarnings;
    }

    @Config
    @Mapping({ "compiler", "show-invalid-css-property-warnings" })
    @FlexOnly
    public void setShowInvalidCssPropertyWarnings(ConfigurationValue cv, boolean show)
    {
        this.showInvalidCSSPropertyWarnings = show;
    }

    //
    // 'compiler.show-deprecation-warnings' option
    //

    /**
     * Controls whether warnings are displayed when a deprecated API is used.
     */
    private boolean showDeprecationWarnings = false;

    public boolean showDeprecationWarnings()
    {
        return showDeprecationWarnings;
    }

    @Config(advanced = true, hidden = true)
    @Mapping({ "compiler", "show-deprecation-warnings" })
    public void setCompilerShowDeprecationWarnings(ConfigurationValue cv, boolean show)
    {
        this.showDeprecationWarnings = show;
    }

    //
    // 'compiler.show-shadowed-device-font-warnings' option
    //
    @Config
    @Mapping({ "compiler", "show-shadowed-device-font-warnings" })
    @FlexOnly
    public void setCompilerShowShadowedDeviceFontWarnings(ConfigurationValue cv, boolean show)
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    //
    // 'compiler.show-unused-type-selector-warnings' option
    //

    private boolean showUnusedTypeSelectorWarnings = true;

    public boolean showUnusedTypeSelectorWarnings()
    {
        return showUnusedTypeSelectorWarnings;
    }

    //
    // 'compiler.show-multiple-definition-warnings' option
    //

    private boolean showMultipleDefinitionWarnings = true;

    public boolean showMultipleDefinitionWarnings()
    {
        return showMultipleDefinitionWarnings;
    }

    @Config
    @Mapping({ "compiler", "show-unused-type-selector-warnings" })
    @FlexOnly
    public void setCompilerShowUnusedTypeSelectorWarnings(ConfigurationValue cv, boolean show)
    {
        this.showUnusedTypeSelectorWarnings = show;
    }

    //
    // 'compiler.source-path' option
    //

    /**
     * Source path elements searched for ActionScript class files, possibly containing a {locale} token.
     */
    private final List<String> unexpandedSourcePath = new ArrayList<String>();

    /**
     * Directories searched for ActionScript class files. The specified compiler.source-path can have path elements
     * which contain a special {locale} token. If you compile for a single locale, this token is replaced by the
     * specified locale. If you compile for multiple locales, any path element with the {locale} token is ignored,
     * because we do not support compiling, for example, both en_US and ja_JP versions of MyComponent into the same SWF.
     * A path element with {locale} is similarly ignored if you compile for no locale.
     */
    private final List<String> sourcePath = new ArrayList<String>();

    /** Context object for "source-path" option. */
    private ConfigurationValue sourcePathContext = null;

    public List<String> getCompilerSourcePath()
    {
        return sourcePath;
    }

    /**
     * Get the source paths computed from the given {@code locale}. The locale must be included in the configuration.
     * 
     * @param locale Locale name.
     * @return Source paths computed from the given {@code locale}.
     * @throws CannotOpen Error resolving one of the paths from this locale.
     */
    public ImmutableList<String> getCompilerResourceBundlePathForLocale(String locale) throws CannotOpen
    {
        assert locales.contains(locale) : "Locale is not configured: " + locale;
        return expandTokens(unexpandedSourcePath, ImmutableSet.of(locale), sourcePathContext,
                !reportMissingCompilerLibraries);
    }

    @Config(allowMultiple = true)
    @Arguments(Arguments.PATH_ELEMENT)
    @SoftPrerequisites("locale")
    public void setCompilerSourcePath(ConfigurationValue cv, String[] paths) throws ConfigurationException
    {
        final List<String> pathList = Arrays.asList(paths);
        unexpandedSourcePath.addAll(pathList);

        final ImmutableList<String> resolvedSourcePaths = expandTokens(pathList, locales, cv);
        assertThatAllPathsAreDirectories(resolvedSourcePaths, cv);
        sourcePath.addAll(resolvedSourcePaths);

        sourcePathContext = cv;
    }

    /**
     * Check that all paths in the path list are directories.
     * 
     * @param paths A list of paths.
     * @param cv Context.
     * @throws NotDirectory Path is not a directory exception.
     */
    public static void assertThatAllPathsAreDirectories(final List<String> paths, final ConfigurationValue cv)
            throws NotDirectory
    {
        assert paths != null : "Expected path list.";
        assert cv != null : "Expected ConfigurationValue as context.";

        for (final String path : paths)
        {
            final File file = new File(path);
            if (!file.isDirectory())
                throw new NotDirectory(path, cv.getVar(), cv.getSource(), cv.getLine());
        }
    }

    public static ConfigurationInfo getCompilerSourcePathInfo()
    {
        return new ConfigurationInfo(-1, new String[] { "path-element" })
        {
            @Override
            public boolean allowMultiple()
            {
                return true;
            }

            @Override
            public boolean isPath()
            {
                return true;
            }
        };
    }

    //
    // 'compiler.strict' option
    //

    /**
     * Run the AS3 compiler in strict mode
     */
    private boolean strict;

    public boolean strict()
    {
        return this.strict;
    }

    @Config
    @Mapping({ "compiler", "strict" })
    public void setCompilerStrict(ConfigurationValue cv, boolean strict)
    {
        this.strict = strict;
    }

    //
    // 'compiler.suppress-warnings-in-incremental' option (incomplete)
    //

    // for Zorn
    //
    // When doing incremental compilation, the compiler doesn't recompile codes that are previously compiled with
    // warnings. It only outputs the warning messages so as to remind users of the warnings.
    //
    // The command-line tool and Zorn work differently in that Zorn keeps the warning logger while the commnad-line
    // tool, of course, can't keep the warning logger alive...
    //
    // Zorn needs this flag to tell the compiler not to output warnings again in incremental compilations because
    // it keeps its own log.
    private boolean suppressWarningsInIncremental = false;

    public boolean suppressWarningsInIncremental()
    {
        return suppressWarningsInIncremental;
    }

    public void setCompilerSuppressWarningsInIncremental(boolean b)
    {
        suppressWarningsInIncremental = b;
    }

    //
    // 'compiler.theme' option
    //

    private List<String> themeFiles = null;

    /**
     * Get normalized theme file paths. If a the compiler is in "Flex 3 compatibility" mode and only "Spark" theme is
     * used, it will be replaced with the legacy "Halo" theme.
     * 
     * @return A list of normalized paths to the theme files.
     */
    public List<String> getCompilerThemeFiles()
    {
        if (themeFiles == null)
            return EMPTY_STRING_LIST;

        final boolean isVersion3OrEarlier = getCompilerMxmlCompatibilityVersion() <= MXML_VERSION_3_0;
        final boolean hasOnlyOneThemeFile = themeFiles.size() == 1;
        if (isVersion3OrEarlier && hasOnlyOneThemeFile)
        {
            // Swap in the default Flex 3 theme of Halo.
            final String path = FilenameUtils.normalize(themeFiles.get(0), true);
            final String sparkPath = "/themes/Spark/spark.css";

            if (path.endsWith(sparkPath))
            {
                int index = path.indexOf(sparkPath);
                final String haloPath = path.substring(0, index) + "/themes/Halo/halo.swc";
                themeFiles.set(0, FilenameNormalization.normalize(haloPath));
            }
        }
        return themeFiles;
    }

    @Config(allowMultiple = true)
    @Mapping({ "compiler", "theme" })
    @Arguments("filename")
    @InfiniteArguments
    @FlexOnly
    public void setCompilerTheme(ConfigurationValue cv, List<String> paths) throws CannotOpen
    {
        // Use "resolvePathsStrict()" if invalid theme file can't be ignored.
        final ImmutableList<String> resolved = resolvePathsStrict(ImmutableList.copyOf(paths), cv);

        if (themeFiles == null)
            themeFiles = new ArrayList<String>();
        themeFiles.addAll(resolved);
    }

    //
    // 'compiler.defaults-css-files' option
    //

    private Deque<String> defaultsCSSFiles = new ArrayDeque<String>();

    /**
     * List of filenames of defaults style stylesheets (css only).
     * <p>
     * <b>For example:</b><br>
     * <code>-defaults-css-files=[A, B, C]</code><br>
     * Then, 'A' should have precedence over 'B', then 'C', then SWCs defaultsCssFiles should have the order: SWCS, C,
     * B, A
     * 
     * @see #setDefaultsCSSFiles
     */
    public Deque<String> getDefaultsCSSFiles()
    {
        return defaultsCSSFiles;
    }

    /**
     * Inserts CSS files into the output the same way that a per-SWC defaults.css file works, but without having to
     * re-archive the SWC file to test each change.
     * <p>
     * CSS files included in the output with this option have a higher precedence than default CSS files in existing
     * SWCs. For example, a CSS file included with this option overrides definitions in framework.swc's defaults.css
     * file, but it has the same overall precedence as other included CSS files inside the SWC file.
     * <p>
     * This option does not actually insert the CSS file into the SWC file; it simulates it. When you finish developing
     * the CSS file, you should rebuild the SWC file with the new integrated CSS file.
     * <p>
     * This option takes one or more files. The precedence for multiple CSS files included with this option is from
     * first to last.
     */
    @Config(allowMultiple = true, advanced = true)
    @Mapping({ "compiler", "defaults-css-files" })
    @Arguments("filename")
    @InfiniteArguments
    @FlexOnly
    public void setDefaultsCSSFiles(ConfigurationValue cv, List<String> paths) throws CannotOpen
    {
        final ImmutableList<String> resolved = resolvePathsStrict(ImmutableList.copyOf(paths), cv);
        for (final String path : resolved)
        {
            defaultsCSSFiles.addFirst(path);
        }
    }

    //
    // 'compiler.exclude-defaults-css-files' option
    //

    private Deque<String> excludeDefaultsCSSFiles = new ArrayDeque<String>();

    /**
     * List of filenames to exclude from list of defaults style stylesheets (css only).
     * For defaults.css files in a SWC, use HTML.swc:defaults.css where HTML is the
     * name of a SWC.
     * <p>
     * <b>For example:</b><br>
     * <code>-exclude-defaults-css-files=[A, B, C]</code><br>
     * Then, 'A' should have precedence over 'B', then 'C', then SWCs defaultsCssFiles should have the order: SWCS, C,
     * B, A
     * 
     * @see #setExcludeDefaultsCSSFiles
     */
    public Deque<String> getExcludeDefaultsCSSFiles()
    {
        return excludeDefaultsCSSFiles;
    }

    /**
     * Excludes CSS files from the output.
     * <p>
     * This option takes one or more files. The precedence for multiple CSS files included with this option is from
     * first to last.
     */
    @Config(allowMultiple = true, advanced = true)
    @Mapping({ "compiler", "exclude-defaults-css-files" })
    @Arguments("filename")
    @InfiniteArguments
    @FlexOnly
    public void setExcludeDefaultsCSSFiles(ConfigurationValue cv, List<String> paths) throws CannotOpen
    {
        final ImmutableList<String> resolved = resolvePathsStrict(ImmutableList.copyOf(paths), cv, true);
        for (final String path : resolved)
        {
            excludeDefaultsCSSFiles.addFirst(path);
        }
    }

    /**
     * Location of theme style stylesheets (css only, configured via themefiles above).
     */
    private List<IFileSpecification> themeCssFiles = new LinkedList<IFileSpecification>();

    public List<IFileSpecification> getCompilerThemeCssFiles()
    {
        return themeCssFiles;
    }

    public void addThemeCssFiles(List<IFileSpecification> files)
    {
        themeCssFiles.addAll(files);
    }

    //
    // 'compiler.use-resource-bundle-metadata' option
    //

    @Config(removed = true)
    @Mapping({ "compiler", "use-resource-bundle-metadata" })
    public void setCompilerUseResourceBundleMetadata(ConfigurationValue cv, boolean b)
    {
    }

    //
    // 'compiler.verbose-stacktraces' option
    //

    private boolean verboseStacktraces;

    // from as3 and mxml configuration interface
    public boolean debug()
    {
        // the debug() in as3 and mxml configuration maps to stacktraceLineNumbers
        return verboseStacktraces;
    }

    public boolean release() {
        return !verboseStacktraces;
    }

    @Config
    @Mapping({ "compiler", "verbose-stacktraces" })
    public void setCompilerVerboseStacktraces(ConfigurationValue cv, boolean verboseStacktraces)
    {
        if (generateDebugTags)
        {
            this.verboseStacktraces = true;
        }
        else
        {
            this.verboseStacktraces = verboseStacktraces;
        }
    }

    //
    // 'compiler.warn-array-tostring-changes' option
    //

    private boolean warn_array_tostring_changes = false;

    public boolean warn_array_tostring_changes()
    {
        return warn_array_tostring_changes;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-array-tostring-changes" })
    public void setCompilerWarnArrayTostringChanges(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_array_tostring_changes)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-assignment-within-conditional' option
    //

    private boolean warn_assignment_within_conditional = true;

    public boolean warn_assignment_within_conditional()
    {
        return warn_assignment_within_conditional;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-assignment-within-conditional" })
    public void setCompilerWarnAssignmentWithinConditional(ConfigurationValue cv, boolean b)
    {
        warn_assignment_within_conditional = b;
    }

    //
    // 'compiler.warn-bad-array-cast' option
    //

    private boolean warn_bad_array_cast = true;

    public boolean warn_bad_array_cast()
    {
        return warn_bad_array_cast;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-array-cast" })
    public void setCompilerWarnBadArrayCast(ConfigurationValue cv, boolean b)
    {
        warn_bad_array_cast = b;
    }

    //
    // 'compiler.warn-bad-bool-assignment' option
    //

    private boolean warn_bad_bool_assignment = true;

    public boolean warn_bad_bool_assignment()
    {
        return warn_bad_bool_assignment;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-bool-assignment" })
    public void setCompilerWarnBadBoolAssignment(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_bad_bool_assignment)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-bad-date-cast' option
    //

    private boolean warn_bad_date_cast = true;

    public boolean warn_bad_date_cast()
    {
        return warn_bad_date_cast;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-date-cast" })
    public void setCompilerWarnBadDateCast(ConfigurationValue cv, boolean b)
    {
        warn_bad_date_cast = b;
    }

    //
    // 'compiler.warn-bad-es3-type-method' option
    //

    private boolean warn_bad_es3_type_method = true;

    public boolean warn_bad_es3_type_method()
    {
        return warn_bad_es3_type_method;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-es3-type-method" })
    public void setCompilerWarnBadEs3TypeMethod(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_bad_es3_type_method)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-bad-es3-type-prop' option
    //

    private boolean warn_bad_es3_type_prop = true;

    public boolean warn_bad_es3_type_prop()
    {
        return warn_bad_es3_type_prop;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-es3-type-prop" })
    public void setCompilerWarnBadEs3TypeProp(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_bad_es3_type_prop)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-bad-nan-comparison' option
    //

    private boolean warn_bad_nan_comparison = true;

    public boolean warn_bad_nan_comparison()
    {
        return warn_bad_nan_comparison;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-nan-comparison" })
    public void setCompilerWarnBadNanComparison(ConfigurationValue cv, boolean b)
    {
        warn_bad_nan_comparison = b;
    }

    //
    // 'compiler.warn-bad-null-assignment' option
    //

    private boolean warn_bad_null_assignment = true;

    public boolean warn_bad_null_assignment()
    {
        return warn_bad_null_assignment;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-null-assignment" })
    public void setCompilerWarnBadNullAssignment(ConfigurationValue cv, boolean b)
    {
        warn_bad_null_assignment = b;
    }

    //
    // 'compiler.warn-bad-null-comparison' option
    //

    private boolean warn_bad_null_comparison = true;

    public boolean warn_bad_null_comparison()
    {
        return warn_bad_null_comparison;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-null-comparison" })
    public void setCompilerWarnBadNullComparison(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_bad_null_comparison)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-bad-undefined-comparison' option
    //

    private boolean warn_bad_undefined_comparison = true;

    public boolean warn_bad_undefined_comparison()
    {
        return warn_bad_undefined_comparison;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-bad-undefined-comparison" })
    public void setCompilerWarnBadUndefinedComparison(ConfigurationValue cv, boolean b)
    {
        warn_bad_undefined_comparison = b;
    }

    //
    // 'compiler.warn-boolean-constructor-with-no-args' option
    //

    private boolean warn_boolean_constructor_with_no_args = false;

    public boolean warn_boolean_constructor_with_no_args()
    {
        return warn_boolean_constructor_with_no_args;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-boolean-constructor-with-no-args" })
    public void setCompilerWarnBooleanConstructorWithNoArgs(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_boolean_constructor_with_no_args)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-changes-in-resolve' option
    //

    private boolean warn_changes_in_resolve = false;

    public boolean warn_changes_in_resolve()
    {
        return warn_changes_in_resolve;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-changes-in-resolve" })
    public void setCompilerWarnChangesInResolve(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_changes_in_resolve)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-class-is-sealed' option
    //

    private boolean warn_class_is_sealed = true;

    public boolean warn_class_is_sealed()
    {
        return warn_class_is_sealed;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-class-is-sealed" })
    public void setCompilerWarnClassIsSealed(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_class_is_sealed)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-const-not-initialized' option
    //

    private boolean warn_const_not_initialized = true;

    public boolean warn_const_not_initialized()
    {
        return warn_const_not_initialized;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-const-not-initialized" })
    public void setCompilerWarnConstNotInitialized(ConfigurationValue cv, boolean b)
    {
        warn_const_not_initialized = b;
    }

    //
    // 'compiler.warn-constructor-returns-value' option
    //

    private boolean warn_constructor_returns_value = false;

    public boolean warn_constructor_returns_value()
    {
        return warn_constructor_returns_value;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-constructor-returns-value" })
    public void setCompilerWarnConstructorReturnsValue(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_constructor_returns_value)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-deprecated-event-handler-error' option
    //

    private boolean warn_deprecated_event_handler_error = false;

    public boolean warn_deprecated_event_handler_error()
    {
        return warn_deprecated_event_handler_error;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-deprecated-event-handler-error" })
    public void setCompilerWarnDeprecatedEventHandlerError(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_deprecated_event_handler_error)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-deprecated-function-error' option
    //

    private boolean warn_deprecated_function_error = true;

    public boolean warn_deprecated_function_error()
    {
        return warn_deprecated_function_error;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-deprecated-function-error" })
    public void setCompilerWarnDeprecatedFunctionError(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_deprecated_function_error)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-deprecated-property-error' option
    //

    private boolean warn_deprecated_property_error = true;

    public boolean warn_deprecated_property_error()
    {
        return warn_deprecated_property_error;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-deprecated-property-error" })
    public void setCompilerWarnDeprecatedPropertyError(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_deprecated_property_error)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-duplicate-argument-names' option
    //

    private boolean warn_duplicate_argument_names = true;

    public boolean warn_duplicate_argument_names()
    {
        return warn_duplicate_argument_names;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-duplicate-argument-names" })
    public void setCompilerWarnDuplicateArgumentNames(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_duplicate_argument_names)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-duplicate-variable-def' option
    //

    private boolean warn_duplicate_variable_def = true;

    public boolean warn_duplicate_variable_def()
    {
        return warn_duplicate_variable_def;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-duplicate-variable-def" })
    public void csetCompilerWarnDuplicateVariableDef(ConfigurationValue cv, boolean b)
    {
        warn_duplicate_variable_def = b;
    }

    //
    // 'compiler.warn-for-var-in-changes' option
    //

    private boolean warn_for_var_in_changes = false;

    public boolean warn_for_var_in_changes()
    {
        return warn_for_var_in_changes;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-for-var-in-changes" })
    public void setCompilerWarnForVarInChanges(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_for_var_in_changes)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-import-hides-class' option
    //

    private boolean warn_import_hides_class = true;

    public boolean warn_import_hides_class()
    {
        return warn_import_hides_class;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-import-hides-class" })
    public void setCompilerWarnImportHidesClass(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_import_hides_class)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-instance-of-changes' option
    //

    private boolean warn_instance_of_changes = true;

    public boolean warn_instance_of_changes()
    {
        return warn_instance_of_changes;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-instance-of-changes" })
    public void setCompilerWarnInstanceOfChanges(ConfigurationValue cv, boolean b)
    {
        warn_instance_of_changes = b;
    }

    //
    // 'compiler.warn-internal-error' option
    //

    private boolean warn_internal_error = true;

    public boolean warn_internal_error()
    {
        return warn_internal_error;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-internal-error" })
    public void setCompilerWarnInternalError(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_internal_error)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-level-not-supported' option
    //

    private boolean warn_level_not_supported = true;

    public boolean warn_level_not_supported()
    {
        return warn_level_not_supported;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-level-not-supported" })
    public void setCompilerWarnLevelNotSupported(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_level_not_supported)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-missing-namespace-decl' option
    //

    private boolean warn_missing_namespace_decl = true;

    public boolean warn_missing_namespace_decl()
    {
        return warn_missing_namespace_decl;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-missing-namespace-decl" })
    public void setCompilerWarnMissingNamespaceDecl(ConfigurationValue cv, boolean b)
    {
        warn_missing_namespace_decl = b;
    }

    //
    // 'compiler.warn-negative-uint-literal' option
    //

    private boolean warn_negative_uint_literal = true;

    public boolean warn_negative_uint_literal()
    {
        return warn_negative_uint_literal;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-negative-uint-literal" })
    public void setCompilerWarnNegativeUintLiteral(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_negative_uint_literal)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-no-constructor' option
    //

    private boolean warn_no_constructor = false;

    public boolean warn_no_constructor()
    {
        return warn_no_constructor;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-no-constructor" })
    public void setCompilerWarnNoConstructor(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_no_constructor)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-no-explicit-super-call-in-constructor' option
    //

    private boolean warn_no_explicit_super_call_in_constructor = false;

    public boolean warn_no_explicit_super_call_in_constructor()
    {
        return warn_no_explicit_super_call_in_constructor;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-no-explicit-super-call-in-constructor" })
    public void setCompilerWarnNoExplicitSuperCallInConstructor(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_no_explicit_super_call_in_constructor)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-no-type-decl' option
    //

    private boolean warn_no_type_decl = true;

    public boolean warn_no_type_decl()
    {
        return warn_no_type_decl;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-no-type-decl" })
    public void setCompilerWarnNoTypeDecl(ConfigurationValue cv, boolean b)
    {
        warn_no_type_decl = b;
    }

    //
    // 'compiler.warn-number-from-string-changes' option
    //

    private boolean warn_number_from_string_changes = false;

    public boolean warn_number_from_string_changes()
    {
        return warn_number_from_string_changes;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-number-from-string-changes" })
    public void setCompilerWarnNumberFromStringChanges(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_number_from_string_changes)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-scoping-change-in-this' option
    //

    private boolean warn_scoping_change_in_this = false;

    public boolean warn_scoping_change_in_this()
    {
        return warn_scoping_change_in_this;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-scoping-change-in-this" })
    public void setCompilerWarnScopingChangeInThis(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_scoping_change_in_this)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-slow-text-field-addition' option
    //

    private boolean warn_slow_text_field_addition = true;

    public boolean warn_slow_text_field_addition()
    {
        return warn_slow_text_field_addition;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-slow-text-field-addition" })
    public void setCompilerWarnSlowTextFieldAddition(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_slow_text_field_addition)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-unlikely-function-value' option
    //

    private boolean warn_unlikely_function_value = true;

    public boolean warn_unlikely_function_value()
    {
        return warn_unlikely_function_value;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-unlikely-function-value" })
    public void setCompilerWarnUnlikelyFunctionValue(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_unlikely_function_value)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // 'compiler.warn-xml-class-has-changed' option
    //

    private boolean warn_xml_class_has_changed = false;

    public boolean warn_xml_class_has_changed()
    {
        return warn_xml_class_has_changed;
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "warn-xml-class-has-changed" })
    public void setCompilerWarnXmlClassHasChanged(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != warn_xml_class_has_changed)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // compiler.generate-abstract-syntax-tree
    //

    private boolean generateAbstractSyntaxTree = true;

    @Config(hidden = true)
    @Mapping({ "compiler", "generate-abstract-syntax-tree" })
    public void setCompilerGenerateAbstractSyntaxTree(ConfigurationValue cv, boolean b)
    {
        generateAbstractSyntaxTree = b;
    }

    public boolean getCompilerGenerateAbstractSyntaxTree()
    {
        return generateAbstractSyntaxTree;
    }

    //
    // 'compiler.isolateStyles' option
    //

    /**
     * Allow the user to decide if the compiled application/module should have its own style manager. Turn off isolate
     * styles for compatibility less than 4.0.
     */
    private boolean isolateStyles = true;

    public boolean getCompilerIsolateStyles()
    {
        return isolateStyles && (getCompilerCompatibilityVersion() >= MXML_VERSION_4_0);
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "isolate-styles" })
    @FlexOnly
    public void setCompilerIsolateStyles(ConfigurationValue cv, boolean isolateStyles)
    {
        this.isolateStyles = isolateStyles;
    }

    //
    // 'compiler.compress' option (default is true)
    //

    private boolean useCompression = true;

    @Config
    @Mapping({ "compiler", "compress" })
    public void setCompress(ConfigurationValue cv, boolean useCompression)
    {
        this.useCompression = useCompression;
    }

    /**
     * Setting {@code -compiler.compress=false} will force compiler not to compress the output SWF.
     */
    public boolean useCompression()
    {
        return this.useCompression;
    }

    // ATTENTION: Please set default values in DefaultsConfigurator.

    private static final String LOCALE_TOKEN = "{locale}";
    private static final String TARGET_PLAYER_MAJOR_VERSION_TOKEN = "{targetPlayerMajorVersion}";
    private static final String TARGET_PLAYER_MINOR_VERSION_TOKEN = "{targetPlayerMinorVersion}";
    private static final String TARGET_PLAYER_MAJOR_VERSION_TOKEN_REGEX_ESCAPED = Pattern.quote(
            TARGET_PLAYER_MAJOR_VERSION_TOKEN);
    private static final String TARGET_PLAYER_MINOR_VERSION_TOKEN_REGEX_ESCAPED = Pattern.quote(
            TARGET_PLAYER_MINOR_VERSION_TOKEN);

    // Special Case for Apache.  These are not currently exposed with command line options.
    public static final String PLAYERGLOBAL_HOME_TOKEN = "{playerglobalHome}";
    public static final String AIR_HOME_TOKEN = "{airHome}";
    public static final String FLEX_VERSION_TOKEN = "{flexVersion}";

    public static final String STRICT = "compiler.strict";
    public static final String AS3 = "compiler.as3";
    public static final String ES = "compiler.es";

    public ImmutableList<String> expandTokens(final Iterable<String> pathElements, final Iterable<String> locales,
            final ConfigurationValue configurationValue)
    {
        return expandTokens(pathElements, locales, configurationValue, false);
    }

    /**
     * All path-tokens get expanded from this method, as of now, {locale} and {targetPlayerMajorVersion} Replaces
     * instances of "{targetPlayerMajorVersion}" and "{targetPlayerMinorVersion}" with configured value. Expands the
     * {locale} token in a list of path elements for the source-path or library-path. The treatment of a path element
     * containing "{locale}" depends on whether we are processing a source-path or a library-path, and on whether we are
     * compiling for a single locale, multiple locales, or no locale:
     * 
     * <pre>
     * -source-path=foo,bar/{locale},baz -locale=en_US 
     * -> foo,bar/en_US,baz 
     * 
     * -source-path=foo,bar/{locale},baz -locale=en_US,ja_JP
     * -> foo,bar/en_US,bar/ja_JP,baz 
     * 
     * -source-path=foo,bar/{locale},baz -locale=
     * -> foo,baz 
     * 
     * -library-path=foo,bar/{locale},baz -locale=en_US 
     * -> foo,bar/en_US,baz 
     * 
     * -library-path=foo,bar/{locale},baz -locale=en_US,ja_JP
     * -> foo,bar/en_US,bar/ja_JP,baz 
     * 
     * -library-path=foo,bar/{locale},baz -locale=
     * -> foo,baz
     * </pre>
     * 
     * @param pathElements A list of unprocessed paths from configuration values.
     * @param locales A set of locales.
     * @param configurationValue Context.
     * @param returnMissingFiles controls whether or not files that do not exist are included in the list of expanded
     *        files. Pass true to include files that do not exist, false otherwise.
     * @return A list of normalized and resolved file paths.
     * @throws CannotOpen
     */
    protected ImmutableList<String> expandTokens(final Iterable<String> pathElements, final Iterable<String> locales,
            final ConfigurationValue configurationValue, final boolean returnMissingFiles)
    {
        assert pathElements != null : "Expected path list.";
        assert locales != null : "Expected locales.";
        assert configurationValue != null : "Expected ConfigurationValue as a context.";

        String targetPlayerMajorVersion = String.valueOf(getTargetPlayerMajorVersion());
        String targetPlayerMinorVersion = String.valueOf(getTargetPlayerMinorVersion());

        // Expand target player and locale tokens.
        final ImmutableList.Builder<String> resolvedPaths = new ImmutableList.Builder<String>();
        for (String pathElement : pathElements)
        {
            pathElement = expandRuntimeTokens(pathElement, configurationValue.getBuffer());
            String flexVersion =  getClass().getPackage().getImplementationVersion();
            if (flexVersion != null)
            {
                pathElement = pathElement.replace(FLEX_VERSION_TOKEN, flexVersion);
            }

            String playerExpandedPath = pathElement.replaceAll(TARGET_PLAYER_MAJOR_VERSION_TOKEN_REGEX_ESCAPED,
                    targetPlayerMajorVersion).replaceAll(TARGET_PLAYER_MINOR_VERSION_TOKEN_REGEX_ESCAPED,
                            targetPlayerMinorVersion);

            try
            {
                if (playerExpandedPath.contains(LOCALE_TOKEN))
                {
                    for (final String locale : locales)
                    {
                        final String expandedPath = playerExpandedPath.replace(LOCALE_TOKEN, locale);
                        String resolvedPath = resolvePathStrict(expandedPath, configurationValue);
                        resolvedPaths.add(resolvedPath);

                        //Add this to the locale dependent sources map
                        localeDependentSources.put(resolvedPath, locale);
                    }
                }
                else
                {
                    String resolvedPath = resolvePathStrict(playerExpandedPath, configurationValue, returnMissingFiles);
                    resolvedPaths.add(resolvedPath);
                }
            }
            catch (CannotOpen e)
            {
                // Making an exception here and catching this fatal error.
                // This is an exception because library paths come thru this
                // code path and we don't want to throw all of the libraries 
                // out because one of the paths is bad. We want to load as 
                // many libraries as we can an report the ones we couldn't load.
                configurationProblems.add(new ConfigurationProblem(e));
            }
        }

        return resolvedPaths.build();
    }

    /**
     * Replaces instances of {playerglobalHome} and {airHome}. Values can come from either ../env.properties (relative
     * to jar file) or environment variables. The property file values have precedence. The pairs are
     * env.PLAYERGLOBAL_HOME and PLAYERGLOBAL_HOME, and, env.AIR_HOME and AIR_HOME.
     */
    private String expandRuntimeTokens(String pathElement, ConfigurationBuffer buffer)
    {
        // Look at property file first, if it exists, and see if the particular property
        // is defined.  If not found, then look for the environment variable.
        // If there is neither leave the token in place since it is easier to
        // diagnose the problem with a token in the error message path then it is with
        // a "" in the path.
        Properties envProperties = loadEnvPropertyFile();

        String playerglobalHome = envProperties != null
                ? envProperties.getProperty("env.PLAYERGLOBAL_HOME", System.getenv("PLAYERGLOBAL_HOME"))
                : System.getenv("PLAYERGLOBAL_HOME");

        if (playerglobalHome == null)
            playerglobalHome = buffer.getToken("env.PLAYERGLOBAL_HOME");
        if (playerglobalHome == null)
            playerglobalHome = PLAYERGLOBAL_HOME_TOKEN;

        String airHome = envProperties != null ? envProperties.getProperty("env.AIR_HOME", System.getenv("AIR_HOME"))
                : System.getenv("AIR_HOME");

        if (airHome == null)
            airHome = buffer.getToken("env.AIR_HOME");
        if (airHome == null)
            airHome = AIR_HOME_TOKEN;

        pathElement = pathElement.replace(PLAYERGLOBAL_HOME_TOKEN, playerglobalHome);
        pathElement = pathElement.replace(AIR_HOME_TOKEN, airHome);

        return pathElement;
    }

    /**
     * Load the env.properties file from the classpath.
     * 
     * @return null if env.properties does not exist in classpath or could not be loaded
     */
    private Properties loadEnvPropertyFile()
    {
        Properties properties = null;
        InputStream in = null;

        try
        {
            in = getClass().getClassLoader().getResourceAsStream("env.properties");
            if (in == null)
            {
                try
                {
                    File f = new File("../env.properties");
                    in = new FileInputStream(f);
                    properties = new Properties();
                    properties.load(in);
                    in.close();
                    return properties;
                }
                catch (FileNotFoundException e)
                {
                    try
                    {
                        File f = new File("unittest.properties");
                        in = new FileInputStream(f);
                        properties = new Properties();
                        properties.load(in);
                        in.close();
                        properties.setProperty("env.PLAYERGLOBAL_HOME", properties.getProperty("PLAYERGLOBAL_HOME"));
                        properties.setProperty("env.AIR_HOME", properties.getProperty("AIR_HOME"));
                        properties.setProperty("env.PLAYERGLOBAL_VERSION", properties.getProperty("PLAYERGLOBAL_VERSION"));
                        return properties;
                    }
                    catch (FileNotFoundException e1)
                    {
                        return null;
                    }
                    catch (IOException e1)
                    {
                        return null;
                    }
                }
                catch (IOException e)
                {
                    return null;
                }
            }

            properties = new Properties();
            properties.load(in);
            in.close();
        }
        catch (Exception e)
        {
        }

        return properties;
    }

    private Map<String, String> localeDependentSources = new HashMap<String, String>();

    /**
     * Returns a map that stores locale dependent files. For each item in this map, key is the path of the resource and
     * value id the locale it belongs to.
     */
    public Map<String, String> getLocaleDependentSources()
    {
        return localeDependentSources;
    }

    /**
     * 
     * @param path A path to resolve.
     * @param cv Configuration context.
     * @return A single normalized resolved file. If the path could be expanded into more than one path, then use
     *         {@link resolvePathsStrict}
     * @throws CannotOpen
     */
    protected String resolvePathStrict(final String path, final ConfigurationValue cv) throws CannotOpen
    {
        return resolvePathStrict(path, cv, false);
    }

    /**
     * Resolve a single path. This is a more strict version of {@link #resolvePaths()} in that it throws
     * {@link CannotOpen} exception when a file path element can't be resolved.
     * 
     * @param path A path to resolve.
     * @param cv Configuration context.
     * @param returnMissingFiles Determines if the CannotOpen exception is thrown if a file does not exist. Pass true to
     *        disable exceptions and return files that do not exist. Pass false to throw exceptions.
     * @return A single normalized resolved file. If the path could be expanded into more than one path, then use
     *         {@link resolvePathsStrict}.
     * @throws CannotOpen error
     * @see #resolvePaths(ImmutableList, ConfigurationValue)
     */
    private String resolvePathStrict(final String path, final ConfigurationValue cv, final boolean returnMissingFiles)
            throws CannotOpen
    {
        ImmutableList<String> singletonPath = ImmutableList.of(path);
        ImmutableList<String> results = resolvePathsStrict(singletonPath, cv, returnMissingFiles);
        return results.get(0);
    }

    /**
     * Resolve a list of paths. This is a more strict version of {@link #resolvePaths()} in that it throws
     * {@link CannotOpen} exception when a file path element can't be resolved.
     * 
     * @param paths A list of paths to resolve.
     * @param cv Configuration context.
     * @return A list of normalized resolved file paths.
     * @throws CannotOpen error
     * @see #resolvePaths(ImmutableList, ConfigurationValue)
     */
    private ImmutableList<String> resolvePathsStrict(final ImmutableList<String> paths, final ConfigurationValue cv)
            throws CannotOpen
    {
        return resolvePathsStrict(paths, cv, false);
    }

    /**
     * Resolve a list of paths. This is a more strict version of {@link #resolvePaths()} in that it throws
     * {@link CannotOpen} exception when a file path element can't be resolved.
     * 
     * @param paths A list of paths to resolve.
     * @param cv Configuration context.
     * @param returnMissingFiles Determines if the CannotOpen exception is thrown if a file does not exist. Pass true to
     *        disable exceptions and return files that do not exist. Pass false to throw exceptions.
     * @return A list of normalized resolved file paths.
     * @throws CannotOpen error
     * @see #resolvePaths(ImmutableList, ConfigurationValue)
     */
    private ImmutableList<String> resolvePathsStrict(final ImmutableList<String> paths, final ConfigurationValue cv,
            final boolean returnMissingFiles) throws CannotOpen
    {
        assert paths != null : "Expected paths";
        assert cv != null : "Require ConfigurationValue as context.";

        final ImmutableList.Builder<String> resolvedPathsBuilder = new ImmutableList.Builder<String>();
        for (String processedPath : paths)
        {
            if (cv.getContext() != null)
            {
                boolean isAbsolute = new File(processedPath).isAbsolute();
                if (!isAbsolute)
                    processedPath = new File(cv.getContext(), processedPath).getAbsolutePath();
            }
            if (processedPath.contains("*"))
            {
                // if contains wild card, just prove the part before the wild card is valid
                int c = processedPath.lastIndexOf(File.separator, processedPath.indexOf("*"));
                if (c != -1)
                    processedPath = processedPath.substring(0, c);
            }
            if (!processedPath.contains(".swc:"))
            {
	            final File fileSpec = pathResolver.resolve(processedPath);
	            if (!returnMissingFiles && !fileSpec.exists())
	            {
	                throw new CannotOpen(FilenameNormalization.normalize(processedPath), cv.getVar(), cv.getSource(),
	                        cv.getLine());
	            }
	            resolvedPathsBuilder.add(fileSpec.getAbsolutePath());
            }
            else
                resolvedPathsBuilder.add(processedPath);
        }
        return resolvedPathsBuilder.build();
    }

    //////////////////////////////////////////////////////////////////////////
    // compiler.extensions.*
    //////////////////////////////////////////////////////////////////////////

    //
    // 'compiler.extensions.extension' option
    //

    /**
     * Configures a list of many extensions mapped to a single Extension URI.
     * <extension> <extension>something-extension.jar</extension>
     * <parameters>version=1.1,content=1.2</parameters> </extension>
     * 
     * @param cv The configuration value context.
     * @param pathlist A List of values for the Extension element, with the first item expected to be the uri and the
     *        remaining are extension paths.
     * @throws CannotOpen When no arg is provided or when the jar does not exist.
     */
    @Config(allowMultiple = true, removed = true)
    @Mapping({ "compiler", "extensions", "extension" })
    @Arguments({ "extension", "parameters" })
    @InfiniteArguments
    public void setExtension(ConfigurationValue cv, String[] pathlist) throws CannotOpen
    {
    }

    //////////////////////////////////////////////////////////////////////////
    // compiler.fonts.*
    //////////////////////////////////////////////////////////////////////////

    @Config
    @Mapping({ "compiler", "fonts", "advanced-anti-aliasing" })
    @FlexOnly
    public void setCompilerFontsAdvancedAntiAliasing(ConfigurationValue cv, boolean val)
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    @Config(allowMultiple = true, advanced = true)
    @Mapping({ "compiler", "fonts", "languages", "language-range" })
    @Arguments({ "lang", "range" })
    @FlexOnly
    public void setCompilerFontsLanguagesLanguageRange(ConfigurationValue cv, String lang, String range)
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    @Config
    @Mapping({ "compiler", "fonts", "local-fonts-snapshot" })
    @FlexOnly
    public void setCompilerFontsLocalFontsSnapshot(ConfigurationValue cv, String localFontsSnapshotPath)
            throws CannotOpen
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    @Config
    @Mapping({ "compiler", "fonts", "local-font-paths" })
    @Arguments(Arguments.PATH_ELEMENT)
    @InfiniteArguments
    @FlexOnly
    public void setCompilerFontsLocalFontPaths(ConfigurationValue cv, List<String> list) throws CannotOpen
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    @Config(advanced = true)
    @Mapping({ "compiler", "fonts", "managers" })
    @Arguments("manager-class")
    @InfiniteArguments
    @FlexOnly
    public void setCompilerFontsManagers(ConfigurationValue cv, List<String> list)
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    @Config
    @Mapping({ "compiler", "fonts", "max-cached-fonts" })
    @FlexOnly
    public void setCompilerFontsMaxCachedFonts(ConfigurationValue cv, String val)
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    @Config
    @Mapping({ "compiler", "fonts", "max-glyphs-per-face" })
    @FlexOnly
    public void setCompilerFontsMaxGlyphsPerFace(ConfigurationValue cv, String val)
    {
        // intentionally do nothing here as feature removed, but don't annotate as removed
        // as to not generate warnings for flex-config's which still set this options
    }

    //////////////////////////////////////////////////////////////////////////
    // compiler.namespaces
    //////////////////////////////////////////////////////////////////////////

    private List<MXMLNamespaceMapping> manifestMappings;

    public List<MXMLNamespaceMapping> getCompilerNamespacesManifestMappings()
    {
        return manifestMappings;
    }

    /**
     * Configures a list of many manifests mapped to a single namespace URI.
     * <namespace> <uri>library:adobe/flex/something</uri> <manifest>something-manifest.xml</manifest>
     * <manifest>something-else-manifest.xml</manifest> ... </namespace>
     * 
     * @param cfgval The configuration value context.
     * @param args A List of values for the namespace element, with the first item expected to be the uri and the
     *        remaining are manifest paths.
     */
    @Config(allowMultiple = true)
    @Mapping({ "compiler", "namespaces", "namespace" })
    @Arguments({ "uri", "manifest" })
    @InfiniteArguments
    @FlexOnly
    public void setCompilerNamespacesNamespace(ConfigurationValue cfgval, List<String> args)
            throws ConfigurationException
    {
        if (args == null)
            throw new ConfigurationException.CannotOpen(null, cfgval.getVar(), cfgval.getSource(), cfgval.getLine());

        // allow -compiler.namespaces.namespace= which means don't add
        // anything, which matches the behavior of things like -compiler.library-path
        // which don't throw an error in this case either.
        if (args.isEmpty())
            return;

        if (args.size() < 2)
            throw new ConfigurationException.NamespaceMissingManifest("namespace", cfgval.getSource(),
                    cfgval.getLine());

        if (args.size() % 2 != 0)
            throw new ConfigurationException.IncorrectArgumentCount(args.size() + 1, args.size(), cfgval.getVar(),
                    cfgval.getSource(), cfgval.getLine());

        if (manifestMappings == null)
            manifestMappings = new ArrayList<MXMLNamespaceMapping>();

        for (int i = 0; i < args.size() - 1; i += 2)
        {
            final String uri = args.get(i);
            final String manifestFile = args.get(i + 1);
            final String path = resolvePathStrict(manifestFile, cfgval);
            manifestMappings.add(new MXMLNamespaceMapping(uri, path));
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // metadata.*
    ///////////////////////////////////////////////////////////////////////////

    //
    // 'metadata.contributor' option
    //

    private final Set<String> contributors = new TreeSet<String>();

    @Config(allowMultiple = true)
    @Mapping({ "metadata", "contributor" })
    @Arguments("name")
    public void setMetadataContributor(ConfigurationValue cv, String name)
    {
        contributors.add(name);
    }

    //
    // 'metadata.creator' option
    //

    private final Set<String> creators = new TreeSet<String>();

    @Config(allowMultiple = true)
    @Mapping({ "metadata", "creator" })
    @Arguments("name")
    public void setMetadataCreator(ConfigurationValue cv, String name)
    {
        creators.add(name);
    }

    //
    // 'metadata.date' option
    //

    public String date = null;

    @Config
    @Mapping({ "metadata", "date" })
    @Arguments("text")
    public void setMetadataDate(ConfigurationValue cv, String text)
    {
        date = text;
    }

    //
    // 'metadata.description' option
    //

    private final Map<String, String> localizedDescriptions = new LinkedHashMap<String, String>();

    @Config
    @Mapping({ "metadata", "description" })
    @Arguments("text")
    public void setMetadataDescription(ConfigurationValue cv, String text)
    {
        localizedDescriptions.put("x-default", text);
    }

    //
    // 'metadata.language' option
    //

    public final Set<String> langs = new TreeSet<String>();

    @Config(allowMultiple = true)
    @Mapping({ "metadata", "language" })
    @Arguments("code")
    public void setMetadataLanguage(ConfigurationValue cv, String code)
    {
        langs.add(code);
    }

    //
    // 'metadata.localized-description' option
    //

    @Config(allowMultiple = true)
    @Mapping({ "metadata", "localized-description" })
    @Arguments({ "text", "lang" })
    public void setMetadataLocalizedDescription(ConfigurationValue cv, String text, String lang)
    {
        localizedDescriptions.put(lang, text);
    }

    //
    // 'metadata.localized-title' option
    //

    @Config(allowMultiple = true)
    @Mapping({ "metadata", "localized-title" })
    @Arguments({ "title", "lang" })
    public void setMetadataLocalizedTitle(ConfigurationValue cv, String title, String lang)
    {
        localizedTitles.put(lang, title);
    }

    //
    // 'metadata.publisher' option
    //

    private final Set<String> publishers = new TreeSet<String>();

    @Config(allowMultiple = true)
    @Mapping({ "metadata", "publisher" })
    @Arguments("name")
    public void setMetadataPublisher(ConfigurationValue cv, String name)
    {
        publishers.add(name);
    }

    //
    // 'metadata.title' option
    //

    private final Map<String, String> localizedTitles = new LinkedHashMap<String, String>();

    @Config
    @Mapping({ "metadata", "title" })
    @Arguments("text")
    public void setMetadataTitle(ConfigurationValue cv, String title)
    {
        localizedTitles.put("x-default", title);
    }

    //////////////////////////////////////////////////////////////////////////
    // runtime-shared-library-settings
    //////////////////////////////////////////////////////////////////////////

    // 
    // 'force-rsl' option
    //
    private Set<String> forceRsls;

    /**
     * Get the array of SWCs that should have their RSLs loaded, even if the compiler detects no classes being used from
     * the SWC.
     * 
     * @return Array of SWCs that should have their RSLs loaded.
     */
    public Set<String> getForceRsls()
    {
        if (forceRsls == null)
        {
            return Collections.emptySet();
        }

        return forceRsls;
    }

    @Config(advanced = true, allowMultiple = true)
    @Mapping({ "runtime-shared-library-settings", "force-rsls" })
    @SoftPrerequisites({ "runtime-shared-library-path" })
    @Arguments(Arguments.PATH_ELEMENT)
    @InfiniteArguments
    @FlexOnly
    public void setForceRsls(ConfigurationValue cfgval, String[] args) throws ConfigurationException
    {
        if (forceRsls == null)
        {
            forceRsls = new HashSet<String>();
        }

        // Add swc to the forceRsls set.
        for (String arg : args)
        {
            // path-element parameter (swc)
            // verify path exists and the swc has an
            // existing -rslp option specified.
            String swcPath = resolvePathStrict(arg, cfgval);

            // verify the swc is used in an the RSL configuration.
            if (!doesSwcHaveRSLInfo(swcPath))
            {
                throw new ConfigurationException.SwcDoesNotHaveRslData(swcPath, cfgval.getVar(), cfgval.getSource(),
                        cfgval.getLine());
            }

            forceRsls.add(swcPath);
        }
    }

    // 
    // 'application-domain' option
    //

    /*
     * Key: swc file path; Value: application domain target
     */
    private HashMap<String, ApplicationDomainTarget> applicationDomains;

    /**
     * Get the application domain an RSL should be loaded into. The default is the current application domain but the
     * user can override this setting.
     * 
     * @param swcPath The full path of the swc file.
     * 
     * @return The application domain the RSL should be loaded into. If the swc is not found, then 'default' is
     *         returned.
     */
    public ApplicationDomainTarget getApplicationDomain(String swcPath)
    {
        if (applicationDomains == null || swcPath == null)
        {
            return ApplicationDomainTarget.DEFAULT;
        }

        for (Map.Entry<String, ApplicationDomainTarget> entry : applicationDomains.entrySet())
        {
            if (entry.getKey().equals(swcPath))
            {
                return entry.getValue();
            }
        }

        return ApplicationDomainTarget.DEFAULT;
    }

    @Config(advanced = true, allowMultiple = true)
    @SoftPrerequisites({ "runtime-shared-library-path" })
    @Mapping({ "runtime-shared-library-settings", "application-domain" })
    @Arguments({ "path-element", "application-domain-target" })
    @InfiniteArguments
    @FlexOnly
    // TODO: need to create an argument name generator for the args.
    public void setApplicationDomain(ConfigurationValue cfgval, String[] args) throws ConfigurationException
    {
        // ignore the force option if we are static linking
        if (getStaticLinkRsl())
            return;

        if (applicationDomains == null)
        {
            applicationDomains = new HashMap<String, ApplicationDomainTarget>();
        }

        // Add swc and application domain target to the map.
        // The args are: swc file path, application domain type, ...
        for (int i = 0; i < args.length; i++)
        {
            String arg = args[i++];

            // path-element parameter (swc)
            // verify path exists and the swc has an
            // existing -rslp option specified.
            String swcPath = resolvePathStrict(arg, cfgval);

            // verify the swc is used in an the RSL configuration.
            if (!doesSwcHaveRSLInfo(swcPath))
            {
                throw new ConfigurationException.SwcDoesNotHaveRslData(swcPath, cfgval.getVar(), cfgval.getSource(),
                        cfgval.getLine());
            }

            // Verify the application domain target is valid.
            arg = args[i];
            ApplicationDomainTarget adTarget = getApplicationDomainTarget(arg);
            if (adTarget == null)
            {
                // throw a configuration exception that the application domain 
                // type is incorrect.
                throw new ConfigurationException.BadApplicationDomainValue(swcPath, arg, cfgval.getVar(),
                        cfgval.getSource(), cfgval.getLine());
            }

            applicationDomains.put(swcPath, adTarget);
        }
    }

    /**
     * Test if the specified parameter is a valid application domain type. If it is then return the corresponding enum.
     * 
     * @param arg String value representing an ApplicationDomainTarget.
     * @return An ApplicationDomainTarget enum if the parameter is a valid application domain target, null otherwise.
     */
    private ApplicationDomainTarget getApplicationDomainTarget(String arg)
    {
        for (ApplicationDomainTarget appDomain : ApplicationDomainTarget.values())
        {
            if (appDomain.getApplicationDomainValue().equals(arg))
                return appDomain;
        }

        return null;
    }

    /**
     * Check if the SWC has any RSL info associated with it.
     * 
     * @param swcPath
     * @return true if the swc has RSL info, false otherwise.
     */
    private boolean doesSwcHaveRSLInfo(String swcPath)
    {
        if (swcPath == null)
            return false;

        List<RuntimeSharedLibraryPathInfo> rslInfoList = getRslPathInfo();
        for (RuntimeSharedLibraryPathInfo rslInfo : rslInfoList)
        {
            if (swcPath.equals(rslInfo.getSWCFile().getPath()))
                return true;
        }

        return false;
    }

    //////////////////////////////////////////////////////////////////////////
    // compiler.mxml
    //////////////////////////////////////////////////////////////////////////

    //
    // 'compiler.mxml.compatibility-version' option
    //

    public static final int MXML_VERSION_4_7 = 0x04070000;
    public static final int MXML_VERSION_4_6 = 0x04060000;
    public static final int MXML_VERSION_4_5 = 0x04050000;
    public static final int MXML_VERSION_4_0 = 0x04000000;
    public static final int MXML_VERSION_3_0 = 0x03000000;
    public static final int MXML_VERSION_2_0_1 = 0x02000001;
    public static final int MXML_VERSION_2_0 = 0x02000000;
    public static final int MXML_CURRENT_VERSION = MXML_VERSION_4_7;
    public static final int MXML_EARLIEST_MAJOR_VERSION = 3;
    public static final int MXML_LATEST_MAJOR_VERSION = 4;
    public static final int MXML_LATEST_MINOR_VERSION = 7;

    private int mxml_major = MXML_LATEST_MAJOR_VERSION;
    private int mxml_minor = MXML_LATEST_MINOR_VERSION;
    private int mxml_revision;

    private int mxmlMinMajor = MXML_EARLIEST_MAJOR_VERSION;
    private int mxmlMinMinor;
    private int mxmlMinRevision;

    public int getCompilerMxmlMajorCompatibilityVersion()
    {
        return mxml_major;
    }

    public int getCompilerMxmlMinorCompatibilityVersion()
    {
        return mxml_minor;
    }

    public int getCompilerMxmlRevisionCompatibilityVersion()
    {
        return mxml_revision;
    }

    /*
     * Unlike the framework's FlexVersion.compatibilityVersionString, this
     * returns null rather than a string like "3.0.0" for the current version.
     * But if a -compatibility-version was specified, this string will always be
     * of the form N.N.N. For example, if -compatibility-version=2, this string
     * is "2.0.0", not "2".
     */
    public String getCompilerMxmlCompatibilityVersionString()
    {
        return (mxml_major == 0 && mxml_minor == 0 && mxml_revision == 0) ? null
                : mxml_major + "." + mxml_minor + "." + mxml_revision;
    }

    /*
     * This returns an int that can be compared with version constants such as
     * MxmlConfiguration.VERSION_3_0.
     */
    public int getCompilerMxmlCompatibilityVersion()
    {
        int version = (mxml_major << 24) + (mxml_minor << 16) + mxml_revision;
        return version != 0 ? version : MXML_CURRENT_VERSION;
    }

    @Config
    @Mapping({ "compiler", "mxml", "compatibility-version" })
    @Arguments("version")
    @FlexOnly
    public void setCompilerMxmlCompatibilityVersion(ConfigurationValue cv, String version) throws ConfigurationException
    {
        if (version == null)
        {
            return;
        }

        String[] results = version.split("\\.");

        if (results.length == 0)
        {
            throw new ConfigurationException.BadVersion(version, "compatibility-version");

        }

        // Set minor and revision numbers to zero in case only a major number 
        // was specified.
        this.mxml_minor = 0;
        this.mxml_revision = 0;

        for (int i = 0; i < results.length; i++)
        {
            int versionNum = 0;

            try
            {
                versionNum = Integer.parseInt(results[i]);
            }
            catch (NumberFormatException e)
            {
                throw new ConfigurationException.BadVersion(version, "compatibility-version");
            }

            if (i == 0)
            {
                if (versionNum >= MXML_EARLIEST_MAJOR_VERSION && versionNum <= MXML_LATEST_MAJOR_VERSION)
                {
                    this.mxml_major = versionNum;
                }
                else
                {
                    throw new ConfigurationException.BadVersion(version, "compatibility-version");
                }
            }
            else
            {
                if (versionNum >= 0)
                {
                    if (i == 1)
                    {
                        this.mxml_minor = versionNum;
                    }
                    else
                    {
                        this.mxml_revision = versionNum;
                    }
                }
                else
                {
                    throw new ConfigurationException.BadVersion(version, "compatibility-version");
                }
            }
        }
    }

    /*
     * Minimum supported SDK version for this library. This string will always
     * be of the form N.N.N. For example, if -minimum-supported-version=2, this
     * string is "2.0.0", not "2".
     */
    public String getCompilerMxmlMinimumSupportedVersionString()
    {
        return (mxmlMinMajor == 0 && mxmlMinMinor == 0 && mxmlMinRevision == 0) ? null
                : mxmlMinMajor + "." + mxmlMinMinor + "." + mxmlMinRevision;
    }

    /*
     * This returns an int that can be compared with version constants such as
     * MxmlConfiguration.VERSION_3_0.
     */
    public int getCompilerMxmlMinimumSupportedVersion()
    {
        int version = (mxmlMinMajor << 24) + (mxmlMinMinor << 16) + mxmlMinRevision;
        return version != 0 ? version : (MXML_EARLIEST_MAJOR_VERSION << 24);
    }

    public void setCompilerMxmlMinimumSupportedVersion(int version)
    {
        mxmlMinMajor = version >> 24 & 0xFF;
        mxmlMinMinor = version >> 16 & 0xFF;
        mxmlMinRevision = version & 0xFF;
    }

    @Config
    @Mapping({ "compiler", "mxml", "minimum-supported-version" })
    @FlexOnly
    public void setCompilerMxmlMinimumSupportedVersion(ConfigurationValue cv, String version)
            throws ConfigurationException
    {
        if (version == null)
        {
            return;
        }

        String[] results = version.split("\\.");

        if (results.length == 0)
        {
            throw new ConfigurationException.BadVersion(version, "minimum-supported-version");

        }

        for (int i = 0; i < results.length; i++)
        {
            int versionNum = 0;

            try
            {
                versionNum = Integer.parseInt(results[i]);
            }
            catch (NumberFormatException e)
            {
                throw new ConfigurationException.BadVersion(version, "minimum-supported-version");
            }

            if (i == 0)
            {
                if (versionNum >= MXML_EARLIEST_MAJOR_VERSION && versionNum <= MXML_LATEST_MAJOR_VERSION)
                {
                    this.mxmlMinMajor = versionNum;
                }
                else
                {
                    throw new ConfigurationException.BadVersion(version, "minimum-supported-version");
                }
            }
            else
            {
                if (versionNum >= 0)
                {
                    if (i == 1)
                    {
                        mxmlMinMinor = versionNum;
                    }
                    else
                    {
                        mxmlMinRevision = versionNum;
                    }
                }
                else
                {
                    throw new ConfigurationException.BadVersion(version, "minimum-supported-version");
                }
            }
        }

        isMinimumSupportedVersionConfigured = true;
    }

    private boolean isMinimumSupportedVersionConfigured = false;

    public boolean isCompilerMxmlMinimumSupportedVersionConfigured()
    {
        return isMinimumSupportedVersionConfigured;
    }

    //
    // 'compiler.mobile' option
    //

    private boolean mobile = false;

    /**
     * @return determines whether the target runtime is a mobile device. This may alter the features available, such as
     *         certain blend-modes when compiling FXG.
     */
    public boolean getMobile()
    {
        return mobile;
    }

    @Config()
    @Mapping({ "compiler", "mobile" })
    public void setMobile(ConfigurationValue cv, boolean b)
    {
        mobile = b;
    }

    ////////////////////////////////////////////////////////////////////////////
    // licenses.*
    ////////////////////////////////////////////////////////////////////////////

    //
    //  'license' option
    //

    @Config(allowMultiple = true, displayed = false, removed = true)
    @Mapping({ "licenses", "license" })
    @Arguments({ "product", "serial-number" })
    public void setLicensesLicense(ConfigurationValue cfgval, String product, String serialNumber)
            throws ConfigurationException
    {
    }

    ////////////////////////////////////////////////////////////////////////////
    // frames.*
    ////////////////////////////////////////////////////////////////////////////

    private List<FrameInfo> frameList = new LinkedList<FrameInfo>();

    public List<FrameInfo> getFrameList()
    {
        return frameList;
    }

    @Config(advanced = true, allowMultiple = true)
    @Mapping({ "frames", "frame" })
    @Arguments({ "label", "classname" })
    @InfiniteArguments
    public void setFramesFrame(ConfigurationValue cv, List<String> args) throws ConfigurationException
    {
        // "args" are [label, qname, qname, qname, ...]

        final FrameInfo info = new FrameInfo();

        if (args.size() < 2)
            throw new ConfigurationException.BadFrameParameters(cv.getVar(), cv.getSource(), cv.getLine());

        for (final String next : args)
        {
            if (info.getLabel() == null)
            {
                info.setLabel(next);
            }
            else
            {
                info.getFrameClasses().add(next);
            }
        }

        frameList.add(info);
    }

    //
    // -as3
    //

    private boolean as3 = true;

    @Config(advanced = true)
    @Mapping({ "compiler", "as3" })
    @DeprecatedConfig
    public void setAS3(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != as3)
            addRemovedConfigurationOptionProblem(cv);
    }

    //
    // -es
    //

    private boolean es = false;

    @Config(advanced = true)
    @Mapping({ "compiler", "es" })
    @DeprecatedConfig
    public void setES(ConfigurationValue cv, boolean b)
    {
        // This option is set in flex-config.xml so only warn
        // if the user sets a non-default value.
        if (b != es)
            addRemovedConfigurationOptionProblem(cv);
    }

    ////////////////////////////////////////////////////////////////////////////
    // Compc Options
    ////////////////////////////////////////////////////////////////////////////

    //
    // compute-digest=true|false
    //

    /**
     * Writes a digest to the catalog.xml of a library. Use this when the library will be used as a cross-domain RSL or
     * when you want to enforce the versioning of RSLs. The default value is true.
     */
    @Config(compcOnly = true, removed = true)
    @Mapping("compute-digest")
    public void setComputeDigest(ConfigurationValue cv, boolean value)
    {
    }

    /**
     * directory=false|true
     */
    private boolean outputSwcAsDirectory = false;

    /**
     * Outputs the SWC file in an open directory format rather than a SWC file. You use this option with the output
     * option to specify a destination directory, as the following example shows:
     * 
     * <pre>
     * compc -directory=true -output=destination_directory
     * </pre>
     */
    @Config(compcOnly = true)
    @Mapping("directory")
    public void setOutputSwcAsDirectory(ConfigurationValue cv, boolean value)
    {
        outputSwcAsDirectory = value;
    }

    /**
     * @return True if the compiler will build the SWC file in an open directory format rather than a SWC file.
     */
    public boolean getOutputSwcAsDirectory()
    {
        return outputSwcAsDirectory;
    }

    /**
     * include-classes class [...]
     */
    private final List<String> includeClasses = new ArrayList<String>();

    /**
     * Specifies classes to include in the SWC file. You provide the class name (for example, MyClass) rather than the
     * file name (for example, MyClass.as) to the file for this option. As a result, all classes specified with this
     * option must be in the compiler's source path. You specify this by using the source-path compiler option.
     * <p>
     * You can use packaged and unpackaged classes. To use components in namespaces, use the include-namespaces option.
     * <p>
     * If the components are in packages, ensure that you use dot-notation rather than slashes to separate package
     * levels.
     * <p>
     * This is the default option for the component compiler.
     */
    @Config(compcOnly = true, allowMultiple = true)
    @Arguments(Arguments.CLASS)
    @Mapping("include-classes")
    public void setIncludeClasses(ConfigurationValue cv, List<String> values)
    {
        includeClasses.addAll(values);
    }

    /**
     * @return A list of class names to be included in the target.
     */
    public List<String> getIncludeClasses()
    {
        return includeClasses;
    }

    /**
     * include-file name path [...]
     */
    public final Map<String, String> includeFilesNamePath = new LinkedHashMap<String, String>();

    /**
     * Adds the file to the SWC file. This option does not embed files inside the library.swf file. This is useful for
     * adding graphics files, where you want to add non-compiled files that can be referenced in a style sheet or
     * embedded as assets in MXML files.
     * <p>
     * If you add a stylesheet that references compiled resources such as programmatic skins, use the include-stylesheet
     * option.
     * <p>
     * If you use the [Embed] syntax to add a resource to your application, you are not required to use this option to
     * also link it into the SWC file.
     */
    @Config(compcOnly = true, allowMultiple = true)
    @Mapping("include-file")
    @Arguments({ "name", "path" })
    public void setIncludeFiles(ConfigurationValue cv, List<String> values)
            throws IncorrectArgumentCount, CannotOpen, RedundantFile
    {
        // Expect name-path pairs in the arguments.
        final int size = values.size();
        if (size % 2 != 0)
            throw new IncorrectArgumentCount(size + 1, size, cv.getVar(), cv.getSource(), cv.getLine());

        for (int nameIndex = 0; nameIndex < size - 1; nameIndex += 2)
        {
            final String name = values.get(nameIndex);
            final String path = resolvePathStrict(values.get(nameIndex + 1), cv);

            if (includeFilesNamePath.containsKey(name))
            {
                throw new ConfigurationException.RedundantFile(name, cv.getVar(), cv.getSource(), cv.getLine());
            }

            includeFilesNamePath.put(name, path);
        }
    }

    /**
     * @return A map of included files. The keys are file entry names; The values are file paths.
     */
    public Map<String, String> getIncludeFiles()
    {
        return includeFilesNamePath;
    }

    /**
     * include-lookup-only=false|true
     */
    private boolean includeLookupOnly = false;

    /**
     * If true, only manifest entries with lookupOnly=true are included in the SWC catalog.
     */
    @Config(compcOnly = true, advanced = true)
    @Mapping("include-lookup-only")
    @FlexOnly
    public void setIncludeLookupOnly(ConfigurationValue cv, boolean value)
    {
        includeLookupOnly = value;
    }

    /**
     * @return If true, only manifest entries with lookupOnly=true are included in the SWC catalog.
     */
    public boolean getIncludeLookupOnly()
    {
        return includeLookupOnly;
    }

    /**
     * include-namespaces uri [...]
     */
    private final List<String> includeNamespaces = new ArrayList<String>();

    /**
     * Specifies namespace-style components in the SWC file. You specify a list of URIs to include in the SWC file. The
     * uri argument must already be defined with the namespace option.
     * <p>
     * To use components in packages, use the include-classes option.
     */
    @Config(compcOnly = true, allowMultiple = true)
    @Mapping("include-namespaces")
    @Arguments({ "uri" })
    @FlexOnly
    public void setIncludeNamespaces(ConfigurationValue cv, List<String> values)
    {
        includeNamespaces.addAll(values);
    }

    /**
     * @return A list of URIs to include in the SWC file.
     */
    public List<String> getIncludeNamespaces()
    {
        return includeNamespaces;
    }

    /**
     * include-sources path-element
     */
    private final List<String> includeSources = new ArrayList<String>();

    /**
     * Specifies classes or directories to add to the SWC file. When specifying classes, you specify the path to the
     * class file (for example, MyClass.as) rather than the class name itself (for example, MyClass). This lets you add
     * classes to the SWC file that are not in the source path. In general, though, use the include-classes option,
     * which lets you add classes that are in the source path.
     * <p>
     * If you specify a directory, this option includes all files with an MXML or AS extension, and ignores all other
     * files.
     * <p>
     * If you use this option to include MXML components that are in a non-default package, you must include the source
     * folder in the source path.
     */
    @Config(compcOnly = true, allowMultiple = true)
    @Mapping("include-sources")
    @Arguments(Arguments.PATH_ELEMENT)
    public void setIncludeSources(ConfigurationValue cv, List<String> values) throws NotAFile
    {
        fillListWithResolvedPaths(values, includeSources, cv);
    }

    /**
     * @return Normalized file paths of the included source files.
     */
    public List<String> getIncludeSources()
    {
        return includeSources;
    }

    /**
     * Add resolved file paths from {@code source} list to {@code target} list.
     * 
     * @param source Source list with un-resolved file paths.
     * @param target Target list.
     * @param cv Context.
     * @throws CannotOpen
     */
    private void fillListWithResolvedPaths(final List<String> source, final List<String> target,
            final ConfigurationValue cv) throws NotAFile
    {
        for (final String path : source)
        {
            String resolvedPath;
            try
            {
                resolvedPath = resolvePathStrict(path, cv);
                target.add(resolvedPath);
            }
            catch (CannotOpen e)
            {
                throw new ConfigurationException.NotAFile(path, cv.getVar(), cv.getSource(), cv.getLine());
            }
        }
    }

    /**
     * include-stylesheet namepath [...]
     */
    private final List<String> includeStyleSheets = new ArrayList<String>();

    /**
     * Specifies stylesheets to add to the SWC file. This option compiles classes that are referenced by the stylesheet
     * before including the stylesheet in the SWC file.
     * <p>
     * You do not need to use this option for all stylesheets; only stylesheets that reference assets that need to be
     * compiled such as programmatic skins or other class files. If your stylesheet does not reference compiled assets,
     * you can use the include-file option.
     * <p>
     * This option does not compile the stylesheet into a SWF file before including it in the SWC file. You compile a
     * CSS file into a SWF file when you want to load it at run time.
     */
    @Config(compcOnly = true, allowMultiple = true)
    @Mapping("include-stylesheet")
    @Arguments({ "name", "path" })
    @FlexOnly
    public void setIncludeStyleSheets(ConfigurationValue cv, List<String> values) throws NotAFile
    {
        fillListWithResolvedPaths(values, includeStyleSheets, cv);
    }

    /**
     * @return A list of the normalized file path of stylesheets to add to the SWC file.
     */
    public List<String> getIncludeStyleSheets()
    {
        return includeStyleSheets;
    }

    private File dependencyGraphOutput;

    /**
     * Specifies a file name that a graphml version of the dependency graph should be written to.
     * 
     */
    @Config(advanced = true)
    @Mapping("dependency-graph")
    @Arguments("filename")
    public void setDependencyGraphOutput(ConfigurationValue cv, String fileName)
    {
        dependencyGraphOutput = new File(getOutputPath(cv, fileName));
    }

    /**
     * Gets the location the graphml version of the dependency graph should be written to, null if no dependecy graph
     * should be written.
     * 
     * @return The location the dependency graph should be written to.
     */
    public File getDependencyGraphOutput()
    {
        return dependencyGraphOutput;
    }

    //
    // 'output' option
    //

    private String output;

    public String getOutput()
    {
        return output;
    }

    @Config
    @Arguments("filename")
    public void setOutput(ConfigurationValue val, String output) throws ConfigurationException
    {
        this.output = getOutputPath(val, output);
    }

    //
    // 'dump-config-file' option from ToolsConfiguration
    //

    private String dumpConfigFile = null;

    /**
     * @return filename of the configuration dump
     */
    public String getDumpConfig()
    {
        return dumpConfigFile;
    }

    @Config(advanced = true, displayed = false)
    @Arguments("filename")
    @Mapping("dump-config")
    public void setDumpConfig(ConfigurationValue cv, String filename)
    {
        dumpConfigFile = getOutputPath(cv, filename);
    }

    //
    // 'warnings' option from ToolsConfiguration
    //

    private boolean warnings = true;

    public boolean getWarnings()
    {
        return warnings;
    }

    @Config
    @Mapping("warnings")
    public void setWarnings(ConfigurationValue cv, boolean b)
    {
        warnings = b;
    }

    //
    // 'error-problems'
    //

    private Collection<Class<ICompilerProblem>> errorClasses;

    /**
     * Get the collection of user specified problem classes that should be treated as errors.
     * 
     * @return list of problem classes that should be treated as errors.
     */
    public Collection<Class<ICompilerProblem>> getErrorProblems()
    {
        return errorClasses != null ? errorClasses : Collections.<Class<ICompilerProblem>> emptyList();
    }

    @Config(allowMultiple = true)
    @Arguments(Arguments.CLASS)
    @InfiniteArguments
    public void setErrorProblems(ConfigurationValue cv, List<String> classNames) throws ConfigurationException
    {
        if (errorClasses == null)
            errorClasses = new HashSet<Class<ICompilerProblem>>();

        // Convert string to a class and save.
        for (String className : classNames)
        {
            Class<ICompilerProblem> resolvedClass = resolveProblemClassName(className);
            if (resolvedClass == null)
            {
                throw new ConfigurationException.CompilerProblemClassNotFound(className, cv.getVar(), cv.getSource(),
                        cv.getLine());
            }

            errorClasses.add(resolvedClass);
        }
    }

    //
    // 'warning-problems'
    //

    private Collection<Class<ICompilerProblem>> warningClasses;

    /**
     * Get the collection of user specified problem classes that should be treated as warnings.
     * 
     * @return list of problem classes that should be treated as warnings.
     */
    public Collection<Class<ICompilerProblem>> getWarningProblems()
    {
        return warningClasses != null ? warningClasses : Collections.<Class<ICompilerProblem>> emptyList();
    }

    @Config(allowMultiple = true)
    @Arguments(Arguments.CLASS)
    @InfiniteArguments
    public void setWarningProblems(ConfigurationValue cv, List<String> classNames) throws ConfigurationException
    {
        if (warningClasses == null)
            warningClasses = new HashSet<Class<ICompilerProblem>>();

        // Convert string to a class and save.
        for (String className : classNames)
        {
            Class<ICompilerProblem> resolvedClass = resolveProblemClassName(className);
            if (resolvedClass == null)
            {
                throw new ConfigurationException.CompilerProblemClassNotFound(className, cv.getVar(), cv.getSource(),
                        cv.getLine());
            }

            warningClasses.add(resolvedClass);
        }
    }

    //
    // 'ignore-problems'
    //

    private Collection<Class<ICompilerProblem>> ignoreClasses;

    /**
     * Get the collection of user specified problem classes that should be ignored.
     * 
     * @return list of problem classes that should be ignored.
     */
    public Collection<Class<ICompilerProblem>> getIgnoreProblems()
    {
        return ignoreClasses != null ? ignoreClasses : Collections.<Class<ICompilerProblem>> emptyList();
    }

    @Config(allowMultiple = true)
    @Arguments(Arguments.CLASS)
    @InfiniteArguments
    public void setIgnoreProblems(ConfigurationValue cv, List<String> classNames) throws ConfigurationException
    {
        if (ignoreClasses == null)
            ignoreClasses = new HashSet<Class<ICompilerProblem>>();

        // Convert string to a class and save.
        for (String className : classNames)
        {
            Class<ICompilerProblem> resolvedClass = resolveProblemClassName(className);
            if (resolvedClass == null)
            {
                throw new ConfigurationException.CompilerProblemClassNotFound(className, cv.getVar(), cv.getSource(),
                        cv.getLine());
            }

            ignoreClasses.add(resolvedClass);
        }
    }

    //
    // 'legacy-message-format'
    //

    private boolean legacyMessageFormat = true;

    public boolean useLegacyMessageFormat()
    {
        return legacyMessageFormat;
    }

    @Config(hidden = true)
    public void setLegacyMessageFormat(ConfigurationValue cv, boolean value) throws ConfigurationException
    {
        legacyMessageFormat = value;
    }

    //
    // 'create-target-with-errors'
    //

    private boolean createTargetWithErrors = false;

    public boolean getCreateTargetWithErrors()
    {
        return createTargetWithErrors;
    }

    @Config(hidden = true)
    public void setCreateTargetWithErrors(ConfigurationValue cv, boolean value) throws ConfigurationException
    {
        createTargetWithErrors = value;
    }

    //
    // 'flex'
    //
    private boolean isFlex = false;

    public boolean isFlex()
    {
        return isFlex;
    }

    /**
     * Option to enable or prevent various Flex compiler behaviors. This is currently used to enable/disable the
     * generation of a root class for library swfs and generation of Flex specific code for application swfs.
     */
    @Config(hidden = true)
    public void setFlex(ConfigurationValue cv, boolean value) throws ConfigurationException
    {
        isFlex = value;
    }

    private boolean isExcludeNativeJSLibraries = false;

    public boolean isExcludeNativeJSLibraries()
    {
        return isExcludeNativeJSLibraries;
    }

    /**
     * Option to remove the Native JS libraries from external-library-path and library-path as they shouldn't be any
     * when compiling SWFs / SWCs.
     */
    @Config()
    @Mapping("exclude-native-js-libraries")
    public void setExcludeNativeJSLibraries(ConfigurationValue cv, boolean value) throws ConfigurationException
    {
        isExcludeNativeJSLibraries = value;
    }

    /**
     * Resolve a problem class name to a Java Class.
     * 
     * @param className May be fully qualified. If the class name is not fully qualified, it is assumed to live in the
     *        "org.apache.flex.compiler.problems" package.
     * 
     * @return A class corresponding to the className or null if the class name was not found.
     */
    @SuppressWarnings("unchecked")
    private Class<ICompilerProblem> resolveProblemClassName(String className)
    {
        if (className == null)
            return null;

        Class<?> resolvedClass = null;

        try
        {
            resolvedClass = Class.forName(className);
        }
        catch (ClassNotFoundException e)
        {
            return null;
        }

        if (ICompilerProblem.class.isAssignableFrom(resolvedClass))
            return (Class<ICompilerProblem>) resolvedClass;
        else
            return null;
    }

    //
    // 'file-specs' option
    //

    private List<String> fileSpecs = new ArrayList<String>();

    /**
     * Get target file path. Target file is the last file in the {@link #getFileSpecs()}.
     * FIXME: Calling this target file is a bit misleading as it's sort of the "main" source file
     */
    public String getTargetFile()
    {
        if (fileSpecs.isEmpty())
            return null;
        else
            return Iterables.getLast(fileSpecs);
    }

    /**
     * @return Path of the target's parent directory.
     */
    public String getTargetFileDirectory()
    {
        final String targetFile = getTargetFile();
        if (targetFile == null)
            return null;

        final String normalizedTargetFile = FilenameNormalization.normalize(targetFile);

        return FilenameUtils.getFullPathNoEndSeparator(normalizedTargetFile);
    }

    /**
     * This has been added so that unit tests can change the target file. It isn't normally called when running the
     * command line compiler.
     */
    public void setTargetFile(String mainFile)
    {
        fileSpecs.clear();
        fileSpecs.add(mainFile);
    }

    /**
     * @return A list of filespecs. It's the default variable for command line.
     */
    public List<String> getFileSpecs()
    {
        return fileSpecs;
    }

    @Config(allowMultiple = true, hidden = true)
    @Arguments(Arguments.PATH_ELEMENT)
    @InfiniteArguments
    @SoftPrerequisites("flex")
    public void setFileSpecs(ConfigurationValue cv, List<String> args) throws ConfigurationException
    {
        this.fileSpecs.addAll(args);

        checkForMxmlFiles(args);
    }

    private void checkForMxmlFiles(List<String> paths)
    {
        // If there are mxml or css files then we are compiling a flex 
        // application so enable "flex".
        for (String path : paths)
        {
            if (path.endsWith(".mxml") || path.endsWith(".css"))
                isFlex = true;
        }
    }

    //
    // 'help' option from CommandLineConfiguration
    //

    /**
     * dummy, just a trigger for help text
     */
    @Config(displayed = false, greedy = true)
    @Arguments("keyword")
    @InfiniteArguments
    public void setHelp(ConfigurationValue cv, String[] keywords)
    {

    }

    //
    // 'load-config' option from CommandLineConfiguration
    //

    private String configFile = null;

    /**
     * @return Normalized path to a Flex configuration file.
     */
    public String getLoadConfig()
    {
        return configFile;
    }

    /**
     * Since {@link ConfigurationBuffer} loads the "load-config" files, the value of this configuration option isn't
     * intersting to the rest part of the compiler.
     */
    @Config(allowMultiple = true)
    @Arguments("filename")
    public void setLoadConfig(ConfigurationValue cv, String filename) throws ConfigurationException
    {
        configFile = resolvePathStrict(filename, cv);
    }

    //
    // 'version' option from CommandLineConfiguration
    //

    /**
     * Dummy option. Just a trigger for version info.
     */
    @Config
    public void setVersion(ConfigurationValue cv, boolean value)
    {
    }

    //
    // 'verbose' option from CommandLineConfiguration
    //

    private boolean verbose = false;

    public boolean isVerbose()
    {
        return verbose;
    }

    @Config(hidden = true)
    public void setVerbose(ConfigurationValue cfgval, boolean b)
    {
        verbose = b;
    }

    //
    // 'dump-ast' option from CommandLineConfiguration
    //

    private boolean dumpAst;

    public boolean isDumpAst()
    {
        return dumpAst;
    }

    @Config(hidden = true)
    public void setDumpAst(ConfigurationValue cfgval, boolean b)
    {
        dumpAst = b;
    }

    //
    // 'enable-inlining' option from CommandLineConfiguration
    //
    private boolean enableInlining = false;

    /**
     * @return true if function inlining has been enabled.
     */
    public boolean isInliningEnabled()
    {
        return enableInlining;
    }

    /**
     * Enable or disable function inlining.
     * 
     * @param cfgval The configuration value context.
     * @param b true to enable inlining, false otherwise.
     */
    @Config(hidden = true)
    @Mapping({ "compiler", "inline" })
    public void setEnableInlining(ConfigurationValue cfgval, boolean b)
    {
        enableInlining = b;
    }

    //
    // 'remove-dead-code' option from CommandLineConfiguration
    //
    private boolean removeDeadCode = false;

    /**
     * @return true if dead code removal has been enabled.
     */
    public boolean getRemoveDeadCode()
    {
        return this.removeDeadCode;
    }

    /**
     * Enable or disable dead code removal.
     * 
     * @param cfgval the configuration value context.
     * @param b true to enable dead code removal, false to disable.
     */
    @Config(advanced = true)
    @Mapping({ "compiler", "remove-dead-code" })
    public void setRemoveDeadCode(ConfigurationValue cfgval, boolean b)
    {
        this.removeDeadCode = b;
    }

    //
    // Validation methods from ToolsConfiguration
    //

    void validateDumpConfig(ConfigurationBuffer configurationBuffer) throws ConfigurationException
    {
        if (dumpConfigFile != null)
        {
            final String text = FileConfigurator.formatBuffer(configurationBuffer, "flex-config",
                    LocalizationManager.get(), "flex2.configuration");
            try
            {
                final Writer writer = new FileWriter(dumpConfigFile);
                IOUtils.write(text, writer);
                IOUtils.closeQuietly(writer);
            }
            catch (IOException e)
            {
                throw new ConfigurationException.IOError(dumpConfigFile);
            }
        }
    }

    /**
     * Collection of fatal and non-fatal configuration problems.
     */
    private Collection<ICompilerProblem> configurationProblems = new ArrayList<ICompilerProblem>();

    /**
     * Get the configuration problems. This should be called after the configuration has been processed.
     * 
     * @return a collection of fatal and non-fatal configuration problems.
     */
    public Collection<ICompilerProblem> getConfigurationProblems()
    {
        return configurationProblems;
    }

    private boolean warnOnFlexOnlyOptionUsage = false;

    /**
     * @return True if warnings are generated when "Flex only" options are used, false otherwise.
     */
    public boolean getWarnOnFlexOnlyOptionUsage()
    {
        return warnOnFlexOnlyOptionUsage;
    }

    /**
     * Controls if the compiler warns when "Flex only" configuration options are used in the compiler.
     * 
     * @param value True to enable warnings, false to disable warnings. The default is to not warn.
     */
    public void setWarnOnFlexOnlyOptionUsage(boolean value)
    {
        this.warnOnFlexOnlyOptionUsage = value;
    }

    private boolean enableTelemetry = false;

    /**
     *
     * @return True if telemetry is enabled, false otherwise.
     */
    public boolean isEnableTelemetry()
    {
        return enableTelemetry;
    }

    /**
     * Controls if the flash runtime should allow providing advanced telemetry options to external tools.
     *
     * @param enableTelemetry True to enable telemetry, false to disable. The default ist to disable.
     */
    public void setEnableTelemetry(boolean enableTelemetry)
    {
        this.enableTelemetry = enableTelemetry;
    }

    /**
     * Turns on the advanced telemetry options of the flash runtime to allow clients like scout to connect.
     *
     * Remark: Internally and in the spec this option is called "enable telemetry" but by tools and the commandline it's
     * referenced by advanced-telemetry.
     */
    @Config(advanced = true)
    @Mapping({ "compiler", "advanced-telemetry" })
    @FlexOnly
    public void setEnableTelemetry(ConfigurationValue cv, boolean enableTelemetry) throws CannotOpen
    {
        this.enableTelemetry = enableTelemetry;
    }

    private void processDeprecatedAndRemovedOptions(ConfigurationBuffer configurationBuffer)
    {
        for (final String var : configurationBuffer.getVars())
        {
            ConfigurationInfo info = configurationBuffer.getInfo(var);
            List<ConfigurationValue> values = configurationBuffer.getVar(var);
            if (values != null)
            {
                for (final ConfigurationValue cv : values)
                {
                    if (info.isRemoved())
                    {
                        //addRemovedConfigurationOptionProblem(cv);
                    }
                    else if (info.isDeprecated() && configurationBuffer.getVar(var) != null)
                    {
                        String replacement = info.getDeprecatedReplacement();
                        String since = info.getDeprecatedSince();
                        DeprecatedConfigurationOptionProblem problem = new DeprecatedConfigurationOptionProblem(var,
                                replacement, since, cv.getSource(), cv.getLine());
                        configurationProblems.add(problem);
                    }
                    else if (warnOnFlexOnlyOptionUsage && info.isFlexOnly())
                    {
                        FlexOnlyConfigurationOptionNotSupported problem = new FlexOnlyConfigurationOptionNotSupported(
                                var, cv.getSource(), cv.getLine());
                        configurationProblems.add(problem);
                    }
                }
            }
        }
    }

    /**
     * Add a RemovedConfigurationOptionProblem to the list of configuration problems.
     * 
     * @param cv
     */
    private void addRemovedConfigurationOptionProblem(ConfigurationValue cv)
    {
        RemovedConfigurationOptionProblem problem = new RemovedConfigurationOptionProblem(cv.getVar(), cv.getSource(),
                cv.getLine());
        configurationProblems.add(problem);
    }

    private boolean strictXML = false;

    /**
     *
     * @return True if strictXML is enabled, false otherwise.
     */
    public boolean isStrictXML()
    {
        return strictXML;
    }

    /**
     * Controls if the compiler should try to resolve XML methods.  Enabling this makes it
     * possible to write new XML implementations but causes more warnings.  Default is false.
     *
     * @param strictXML True to enable strict XML checking, false to disable. The default is to disable.
     */
    public void setStrictXML(boolean strictXML)
    {
        this.strictXML = strictXML;
    }

    /**
     * Turns on the strict XML checking in the compiler.  Enabling this makes it
     * possible to write new XML implementations but causes more warnings.
     *
     */
    @Config(advanced = true)
    @Mapping({ "compiler", "strict-xml" })
    @FlexOnly
    public void setStrictXML(ConfigurationValue cv, boolean strictXML) throws CannotOpen
    {
        this.strictXML = strictXML;
    }

}
