[FEAT] update to new API of archidata

This commit is contained in:
Edouard DUPIN 2025-01-05 20:08:56 +01:00
parent f03a18c34c
commit 0260b4d408
49 changed files with 982 additions and 568 deletions

View File

@ -20,12 +20,12 @@
<dependency> <dependency>
<groupId>kangaroo-and-rabbit</groupId> <groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId> <artifactId>archidata</artifactId>
<version>0.15.0</version> <version>0.19.1-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>logback-classic</artifactId>
<version>2.1.0-alpha1</version> <version>1.4.11</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>

258
back/pom.xml.versionsBackup Normal file
View File

@ -0,0 +1,258 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.kar</groupId>
<artifactId>karusic</artifactId>
<version>0.1.0</version>
<properties>
<maven.compiler.version>3.1</maven.compiler.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.dependency.version>3.1.1</maven.dependency.version>
</properties>
<repositories>
<repository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.14.3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.1.0-alpha1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.18.0-rc1</version>
</dependency>
<!--
************************************************************
** TEST dependency **
************************************************************
-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.24.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test/src</testSourceDirectory>
<directory>${project.basedir}/out/maven/</directory>
<resources>
<resource>
<directory>src/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${basedir}/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<mainClass>org.kar.karusic.WebLauncher</mainClass>
</configuration>
</plugin>
<!-- Create the source bundle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- junit results -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- Create coverage -->
<!--
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.50</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
-->
<!-- Java-doc generation for stand-alone site -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>exec-application</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>org.kar.karusic.WebLauncher</mainClass>
</configuration>
</plugin>
<!-- Check the style of the code -->
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.23.0</version>
<configuration>
<encoding>UTF-8</encoding>
<lineEnding>LF</lineEnding>
<configFile>Formatter.xml</configFile>
<directories>
<directory>src/</directory>
<directory>test/src</directory>
</directories>
<includes>
<include>**/*.java</include>
</includes>
<excludes>
<exclude>module-info.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.5.0</version>
<configuration>
<includeFilterFile>spotbugs-security-include.xml</includeFilterFile>
<excludeFilterFile>spotbugs-security-exclude.xml</excludeFilterFile>
<!--<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>1.12.0</version>
</plugin>
</plugins>
-->
</configuration>
</plugin>
</plugins>
</build>
<!-- Generate Java-docs As Part Of Project Reports -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>public</show>
</configuration>
</plugin>
</plugins>
</reporting>
</project>

View File

@ -0,0 +1,27 @@
package org.kar.karusic.CodecBson;
import java.util.UUID;
import org.bson.BsonReader;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
public class UUIDCodec implements Codec<UUID> {
@Override
public UUID decode(final BsonReader reader, final DecoderContext decoderContext) {
return UUID.fromString(reader.readString());
}
@Override
public void encode(final BsonWriter writer, final UUID value, final EncoderContext encoderContext) {
writer.writeString(value.toString());
}
@Override
public Class<UUID> getEncoderClass() {
return UUID.class;
}
}

View File

@ -12,15 +12,17 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ResourceConfig;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.UpdateJwtPublicKey; import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource; import org.kar.archidata.api.DataResource;
import org.kar.archidata.api.ProxyResource; import org.kar.archidata.api.ProxyResource;
import org.kar.archidata.catcher.GenericCatcher; import org.kar.archidata.catcher.GenericCatcher;
import org.kar.archidata.db.DbConfig;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.filter.CORSFilter; import org.kar.archidata.filter.CORSFilter;
import org.kar.archidata.filter.OptionFilter; import org.kar.archidata.filter.OptionFilter;
import org.kar.archidata.migration.MigrationEngine; import org.kar.archidata.migration.MigrationEngine;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.ContextGenericTools;
import org.kar.karusic.api.AlbumResource; import org.kar.karusic.api.AlbumResource;
import org.kar.karusic.api.ArtistResource; import org.kar.karusic.api.ArtistResource;
import org.kar.karusic.api.Front; import org.kar.karusic.api.Front;
@ -35,6 +37,8 @@ import org.kar.karusic.migration.Migration20231126;
import org.kar.karusic.migration.Migration20240225; import org.kar.karusic.migration.Migration20240225;
import org.kar.karusic.migration.Migration20240226; import org.kar.karusic.migration.Migration20240226;
import org.kar.karusic.migration.Migration20240907; import org.kar.karusic.migration.Migration20240907;
import org.kar.karusic.migration.Migration20250104;
import org.kar.karusic.migration.Migration20250105;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -63,8 +67,10 @@ public class WebLauncher {
migrationEngine.add(new Migration20240225()); migrationEngine.add(new Migration20240225());
migrationEngine.add(new Migration20240226()); migrationEngine.add(new Migration20240226());
migrationEngine.add(new Migration20240907()); migrationEngine.add(new Migration20240907());
migrationEngine.add(new Migration20250104());
migrationEngine.add(new Migration20250105());
WebLauncher.LOGGER.info("Migrate the DB [START]"); WebLauncher.LOGGER.info("Migrate the DB [START]");
migrationEngine.migrateWaitAdmin(GlobalConfiguration.dbConfig); migrationEngine.migrateWaitAdmin(new DbConfig());
WebLauncher.LOGGER.info("Migrate the DB [STOP]"); WebLauncher.LOGGER.info("Migrate the DB [STOP]");
} }
@ -83,26 +89,26 @@ public class WebLauncher {
public void plop(final String aaa) { public void plop(final String aaa) {
// List available Image Readers // List available Image Readers
System.out.println("Available Image Readers:"); WebLauncher.LOGGER.trace("Available Image Readers:");
final Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(aaa); final Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(aaa);
while (readers.hasNext()) { while (readers.hasNext()) {
final ImageReader reader = readers.next(); final ImageReader reader = readers.next();
System.out.println("Reader: " + reader.getOriginatingProvider().getDescription(null)); WebLauncher.LOGGER.trace("Reader: " + reader.getOriginatingProvider().getDescription(null));
System.out.println("Reader CN: " + reader.getOriginatingProvider().getPluginClassName()); WebLauncher.LOGGER.trace("Reader CN: " + reader.getOriginatingProvider().getPluginClassName());
// ImageIO.deregisterServiceProvider(reader.getOriginatingProvider()); // ImageIO.deregisterServiceProvider(reader.getOriginatingProvider());
} }
// List available Image Writers // List available Image Writers
System.out.println("\nAvailable Image Writers:"); WebLauncher.LOGGER.trace("\nAvailable Image Writers:");
final Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(aaa); final Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(aaa);
while (writers.hasNext()) { while (writers.hasNext()) {
final ImageWriter writer = writers.next(); final ImageWriter writer = writers.next();
System.out.println("Writer: " + writer.getOriginatingProvider().getDescription(null)); WebLauncher.LOGGER.trace("Writer: " + writer.getOriginatingProvider().getDescription(null));
System.out.println("Writer CN: " + writer.getOriginatingProvider().getPluginClassName()); WebLauncher.LOGGER.trace("Writer CN: " + writer.getOriginatingProvider().getPluginClassName());
} }
} }
public void process() throws InterruptedException { public void process() throws InterruptedException, DataAccessException {
ImageIO.scanForPlugins(); ImageIO.scanForPlugins();
plop("jpeg"); plop("jpeg");
@ -137,6 +143,8 @@ public class WebLauncher {
rc.register(HealthCheck.class); rc.register(HealthCheck.class);
rc.register(Front.class); rc.register(Front.class);
ContextGenericTools.addJsr310(rc);
// add jackson to be discover when we are ins standalone server // add jackson to be discover when we are ins standalone server
rc.register(JacksonFeature.class); rc.register(JacksonFeature.class);
// enable this to show low level request // enable this to show low level request
@ -148,7 +156,7 @@ public class WebLauncher {
// System.out.println(" getDBLogin: '" + ConfigVariable.getDBLogin() + "'"); // System.out.println(" getDBLogin: '" + ConfigVariable.getDBLogin() + "'");
// System.out.println(" getDBPassword: '" + ConfigVariable.getDBPassword() + "'"); // System.out.println(" getDBPassword: '" + ConfigVariable.getDBPassword() + "'");
// System.out.println(" getDBName: '" + ConfigVariable.getDBName() + "'"); // System.out.println(" getDBName: '" + ConfigVariable.getDBName() + "'");
System.out.println(" ==> " + GlobalConfiguration.dbConfig); System.out.println(" ==> " + new DbConfig());
System.out.println("OAuth service " + getBaseURI()); System.out.println("OAuth service " + getBaseURI());
this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc); this.server = GrizzlyHttpServerFactory.createHttpServer(getBaseURI(), rc);
final HttpServer serverLink = this.server; final HttpServer serverLink = this.server;

View File

@ -4,6 +4,7 @@ import java.util.List;
import org.kar.archidata.api.DataResource; import org.kar.archidata.api.DataResource;
import org.kar.archidata.api.ProxyResource; import org.kar.archidata.api.ProxyResource;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.externalRestApi.AnalyzeApi; import org.kar.archidata.externalRestApi.AnalyzeApi;
import org.kar.archidata.externalRestApi.TsGenerateApi; import org.kar.archidata.externalRestApi.TsGenerateApi;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
@ -43,7 +44,7 @@ public class WebLauncherLocal extends WebLauncher {
} }
@Override @Override
public void process() throws InterruptedException { public void process() throws InterruptedException, DataAccessException {
if (true) { if (true) {
// for local test: // for local test:
ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/"; ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/";

View File

@ -9,9 +9,9 @@ import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress; import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karusic.model.Album; import org.kar.karusic.model.Album;
@ -41,8 +41,9 @@ public class AlbumResource {
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
@Operation(description = "Get a specific Album with his ID") @Operation(description = "Get a specific Album with his ID")
public static Album get(@PathParam("id") final Long id) throws Exception { public Album get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Album.class, id); return DataAccess.get(Album.class, id);
// return this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).first();
} }
@GET @GET
@ -50,6 +51,8 @@ public class AlbumResource {
@Operation(description = "Get all the available Albums") @Operation(description = "Get all the available Albums")
public List<Album> gets() throws Exception { public List<Album> gets() throws Exception {
return DataAccess.gets(Album.class); return DataAccess.gets(Album.class);
// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class);
// return query.stream().toList();
} }
@POST @POST
@ -57,6 +60,12 @@ public class AlbumResource {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Add an album (when all the data already exist)") @Operation(description = "Add an album (when all the data already exist)")
public Album post(final Album data) throws Exception { public Album post(final Album data) throws Exception {
// TODO: how to manage the checker ???
// final Album ret = this.morphiaService.getDatastore().save(data);
// return ret;
/* final MongoCollection<Track> trackCollection = db.getCollection("TTRACLK", Track.class); final InsertOneResult res = trackCollection.insertOne(plop); LOGGER.warn("plpop {}", res); final
* ObjectId ploppppp = res.getInsertedId().asObjectId().getValue(); LOGGER.warn("plpop 2522 {}", res.getInsertedId().asObjectId().getValue()); final Track ret =
* trackCollection.find(Filters.eq("_id", res.getInsertedId().asObjectId().getValue())) .first(); System.out.println("Grade found:\t" + ret); */
return DataAccess.insert(data, new CheckFunction(CHECKER)); return DataAccess.insert(data, new CheckFunction(CHECKER));
} }
@ -66,37 +75,45 @@ public class AlbumResource {
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Update a specific album") @Operation(description = "Update a specific album")
public Album patch(@PathParam("id") final Long id, @AsyncType(Album.class) final String jsonRequest) throws Exception { public Album patch(@PathParam("id") final Long id, @AsyncType(Album.class) final String jsonRequest) throws Exception {
// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id));
// final UpdateOperations<Album> ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class)
// .set("name", master.getName());
// this.morphiaService.getDatastore().update(query, ops);
// return Response.ok(master).build();
DataAccess.updateWithJson(Album.class, id, jsonRequest, new CheckFunction(CHECKER)); DataAccess.updateWithJson(Album.class, id, jsonRequest, new CheckFunction(CHECKER));
return DataAccess.get(Album.class, id); return DataAccess.get(Album.class, id);
} }
// @PUT
// @Path("{id}")
// @RolesAllowed("ADMIN")
// @Consumes(MediaType.APPLICATION_JSON)
// @Operation(description = "Update a specific album")
// public Album put(@PathParam("id") final Long id, final Album album)
// throws Exception {
// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id));
// final UpdateOperations<Album> ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class)
// .set("name", album.getName());
// this.morphiaService.getDatastore().update(query, ops);
// return Response.ok(album).build();
// }
@DELETE @DELETE
@Path("{id}") @Path("{id}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a specific album") @Operation(description = "Remove a specific album")
public void remove(@PathParam("id") final Long id) throws Exception { public void remove(@PathParam("id") final Long id) throws Exception {
DataAccess.delete(Album.class, id); DataAccess.delete(Album.class, id);
// this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id)).delete();
} }
@POST /* @POST
@Path("{id}/track/{trackId}") * @Path("{id}/track/{trackId}")
@RolesAllowed("ADMIN") * @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) * @Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Add a Track on a specific album") * @Operation(description = "Add a Track on a specific album") public Album addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
public Album addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { * AddOnManyToMany.removeLink(this.dam, Album.class, id, "track", trackId); return this.dam.get(Album.class, id); } */
AddOnManyToMany.removeLink(Album.class, id, "track", trackId);
return DataAccess.get(Album.class, id);
}
@DELETE
@Path("{id}/track/{trackId}")
@RolesAllowed("ADMIN")
@Operation(description = "Remove a Track on a specific album")
public Album removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
AddOnManyToMany.removeLink(Album.class, id, "track", trackId);
return DataAccess.get(Album.class, id);
}
@POST @POST
@Path("{id}/cover") @Path("{id}/cover")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@ -105,12 +122,14 @@ public class AlbumResource {
@TypeScriptProgress @TypeScriptProgress
public Album uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, public Album uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { @FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) { try (DBAccess db = DBAccess.createInterface()) {
DataTools.uploadCoverFromUri(Album.class, id, uri); if (uri != null) {
} else { DataTools.uploadCoverFromUri(db, Album.class, id, uri);
DataTools.uploadCover(Album.class, id, fileInputStream, fileMetaData); } else {
DataTools.uploadCover(db, Album.class, id, fileInputStream, fileMetaData);
}
return db.get(Album.class, id);
} }
return DataAccess.get(Album.class, id);
} }
@DELETE @DELETE
@ -118,7 +137,9 @@ public class AlbumResource {
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Operation(description = "Remove a cover on a specific album") @Operation(description = "Remove a cover on a specific album")
public Album removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { public Album removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception {
AddOnDataJson.removeLink(Album.class, id, "covers", coverId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Album.class, id); AddOnDataJson.removeLink(db, Album.class, "id", id, "covers", coverId);
return db.get(Album.class, id);
}
} }
} }

