diff --git a/.gitignore b/.gitignore index 1df3855..8f19bec 100644 --- a/.gitignore +++ b/.gitignore @@ -220,4 +220,6 @@ release.properties dependency-reduced-pom.xml buildNumber.properties .mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar \ No newline at end of file +.mvn/wrapper/maven-wrapper.jar + +data/* \ No newline at end of file diff --git a/README.md b/README.md index b6cf0a4..9a7f6a0 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,42 @@ # PRC-CERIF [![Build Status](https://github.com/CSUC/PRC-CSV2XML/actions/workflows/main.yml/badge.svg)](https://github.com/CSUC/PRC-CSV2XML/actions/workflows/main.yml) -## Resources -* [Release Notes](../../releases) -* [Wiki](../../wiki/Home) +## Descripció +Aquesta aplicació converteix dades de recerca en format CSV a XML seguint l'estàndard CERIF (Common European Research Information Format). L'aplicació està dissenyada per processar dades de recerca de la Universitat Politècnica de Catalunya (UPC) i generar fitxers XML compatibles amb el sistema euroCRIS. -## Build +## Característiques +- Conversió de dades de recerca a format CERIF XML +- Suport per a investigadors, departaments, grups de recerca, projectes i publicacions +- Processament de dades utilitzant Apache Spark +- Generació d'identificadors únics (UUID) per a cada entitat +- Suport per a múltiples idiomes en els metadades -``` +## Requisits +- Java 8 o superior +- Apache Spark +- Maven 3.x + +## Instal·lació + +### Des de font +```bash +git clone https://github.com/CSUC/PRC-CSV2XML.git +cd PRC-CSV2XML sh build.sh ``` -## Command line -https://spark.apache.org/docs/latest/submitting-applications.html +### Des de Docker +```bash +docker pull csuc/prc-cerif:latest ``` -spark-submit --master "local[*]" --class org.csuc.cli.Cerif --packages info.picocli:picocli:4.7.6,com.crealytics:spark-excel_2.12:3.5.1_0.20.4,com.typesafe:config:1.4.3 --jars euroCRIS-cerif-definitions-1.6.2.jar prc-cerif-${version}.jar args + +## Ús + +### Línia de comandes +```bash +spark-submit --master "local[*]" --class org.csuc.cli.Cerif --packages info.picocli:picocli:4.7.6,com.crealytics:spark-excel_2.12:3.5.1_0.20.4,com.typesafe:config:1.4.3 --jars euroCRIS-cerif-definitions-${version}.jar prc-cerif-${version}.jar args ``` + +### Opcions ``` Usage: prc-cerif [-fhV] -i= [-o=] -r= -f, --formatted formatted output file (default: false) @@ -24,3 +46,26 @@ Usage: prc-cerif [-fhV] -i= [-o=] -r= -r, --ruct= ruct code (https://www.educacion.gob.es/ruct/home) -V, --version Print version information and exit. ``` + +### Docker +```bash +docker run -v /path/to/data:/opt/spark/work-dir csuc/prc-cerif:latest -i input.xlsx -r RUCT_CODE -o output.xml +``` + +## Estructura del projecte +- `euroCRIS-cerif-definitions`: Definicions XSD i classes generades per al format CERIF +- `transformation`: Codi font de l'aplicació principal + - `src/main/java/org/csuc/cli`: Classes de línia de comandes + - `src/main/java/org/csuc/marshal`: Classes per a la conversió de dades + - `src/main/java/org/csuc/typesafe`: Configuracions i semàntica + - `src/main/resources`: Fitxers de configuració + +## Recursos +* [Release Notes](../../releases) +* [Wiki](../../wiki/Home) + +## Llicència +Aquest projecte està llicenciat sota la llicència MIT - veure el fitxer [LICENSE](LICENSE) per més detalls. + +## Contacte +Albert Martínez diff --git a/docker/Dockerfile b/docker/Dockerfile index c1f454e..3accf28 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,13 +1,49 @@ -FROM apache/spark:latest +# Stage 1: Compilació +FROM maven:3.8-openjdk-8-slim AS builder + +ENV VERSION="2.4.19" + +LABEL maintainer="Albert Martínez " +LABEL version="$VERSION" +LABEL description="PRC-CSV2XML: Conversor de CSV/Excel a XML CERIF" + +# Configurar repositori Maven central +RUN mkdir -p /root/.m2 && \ + echo 'centralMaven Centralhttps://repo.maven.apache.org/maven2central' > /root/.m2/settings.xml + +# Copiar el codi font +WORKDIR /app +COPY . . + +# Compilar el projecte +RUN mvn clean install -DskipTests + +# Stage 2: Execució +FROM bitnami/spark:3.5.1 + +ENV VERSION="2.4.19" LABEL maintainer="Albert Martínez " +LABEL version="$VERSION" +LABEL description="PRC-CSV2XML: Conversor de CSV/Excel a XML CERIF" +# Crear directoris necessaris USER root +RUN mkdir -p /app /data -ADD https://github.com/CSUC/PRC-CSV2XML/releases/download/2.4.19/euroCRIS-cerif-definitions-1.6.2.jar /opt/spark/work-dir/euroCRIS-cerif-definitions.jar -ADD https://github.com/CSUC/PRC-CSV2XML/releases/download/2.4.19/prc-cerif-2.4.19.jar /opt/spark/work-dir/prc-cerif.jar -COPY run.sh /opt/spark/work-dir +# Copiar els JARs compilats +COPY --from=builder /app/transformation/target/prc-cerif-$VERSION.jar /app/prc-cerif.jar +COPY --from=builder /app/euroCRIS-cerif-definitions/target/euroCRIS-cerif-definitions-$VERSION.jar /app/euroCRIS-cerif-definitions.jar -ENV PATH "${SPARK_HOME}/bin:${PATH}" +# Configurar el directori de treball +WORKDIR /app -CMD ["/bin/bash"] \ No newline at end of file +# Comanda per defecte +ENTRYPOINT ["spark-submit", \ + "--master", "local[*]", \ + "--driver-memory", "4g", \ + "--executor-memory", "4g", \ + "--packages", "info.picocli:picocli:4.7.6,com.crealytics:spark-excel_2.12:3.5.1_0.20.4,com.typesafe:config:1.4.3,commons-io:commons-io:2.15.0,commons-codec:commons-codec:1.16.0,org.apache.commons:commons-lang3:3.13.0,org.apache.commons:commons-text:1.10.0,org.slf4j:slf4j-api:2.0.11,org.apache.commons:commons-compress:1.25.0", \ + "--jars", "/app/euroCRIS-cerif-definitions.jar", \ + "--class", "org.csuc.cli.Cerif", \ + "/app/prc-cerif.jar"] \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 93b5378..d8add7c 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,35 +1,118 @@ -# Docker +# PRC-CSV2XML Docker -## Run +Aquest directori conté la configuració Docker per executar el convertidor de CSV/Excel a XML CERIF. -manage volumes -``` -export SOURCE_FOLDER={source} -export TARGET_FOLDER={target} -``` -``` -docker-compose -f docker/docker-compose.yml run -d prc-cerif -``` +## Requisits -## Build -``` -docker-compose -f docker/docker-compose.yml build -``` +- Docker +- Docker Compose +- Mínim 4GB de RAM disponible -## Usage +## Estructura ``` -docker exec -it {container_id} bash +docker/ +├── Dockerfile # Configuració multi-stage per compilar i executar +├── docker-compose.yml # Configuració del servei +└── data/ # Directori per als fitxers d'entrada/sortida ``` -``` -sh run.sh --help - -Usage: prc-cerif [-fhV] -i= [-o=] -r= --f, --formatted formatted output file (default: false) --h, --help Show this help message and exit. --i, --input= data file --o, --output= output file (default: /tmp/`ruct`.xml) --r, --ruct= ruct code (https://www.educacion.gob.es/ruct/home) --V, --version Print version information and exit. -``` +## Configuració + +El Dockerfile utilitza un procés multi-stage: +1. Stage de compilació: Utilitza Maven per compilar el projecte +2. Stage d'execució: Utilitza Spark per executar l'aplicació + +El docker-compose.yml configura: +- Memòria: 4GB per driver i executor +- Volums: Mapeig del directori `data` per fitxers d'entrada/sortida +- Healthcheck: Verifica que Spark estigui executant-se +- Restart: Automàtic en cas d'error + +## Ús + +1. Preparar els fitxers: + ```bash + # Crear el directori data si no existeix + mkdir -p docker/data + + # Copiar el fitxer d'entrada + cp ruta/al/fitxer.csv docker/data/entrada.csv + ``` + +2. Construir la imatge: + ```bash + sudo docker compose -f docker/docker-compose.yml build + ``` + +3. Executar el convertidor: + ```bash + # Forma bàsica + sudo docker compose -f docker/docker-compose.yml run --rm prc-cerif \ + --input /data/entrada.csv \ + --output /data/sortida.xml \ + --ruct RUCT_CODE + + # Amb sortida formatada + sudo docker compose -f docker/docker-compose.yml run --rm prc-cerif \ + --input /data/entrada.csv \ + --output /data/sortida.xml \ + --ruct RUCT_CODE \ + --formatted + + # Especificant un fitxer Excel + sudo docker compose -f docker/docker-compose.yml run --rm prc-cerif \ + --input /data/entrada.xlsx \ + --output /data/sortida.xml \ + --ruct RUCT_CODE + ``` + +4. El fitxer XML generat es trobarà a `docker/data/sortida.xml` + +## Opcions disponibles + +- `--input`: Ruta al fitxer d'entrada (CSV/Excel) +- `--output`: Ruta al fitxer de sortida (XML) +- `--ruct`: Codi RUCT de la institució +- `--formatted`: Genera un fitxer XML formatat (més llegible) +- `--help`: Mostra l'ajuda + +## Solució de problemes + +1. Error de memòria: + - Augmentar la memòria a `docker-compose.yml`: + ```yaml + environment: + - SPARK_OPTS=--driver-java-options=-Xmx8g + - JAVA_OPTS=-Xmx8g + ``` + +2. Error de dependències: + - Verificar la connexió a Internet + - Netejar la cache de Docker: + ```bash + sudo docker system prune -a + ``` + +3. Error d'accés als fitxers: + - Verificar els permisos del directori `data` + - Assegurar que el fitxer d'entrada existeix + - Comprovar que el format del fitxer és correcte (CSV o Excel) + +4. Error de codi RUCT: + - Verificar que el codi RUCT és vàlid + - Consultar la llista de codis RUCT a: https://www.educacion.gob.es/ruct/home + +## Notes + +- La imatge utilitza Spark 3.5.1 +- Les dependències es compilen durant la construcció de la imatge +- Els fitxers d'entrada/sortida es gestionen a través del directori `data` +- La versió actual és 2.4.19 +- Els fitxers JAR s'instal·len amb noms genèrics: + - `prc-cerif.jar` (versió ${VERSION}) + - `euroCRIS-cerif-definitions.jar` (versió ${VERSION}) + +## Contacte + +Albert Martínez \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 469ce5d..a162592 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,11 +1,18 @@ -version: '3.8' services: prc-cerif: build: - context: . - dockerfile: Dockerfile - image: 'prc/prc-cerif:2.4.19' + context: .. + dockerfile: docker/Dockerfile + image: prc-cerif:latest container_name: prc-cerif - hostname: prc-cerif + environment: + - SPARK_OPTS=--driver-java-options=-Xmx4g + - JAVA_OPTS=-Xmx4g volumes: - - ${SOURCE_FOLDER}:${TARGET_FOLDER}:rw + - ../data:/data + healthcheck: + test: ["CMD", "ps", "aux", "|", "grep", "spark"] + interval: 30s + timeout: 10s + retries: 3 + restart: unless-stopped \ No newline at end of file diff --git a/docker/run.sh b/docker/run.sh deleted file mode 100644 index d1db9b9..0000000 --- a/docker/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cd /opt/spark/work-dir - -/opt/spark/bin/spark-submit --master "local[*]" --class org.csuc.cli.Cerif --packages info.picocli:picocli:4.7.5,com.crealytics:spark-excel_2.12:3.5.0_0.20.2,com.typesafe:config:1.4.3 --jars euroCRIS-cerif-definitions.jar prc-cerif.jar "$@" \ No newline at end of file diff --git a/euroCRIS-cerif-definitions/pom.xml b/euroCRIS-cerif-definitions/pom.xml index f98d847..ac2d8b5 100644 --- a/euroCRIS-cerif-definitions/pom.xml +++ b/euroCRIS-cerif-definitions/pom.xml @@ -1,3 +1,4 @@ + @@ -8,81 +9,100 @@ 4.0.0 euroCRIS-cerif-definitions - 1.6.2 + ${revision} euroCRIS-cerif-definitions UTF-8 + 4.0.0 junit junit - 4.13.2 + ${junit.version} + test - + - javax.xml.bind - jaxb-api - 2.4.0-b180830.0359 + jakarta.xml.bind + jakarta.xml.bind-api + ${jaxb.version} - + - com.sun.xml.bind - jaxb-core - 4.0.5 + org.glassfish.jaxb + jaxb-runtime + ${jaxb.version} - + com.sun.xml.bind - jaxb-impl - 4.0.5 + jaxb-core + ${jaxb.version} - - + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.0 + + ${maven.compiler.source} + ${project.build.sourceEncoding} + ${project.build.sourceEncoding} + ${project.build.sourceEncoding} + false + + org.jvnet.jaxb2.maven2 maven-jaxb2-plugin 0.14.0 - add-source-for-oaidc generate - - src/main/resources - - CERIF_1.6_2.xsd - - target/generated-sources/xjc-cerif - true - true - + + ${project.basedir}/src/main/resources + + *.xsd + + xmlns.org.eurocris.cerif_1 + org.codehaus.mojo build-helper-maven-plugin - 3.0.0 + 3.5.0 add-source - install + generate-sources add-source - ${basedir}/target/generated-sources/xjc-cerif + ${project.build.directory}/generated-sources/xjc diff --git a/pom.xml b/pom.xml index 5f96f3a..5fefbe4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,3 +1,4 @@ + 4.0.0 @@ -27,6 +28,8 @@ 4.13.2 4.7.6 1.4.3 + 3.5.0 + 3.5.1_0.20.4 @@ -46,11 +49,59 @@ ${picocli.version} + com.typesafe config ${typesafe.config.version} + + + + org.apache.spark + spark-core_2.12 + ${spark.version} + + + + + org.apache.spark + spark-sql_2.12 + ${spark.version} + + + + + com.crealytics + spark-excel_2.12 + ${spark.excel.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.0 + + ${maven.compiler.source} + ${project.build.sourceEncoding} + ${project.build.sourceEncoding} + ${project.build.sourceEncoding} + false + + + + diff --git a/transformation/pom.xml b/transformation/pom.xml index 570e2b6..d2a796f 100644 --- a/transformation/pom.xml +++ b/transformation/pom.xml @@ -1,4 +1,5 @@ - + PRC-CSV2XML @@ -20,50 +21,53 @@ - - junit - junit - 4.13.2 - - org.csuc euroCRIS-cerif-definitions - 1.6.2 - - - - com.typesafe - config + ${revision} - + org.apache.spark - spark-core_2.13 + spark-core_2.12 ${spark.version} - org.apache.spark - spark-sql_2.13 + spark-sql_2.12 ${spark.version} - + com.crealytics spark-excel_2.12 ${spark.excel.version} - + info.picocli picocli + ${picocli.version} + + + com.typesafe + config + ${typesafe.config.version} + + + + + junit + junit + ${junit.version} + test + @@ -81,5 +85,59 @@ + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.0 + + ${maven.compiler.source} + ${project.build.sourceEncoding} + ${project.build.sourceEncoding} + ${project.build.sourceEncoding} + false + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + org.csuc.cli.Cerif + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + diff --git a/transformation/src/main/java/org/csuc/cli/Cerif.java b/transformation/src/main/java/org/csuc/cli/Cerif.java index 150ad1c..abf1f77 100644 --- a/transformation/src/main/java/org/csuc/cli/Cerif.java +++ b/transformation/src/main/java/org/csuc/cli/Cerif.java @@ -25,6 +25,14 @@ import static org.apache.spark.sql.functions.*; +/** + * Classe principal que gestiona la conversió de dades CSV a XML CERIF. + * Aquesta classe utilitza Apache Spark per processar les dades i generar + * fitxers XML segons l'estàndard CERIF. + * + * @author Albert Martínez + * @version 2.4.19 + */ @CommandLine.Command( name = "prc-cerif", usageHelpAutoWidth = true, @@ -41,26 +49,46 @@ public class Cerif implements Runnable { @CommandLine.Spec CommandLine.Model.CommandSpec spec; + /** + * Fitxer d'entrada amb les dades a processar + */ @CommandLine.Option(names = {"-i", "--input"}, required = true, description = "data file", paramLabel = "") private Path input; + /** + * Indica si el fitxer XML de sortida ha de ser formatat + */ @CommandLine.Option(names = {"-f", "--formatted"}, description = "formatted output file (default: ${DEFAULT-VALUE})", paramLabel = "") private Boolean formatted = false; + /** + * Codi RUCT de la institució + */ @CommandLine.Option(names = {"-r", "--ruct"}, required = true, description = "ruct code (https://www.educacion.gob.es/ruct/home)", paramLabel = "") private String ruct; + /** + * Fitxer de sortida XML + */ @CommandLine.Option(names = {"-o", "--output"}, description = "output file (default: /tmp/`ruct`.xml)", paramLabel = "") private Path output; private Instant inici; + /** + * Punt d'entrada principal de l'aplicació + * + * @param args Arguments de la línia de comandes + */ public static void main(String[] args) { CommandLine cmd = new CommandLine(new Cerif()); if (args.length == 0) cmd.usage(System.out); else cmd.execute(args); } + /** + * Executa el procés de conversió de dades + */ @Override public void run() { try { diff --git a/transformation/src/main/java/org/csuc/global/Time.java b/transformation/src/main/java/org/csuc/global/Time.java index 71fc4aa..85d5a3e 100644 --- a/transformation/src/main/java/org/csuc/global/Time.java +++ b/transformation/src/main/java/org/csuc/global/Time.java @@ -10,8 +10,11 @@ import java.util.Date; /** - * @author amartinez + * Classe d'utilitats per a la gestió de dates i temps. + * Proporciona mètodes per convertir dates entre diferents formats + * i generar dates en format XMLGregorianCalendar. * + * @author Albert Martínez */ public class Time { private static String DATE = "yyyy-MM-dd"; @@ -19,12 +22,12 @@ public class Time { /** + * Converteix una data en format String a XMLGregorianCalendar amb format de data i hora. + * Si hi ha algun error en la conversió, retorna null. * - * Canvia el format d'una data de tipus Date a Date Time (ISO-8601). Qualsevol error retorna un String null - * per a poder invalidad la data. - * - * @param inputDate - * @return + * @param inputDate Data d'entrada en format String + * @return XMLGregorianCalendar amb la data i hora convertida, o null si hi ha error + * @throws Exception Si hi ha un error en la conversió de la data */ public static XMLGregorianCalendar formatDateTime(String inputDate) throws Exception { if (inputDate == null) return null; @@ -36,12 +39,12 @@ public static XMLGregorianCalendar formatDateTime(String inputDate) throws Excep } /** + * Converteix una data en format String a XMLGregorianCalendar amb format de data. + * Si hi ha algun error en la conversió, retorna null. * - * Canvia el format d'una data de tipus Date a Date Time (ISO-8601). Qualsevol error retorna un String null - * per a poder invalidad la data. - * - * @param inputDate - * @return + * @param inputDate Data d'entrada en format String + * @return XMLGregorianCalendar amb la data convertida, o null si hi ha error + * @throws Exception Si hi ha un error en la conversió de la data */ public static XMLGregorianCalendar formatDate(String inputDate) throws Exception { if (inputDate == null) return null; diff --git a/transformation/src/main/java/org/csuc/marshal/Marshaller.java b/transformation/src/main/java/org/csuc/marshal/Marshaller.java index 03ee643..4a0593e 100644 --- a/transformation/src/main/java/org/csuc/marshal/Marshaller.java +++ b/transformation/src/main/java/org/csuc/marshal/Marshaller.java @@ -14,10 +14,23 @@ import java.util.GregorianCalendar; import java.util.List; +/** + * Classe responsable de la generació del fitxer XML CERIF. + * Aquesta classe utilitza JAXB per serialitzar les dades a format XML + * segons l'estàndard CERIF. + * + * @author Albert Martínez + */ public class Marshaller { private CERIF cerif = new CERIF(); + /** + * Constructor de la classe Marshaller + * + * @param ruct Codi RUCT de la institució + * @throws DatatypeConfigurationException Si hi ha un error en la configuració de les dates + */ public Marshaller(String ruct) throws DatatypeConfigurationException { GregorianCalendar gregory = new GregorianCalendar(); gregory.setTime(new Date()); @@ -25,6 +38,15 @@ public Marshaller(String ruct) throws DatatypeConfigurationException { cerif.setSourceDatabase(ruct); } + /** + * Genera el fitxer XML CERIF amb les dades proporcionades + * + * @param output Ruta del fitxer de sortida + * @param formatted Indica si el XML ha de ser formatat + * @param objects Llistes d'objectes a serialitzar + * @throws JAXBException Si hi ha un error en la serialització + * @throws FileNotFoundException Si no es pot crear el fitxer de sortida + */ public void build(String output, boolean formatted, List... objects) throws JAXBException, FileNotFoundException { Arrays.stream(objects).forEach(o -> { cerif.getCfClassOrCfClassSchemeOrCfClassSchemeDescr().addAll(o); diff --git a/transformation/src/main/java/org/csuc/typesafe/semantics/Semantics.java b/transformation/src/main/java/org/csuc/typesafe/semantics/Semantics.java index 8a6caeb..16dc1a7 100644 --- a/transformation/src/main/java/org/csuc/typesafe/semantics/Semantics.java +++ b/transformation/src/main/java/org/csuc/typesafe/semantics/Semantics.java @@ -1,19 +1,34 @@ package org.csuc.typesafe.semantics; - import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; /** - * @author amartinez + * Classe d'utilitats per a la gestió de la semàntica CERIF. + * Proporciona mètodes per obtenir identificadors de classes i esquemes + * a partir del fitxer de configuració semantics.conf. + * + * @author Albert Martínez */ public class Semantics { + /** + * Obté l'identificador d'esquema CERIF per al tipus especificat. + * + * @param id Tipus d'esquema + * @return Identificador de l'esquema + */ public static String getSchemaId(SchemeId id) { Config conf = ConfigFactory.load("semantics.conf"); return conf.getObject("schemeId").toConfig().getString(id.name()); } + /** + * Obté l'identificador de classe CERIF per al tipus especificat. + * + * @param id Tipus de classe + * @return Identificador de la classe + */ public static String getClassId(ClassId id) { Config conf = ConfigFactory.load("semantics.conf"); return conf.getObject("classId").toConfig().getString(id.name());