/*
 *
 *  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 flex2.tools.oem.internal;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;

import macromedia.asc.embedding.ConfigVar;
import macromedia.asc.util.ObjectList;
import flex2.compiler.common.CompilerConfiguration;
import flex2.compiler.common.FontsConfiguration;
import flex2.compiler.common.FramesConfiguration;
import flex2.compiler.common.NamespacesConfiguration;
import flex2.compiler.common.RuntimeSharedLibrarySettingsConfiguration;
import flex2.compiler.common.Configuration.RslPathInfo;
import flex2.compiler.common.FramesConfiguration.FrameInfo;
import flex2.compiler.config.ConfigurationBuffer;
import flex2.compiler.io.FileUtil;
import flex2.compiler.io.LocalFile;
import flex2.compiler.io.VirtualFile;
import flex2.tools.LicensesConfiguration;
import flex2.tools.ToolsConfiguration;
import flex2.tools.oem.Configuration;

/**
 * A ToolsConfiguration wrapper, which provides strongly typed
 * configuration getters and setters, which internally storing them
 * loosely typed for later processing.  This is part of a complex
 * scheme to only expose some of the compiler's configurability while
 * supporting merging with configuration defaults.
 *
 * @version 2.0.1
 * @author Clement Wong
 */
public class OEMConfiguration implements Configuration, ConfigurationConstants, Cloneable
{
	/**
	 *  Created to enable picking out cross-domain args by type.
	 */
	class RslPathList extends ArrayList<String[]>
    {
		private static final long serialVersionUID = 0L;
	}
	
    /**
     *  Ditto for conditional compilation
     */
    class CompilerDefinitionList extends ArrayList<String>
    {
        private static final long serialVersionUID = 0L;
    }
	
    /**
     *  Ditto for application-domains
     */
    class ApplicationDomainsList extends ArrayList<String[]>
    {
        private static final long serialVersionUID = 0L;
    }
    
	OEMConfiguration(ConfigurationBuffer cfgbuf, ToolsConfiguration configuration)
	{
		this.cfgbuf = cfgbuf;
		this.configuration = configuration;
		
		args = new LinkedHashMap<String, Object>();
		more = new LinkedHashMap<String, Object>();
		linker_args = new LinkedHashMap<String, Object>();
		linker_more = new LinkedHashMap<String, Object>();
		newLinkerOptionsAfterCompile = new HashSet<String>();
		
		if (configuration != null)
		{
			populateDefaults(configuration);
		}
		
		defaults = args;
		args = new LinkedHashMap<String, Object>();
		linker_args = new LinkedHashMap<String, Object>();
		newLinkerOptionsAfterCompile.clear();
		
		keepLinkReport = false;
		keepSizeReport = false;
		keepConfigurationReport = false;
		
		tokens = new TreeMap<String, String>();
	}

	public ConfigurationBuffer cfgbuf;
	public final ToolsConfiguration configuration;
	
	private Map<String, Object> args, defaults, more, linker_args, linker_more;
	private String[] extras;
	public final Set<String> newLinkerOptionsAfterCompile;
	private boolean keepLinkReport, keepSizeReport, keepConfigurationReport;
	
	private Map<String, String> tokens;

	/**
	 * 
	 * @param c
	 */
	void importDefaults(OEMConfiguration c)
	{
		args.putAll(c.defaults);
	}
	
	/**
	 * 
	 * @return
	 */
	public String[] getCompilerOptions()
	{
		return getOptions(args, more, true);
	}
	
	/**
	 * 
	 * @return
	 */
	public String[] getLinkerOptions()
	{
		return getOptions(linker_args, linker_more, false);
	}
	
	/**
	 * 
	 * @return
	 */
    
    //TEST ME
	private String[] getOptions(Map<String, Object> args, Map<String, Object> more, boolean processExtras)
	{
		ArrayList<String> buffer = new ArrayList<String>();
		
        //TODO this can be optimized to use the entrySet
		for (Iterator<String> i = tokens.keySet().iterator(); i.hasNext(); )
		{
			String key = i.next();
			String value = tokens.get(key);
			buffer.add("+" + key + "=" + value);
		}
		
		for (Iterator<String> i = args.keySet().iterator(); i.hasNext(); )
		{
			String key = (String) i.next();
			Object value = args.get(key);

			if (value instanceof Boolean)
			{
				buffer.add(key + "=" + value);
			}
			else if (value instanceof Number)
			{
				buffer.add(key);
				buffer.add(value.toString());
			}
			else if (COMPILER_CONTEXT_ROOT.equals(key) && value instanceof String)
			{				
				buffer.add(key);
				buffer.add((String)value);
			}
			else if (value instanceof String)
			{				
				if (!"".equals(value))
				{
					buffer.add(key);
					buffer.add((String)value);
				}
				else
				{
					buffer.add(key + "=");
				}
			}
			else if (value instanceof File)
			{
				String p = ((File) value).getPath();
				if (!"".equals(p))
				{
					buffer.add(key);
					buffer.add(p);
				}
				else
				{
					buffer.add(key + "=");
				}
			}
			else if (value instanceof URL)
			{
				String u = ((URL) value).toExternalForm();
				if (!"".equals(u))
				{
					buffer.add(key);
					buffer.add(u);
				}
				else
				{
					buffer.add(key + "=");
				}
			}
			else if (value instanceof java.util.Date)
			{
				buffer.add(key);
				buffer.add(value.toString());
			}
			else if (value instanceof Map)
			{
				Map m = (Map) value;
				for (Iterator j = m.keySet().iterator(); j.hasNext(); )
				{
					String k = (String) j.next();
					Object v = m.get(k);
					
					if (v instanceof String)
					{
						buffer.add(key);
						buffer.add(k);
						buffer.add((String)v);
					}
					else if (v instanceof File)
					{
						buffer.add(key);
						buffer.add(k);
						buffer.add(((File) v).getPath());
					}
					else if (v instanceof String[])
					{
						buffer.add(key);
						buffer.add(k);
						buffer.add(toCommaSeparatedString((String[]) v));
					}
					else if (v instanceof List)
					{
						buffer.add(key);
						buffer.add(k);
						Iterator it = ((List)v).iterator();
						while (it.hasNext())
						{
							Object next = it.next();
							if (next != null)
								buffer.add(next.toString());
						}
					}
					else if (v != null)
					{
						assert false;
					}
				}
			}
			else if (value instanceof int[])
			{
				int[] a = (int[]) value;
				buffer.add(key);
				buffer.add(String.valueOf(a[0]));
				buffer.add(String.valueOf(a[1]));
			}
			else if (value instanceof String[])
			{
				String[] a = merge((String[]) args.get(key), (String[]) more.get(key));
				int length = a == null ? 0 : a.length;
				if (length > 0)
				{
					buffer.add(key);
				}
				else
				{
					buffer.add(key + "=");
				}
				for (int j = 0; j < length; j++)
				{
					if (a[j] != null)
					{
						buffer.add(a[j]);
					}
				}
			}
			else if (LOAD_CONFIG.equals(key) && value instanceof File[])
			{
				File[] a = merge((File[]) args.get(key), (File[]) more.get(key));
				for (int j = 0, length = a == null ? 0 : a.length; j < length; j++)
				{
					if (a[j] != null)
					{
						buffer.add(key);
						buffer.add(a[j].getPath());
					}
				}
			}
			else if (value instanceof File[])
			{
				File[] a = merge((File[]) args.get(key), (File[]) more.get(key));
				int length = a == null ? 0 : a.length;
				if (length > 0)
				{
					buffer.add(key);
				}
				else
				{
					buffer.add(key + "=");
				}
				for (int j = 0; j < length; j++)
				{
					if (a[j] != null)
					{
						buffer.add(a[j].getPath());
					}
				}
			}
			else if (value instanceof URL[])
			{
				URL[] a = merge((URL[]) args.get(key), (URL[]) more.get(key));
				int length = a == null ? 0 : a.length;
				if (length > 0)
				{
					buffer.add(key);
				}
				else
				{
					buffer.add(key + "=");
				}
				for (int j = 0; j < length; j++)
				{
					if (a[j] != null)
					{
						buffer.add(a[j].toExternalForm());
					}
				}
			}
			else if (value instanceof RslPathList)
			{
				RslPathList valueList = (RslPathList)value;
				for (Iterator<String[]> iter = valueList.iterator(); iter.hasNext();) 
				{
					StringBuilder sb = new StringBuilder(RUNTIME_SHARED_LIBRARY_PATH);
					sb.append("=");
					String[] cdArgs = iter.next();
					sb.append(cdArgs[0]);
					for (int j = 1; j < cdArgs.length; j++)
					{
						sb.append(",");
						sb.append(cdArgs[j]);
					}
					buffer.add(sb.toString());
				}
			}
            else if (value instanceof CompilerDefinitionList)
            {
                final CompilerDefinitionList defs = (CompilerDefinitionList)value;
                for (Iterator<String> iter = defs.iterator(); iter.hasNext();)
                {
                    // String.valueOf will help turn null into "null"
                    String name = String.valueOf(iter.next());
                    String val  = String.valueOf(iter.next());
                    
                    // handle empty-string values
                    
                    // technically, name should not ever be empty length (value can be),
                    // but we don't want to do error handling, CompilerConfiguration.cfgDefine()
                    // will do it for us later
                    if (name.length() == 0)
                    {
                        name = "\"\"";
                    }
                    
                    if (val.length() == 0)
                    {
                        val = "\"\"";
                    }
                    
                    /* note '+=': defines from all flex-config.xmls will be collected (just '=' would
                     * always ignore all but the most recent definitions), hopefully in a meaningful
                     * order (flex-config, user-config, commandline) since we now allow re-definitions.
                     */
                    buffer.add(COMPILER_DEFINE + "+=" + name + "," + val);
                }
            }
            else if (value instanceof ApplicationDomainsList)
            {
                ApplicationDomainsList valueList = (ApplicationDomainsList)value;
                
                if (valueList.size() == 0)
                    buffer.add(key + "=");  // we should only ever come here for the first and only key.
                else
                    buffer.add(key);
                
                for (String[] adArgs : valueList) 
                {
                    for (int j = 0; j < adArgs.length; j++)
                    {
                        buffer.add(adArgs[j]);
                    }
                }
            }
			else if (value != null)
			{
				assert false;
			}
			else
			{
				// System.err.println("unprocessed compiler options: " + key + "=" + value);
			}
		}
		
		for (Iterator<String> i = more.keySet().iterator(); i.hasNext(); )
		{
			String key = (String) i.next();
			Object value = more.get(key);

			if (value instanceof String[])
			{
				if (!args.containsKey(key))
				{
					buffer.add(key + "+=" + toCommaSeparatedString((String[]) value));
				}
			}
			/*
			else if (LOAD_CONFIG.equals(key) && value instanceof File[])
			{
				if (!args.containsKey(key))
				{
					File[] a = merge(null, (File[]) more.get(key));
					for (int j = 0, length = a == null ? 0 : a.length; j < length; j++)
					{
						if (a[j] != null)
						{
							buffer.add(key);
							buffer.add(a[j].getPath());
						}
					}
				}
			}
			*/
			else if (value instanceof File[])
			{
				if (!args.containsKey(key))
				{
					buffer.add(key + "+=" + toCommaSeparatedString((File[]) value));
				}
			}
			else if (value instanceof URL[])
			{
				if (!args.containsKey(key))
				{
					buffer.add(key + "+=" + toCommaSeparatedString((URL[]) value));
				}
			}
			else if (value instanceof Map)
			{
				Map m = (Map) value;
				for (Iterator j = m.keySet().iterator(); j.hasNext(); )
				{
					String k = (String) j.next();
					Object v = m.get(k);
					
					if (v instanceof List)
					{
						Iterator it = ((List)v).iterator();
						while (it.hasNext())
						{
							Object next = it.next();
							if (next != null)
                                buffer.add(key + "+=" + k + "," + next.toString());
						}
					}
					else if (v != null)
					{
						assert false;
					}
				}
			}
			else if (value instanceof Map)
			{
				Map m = (Map) value;
				for (Iterator j = m.keySet().iterator(); j.hasNext(); )
				{
					String k = (String) j.next();
					Object v = m.get(k);
					
					if (v instanceof List)
					{
						Iterator it = ((List)v).iterator();
						while (it.hasNext())
						{
							Object next = it.next();
							if (next != null)
                                buffer.add(key + "+=" + k + "," + next.toString());
						}
					}
					else if (v != null)
					{
						assert false;
					}
				}
			}
			else if (value != null)
			{
				assert false;
			}
			else
			{
				// System.err.println("unprocessed compiler options: " + key + "=" + value);
			}
		}

		for (int i = 0, length = extras == null ? 0 : extras.length; processExtras && i < length; i++)
		{
			if (extras[i] != null)
			{
				buffer.add(extras[i]);
			}
		}
		
		String[] options = new String[buffer.size()];
		buffer.toArray(options);
		
		return options;
	}
	