View File

@ -2,15 +2,16 @@ package org.kar.karusic.api;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress; import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karusic.model.Artist; import org.kar.karusic.model.Artist;
@ -38,7 +39,7 @@ public class ArtistResource {
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
public static Artist get(@PathParam("id") final Long id) throws Exception { public Artist get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Artist.class, id); return DataAccess.get(Artist.class, id);
} }
@ -78,20 +79,23 @@ public class ArtistResource {
@TypeScriptProgress @TypeScriptProgress
public Artist uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, public Artist uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { @FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) { try (DBAccess db = DBAccess.createInterface()) {
DataTools.uploadCoverFromUri(Artist.class, id, uri); if (uri != null) {
} else { DataTools.uploadCoverFromUri(db, Artist.class, id, uri);
DataTools.uploadCover(Artist.class, id, fileInputStream, fileMetaData); } else {
DataTools.uploadCover(db, Artist.class, id, fileInputStream, fileMetaData);
}
return db.get(Artist.class, id);
} }
return DataAccess.get(Artist.class, id);
} }
@DELETE @DELETE
@Path("{id}/cover/{coverId}") @Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public Artist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { public Artist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
LOGGER.error("klmlmkmlkmlklmklmk"); try (DBAccess db = DBAccess.createInterface()) {
AddOnDataJson.removeLink(Artist.class, id, "covers", coverId); AddOnDataJson.removeLink(db, Artist.class, "id", id, "covers", coverId);
return DataAccess.get(Artist.class, id); return db.get(Artist.class, id);
}
} }
} }

View File

@ -2,15 +2,16 @@ package org.kar.karusic.api;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress; import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karusic.model.Gender; import org.kar.karusic.model.Gender;
@ -38,7 +39,7 @@ public class GenderResource {
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
public static Gender get(@PathParam("id") final Long id) throws Exception { public Gender get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Gender.class, id); return DataAccess.get(Gender.class, id);
} }
@ -78,19 +79,23 @@ public class GenderResource {
@TypeScriptProgress @TypeScriptProgress
public Gender uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream, public Gender uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { @FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) { try (DBAccess db = DBAccess.createInterface()) {
DataTools.uploadCoverFromUri(Gender.class, id, uri); if (uri != null) {
} else { DataTools.uploadCoverFromUri(db, Gender.class, id, uri);
DataTools.uploadCover(Gender.class, id, fileInputStream, fileMetaData); } else {
DataTools.uploadCover(db, Gender.class, id, fileInputStream, fileMetaData);
}
return db.get(Gender.class, id);
} }
return DataAccess.get(Gender.class, id);
} }
@DELETE @DELETE
@Path("{id}/cover/{coverId}") @Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public Gender removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { public Gender removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
AddOnDataJson.removeLink(Gender.class, id, "covers", coverId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Gender.class, id); AddOnDataJson.removeLink(db, Gender.class, "id", id, "covers", coverId);
return db.get(Gender.class, id);
}
} }
} }

View File

@ -2,14 +2,14 @@ package org.kar.karusic.api;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
import org.kar.karusic.model.Playlist; import org.kar.karusic.model.Playlist;
@ -37,7 +37,7 @@ public class PlaylistResource {
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
public static Playlist get(@PathParam("id") final Long id) throws Exception { public Playlist get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Playlist.class, id); return DataAccess.get(Playlist.class, id);
} }
@ -75,16 +75,20 @@ public class PlaylistResource {
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
AddOnManyToMany.removeLink(Playlist.class, id, "track", trackId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Playlist.class, id); AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId);
return db.get(Playlist.class, id);
}
} }
@DELETE @DELETE
@Path("{id}/track/{trackId}") @Path("{id}/track/{trackId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public Playlist removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception { public Playlist removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
AddOnManyToMany.removeLink(Playlist.class, id, "track", trackId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Playlist.class, id); AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId);
return db.get(Playlist.class, id);
}
} }
@POST @POST
@ -94,14 +98,18 @@ public class PlaylistResource {
@AsyncType(Playlist.class) @AsyncType(Playlist.class)
public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
throws Exception { throws Exception {
DataTools.uploadCover(Playlist.class, id, fileInputStream, fileMetaData); try (DBAccess db = DBAccess.createInterface()) {
DataTools.uploadCover(db, Playlist.class, id, fileInputStream, fileMetaData);
}
} }
@DELETE @DELETE
@Path("{id}/cover/{coverId}") @Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
AddOnDataJson.removeLink(Playlist.class, id, "covers", coverId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Playlist.class, id); AddOnDataJson.removeLink(db, Playlist.class, "id", id, "covers", coverId);
return DataAccess.get(Playlist.class, id);
}
} }
} }

