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.data.holder.Map;
    18  import org.as2lib.data.type.Bit;
    19  import org.as2lib.data.type.Byte;
    20  import org.as2lib.env.event.distributor.CompositeEventDistributorControl;
    21  import org.as2lib.io.file.LoadStartListener;
    22  import org.as2lib.io.file.LoadCompleteListener;
    23  import org.as2lib.io.file.LoadProgressListener;
    24  import org.as2lib.io.file.LoadErrorListener;
    25  import org.as2lib.io.file.FileLoader;
    26  import org.as2lib.io.file.File;
    27  import org.as2lib.app.exec.Executable;
    28  import org.as2lib.app.exec.AbstractTimeConsumer;
    29  import org.as2lib.env.except.IllegalArgumentException;
    30  
    31  /**
    32   * {@code AbstractFileLoader} is a abstract implementation for a {@code FileLoader}.
    33   * 
    34   * <p>Extend {@code AbstractFileLoader} to implement most methods required
    35   * for a {@code ResourceLoader}.
    36   * 
    37   * @author Martin Heidegger
    38   * @version 1.0
    39   */
    40  class org.as2lib.io.file.AbstractFileLoader extends AbstractTimeConsumer implements FileLoader {
    41  	
    42  	/** Error code if a certain file could not be found. */
    43  	public static var FILE_NOT_FOUND_ERROR:String = "File not found";
    44  	
    45  	/** URI for the request. */
    46  	private var uri:String;
    47  	
    48  	/** Method to pass resource request parameters. */
    49  	private var method:String = "POST";
    50  	
    51  	/** Parameters to be used for the resource request. */
    52  	private var parameters:Map;
    53  	
    54  	/** Faster access to internal event handling. */
    55  	private var dC:CompositeEventDistributorControl;
    56  	
    57  	/** {@link Executable} to be executed on finish of loading. */
    58  	private var callBack:Executable;
    59  	
    60  	/**
    61  	 * Constructs a new {@code AbstractFileLoader}
    62  	 * 
    63  	 * <p>Pass all arguments from the extended constructor by using super to 
    64  	 * add the parameters to the instance.
    65  	 */
    66  	function AbstractFileLoader(Void) {
    67  		super();
    68  		dC = distributorControl;
    69  		acceptListenerType(LoadStartListener);
    70  		acceptListenerType(LoadCompleteListener);
    71  		acceptListenerType(LoadProgressListener);
    72  		acceptListenerType(LoadErrorListener);
    73  	}
    74  	
    75  	/**
    76  	 * Returns for the location of the resource that was requested to load.
    77  	 * 
    78  	 * @return location of the resource to load
    79  	 */
    80  	public function getUri(Void):String {
    81  		return uri;
    82  	}
    83  	
    84  	/**
    85  	 * Returns the pecentage of the file that has been loaded.
    86  	 * 
    87  	 * <p>Evaluates the current percentage of the execution by using
    88  	 * {@code getBytesTotal} and {@code getBytesLoaded}.
    89  	 * 
    90  	 * <p>Returns {@code null} if the percentage is not evaluable
    91  	 * 
    92  	 * @return percentage of the file that has been loaded
    93  	 */
    94  	public function getPercentage(Void):Number {
    95  		if (hasStarted() || hasFinished()) {
    96  			var percentage:Number = (
    97  				100  
    98  				/ getBytesTotal().getBytes()
    99  				* getBytesLoaded().getBytes()
   100  				);
   101  			if (percentage >= 100) {
   102  				percentage = 100;
   103  			}
   104  			return percentage;
   105  		} else {
   106  			return null;
   107  		}
   108  	}
   109  	/**
   110  	 * Returns the current transfer rate for the execution.
   111  	 * 
   112  	 * <p>Evalutes the transfer rate by using {@code getBytesLoaded} and
   113  	 * {@code getDuration}.
   114  	 * 
   115  	 * @return transfer rate in bit (per second)
   116  	 */
   117  	public function getTransferRate(Void):Bit {
   118  		return new Bit(getBytesLoaded().getBit()/getDuration().inSeconds());
   119  	}
   120  
   121  	/**
   122  	 * Stub implementation for the amount of bytes that were loaded.
   123  	 * 
   124  	 * @return {@code null} for not evaluable
   125  	 */
   126  	public function getBytesTotal(Void):Byte {
   127  		return null;
   128  	}
   129  	
   130  	/**
   131  	 * Stub implementation for the amount of bytes to be loaded.
   132  	 * 
   133  	 * @return {@code null} for not evaluable
   134  	 */
   135  	public function getBytesLoaded(Void):Byte {
   136  		return null;
   137  	}
   138  	
   139  	/**
   140  	 * Prepares the loading of a certain file.
   141  	 * 
   142  	 * <p>To be overwritten with the concrete load implentation. Do not forget 
   143  	 * to apply super.load().
   144  	 * 
   145  	 * @param uri location of the resource to load
   146  	 * @param parameters (optional) parameters for loading the resource
   147  	 * @param method (optional) POST/GET as method for submitting the parameters,
   148  	 *        default method used if {@code method} was not passed-in is POST.
   149  	 * @param callBack (optional) {@link Executable} to be executed after the
   150  	 *        the resource was loaded.
   151  	 */
   152  	public function load(uri:String, method:String, parameters:Map, callBack:Executable):Void {
   153  		if (!uri) {
   154  			throw new IllegalArgumentException("Url has to be set for starting the process.", this, arguments);
   155  		}
   156  		this.uri = uri;
   157  		this.parameters = parameters;
   158  		this.callBack = callBack;
   159  		this.method = (method.toUpperCase() == "GET") ? "GET" : "POST";
   160  		started = true;
   161  		finished = false;
   162  		startTime = getTimer();
   163  	}
   164  	
   165  	/**
   166  	 * Returns the {@code method} to pass request parameters for request.
   167  	 * 
   168  	 * @return method to pass request parameters
   169  	 */
   170  	public function getParameterSubmitMethod(Void):String {
   171  		return method;
   172  	}
   173  
   174  	/**
   175  	 * Sets the {@code parameters} for the request to the resource.
   176  	 * 
   177  	 * <p>Returns {@code null} if no parameters has been set.
   178  	 * 
   179  	 * @return parameters to be passed with the resource request
   180  	 */
   181  	public function getParameters(Void):Map {
   182  		return parameters;
   183  	}
   184  
   185  	/**
   186  	 * Returns the loaded resource.
   187  	 * 
   188  	 * @return the loaded resource
   189  	 * @throws org.as2lib.io.file.ResourceNotLoadedException if the resource has
   190  	 *         not been loaded yet
   191  	 */
   192  	public function getFile(Void):File {
   193  		return null;
   194  	}
   195  	
   196  	/**
   197  	 * Internal helper to send the start event.
   198  	 */
   199  	private function sendStartEvent(Void):Void {
   200  		var startDistributor:LoadStartListener
   201  			= dC.getDistributor(LoadStartListener);
   202  		startDistributor.onLoadStart(this);
   203  	}
   204  	
   205  	/**
   206  	 * Internal helper to send the error event.
   207  	 * 
   208  	 * @param code errorcode for the certain error
   209  	 * @param error information to the certain error
   210  	 */
   211  	private function sendErrorEvent(code:String, error):Void {
   212  		var errorDistributor:LoadErrorListener
   213  			= dC.getDistributor(LoadErrorListener);
   214  		errorDistributor.onLoadError(this, code, error);
   215  	}
   216  	
   217  	/**
   218  	 * Internal helper to send the complete event.
   219  	 * 
   220  	 * <p>Event to be sent if the file was completly loaded.
   221  	 */
   222  	private function sendCompleteEvent(Void):Void {
   223  		var completeDistributor:LoadCompleteListener
   224  			= dC.getDistributor(LoadCompleteListener);
   225  		completeDistributor.onLoadComplete(this);
   226  		callBack.execute(this);
   227  	}
   228  	
   229  	/**
   230  	 * Internal helper to send the progress event.
   231  	 */
   232  	private function sendProgressEvent(Void):Void {
   233  		var completeDistributor:LoadProgressListener
   234  			= dC.getDistributor(LoadProgressListener);
   235  		completeDistributor.onLoadProgress(this);
   236  	}
   237  
   238  }