<commit_before>/* 
- Extend ObjectProxy? - 11k footprint! #*@!^&%  - but Proxy is in the player!
*/
package ras3r 
{
	import ras3r.reactive_resource.*;

	import fl.data.DataProvider;
	import fl.events.DataChangeEvent;
	import flash.events.*;
	import flash.net.*;
	import flash.system.*;
	import flash.utils.*;
	import mx.events.PropertyChangeEvent;
	import mx.utils.ObjectProxy;

	//import code.google.as3httpclient.*;

	use namespace flash_proxy;

	// required if you want to use BindingUtils or ChangeWatcher on dynamic properties!
	// curly braces bindings in MXML cause this directive to be created at compile-time,
	// however AS3 runtime bindings do NOT.
	[Bindable("propertyChange")]

	dynamic public class ReactiveResource extends ObjectProxy
	{
		XML.prettyPrinting = false;

		// >>> STATIC PROPERTIES
		// >>> STATIC METHODS
		static private function add_observers (o:*, options:Hash, complete:String = 'complete') :void
		{
			// after_find == complete
			var after_find:Function;
		 	if (options.complete is Function)
			{
				Logger.info('ReactiveResource.find: "complete: func" handler syntax deprecated in favor of "after_find: func"');
				after_find = options.remove('complete');
			}
			else
			{
				after_find = options.remove('after_find');
			}
			if (after_find is Function) o.addEventListener(complete, after_find);

			// custom after_* hooks:
			for (var key:String in options)
			{
				if (key.indexOf('after_') == 0)
				{
					o.addEventListener(key, options.remove(key));
				}
			}
		}

		static private function collection_name (self:Class) :String // pseudo-equivalent to RoR's table_name
		{
			return Inflector.restify(Inflector.demodulize(getQualifiedClassName(self)));
		}

		static public function collection_path (self:Class, prefix_options:Object = null, query_options:Object = null) :String // pseudo-equivalent to RoR's table_name
		{
			var url:String = prefix_source(self, prefix_options);
						
			url += '.xml';

			return url;
		}
		
		static public function element_path (self:Class, id:Object, prefix_options:Object = null, query_options:Object = null) :String // pseudo-equivalent to RoR's table_name
		{
			var url:String = prefix_source(self, prefix_options);
			
			url += '/' + id + '.xml';

			return url;
		}

		// Rails-inspired finder
		// self: reference to class (Product, Store, etc)
		// scope: 'all' or 'one' or '43'
		// args: { store_id: 43 } or { from: 'http://www.example.com/items/3.xml' }
		//static public function find (self:Class, scope:*, options:Object = null) :*
		static public function find (...args) :*
		{
			var self:Class = (args[0] is Class) ? (args.shift()) : ReactiveResource;
			var scope:* = args.shift();
			//var options:Object = args.shift();
			var options:Hash = new Hash(args.shift());

			switch (scope)
			{
				case 'all': 	return find_all(self, options); break;
				case 'one': 	return find_one(self, options); break;
				default: 		return find_single(self, scope, options);
			}
		}

		static private function find_all (self:Class, options:Hash = null) :DataProvider
		{
			// pop from: param
			var from:String = options.remove('from');

			// pop from: param
			var limit:String = options.remove('limit');

			// create empty collection
			var collection:DataProvider = new DataProvider();

			// bubble DataChange event to 'complete' handler
			//if (options && options.complete is Function) collection.addEventListener(DataChangeEvent.DATA_CHANGE, options.remove('complete'));
			// wire event handlers (aka 'observers')
			add_observers(collection, options, DataChangeEvent.DATA_CHANGE);

			// execute request
/*			get((from ? from : collection_path(self, options)), Delegate.create(after_find_all, self, collection, limit), onFindAllFault, options);*/
/*			static public function after_find_all (e:Event, self:Class, collection:DataProvider, limit:uint) :void*/
			var after_find:Function = function (e:Event) :void
			{
				after_find_all(e, self, collection, uint(limit));
			};
			get((from ? from : collection_path(self, options)), after_find, onFindAllFault, options);

			// return collection (may be empty: listen for 'dataChange'!)
			return collection;
		}

		static private function find_one (self:Class, options:Hash = null) :*
		{
			// pop from: param
			var from:String = options.remove('from');

			// create new instance of Class
			var rr:* = new self();

			// wire event handlers (aka 'observers')
			// wire up 'complete' and all 'after_*' events/listeners passed in options Hash
			add_observers(rr, options);

			// execute request
			get(from, rr.after_find, rr.after_find_failed, options);

			// return item (may be empty: listen for 'complete'!)
			return rr;
		}

		static private function find_single (self:Class, id:int, args:Hash = null) :*
		{
			// assemble from: path
			args.from = element_path(self, id, args);

			// create new instance of Class
			var rr:* = find_one(self, args);

			// assign id
			rr.id = id;

			// return item (may be empty: listen for 'complete'!)
			return rr;
		}

		// TODO: move to a connection management object of some sort
		protected static function get (path:String, onResult:Function, onFault:Function, args:Object = null) :void
		{
			var request:Request = new Request('get', path);

			request.addEventListener('complete', onResult);
			request.addEventListener('status', on_response_status);
			request.addEventListener('ioError', onFault);

			if (args)
			{
				if (args.fault is Function) request.addEventListener('ioError', args.fault);
				if (args.progress is Function) request.addEventListener('progress', args.progress);
				if (args.status is Function) request.addEventListener('httpStatus', args.status);
			}

			request.load();<commit_msg>ReactiveResource support for UUIDs as IDs<commit_after>/* 
- Extend ObjectProxy? - 11k footprint! #*@!^&%  - but Proxy is in the player!
*/
package ras3r 
{
	import ras3r.reactive_resource.*;

	import fl.data.DataProvider;
	import fl.events.DataChangeEvent;
	import flash.events.*;
	import flash.net.*;
	import flash.system.*;
	import flash.utils.*;
	import mx.events.PropertyChangeEvent;
	import mx.utils.ObjectProxy;

	//import code.google.as3httpclient.*;

	use namespace flash_proxy;

	// required if you want to use BindingUtils or ChangeWatcher on dynamic properties!
	// curly braces bindings in MXML cause this directive to be created at compile-time,
	// however AS3 runtime bindings do NOT.
	[Bindable("propertyChange")]

	dynamic public class ReactiveResource extends ObjectProxy
	{
		XML.prettyPrinting = false;

		// >>> STATIC PROPERTIES
		// >>> STATIC METHODS
		static private function add_observers (o:*, options:Hash, complete:String = 'complete') :void
		{
			// after_find == complete
			var after_find:Function;
		 	if (options.complete is Function)
			{
				Logger.info('ReactiveResource.find: "complete: func" handler syntax deprecated in favor of "after_find: func"');
				after_find = options.remove('complete');
			}
			else
			{
				after_find = options.remove('after_find');
			}
			if (after_find is Function) o.addEventListener(complete, after_find);

			// custom after_* hooks:
			for (var key:String in options)
			{
				if (key.indexOf('after_') == 0)
				{
					o.addEventListener(key, options.remove(key));
				}
			}
		}

		static private function collection_name (self:Class) :String // pseudo-equivalent to RoR's table_name
		{
			return Inflector.restify(Inflector.demodulize(getQualifiedClassName(self)));
		}

		static public function collection_path (self:Class, prefix_options:Object = null, query_options:Object = null) :String // pseudo-equivalent to RoR's table_name
		{
			var url:String = prefix_source(self, prefix_options);
						
			url += '.xml';

			return url;
		}
		
		static public function element_path (self:Class, id:Object, prefix_options:Object = null, query_options:Object = null) :String // pseudo-equivalent to RoR's table_name
		{
			var url:String = prefix_source(self, prefix_options);
			
			url += '/' + id + '.xml';

			return url;
		}

		// Rails-inspired finder
		// self: reference to class (Product, Store, etc)
		// scope: 'all' or 'one' or '43'
		// args: { store_id: 43 } or { from: 'http://www.example.com/items/3.xml' }
		//static public function find (self:Class, scope:*, options:Object = null) :*
		static public function find (...args) :*
		{
			var self:Class = (args[0] is Class) ? (args.shift()) : ReactiveResource;
			var scope:* = args.shift();
			//var options:Object = args.shift();
			var options:Hash = new Hash(args.shift());

			switch (scope)
			{
				case 'all': 	return find_all(self, options); break;
				case 'one': 	return find_one(self, options); break;
				default: 		return find_single(self, scope, options);
			}
		}

		static private function find_all (self:Class, options:Hash = null) :DataProvider
		{
			// pop from: param
			var from:String = options.remove('from');

			// pop from: param
			var limit:String = options.remove('limit');

			// create empty collection
			var collection:DataProvider = new DataProvider();

			// bubble DataChange event to 'complete' handler
			//if (options && options.complete is Function) collection.addEventListener(DataChangeEvent.DATA_CHANGE, options.remove('complete'));
			// wire event handlers (aka 'observers')
			add_observers(collection, options, DataChangeEvent.DATA_CHANGE);

			// execute request
/*			get((from ? from : collection_path(self, options)), Delegate.create(after_find_all, self, collection, limit), onFindAllFault, options);*/
/*			static public function after_find_all (e:Event, self:Class, collection:DataProvider, limit:uint) :void*/
			var after_find:Function = function (e:Event) :void
			{
				after_find_all(e, self, collection, uint(limit));
			};
			get((from ? from : collection_path(self, options)), after_find, onFindAllFault, options);

			// return collection (may be empty: listen for 'dataChange'!)
			return collection;
		}

		static private function find_one (self:Class, options:Hash = null) :*
		{
			// pop from: param
			var from:String = options.remove('from');

			// create new instance of Class
			var rr:* = new self();

			// wire event handlers (aka 'observers')
			// wire up 'complete' and all 'after_*' events/listeners passed in options Hash
			add_observers(rr, options);

			// execute request
			get(from, rr.after_find, rr.after_find_failed, options);

			// return item (may be empty: listen for 'complete'!)
			return rr;
		}

		static private function find_single (self:Class, id:String, args:Hash = null) :*
		{
			// assemble from: path
			args.from = element_path(self, id, args);

			// create new instance of Class
			var rr:* = find_one(self, args);

			// assign id
			rr.id = id;

			// return item (may be empty: listen for 'complete'!)
			return rr;
		}

		// TODO: move to a connection management object of some sort
		protected static function get (path:String, onResult:Function, onFault:Function, args:Object = null) :void
		{
			var request:Request = new Request('get', path);

			request.addEventListener('complete', onResult);
			request.addEventListener('status', on_response_status);
			request.addEventListener('ioError', onFault);

			if (args)
			{
				if (args.fault is Function) request.addEventListener('ioError', args.fault);
				if (args.progress is Function) request.addEventListener('progress', args.progress);
				if (args.status is Function) request.addEventListener('httpStatus', args.status);
			}

			request.load();
{'fraction_non_alphanumeric': 0.12775215385954225, 'fraction_numerical': 0.002262640327212601, 'mean_word_length': 3.76056338028169, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '336206', 'n_tokens_mistral': 4029, 'n_tokens_neox': 3445, 'n_words': 1006}