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 Mail 28 29 @description : 30 Messages pesistants. 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 - Pas de return dans un constructeur. 41 - Utilisation de l'accès Singleton aux classes User 42 ------------------------------------------- 43 */ 44 45 import org.omus.util.EventDispatcher; 46 import org.omus.util.iObservable; 47 import org.omus.util._Error; 48 49 import org.omus.msg.MessageHandler; 50 import org.omus.msg.iMessageHandler; 51 import org.omus.msg.Envelope; 52 import org.omus.msg.EnvelopeFactory; 53 import org.omus.msg.Mailbox; 54 import org.omus.msg.Message; 55 import org.omus.msg.MessageRouter; 56 57 import org.omus.util._Class; 58 59 import org.omus.core.User; 60 61 /** 62 * Cette classe gère des objets Mail. 63 * Chaque client a deux mailBox : outBox and inBox. 64 * La référence à celles-ci s'obtient via User. 65 * <p> 66 * Evénements auxquels s'abonner : 67 * <ul> 68 * <li>onSend(mail:Mail) Généré lorsqu'un Mail a été soumis correctement. 69 * _param mail Copie du Mail envoyé. 70 * </li><li>onLoadAttachment(mail:Mail) Généré lorsque le fichier joint du Mail est fini de charger. 71 * _param mail Copie du Mail envoyé. 72 * </li><li>onMark(mail:Mail) Généré lorsque l'état de lecture du message a été modifié. 73 * _param mail Copie du Mail envoyé. 74 * </li><li>onRemove(mail:Mail) Généré lorsque le mùessage a été supprimé de sa boîte. 75 * _param mail Copie du Mail envoyé. 76 * </li><li>onError(mail:Mail, error:_Error) Généré lors d'une erreur de modification de l'état du Mail. 77 * _param mail Copie du Mail envoyé. 78 * _param error Erreur. 79 * </li></ul></p> 80 * Cette classe est aggrémentée par composition des méthodes des sources d'événements (EventDispatcher). 81 * Elle est aggrémentée par composition de la classe MessageHandler. 82 * 83 * @see org.omus.util.EventDispatcher 84 * @see org.omus.util.iObservable 85 * @see org.omus.msg.MessageHandler 86 * @see org.omus.msg.iMessageHandler 87 * 88 * @see org.omus.core.User#getInBox 89 * @see org.omus.core.User#getOutBox 90 * 91 * @author Jens Halm copyright http://www.spicefactory.org/ 92 * @author erixtekila copyleft http://www.v-i-a.net 93 * @version 1.2.0 94 */ 95 class org.omus.msg.Mail implements iObservable, iMessageHandler 96 { 97 //-------------------- 98 // PROPRIETES 99 //-------------------- 100 /** 101 * Type de boîte contenant le message courant. 102 */ 103 private var box:Mailbox; 104 105 /** 106 * Conteneur des données du message courant. 107 */ 108 public var row:Object; 109 110 /** 111 * Conteneur des informations liées au message courant. 112 * Les objets Mail n'ont pas de body, tout message doit donc être attaché. 113 * Tous les objets valides du framework peuvent être joints. 114 */ 115 private var attach:Object; 116 117 /** 118 * Référence au système de génération d'événements. 119 */ 120 private var _eventSource:EventDispatcher; 121 122 /** 123 * Référence à la classe MessageHandler; 124 */ 125 private var _messageHandler:MessageHandler; 126 127 //-------------------- 128 // CONSTRUCTEUR 129 //-------------------- 130 /** 131 * L'objet Mail dispose des méthodes d'EventDispatcher 132 * et de celles de MessageHandler par composition. 133 * 134 * @param subj Sujet du mail. 135 * @see org.omus.util.EventDispatcher 136 * @see org.omus.util.iObservable 137 * @see org.omus.msg.MessageHandler 138 * @see org.omus.msg.iMessageHandler 139 */ 140 public function Mail (subj:String) 141 { 142 // Composition avec EventDispatcher 143 _eventSource = new EventDispatcher(); 144 // Composition avec MessageHandler 145 _messageHandler = new MessageHandler(); 146 147 // Initialisation des événements 148 _messageHandler.initMessageHandler(this); 149 150 // Propriétés 151 // TODO : Accès Singleton 152 var clazz = _Class.getInstance(); 153 // TODO : Constructeur sans return. if (! _global.org.omus.clazz.checkArguments("new org.omus.Mail",[[subj,"string",true]])) return; 154 if (clazz.checkArguments("new org.omus.Mail", [[subj, "string", true]])) 155 { 156 box = null; 157 row = new Object(); 158 // Contenu du Mail 159 row.subject = subj; 160 row.dt = new Date(); 161 row.readFlag = false; 162 row.username = null; 163 attach = new Object(); 164 165 // Callbacks des envois de messages. 166 addHandler("loadMail","handleLoad"); 167 addHandler("removeMail","handleRemove"); 168 addHandler("markMail","handleMark"); 169 addHandler("sendMail","handleSend"); 170 } 171 172 // trace(this+ " installé."); 173 } 174 175 176 //-------------------- 177 // METHODES PUBLIQUES 178 //-------------------- 179 /** 180 * Utilisé dans un contexte littéral 181 * @return Une chaine définissant l'objet 182 */ 183 public function toString():String 184 { 185 var s = "[Objet Mailbox]"; 186 s += "\norg.omus.Mail:\n==========\nmsgID = " + row.msgID; 187 s += "\nmailbox = " + getMailbox().getType(); 188 s += "\nsubject = " + getSubject(); 189 s += "\nsender = " + getSender(); 190 s += "\nrecipient = " + getRecipient(); 191 s += "\ndate = " + getDate(); 192 s += "\nunread = " + isUnread(); 193 s += "\nattachment = "; 194 if (attach == null) 195 { 196 s += "not loaded"; 197 } else 198 { 199 s+= org.omus.util.Log.formatObject(attach, 1); 200 } 201 return s; 202 } 203 204 /** 205 * Initailisation d'un message. 206 */ 207 public function init (box:Mailbox, row:Object):Void 208 { 209 this.box = box; 210 this.row = row; 211 attach = null; 212 } 213 214 /** 215 * Renvoie la boîte de réception du message courant. 216 * 217 * @return Une référence à Mailbox entrante ou sortante. 218 */ 219 public function getMailbox ():Mailbox 220 { 221 return box; 222 } 223 224 /** 225 * Renvoie le sujet du message courant. 226 * 227 * @return Le sujet sous forme de chaîne. 228 */ 229 public function getSubject ():String 230 { 231 return row.subject; 232 } 233 234 /** 235 * Renvoie l'envoyeur du message courant. 236 * 237 * @return Le nom du membre. 238 */ 239 public function getSender ():String 240 { 241 // TODO : Utilise l'accès Singleton à User 242 var user = User.getInstance(); 243 if (box == user.getOutBox() || box == null) 244 { 245 return user.getName(); 246 } else 247 { 248 return row.username; 249 } 250 } 251 252 /** 253 * Renvoie le destinataire du message courant. 254 * 255 * @return Le nom de l'utilisateur destinataire. 256 */ 257 public function getRecipient ():String 258 { 259 // TODO : Utilise l'accès Singleton à User 260 var user = User.getInstance(); 261 if (box == user.getInBox()) 262 { 263 return user.getName(); 264 } else 265 { 266 return row.username; 267 } 268 } 269 270 /** 271 * Renvoie le message joint comprenant notamment le body du message. 272 * Celui-ci se chargera à la demande avec la méthode loadAttachment. 273 * 274 * @return L'attachement joint au message courant. Tous les types du framework Oregano sont permis. 275 * @see org.omus.msg.Mail#loadAttachment 276 */ 277 public function getAttachment ():Object 278 { 279 return attach; 280 } 281 282 /** 283 * Renvoie la date d'envoi du message courant. 284 * 285 * @return Une date d'envoi. 286 */ 287 public function getDate ():Date 288 { 289 return row.dt; 290 } 291 292 /** 293 * Renvoie l'état de lecture du message courant. 294 * 295 * @return true si le message n'est pas lu. 296 */ 297 public function isUnread ():Boolean 298 { 299 return ! row.readFlag; 300 } 301 302 /** 303 * Renseigne l'état de chargment de l'attachement du message courant. 304 * 305 * @return true si l'attachement est chargé sur le poste client. 306 */ 307 public function isLoaded ():Boolean 308 { 309 return (attach != null); 310 } 311 312 /** 313 * Envoi du message courant. 314 * Une copie est placée automatiquement dans l'outBox. 315 * 316 * @param recipient Le nom du destinataire. 317 */ 318 public function send (recipient:String):Void 319 { 320 // TODO : Accès Singleton 321 var clazz = _Class.getInstance(); 322 if (! clazz.checkArguments("send", [[recipient, "string", true]])) return; 323 324 // Message 325 var msg:Message = new Message("sendMail"); 326 var attach = msg.getAttachment(); 327 attach.username = recipient; 328 attach.subject = row.subject; 329 attach.message = this.attach; 330 331 // TODO : Accès Singleton 332 var envFactory:EnvelopeFactory = EnvelopeFactory.getInstance(); 333 var env = envFactory.getOutgoing(msg,"mailbox"); 334 // TODO : Accès Singleton 335 var msgRouter:MessageRouter = MessageRouter.getInstance(); 336 msgRouter.handleOutgoing(env, this, "send", arguments, null); 337 } 338 339 /** 340 * Charge le message joint du Mail courant. 341 */ 342 public function loadAttachment ():Void 343 { 344 if (box == null) 345 { 346 // Logs internes 347 _global.oregano.iLog.error("clj-043", ""); 348 return; 349 } 350 var env = getMessage("loadMail"); 351 // TODO : Accès Singleton 352 var msgRouter = MessageRouter.getInstance(); 353 msgRouter.handleOutgoing(env, this, "send", arguments, null); 354 } 355 356 /** 357 * Supprime ce message de la boîte auquel il appartient. 358 */ 359 public function remove ():Void 360 { 361 if (box == null) 362 { 363 // Logs internes 364 _global.oregano.iLog.error("clj-044",""); 365 return; 366 } 367 var env = getMessage("removeMail"); 368 // TODO : Accès Singleton 369 var msgRouter = MessageRouter.getInstance(); 370 msgRouter.handleOutgoing(env, this, "remove", arguments, null); 371 } 372 373 /** 374 * Signale le message comme lu / non lu. 375 * 376 * @param asRead true si lu, false pour non lu. 377 */ 378 public function mark (asRead:Boolean):Void 379 { 380 // TODO : Accès Singleton 381 var clazz = _Class.getInstance(); 382 if (! clazz.checkArguments("mark", [[asRead, "boolean", true]])) return; 383 384 if (box == null) 385 { 386 // Logs internes 387 _global.oregano.iLog.error("clj-045", ""); 388 return; 389 } 390 var env = getMessage("markMail"); 391 env.getMessage().getAttachment().asRead = asRead; 392 // TODO : Accès Singleton. 393 var msgRouter = MessageRouter.getInstance(); 394 msgRouter.handleOutgoing(env, this, "mark", arguments, null); 395 } 396 397 //*** Implémentation de iObservable ***\ 398 /** 399 * Notifie les observateurs d'un événement. 400 * 401 * @param logLevel Une chaine caractérisant le niveau de logging de l'information. 402 * @param eventName Nom de l'événement. 403 * @param arg1 [option] Autant de paramêtres de voulu. 404 */ 405 private function fireEvent (logLevel:String, eventName:String):Void 406 { 407 _eventSource.fireEvent.apply (_eventSource, arguments); 408 } 409 410 /** 411 * Ajoute un nouvel observateur. 412 * 413 * @param listener Référence de l'observateur. 414 * @return Un booléen indiquant la réussite de l'opération. 415 */ 416 public function addListener (listener:Object):Boolean 417 { 418 return _eventSource.addListener(listener); 419 } 420 421 /** 422 * Supprime un observateur. 423 * 424 * @param listener Référence de l'observateur. 425 * @return Un booléen indiquant la réussite de l'opération. 426 */ 427 public function removeListener (listener:Object):Boolean 428 { 429 return _eventSource.removeListener(listener); 430 } 431 432 /** 433 * Supprime tous les abonnés. 434 */ 435 public function removeAllListeners ():Void 436 { 437 _eventSource.removeAllListeners(); 438 } 439 440 /** 441 * Retourne le nombre d'observateurs. 442 * 443 * @return Le nombre d'observateurs enregistrés. 444 */ 445 public function countListeners ():Number 446 { 447 return _eventSource.countListeners(); 448 } 449 450 451 //*** Implémentation de iMessageHandler ***\\ 452 /** 453 * Active la gestion d'un type de message par accusé de réception 454 * en fonction du contenu de son enveloppe. 455 * 456 * @param env Une référence à l'enveloppe. 457 */ 458 public function handleMessage (env:Envelope):Void 459 { 460 _messageHandler.handleMessage(env); 461 } 462 463 /** 464 * Rajoute un gestionnaire chargé d'intercepter 465 * la réponse du serveur suite à un message soumis. 466 * Forme d'accusé de réception (callback). 467 * 468 * @param subject Le type de message. 469 * @param methodName Le nom de l'événement gérant un type de message. 470 */ 471 public function addHandler (subject:String, methodName:String):Void 472 { 473 _messageHandler.addHandler (subject, methodName); 474 } 475 476 477 // Callbacks des messges Message avec accusés de réception 478 /** 479 * Gestionnaire de l'accusé de réception du message de la soumission du Mail. 480 * Génère un événement onSend ou onError aux observateurs. 481 * 482 * @param env Enveloppe du message retourné. 483 */ 484 private function handleSend (env:Envelope):Void 485 { 486 var attach = env.getMessage().getAttachment(); 487 var errCode = attach.error; 488 if (errCode == "ok") 489 { 490 var newMail = new Mail(""); 491 var newRow = { 492 subject:row.subject, 493 username:attach.username, 494 dt:attach.dt, 495 msgID:attach.msgID, 496 readFlag:false 497 }; 498 // TODO : Accès Singleton 499 var user = User.getInstance(); 500 newMail.init(user.getOutBox(), newRow); 501 user.getOutBox().addMail(newMail, newMail.row.msgID); 502 // Broadcast 503 fireEvent("info", "onSend", newMail); 504 } else 505 { 506 var err = new _Error(errCode, "send", new Array()); 507 // Broadcast 508 fireEvent("error", "onError", this, err); 509 } 510 } 511 512 /** 513 * Gestionnaire de l'accusé de réception du message de réception du fichier joint. 514 * Génère un événement onLoadAttachment ou onError aux observateurs. 515 * 516 * @param env Enveloppe du message retourné. 517 */ 518 private function handleLoad (env:Envelope):Void 519 { 520 var attach = env.getMessage().getAttachment(); 521 var errCode = attach.error; 522 if (errCode == "ok") 523 { 524 var t = attach.tables.result; 525 this.attach = t.getRow(0).message; 526 //this.attach = attach.fields.message; 527 // Broadcast 528 fireEvent("info", "onLoadAttachment", this); 529 attach = null; 530 } else 531 { 532 var err = new _Error(errCode, "loadAttachment", new Array()); 533 // Broadcast 534 this.fireEvent("error","onError",this,err); 535 } 536 } 537 538 539 /** 540 * Gestionnaire de l'accusé de réception du message de suppresion du message de la boîte. 541 * Génère un événement onRemove ou onError aux observateurs. 542 * 543 * @param env Enveloppe du message retourné. 544 */ 545 private function handleRemove (env:Envelope):Void 546 { 547 var attach = env.getMessage().getAttachment(); 548 var errCode = attach.error; 549 if (errCode == "ok") 550 { 551 box._removeMail(this, row.msgID); 552 box = null; 553 // Broadcast 554 fireEvent("info", "onRemove", this); 555 } else 556 { 557 var err = new _Error(errCode, "remove", new Array()); 558 // Broadcsat 559 fireEvent("error", "onError", this, err); 560 } 561 } 562 563 /** 564 * Gestionnaire de l'accusé de réception du message de modification de statut de lecture. 565 * Génère un événement onMark ou onError aux observateurs. 566 * 567 * @param env Enveloppe du message retourné. 568 */ 569 private function handleMark (env:Envelope):Void 570 { 571 var attach = env.getMessage().getAttachment(); 572 var errCode = attach.error; 573 var asRead:Boolean; 574 if (box.getType() == "outBox") 575 { 576 asRead = attach.asRead; 577 } else 578 { 579 // TODO : Accès Singleton 580 var msgRouter = MessageRouter.getInstance(); 581 asRead = msgRouter.getCache(env.getID(), "args")[0]; 582 } 583 if (errCode == "ok") 584 { 585 var old = row.readFlag; 586 if (old && ! asRead) 587 { 588 box.unread++; 589 } else if (! old && asRead) 590 { 591 box.unread--; 592 } else 593 { 594 return; 595 } 596 row.readFlag = asRead; 597 // Broadcast 598 fireEvent("info", "onMark", this); 599 } else 600 { 601 var err = new _Error(errCode, "mark", [asRead]); 602 // Broadcast 603 fireEvent("error", "onError", this, err); 604 } 605 } 606 // Fin des callbacks des messges Message avec accusés de réception 607 608 609 //-------------------- 610 // METHODES PRIVEES 611 //-------------------- 612 /** 613 * Modifie l'état du message courant. 614 * 615 * @param subject Etat du message à modifier : removeMail… 616 * @return Enveloppe du message à synchoniser avec le serveur. 617 */ 618 private function getMessage (subject:String):Envelope 619 { 620 var msg = new Message(subject); 621 var attach = msg.getAttachment(); 622 attach.box = box.type; 623 attach.msgID = row.msgID; 624 625 // TODO : Accès Singleton 626 var envFactory = EnvelopeFactory.getInstance(); 627 return envFactory.getOutgoing(msg, "mailbox"); 628 } 629 630 //-------------------- 631 // METHODES STATIQUES 632 //-------------------- 633 /** 634 * Utilisé dans un contexte littéral 635 * 636 * @return Une chaine définissant l'objet. 637 */ 638 public static function toLog():String 639 { 640 return "[Objet Mail]"; 641 } 642 643 } 644