1  //!-- UTF8
     2  /*
     3  	Oregano Multiuser Server - Version 1.2.0 - January 4th, 2005
     4  
     5  	Web:  www.oregano-server.org
     6  	Mail: info@oregano-server.org
     7  
     8  	Copyright 2003 - 2004 Jens Halm / Cologne, Germany
     9  
    10      This library is free software; you can redistribute it and/or
    11      modify it under the terms of the GNU Lesser General Public
    12      License as published by the Free Software Foundation; either
    13      version 2.1 of the License, or (at your option) any later version.
    14  
    15      This library is distributed in the hope that it will be useful,
    16      but WITHOUT ANY WARRANTY; without even the implied warranty of
    17      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    18      Lesser General Public License for more details.
    19  
    20      You should have received a copy of the GNU Lesser General Public
    21      License along with this library; if not, write to the Free Software
    22      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23  */
    24  
    25  /*
    26  -------------------------------------------
    27  	Classe _Class
    28  
    29  	@description :
    30  	Incorpore des utilitaires.
    31  
    32  
    33  	@author Jens Halm copyright http://www.spicefactory.org/
    34  	@author erixtekila copyleft http://www.v-i-a.net  
    35  -------------------------------------------
    36  	version history :
    37  	1.2.0 : 29/12/04
    38  			- Portage en actionscript 2 pour le
    39  			compile time type checking
    40  			- Modification du nom de la méthode "implement" par "mix_in"
    41  			- checkArguments avec les types primitifs.
    42  -------------------------------------------
    43  */
    44  
    45  
    46  
    47  /**
    48  *	Classe d'utilitaires.
    49  *	Cette classe est implémentée en suivant le modèle Singleton.
    50  *	Un accès global à son instance est obtenu graçe à la méthode getInstance.
    51  *
    52  *	@author Jens Halm copyright http://www.spicefactory.org/
    53  	@author erixtekila copyleft http://www.v-i-a.net 
    54  *	@version 1.2.0
    55  */
    56  class org.omus.util._Class
    57  {
    58  	//--------------------
    59  	// PROPRIETES
    60  	//--------------------
    61  	private static var _instance:_Class;
    62  	/**
    63  	 *	Contient une référence vers les classes enregistrées.
    64  	 *	Permet la Réflection sur les classes.
    65  	 *	TODO : private ?
    66  	 */
    67  	
    68  	private var registered:Object;
    69  	/*
    70  	 *	Tableau associatif de correspondances de [type : raccourci].
    71  	 */
    72  	
    73  	public var typeToChar:Object;
    74  	/*
    75  	 *	Tableau associatif de correspondances de [raccourci : type].
    76  	 */
    77  	private var charToType:Object;
    78  	
    79  	/*
    80  	 *	Type de données supportées par le serveur.
    81  	 */
    82  	private var cellMap:Object;
    83  	
    84  	/**
    85  	 *	TODO
    86  	 */
    87  	private var propMap:Object;
    88  	
    89  	//--------------------
    90  	// CONSTRUCTEUR
    91  	//--------------------
    92  	/**
    93  	*	L'objet Session dispose des méthodes d'EventDispatcher.
    94  	*
    95  	*	@see org.omus.util.EventDispatcher
    96  	*/
    97  	private function _Class ()
    98  	{
    99  		registered = new Object();
   100  		typeToChar = {
   101  						boolean:"b",
   102  						int:"i",
   103  						long:"l",
   104  						float:"f",
   105  						string:"s",
   106  						date:"d",
   107  						array:"a",
   108  						object:"o",
   109  						table:"t"
   110  					};
   111  		charToType = {
   112  						b:"boolean",
   113  						i:"int",
   114  						l:"long",
   115  						f:"float",
   116  						s:"string",
   117  						d:"date",
   118  						a:"array",
   119  						o:"object",
   120  						t:"table"
   121  					};
   122  		cellMap = {
   123  					boolean:"boolean",
   124  					int:"number",
   125  					long:"number",
   126  					float:"number",
   127  					string:"string",
   128  					date:Date,
   129  					array:Array,
   130  					object:Object,
   131  					table:org.omus.data.Table
   132  					};
   133  		propMap = {
   134  					counter:"number",
   135  					largeString:"string",
   136  					largeArray:Array,
   137  					largeObject:Object,
   138  					largeTable:org.omus.data.Table
   139  					};
   140  		
   141  		// trace(this+ " installé.");
   142  	}
   143  	
   144  	//--------------------
   145  	// METHODES PUBLIQUES
   146  	//--------------------
   147  	/**
   148  	 *	Utilisé dans un contexte littéral.
   149  	 *
   150  	 *	@return Une chaine définissant l'objet.
   151  	*/
   152  	public function toString():String
   153  	{
   154  		return "[Objet _Class]";
   155  	}
   156  	
   157  	/** 
   158  	 *	Méthode d'enregistement pour la Réflection des classes.
   159  	 *
   160  	 *	@param name		Nom de la classe.
   161  	 *	@param constr	Référence à la classe à enregistrer.
   162  	 */
   163  	public function register (name:String, constr:Object):Void
   164  	{
   165  		// TODO : Accès Singleton
   166  		var clazz = _Class.getInstance();
   167  		var argCheck = [[name,"string",true],[constr,"function",true]];
   168  		if (! clazz.checkArguments("org.omus.clazz.register", argCheck)) return;
   169  		if (name == "PropertySet") {
   170  			// Logs internes
   171  			_global.oregano.iLog.error("clj-003","");
   172  			return;
   173  		}
   174  		registered[name] = constr;
   175  	}
   176  	
   177  	/**
   178  	 *	Retourne une référence à la classe par réflection.
   179  	 *
   180  	 *	@param name		Nom de la classe.
   181  	 *	@return Une référence à la classe.
   182  	 */
   183  	public function getConstructor (name:String):Object
   184  	{
   185  		return registered[name];
   186  	}
   187  	
   188  	//--------------------
   189  	// METHODES PUBLIQUES
   190  	//-------------------- NON DOCUMENTEES (réservées Oregano)
   191  	/**
   192  	 *	Vérifie que des arguments d'une fonction sont typées correctement.
   193  	 *	Certains types de données sont cruciaux pour le bon fonctionnement.
   194  	 *
   195  	 *	@param methodName	Nom de la méthode.
   196  	 *	@param params		Liste de listes.
   197  	 *						exemple :
   198  	 *						var argCheck = [[name,"string",true],[constr,"function",true]]
   199  	 *	@return Un booléen indiquant la réussite de la vérification.
   200  	 */
   201  	public function checkArguments (methodName:String, params:Array):Boolean
   202  	{
   203  		var l = params.length;
   204  		for (var i = 0; i < l; i++)
   205  		{
   206  			var p = params[i];
   207  			// ! TODO instanceof
   208  			if (! isInstance (p[0], p[1]))
   209  			{
   210  				if (p[2] || (typeof(p[0]) != "undefined" && typeof(p[0]) != "null"))
   211  				{
   212  					var str = "\nmethod name: " + methodName + "\n";
   213  					str += "argument index = " + i + "\n";
   214  					str += "required: " + typeToString(p[1]) + "\n";
   215  					str += "found:    " + objToString(p[0]);
   216  					// Logs internes
   217  					_global.oregano.iLog.error("clj-002",str);//TRACE(str);
   218  					return false;
   219  				}
   220  			}
   221  		}
   222  		return true;
   223  	}
   224  	
   225  	/**
   226  	 *	Renvoie une référence à un objet par réflection.
   227  	 *
   228  	 *	@param obj		Une référence à un objet.
   229  	 *	@return Référence à l'objet si sa classe est régie par la réflection, sinon null.
   230  	 */
   231  	public function getClassName (obj:Object):Object
   232  	{
   233  		var r = registered;		
   234  		for (var each:String in r) {
   235  			if (r[each].prototype == obj.__proto__) return each;
   236  		}
   237  		return null;
   238  	}
   239  	
   240  	/**
   241  	 *	Renvoie un type sous forme de chaine de caractères.
   242  	 *	Utile pour l'encodage.
   243  	 *
   244  	 *	@param		Le type de l'objet.
   245  	 *	@return Une chaine définissant le typage de l'objet.
   246  	 */
   247  	public function cellTypeToChar (typeName:String):String
   248  	{
   249  		return typeToChar[typeName];
   250  	}
   251  	
   252  	/**
   253  	 *	Renvoie une chaine du type du raccourci soumis.
   254  	 *
   255  	 *	@param char		Un identifiant raccourci d'un type. Ex : b=>"boolean".
   256  	 *	@return Une représentation du type.
   257  	 */
   258  	public function charToCellType (char:String):String
   259  	{
   260  		return charToType[char];
   261  	}
   262  	
   263  	/**
   264  	 *	Renvoie une chaine représentant la classe utilisée.
   265  	 *
   266  	 *	@param typeName		Nom du type recherché.
   267  	 *	@return Une représentation de la classe.
   268  	 */
   269  	public function cellTypeToClass (typeName:String):String
   270  	{
   271  		return cellMap[typeName];
   272  	}
   273  	
   274  	/**
   275  	 *	Renvoie une chaine représentant le type d'une classe.
   276  	 *
   277  	 *	@param typeName		Un identifiant de la propriété.
   278  	 *	@return				Une référence la classe.
   279  	 */
   280  	public function propTypeToClass (typeName:String):Object
   281  	{
   282  		var cl = cellMap[typeName];
   283  		if (typeof(cl) != "undefined") return cl;
   284  		return propMap[typeName];
   285  	}
   286  	
   287  	//--------------------
   288  	// METHODES STATIQUES
   289  	//--------------------
   290  	/**
   291  	 *	Accès global à la référence du Singleton
   292  	 *
   293  	 *	@return Une référence à la classe.
   294  	 */
   295  	public static function getInstance ():_Class
   296  	{
   297  		if(_instance == undefined) _instance = new _Class();
   298  		return _instance;
   299  	}
   300  	
   301  	/**
   302  	 *	Utilisé dans un contexte littéral
   303  	 *
   304  	 *	@return Une chaine définissant l'objet.
   305  	 */
   306  	public static function toLog():String
   307  	{
   308  		return "[Objet _Class]";
   309  	}
   310  	
   311  	/**
   312  	 *	Décore (de façon permanente et en runtime)
   313  	 *	une classe de nouvelles méthodes issues d'un objet instancié
   314  	 *	Remplace la méthode "implement" de la version originale Oregano.
   315  	 *
   316  	 *	@param constr		Référence au constructeur de le classe à décorer
   317  	 *	@param obj			Référence à l'objet contenant les méthodes
   318  	 *	@deprecated La technique des mix-ins a été remplacée par la composition
   319  	 */
   320  	public static function mix_in (constr:Function, obj:Object):Void
   321  	{
   322  		var p = constr.prototype;
   323  		for (var each:String in obj)
   324  		{
   325  			p[each] = obj[each];
   326  		}
   327  	}
   328  	
   329  		
   330  	/**
   331  	 *	Permet de connaître le type d'un objet.
   332  	 *	! TODO : instanceof
   333  	 *	
   334  	 *	@param obj		Un objet.
   335  	 *	@param type		Son type à évaluer 
   336  	 *					Pour le moment string, number et tous les résultats de typeof sinon 
   337  	 *					une référence à une classe.
   338  	 *	@return true si du même type.
   339  	 */
   340  	public static function isInstance (obj:Object, type:Object):Boolean
   341  	{
   342  		var mode = typeof (type);
   343  		if (mode == "string")
   344  		{
   345  			var ok = (typeof(obj) == type);
   346  			if (ok && type == "number") return (!isNaN(obj));
   347  			else return ok;
   348  		} else return obj instanceof type;
   349  	}	
   350  	//--------------------
   351  	// METHODES PRIVEES
   352  	//--------------------
   353  	/**
   354  	 *	Renvoie le type de classe de l'objet spécifié.
   355  	 *
   356  	 *	@param clazz		Référence à l'objet.
   357  	 *	@return Une chaîne définissant l'objet.
   358  	 */
   359  	private function typeToString (clazz:Function):String
   360  	{
   361  		if (typeof(clazz) == "string") return String(clazz);
   362  		if (clazz.toString != Object.prototype) return "Object";
   363  		if (clazz.prototype == Object.prototype) return "Object";
   364  		if (clazz.prototype == Array.prototype) return "Array";
   365  		return clazz.toString();
   366  	}
   367  	
   368  	/**
   369  	 *	Renvoie le nom du constructeur lorsque c'est possible.
   370  	 *
   371  	 *	@param obj		Objet recherché.
   372  	 *	@return Le nom du constructeur de l'objet.
   373  	 */
   374  	private function objToString (obj:Object):String
   375  	{
   376  		if (typeof(obj) != "object") return typeof(obj);
   377  		var constr = obj.constructor.toString();
   378  		if (constr.substr(0, 9) == "org.omus.") return constr;
   379  		if (obj instanceof Array) return "Array";
   380  		return "Object";
   381  	}
   382  }
   383