View File

@ -5,16 +5,16 @@ import java.io.InputStream;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType; import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional; import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress; import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.addOn.AddOnManyToMany;
import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.model.Data; import org.kar.archidata.model.Data;
import org.kar.archidata.tools.DataTools; import org.kar.archidata.tools.DataTools;
@ -44,7 +44,7 @@ public class TrackResource {
@GET @GET
@Path("{id}") @Path("{id}")
@RolesAllowed("USER") @RolesAllowed("USER")
public static Track get(@PathParam("id") final Long id) throws Exception { public Track get(@PathParam("id") final Long id) throws Exception {
return DataAccess.get(Track.class, id); return DataAccess.get(Track.class, id);
} }
@ -82,16 +82,20 @@ public class TrackResource {
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA }) @Consumes({ MediaType.MULTIPART_FORM_DATA })
public Track addTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { public Track addTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception {
AddOnManyToMany.removeLink(Track.class, id, "artist", artistId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Track.class, id); AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId);
return DataAccess.get(Track.class, id);
}
} }
@DELETE @DELETE
@Path("{id}/artist/{trackId}") @Path("{id}/artist/{trackId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public Track removeTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception { public Track removeTrack(@PathParam("id") final Long id, @PathParam("artistId") final Long artistId) throws Exception {
AddOnManyToMany.removeLink(Track.class, id, "artist", artistId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Track.class, id); AddOnDataJson.removeLink(db, Track.class, "id", id, "artist", artistId);
return DataAccess.get(Track.class, id);
}
} }
@POST @POST
@ -101,20 +105,24 @@ public class TrackResource {
@TypeScriptProgress @TypeScriptProgress
public Track uploadCover(@PathParam("id") final Long id, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream, public Track uploadCover(@PathParam("id") final Long id, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception { @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
if (uri != null) { try (DBAccess db = DBAccess.createInterface()) {
DataTools.uploadCoverFromUri(Track.class, id, uri); if (uri != null) {
} else { DataTools.uploadCoverFromUri(db, Track.class, id, uri);
DataTools.uploadCover(Track.class, id, fileInputStream, fileMetaData); } else {
DataTools.uploadCover(db, Track.class, id, fileInputStream, fileMetaData);
}
return DataAccess.get(Track.class, id);
} }
return DataAccess.get(Track.class, id);
} }
@DELETE @DELETE
@Path("{id}/cover/{coverId}") @Path("{id}/cover/{coverId}")
@RolesAllowed("ADMIN") @RolesAllowed("ADMIN")
public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final UUID coverId) throws Exception { public Track removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
AddOnDataJson.removeLink(Track.class, id, "covers", coverId); try (DBAccess db = DBAccess.createInterface()) {
return DataAccess.get(Track.class, id); AddOnDataJson.removeLink(db, Track.class, "id", id, "covers", coverId);
return db.get(Track.class, id);
}
} }
@POST @POST
@ -132,7 +140,7 @@ public class TrackResource {
@FormDataParam("file") final InputStream fileInputStream, // @FormDataParam("file") final InputStream fileInputStream, //
@FormDataParam("file") final FormDataContentDisposition fileMetaData // @FormDataParam("file") final FormDataContentDisposition fileMetaData //
) { ) {
try { try (DBAccess db = DBAccess.createInterface()) {
// correct input string stream : // correct input string stream :
trackId = DataTools.multipartCorrection(trackId); trackId = DataTools.multipartCorrection(trackId);
albumId = DataTools.multipartCorrection(albumId); albumId = DataTools.multipartCorrection(albumId);
@ -153,12 +161,12 @@ public class TrackResource {
final long tmpUID = DataTools.getTmpDataId(); final long tmpUID = DataTools.getTmpDataId();
final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID); final String sha512 = DataTools.saveTemporaryFile(fileInputStream, tmpUID);
Data data = DataTools.getWithSha512(sha512); Data data = DataTools.getWithSha512(db, sha512);
if (data == null) { if (data == null) {
LOGGER.info("Need to add the data in the BDD ... "); LOGGER.info("Need to add the data in the BDD ... ");
try { try {
data = DataTools.createNewData(tmpUID, fileMetaData.getFileName(), sha512); data = DataTools.createNewData(db, tmpUID, fileMetaData.getFileName(), sha512);
} catch (final IOException ex) { } catch (final IOException ex) {
DataTools.removeTemporaryFile(tmpUID); DataTools.removeTemporaryFile(tmpUID);
ex.printStackTrace(); ex.printStackTrace();
@ -170,7 +178,7 @@ public class TrackResource {
} }
} else if (data.deleted) { } else if (data.deleted) {
LOGGER.info("Data already exist but deleted"); LOGGER.info("Data already exist but deleted");
DataTools.undelete(data.uuid); DataTools.undelete(db, data.oid);
data.deleted = false; data.deleted = false;
} else { } else {
LOGGER.info("Data already exist ... all good"); LOGGER.info("Data already exist ... all good");
@ -182,14 +190,14 @@ public class TrackResource {
trackElem.track = trackId != null ? Long.parseLong(trackId) : null; trackElem.track = trackId != null ? Long.parseLong(trackId) : null;
trackElem.albumId = albumId != null ? Long.parseLong(albumId) : null; trackElem.albumId = albumId != null ? Long.parseLong(albumId) : null;
trackElem.genderId = genderId != null ? Long.parseLong(genderId) : null; trackElem.genderId = genderId != null ? Long.parseLong(genderId) : null;
trackElem.dataId = data.uuid; trackElem.dataId = data.oid;
// Now list of artist has an internal management: // Now list of artist has an internal management:
if (artistId != null) { if (artistId != null) {
trackElem.artists = new ArrayList<>(); trackElem.artists = new ArrayList<>();
trackElem.artists.add(artistId != null ? Long.parseLong(artistId) : null); trackElem.artists.add(artistId != null ? Long.parseLong(artistId) : null);
} }
trackElem = DataAccess.insert(trackElem, new CheckFunction(CHECKER)); trackElem = DataAccess.insert(trackElem, new CheckFunction(CHECKER));
/* Old mode of artist insertion (removed due to the slowlest request of getting value if (artistElem != null) { DataAccess.addLink(Track.class, trackElem.id, "artist", artistElem.id); } */ /* Old mode of artist insertion (removed due to the slowlest request of getting value if (artistElem != null) { this.dam.addLink(Track.class, trackElem.id, "artist", artistElem.id); } */
return Response.ok(trackElem).build(); return Response.ok(trackElem).build();
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.info("Catch an unexpected error ... {}", ex.getMessage()); LOGGER.info("Catch an unexpected error ... {}", ex.getMessage());

View File

@ -2,7 +2,7 @@ package org.kar.karusic.migration;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.DataAccess; import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.migration.MigrationSqlStep; import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.model.Data; import org.kar.archidata.model.Data;
import org.kar.archidata.model.User; import org.kar.archidata.model.User;
@ -35,35 +35,35 @@ public class Initialization extends MigrationSqlStep {
addClass(elem); addClass(elem);
} }
addAction(""" addAction((final DBAccess da) -> {
INSERT INTO `gender` (`id`, `name`, `description`) VALUES final List<Gender> data = List.of(//
(1, 'Variété française', NULL), new Gender(1L, "Variété française"), //
(2, 'Pop', NULL), new Gender(2L, "Pop"), //
(3, 'inconnue', NULL), new Gender(3L, "inconnue"), //
(4, 'Disco', NULL), new Gender(4L, "Disco"), //
(5, 'Enfants', NULL), new Gender(5L, "Enfants"), //
(6, 'Portugaise', NULL), new Gender(6L, "Portugaise"), //
(7, 'Apprentissage', NULL), new Gender(7L, "Apprentissage"), //
(8, 'Blues', NULL), new Gender(8L, "Blues"), //
(9, 'Jazz', NULL), new Gender(9L, "Jazz"), //
(10, 'Chanson Noël', NULL), new Gender(10L, "Chanson Noël"), //
(11, 'DubStep', NULL), new Gender(11L, "DubStep"), //
(12, 'Rap français', NULL), new Gender(12L, "Rap français"), //
(13, 'Classique', NULL), new Gender(13L, "Classique"), //
(14, 'Rock', NULL), new Gender(14L, "Rock"), //
(15, 'Electro', NULL), new Gender(15L, "Electro"), //
(16, 'Celtique', NULL), new Gender(16L, "Celtique"), //
(17, 'Country', NULL), new Gender(17L, "Country"), //
(18, 'Variété Québéquoise', NULL), new Gender(18L, "Variété Québéquoise"), //
(19, 'Médiéval', NULL), new Gender(19L, "Médiéval"), //
(20, 'Variété Italienne', NULL), new Gender(20L, "Variété Italienne"), //
(21, 'Comédie Musicale', NULL), new Gender(21L, "Comédie Musicale"), //
(22, 'Vianney', NULL), new Gender(22L, "Vianney"), //
(23, 'Bande Original', NULL), new Gender(23L, "Bande Original"), //
(24, 'Bande Originale', NULL), new Gender(24L, "Bande Originale"), //
(25, 'Variété Belge', NULL), new Gender(25L, "Variété Belge"), //
(26, 'Gospel', NULL); new Gender(26L, "Gospel"));
"""); });
// set start increment element to permit to add after default elements // set start increment element to permit to add after default elements
addAction(""" addAction("""
ALTER TABLE `album` AUTO_INCREMENT = 1000; ALTER TABLE `album` AUTO_INCREMENT = 1000;
@ -85,10 +85,10 @@ public class Initialization extends MigrationSqlStep {
""", "mysql"); """, "mysql");
} }
public static void dropAll() { public static void dropAll(final DBAccess da) {
for (final Class<?> element : CLASSES_BASE) { for (final Class<?> element : CLASSES_BASE) {
try { try {
DataAccess.drop(element); da.drop(element);
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.error("Fail to drop table !!!!!!"); LOGGER.error("Fail to drop table !!!!!!");
ex.printStackTrace(); ex.printStackTrace();
@ -96,10 +96,10 @@ public class Initialization extends MigrationSqlStep {
} }
} }
public static void cleanAll() { public static void cleanAll(final DBAccess da) {
for (final Class<?> element : CLASSES_BASE) { for (final Class<?> element : CLASSES_BASE) {
try { try {
DataAccess.cleanAll(element); da.cleanAll(element);
} catch (final Exception ex) { } catch (final Exception ex) {
LOGGER.error("Fail to clean table !!!!!!"); LOGGER.error("Fail to clean table !!!!!!");
ex.printStackTrace(); ex.printStackTrace();

View File

@ -11,159 +11,4 @@ public class Migration20231126 extends MigrationSqlStep {
return "migration-2023-11-26: reorder the migration for the new API of archidata"; return "migration-2023-11-26: reorder the migration for the new API of archidata";
} }
public Migration20231126() {
}
@Override
public void generateStep() throws Exception {
// update migration update (last one)
addAction("""
ALTER TABLE `KAR_migration`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
ADD `version` int NOT NULL DEFAULT '2' AFTER `deleted`,
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL COMMENT 'Name of the migration' AFTER `version`,
CHANGE `terminated` `terminated` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'if the migration is well terminated or not' AFTER `name`,
CHANGE `stepId` `stepId` int NULL COMMENT 'index in the migration progression' AFTER `terminated`,
CHANGE `count` `count` int NULL COMMENT 'number of element in the migration' AFTER `stepId`,
CHANGE `log` `log` text COLLATE 'utf8mb3_general_ci' NULL COMMENT 'Log generate by the migration' AFTER `count`;
""");
addAction("""
ALTER TABLE `album`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`,
CHANGE `publication` `publication` date NULL AFTER `description`;
""");
addAction("""
ALTER TABLE `album_link_cover`
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
CHANGE `album_id` `object1id` bigint NOT NULL AFTER `deleted`,
CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`;
""");
addAction("""
ALTER TABLE `artist`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
CHANGE `firstName` `firstName` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `description`,
CHANGE `surname` `surname` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `firstName`,
CHANGE `birth` `birth` date NULL AFTER `surname`,
CHANGE `death` `death` date NULL AFTER `birth`;
""");
addAction("""
ALTER TABLE `artist_link_cover`
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
CHANGE `artist_id` `object1id` bigint NOT NULL AFTER `deleted`,
CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`;
""");
addAction("""
ALTER TABLE `data`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
CHANGE `sha512` `sha512` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Sha512 of the data' AFTER `deleted`,
CHANGE `mimeType` `mimeType` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NOT NULL COMMENT 'Mime -type of the media' AFTER `sha512`,
CHANGE `size` `size` bigint NOT NULL COMMENT 'Size in Byte of the data' AFTER `mimeType`;
""");
addAction("""
ALTER TABLE `gender`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`;
""");
addAction("""
ALTER TABLE `gender_link_cover`
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
CHANGE `gender_id` `object1id` bigint NOT NULL AFTER `deleted`,
CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`;
""");
addAction("""
ALTER TABLE `playlist`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`;
""");
addAction("""
ALTER TABLE `playlist_link_cover`
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
CHANGE `playlist_id` `object1id` bigint NOT NULL AFTER `deleted`,
CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`;
""");
addAction("""
ALTER TABLE `playlist_link_track`
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
CHANGE `playlist_id` `object1id` bigint NOT NULL AFTER `deleted`,
CHANGE `track_id` `object2id` bigint NOT NULL AFTER `object1id`;
""");
addAction("""
ALTER TABLE `track`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
CHANGE `name` `name` varchar(256) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
CHANGE `description` `description` text COLLATE 'utf8mb3_general_ci' NULL AFTER `name`,
CHANGE `genderId` `genderId` bigint NULL AFTER `description`,
CHANGE `albumId` `albumId` bigint NULL AFTER `genderId`,
CHANGE `track` `track` bigint NULL AFTER `albumId`,
CHANGE `dataId` `dataId` bigint NULL AFTER `track`,
CHANGE `artists` `artists` text COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `dataId`;
""");
addAction("""
ALTER TABLE `track_link_cover`
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' AFTER `updatedAt`,
CHANGE `track_id` `object1id` bigint NOT NULL AFTER `deleted`,
CHANGE `cover_id` `object2id` bigint NOT NULL AFTER `object1id`;
""");
addAction("""
ALTER TABLE `user`
CHANGE `id` `id` bigint NOT NULL COMMENT 'Primary key of the base' AUTO_INCREMENT FIRST,
CHANGE `create_date` `createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' AFTER `id`,
CHANGE `modify_date` `updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'When update the object' AFTER `createdAt`,
CHANGE `deleted` `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' AFTER `updatedAt`,
CHANGE `login` `login` varchar(128) COLLATE 'utf8mb4_0900_ai_ci' NULL AFTER `deleted`,
CHANGE `lastConnection` `lastConnection` timestamp(3) NULL AFTER `login`,
CHANGE `admin` `admin` tinyint(1) NOT NULL DEFAULT '0' AFTER `lastConnection`,
CHANGE `blocked` `blocked` tinyint(1) NOT NULL DEFAULT '0' AFTER `admin`,
CHANGE `removed` `removed` tinyint(1) NOT NULL DEFAULT '0' AFTER `blocked`;
""");
addAction("""
CREATE TABLE `user_link_cover` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Primary key of the base' ,
`createdAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT 'Create time of the object' ,
`updatedAt` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT 'When update the object' ,
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'When delete, they are not removed, they are just set in a deleted state' ,
`object1Id` bigint NOT NULL COMMENT 'Object reference 1' ,
`object2Id` bigint NOT NULL COMMENT 'Object reference 2' ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
""");
}
} }

View File

@ -11,16 +11,4 @@ public class Migration20240225 extends MigrationSqlStep {
return "migration-2024-02-25: change model of thrack to use real json"; return "migration-2024-02-25: change model of thrack to use real json";
} }
public Migration20240225() {
}
@Override
public void generateStep() throws Exception {
// update migration update (last one)
addAction("""
UPDATE `track` SET artists = CONCAT('[', artists, ']') WHERE artists IS NOT NULL
""");
}
} }

View File

@ -1,22 +1,6 @@
package org.kar.karusic.migration; package org.kar.karusic.migration;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.kar.archidata.api.DataResource;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.model.LinkTableLongLong;
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.migration.MigrationSqlStep; import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.tools.UuidUtils;
import org.kar.karusic.migration.model.CoverConversion;
import org.kar.karusic.migration.model.MediaConversion;
import org.kar.karusic.migration.model.UUIDConversion;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -30,106 +14,4 @@ public class Migration20240226 extends MigrationSqlStep {
return "migration-2024-02-26: convert base with UUID"; return "migration-2024-02-26: convert base with UUID";
} }
public Migration20240226() {
}
@Override
public void generateStep() throws Exception {
addAction("""
ALTER TABLE `data` ADD `uuid` binary(16) AFTER `id`;
""");
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
for (final UUIDConversion elem : datas) {
elem.uuid = UuidUtils.nextUUID();
}
for (final UUIDConversion elem : datas) {
DataAccess.update(elem, elem.id, List.of("uuid"), new OverrideTableName("data"));
}
});
addAction("""
ALTER TABLE `data` CHANGE `uuid` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
""");
final List<String> tableToTransform = List.of("album", "artist", "gender", "playlist", "track", "user");
for (final String tableName : tableToTransform) {
addAction("ALTER TABLE `" + tableName + "` ADD `covers` text NULL;");
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
final List<CoverConversion> medias = DataAccess.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName));
final List<LinkTableLongLong> links = DataAccess.gets(LinkTableLongLong.class, new OverrideTableName(tableName + "_link_cover"));
LOGGER.info("Get somes data: {} {} {}", datas.size(), medias.size(), links.size());
for (final CoverConversion media : medias) {
final List<UUID> values = new ArrayList<>();
for (final LinkTableLongLong link : links) {
if (link.object1Id.equals(media.id)) {
for (final UUIDConversion data : datas) {
if (data.id.equals(link.object2Id)) {
values.add(data.uuid);
break;
}
}
break;
}
}
if (values.size() != 0) {
media.covers = values;
LOGGER.info(" update: {} => {}", media.id, media.covers);
DataAccess.update(media, media.id, List.of("covers"), new OverrideTableName(tableName));
}
}
});
addAction("DROP TABLE `" + tableName + "_link_cover`;");
}
addAction("""
ALTER TABLE `track` ADD `dataUUID` binary(16) AFTER dataId;
""");
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
final List<MediaConversion> medias = DataAccess.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("track"));
for (final MediaConversion media : medias) {
for (final UUIDConversion data : datas) {
if (data.id.equals(media.dataId)) {
media.dataUUID = data.uuid;
DataAccess.update(media, media.id, List.of("dataUUID"), new OverrideTableName("track"));
break;
}
}
}
});
addAction("""
DROP TABLE `playlist`;
""");
addAction("""
DROP TABLE `playlist_link_track`;
""");
addAction("""
ALTER TABLE `track` DROP `dataId`;
""");
addAction("""
ALTER TABLE `track` CHANGE `dataUUID` `dataId` binary(16) NOT NULL;
""");
// Move the files...
addAction(() -> {
final List<UUIDConversion> datas = DataAccess.gets(UUIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
for (final UUIDConversion data : datas) {
final String origin = DataResource.getFileDataOld(data.id);
final String destination = DataResource.getFileData(data.uuid);
LOGGER.info("move file = {}", origin);
LOGGER.info(" ==> {}", destination);
Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE);
}
});
addAction("""
ALTER TABLE `data` DROP `id`;
""");
addAction("""
ALTER TABLE `data` CHANGE `uuid` `id` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
""");
addAction("""
ALTER TABLE `data` ADD PRIMARY KEY `id` (`id`);
""");
}
} }

