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.

PersistenciaAcademica (in package util) provides local file persistence that operates entirely independently of SQL Server. Whenever the application writes or loads data, it can serialise the five in-memory data structures — the course array, student BST, semester matrix, enrollment list, and request queue — to a set of tab-separated value (TSV) files on disk. This means that even when the database is unreachable, no work is lost between sessions: the application saves to disk on exit and reloads on startup without requiring a network round-trip.

Storage Location

All TSV files are written to a subdirectory of the current user’s home folder. The directory name is exposed as a public constant so that other utilities in the util package can locate the same folder.
public static final String DIR_NAME = ".proyecto_utp_aed_datos";
// Resolved at runtime to: System.getProperty("user.home") + "/.proyecto_utp_aed_datos/"
On a typical Linux or macOS machine this resolves to ~/.proyecto_utp_aed_datos/. On Windows it resolves to C:\Users\<username>\.proyecto_utp_aed_datos\. The directory is created automatically by FileUtils.forceMkdir() the first time guardar() is called.

TSV Files

Four files are maintained inside the directory. Each line represents one record; columns are separated by a single tab character (\t).
FileColumns (in order)Description
cursos.tsvcodigo, nombre, creditos, semestreCourse catalogue sourced from ArregloCursos
estudiantes.tsvcarnet, nombre, carreraStudent registry sourced from ArbolEstudiantes (in-order traversal)
matriculas.tsvcarnet, codigo_cursoEnrollment pairs sourced from ListaMatricula
solicitudes.tsvcarnet, tipo, descripcion, fecha, atendida, fechaAtencionRequest queue (0/1 for atendida; ISO-8601 datetimes)
Lines beginning with # are treated as comments and skipped during loading. Completely blank lines are also ignored, so you can add a header comment to any TSV file without breaking the parser.

guardar() — Saving All Structures

guardar() is a static method that accepts the six live data-structure references held by the application controller.
public static void guardar(
    ArregloCursos arregloCursos,
    ArbolEstudiantes arbolEstudiantes,
    MatrizSemestres matrizSemestres,
    ListaCursos listaCursos,
    ListaMatricula listaMatricula,
    Queue<Solicitud> colaSolicitudes
)
1

Create the directory

FileUtils.forceMkdir(directorioFile()) ensures ~/.proyecto_utp_aed_datos/ exists, creating it (and any missing parent directories) if necessary.
2

Write cursos.tsv

Iterates arregloCursos.obtenerCursos(). Each non-null Curso is serialised as four tab-joined columns: codigo, nombre, creditos, semestre.
3

Write estudiantes.tsv

Calls arbolEstudiantes.inorden(estudiantes::add) to produce an in-order (sorted by carnet) list, then serialises each Estudiante as three columns: carnet, nombre, carrera.
4

Write matriculas.tsv

Calls listaMatricula.recorrer(matriculas::add) and serialises each Matricula as two columns: estudiante.getCarnet(), curso.getCodigo().
5

Write solicitudes.tsv

Iterates the Queue<Solicitud> directly. Dates are formatted with DateTimeFormatter.ISO_LOCAL_DATE_TIME; atendida is written as "1" or "0"; a null fechaAtencion is written as an empty string.

cargar() — Loading All Structures

cargar() is the mirror of guardar(). It receives the same six structure references and rehydrates them from disk.
public static void cargar(
    ArregloCursos arregloCursos,
    MatrizSemestres matrizSemestres,
    ListaCursos listaCursos,
    ArbolEstudiantes arbolEstudiantes,
    ListaMatricula listaMatricula,
    Queue<Solicitud> colaSolicitudes
)
1

Guard check

If ~/.proyecto_utp_aed_datos/ does not exist as a directory, cargar() returns immediately without modifying any structure.
2

Clear all structures

All six structures are emptied before any file is read: limpiar() on each collection, and Queue.poll() in a loop for colaSolicitudes. This prevents duplicate records when cargar() is called more than once.
3

Load cursos.tsv (first)

Each course is inserted into arregloCursos, matrizSemestres, and listaCursos. Courses must be loaded before enrollments because listaMatricula lookups require a live Curso reference.
4

Load estudiantes.tsv (second)

Each student is inserted into arbolEstudiantes. Students must be loaded before enrollments for the same reason.
5

Load matriculas.tsv (third)

For each row, arbolEstudiantes.buscar(carnet) and listaCursos.buscar(codigo) are called. If either lookup returns null (orphaned reference), the enrollment line is silently skipped. After all enrollments are loaded, CuentasEstudiantes.registrarPorMatricula() is called for each enrolled student to ensure their login credential file is up to date.
6

Load solicitudes.tsv (last)

Date strings are parsed with DateTimeFormatter.ISO_LOCAL_DATE_TIME; unparseable or empty date fields default to LocalDateTime.now() for fecha and null for fechaAtencion.

TSV Escaping

Tab characters are the column delimiter, so any tab, carriage-return, or newline character found inside a field value is replaced with a single space before writing. This is handled by the private esc() helper:
private static String esc(String s) {
    return Strings.nullToEmpty(s)
        .replace("\t", " ")
        .replace("\r", " ")
        .replace("\n", " ");
}
Strings.nullToEmpty() (Google Guava) converts null values to "" so that Joiner.useForNull("") and esc() together guarantee no NullPointerException can reach the file writer.

Datetime Format

Dates on Solicitud objects are serialised and deserialised using the ISO-8601 local datetime format provided by Java’s DateTimeFormatter.ISO_LOCAL_DATE_TIME (e.g. 2024-03-15T14:30:00). No timezone information is stored; all datetimes are treated as local.
private static final DateTimeFormatter ISO = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

// Serialise
s.getFecha().format(ISO)        // → "2024-03-15T14:30:00"

// Deserialise
LocalDateTime.parse(f, ISO)     // ← "2024-03-15T14:30:00"

Apache Commons IO & Google Guava

PersistenciaAcademica relies on two third-party libraries for all low-level I/O and string manipulation:
LibraryUsage
Apache Commons IO FileUtilsreadLines(file, charset), writeLines(file, charset, lines), forceMkdir(dir) — handles charset-aware file I/O without manual stream management
Google Guava JoinerJoiner.on('\t').useForNull("") — joins column values with a tab separator, safely substituting "" for any null field
Google Guava SplitterSplitter.on('\t').trimResults() — splits each line back into columns and trims surrounding whitespace
Google Guava ImmutableListWraps the Splitter output so that p.get(index) is bounds-safe
The directory ~/.proyecto_utp_aed_datos/ is also where cuentas_estudiantes.txt is written by CuentasEstudiantes. Both utilities share the same folder, so a single backup of that directory captures the complete local state of the application.

Relationship to SQL Server

PersistenciaAcademica and the DAO layer are complementary, not mutually exclusive. The typical application flow is:
  1. On startupcargar() rehydrates the in-memory structures from the TSV files (fast, no network required).
  2. On each mutation — the relevant DAO method (insertar, actualizar, eliminar) attempts to persist the change to SQL Server.
  3. On shutdown / explicit saveguardar() writes the current in-memory state back to the TSV files, capturing any changes made while offline.
This dual-persistence design means that a temporary SQL Server outage causes at most one session’s worth of database divergence, which can be reconciled manually by re-running the DAO sync on the next successful connection.

Build docs developers (and LLMs) love