public static function getInstance()
 {
     if (self::$instance == NULL) {
         self::$instance = new ArtifactHolder();
     }
     return self::$instance;
 }
 /**
  * Metodo auxiliar para cargar los objetos asociados en cascada, tanto los hasOne como los hasMany, 
  * verificando previamente si no fueron ya cargados.
  * @param PersistentObject $obj el objeto al que hay que cargarle los objetos asociados.
  */
 private function getCascadeAssocs($obj)
 {
     // Para saber si estaba limpia previamente, para poder limpiar lo que esta operacion ensucia (dirty bits)
     $wasClean = $obj->isClean();
     // TODO: Verificar si para los objetos en hasOne, sus asociaciones son cargadas en cascada.
     // Para cada objeto hasOne, lo trae.
     // Para el objeto hago get para hasOne y getMany para los hasMany.
     $ho_attrs = $obj->getHasOne();
     foreach ($ho_attrs as $attr => $assoc_class) {
         // attr = "email_id" ?
         $ho_instance = new $assoc_class();
         $hasOneAttr = DatabaseNormalization::getSimpleAssocName($attr);
         // email
         $assoc_id = $ho_instance->aGet($attr);
         $assoc_obj = NULL;
         if (ArtifactHolder::getInstance()->existsModel($assoc_class, $assoc_id)) {
             $assoc_obj = ArtifactHolder::getInstance()->getModel($assoc_class, $assoc_id);
         } else {
             $assoc_obj = $this->get($assoc_class, $assoc_id);
             ArtifactHolder::getInstance()->addModel($assoc_obj);
         }
         //$obj->{"set".$attr}( $assoc_obj );
         $obj->aSet($attr, $assoc_obj);
     }
     // Para cada objeto hasMany, lo trae
     // Para el objeto hago get para hasOne y getMany para los hasMany.
     $hm_attrs = $obj->getHasMany();
     foreach ($hm_attrs as $attr => $class) {
         $this->getMany($obj, $attr);
         // Carga los elementos del atributo en la clase.
     }
     // TODO: si carga en cascada, entonces la instancia de obj y sus clases asociadas
     //       se cargan todas en el mismo momento, por lo que no habria nada sucio,
     //       y seria innecesario verificar si estaba sucia antes de la carga.
     // Solo limpia si la clase estaba limpia antes de la operacion
     if ($wasClean) {
         $obj->resetDirty();
     }
     // Apaga las banderas que se prendieron en la carga
 }
 /**
  * Devuelve una lista de PO correspondientes a la consulta realizada.
  */
 public function findBy(PersistentObject $instance, Condition $condition, ArrayObject $params)
 {
     //Logger::getInstance()->pm_log("PM::findBy ". $instance->getClass() ." : " . __FILE__."@". __LINE__);
     // Consulta para saber la clase real (subclase concreta) del objeto que se está pidiendo
     $allAttrValues = $this->findByAttributeMatrix($instance, $condition, $params);
     //$dal->listAll( $tableName, $params ); // FIXME: AHORA TIRA TODOS LOS ATRIBUTOS Y NECESITO SOLO CLASS e ID.
     $res = array();
     // Lista de objetos
     foreach ($allAttrValues as $row) {
         // FIXED: http://code.google.com/p/yupp/issues/detail?id=110
         // Si la clase real (row[class]) es distinta a la clase por la que busco ($instance->getClass()),
         // la clase por la que busco será una superclase de la real.
         // Carga considerando estrategia... y se fija en el holder si ese objeto no esta ya cargado.
         $obj = NULL;
         if (ArtifactHolder::getInstance()->existsModel($row['class'], $row['id'])) {
             $obj = ArtifactHolder::getInstance()->getModel($row['class'], $row['id']);
         } else {
             $obj = $this->po_loader->get($row['class'], $row['id']);
             // Define la estrategia con la que se cargan los objetos...
             ArtifactHolder::getInstance()->addModel($obj);
             // Lo pongo aca para que no se guarde luego de la recursion de las assocs...
         }
         $res[] = $obj;
     }
     return $res;
 }