View File

@ -0,0 +1,144 @@
package org.kar.karusic.migration;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.api.DataResource;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.karusic.migration.model.CoverConversion;
import org.kar.karusic.migration.model.MediaConversion;
import org.kar.karusic.migration.model.OIDConversion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Migration20250104 extends MigrationSqlStep {
private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240226.class);
public static final int KARSO_INITIALISATION_ID = 1;
@Override
public String getName() {
return "migration-2025-01-04: convert base from UUID to OID";
}
@Override
public void generateStep() throws Exception {
// Create a simple function to create objectId in the DB (for manual insertion ...)
// addAction("""
// DELIMITER //
//
// CREATE FUNCTION generate_objectid()
// RETURNS BINARY(12)
// DETERMINISTIC
// BEGIN
// DECLARE ts BINARY(4);
// DECLARE random_part BINARY(5);
// DECLARE counter BINARY(3);
// SET ts = UNHEX(HEX(UNIX_TIMESTAMP()));
// SET random_part = UNHEX(HEX(FLOOR(RAND() * POW(2, 40))));
// SET counter = UNHEX(HEX(FLOOR(RAND() * POW(2, 24))));
// RETURN CONCAT(ts, random_part, counter);
// END //
//
// DELIMITER ;
// """);
addAction("""
ALTER TABLE `data` ADD `_id` binary(12) AFTER `uuid`;
""");
addAction((final DBAccess da) -> {
final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
for (final OIDConversion elem : datas) {
elem._id = new ObjectId();
}
for (final OIDConversion elem : datas) {
da.update(elem, elem.uuid, List.of("_id"), new OverrideTableName("data"));
}
});
final List<String> tableToTransform = List.of("album", "artist", "gender", "track", "user");
for (final String tableName : tableToTransform) {
addAction("ALTER TABLE `" + tableName + "` ADD `covers_oid` text NULL;");
addAction((final DBAccess da) -> {
final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
final List<CoverConversion> tableCoverTransforms = da.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName));
LOGGER.info("Get somes data: {} {}", datas.size(), tableCoverTransforms.size());
for (final CoverConversion tableTransform : tableCoverTransforms) {
final List<ObjectId> values = new ArrayList<>();
if (tableTransform.covers == null) {
continue;
}
for (final UUID link : tableTransform.covers) {
for (final OIDConversion data : datas) {
if (data.uuid.equals(link)) {
values.add(data._id);
break;
}
}
}
if (values.size() != 0) {
tableTransform.covers_oid = values;
LOGGER.info(" update: {}: {} => {}", tableTransform.id, tableTransform.covers, tableTransform.covers_oid);
da.update(tableTransform, tableTransform.id, List.of("covers_oid"), new OverrideTableName(tableName));
}
}
});
addAction("ALTER TABLE `" + tableName + "` DROP `covers`;");
addAction("ALTER TABLE `" + tableName + "` CHANGE `covers_oid` `covers` text NULL;");
}
addAction("""
ALTER TABLE `track` ADD `dataOid` binary(12) AFTER dataId;
""");
addAction((final DBAccess da) -> {
final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
final List<MediaConversion> medias = da.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("track"));
for (final MediaConversion media : medias) {
for (final OIDConversion data : datas) {
if (data.uuid.equals(media.dataId)) {
media.dataOid = data._id;
da.update(media, media.id, List.of("dataOid"), new OverrideTableName("track"));
break;
}
}
}
});
addAction("""
ALTER TABLE `track` DROP `dataId`;
""");
addAction("""
ALTER TABLE `track` CHANGE `dataOid` `dataId` binary(12) NOT NULL;
""");
// Move the files...
addAction((final DBAccess da) -> {
final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
for (final OIDConversion data : datas) {
final String origin = DataResource.getFileDataOld(data.uuid);
final String destination = DataResource.getFileData(data._id);
LOGGER.info("move file = {}", origin);
LOGGER.info(" ==> {}", destination);
try {
Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE);
} catch (final NoSuchFileException ex) {
LOGGER.warn("Fail to move file : {}", ex.getMessage());
}
}
});
addAction("""
ALTER TABLE `data` DROP `uuid`;
""");
// addAction("""
// ALTER TABLE `data` CHANGE `_id` `_id` BINARY(12) DEFAULT (generate_objectid());
// """);
addAction("""
ALTER TABLE `data` ADD PRIMARY KEY `_id` (`_id`);
""");
}
}

