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 - 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 Transaction
    28   
    29  	@description :
    30  	
    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 : 04/02/05
    38  			- Portage en actionscript 2 pour le
    39  			compile time type checking
    40   -------------------------------------------
    41   */
    42  
    43  import org.omus.util.EventDispatcher;
    44  import org.omus.util.iObservable;
    45  import org.omus.util._Error;
    46  import org.omus.util._Class;
    47  
    48  import org.omus.db.DbTransactionPart;
    49  import org.omus.db.DbResult;
    50  
    51  import org.omus.msg.Message;
    52  import org.omus.msg.Envelope;
    53  import org.omus.msg.MessageRouter;
    54  import org.omus.msg.EnvelopeFactory;
    55  
    56  /**
    57   *	Cette classe gère les requêtes sur la base de données (lecture et écriture).
    58   *	Uniquement nécessaire en cas d'utilisation de nouvelles tables dans la base de données.
    59   *	Les requêtes sont effectuées via le fichier dbCustom.xml
    60   *	<p>
    61   *	Evénements auxquels s'abonner :
    62   *	<ul>
    63   *	<li>onResult(result:DbResult)	Généré lorsque le résultat d'une requête est reçu.
    64   *										_param result		Résultat.
    65   *	</li><li>onError(error:_Error)			Généré à cause d'une mauvaise modification de propriété persistante.
    66   *	</li></ul></p>
    67   *	Elle est aggrémentée par composition des méthodes des sources d'événements (EventDispatcher).
    68   *	@see org.omus.util.EventDispatcher
    69   *	@see org.omus.util.iObservable
    70   *
    71   *	@author Jens Halm copyright http://www.spicefactory.org/
    72   *	@author erixtekila copyleft http://www.v-i-a.net 
    73   *	@version 1.2.0
    74   */
    75  class org.omus.db.DbTransaction implements iObservable
    76  {
    77  	//--------------------
    78  	// PROPRIETES
    79  	//--------------------
    80  	/**
    81  	 *	Elements d'une requête : DbWriter ou DbReader.
    82  	 */
    83  	private var parts:Array;
    84  	
    85  	/**
    86  	 *	Paramètre soumis au fichier xml <in>.
    87  	 */
    88  	private var params:Object;
    89  	
    90  	/**
    91  	 *	Un tableau associatif contenant la validité des transactions incluses.
    92  	 */
    93  	private var resultIDs:Object;
    94  	
    95  	/**
    96  	 *	Référence au système de génération d'événements.
    97  	 */
    98  	private var _eventSource:EventDispatcher;
    99  	
   100  	//--------------------
   101  	// CONSTRUCTEUR
   102  	//--------------------
   103  	/**
   104  	 *	L'objet DbTransaction dispose des méthodes d'EventDispatcher par composition.
   105  	 *	
   106  	 */
   107  	public function DbTransaction()
   108  	{
   109  		// Composition avec EventDispatcher
   110  		_eventSource = new EventDispatcher();
   111  		
   112  		// Propriétés
   113  		parts = new Array();
   114  		params = new Object();
   115  		resultIDs = new Object();
   116  		
   117  		// trace(this+ " installé.");
   118  	}
   119  	
   120  	
   121  	//--------------------
   122  	// METHODES PUBLIQUES
   123  	//--------------------
   124  	/**
   125  	 *	Utilisé dans un contexte littéral
   126  	 *	@return	Une chaine définissant l'objet
   127  	 */
   128  	public function toString():String
   129  	{
   130  		var s = "[Objet DbTransaction]";
   131  		s += "\norg.omus.db.DbTransaction:\nparts = " + org.omus.util.Log.formatArray(parts, 1);
   132  		s += "parameters = " + org.omus.util.Log.formatObject(params, 1);
   133  		return s;
   134  	}
   135  	
   136  	/**
   137  	 *	Définit un paramètre à soumettre à la base de donnée via dbCustom.xml.
   138  	 *	Ce paramètre doit correspondre au nœud <in>
   139  	 *
   140  	 *	@param name			Nom du critère.
   141  	 *	@param value		Un objet appartenant au framework Oregano.
   142  	 */
   143  	public function setParam (name:String, value:Object):Void
   144  	{
   145  		// TODO : Accès Singleton
   146  		var clazz = _Class.getInstance();
   147  		if (! clazz.checkArguments("org.omus.DbTransaction.setParam", [[name, "string", true]])) return;
   148  		var t = typeof(value);
   149  		if (t == "undefined" || t == "null" || t == "function")
   150  		{
   151  			// Logs internes
   152  			_global.oregano.iLog.error("clj-039","parameter name = " + name + " - value = " + value);
   153  			return;
   154  		}
   155  		params[name] = value;
   156  	}
   157  
   158  	/**
   159  	 *	Rajoute un élément dans la requête SQL.
   160  	 *
   161  	 *	@param	part		DbReader ou DbWriter selon quelle action effectuer sur la base.
   162  	 */
   163  	public function addPart (part:DbTransactionPart):Void
   164  	{
   165  		// TODO : Accès Singleton
   166  		var clazz = _Class.getInstance();
   167  		if (! clazz.checkArguments("org.omus.DbTransaction.addPart", [[part, org.omus.db.DbTransactionPart, true]])) return;
   168  		var id = part.obj.resultID;
   169  		var conf = part.obj.configID;
   170  		if ((typeof(id) != "string" && typeof(id) != "undefined") || typeof(conf) != "string")
   171  		{
   172  			// Logs internes
   173  			_global.oregano.iLog.error("clj-040","configID = " + conf + " - resultID = " + id);
   174  			return;
   175  		}
   176  		if (id != undefined) {
   177  			if (resultIDs[id] != undefined) 
   178  			{
   179  				// Logs internes
   180  				_global.oregano.iLog.error("clj-041","resultID = " + id);
   181  				return;
   182  			}
   183  			resultIDs[id] = true;
   184  		}
   185  		parts.push(part.obj);
   186  	}
   187  	
   188  	/**
   189  	 *	Envoie la totalité de la requête.
   190  	 *	Génère un événement onError aux observateurs.
   191  	 */
   192  	public function execute ():Void
   193  	{
   194  		if (parts.length == 0) 
   195  		{
   196  			// Broadcast
   197  			fireEvent("error", "onError", new _Error("dbe-013", "execute", new Array()));
   198  			return;
   199  		}
   200  		// Message
   201  		var msg = new Message("transaction");
   202  		var attach = msg.getAttachment();
   203  		attach.parts = parts;
   204  		attach.params = params;
   205  		// TODO : Accès Singleton
   206  		var envFactory = EnvelopeFactory.getInstance();
   207  		var env = envFactory.getOutgoing(msg, "database");
   208  		//  TODO : Accès Singleton
   209  		var msgRouter = MessageRouter.getInstance();
   210  		msgRouter.handleOutgoing(env, this, "execute", new Array(), null);
   211  	}
   212  	
   213  	//*** Implémentation de iObservable ***\
   214  	/**
   215  	 *	Notifie les observateurs d'un événement.
   216  	 *
   217  	 *	@param logLevel Une chaine caractérisant le niveau de logging de l'information.
   218  	 *	@param eventName Nom de l'événement.
   219  	 *	@param arg1		[option] Autant de paramêtres de voulu.
   220  	 */
   221  	private function fireEvent (logLevel:String, eventName:String):Void
   222  	{
   223  		_eventSource.fireEvent.apply (_eventSource, arguments);
   224  	}
   225  	
   226  	/**
   227  	 *	Ajoute un nouvel observateur.
   228  	 * 
   229  	 *	@param		listener Référence de l'observateur.
   230  	 *	@return Un booléen indiquant la réussite de l'opération.
   231  	 */
   232  	public function addListener (listener:Object):Boolean
   233  	{
   234  		return _eventSource.addListener(listener);
   235  	}
   236  	
   237  	/**
   238  	 *	Supprime un observateur.
   239  	 *
   240  	 *	@param		listener Référence de l'observateur.
   241  	 *	@return Un booléen indiquant la réussite de l'opération.
   242  	 */
   243  	public function removeListener (listener:Object):Boolean
   244  	{
   245  		return _eventSource.removeListener(listener);
   246  	}
   247  	
   248  	/**
   249  	 *	Supprime tous les abonnés.
   250  	 */
   251  	public function removeAllListeners ():Void
   252  	{
   253  		_eventSource.removeAllListeners();
   254  	}
   255  	
   256  	/**
   257  	 *	Retourne le nombre d'observateurs.
   258  	 *
   259  	 *	@return Le nombre d'observateurs enregistrés.
   260  	 */
   261  	public function countListeners ():Number
   262  	{
   263  		return _eventSource.countListeners();
   264  	}
   265  	
   266  	//*** Accusé de réception
   267  	// TODO : Implémenter iMessageHandler ?
   268  	/**
   269  	 *	Gestionnaire de l'accusé de réception du message résultant de la requête SQL.
   270  	 *	Génère un événement onResult ou onError aux observateurs.
   271  	 *
   272  	 *	@param env		Enveloppe du message retourné.
   273  	 */
   274  	public function handleMessage (env:Envelope):Void
   275  	{
   276  		var msg = env.getMessage();
   277  		var attach = msg.getAttachment();
   278  		var errCode = attach.error;
   279  		if (errCode == "ok") 
   280  		{
   281  			var result = new DbResult(attach.tables, attach.fields, attach.affRows);
   282  			// Broadcast
   283  			fireEvent("info", "onResult", result);
   284  		} else
   285  		{
   286  			// Broadcast
   287  			fireEvent("error", "onError", new _Error(errCode, "execute", new Array()));
   288  		}
   289  	}
   290  	
   291  	//--------------------
   292  	// METHODES PRIVEES
   293  	//--------------------
   294  	
   295  	
   296  	//--------------------
   297  	// METHODES STATIQUES
   298  	//--------------------
   299  	/**
   300  	 *	Utilisé dans un contexte littéral
   301  	 *
   302  	 *	@return Une chaine définissant l'objet.
   303  	 */
   304  	public static function toLog():String
   305  	{
   306  		return "[Objet DbTransaction]";
   307  	}
   308  }
   309