1  /*
     2   * Copyright the original author or authors.
     3   * 
     4   * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   * 
     8   *      http://www.mozilla.org/MPL/MPL-1.1.html
     9   * 
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  import org.as2lib.app.exec.Executable;
    18  import org.as2lib.data.holder.Map;
    19  import org.as2lib.env.event.EventSupport;
    20  import org.as2lib.env.overload.Overload;
    21  import org.as2lib.io.file.CompositeTextFileFactory;
    22  import org.as2lib.io.file.FileLoader;
    23  import org.as2lib.io.file.LoadCompleteListener;
    24  import org.as2lib.io.file.LoadErrorListener;
    25  import org.as2lib.io.file.LoadProgressListener;
    26  import org.as2lib.io.file.LoadStartListener;
    27  import org.as2lib.io.file.SwfFileLoader;
    28  import org.as2lib.io.file.TextFileFactory;
    29  import org.as2lib.io.file.TextFileLoader;
    30  import org.as2lib.io.file.XmlFileFactory;
    31  
    32  /**
    33   * {@code Loader} is a central distributor for loading files.
    34   * 
    35   * <p>{@code Loader} should be used for loading files if you do not like to
    36   * bother about the certain loading mechianism.
    37   * 
    38   * <p>If you want to reduces the occurences of {@code Loader} instances you can
    39   * use {@code Loader.getInstance} that contains a {@code Loader} instance.
    40   * 
    41   * <p>{@code Loader.getInstance().load("uri")} is available to load any common file.
    42   * 
    43   * <p>Loading a external {@code .swf} requires a {@code MovieClip} to load therefore
    44   * you should use {@code loadSwf} or use the overloaded {@code load} with passing
    45   * the {@code MovieClip} as second parameter.
    46   * 
    47   * <p>{@code Loader} uses paralell loading, this means it starts as much requests
    48   * as allowed paralell.
    49   * 
    50   * <p>{@code Loader} publishes the same event line {@link FileLoader}.
    51   * 
    52   * <p>Example for using {@code Loader.load}:
    53   * <code>
    54   *   import org.as2lib.io.file.Loader;
    55   *   
    56   *   var loader:Loader = Loader.getInstance();
    57   *   loader.addListener(...); // Add your listener for the file loading.
    58   *   loader.load("content.txt"); 
    59   *   loader.load("content.xml");
    60   *   loader.load("content.swf", _root.createEmptyMovieClip("content", _root.getNextHighestDepth());
    61   * </code>
    62   * 
    63   * @author Martin Heidegger
    64   * @version 1.0
    65   */
    66  class org.as2lib.io.file.Loader extends EventSupport
    67  	implements LoadStartListener,
    68  		LoadCompleteListener,
    69  		LoadErrorListener,
    70  		LoadProgressListener {
    71  	
    72  	/** Instance of the Loader. */
    73  	private static var instance:Loader;
    74  	
    75  	/**
    76  	 * Returns a {@code Loader} instance.
    77  	 * 
    78  	 * @return {@code Loader} instance.
    79  	 */
    80  	public static function getInstance():Loader {
    81  		if (!instance) {
    82  			instance = new Loader();
    83  		}
    84  		return instance;
    85  	}	
    86  	
    87  	/** Factory to create {@code TextFile} implementations, configurable. */
    88  	private var textFileFactory:TextFileFactory;
    89  	
    90  	/**
    91  	 * Constructs a new {@code Loader}.
    92  	 */
    93  	public function Loader(Void) {
    94  		var factory:CompositeTextFileFactory = new CompositeTextFileFactory();
    95  		factory.putTextFileFactoryByExtension("xml", new XmlFileFactory());
    96  		textFileFactory = factory;
    97  	}
    98  	
    99  	/**
   100  	 * Loads a {@code .swf} to a {@code MovieClip} instance.
   101  	 * 
   102  	 * @param uri location of the resource to load
   103  	 * @param mc {@code MovieClip} as container for the {@code .swf} content
   104  	 * @param parameters (optional) parameters for loading the resource
   105  	 * @param method (optional) POST/GET as method for submitting the parameters,
   106  	 *        default method used if {@code method} was not passed-in is POST.
   107  	 * @param callBack (optional) {@link Executable} to be executed if the resource
   108  	 *        was complete loaded
   109  	 * @return {@code SwfFileLoader} that loads the resource
   110  	 */
   111  	public function loadSwf(uri:String, mc:MovieClip, parameters:Map,
   112  			method:String, callBack:Executable):SwfFileLoader {
   113  		var fL:SwfFileLoader = new SwfFileLoader(mc);
   114  		fL.addListener(this);
   115  		fL.load(uri, method, parameters);
   116  		return fL;
   117  	}
   118  	
   119  	/**
   120  	 * Loads a external text file.
   121  	 * 
   122  	 * @param uri location of the resource to load
   123  	 * @param method (optional) POST/GET as method for submitting the parameters,
   124  	 *        default method used if {@code method} was not passed-in is POST.
   125  	 * @param parameters (optional) parameters for loading the resource
   126  	 * @param callBack (optional) {@link Executable} to be executed if the resource
   127  	 *        was complete loaded
   128  	 * @return {@code TextFileLoader} that loads the certain file
   129  	 */
   130  	public function loadText(uri:String, method:String, parameters:Map,
   131  			callBack:Executable):TextFileLoader {
   132  		var fL:TextFileLoader = new TextFileLoader(textFileFactory);
   133  		fL.addListener(this);
   134  		fL.load(uri, method, parameters);
   135  		return fL;
   136  	}
   137  	
   138  	/**
   139  	 * Defines the {@code TextFileFactory} to be used by {@code loadText}.
   140  	 * 
   141  	 * <p>{@code loadText} requires a {@code TextFileFactory} to generate the
   142  	 * concrete {@code TextFile} instance that represents the resource. This 
   143  	 * methods allows configuration of the supported file formats.
   144  	 * 
   145  	 * <p>The default configuration contains a {@link CompositeTextFileFactory} with
   146  	 * {@link org.as2lib.io.file.SimpleTextFileFactory} as default
   147  	 * {@code TextFileFactory} and {@link XmlFileFactory} for the extension "xml".
   148  	 * 
   149  	 * @param textFileFactory {@code TextFileFactory} to be used by {@code loadFile}
   150  	 */
   151  	public function setFileFactory(textFileFactory:TextFileFactory):Void {
   152  		this.textFileFactory = textFileFactory;
   153  	}
   154  	
   155  	/**
   156  	 * @overload #loadSwf
   157  	 * @overload #loadText
   158  	 */
   159  	public function load(url, target) {
   160  		var overload:Overload = new Overload();
   161  		overload.addHandler([String, MovieClip, String, Map, Executable], loadSwf);
   162  		overload.addHandler([String, MovieClip, String, Map], loadSwf);
   163  		overload.addHandler([String, MovieClip, String], loadSwf);
   164  		overload.addHandler([String, MovieClip], loadSwf);
   165  		overload.addHandler([String, String, Map, Executable], loadText);
   166  		overload.addHandler([String, String, Map], loadText);
   167  		overload.addHandler([String, Map], loadText);
   168  		overload.addHandler([String], loadText);
   169  		return overload.forward(arguments);
   170  	}
   171  	
   172  	/**
   173  	 * (implementation detail) Handles the response of a finished {@code FileLoader}.
   174  	 * 
   175  	 * @param fileLoader {@code FileLoader} that loaded the certain resource
   176  	 */
   177  	public function onLoadComplete(fileLoader:FileLoader):Void {
   178  		var completeDistributor:LoadCompleteListener =
   179  			distributorControl.getDistributor(LoadCompleteListener);
   180  		completeDistributor.onLoadComplete(fileLoader);
   181  	}
   182  
   183  	/**
   184  	 * (implementation detail) Handles the response if a {@code FileLoader}
   185  	 * started working.
   186  	 * 
   187  	 * @param resourceLoader {@code FileLoader} that loaded the certain resource
   188  	 */
   189  	public function onLoadStart(resourceLoader:FileLoader):Void {
   190  		var errorDistributor:LoadStartListener =
   191  			distributorControl.getDistributor(LoadStartListener);
   192  		errorDistributor.onLoadStart(resourceLoader);
   193  	}
   194  
   195  	/**
   196  	 * (implementation detail) Handles the response if a {@code FileLoader}
   197  	 * could not find a resource.
   198  	 * 
   199  	 * @param resourceLoader {@code FileLoader} that loaded the certain resource
   200  	 */
   201  	public function onLoadError(resourceLoader:FileLoader, errorCode:String, error):Boolean {
   202  		var errorDistributor:LoadErrorListener =
   203  			distributorControl.getDistributor(LoadErrorListener);
   204  		return errorDistributor.onLoadError(resourceLoader, errorCode, error);
   205  	}
   206  
   207  	/**
   208  	 * (implementation detail) Handles the response if a {@code FileLoader}
   209  	 * progressed loading.
   210  	 * 
   211  	 * @param resourceLoader {@code FileLoader} that loaded the certain resource
   212  	 */
   213  	public function onLoadProgress(resourceLoader:FileLoader):Void {
   214  		var progressDistributor:LoadProgressListener =
   215  			distributorControl.getDistributor(LoadProgressListener);
   216  		progressDistributor.onLoadProgress(resourceLoader);
   217  	}
   218  }