View File

@ -0,0 +1,31 @@
package org.kar.karusic.migration;
import org.kar.archidata.migration.MigrationSqlStep;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Migration20250105 extends MigrationSqlStep {
private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240907.class);
public static final int KARSO_INITIALISATION_ID = 1;
@Override
public String getName() {
return "migration-2025-01-05: remove old UUID";
}
@Override
public void generateStep() throws Exception {
// addAction("""
// ALTER TABLE `data` DROP INDEX `PRIMARY`;
// """);
// addAction("""
// ALTER TABLE `data` CHANGE `id` `uuid` binary(16) DEFAULT (UUID_TO_BIN(UUID(), TRUE));
// """);
// addAction("""
// ALTER TABLE `data` ADD PRIMARY KEY `uuid` (`uuid`);
// """);
}
}

View File

@ -3,6 +3,7 @@ package org.kar.karusic.migration.model;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import jakarta.persistence.Id; import jakarta.persistence.Id;
@ -12,4 +13,6 @@ public class CoverConversion {
public Long id = null; public Long id = null;
@DataJson @DataJson
public List<UUID> covers = null; public List<UUID> covers = null;
@DataJson
public List<ObjectId> covers_oid = null;
} }

View File

@ -2,11 +2,13 @@ package org.kar.karusic.migration.model;
import java.util.UUID; import java.util.UUID;
import org.bson.types.ObjectId;
import jakarta.persistence.Id; import jakarta.persistence.Id;
public class MediaConversion { public class MediaConversion {
@Id @Id
public Long id = null; public Long id = null;
public Long dataId = null; public UUID dataId = null;
public UUID dataUUID = null; public ObjectId dataOid = null;
} }

View File

@ -2,10 +2,12 @@ package org.kar.karusic.migration.model;
import java.util.UUID; import java.util.UUID;
import org.bson.types.ObjectId;
import jakarta.persistence.Id; import jakarta.persistence.Id;
public class UUIDConversion { public class OIDConversion {
@Id @Id
public Long id = null;
public UUID uuid = null; public UUID uuid = null;
public ObjectId _id = null;
} }

View File

@ -2,8 +2,8 @@ package org.kar.karusic.model;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.options.CheckJPA; import org.kar.archidata.dataAccess.options.CheckJPA;
@ -12,11 +12,13 @@ import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import dev.morphia.annotations.Entity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity("Album")
@Table(name = "album") @Table(name = "album")
@DataIfNotExists @DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@ -34,6 +36,6 @@ public class Album extends GenericDataSoftDelete {
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the specific covers")
@DataJson(targetEntity = Data.class) @DataJson(targetEntity = Data.class)
@Nullable @Nullable
public List<UUID> covers = null; public List<ObjectId> covers = null;
public LocalDate publication = null; public LocalDate publication = null;
} }

View File

