Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/kenri89/PROYECTO_UTP_AED_1_1/llms.txt

Use this file to discover all available pages before exploring further.

The PanelHistorial panel provides a reverse-chronological log of every enrollment operation performed during the current session. It is backed by PilaAcciones_U3 — a custom LIFO stack implemented as a singly-linked list, where each node holds an AccionMatricula record. Because the stack is traversed non-destructively for display (using a copy), the undo functionality in PanelMatricula remains fully operational even after the history panel has been viewed many times.

The AccionMatricula Record

Each entry in the stack captures two pieces of information: the type of operation and a snapshot of the Matricula object at the time it was performed.
FieldTypeValuesDescription
tipoString"REGISTRO", "ELIMINACIÓN", "ACTUALIZACIÓN"The action performed on the enrollment.
matriculaMatriculaAny valid Matricula instanceThe enrollment state captured at action time.
public class AccionMatricula {
    private String tipo;       // "REGISTRO", "ACTUALIZACIÓN", "ELIMINACIÓN"
    private Matricula matricula;

    public AccionMatricula(String tipo, Matricula matricula) {
        this.tipo      = tipo;
        this.matricula = matricula;
    }

    public String    getTipo()      { return tipo; }
    public Matricula getMatricula() { return matricula; }
}

How PilaAcciones_U3 Works

PilaAcciones_U3 is a custom singly-linked stack (not java.util.Stack). Each internal Nodo holds an AccionMatricula and a pointer to the next node. The tope field always points to the most recently pushed action.

Push — apilar()

Creates a new node, sets its siguiente to the current tope, then advances tope to the new node. O(1).
public void apilar(AccionMatricula accion) {
    Nodo nuevo = new Nodo(accion);
    nuevo.siguiente = tope;
    tope = nuevo;
}

Pop — desapilar()

Reads the action at tope, advances tope to tope.siguiente, and returns the action. Returns null if empty. O(1).
public AccionMatricula desapilar() {
    if (tope == null) return null;
    AccionMatricula accion = tope.accion;
    tope = tope.siguiente;
    return accion;
}

Traverse — recorrer()

Iterates from tope downward, passing each AccionMatricula to the provided Consumer. Non-destructive — tope is not modified. Used for audit display.
public void recorrer(Consumer<AccionMatricula> callback) {
    Nodo actual = tope;
    while (actual != null) {
        callback.accept(actual.accion);
        actual = actual.siguiente;
    }
}

Copy — copiar()

Creates a full structural copy in two passes (invert into auxiliary, re-invert into result) so the copy has the same top-to-bottom order as the original. Used by PanelHistorial to avoid destroying the stack during display.
PilaAcciones_U3 copia = pilaHistorial.copiar();

Display in PanelHistorial

When the panel loads (or when Filtrar is clicked), cargarHistorial() calls pilaHistorial.copiar() to obtain a safe copy, then pops every action from the copy to populate the table. Because items are popped from the copy’s top, the most recent actions appear first:
PilaAcciones_U3 copia = pilaAcciones.copiar();
while (!copia.estaVacia()) {
    AccionMatricula accion = copia.desapilar();
    Matricula mat = accion.getMatricula();
    modelo.addRow(new Object[]{
        mat.getEstudiante().getCarnet(),
        mat.getEstudiante().getNombre(),
        mat.getCurso().getCodigo(),
        mat.getCurso().getNombre(),
        accion.getTipo()
    });
}
The table displays five columns: Carnet, Nombre, Curso (code), Nombre Curso, Acción.

Filtering by Student

A combo-box at the top of the panel (populated from ArbolEstudiantes.inorden()) allows filtering by carnet. Selecting a specific carnet shows only that student’s actions; selecting “Todos” shows the full history.
String filtro = (String) comboCarnets.getSelectedItem();
if (filtro.equals("Todos") || mat.getEstudiante().getCarnet().equals(filtro)) {
    // add row
}

Access by Role

Panel visibility is controlled in MenuPrincipal based on Usuario.getRol():
RoleCan see PanelHistorial?
admin✅ Yes
secretaria❌ No
estudiante✅ Yes
docente✅ Yes
// MenuPrincipal.java
btnHistorial.setVisible(esAdmin || esEstudiante || esDocente);

Session-Only Persistence

The history stack is session-scoped. PilaAcciones_U3 lives entirely in heap memory — it is not written to any TSV file or SQL Server table. Closing and reopening the application resets it to an empty state. Only the underlying Matricula changes themselves are durable (via MatriculaDAO); the action log is ephemeral.

Full Usage Example

// Pushing an action when an enrollment is created
pilaHistorial.apilar(new AccionMatricula("REGISTRO", matricula));

// Pushing an action when an enrollment is cancelled
pilaHistorial.apilar(new AccionMatricula("ELIMINACIÓN", matricula));

// Reading all actions top-to-bottom without destroying the stack
pilaHistorial.recorrer(accion -> {
    System.out.println(accion.getTipo() + " — " + accion.getMatricula());
});

// Safe copy for display in PanelHistorial (preserves undo capability)
PilaAcciones_U3 copia = pilaHistorial.copiar();
while (!copia.estaVacia()) {
    AccionMatricula accion = copia.desapilar();
    // render accion in the table
}
Because copiar() creates a structural copy in O(n) time, avoid calling it on very high-frequency loops. For normal session-length usage (dozens to low hundreds of enrollment actions), performance is negligible.

Build docs developers (and LLMs) love