/**
  * Dada una instancia de PO, devuelve una estructura con las clases que se deben guardar 
  * en distintas tablas y los atrbibutos de cada una con sus respectivos valores.
  */
 public static function getPartialInstancesToSave($po_ins)
 {
     Logger::getInstance()->dal_log("MTI::getPartialInstancesToSave " . $po_ins->getClass());
     //Logger::struct( $po_ins, __FILE__ . ".getPartialInstancesToSave " . __LINE__ );
     // TODO: (performance) si el objeto no representa un MTI no deberia hacerse todo el trabajo de copiar cada atributo del objeto,
     //       eso deberia verificarse antes, y de no ser un MTI, devolver nomas un array con el objeto entrante.
     // Para simplificar y no tener que hacer aGet sobre po_ins
     $values = $po_ins->getAttributeValues();
     //$superclasses = ModelUtils::getAllAncestorsOf( $po_ins->getClass() ); // puede ser en cualquier orden!
     $superclasses = ModelUtils::getAllAncestorsOf($values['class']);
     // puede ser en cualquier orden!
     /*
     // Quiero la clase de nivel 1
     $level1Class = NULL;
     foreach ( $superclasses as $class )
     {
        if ( get_parent_class( $class ) == 'PersistentObject' )
        {
           $level1Class = $class;
           break; // salir del foreach
        }
     }
     $struct = self::getMultipleTableInheritanceStructureToGenerateModel( array($level1Class) );
     */
     // Lo anterior es lo mismo que hacer esto:
     // NO! SERIA LO MISMO SI LA INSTANCIA QUE ME PASAN ES DE LA ULTIMA CLASE DE LA ESTRUCTURA DE HERENCIA.
     // CORRECCION, esta bien porque hace getClass, y obtiene la clase real que es la ultima de la estructura!!!!
     //$superclasses[] = $po_ins->getClass();
     $superclasses[] = $values['class'];
     // Mapa de clases y subclases que se mapean en la misma tabla.
     $struct = self::getMultipleTableInheritance($superclasses);
     //Logger::getInstance()->dal_log("getMultipleTableInheritance (son las subclases en la misma tabla) " . __FILE__ . " " . __LINE__ );
     //Logger::struct( $struct );
     // TODO: Partial Instances no considera valores, tengo que setear los valores a mano a partir de los valores de po_ins.
     $partialInstances = self::getPartialInstantes($struct);
     // Instancias de las clases en $superclasses que solo tienen los atributos que van en cada tabla. Cada clase de estas se mapea directamente con una tabla.
     foreach ($partialInstances as $partialInstance) {
         $attrs_values = $partialInstance->getAttributeTypes();
         // El tipo no lo uso para nada, solo necesito la declaracion de atributos.
         foreach ($attrs_values as $attr => $type) {
             //echo $partialInstance->getClass() . " " . $po_ins->getClass() . " $attr<br />";
             //if ( $partialInstance->getClass() === $po_ins->getClass() || // Seteo atributos inyectados tambien, xq son de esta instancia!
             if ($partialInstance->getClass() === $values['class'] || !PersistentObject::isInyectedAttribute($attr)) {
                 // ===============================================================================
                 // aGet tiene cierta complejidad pidiendo values directamente es mas rapido
                 //$partialInstance->aSet($attr, $po_ins->aGet($attr));
                 $partialInstance->aSet($attr, $values[$attr]);
                 // PO garantiza que vienen valores para todos los indices, aunque sean NULL, por eso no es necesario hacer un isset($values[$attr])
             }
         }
         // El deleted, si la instancia a salvar esta deleted, todos los registros deben estarlo!
         //$partialInstance->setDeleted( $po_ins->getDeleted() );
         $partialInstance->setDeleted($values['deleted']);
     }
     // getPartialInstancesToSave
     return $partialInstances;
     // derecho para salvar cada uno usando save_object!!!
 }
 /**
  * Devuelve HTML para edicion de un objeto como una tabla con 2 columnas, la primera de nombres de campos la segunda con campos con valores para modificar.
  */
 private static function display_edit(PersistentObject $po)
 {
     $res = '<table>';
     $attrs = $po->getAttributeTypes();
     foreach ($attrs as $attr => $type) {
         // Los atributos inyectados no se deberian poder editar!
         $res .= '<tr><td>';
         $res .= $attr;
         // TODO: Habria que ver si esto es i18n, deberia haber algun "display name" asociado al nombre del campo.
         $res .= '</td><td>';
         if ($po->isInyectedAttribute($attr)) {
             //$res .= $po->aGet($attr);
             $res .= self::field_to_html_show($attr, $type, $po->aGet($attr));
         } else {
             if (DatabaseNormalization::isSimpleAssocName($attr)) {
                 // Si es un fk a un id de un hasOne, quiero mostrar una lista de los posibles ids
                 // de la clase de la relacion HO que le puedo asignar, y como esto es create o edit,
                 // si tiene un valor actual, deberia quedar seleccionado en el select.
                 $currentValue = $po->aGet($attr);
                 // Puede ser NULL
                 $role = DatabaseNormalization::getSimpleAssocName($attr);
                 // email_id -> email
                 $relClass = $po->getAttributeType($role);
                 // Clase de la relacion HO
                 // Objetos que puedo tener relacionadoss
                 // Se puede en PHP 5.3.0...
                 //$list = $relClass::listAll(new ArrayObject()); // Objetos que podria tener asociados
                 // ... pero por las dudas ...
                 $list = call_user_func_array(array($relClass, 'listAll'), array(new ArrayObject()));
                 $select = '<select name="' . $attr . '"><option value=""></option>';
                 foreach ($list as $relObj) {
                     $sel = $currentValue == $relObj->getId() ? ' selected="true"' : '';
                     $select .= '<option value="' . $relObj->getId() . '"' . $sel . '>' . $relClass . '[' . $relObj->getId() . ']</option>';
                     // TODO: Si se tuviera un toString en la clase se mostraria mejor
                 }
                 $select .= '</select>';
                 $res .= $select;
             } else {
                 $maxStringLength = NULL;
                 if ($type === Datatypes::TEXT) {
                     $maxLengthConstraint = $po->getConstraintOfClass($attr, 'MaxLengthConstraint');
                     if ($maxLengthConstraint !== NULL) {
                         $maxStringLength = $maxLengthConstraint->getValue();
                     }
                 }
                 $res .= self::field_to_html_edit($attr, $type, $po->aGet($attr), $maxStringLength);
                 // Si el campo tiene errores, los muestro
                 if ($po->getErrors()->hasFieldErrors($attr)) {
                     $res .= '<div class="errors">';
                     $res .= self::fieldErrors($po, $attr);
                     $res .= '</div>';
                 }
             }
         }
         $res .= '</td></tr>';
     }
     $res .= '</table>';
     return $res;
 }