@ -2,8 +2,8 @@ package org.kar.karusic.model;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.options.CheckJPA; import org.kar.archidata.dataAccess.options.CheckJPA;
@ -12,11 +12,13 @@ import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import dev.morphia.annotations.Entity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity("Artist")
@Table(name = "artist") @Table(name = "artist")
@DataIfNotExists @DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@ -34,7 +36,7 @@ public class Artist extends GenericDataSoftDelete {
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the specific covers")
@DataJson(targetEntity = Data.class) @DataJson(targetEntity = Data.class)
@Nullable @Nullable
public List<UUID> covers = null; public List<ObjectId> covers = null;
@Column(length = 256) @Column(length = 256)
public String firstName = null; public String firstName = null;
@Column(length = 256) @Column(length = 256)

View File

@ -13,8 +13,8 @@ CREATE TABLE `node` (
*/ */
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.options.CheckJPA; import org.kar.archidata.dataAccess.options.CheckJPA;
@ -23,11 +23,13 @@ import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import dev.morphia.annotations.Entity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity("Gender")
@Table(name = "gender") @Table(name = "gender")
@DataIfNotExists @DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@ -45,6 +47,13 @@ public class Gender extends GenericDataSoftDelete {
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the specific covers")
@DataJson(targetEntity = Data.class) @DataJson(targetEntity = Data.class)
@Nullable @Nullable
public List<UUID> covers = null; public List<ObjectId> covers = null;
public Gender() {}
public Gender(final Long id, final String name) {
this.id = id;
this.name = name;
}
} }

View File

@ -13,8 +13,8 @@ CREATE TABLE `node` (
*/ */
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.options.CheckJPA; import org.kar.archidata.dataAccess.options.CheckJPA;
@ -23,6 +23,7 @@ import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import dev.morphia.annotations.Entity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
@ -30,6 +31,7 @@ import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity("Playlist")
@Table(name = "playlist") @Table(name = "playlist")
@DataIfNotExists @DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@ -47,7 +49,7 @@ public class Playlist extends GenericDataSoftDelete {
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the specific covers")
@DataJson(targetEntity = Data.class) @DataJson(targetEntity = Data.class)
@Nullable @Nullable
public List<UUID> covers = null; public List<ObjectId> covers = null;
@ManyToMany(fetch = FetchType.LAZY, targetEntity = Track.class) @ManyToMany(fetch = FetchType.LAZY, targetEntity = Track.class)
public List<Long> tracks = null; public List<ObjectId> tracks = null;
} }

View File

@ -13,8 +13,8 @@ CREATE TABLE `node` (
*/ */
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists; import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson; import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.options.CheckJPA; import org.kar.archidata.dataAccess.options.CheckJPA;
@ -23,11 +23,13 @@ import org.kar.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import dev.morphia.annotations.Entity;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity("Track")
@Table(name = "track") @Table(name = "track")
@DataIfNotExists @DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
@ -46,11 +48,11 @@ public class Track extends GenericDataSoftDelete {
@Schema(description = "List of Id of the specific covers") @Schema(description = "List of Id of the specific covers")
@DataJson(targetEntity = Data.class) @DataJson(targetEntity = Data.class)
@Nullable @Nullable
public List<UUID> covers = null; public List<ObjectId> covers = null;
public Long genderId = null; public Long genderId = null;
public Long albumId = null; public Long albumId = null;
public Long track = null; public Long track = null;
public UUID dataId = null; public ObjectId dataId = null;
// @ManyToMany(fetch = FetchType.LAZY, targetEntity = Artist.class) // @ManyToMany(fetch = FetchType.LAZY, targetEntity = Artist.class)
@DataJson @DataJson
@Column(length = 0) @Column(length = 0)

View File

@ -0,0 +1,18 @@
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger - %msg%n
</pattern>
<!--
<pattern>
%d{HH:mm:ss.SSS} | %thread | %highlight(%-5level) | %logger - %msg%n
</pattern>
-->
</encoder>
</appender>
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@ -3,12 +3,14 @@
# Default logging detail level for all instances of SimpleLogger. # Default logging detail level for all instances of SimpleLogger.
# Must be one of ("trace", "debug", "info", "warn", or "error"). # Must be one of ("trace", "debug", "info", "warn", or "error").
# If not specified, defaults to "info". # If not specified, defaults to "info".
org.slf4j.simpleLogger.defaultLogLevel=trace org.slf4j.simpleLogger.defaultLogLevel=INFO
# Logging detail level for a SimpleLogger instance named "xxxxx". # Logging detail level for a SimpleLogger instance named "xxxxx".
# Must be one of ("trace", "debug", "info", "warn", or "error"). # Must be one of ("trace", "debug", "info", "warn", or "error").
# If not specified, the default logging detail level is used. # If not specified, the default logging detail level is used.
#org.slf4j.simpleLogger.log.xxxxx= #org.slf4j.simpleLogger.log.xxxxx=
org.slf4j.simpleLogger.log.org.kar.archidata=TRACE
org.slf4j.simpleLogger.log.org.kar.karusic=TRACE
# Set to true if you want the current date and time to be included in output messages. # Set to true if you want the current date and time to be included in output messages.
# Default is false, and will output the number of milliseconds elapsed since startup. # Default is false, and will output the number of milliseconds elapsed since startup.
@ -32,4 +34,9 @@ org.slf4j.simpleLogger.showThreadName=true
# Defaults to false. # Defaults to false.
#org.slf4j.simpleLogger.showShortLogName=false #org.slf4j.simpleLogger.showShortLogName=false
# Utilise les codes ANSI pour la couleur
org.slf4j.simpleLogger.warnColor=\u001B[33m
org.slf4j.simpleLogger.errorColor=\u001B[31m
org.slf4j.simpleLogger.infoColor=\u001B[32m
org.slf4j.simpleLogger.debugColor=\u001B[34m

View File

@ -0,0 +1,126 @@
package test.kar.karusic;
import java.io.IOException;
import java.util.List;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.db.DbConfig;
import org.kar.archidata.db.DbIoFactory;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.karusic.model.Album;
import org.kar.karusic.model.Artist;
import org.kar.karusic.model.Gender;
import org.kar.karusic.model.Playlist;
import org.kar.karusic.model.Track;
import org.kar.karusic.model.UserKarusic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.InternalServerErrorException;
public class ConfigureDb {
final static private Logger LOGGER = LoggerFactory.getLogger(ConfigureDb.class);
final static private String modeTestForced = null;// "MONGO";
public static DBAccess da = null;
public static void configure() throws IOException, InternalServerErrorException, DataAccessException {
String modeTest = System.getenv("TEST_E2E_MODE");
if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) {
modeTest = "SQLITE-MEMORY";
} else if ("true".equalsIgnoreCase(modeTest)) {
modeTest = "MY-SQL";
}
// override the local test:
if (modeTestForced != null) {
modeTest = modeTestForced;
}
final List<Class<?>> listObject = List.of( //
Album.class, //
Artist.class, //
Gender.class, //
Playlist.class, //
Track.class, //
UserKarusic.class //
);
if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) {
ConfigBaseVariable.dbType = "sqlite";
ConfigBaseVariable.bdDatabase = null;
ConfigBaseVariable.dbHost = "memory";
// for test we need to connect all time the DB
ConfigBaseVariable.dbKeepConnected = "true";
} else if ("SQLITE".equalsIgnoreCase(modeTest)) {
ConfigBaseVariable.dbType = "sqlite";
ConfigBaseVariable.bdDatabase = null;
ConfigBaseVariable.dbKeepConnected = "true";
} else if ("MY-SQL".equalsIgnoreCase(modeTest)) {
ConfigBaseVariable.dbType = "mysql";
ConfigBaseVariable.bdDatabase = "test_karusic_db";
ConfigBaseVariable.dbPort = "3906";
ConfigBaseVariable.dbUser = "root";
} else if ("MONGO".equalsIgnoreCase(modeTest)) {
ConfigBaseVariable.dbType = "mongo";
ConfigBaseVariable.bdDatabase = "test_karusic_db";
} else {
// User local modification ...
ConfigBaseVariable.bdDatabase = "test_karusic_db";
ConfigBaseVariable.dbPort = "3906";
ConfigBaseVariable.dbUser = "root";
}
removeDB();
// Connect the dataBase...
da = DBAccess.createInterface();
}
public static void removeDB() {
String modeTest = System.getenv("TEST_E2E_MODE");
if (modeTest == null || modeTest.isEmpty() || "false".equalsIgnoreCase(modeTest)) {
modeTest = "SQLITE-MEMORY";
} else if ("true".equalsIgnoreCase(modeTest)) {
modeTest = "MY-SQL";
}
// override the local test:
if (modeTestForced != null) {
modeTest = modeTestForced;
}
DbConfig config = null;
try {
config = new DbConfig();
} catch (final DataAccessException e) {
e.printStackTrace();
LOGGER.error("Fail to clean the DB");
return;
}
config.setDbName(null);
LOGGER.info("Remove the DB and create a new one '{}'", config.getDbName());
try (final DBAccess daRoot = DBAccess.createInterface(config)) {
if ("SQLITE-MEMORY".equalsIgnoreCase(modeTest)) {
// nothing to do ...
} else if ("SQLITE".equalsIgnoreCase(modeTest)) {
daRoot.deleteDB(ConfigBaseVariable.bdDatabase);
} else if ("MY-SQL".equalsIgnoreCase(modeTest)) {
daRoot.deleteDB(ConfigBaseVariable.bdDatabase);
} else if ("MONGO".equalsIgnoreCase(modeTest)) {
daRoot.deleteDB(ConfigBaseVariable.bdDatabase);
}
daRoot.createDB(ConfigBaseVariable.bdDatabase);
} catch (final InternalServerErrorException e) {
e.printStackTrace();
LOGGER.error("Fail to clean the DB");
return;
} catch (final IOException e) {
e.printStackTrace();
LOGGER.error("Fail to clean the DB");
return;
}
}
public static void clear() throws IOException {
LOGGER.info("Remove the test db");
removeDB();
// The connection is by default open ==> close it at the end of test:
da.close();
DbIoFactory.closeAllForceMode();
ConfigBaseVariable.clearAllValue();
}
}

View File

@ -7,10 +7,8 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.kar.archidata.db.DBEntry;
import org.kar.archidata.tools.ConfigBaseVariable; import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.RESTApi; import org.kar.archidata.tools.RESTApi;
import org.kar.karusic.migration.Initialization;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -27,31 +25,16 @@ public class TestBase {
@BeforeAll @BeforeAll
public static void configureWebServer() throws Exception { public static void configureWebServer() throws Exception {
ConfigureDb.configure();
LOGGER.info("configure server ..."); LOGGER.info("configure server ...");
webInterface = new WebLauncherTest(); webInterface = new WebLauncherTest();
LOGGER.info("Clean previous table"); LOGGER.info("Clean previous table");
try {
Initialization.dropAll();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("plop: {}", ex.getLocalizedMessage());
throw ex;
}
LOGGER.info("Create DB");
try {
webInterface.migrateDB();
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("Detect an error: {}", ex.getMessage());
}
LOGGER.info("Start REST (BEGIN)"); LOGGER.info("Start REST (BEGIN)");
webInterface.process(); webInterface.process();
LOGGER.info("Start REST (DONE)"); LOGGER.info("Start REST (DONE)");
api = new RESTApi(ConfigBaseVariable.apiAdress); api = new RESTApi(ConfigBaseVariable.apiAdress);
api.setToken(Common.USER_TOKEN); api.setToken(Common.ADMIN_TOKEN);
} }
@AfterAll @AfterAll
@ -59,9 +42,7 @@ public class TestBase {
LOGGER.info("Kill the web server"); LOGGER.info("Kill the web server");
webInterface.stop(); webInterface.stop();
webInterface = null; webInterface = null;
LOGGER.info("Remove the test db"); ConfigureDb.clear();
DBEntry.closeAllForceMode();
ConfigBaseVariable.clearAllValue();
} }
} }

View File

@ -0,0 +1,61 @@
package test.kar.karusic;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
import java.io.IOException;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.kar.karusic.model.Track;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
@ExtendWith(StepwiseExtension.class)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class TestMongoDb {
final static private Logger LOGGER = LoggerFactory.getLogger(TestMongoDb.class);
@BeforeAll
public static void configureWebServer() throws Exception {}
@AfterAll
public static void removeDataBase() throws IOException {
}
@Order(1)
@Test
public void testCreateTable() throws Exception {
final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017");// System.getProperty("mongodb.uri"));
// Configure the CodecRegistry to include a codec to handle the translation to and from BSON for our POJOs.
final CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
// Add the default codec registry, which contains all the default codecs. They can handle all the major types in
// Java-like Boolean, Double, String, BigDecimal, etc.
final CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);
// Wrap all my settings together using MongoClientSettings.
final MongoClientSettings clientSettings = MongoClientSettings.builder().applyConnectionString(connectionString).codecRegistry(codecRegistry).build();
// Initiate the connection with MongoDB.
try (MongoClient mongoClient = MongoClients.create(clientSettings)) {
final MongoDatabase db = mongoClient.getDatabase("sample_training");
final MongoCollection<Track> grades = db.getCollection("Track", Track.class);
}
}
}

View File

@ -19,6 +19,7 @@ services:
kar_mongodb_service: kar_mongodb_service:
image: mongo:latest image: mongo:latest
restart: always
environment: environment:
MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: base_db_password MONGO_INITDB_ROOT_PASSWORD: base_db_password
@ -27,19 +28,6 @@ services:
volumes: volumes:
- ./dataMongo:/data/db - ./dataMongo:/data/db
mongo_express_service:
image: mongo-express
restart: always
ports:
- 8081:8081
links:
- kar_mongodb_service:db
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: base_db_password
ME_CONFIG_MONGODB_URL: mongodb://root:base_db_password@db:27017/
ME_CONFIG_BASICAUTH: false
kar_adminer_service: kar_adminer_service:
image: adminer:latest image: adminer:latest
restart: always restart: always
@ -52,3 +40,17 @@ services:
ports: ports:
- 4079:8080 - 4079:8080
mem_limit: 50m mem_limit: 50m
mongo_express_service:
image: mongo-express
restart: always
ports:
- 4077:8081
links:
- kar_mongodb_service:db
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: base_db_password
ME_CONFIG_MONGODB_URL: mongodb://root:base_db_password@db:27017/
ME_CONFIG_BASICAUTH: false

View File

@ -22,30 +22,6 @@ import {
export namespace AlbumResource { export namespace AlbumResource {
/**
* Add a Track on a specific album
*/
export function addTrack({
restConfig,
params,
}: {
restConfig: RESTConfig,
params: {
trackId: Long,
id: Long,
},
}): Promise<Album> {
return RESTRequestJson({
restModel: {
endPoint: "/album/{id}/track/{trackId}",
requestType: HTTPRequestModel.POST,
contentType: HTTPMimeType.MULTIPART,
accept: HTTPMimeType.JSON,
},
restConfig,
params,
}, isAlbum);
};
/** /**
* Get a specific Album with his ID * Get a specific Album with his ID
*/ */
@ -192,30 +168,6 @@ export namespace AlbumResource {
params, params,
}, isAlbum); }, isAlbum);
}; };
/**
* Remove a Track on a specific album
*/
export function removeTrack({
restConfig,
params,
}: {
restConfig: RESTConfig,
params: {
trackId: Long,
id: Long,
},
}): Promise<Album> {
return RESTRequestJson({
restModel: {
endPoint: "/album/{id}/track/{trackId}",
requestType: HTTPRequestModel.DELETE,
contentType: HTTPMimeType.TEXT_PLAIN,
accept: HTTPMimeType.JSON,
},
restConfig,
params,
}, isAlbum);
};
/** /**
* Add a cover on a specific album * Add a cover on a specific album
*/ */