	/**
	 * Enables accessibility in the application.
	 * This is equivalent to using <code>mxmlc/compc --compiler.accessible</code>.<p>
	 * By default, this is disabled.
	 * 
	 * @param b boolean value
	 */
	public void enableAccessibility(boolean b)
	{
		args.put(COMPILER_ACCESSIBLE, b ? Boolean.TRUE : Boolean.FALSE);
		linker_args.put(COMPILER_ACCESSIBLE, b ? Boolean.TRUE : Boolean.FALSE);
		newLinkerOptionsAfterCompile.add(COMPILER_ACCESSIBLE);
	}
	
	/**
	 * Sets the ActionScript file encoding. The compiler will use this encoding to read
	 * the ActionScript source files.
	 * This is equivalent to using <code>mxmlc/compc --compiler.actionscript-file-encoding</code>.<p>
	 * By default, the encoding is <code>UTF-8</code>.
	 * 
	 * @param encoding charactere encoding, e.g. <code>UTF-8</code>, <code>Big5</code>
	 */
	public void setActionScriptFileEncoding(String encoding)
	{
		args.put(COMPILER_ACTIONSCRIPT_FILE_ENCODING, encoding);
	}
	
	/**
	 * Allows some source path directories to be subdirectories of the other.
	 * This is equivalent to using <code>mxmlc/compc --compiler.allow-source-path-overlap</code>.<p>
	 * By default, this is disabled.<p>
	 * 
	 * In some J2EE settings, directory overlapping should be allowed. For example,
	 * 
	 * <pre>
	 * wwwroot/MyAppRoot
	 * wwwroot/WEB-INF/flex/source_path1
	 * </pre>
	 * 
	 * @param b boolean value
	 */
	public void allowSourcePathOverlap(boolean b)
	{
		args.put(COMPILER_ALLOW_SOURCE_PATH_OVERLAP, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
	 * Uses the ActionScript 3 class based object model for greater performance and better error reporting.
	 * In the class based object model, most built-in functions are implemented as fixed methods of classes.
	 * This is equivalent to using <code>mxmlc/compc --compiler.as3</code>.<p>
	 * By default, this is enabled.
	 * 
	 * @param b boolean value
	 */
	public void useActionScript3(boolean b)
	{
		args.put(COMPILER_AS3, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
     * Sets the context root path so that the compiler can replace <code>{context.root}</code> tokens for
     * service channel endpoints. This is equivalent to using the <code>compiler.context-root</code> option
     * for the mxmlc or compc compilers.
     * 
     * <p>
     * By default, this value is undefined.
     * 
     * @param path An instance of String.
	 */
	public void setContextRoot(String path)
	{
		args.put(COMPILER_CONTEXT_ROOT, path);
	}

	/**
	 * Enables debugging in the application.
	 * This is equivalent to using <code>mxmlc/compc --compiler.debug</code> and <code>--debug-password</code>.<p>
	 * By default, debug is <code>false</code> and the debug password is "".
	 * 
	 * @param b boolean value
	 * @param debugPassword a password that is embedded in the application.
	 */
	public void enableDebugging(boolean b, String debugPassword)
	{
		args.put(COMPILER_DEBUG, b ? Boolean.TRUE : Boolean.FALSE);
		args.put(DEBUG_PASSWORD, debugPassword);
		
		linker_args.put(COMPILER_DEBUG, b ? Boolean.TRUE : Boolean.FALSE);
		linker_args.put(DEBUG_PASSWORD, debugPassword);
		
		newLinkerOptionsAfterCompile.add(COMPILER_DEBUG);
		newLinkerOptionsAfterCompile.add(DEBUG_PASSWORD);
	}

	/**
	 * Sets the location of the default CSS file.
	 * This is equivalent to using <code>mxmlc/compc --compiler.defaults-css-url</code>.
	 * 
	 * @param url an instance of <code>java.io.File</code>.
	 */
	public void setDefaultCSS(File url)
	{
		args.put(COMPILER_DEFAULTS_CSS_URL, url);
	}
	
	/**
	 * Uses the ECMAScript edition 3 prototype based object model to allow dynamic overriding
	 * of prototype properties. In the prototype based object model built-in functions are
	 * implemented as dynamic properties of prototype objects.
	 * This is equivalent to using <code>mxmlc/compc --compiler.es</code>.<p>
	 * By default, this is disabled.
	 * 
	 * @param b boolean value
	 */
	public void useECMAScript(boolean b)
	{
		args.put(COMPILER_ES, b ? Boolean.TRUE : Boolean.FALSE);
	}

	/**
	 * Sets the list of SWC files or directories to compile against but to omit from linking.
	 * This is equivalent to using <code>mxmlc/compc --compiler.external-library-path</code>.
	 * 
	 * @param paths <code>File.isDirectory()</code> should return <code>true</code> or <code>File</code> instances should represent SWC files.
	 */
	public void setExternalLibraryPath(File[] paths)
	{
		args.put(COMPILER_EXTERNAL_LIBRARY_PATH, paths);
		more.remove(COMPILER_EXTERNAL_LIBRARY_PATH);
	}

	/**
	 * Adds to the existing list of SWC files.
	 * 
	 * @see #setExternalLibraryPath(File[])
	 * @param paths <code>File.isDirectory()</code> should return <code>true</code> or <code>File</code> instances should represent SWC files.
	 */
	public void addExternalLibraryPath(File[] paths)
	{
		addFiles(COMPILER_EXTERNAL_LIBRARY_PATH, paths);
	}

	/**
	 * Sets a range to restrict the number of font glyphs embedded into the application.
	 * This is equivalent to using <code>mxmlc/compc --compiler.fonts.languages.language-range</code>.
	 * For example,
	 * 
	 * <pre>
	 * setFontLanguageRange("englishRange", "U+0020-U+007E");
	 * </pre>
	 * 
	 * @param language language name
	 * @param range a range of glyphs
	 */
    public void setFontLanguageRange(String language, String range)
	{
		if (!args.containsKey(COMPILER_FONTS_LANGUAGES_LANGUAGE_RANGE))
		{
			args.put(COMPILER_FONTS_LANGUAGES_LANGUAGE_RANGE, new TreeMap<String, String>());
		}
		
        // I am ONLY doing this because we set it three lines above
		@SuppressWarnings("unchecked")
		Map<String, String> map = (Map<String, String>) args.get(COMPILER_FONTS_LANGUAGES_LANGUAGE_RANGE);
		map.put(language, range);
	}
	
	/**
	 * Sets the location of the local font snapshot file. The file contains system font data produced by
	 * <code>flex2.tools.FontSnapshot</code>. This is equivalent to using <code>mxmlc/compc --compiler.fonts.local-fonts-snapshot</code>.
	 * 
	 * @param file file
	 */
	public void setLocalFontSnapshot(File file)
	{
		args.put(COMPILER_FONTS_LOCAL_FONTS_SNAPSHOT, file);
	}

   /**
     * Sets the local font file paths to be searched by the compiler.
     * This is equivalent to using <code>mxmlc/compc --compiler.fonts.local-font-paths</code>.
     * 
     * @param paths an array of file paths.
     */
    public void setLocalFontPaths(String[] paths)
    {
        args.put(COMPILER_FONTS_LOCAL_FONT_PATHS, paths);
        more.remove(COMPILER_FONTS_LOCAL_FONT_PATHS);
    }

    /**
     * Adds local font paths to the existing local font path list.
     * 
     * @see #setLocalFontPaths(String[])
     * @param paths an array of local font file paths.
     */
    public void addLocalFontPaths(String[] paths)
    {
        addStrings(COMPILER_FONTS_LOCAL_FONT_PATHS, paths);
    }

	/**
	 * Sets the font managers used by the compiler.
	 * This is equivalent to using <code>mxmlc/compc --compiler.fonts.managers</code>.
	 * 
	 * @param classNames an array of Java class names.
	 */
	public void setFontManagers(String[] classNames)
	{
		args.put(COMPILER_FONTS_MANAGERS, classNames);
		more.remove(COMPILER_FONTS_MANAGERS);
	}
	
	/**
	 * Adds font managers to the existing font manager list.
	 * 
	 * @see #setFontManagers(String[])
	 * @param classNames an array of Java class names.
	 */
	public void addFontManagers(String[] classNames)
	{
		addStrings(COMPILER_FONTS_MANAGERS, classNames);
	}
	
	/**
	 * Sets the maximum number of embedded font faces that can be cached.
	 * This is equivalent to using <code>mxmlc/compc --compiler.fonts.max-cached-fonts</code>.
	 * By default, it's 20.
	 * 
	 * @param size an integer
	 */
	public void setMaximumCachedFonts(int size)
	{
		if (size > 0)
		{
			args.put(COMPILER_FONTS_MAX_CACHED_FONTS, new Integer(size));
		}
	}
	
	/**
	 * Sets the maximum number of character glyph outlines to cache for each font face.
	 * This is equivalent to using <code>mxmlc/compc --compiler.fonts.max-glyphs-per-face</code>.
	 * By default, it's 1000.
	 *  
	 * @param size an integer
	 */
	public void setMaximumGlyphsPerFace(int size)
	{
		if (size > 0)
		{
			args.put(COMPILER_FONTS_MAX_GLYPHS_PER_FACE, new Integer(size));
		}
	}
	
	/**
	 * Sets the compiler when it runs on a server without a display.
	 * This is equivalent to using <code>mxmlc/compc --compiler.headless-server</code>.
	 * 
	 * @param b boolean value
	 */
	public void useHeadlessServer(boolean b)
	{
		args.put(COMPILER_HEADLESS_SERVER, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
	 * Sets the AS3 metadata the compiler should keep in the SWF.
	 * This is equivalent to using <code>mxmlc --compiler.keep-as3-metadata</code>.
	 * 
	 * <p>
	 * The default value is <code>{Bindable, Managed, ChangeEvent, NonCommittingChangeEvent, Transient}</code>.
	 * 
	 * @param md an array of AS3 metadata names
	 */
	public void setActionScriptMetadata(String[] md)
	{
		args.put(COMPILER_KEEP_AS3_METADATA, md);
		more.remove(COMPILER_KEEP_AS3_METADATA);
		
		linker_args.put(COMPILER_KEEP_AS3_METADATA, md);
		linker_more.remove(COMPILER_KEEP_AS3_METADATA);
		
		newLinkerOptionsAfterCompile.add(COMPILER_KEEP_AS3_METADATA);
	}
	
	/**
	 * Adds the list of AS3 metadata names to the existing list of AS3 metadata the compiler should
	 * keep in the SWF.
	 * 
	 * @param md an array of AS3 metadata names
	 */
	public void addActionScriptMetadata(String[] md)
	{
		addStrings(COMPILER_KEEP_AS3_METADATA, md);
		addStrings(linker_more, COMPILER_KEEP_AS3_METADATA, md);

		newLinkerOptionsAfterCompile.add(COMPILER_KEEP_AS3_METADATA);
	}

	/**
	 * Disables the pruning of unused type selectors.
	 * This is equivalent to using <code>mxmlc/compc --compiler.keep-all-type-selectors</code>.
	 * By default, it is set to <code>false</code>.
	 * 
	 * @param b boolean value
	 */
	public void keepAllTypeSelectors(boolean b)
	{
		args.put(COMPILER_KEEP_ALL_TYPE_SELECTORS, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
	 * Saves temporary source files generated during MXML compilation.
	 * This is equivalent to using <code>mxmlc/compc --compiler.keep-generated-actionscript</code>.
	 * By default, it is set to <code>false</code>.
	 * 
	 * @param b boolean value
	 */
	public void keepCompilerGeneratedActionScript(boolean b)
	{
		args.put(COMPILER_KEEP_GENERATED_ACTIONSCRIPT, b ? Boolean.TRUE : Boolean.FALSE);
	}

	/**
	 * Instructs the linker to keep a report of the content that is included in the application.
	 * Callers may use <code>Report.writeLinkReport()</code> to retrieve the linker report.
	 * 
	 * @param b boolean value
	 */
	public void keepLinkReport(boolean b)
	{
		keepLinkReport = b;
		newLinkerOptionsAfterCompile.add(LINK_REPORT);
	}
	
	public boolean keepLinkReport()
	{
		return keepLinkReport;
	}
	
	/**
	 * Instructs the linker to keep a SWF size report.
	 * Callers may use <code>Report.writeSizeReport()</code> to retrieve the size report.
	 * 
	 * @param b boolean value
	 */
	public void keepSizeReport(boolean b)
	{
		keepSizeReport = b;
		newLinkerOptionsAfterCompile.add(SIZE_REPORT);
	}
	
	public boolean keepSizeReport()
	{
		return keepSizeReport;
	}
	
	/**
	 * Instructs the compiler to keep a report of the compiler configuration settings.
	 * Callers may use <code>Report.writeConfigurationReport()</code> to retrieve the configuration report.
	 * 
	 * @param b boolean value
	 */
	public void keepConfigurationReport(boolean b)
	{
		keepConfigurationReport = b;
	}
	
	public boolean keepConfigurationReport()
	{
		return keepConfigurationReport;
	}

	
	/**
	 * Includes a list of libraries (SWCs) to completely include in the application
	 * This is equivalent to using <code>mxmlc/compc --compiler.include-libraries</code>.
	 * 
	 * @param libraries an array of <code>java.io.File</code> (<code>File.isDirectory()</code> should return <code>true</code> or instances must represent SWC files).
	 * @see #setIncludes(String[])
	 * @see #setExterns(File[])
	 * @see #setExterns(String[])
	 * @see #setExternalLibraryPath(File[])
	 */
	public void includeLibraries(File[] libraries)
	{
		args.put(COMPILER_INCLUDE_LIBRARIES, libraries);
	}

    /**
     * Sets a list of resource bundles to include in the swf.
     * This is equivalent to using <code>mxmlc/compc --include-resource-bundle</code>.
     * 
     * @param bundles an array of <code>java.lang.String</code>
    */
    public void setIncludeResourceBundles(String[] bundles)
    {
        args.put(INCLUDE_RESOURCE_BUNDLES, bundles);        
    }   

    /**
     * Adds a list of resource bundles to the existing list.
     * 
     * @see #setIncludeResourceBundles(String[])
     * @param bundles an array of <code>java.lang.String</code>
     */
    public void addIncludeResourceBundles(String[] bundles)
    {
        addStrings(INCLUDE_RESOURCE_BUNDLES, bundles);
    }
    
    /**
	 * Sets a list of SWC files or directories that contain SWC files.
	 * This is equivalent to using <code>mxmlc/compc --compiler.library-path</code>.
	 * 
	 * @param paths an array of <code>File</code>. <code>File.isDirectory()</code> should return <code>true</code> or instances must represent SWC files.
	 */
	public void setLibraryPath(File[] paths)
	{
		args.put(COMPILER_LIBRARY_PATH, paths);
		more.remove(COMPILER_LIBRARY_PATH);
	}

	/**
	 * Adds a list of SWC files or directories to the default library path.
	 * 
	 * @param paths an array of <code>File</code>. <code>File.isDirectory()</code> should return <code>true</code> or instances must represent SWC files.
	 * @see #setLibraryPath(File[])
	 */
	public void addLibraryPath(File[] paths)
	{
		addFiles(COMPILER_LIBRARY_PATH, paths);
	}
	
	public void setTargets(String[] targets)
	{
		args.put(COMPILER_TARGETS, targets);
	}
	
	/**
	 * Sets the locales that the compiler would use to replace <code>{locale}</code> tokens that appear in some configuration values.
	 * This is equivalent to using <code>mxmlc/compc --compiler.locale</code>.
	 * For example,
	 * 
	 * <pre>
	 * addSourcePath(new File[] { "locale/{locale}" });
	 * addLocale(new String[] { "en_US" });
	 * </pre>
	 * 
	 * The <code>locale/en_US</code> directory will be added to the source path.
	 *
	 * @param locale String
	 * 
	 * @since 3.0
	 */
	public void setLocale(String[] locales)
	{
		args.put(COMPILER_LOCALE, locales);
	}
	
	/**
	 * Sets the locale that the compiler would use to replace <code>{locale}</code> tokens that appear in some configuration values.
	 * This is equivalent to using <code>mxmlc/compc --compiler.locale</code> to set a single locale.
	 * For example,
	 * 
	 * <pre>
	 * addSourcePath(new File[] { "locale/{locale}" });
	 * setLocale(Locale.US);
	 * </pre>
	 * 
	 * The <code>locale/en_US</code> directory will be added to the source path.
	 *
	 * @param locale java.util.Locale
	 * 
	 * @deprecated As of 3.0, use setLocale(String[])
	 */
	public void setLocale(Locale locale)
	{
		setLocale(new String[] { locale.toString() });
	}

    /**
     * Specifies a URI to associate with a manifest of components for use as
     * MXML elements. This is equivalent to using:
     * <code>mxmlc/compc --compiler.namespaces.namespace</code>.
     * 
     * @param namespaceURI a namespace URI
     * @param manifest a component manifest file (XML)
     */
    public void setComponentManifest(String namespaceURI, File manifest)
    {
        List<File> manifests = new ArrayList<File>(2);
        manifests.add(manifest);
        setComponentManifests(namespaceURI, manifests);
    }

    /**
     * Specifies a URI to associate with a list of potentially several manifests
     * which map MXML elements to component implementations. This is equivalent
     * to using: <code>mxmlc/compc --compiler.namespaces.namespace</code>.
     * 
     * @param namespaceURI a namespace URI
     * @param manifests A List of component manifest files (XML)
     */
    public void setComponentManifests(String namespaceURI, List<File> manifests)
    {
        if (!more.containsKey(COMPILER_NAMESPACES_NAMESPACE))
        {
            more.put(COMPILER_NAMESPACES_NAMESPACE, new LinkedHashMap<String, List<File>>());
        }

        // I am ONLY doing this because we set it three lines above
        @SuppressWarnings("unchecked")
        Map<String, List<File>> map = (Map<String, List<File>>) more.get(COMPILER_NAMESPACES_NAMESPACE);
        map.put(namespaceURI, manifests);
    }

	/**
	 * Enables post-link optimization. This is equivalent to using <code>mxmlc/compc --compiler.optimize</code>.
	 * Application sizes are usually smaller with this option enabled.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void optimize(boolean b)
	{
		args.put(COMPILER_OPTIMIZE, b ? Boolean.TRUE : Boolean.FALSE);
		linker_args.put(COMPILER_OPTIMIZE, b ? Boolean.TRUE : Boolean.FALSE);
		newLinkerOptionsAfterCompile.add(COMPILER_OPTIMIZE);
	}
	
	/**
	 * {@inheritDoc}
	 */
	public void compress(boolean b)
	{
        args.put(COMPILER_COMPRESS, b ? Boolean.TRUE : Boolean.FALSE);
        linker_args.put(COMPILER_COMPRESS, b ? Boolean.TRUE : Boolean.FALSE);
        newLinkerOptionsAfterCompile.add(COMPILER_COMPRESS);	    
	}

	/**
	 * Sets the location of the FDS service configuration file.
	 * This is equivalent to using <code>mxmlc/compc --compiler.services</code>
	 * @param file file
	 */
	public void setServiceConfiguration(File file)
	{
		args.put(COMPILER_SERVICES, file);
	}
	
	/**
	 * Runs the ActionScript compiler in a mode that detects legal but potentially incorrect code.
	 * This is equivalent to using <code>mxmlc/compc --compiler.show-actionscript-warnings</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 * @see #checkActionScriptWarning(int, boolean)
	 */
	public void showActionScriptWarnings(boolean b)
	{
		args.put(COMPILER_SHOW_ACTIONSCRIPT_WARNINGS, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
	 * Toggles whether warnings generated from data binding code are displayed.
	 * This is equivalent to using <code>mxmlc/compc --compiler.show-binding-warnings</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void showBindingWarnings(boolean b)
	{
		args.put(COMPILER_SHOW_BINDING_WARNINGS, b ? Boolean.TRUE : Boolean.FALSE);
	}

	/**
	 * Toggles whether the use of deprecated APIs generates a warning.
	 * This is equivalent to using <code>mxmlc/compc --compiler.show-deprecation-warnings</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void showDeprecationWarnings(boolean b)
	{
		args.put(COMPILER_SHOW_DEPRECATION_WARNINGS, b ? Boolean.TRUE : Boolean.FALSE);
	}

    /**
     * Toggles whether warnings are displayed when an embedded font name shadows
     * a device font name.
     * This is equivalent to using <code>mxmlc/compc --compiler.show-shadowed-device-font-warnings</code>.
     * By default, it is set to <code>true</code>.
     * 
     * @param b boolean value
     */
    public void showShadowedDeviceFontWarnings(boolean b)
    {
        args.put(COMPILER_SHOW_SHADOWED_DEVICE_FONT_WARNINGS, b ? Boolean.TRUE : Boolean.FALSE);
    }

	/**
	 * Toggles whether warnings generated from unused type selectors are displayed.
	 * This is equivalent to using <code>mxmlc/compc --compiler.show-unused-type-selector-warnings</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void showUnusedTypeSelectorWarnings(boolean b)
	{
		args.put(COMPILER_SHOW_UNUSED_TYPE_SELECTOR_WARNINGS, b ? Boolean.TRUE : Boolean.FALSE);
	}

	/**
	 * Sets a list of path elements that form the roots of ActionScript class hierarchies.
	 * This is equivalent to using <code>mxmlc/compc --compiler.source-path</code>.
	 * 
	 * @param paths an array of <code>java.io.File</code> (<code>File.isDirectory()</code> must return <code>true</code>).
	 */
	public void setSourcePath(File[] paths)
	{
		args.put(COMPILER_SOURCE_PATH, paths);
		more.remove(COMPILER_SOURCE_PATH);
	}

	/**
	 * Adds a list of path elements to the existing source path list.
	 * 
	 * @param paths an array of <code>java.io.File</code> (<code>File.isDirectory()</code> must return <code>true</code>).
	 * @see #setSourcePath(File[])
	 */
	public void addSourcePath(File[] paths)
	{
		addFiles(COMPILER_SOURCE_PATH, paths);
	}
	
	/**
	 * Runs the ActionScript compiler in strict error checking mode.
	 * This is equivalent to using <code>mxmlc/compc --compiler.strict</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void enableStrictChecking(boolean b)
	{
		args.put(COMPILER_STRICT, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
	 * Sets a list of CSS or SWC files to apply as a theme.
	 * This is equivalent to using <code>mxmlc/compc --compiler.theme</code>.
	 * 
	 * @param files an array of <code>java.io.File</code>
	 */
	public void setTheme(File[] files)
	{
		args.put(COMPILER_THEME, files);
		more.remove(COMPILER_THEME);
	}

	/**
	 * Adds a list of CSS or SWC files to the existing list of theme files.
	 * 
	 * @param files an array of <code>java.io.File</code>
	 * @see #setTheme(File[])
	 */
	public void addTheme(File[] files)
	{
		addFiles(COMPILER_THEME, files);
	}
    
	/**
	 * Determines whether resources bundles are included in the application.
	 * This is equivalent to using <code>mxmlc/compc --compiler.use-resource-bundle-metadata</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void useResourceBundleMetaData(boolean b)
	{
		args.put(COMPILER_USE_RESOURCE_BUNDLE_METADATA, b ? Boolean.TRUE : Boolean.FALSE);
	}
	
	/**
	 * Generates bytecodes that include line numbers. When a run-time error occurs,
	 * the stacktrace shows these line numbers. Enabling this option generates larger SWF files.
	 * This is equivalent to using <code>mxmlc/compc --compiler.verbose-stacktraces</code>.
	 * By default, it is set to <code>false</code>.
	 * 
	 * @param b boolean value
	 */
	public void enableVerboseStacktraces(boolean b)
	{
		args.put(COMPILER_VERBOSE_STACKTRACES, b ? Boolean.TRUE : Boolean.FALSE);
		linker_args.put(COMPILER_VERBOSE_STACKTRACES, b ? Boolean.TRUE : Boolean.FALSE);
		newLinkerOptionsAfterCompile.add(COMPILER_VERBOSE_STACKTRACES);
	}
	 
	/**
	 * Enables FlashType for embedded fonts, which provides greater clarity for small fonts.
	 * This is equilvalent to using <code>mxmlc/compc --compiler.fonts.flash-type</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void enableFlashType(boolean b)
	{
		args.put(COMPILER_FONTS_FLASH_TYPE, b ? Boolean.TRUE : Boolean.FALSE);
	}

	/**
	 * Enables advanced anti-aliasing for embedded fonts, which provides greater clarity for small fonts.
	 * This is equilvalent to using <code>mxmlc/compc --compiler.fonts.advanced-anti-aliasing</code>.
	 * By default, it is set to <code>false</code>.
	 * 
	 * @param b boolean value
	 */
	public void enableAdvancedAntiAliasing(boolean b)
	{
		args.put(COMPILER_FONTS_ADVANCED_ANTI_ALIASING, b ? Boolean.TRUE : Boolean.FALSE);
	}

    /**
     * Enables the removal of RSLs associated with libraries
     * that are not used by an application.
     * This is equivalent to using the
     * <code>remove-unused-rsls</code> option of the mxmlc compiler.
     * 
     * <p>
     * The default value is <code>false</code>.
     * 
     * @param b Boolean value that enables or disables the removal.
     *    
     * @since 4.5
     */
    public void removeUnusedRuntimeSharedLibraryPaths(boolean b)
    {
        args.put(REMOVE_UNUSED_RSLS, b ? Boolean.TRUE : Boolean.FALSE);
    }
	
	/**
	 * Enables checking of ActionScript warnings. They are:
	 * 
	 * <pre>
	 * --compiler.warn-array-tostring-changes
	 * --compiler.warn-assignment-within-conditional
	 * --compiler.warn-bad-array-cast
	 * --compiler.warn-bad-bool-assignment
	 * --compiler.warn-bad-date-cast
	 * --compiler.warn-bad-es3-type-method
	 * --compiler.warn-bad-es3-type-prop
	 * --compiler.warn-bad-nan-comparison
	 * --compiler.warn-bad-null-assignment
	 * --compiler.warn-bad-null-comparison
	 * --compiler.warn-bad-undefined-comparison
	 * --compiler.warn-boolean-constructor-with-no-args
	 * --compiler.warn-changes-in-resolve
	 * --compiler.warn-class-is-sealed
	 * --compiler.warn-const-not-initialized
	 * --compiler.warn-constructor-returns-value
	 * --compiler.warn-deprecated-event-handler-error
	 * --compiler.warn-deprecated-function-error
	 * --compiler.warn-deprecated-property-error
	 * --compiler.warn-duplicate-argument-names
	 * --compiler.warn-duplicate-variable-def
	 * --compiler.warn-for-var-in-changes
	 * --compiler.warn-import-hides-class
	 * --compiler.warn-instance-of-changes
	 * --compiler.warn-internal-error
	 * --compiler.warn-level-not-supported
	 * --compiler.warn-missing-namespace-decl
	 * --compiler.warn-negative-uint-literal
	 * --compiler.warn-no-constructor
	 * --compiler.warn-no-explicit-super-call-in-constructor
	 * --compiler.warn-no-type-decl
	 * --compiler.warn-number-from-string-changes
	 * --compiler.warn-scoping-change-in-this
	 * --compiler.warn-slow-text-field-addition
	 * --compiler.warn-unlikely-function-value
	 * --compiler.warn-xml-class-has-changed
	 * </pre>
	 * 
	 * @param warningCode warning code
	 * @param b boolean value
	 * @see #WARN_ARRAY_TOSTRING_CHANGES
	 * @see #WARN_ASSIGNMENT_WITHIN_CONDITIONAL
	 * @see #WARN_BAD_ARRAY_CAST
	 * @see #WARN_BAD_BOOLEAN_ASSIGNMENT
	 * @see #WARN_BAD_DATE_CAST
	 * @see #WARN_BAD_ES3_TYPE_METHOD
	 * @see #WARN_BAD_ES3_TYPE_PROP
	 * @see #WARN_BAD_NAN_COMPARISON
	 * @see #WARN_BAD_NULL_ASSIGNMENT
	 * @see #WARN_BAD_NULL_COMPARISON
	 * @see #WARN_BAD_UNDEFINED_COMPARISON
	 * @see #WARN_BOOLEAN_CONSTRUCTOR_WITH_NO_ARGS
	 * @see #WARN_CHANGES_IN_RESOLVE
	 * @see #WARN_CLASS_IS_SEALED
	 * @see #WARN_CONST_NOT_INITIALIZED
	 * @see #WARN_CONSTRUCTOR_RETURNS_VALUE
	 * @see #WARN_DEPRECATED_EVENT_HANDLER_ERROR
	 * @see #WARN_DEPRECATED_FUNCTION_ERROR
	 * @see #WARN_DEPRECATED_PROPERTY_ERROR
	 * @see #WARN_DUPLICATE_ARGUMENT_NAMES
	 * @see #WARN_DUPLICATE_VARIABLE_DEF
	 * @see #WARN_FOR_VAR_IN_CHANGES
	 * @see #WARN_IMPORT_HIDES_CLASS
	 * @see #WARN_INSTANCEOF_CHANGES
	 * @see #WARN_INTERNAL_ERROR
	 * @see #WARN_LEVEL_NOT_SUPPORTED
	 * @see #WARN_MISSING_NAMESPACE_DECL
	 * @see #WARN_NEGATIVE_UINT_LITERAL
	 * @see #WARN_NO_CONSTRUCTOR
	 * @see #WARN_NO_EXPLICIT_SUPER_CALL_IN_CONSTRUCTOR
	 * @see #WARN_NO_TYPE_DECL
	 * @see #WARN_NUMBER_FROM_STRING_CHANGES
	 * @see #WARN_SCOPING_CHANGE_IN_THIS
	 * @see #WARN_SLOW_TEXTFIELD_ADDITION
	 * @see #WARN_UNLIKELY_FUNCTION_VALUE
	 * @see #WARN_XML_CLASS_HAS_CHANGED
	 */
	public void checkActionScriptWarning(int warningCode, boolean b)
	{
		String key = null;
		
		switch (warningCode)
		{
		case WARN_ARRAY_TOSTRING_CHANGES:
			key = COMPILER_WARN_ARRAY_TOSTRING_CHANGES;
			break;
		case WARN_ASSIGNMENT_WITHIN_CONDITIONAL:
			key = COMPILER_WARN_ASSIGNMENT_WITHIN_CONDITIONAL;
			break;
		case WARN_BAD_ARRAY_CAST:
			key = COMPILER_WARN_BAD_ARRAY_CAST;
			break;
		case WARN_BAD_BOOLEAN_ASSIGNMENT:
			key = COMPILER_WARN_BAD_BOOL_ASSIGNMENT;
			break;
		case WARN_BAD_DATE_CAST:
			key = COMPILER_WARN_BAD_DATE_CAST;
			break;
		case WARN_BAD_ES3_TYPE_METHOD:
			key = COMPILER_WARN_BAD_ES3_TYPE_METHOD;
			break;
		case WARN_BAD_ES3_TYPE_PROP:
			key = COMPILER_WARN_BAD_ES3_TYPE_PROP;
			break;
		case WARN_BAD_NAN_COMPARISON:
			key = COMPILER_WARN_BAD_NAN_COMPARISON;
			break;
		case WARN_BAD_NULL_ASSIGNMENT:
			key = COMPILER_WARN_BAD_NULL_ASSIGNMENT;
			break;
		case WARN_BAD_NULL_COMPARISON:
			key = COMPILER_WARN_BAD_NULL_COMPARISON;
			break;
		case WARN_BAD_UNDEFINED_COMPARISON:
			key = COMPILER_WARN_BAD_UNDEFINED_COMPARISON;
			break;
		case WARN_BOOLEAN_CONSTRUCTOR_WITH_NO_ARGS:
			key = COMPILER_WARN_BOOLEAN_CONSTRUCTOR_WITH_NO_ARGS;
			break;
		case WARN_CHANGES_IN_RESOLVE:
			key = COMPILER_WARN_CHANGES_IN_RESOLVE;
			break;
		case WARN_CLASS_IS_SEALED:
			key = COMPILER_WARN_CLASS_IS_SEALED;
			break;
		case WARN_CONST_NOT_INITIALIZED:
			key = COMPILER_WARN_CONST_NOT_INITIALIZED;
			break;
		case WARN_CONSTRUCTOR_RETURNS_VALUE:
			key = COMPILER_WARN_CONSTRUCTOR_RETURNS_VALUE;
			break;
		case WARN_DEPRECATED_EVENT_HANDLER_ERROR:
			key = COMPILER_WARN_DEPRECATED_EVENT_HANDLER_ERROR;
			break;
		case WARN_DEPRECATED_FUNCTION_ERROR:
			key = COMPILER_WARN_DEPRECATED_FUNCTION_ERROR;
			break;
		case WARN_DEPRECATED_PROPERTY_ERROR:
			key = COMPILER_WARN_DEPRECATED_PROPERTY_ERROR;
			break;
		case WARN_DUPLICATE_ARGUMENT_NAMES:
			key = COMPILER_WARN_DUPLICATE_ARGUMENT_NAMES;
			break;
		case WARN_DUPLICATE_VARIABLE_DEF:
			key = COMPILER_WARN_DUPLICATE_VARIABLE_DEF;
			break;
		case WARN_FOR_VAR_IN_CHANGES:
			key = COMPILER_WARN_FOR_VAR_IN_CHANGES;
			break;
		case WARN_IMPORT_HIDES_CLASS:
			key = COMPILER_WARN_IMPORT_HIDES_CLASS;
			break;
		case WARN_INSTANCEOF_CHANGES:
			key = COMPILER_WARN_INSTANCE_OF_CHANGES;
			break;
		case WARN_INTERNAL_ERROR:
			key = COMPILER_WARN_INTERNAL_ERROR;
			break;
		case WARN_LEVEL_NOT_SUPPORTED:
			key = COMPILER_WARN_LEVEL_NOT_SUPPORTED;
			break;
		case WARN_MISSING_NAMESPACE_DECL:
			key = COMPILER_WARN_MISSING_NAMESPACE_DECL;
			break;
		case WARN_NEGATIVE_UINT_LITERAL:
			key = COMPILER_WARN_NEGATIVE_UINT_LITERAL;
			break;
		case WARN_NO_CONSTRUCTOR:
			key = COMPILER_WARN_NO_CONSTRUCTOR;
			break;
		case WARN_NO_EXPLICIT_SUPER_CALL_IN_CONSTRUCTOR:
			key = COMPILER_WARN_NO_EXPLICIT_SUPER_CALL_IN_CONSTRUCTOR;
			break;
		case WARN_NO_TYPE_DECL:
			key = COMPILER_WARN_NO_TYPE_DECL;
			break;
		case WARN_NUMBER_FROM_STRING_CHANGES:
			key = COMPILER_WARN_NUMBER_FROM_STRING_CHANGES;
			break;
		case WARN_SCOPING_CHANGE_IN_THIS:
			key = COMPILER_WARN_SCOPING_CHANGE_IN_THIS;
			break;
		case WARN_SLOW_TEXTFIELD_ADDITION:
			key = COMPILER_WARN_SLOW_TEXT_FIELD_ADDITION;
			break;
		case WARN_UNLIKELY_FUNCTION_VALUE:
			key = COMPILER_WARN_UNLIKELY_FUNCTION_VALUE;
			break;
		case WARN_XML_CLASS_HAS_CHANGED:
			key = COMPILER_WARN_XML_CLASS_HAS_CHANGED;
			break;
		}
		
		if (key != null)
		{
			args.put(key, b ? Boolean.TRUE : Boolean.FALSE);
		}
	}
	
	/**
	 * Sets the default background color (may be overridden by the application code).
	 * This is equivalent to using <code>mxmlc/compc --default-background-color</code>.
	 * The default value is <code>0x869CA7</code>.
	 * 
	 * @param color RGB value
	 */
	public void setDefaultBackgroundColor(int color)
	{
		args.put(DEFAULT_BACKGROUND_COLOR, new Integer(color));
		linker_args.put(DEFAULT_BACKGROUND_COLOR, new Integer(color));
		newLinkerOptionsAfterCompile.add(DEFAULT_BACKGROUND_COLOR);
	}
	
	/**
	 * Sets the default frame rate to be used in the application.
	 * This is equivalent to using <code>mxmlc/compc --default-frame-rate</code>.
	 * The default value is <code>24</code>.
	 * 
	 * @param rate frames per second
	 */
	public void setDefaultFrameRate(int rate)
	{
		args.put(DEFAULT_FRAME_RATE, new Integer(rate));
		linker_args.put(DEFAULT_FRAME_RATE, new Integer(rate));
		newLinkerOptionsAfterCompile.add(DEFAULT_FRAME_RATE);
	}
	
	/**
	 * Sets the default script execution limits (may be overridden by root attributes).
	 * This is equivalent to using <code>mxmlc/compc --default-script-limits</code>.
	 * The default maximum recursion depth is <code>1000</code>.
	 * The default maximum execution time is <code>60</code>.
	 * 
	 * @param maxRecursionDepth recursion depth
	 * @param maxExecutionTime execution time in seconds. 
	 */
	public void setDefaultScriptLimits(int maxRecursionDepth, int maxExecutionTime)
	{
		args.put(DEFAULT_SCRIPT_LIMITS, new int[] { maxRecursionDepth, maxExecutionTime });
		linker_args.put(DEFAULT_SCRIPT_LIMITS, new int[] { maxRecursionDepth, maxExecutionTime });
		newLinkerOptionsAfterCompile.add(DEFAULT_SCRIPT_LIMITS);
	}
	
	/**
	 * Sets the default window size.
	 * This is equivalent to using <code>mxmlc/compc --default-size</code>.
	 * The default width is <code>500</code>.
	 * The default height is <code>375</code>.
	 * 
	 * @param width width in pixels
	 * @param height height in pixels
	 */
	public void setDefaultSize(int width, int height)
	{
		args.put(DEFAULT_SIZE, new int[] { width, height });
		linker_args.put(DEFAULT_SIZE, new int[] { width, height });
		newLinkerOptionsAfterCompile.add(DEFAULT_SIZE);
	}
	
	/**
	 * Sets a list of definitions to omit from linking when building an application.
	 * This is equivalent to using <code>mxmlc/compc --externs</code>.
	 * 
	 * @param definitions An array of definitions (e.g. classes, functions, variables, namespaces, etc.)
	 */
	public void setExterns(String[] definitions)
	{
		args.put(EXTERNS, definitions);
		more.remove(EXTERNS);
		linker_args.put(EXTERNS, definitions);
		linker_more.remove(EXTERNS);
		newLinkerOptionsAfterCompile.add(EXTERNS);
	}
	
	/**
	 * Adds a list of definitions to the existing list of definitions.
	 *
	 * @see #setExterns(File[])
	 * @see #setExterns(String[])
	 * @param definitions an array of definitions (e.g. classes, functions, variables, namespaces, etc.)
	 */
	public void addExterns(String[] definitions)
	{
		addStrings(EXTERNS, definitions);
		addStrings(linker_more, EXTERNS, definitions);
		newLinkerOptionsAfterCompile.add(EXTERNS);
	}

	/**
	 * Loads a file containing configuration options. The file format follows the format of <code>flex-config.xml</code>.
	 * This is equivalent to using <code>mxmlc/compc --load-config</code>.
	 * 
	 * @param file an instance of <code>java.io.File</code>
	 */
	public void setConfiguration(File file)
	{
		args.put(LOAD_CONFIG, new File[] {file});
		more.remove(LOAD_CONFIG);
	}
	
	/**
	 * Adds a file to the existing list of configuration files.
	 * 
	 * @see #setConfiguration(File)
	 * @param file a configuration file
	 */
	public void addConfiguration(File file)
	{
		addFiles(LOAD_CONFIG, new File[] {file});
	}

	/**
	 * Sets the configuration parameters. The input should be valid <code>mxmlc/compc</code> command-line arguments.<p>
	 * 
	 * @param args <code>mxmlc/compc</code> command-line arguments
	 */
	public void setConfiguration(String[] args)
	{
		extras = args;
	}
	
	/**
	 * Sets a list of definitions to omit from linking when building an application.
	 * This is equivalent to using <code>mxmlc/compc --load-externs</code>.
	 * This option is similar to <code>setExterns(String[])</code>. The following is an example of
	 * the file format:
	 * 
	 * <pre>
	 * &lt;script>
	 *     &lt;!-- use 'dep', 'pre' or 'dep' to specify a definition to be omitted from linking. -->
	 *     &lt;def id="mx.skins:ProgrammaticSkin"/>
	 *     &lt;pre id="mx.core:IFlexDisplayObject"/>
	 *     &lt;dep id="String"/>
	 * &lt;/script>
	 * </pre>
	 * 
	 * @param files an array of <code>java.io.File</code>
	 */
	public void setExterns(File[] files)
	{
		args.put(LOAD_EXTERNS, files);
		more.remove(LOAD_EXTERNS);
		linker_args.put(LOAD_EXTERNS, files);
		linker_more.remove(LOAD_EXTERNS);
		newLinkerOptionsAfterCompile.add(LOAD_EXTERNS);
	}
	
	/**
	 * Adds a list of files to the existing list of definitions to be omitted from linking.
	 * 
	 * @see #setExterns(File[])
	 * @see #setExterns(String[])
	 * @param files an array of <code>java.io.File</code>.
	 */
	public void addExterns(File[] files)
	{
		addFiles(LOAD_EXTERNS, files);
		addFiles(linker_more, LOAD_EXTERNS, files);
		newLinkerOptionsAfterCompile.add(LOAD_EXTERNS);
	}

	/**
	 * Sets a SWF frame label with a sequence of classnames that will be linked onto the frame.
	 * This is equivalent to using <code>mxmlc/compc --frames.frame</code>.
	 * 
	 * @param label A string
	 * @param classNames an array of class names
	 */
	public void setFrameLabel(String label, String[] classNames)
	{
		if (!args.containsKey(FRAMES_FRAME))
		{
			args.put(FRAMES_FRAME, new TreeMap<String, String[]>());
		}
		
        // I am ONLY doing this because we set it three lines above
        @SuppressWarnings("unchecked")
		Map<String, String[]> map = (Map<String, String[]>) args.get(FRAMES_FRAME);
		map.put(label, classNames);

		if (!linker_args.containsKey(FRAMES_FRAME))
		{
			linker_args.put(FRAMES_FRAME, new TreeMap());
		}
		
        // I am ONLY doing this because we set it three lines above
        @SuppressWarnings("unchecked")
		Map<String, String[]> map2 = (Map<String, String[]>) linker_args.get(FRAMES_FRAME);
		map2.put(label, classNames);
		
		newLinkerOptionsAfterCompile.add(FRAMES_FRAME);
	}
	
	/**
	 * Sets a list of definitions to always link in when building an application.
	 * This is equivalent to using <code>mxmlc/compc --includes</code>.
	 * 
	 * @param definitions an array of definitions (e.g. classes, functions, variables, namespaces, etc).
	 */
	public void setIncludes(String[] definitions)
	{
		args.put(INCLUDES, definitions);
		more.remove(INCLUDES);
		linker_args.put(INCLUDES, definitions);
		linker_more.remove(INCLUDES);
		newLinkerOptionsAfterCompile.add(INCLUDES);
	}
	
	/**
	 * Adds a list of definitions to the existing list of definitions.
	 *
	 * @see #setIncludes(String[])
	 * @param definitions an array of definitions (e.g. classes, functions, variables, namespaces, etc.)
	 */
	public void addIncludes(String[] definitions)
	{
		addStrings(INCLUDES, definitions);
		addStrings(linker_more, INCLUDES, definitions);
		newLinkerOptionsAfterCompile.add(INCLUDES);
	}
	
	/**
	 * Specifies the licenses that the compiler has to validate before compiling.
	 * This is equivalent to using <code>mxmlc/compc --licenses.license</code>
	 * 
	 * @param productName a string
	 * @param serialNumber a serial number
	 */
	public void setLicense(String productName, String serialNumber)
	{
		if (!args.containsKey(LICENSES_LICENSE))
		{
			args.put(LICENSES_LICENSE, new TreeMap<String, String>());
		}
		
        // I am ONLY doing this because we set it three lines above
        @SuppressWarnings("unchecked")
		Map<String, String> map = (Map<String, String>) args.get(LICENSES_LICENSE);
		map.put(productName, serialNumber);		
	}

	/**
	 * Sets the metadata section of the application SWF. This option is equivalent to using the following <code>mxmlc/compc</code>
	 * command-line options:
	 * 
	 * <pre>
	 * --metadata.contributor
	 * --metadata.creator
	 * --metadata.date
	 * --metadata.description
	 * --metadata.language
	 * --metadata.localized-description
	 * --metadata.localized-title
	 * --metadata.publisher
	 * --metadata.title
	 * </pre>
	 * 
	 * The valid fields and types of value are specified below:
	 * 
	 * <pre>
	 * CONTRIBUTOR      java.lang.String
	 * CREATOR          java.lang.String
	 * DATE             java.util.Date
	 * DESCRIPTION      java.util.Map<String, String>
	 * TITLE            java.util.Map<String, String>
	 * LANGUAGE         java.lang.String
	 * PUBLISHER        java.lang.String
	 * </pre>
	 * 
	 * For example,
	 * 
	 * <pre>
	 * Map titles = new HashMap();
	 * titles.put("EN", "Adobe Flex 2 Application");
	 * 
	 * Map descriptions = new HashMap();
	 * descriptions.put("EN", "http://www.adobe.com/products/flex");
	 * 
	 * setSWFMetaData(Configuration.LANGUAGE, "EN");
	 * setSWFMetaData(Configuration.TITLE, titles);
	 * setSWFMetaData(Configuration.DESCRIPTION, descriptions);
	 * </pre>
	 * 
	 * @param field CONTRIBUTOR, CREATOR, DATE, DESCRIPTION, TITLE, LANGUAGE, PUBLISHER
	 * @param value String, Date or Map
	 * @see #CONTRIBUTOR
	 * @see #CREATOR
	 * @see #DATE
	 * @see #DESCRIPTION
	 * @see #TITLE
	 * @see #LANGUAGE
	 * @see #PUBLISHER
	 */
	public void setSWFMetaData(int field, Object value)
	{
		switch (field)
		{
		case CONTRIBUTOR:
			args.put(METADATA_CONTRIBUTOR, value);
			break;
		case CREATOR:
			args.put(METADATA_CREATOR, value);
			break;
		case DATE:
			args.put(METADATA_DATE, value);
			break;
		case DESCRIPTION:
			args.put(METADATA_LOCALIZED_DESCRIPTION, value);
			break;
		case TITLE:
			args.put(METADATA_LOCALIZED_TITLE, value);
			break;
		case LANGUAGE:
			args.put(METADATA_LANGUAGE, value);
			break;
		case PUBLISHER:
			args.put(METADATA_PUBLISHER, value);
			break;
		}

		switch (field)
		{
		case CONTRIBUTOR:
			linker_args.put(METADATA_CONTRIBUTOR, value);
			break;
		case CREATOR:
			linker_args.put(METADATA_CREATOR, value);
			break;
		case DATE:
			linker_args.put(METADATA_DATE, value);
			break;
		case DESCRIPTION:
			linker_args.put(METADATA_LOCALIZED_DESCRIPTION, value);
			break;
		case TITLE:
			linker_args.put(METADATA_LOCALIZED_TITLE, value);
			break;
		case LANGUAGE:
			linker_args.put(METADATA_LANGUAGE, value);
			break;
		case PUBLISHER:
			linker_args.put(METADATA_PUBLISHER, value);
			break;
		}
		
		newLinkerOptionsAfterCompile.add(METADATA_CONTRIBUTOR);
		newLinkerOptionsAfterCompile.add(METADATA_CREATOR);
		newLinkerOptionsAfterCompile.add(METADATA_DATE);
		newLinkerOptionsAfterCompile.add(METADATA_LOCALIZED_DESCRIPTION);
		newLinkerOptionsAfterCompile.add(METADATA_LOCALIZED_TITLE);
		newLinkerOptionsAfterCompile.add(METADATA_LANGUAGE);
		newLinkerOptionsAfterCompile.add(METADATA_PUBLISHER);
		
		args.remove(RAW_METADATA);
		linker_args.remove(RAW_METADATA);
		newLinkerOptionsAfterCompile.remove(RAW_METADATA);
	}

	/**
	 * Sets the path to the Flash Player executable when building a projector. For example,
	 * 
	 * <pre>
	 * setProjector(new File("C:/.../SAFlashPlayer.exe")) {}
	 * </pre>
	 * 
	 * This is equivalent to using <code>mxmlc/compc --projector</code>.
	 * 
	 * @param file the Flash Player executable.
	 */
	public void setProjector(File file)
	{
		args.put(PROJECTOR, file);
	}
	
	/**
	 * Sets the metadata section of the application SWF.
	 * This is equivalent to using <code>mxmlc/compc --raw-metadata</code>.
	 * This option overrides everything set by the <code>setSWFMetaData</code> method.
	 * 
	 * @see #setSWFMetaData(int, Object)
	 * @param xml a well-formed XML fragment
	 */
	public void setSWFMetaData(String xml)
	{
		args.put(RAW_METADATA, xml);
		linker_args.put(RAW_METADATA, xml);
		
		args.remove(METADATA_CONTRIBUTOR);
		args.remove(METADATA_CREATOR);
		args.remove(METADATA_DATE);
		args.remove(METADATA_LOCALIZED_DESCRIPTION);
		args.remove(METADATA_LOCALIZED_TITLE);
		args.remove(METADATA_LANGUAGE);
		args.remove(METADATA_PUBLISHER);

		linker_args.remove(METADATA_CONTRIBUTOR);
		linker_args.remove(METADATA_CREATOR);
		linker_args.remove(METADATA_DATE);
		linker_args.remove(METADATA_LOCALIZED_DESCRIPTION);
		linker_args.remove(METADATA_LOCALIZED_TITLE);
		linker_args.remove(METADATA_LANGUAGE);
		linker_args.remove(METADATA_PUBLISHER);
		
		newLinkerOptionsAfterCompile.remove(METADATA_CONTRIBUTOR);
		newLinkerOptionsAfterCompile.remove(METADATA_CREATOR);
		newLinkerOptionsAfterCompile.remove(METADATA_DATE);
		newLinkerOptionsAfterCompile.remove(METADATA_LOCALIZED_DESCRIPTION);
		newLinkerOptionsAfterCompile.remove(METADATA_LOCALIZED_TITLE);
		newLinkerOptionsAfterCompile.remove(METADATA_LANGUAGE);
		newLinkerOptionsAfterCompile.remove(METADATA_PUBLISHER);
	}
	
	/**
	 * Sets a list of runtime shared library URLs to be loaded before the application starts.
	 * This is equivalent to using <code>mxmlc/compc --runtime-shared-libraries</code>.
	 * 
	 * @param libraries an array of <code>java.lang.String</code>.
	 */
	public void setRuntimeSharedLibraries(String[] libraries)
	{
		args.put(RUNTIME_SHARED_LIBRARIES, libraries);
		more.remove(RUNTIME_SHARED_LIBRARIES);
	}

	/**
	 * Adds a list of runtime shared library URLs to the existing list.
	 * 
	 * @see #setRuntimeSharedLibraries(String[])
	 * @param libraries an array of <code>java.lang.String</code>
	 */
	public void addRuntimeSharedLibraries(String[] libraries)
	{
		addStrings(RUNTIME_SHARED_LIBRARIES, libraries);
	}

	/**
	 * Toggles whether the application SWF is flagged for access to network resources.
	 * This is equivalent to using <code>mxmlc/compc --use-network</code>.
	 * By default, it is set to <code>true</code>.
	 * 
	 * @param b boolean value
	 */
	public void useNetwork(boolean b)
	{
		args.put(USE_NETWORK, b ? Boolean.TRUE : Boolean.FALSE);
		linker_args.put(USE_NETWORK, b ? Boolean.TRUE : Boolean.FALSE);
		newLinkerOptionsAfterCompile.add(USE_NETWORK);
	}
	
	/**
	 * Defines a token. mxmlc and compc support token substitutions. For example,
	 * 
	 * <pre>
	 * mxmlc +flexlib=path1 +foo=bar --var=${foo}
	 * </pre>
	 * 
	 * <code>var=bar</code> after the substitution of <code>${foo}</code>.
	 * 
	 * @param name
	 * @param value
	 */
	public void setToken(String name, String value)
	{
		tokens.put(name, value);
	}

	/**
	 * 
	 * @param key
	 * @param files
	 */
	private void addFiles(String key, File[] files)
	{
		addFiles(more, key, files);
	}

	/**
	 * 
	 * @param more
	 * @param key
	 * @param files
	 */
	private void addFiles(Map<String, Object> more, String key, File[] files)
	{
		File[] existing = null;
		
		if (more.containsKey(key))
		{
			existing = (File[]) more.get(key);
		}
		
		if (existing != null)
		{
			int length1 = existing.length, length2 = files == null ? 0 : files.length;
			
			File[] newPaths = new File[length1 + length2];
			System.arraycopy(existing, 0, newPaths, 0, length1);
			System.arraycopy(files, 0, newPaths, length1, length2);
			
			files = newPaths;
		}
		
		more.put(key, files);
	}
	
	/**
	 * 
	 * @param a1
	 * @param a2
	 * @return
	 */
	private String[] merge(String[] a1, String[] a2)
	{
		int l1 = a1 == null ? 0 : a1.length;
		int l2 = a2 == null ? 0 : a2.length;
		
		String[] a3 = new String[l1 + l2];
		if (a1 != null)
		{
			System.arraycopy(a1, 0, a3, 0, l1);			
		}
		if (a2 != null)
		{
			System.arraycopy(a2, 0, a3, l1, l2);
		}
		
		return a3;
	}
	
	/**
	 * 
	 * @param a1
	 * @param a2
	 * @return
	 */
	private File[] merge(File[] a1, File[] a2)
	{
		int l1 = a1 == null ? 0 : a1.length;
		int l2 = a2 == null ? 0 : a2.length;
		
		File[] a3 = new File[l1 + l2];
		if (a1 != null)
		{
			System.arraycopy(a1, 0, a3, 0, l1);
		}
		if (a2 != null)
		{
			System.arraycopy(a2, 0, a3, l1, l2);
		}
		
		return a3;
	}

	/**
	 * 
	 * @param a1
	 * @param a2
	 * @return
	 */
	private URL[] merge(URL[] a1, URL[] a2)
	{
		int l1 = a1 == null ? 0 : a1.length;
		int l2 = a2 == null ? 0 : a2.length;
		
		URL[] a3 = new URL[l1 + l2];
		if (a1 != null)
		{
			System.arraycopy(a1, 0, a3, 0, l1);
		}
		if (a2 != null)
		{
			System.arraycopy(a2, 0, a3, l1, l2);
		}
		
		return a3;
	}

	
	/**
	 * 
	 * @param key
	 * @param strings
	 */
	private void addStrings(String key, String[] strings)
	{
		addStrings(more, key, strings);
	}
	
	/**
	 * 
	 * @param more
	 * @param key
	 * @param strings
	 */
	private void addStrings(Map<String, Object> more, String key, String[] strings)
	{
		String[] existing = null;
		
		if (more.containsKey(key))
		{
			existing = (String[]) more.get(key);
		}
		
		if (existing != null)
		{
			int length1 = existing.length, length2 = strings == null ? 0 : strings.length;
			
			String[] newStrings = new String[length1 + length2];
			System.arraycopy(existing, 0, newStrings, 0, length1);
			System.arraycopy(strings, 0, newStrings, length1, length2);
			
			strings = newStrings;
		}
		
		more.put(key, strings);
	}

	/**
	 * 
	 * @param key
	 * @param urls
	private void addURLs(String key, URL[] urls)
	{
		URL[] existing = null;
		
		if (more.containsKey(key))
		{
			existing = (URL[]) more.get(key);
		}
		
		if (existing != null)
		{
			int length1 = existing.length, length2 = urls == null ? 0 : urls.length;
			
			URL[] newURLs = new URL[length1 + length2];
			System.arraycopy(existing, 0, newURLs, 0, length1);
			System.arraycopy(urls, 0, newURLs, length1, length2);
			
			urls = newURLs;
		}
		
		more.put(key, urls);
	}
     */

	/**
	 * 
	 */
	public String toString()
	{
		String[] args = getCompilerOptions();
		StringBuilder b = new StringBuilder();
		for (int i = 0; i < args.length; i++)
		{
			b.append(args[i]);
			b.append(' ');
		}
		return b.toString();
	}
	
	/**
	 * 
	 * @param f
	 * @return
	 */
	private File toFile(VirtualFile f)
	{
		return (f instanceof LocalFile) ? new File(f.getName()) : null;
	}

	/**
	 * 
	 * @param f
	 * @return
	 */
	@SuppressWarnings({ "unused", "deprecation" })
    private URL toURL(VirtualFile f)
	{
		try
		{
			return (f instanceof LocalFile) ? new File(f.getName()).toURL() : null;
		}
		catch (MalformedURLException ex)
		{
			return null;
		}
	}

	/**
	 * 
	 * @param p
	 * @return
	private File toFile(String p)
	{
		return (p != null) ? new File(p) : null;
	}
     */
	
	/**
	 * 
	 * @param files
	 * @return
	 */
	private File[] toFiles(VirtualFile[] files)
	{
		File[] newFiles = new File[files == null ? 0 : files.length];
		for (int i = 0, length = newFiles.length; i < length; i++)
		{
			newFiles[i] = toFile(files[i]);
		}
		
		return newFiles;
	}
	
	/**
	 * 
	 * @param list
	 * @return
	 */
	private String[] toStrings(List list)
	{
		String[] strings = new String[list == null ? 0 : list.size()];
		for (int i = 0, length = strings.length; i < length; i++)
		{
			strings[i] = (String) list.get(i);
		}
		return strings;
	}

	/**
	 * 
	 * @param list
	 * @return
	private URL[] toURLs(List list)
	{
		URL[] urls = new URL[list == null ? 0 : list.size()];
		for (int i = 0, length = urls.length; i < length; i++)
		{
			try
			{
				urls[i] = new URL((String) list.get(i));
			}
			catch (MalformedURLException ex)
			{
				urls[i] = null;
			}
		}
		return urls;
	}
     */

	/**
	 * 
	 * @param set
	 * @return
	 */
	private String[] toStrings(Set set)
	{
		String[] strings = new String[set == null ? 0 : set.size()];
		if (set != null)
		{
			int k = 0;
			for (Iterator i = set.iterator(); i.hasNext(); k++)
			{
				strings[k] = (String) i.next();
			}
		}
		return strings;		
	}
	
	/**
	 * 
	 * @param num
	 * @return
	 */
	private int toInteger(String num)
	{
		try
		{
			return Integer.parseInt(num);
		}
		catch (NumberFormatException ex)
		{
			return -1;
		}
	}

	private String toCommaSeparatedString(String[] strings)
	{
		StringBuilder b = new StringBuilder();
		for (int i = 0, length = strings == null ? 0 : strings.length; i < length; i++)
		{
			b.append(strings[i]);
			if (i < length - 1)
			{
				b.append(',');
			}
		}
		return b.toString();
	}

	private String toCommaSeparatedString(File[] files)
	{
		StringBuilder b = new StringBuilder();
		for (int i = 0, length = files == null ? 0 : files.length; i < length; i++)
		{
			b.append(files[i].getPath());
			if (i < length - 1)
			{
				b.append(',');
			}
		}
		return b.toString();
	}

	private String toCommaSeparatedString(URL[] urls)
	{
		StringBuilder b = new StringBuilder();
		for (int i = 0, length = urls == null ? 0 : urls.length; i < length; i++)
		{
			b.append(urls[i].toExternalForm());
			if (i < length - 1)
			{
				b.append(',');
			}
		}
		return b.toString();
	}

    /**
	 * 
     * @param c
     */
	private void populateDefaults(ToolsConfiguration c)
	{
		setDefaultBackgroundColor(c.backgroundColor());
		setDefaultFrameRate(c.getFrameRate());
		setDefaultScriptLimits(c.getScriptRecursionLimit(), c.getScriptTimeLimit());
		setDefaultSize(c.defaultWidth(), c.defaultHeight());
		setExterns(toStrings(c.getExterns()));
		setIncludes(toStrings(c.getIncludes()));
		setTargetPlayer(c.getTargetPlayerMajorVersion(), c.getTargetPlayerMinorVersion(), 
						c.getTargetPlayerRevision());
		enableDigestVerification(c.getVerifyDigests());
		removeUnusedRuntimeSharedLibraryPaths(c.getRemoveUnusedRsls());
		
		List<RslPathInfo> rslList = c.getRslPathInfo();
		boolean first = true;
		for (Iterator<RslPathInfo> iter = rslList.iterator(); iter.hasNext();) {
			RslPathInfo info = (RslPathInfo)iter.next();
			String[] rslUrls = info.getRslUrls().toArray(new String[0]);
			String[] policyUrls = info.getPolicyFileUrls().toArray(new String[0]);
			if (first) {
				setRuntimeSharedLibraryPath(info.getSwcPath(),
						rslUrls,
						policyUrls);
				first = false;
			}
			else {
				addRuntimeSharedLibraryPath(info.getSwcPath(),
						rslUrls,
						policyUrls);
			}
		}
		
		// TODO
		// setSWFMetaData();
		// setProjector();
		
		setSWFMetaData(c.getMetadata());
		setRuntimeSharedLibraries(toStrings(c.getRuntimeSharedLibraries()));
		useNetwork(c.useNetwork());
		
		// useMobileFramework();
		
		populateDefaults(c.getCompilerConfiguration());
		populateDefaults(c.getFramesConfiguration());
		populateDefaults(c.getLicensesConfiguration());
		populateDefaults(c.getRuntimeSharedLibrarySettingsConfiguration());
	}

	/**
	 * 
	 * @param cc
	 */
	private void populateDefaults(CompilerConfiguration cc)
	{
		enableAccessibility(cc.accessible());
		setActionScriptMetadata(cc.getKeepAs3Metadata());
		setActionScriptFileEncoding(cc.getActionscriptFileEncoding());
		allowSourcePathOverlap(cc.allowSourcePathOverlap());
		useActionScript3(cc.dialect() == CompilerConfiguration.AS3Dialect);
		setContextRoot(cc.getContextRoot());
		enableDebugging(cc.debug(), configuration.debugPassword());
		
		if (cc.getDefaultsCssUrl() != null)
		{
			setDefaultCSS(FileUtil.openFile(cc.getDefaultsCssUrl().getName()));
		}
		
		useECMAScript(cc.dialect() == CompilerConfiguration.ESDialect);
		setExternalLibraryPath(toFiles(cc.getExternalLibraryPath()));
		useHeadlessServer(cc.headlessServer());
		keepAllTypeSelectors(cc.keepAllTypeSelectors());
		keepCompilerGeneratedActionScript(cc.keepGeneratedActionScript());
		includeLibraries(toFiles(cc.getIncludeLibraries()));
		setLibraryPath(toFiles(cc.getLibraryPath()));
		setLocale(cc.getLocales());
		optimize(cc.optimize());
		setServiceConfiguration(toFile(cc.getServices()));
		showActionScriptWarnings(cc.warnings());
		showBindingWarnings(cc.showBindingWarnings());
		showDeprecationWarnings(cc.showDeprecationWarnings());
        showShadowedDeviceFontWarnings(cc.showShadowedDeviceFontWarnings());
		showUnusedTypeSelectorWarnings(cc.showUnusedTypeSelectorWarnings());
		setSourcePath(cc.getUnexpandedSourcePath());
		enableStrictChecking(cc.strict());
		setTheme(toFiles(cc.getThemeFiles()));
		useResourceBundleMetaData(cc.useResourceBundleMetadata());
		enableVerboseStacktraces(cc.debug());
        setDefineDirective(cc.getDefine());
        setCompatibilityVersion(cc.getMxmlConfiguration().getMajorCompatibilityVersion(),
        						cc.getMxmlConfiguration().getMinorCompatibilityVersion(),
        						cc.getMxmlConfiguration().getRevisionCompatibilityVersion());

		checkActionScriptWarning(WARN_ARRAY_TOSTRING_CHANGES, cc.warn_array_tostring_changes());
		checkActionScriptWarning(WARN_ASSIGNMENT_WITHIN_CONDITIONAL, cc.warn_assignment_within_conditional());
		checkActionScriptWarning(WARN_BAD_ARRAY_CAST, cc.warn_bad_array_cast());
		checkActionScriptWarning(WARN_BAD_BOOLEAN_ASSIGNMENT, cc.warn_bad_bool_assignment());
		checkActionScriptWarning(WARN_BAD_DATE_CAST, cc.warn_bad_date_cast());
		checkActionScriptWarning(WARN_BAD_ES3_TYPE_METHOD, cc.warn_bad_es3_type_method());
		checkActionScriptWarning(WARN_BAD_ES3_TYPE_PROP, cc.warn_bad_es3_type_prop());
		checkActionScriptWarning(WARN_BAD_NAN_COMPARISON, cc.warn_bad_nan_comparison());
		checkActionScriptWarning(WARN_BAD_NULL_ASSIGNMENT, cc.warn_bad_null_assignment());
		checkActionScriptWarning(WARN_BAD_NULL_COMPARISON, cc.warn_bad_null_comparison());
		checkActionScriptWarning(WARN_BAD_UNDEFINED_COMPARISON, cc.warn_bad_undefined_comparison());
		checkActionScriptWarning(WARN_BOOLEAN_CONSTRUCTOR_WITH_NO_ARGS, cc.warn_boolean_constructor_with_no_args());
		checkActionScriptWarning(WARN_CHANGES_IN_RESOLVE, cc.warn_changes_in_resolve());
		checkActionScriptWarning(WARN_CLASS_IS_SEALED, cc.warn_class_is_sealed());
		checkActionScriptWarning(WARN_CONST_NOT_INITIALIZED, cc.warn_const_not_initialized());
		checkActionScriptWarning(WARN_CONSTRUCTOR_RETURNS_VALUE, cc.warn_constructor_returns_value());
		checkActionScriptWarning(WARN_DEPRECATED_EVENT_HANDLER_ERROR, cc.warn_deprecated_event_handler_error());
		checkActionScriptWarning(WARN_DEPRECATED_FUNCTION_ERROR, cc.warn_deprecated_function_error());
		checkActionScriptWarning(WARN_DEPRECATED_PROPERTY_ERROR, cc.warn_deprecated_property_error());
		checkActionScriptWarning(WARN_DUPLICATE_ARGUMENT_NAMES, cc.warn_duplicate_argument_names());
		checkActionScriptWarning(WARN_DUPLICATE_VARIABLE_DEF, cc.warn_duplicate_variable_def());
		checkActionScriptWarning(WARN_FOR_VAR_IN_CHANGES, cc.warn_for_var_in_changes());
		checkActionScriptWarning(WARN_IMPORT_HIDES_CLASS, cc.warn_import_hides_class());
		checkActionScriptWarning(WARN_INSTANCEOF_CHANGES, cc.warn_instance_of_changes());
		checkActionScriptWarning(WARN_INTERNAL_ERROR, cc.warn_internal_error());
		checkActionScriptWarning(WARN_LEVEL_NOT_SUPPORTED, cc.warn_level_not_supported());
		checkActionScriptWarning(WARN_MISSING_NAMESPACE_DECL, cc.warn_missing_namespace_decl());
		checkActionScriptWarning(WARN_NEGATIVE_UINT_LITERAL, cc.warn_negative_uint_literal());
		checkActionScriptWarning(WARN_NO_CONSTRUCTOR, cc.warn_no_constructor());
		checkActionScriptWarning(WARN_NO_EXPLICIT_SUPER_CALL_IN_CONSTRUCTOR, cc.warn_no_explicit_super_call_in_constructor());
		checkActionScriptWarning(WARN_NO_TYPE_DECL, cc.warn_no_type_decl());
		checkActionScriptWarning(WARN_NUMBER_FROM_STRING_CHANGES, cc.warn_number_from_string_changes());
		checkActionScriptWarning(WARN_SCOPING_CHANGE_IN_THIS, cc.warn_scoping_change_in_this());
		checkActionScriptWarning(WARN_SLOW_TEXTFIELD_ADDITION, cc.warn_slow_text_field_addition());
		checkActionScriptWarning(WARN_UNLIKELY_FUNCTION_VALUE, cc.warn_unlikely_function_value());
		checkActionScriptWarning(WARN_XML_CLASS_HAS_CHANGED, cc.warn_xml_class_has_changed());

		populateDefaults(cc.getFontsConfiguration());
		populateDefaults(cc.getNamespacesConfiguration());
	}

	/**
	 * 
	 * @param fc
	 */
	private void populateDefaults(FontsConfiguration fc)
	{
		FontsConfiguration.Languages lc = fc.getLanguagesConfiguration();
		
		for (Iterator i = lc.keySet().iterator(); i.hasNext(); )
		{
			String key = (String) i.next();
			setFontLanguageRange(key, lc.getProperty(key));
		}
		setLocalFontSnapshot(toFile(fc.getLocalFontsSnapshot()));
		setLocalFontPaths(toStrings(fc.getLocalFontPaths()));
		setFontManagers(toStrings(fc.getManagers()));
		setMaximumCachedFonts(toInteger(fc.getMaxCachedFonts()));
		setMaximumGlyphsPerFace(toInteger(fc.getMaxGlyphsPerFace()));
		enableAdvancedAntiAliasing(fc.getFlashType());
	}

	/**
	 * 
	 * @param nc
	 */
	private void populateDefaults(NamespacesConfiguration nc)
	{
	    Map<String, List<VirtualFile>> manifestMappings = nc.getManifestMappings();

		if (manifestMappings != null)
		{
		    Iterator<Entry<String, List<VirtualFile>>> iterator = manifestMappings.entrySet().iterator();
			while (iterator.hasNext())
			{
				Entry<String, List<VirtualFile>> entry = iterator.next();
			    String uri = entry.getKey();
			    List<VirtualFile> virtualFiles = entry.getValue();
			    List<File> files = new ArrayList<File>(virtualFiles.size());

			    Iterator<VirtualFile> vi = virtualFiles.iterator();
			    while (vi.hasNext())
			    {
	                files.add(toFile(vi.next()));
			    }
                setComponentManifests(uri, files);
			}
		}
	}
	
	/**
	 * 
	 * @param frc
	 */
	private void populateDefaults(FramesConfiguration frc)
	{
		List frList = frc.getFrameList();

		for (int i = 0, length = frList == null ? 0 : frList.size(); i < length; i++)
		{
			FrameInfo info = (FrameInfo) frList.get(i);
			setFrameLabel(info.label, toStrings(info.frameClasses));
		}
	}
	
	/**
	 * 
	 * @param lic
	 */
	private void populateDefaults(LicensesConfiguration lic)
	{
		Map licenseMap = lic.getLicenseMap();

		if (licenseMap != null)
		{
			for (Iterator i = licenseMap.keySet().iterator(); i.hasNext(); )
			{
				String name = (String) i.next();
				setLicense(name, (String) licenseMap.get(name));
			}
		}
	}
	
    /**
     * 
     * @param configuration - runtime shared library settings.
     */
    private void populateDefaults(RuntimeSharedLibrarySettingsConfiguration configuration)
    {
        setForceRuntimeSharedLibraryPaths(toFiles(configuration.getForceRsls()));
        
        Map<VirtualFile, String>adMap = configuration.getApplicationDomains();
        boolean first = true;
        
        for (Map.Entry<VirtualFile, String>entry : adMap.entrySet())
        {
            File file = toFile(entry.getKey());
            if (first)
            {
                setApplicationDomainForRuntimeSharedLibraryPath(
                        file,
                        entry.getValue());
                first = false;
            }
            else
            {
                addApplicationDomainForRuntimeSharedLibraryPath(
                        file,
                        entry.getValue());
            }
        }
        
    }

    public boolean hasChanged()
	{
		return newLinkerOptionsAfterCompile.size() > 0;
	}
	
	public void reset()
	{
		newLinkerOptionsAfterCompile.clear();
	}
	
	public void setTargetPlayer(int major, int minor, int revision)
	{
		args.put(TARGET_PLAYER, major + "." + minor + "." + revision);
	}

	public void setCompatibilityVersion(int major, int minor, int revision)
	{
		if (!(major == 0 && minor == 0 && revision == 0))
		{
			args.put(COMPILER_MXML_COMPATIBILITY, major + "." + minor + "." + revision);
		}
	}

	private String[] createCrossDomainArray(String swc, String[] rslUrls, String[] policyFileUrls)
	{
		if (swc == null || rslUrls == null || policyFileUrls == null) 
		{
			throw new NullPointerException();
		}
		
		if (rslUrls.length != policyFileUrls.length)
		{
			throw new IllegalArgumentException();
		}
		
		List<String> rslList = new ArrayList<String>();
		
		rslList.add(swc);
		
		int argCount = rslUrls.length;
		for (int i = 0; i < argCount; i++) 
		{
			rslList.add(rslUrls[i]);
			rslList.add(policyFileUrls[i]);
		}
		
		return rslList.toArray(new String[0]);
	}
	
	
	public void enableDigestComputation(boolean compute)
	{
		args.put(COMPILER_COMPUTE_DIGEST, compute ? Boolean.TRUE : Boolean.FALSE);				
	}

	
	public void addRuntimeSharedLibraryPath(String swc, String[] rslUrls, String[] policyFileUrls)
	{
		String[] rslArray = createCrossDomainArray(swc, rslUrls, policyFileUrls);

		RslPathList value = (RslPathList) args.get(RUNTIME_SHARED_LIBRARY_PATH);
		if (value == null)
		{
			value = new RslPathList();
			args.put(RUNTIME_SHARED_LIBRARY_PATH, value);
		}

		value.add(rslArray);			
	}

	public void setRuntimeSharedLibraryPath(String swc, String[] rslUrls, String[] policyFileUrls)
	{
		String[] rslArray = createCrossDomainArray(swc, rslUrls, policyFileUrls);

		RslPathList list = new RslPathList();
		list.add(rslArray);
		
		args.put(RUNTIME_SHARED_LIBRARY_PATH, list);
	}

	public void enableDigestVerification(boolean verify)
	{
		args.put(VERIFY_DIGESTS, verify ? Boolean.TRUE : Boolean.FALSE);	
	}

    public void addDefineDirective(String name, String value)
    {
        // error checking on the values themsevles will be handled later,
        // in CompilerConfiguration.cfgDefine()
        CompilerDefinitionList defs = (CompilerDefinitionList) args.get(COMPILER_DEFINE);
        if (defs == null)
        {
            defs = new CompilerDefinitionList();
            args.put(COMPILER_DEFINE, defs);
        }

        defs.add(name);
        defs.add(value);
    }
    
    public void setDefineDirective(String[] names, String[] values)
    {
        if ((names == null) || (values == null) || (names.length != values.length))
        {
            args.remove(COMPILER_DEFINE);
        }
        else
        {
            final CompilerDefinitionList defs = new CompilerDefinitionList();
            args.put(COMPILER_DEFINE, defs);
            
            for(int i = 0; i < values.length; i++)
            {
                defs.add(names[i]);
                defs.add(values[i]);
            }
        }
    }

    /**
     * hacky non-API helper method for populateDefaults
     */
    private void setDefineDirective(ObjectList<ConfigVar> configVars)
    {
        if (configVars != null)
        {
            final CompilerDefinitionList defs = new CompilerDefinitionList();
            args.put(COMPILER_DEFINE, defs);
            for(ConfigVar var : configVars)
            {
                // by this point, error checking should already have been
                // performed on the ConfigVars
                assert (var       != null &&
                        var.ns    != null &&
                        var.name  != null &&
                        var.value != null &&
                        var.ns.length()    > 0 &&
                        var.name.length()  > 0 &&
                        var.value.length() > 0);
                
                defs.add(var.ns + "::" + var.name);
                defs.add(var.value);
            }
        }
    }
    
    @SuppressWarnings("unchecked")
    public Map<String, List<String>> getExtensions() {
        if( !args.containsKey( COMPILER_EXTENSIONS ) ) {
            args.put( COMPILER_EXTENSIONS, new LinkedHashMap<String, List<String>>() );
        }
        return (Map<String, List<String>>) args.get( COMPILER_EXTENSIONS );
    }

    public void addExtensionLibraries( File extension, List<String> parameter )
    {
        getExtensions().put( extension.getAbsolutePath(), parameter );
    }

    public void setExtensionLibraries( Map<File, List<String>> extensions)
    {
        getExtensions().clear();
        Set<File> keys = extensions.keySet();
        for ( File key : keys )
        {
            addExtensionLibraries( key, extensions.get( key ) );
        }
    }
    
    @Override
    public OEMConfiguration clone()
    {
        OEMConfiguration cloneConfig;
        try
        {
            cloneConfig = (OEMConfiguration) super.clone();
        }
        catch ( CloneNotSupportedException e )
        {
            throw new RuntimeException(e);//wont happen
        }
        cloneConfig.args = new LinkedHashMap<String, Object>(args);
        cloneConfig.defaults = new LinkedHashMap<String, Object>(defaults);
        cloneConfig.more = new LinkedHashMap<String, Object>(more);
        cloneConfig.linker_args = new LinkedHashMap<String, Object>(linker_args);
        cloneConfig.linker_more = new LinkedHashMap<String, Object>(linker_more);
        return cloneConfig;
    }

    public void addForceRuntimeSharedLibraryPaths(File[] paths)
    {
        if (paths == null)
            throw new NullPointerException("paths may not be null");

        addFiles(RUNTIME_SHARED_LIBRARY_SETTINGS_FORCE_RSLS, paths);
    }

    public void setForceRuntimeSharedLibraryPaths(File[] paths)
    {
        if (paths == null)
            throw new NullPointerException("paths may not be null");
        
        args.put(RUNTIME_SHARED_LIBRARY_SETTINGS_FORCE_RSLS, paths);
        more.remove(RUNTIME_SHARED_LIBRARY_SETTINGS_FORCE_RSLS);
    }
    
    public void addApplicationDomainForRuntimeSharedLibraryPath(File path, String applicationDomainTarget)
    {
        validateApplicationDomainArguments(path, applicationDomainTarget);
        
        ApplicationDomainsList value = (ApplicationDomainsList) args.get(RUNTIME_SHARED_LIBRARY_SETTINGS_APPLICATION_DOMAIN);
        if (value == null)
        {
            value = new ApplicationDomainsList();
            args.put(RUNTIME_SHARED_LIBRARY_SETTINGS_APPLICATION_DOMAIN, value);
        }

        value.add(new String[]{path.getPath(), applicationDomainTarget});                        
    }
    
    public void setApplicationDomainForRuntimeSharedLibraryPath(File path, String applicationDomainTarget)
    {
        ApplicationDomainsList list = new ApplicationDomainsList();
        if (path == null)
        {
            args.put(RUNTIME_SHARED_LIBRARY_SETTINGS_APPLICATION_DOMAIN, list);
            return;
        }
        
        validateApplicationDomainArguments(path, applicationDomainTarget);

        list.add(new String[]{path.getPath(), applicationDomainTarget});            

        args.put(RUNTIME_SHARED_LIBRARY_SETTINGS_APPLICATION_DOMAIN, list);
    }

    /**
     *  Validate the arguments to the application domain methods.
     *  Throw exceptions if the arguments do not pass the tests. 
     */
    private void validateApplicationDomainArguments(File path, String applicationDomainTarget)
    {
        if (path == null)
            throw new NullPointerException("paths may not be null");
        
        if (applicationDomainTarget == null)
            throw new NullPointerException("applicationDomains may not be null");
    }

}