View File

@ -15,7 +15,7 @@ import {
Artist, Artist,
ArtistWrite, ArtistWrite,
Long, Long,
UUID, ObjectId,
ZodArtist, ZodArtist,
isArtist, isArtist,
} from "../model"; } from "../model";
@ -135,7 +135,7 @@ export namespace ArtistResource {
}: { }: {
restConfig: RESTConfig, restConfig: RESTConfig,
params: { params: {
coverId: UUID, coverId: ObjectId,
id: Long, id: Long,
}, },
}): Promise<Artist> { }): Promise<Artist> {

View File

@ -10,7 +10,7 @@ import {
} from "../rest-tools"; } from "../rest-tools";
import { import {
UUID, ObjectId,
} from "../model"; } from "../model";
export namespace DataResource { export namespace DataResource {
@ -30,13 +30,13 @@ export namespace DataResource {
}, },
params: { params: {
name: string, name: string,
uuid: UUID, oid: ObjectId,
}, },
data: string, data: string,
}): Promise<object> { }): Promise<object> {
return RESTRequestJson({ return RESTRequestJson({
restModel: { restModel: {
endPoint: "/data/{uuid}/{name}", endPoint: "/data/{oid}/{name}",
requestType: HTTPRequestModel.GET, requestType: HTTPRequestModel.GET,
}, },
restConfig, restConfig,
@ -59,13 +59,13 @@ export namespace DataResource {
Authorization?: string, Authorization?: string,
}, },
params: { params: {
uuid: UUID, oid: ObjectId,
}, },
data: string, data: string,
}): Promise<object> { }): Promise<object> {
return RESTRequestJson({ return RESTRequestJson({
restModel: { restModel: {
endPoint: "/data/{uuid}", endPoint: "/data/{oid}",
requestType: HTTPRequestModel.GET, requestType: HTTPRequestModel.GET,
}, },
restConfig, restConfig,
@ -88,13 +88,13 @@ export namespace DataResource {
Authorization?: string, Authorization?: string,
}, },
params: { params: {
uuid: UUID, oid: ObjectId,
}, },
data: string, data: string,
}): Promise<object> { }): Promise<object> {
return RESTRequestJson({ return RESTRequestJson({
restModel: { restModel: {
endPoint: "/data/thumbnail/{uuid}", endPoint: "/data/thumbnail/{oid}",
requestType: HTTPRequestModel.GET, requestType: HTTPRequestModel.GET,
}, },
restConfig, restConfig,

View File

@ -15,7 +15,7 @@ import {
Gender, Gender,
GenderWrite, GenderWrite,
Long, Long,
UUID, ObjectId,
ZodGender, ZodGender,
isGender, isGender,
} from "../model"; } from "../model";
@ -135,7 +135,7 @@ export namespace GenderResource {
}: { }: {
restConfig: RESTConfig, restConfig: RESTConfig,
params: { params: {
coverId: UUID, coverId: ObjectId,
id: Long, id: Long,
}, },
}): Promise<Gender> { }): Promise<Gender> {

View File

@ -12,9 +12,9 @@ import {
import { z as zod } from "zod" import { z as zod } from "zod"
import { import {
Long, Long,
ObjectId,
Playlist, Playlist,
PlaylistWrite, PlaylistWrite,
UUID,
ZodPlaylist, ZodPlaylist,
isPlaylist, isPlaylist,
} from "../model"; } from "../model";
@ -155,7 +155,7 @@ export namespace PlaylistResource {
}: { }: {
restConfig: RESTConfig, restConfig: RESTConfig,
params: { params: {
coverId: UUID, coverId: ObjectId,
id: Long, id: Long,
}, },
}): Promise<Playlist> { }): Promise<Playlist> {

View File

@ -13,9 +13,9 @@ import {
import { z as zod } from "zod" import { z as zod } from "zod"
import { import {
Long, Long,
ObjectId,
Track, Track,
TrackWrite, TrackWrite,
UUID,
ZodTrack, ZodTrack,
isTrack, isTrack,
} from "../model"; } from "../model";
@ -156,7 +156,7 @@ export namespace TrackResource {
}: { }: {
restConfig: RESTConfig, restConfig: RESTConfig,
params: { params: {
coverId: UUID, coverId: ObjectId,
id: Long, id: Long,
}, },
}): Promise<Track> { }): Promise<Track> {

View File

@ -3,7 +3,7 @@
*/ */
import { z as zod } from "zod"; import { z as zod } from "zod";
import {ZodUUID} from "./uuid"; import {ZodObjectId} from "./object-id";
import {ZodLocalDate} from "./local-date"; import {ZodLocalDate} from "./local-date";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
@ -13,7 +13,7 @@ export const ZodAlbum = ZodGenericDataSoftDelete.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).optional(), covers: zod.array(ZodObjectId).optional(),
publication: ZodLocalDate.optional(), publication: ZodLocalDate.optional(),
}); });
@ -35,7 +35,7 @@ export const ZodAlbumWrite = ZodGenericDataSoftDeleteWrite.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).nullable().optional(), covers: zod.array(ZodObjectId).nullable().optional(),
publication: ZodLocalDate.nullable().optional(), publication: ZodLocalDate.nullable().optional(),
}); });

View File

@ -3,7 +3,7 @@
*/ */
import { z as zod } from "zod"; import { z as zod } from "zod";
import {ZodUUID} from "./uuid"; import {ZodObjectId} from "./object-id";
import {ZodLocalDate} from "./local-date"; import {ZodLocalDate} from "./local-date";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
@ -13,7 +13,7 @@ export const ZodArtist = ZodGenericDataSoftDelete.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).optional(), covers: zod.array(ZodObjectId).optional(),
firstName: zod.string().max(256).optional(), firstName: zod.string().max(256).optional(),
surname: zod.string().max(256).optional(), surname: zod.string().max(256).optional(),
birth: ZodLocalDate.optional(), birth: ZodLocalDate.optional(),
@ -38,7 +38,7 @@ export const ZodArtistWrite = ZodGenericDataSoftDeleteWrite.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).nullable().optional(), covers: zod.array(ZodObjectId).nullable().optional(),
firstName: zod.string().max(256).nullable().optional(), firstName: zod.string().max(256).nullable().optional(),
surname: zod.string().max(256).nullable().optional(), surname: zod.string().max(256).nullable().optional(),
birth: ZodLocalDate.nullable().optional(), birth: ZodLocalDate.nullable().optional(),

View File

@ -3,7 +3,7 @@
*/ */
import { z as zod } from "zod"; import { z as zod } from "zod";
import {ZodUUID} from "./uuid"; import {ZodObjectId} from "./object-id";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
export const ZodGender = ZodGenericDataSoftDelete.extend({ export const ZodGender = ZodGenericDataSoftDelete.extend({
@ -12,7 +12,7 @@ export const ZodGender = ZodGenericDataSoftDelete.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).optional(), covers: zod.array(ZodObjectId).optional(),
}); });
@ -33,7 +33,7 @@ export const ZodGenderWrite = ZodGenericDataSoftDeleteWrite.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).nullable().optional(), covers: zod.array(ZodObjectId).nullable().optional(),
}); });

View File

@ -12,6 +12,7 @@ export * from "./integer"
export * from "./iso-date" export * from "./iso-date"
export * from "./local-date" export * from "./local-date"
export * from "./long" export * from "./long"
export * from "./object-id"
export * from "./part-right" export * from "./part-right"
export * from "./playlist" export * from "./playlist"
export * from "./rest-error-response" export * from "./rest-error-response"

View File

@ -0,0 +1,8 @@
/**
* Interface of the server (auto-generated code)
*/
import { z as zod } from "zod";
export const ZodObjectId = zod.string().length(24, "Invalid ObjectId length").regex(/^[a-fA-F0-9]{24}$/, "Invalid ObjectId format");
export type ObjectId = zod.infer<typeof ZodObjectId>;

View File

@ -3,8 +3,7 @@
*/ */
import { z as zod } from "zod"; import { z as zod } from "zod";
import {ZodUUID} from "./uuid"; import {ZodObjectId} from "./object-id";
import {ZodLong} from "./long";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
export const ZodPlaylist = ZodGenericDataSoftDelete.extend({ export const ZodPlaylist = ZodGenericDataSoftDelete.extend({
@ -13,8 +12,8 @@ export const ZodPlaylist = ZodGenericDataSoftDelete.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).optional(), covers: zod.array(ZodObjectId).optional(),
tracks: zod.array(ZodLong), tracks: zod.array(ZodObjectId),
}); });
@ -35,8 +34,8 @@ export const ZodPlaylistWrite = ZodGenericDataSoftDeleteWrite.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).nullable().optional(), covers: zod.array(ZodObjectId).nullable().optional(),
tracks: zod.array(ZodLong).optional(), tracks: zod.array(ZodObjectId).optional(),
}); });

View File

@ -3,7 +3,7 @@
*/ */
import { z as zod } from "zod"; import { z as zod } from "zod";
import {ZodUUID} from "./uuid"; import {ZodObjectId} from "./object-id";
import {ZodLong} from "./long"; import {ZodLong} from "./long";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
@ -13,11 +13,11 @@ export const ZodTrack = ZodGenericDataSoftDelete.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).optional(), covers: zod.array(ZodObjectId).optional(),
genderId: ZodLong.optional(), genderId: ZodLong.optional(),
albumId: ZodLong.optional(), albumId: ZodLong.optional(),
track: ZodLong.optional(), track: ZodLong.optional(),
dataId: ZodUUID.optional(), dataId: ZodObjectId.optional(),
artists: zod.array(ZodLong), artists: zod.array(ZodLong),
}); });
@ -39,11 +39,11 @@ export const ZodTrackWrite = ZodGenericDataSoftDeleteWrite.extend({
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
covers: zod.array(ZodUUID).nullable().optional(), covers: zod.array(ZodObjectId).nullable().optional(),
genderId: ZodLong.nullable().optional(), genderId: ZodLong.nullable().optional(),
albumId: ZodLong.nullable().optional(), albumId: ZodLong.nullable().optional(),
track: ZodLong.nullable().optional(), track: ZodLong.nullable().optional(),
dataId: ZodUUID.nullable().optional(), dataId: ZodObjectId.nullable().optional(),
artists: zod.array(ZodLong).optional(), artists: zod.array(ZodLong).optional(),
}); });

View File

@ -8,11 +8,10 @@ import {ZodUUID} from "./uuid";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete"; import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
export const ZodUser = ZodGenericDataSoftDelete.extend({ export const ZodUser = ZodGenericDataSoftDelete.extend({
login: zod.string().max(128).optional(), login: zod.string().min(3).max(128),
lastConnection: ZodTimestamp.optional(), lastConnection: ZodTimestamp.optional(),
admin: zod.boolean(),
blocked: zod.boolean(), blocked: zod.boolean(),
removed: zod.boolean(), blockedReason: zod.string().max(512).optional(),
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */
@ -32,11 +31,10 @@ export function isUser(data: any): data is User {
} }
} }
export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({ export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
login: zod.string().max(128).nullable().optional(), login: zod.string().min(3).max(128).optional(),
lastConnection: ZodTimestamp.nullable().optional(), lastConnection: ZodTimestamp.nullable().optional(),
admin: zod.boolean(),
blocked: zod.boolean(), blocked: zod.boolean(),
removed: zod.boolean(), blockedReason: zod.string().max(512).nullable().optional(),
/** /**
* List of Id of the specific covers * List of Id of the specific covers
*/ */

View File

@ -7,11 +7,15 @@
import { RestErrorResponse, isRestErrorResponse } from "./model"; import { RestErrorResponse, isRestErrorResponse } from "./model";
export enum HTTPRequestModel { export enum HTTPRequestModel {
ARCHIVE = "ARCHIVE",
DELETE = "DELETE", DELETE = "DELETE",
HEAD = "HEAD",
GET = "GET", GET = "GET",
OPTION = "OPTION",
PATCH = "PATCH", PATCH = "PATCH",
POST = "POST", POST = "POST",
PUT = "PUT", PUT = "PUT",
RESTORE = "RESTORE",
} }
export enum HTTPMimeType { export enum HTTPMimeType {
ALL = "*/*", ALL = "*/*",
@ -248,9 +252,14 @@ export function RESTRequest({
if (restModel.accept !== undefined) { if (restModel.accept !== undefined) {
headers["Accept"] = restModel.accept; headers["Accept"] = restModel.accept;
} }
if (restModel.requestType !== HTTPRequestModel.GET) { if (restModel.requestType !== HTTPRequestModel.GET &&
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
restModel.requestType !== HTTPRequestModel.RESTORE
) {
// if Get we have not a content type, the body is empty // if Get we have not a content type, the body is empty
if (restModel.contentType !== HTTPMimeType.MULTIPART) { if (restModel.contentType !== HTTPMimeType.MULTIPART &&
restModel.contentType !== undefined
) {
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****" // special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
headers["Content-Type"] = restModel.contentType; headers["Content-Type"] = restModel.contentType;
} }

View File

@ -5,9 +5,10 @@ import { Image } from '@chakra-ui/react';
import { DataUrlAccess } from '@/utils/data-url-access'; import { DataUrlAccess } from '@/utils/data-url-access';
import { Icon } from './Icon'; import { Icon } from './Icon';
import { ObjectId } from '@/back-api';
export type CoversProps = BoxProps & { export type CoversProps = BoxProps & {
data?: string[]; data?: ObjectId[];
size?: StyleProps["width"]; size?: StyleProps["width"];
iconEmpty?: As; iconEmpty?: As;
slideshow?: boolean; slideshow?: boolean;

View File

@ -1,11 +1,9 @@
import { useState } from 'react'; import { useState } from 'react';
import React from 'react';
import { import {
Input, Input,
InputGroup, InputGroup,
InputLeftElement, InputLeftElement,
useOutsideClick,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { MdSearch } from 'react-icons/md'; import { MdSearch } from 'react-icons/md';

View File

@ -1,7 +1,7 @@
import { ReactElement } from 'react'; import { ReactElement } from 'react';
import { Center, Flex, Text, Wrap, WrapItem } from '@chakra-ui/react'; import { Center, Flex, Text, Wrap, WrapItem } from '@chakra-ui/react';
import { LuCrown, LuDisc3, LuEar, LuFileAudio, LuUser } from 'react-icons/lu'; import { LuCrown, LuDisc3, LuEar, LuFileAudio } from 'react-icons/lu';
import { MdGroup } from 'react-icons/md'; import { MdGroup } from 'react-icons/md';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';

View File

@ -1,7 +1,6 @@
import { Navigate, Route, Routes } from 'react-router-dom'; import { Navigate, Route, Routes } from 'react-router-dom';
import { Error404 } from '@/errors'; import { Error404 } from '@/errors';
import { ArtistAlbumDetailPage } from '@/scene/artist/ArtistAlbumDetailPage';
import { TrackSelectionPage } from '@/scene/track/TrackSelectionPage'; import { TrackSelectionPage } from '@/scene/track/TrackSelectionPage';
import { TracksStartLetterDetailPage } from '@/scene/track/TracksStartLetterDetailPage'; import { TracksStartLetterDetailPage } from '@/scene/track/TracksStartLetterDetailPage';