diff --git a/src/org/kar/archidata/api/DataResource.java b/src/org/kar/archidata/api/DataResource.java index f107e25..5696b4d 100644 --- a/src/org/kar/archidata/api/DataResource.java +++ b/src/org/kar/archidata/api/DataResource.java @@ -21,6 +21,7 @@ import java.util.UUID; import javax.imageio.ImageIO; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; import org.kar.archidata.annotation.security.PermitTokenInURI; @@ -86,24 +87,25 @@ public class DataResource { return filePath; } - public static String getFileDataOld(final long tmpFolderId) { - final String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator + public static String getFileDataOld(final UUID uuid) { + final String stringUUID = uuid.toString(); + final String filePath = ConfigBaseVariable.getMediaDataFolder() + File.separator + stringUUID + File.separator + "data"; try { - createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + tmpFolderId + File.separator); + createFolder(ConfigBaseVariable.getMediaDataFolder() + File.separator + stringUUID + File.separator); } catch (final IOException e) { e.printStackTrace(); } return filePath; } - public static String getFileData(final UUID uuid) { - final String stringUUID = uuid.toString(); - final String part1 = stringUUID.substring(0, 2); - final String part2 = stringUUID.substring(2, 4); - final String part3 = stringUUID.substring(4); + public static String getFileData(final ObjectId oid) { + final String stringOid = oid.toHexString(); + final String part1 = stringOid.substring(0, 2); + final String part2 = stringOid.substring(2, 4); + final String part3 = stringOid.substring(4); final String finalPath = part1 + File.separator + part2; - String filePath = ConfigBaseVariable.getMediaDataFolder() + "_uuid" + File.separator + finalPath + String filePath = ConfigBaseVariable.getMediaDataFolder() + "_oid" + File.separator + finalPath + File.separator; try { createFolder(filePath); @@ -114,8 +116,8 @@ public class DataResource { return filePath; } - public static String getFileMetaData(final UUID uuid) { - return getFileData(uuid) + ".json"; + public static String getFileMetaData(final ObjectId oid) { + return getFileData(oid) + ".json"; } public Data getWithSha512(final String sha512) { @@ -166,7 +168,7 @@ public class DataResource { e.printStackTrace(); return null; } - final String mediaPath = getFileData(injectedData.uuid); + final String mediaPath = getFileData(injectedData.oid); LOGGER.info("src = {}", tmpPath); LOGGER.info("dst = {}", mediaPath); Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE); @@ -174,9 +176,9 @@ public class DataResource { return injectedData; } - public static void modeFileOldModelToNewModel(final long id, final UUID uuid) throws IOException { - String mediaCurentPath = getFileDataOld(id); - String mediaDestPath = getFileData(uuid); + public static void modeFileOldModelToNewModel(final UUID uuid, final ObjectId oid) throws IOException { + String mediaCurentPath = getFileDataOld(uuid); + String mediaDestPath = getFileData(oid); LOGGER.info("src = {}", mediaCurentPath); LOGGER.info("dst = {}", mediaDestPath); if (Files.exists(Paths.get(mediaCurentPath))) { @@ -252,9 +254,9 @@ public class DataResource { return sb.toString(); } - public Data getSmall(final UUID id) { + public Data getSmall(final ObjectId oid) { try { - return DataAccess.get(Data.class, id); + return DataAccess.get(Data.class, oid); } catch (final Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -288,7 +290,7 @@ public class DataResource { } @GET - @Path("{uuid}") + @Path("{oid}") @PermitTokenInURI @RolesAllowed("USER") @Produces(MediaType.APPLICATION_OCTET_STREAM) @@ -297,17 +299,17 @@ public class DataResource { @Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, - @PathParam("uuid") final UUID uuid) throws FailException { + @PathParam("oid") final ObjectId oid) throws FailException { final GenericContext gc = (GenericContext) sc.getUserPrincipal(); // logger.info("==================================================="); - LOGGER.info("== DATA retrieveDataId ? id={} user={}", uuid, (gc == null ? "null" : gc.userByToken)); + LOGGER.info("== DATA retrieveDataId ? oid={} user={}", oid, (gc == null ? "null" : gc.userByToken)); // logger.info("==================================================="); - final Data value = getSmall(uuid); + final Data value = getSmall(oid); if (value == null) { - return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); + return Response.status(404).entity("media NOT FOUND: " + oid).type("text/plain").build(); } try { - return buildStream(getFileData(uuid), range, + return buildStream(getFileData(oid), range, value.mimeType == null ? "application/octet-stream" : value.mimeType); } catch (final Exception ex) { throw new FailException(Response.Status.INTERNAL_SERVER_ERROR, "Fail to build output stream", ex); @@ -315,7 +317,7 @@ public class DataResource { } @GET - @Path("thumbnail/{uuid}") + @Path("thumbnail/{oid}") @RolesAllowed("USER") @PermitTokenInURI @Produces(MediaType.APPLICATION_OCTET_STREAM) @@ -325,19 +327,19 @@ public class DataResource { @Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, - @PathParam("uuid") final UUID uuid) throws FailException { + @PathParam("oid") final ObjectId oid) throws FailException { final GenericContext gc = (GenericContext) sc.getUserPrincipal(); LOGGER.info("==================================================="); LOGGER.info("== DATA retrieveDataThumbnailId ? {}", (gc == null ? "null" : gc.userByToken)); LOGGER.info("==================================================="); - final Data value = getSmall(uuid); + final Data value = getSmall(oid); if (value == null) { - return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); + return Response.status(404).entity("media NOT FOUND: " + oid).type("text/plain").build(); } - final String filePathName = getFileData(uuid); + final String filePathName = getFileData(oid); final File inputFile = new File(filePathName); if (!inputFile.exists()) { - return Response.status(404).entity("{\"error\":\"media Does not exist: " + uuid + "\"}") + return Response.status(404).entity("{\"error\":\"media Does not exist: " + oid + "\"}") .type("application/json").build(); } if (value.mimeType.contentEquals("image/jpeg") || value.mimeType.contentEquals("image/png") @@ -402,7 +404,7 @@ public class DataResource { } @GET - @Path("{uuid}/{name}") + @Path("{oid}/{name}") @PermitTokenInURI @RolesAllowed("USER") @Produces(MediaType.APPLICATION_OCTET_STREAM) @@ -411,17 +413,17 @@ public class DataResource { @Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, - @PathParam("uuid") final UUID uuid, + @PathParam("oid") final ObjectId oid, @PathParam("name") final String name) throws Exception { final GenericContext gc = (GenericContext) sc.getUserPrincipal(); // logger.info("==================================================="); - LOGGER.info("== DATA retrieveDataFull ? id={} user={}", uuid, (gc == null ? "null" : gc.userByToken)); + LOGGER.info("== DATA retrieveDataFull ? id={} user={}", oid, (gc == null ? "null" : gc.userByToken)); // logger.info("==================================================="); - final Data value = getSmall(uuid); + final Data value = getSmall(oid); if (value == null) { - return Response.status(404).entity("media NOT FOUND: " + uuid).type("text/plain").build(); + return Response.status(404).entity("media NOT FOUND: " + oid).type("text/plain").build(); } - return buildStream(getFileData(uuid), range, + return buildStream(getFileData(oid), range, value.mimeType == null ? "application/octet-stream" : value.mimeType); } diff --git a/src/org/kar/archidata/dataAccess/DBAccessSQL.java b/src/org/kar/archidata/dataAccess/DBAccessSQL.java index 14f95b1..7f276d1 100644 --- a/src/org/kar/archidata/dataAccess/DBAccessSQL.java +++ b/src/org/kar/archidata/dataAccess/DBAccessSQL.java @@ -207,39 +207,6 @@ public class DBAccessSQL extends DBAccess { return out; } - /** Extract a list of UUID with "-" separated element from a SQL input data. - * @param rs Result Set of the BDD - * @param iii Id in the result set - * @return The list of Long value - * @throws SQLException if an error is generated in the SQL request. */ - public List getListOfUUIDs(final ResultSet rs, final int iii, final String separator) throws SQLException { - final String trackString = rs.getString(iii); - if (rs.wasNull()) { - return null; - } - final List out = new ArrayList<>(); - final String[] elements = trackString.split(separator); - for (final String elem : elements) { - final UUID tmp = UUID.fromString(elem); - out.add(tmp); - } - return out; - } - - public List getListOfOIDs(final ResultSet rs, final int iii, final String separator) throws SQLException { - final String trackString = rs.getString(iii); - if (rs.wasNull()) { - return null; - } - final List out = new ArrayList<>(); - final String[] elements = trackString.split(separator); - for (final String elem : elements) { - final ObjectId tmp = new ObjectId(elem); - out.add(tmp); - } - return out; - } - public byte[][] splitIntoGroupsOf16Bytes(final byte[] input) { final int inputLength = input.length; final int numOfGroups = (inputLength + 15) / 16; // Calculate the number of groups needed @@ -309,8 +276,8 @@ public class DBAccessSQL extends DBAccess { if (tmp == null) { ps.setNull(iii.value, Types.BINARY); } else { - final String dataString = ((ObjectId) tmp).toHexString(); - ps.setString(iii.value, dataString); + final byte[] dataByte = ((ObjectId) tmp).toByteArray(); + ps.setBytes(iii.value, dataByte); } } else if (type == UUID.class) { final Object tmp = field.get(data); @@ -432,7 +399,7 @@ public class DBAccessSQL extends DBAccess { final ResultSet rs, final CountInOut countNotNull) throws Exception { if (type == ObjectId.class) { - final String tmp = rs.getString(count.value); + final byte[] tmp = rs.getBytes(count.value); if (rs.wasNull()) { field.set(data, null); } else { @@ -623,7 +590,7 @@ public class DBAccessSQL extends DBAccess { final Class type = field.getType(); if (type == ObjectId.class) { return (final ResultSet rs, final Object obj) -> { - final String tmp = rs.getString(count); + final byte[] tmp = rs.getBytes(count); if (rs.wasNull()) { field.set(obj, null); } else { @@ -1055,12 +1022,12 @@ public class DBAccessSQL extends DBAccess { if (primaryKeyField.getType() == UUID.class) { // uniqueSQLUUID = generatedKeys.getObject(1, UUID.class); /* final Object obj = generatedKeys.getObject(1); final BigInteger bigint = (BigInteger) generatedKeys.getObject(1); uniqueSQLUUID = UuidUtils.asUuid(bigint); final UUID - * generatedUUID = (UUID) generatedKeys.getObject(1); System.out.println("UUID généré: " + generatedUUID); */ + * generatedUUID = (UUID) generatedKeys.getObject(1); LOGGER.trace("UUID généré: " + generatedUUID); */ //final Object obj = generatedKeys.getObject(1); final byte[] tmpid = generatedKeys.getBytes(1); uniqueSQLUUID = UuidUtils.asUuid(tmpid); } else if (primaryKeyField.getType() == ObjectId.class) { - final String tmpid = generatedKeys.getString(1); + final byte[] tmpid = generatedKeys.getBytes(1); uniqueSQLOID = new ObjectId(tmpid); } else { uniqueSQLID = generatedKeys.getLong(1); @@ -1245,12 +1212,13 @@ public class DBAccessSQL extends DBAccess { return; } if (value instanceof final UUID tmp) { + LOGGER.debug("Inject uuid => {}", tmp); final byte[] dataByte = UuidUtils.asBytes(tmp); ps.setBytes(iii.value, dataByte); } else if (value instanceof final ObjectId tmp) { - final String dataString = tmp.toHexString(); - LOGGER.debug("Inject oid => {}", dataString); - ps.setString(iii.value, dataString); + final byte[] dataByte = tmp.toByteArray(); + LOGGER.debug("Inject oid => {}", tmp.toHexString()); + ps.setBytes(iii.value, dataByte); } else if (value instanceof final Long tmp) { LOGGER.debug("Inject Long => {}", tmp); ps.setLong(iii.value, tmp); diff --git a/src/org/kar/archidata/dataAccess/DataFactory.java b/src/org/kar/archidata/dataAccess/DataFactory.java index ab645f1..34f269b 100644 --- a/src/org/kar/archidata/dataAccess/DataFactory.java +++ b/src/org/kar/archidata/dataAccess/DataFactory.java @@ -37,8 +37,7 @@ public class DataFactory { return "binary(16)"; } if (type == ObjectId.class) { - return "varchar(24)"; - // return "binary(12)"; + return "binary(12)"; } if (type == Long.class || type == long.class) { return "bigint"; @@ -95,8 +94,7 @@ public class DataFactory { return "BINARY(16)"; } if (type == ObjectId.class) { - return "text"; - //return "BINARY(12)"; + return "BINARY(12)"; } if (type == Long.class || type == long.class) { return "INTEGER"; diff --git a/src/org/kar/archidata/externalRestApi/TsGenerateApi.java b/src/org/kar/archidata/externalRestApi/TsGenerateApi.java index 542e6a0..6d290c7 100644 --- a/src/org/kar/archidata/externalRestApi/TsGenerateApi.java +++ b/src/org/kar/archidata/externalRestApi/TsGenerateApi.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.ContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.kar.archidata.catcher.RestErrorResponse; @@ -157,6 +158,12 @@ public class TsGenerateApi { tsModels.add(new TsClassElement(models, "ZodUUID", "UUID", "isUUID", "zod.string().uuid()", DefinedPosition.BASIC)); } + models = api.getCompatibleModels(List.of(ObjectId.class)); + if (models != null) { + tsModels.add(new TsClassElement(models, "ZodObjectId", "ObjectId", "isObjectId", + "zod.string().length(24, \"Invalid ObjectId length\").regex(/^[a-fA-F0-9]{24}$/, \"Invalid ObjectId format\")", + DefinedPosition.BASIC)); + } models = api.getCompatibleModels(List.of(Long.class, long.class)); if (models != null) { tsModels.add( diff --git a/src/org/kar/archidata/model/Data.java b/src/org/kar/archidata/model/Data.java index 61813ba..31fc453 100644 --- a/src/org/kar/archidata/model/Data.java +++ b/src/org/kar/archidata/model/Data.java @@ -11,7 +11,7 @@ import jakarta.persistence.Table; @Table(name = "data") @DataIfNotExists @JsonInclude(JsonInclude.Include.NON_NULL) -public class Data extends UUIDGenericDataSoftDelete { +public class Data extends OIDGenericDataSoftDelete { @Column(length = 128, nullable = false) @Schema(description = "Sha512 of the data") public String sha512; diff --git a/src/org/kar/archidata/model/OIDGenericData.java b/src/org/kar/archidata/model/OIDGenericData.java index b1d76c3..f5555a7 100644 --- a/src/org/kar/archidata/model/OIDGenericData.java +++ b/src/org/kar/archidata/model/OIDGenericData.java @@ -9,9 +9,9 @@ import jakarta.validation.constraints.NotNull; public class OIDGenericData extends GenericTiming { @Id - //@jakarta.persistence.Id - @Column(nullable = false, unique = true) + @jakarta.persistence.Id + @Column(nullable = false, unique = true, name = "_id") @Schema(description = "Unique ObjectID of the object", required = false, readOnly = true, example = "65161616841351") @NotNull - public ObjectId _id = null; + public ObjectId oid = null; } diff --git a/src/org/kar/archidata/tools/DataTools.java b/src/org/kar/archidata/tools/DataTools.java index f45d688..60c90c0 100644 --- a/src/org/kar/archidata/tools/DataTools.java +++ b/src/org/kar/archidata/tools/DataTools.java @@ -13,9 +13,9 @@ import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.Arrays; import java.util.List; -import java.util.UUID; import org.apache.tika.Tika; +import org.bson.types.ObjectId; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.kar.archidata.api.DataResource; import org.kar.archidata.dataAccess.DBAccess; @@ -121,7 +121,7 @@ public class DataTools { return null; } - final String mediaPath = DataResource.getFileData(out.uuid); + final String mediaPath = DataResource.getFileData(out.oid); LOGGER.info("src = {}", tmpPath); LOGGER.info("dst = {}", mediaPath); Files.move(Paths.get(tmpPath), Paths.get(mediaPath), StandardCopyOption.ATOMIC_MOVE); @@ -151,9 +151,9 @@ public class DataTools { return createNewData(ioDb, tmpUID, originalFileName, sha512, mimeType); } - public static void undelete(final DBAccess ioDb, final UUID id) { + public static void undelete(final DBAccess ioDb, final ObjectId oid) { try { - ioDb.unsetDelete(Data.class, id); + ioDb.unsetDelete(Data.class, oid); } catch (final Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -338,14 +338,14 @@ public class DataTools { } } else if (data.deleted) { LOGGER.error("Data already exist but deleted"); - undelete(ioDb, data.uuid); + undelete(ioDb, data.oid); data.deleted = false; } else { LOGGER.error("Data already exist ... all good"); } // Fist step: retrieve all the Id of each parents:... LOGGER.info("Find typeNode"); - AddOnDataJson.addLink(ioDb, clazz, null, id, null, data.uuid); + AddOnDataJson.addLink(ioDb, clazz, null, id, null, data.oid); } public static void uploadCover( @@ -384,13 +384,13 @@ public class DataTools { } } else if (data.deleted) { LOGGER.error("Data already exist but deleted"); - undelete(ioDb, data.uuid); + undelete(ioDb, data.oid); data.deleted = false; } else { LOGGER.error("Data already exist ... all good"); } // Fist step: retrieve all the Id of each parents:... LOGGER.info("Find typeNode"); - AddOnDataJson.addLink(ioDb, clazz, null, id, null, data.uuid); + AddOnDataJson.addLink(ioDb, clazz, null, id, null, data.oid); } } diff --git a/test/src/test/kar/archidata/dataAccess/TestListJson.java b/test/src/test/kar/archidata/dataAccess/TestListJson.java index 9084094..0350455 100644 --- a/test/src/test/kar/archidata/dataAccess/TestListJson.java +++ b/test/src/test/kar/archidata/dataAccess/TestListJson.java @@ -166,7 +166,7 @@ public class TestListJson { final SerializeListAsJsonObjectId insertedData = ConfigureDb.da.insert(test); Assertions.assertNotNull(insertedData); - Assertions.assertNotNull(insertedData._id); + Assertions.assertNotNull(insertedData.oid); Assertions.assertNotNull(insertedData.data); Assertions.assertEquals(5, insertedData.data.size()); Assertions.assertEquals(test.data.get(0), insertedData.data.get(0)); @@ -177,10 +177,10 @@ public class TestListJson { // Try to retrieve all the data: final SerializeListAsJsonObjectId retrieve = ConfigureDb.da.get(SerializeListAsJsonObjectId.class, - insertedData._id); + insertedData.oid); Assertions.assertNotNull(retrieve); - Assertions.assertNotNull(retrieve._id); + Assertions.assertNotNull(retrieve.oid); Assertions.assertNotNull(retrieve.data); Assertions.assertEquals(5, retrieve.data.size()); Assertions.assertEquals(test.data.get(0), retrieve.data.get(0)); @@ -199,38 +199,38 @@ public class TestListJson { final SerializeListAsJsonObjectId insertedData = ConfigureDb.da.insert(test); Assertions.assertNotNull(insertedData); - Assertions.assertNotNull(insertedData._id); + Assertions.assertNotNull(insertedData.oid); Assertions.assertNotNull(insertedData.data); Assertions.assertEquals(0, insertedData.data.size()); final ObjectId firstDataInserted1 = new ObjectId(); final ObjectId firstDataInserted2 = new ObjectId(); final ObjectId firstDataInserted3 = new ObjectId(); - AddOnDataJson.addLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData._id, "data", + AddOnDataJson.addLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData.oid, "data", firstDataInserted1); - AddOnDataJson.addLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData._id, "data", + AddOnDataJson.addLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData.oid, "data", firstDataInserted2); - AddOnDataJson.addLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData._id, "data", + AddOnDataJson.addLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData.oid, "data", firstDataInserted3); // Try to retrieve all the data: - SerializeListAsJsonObjectId retrieve = ConfigureDb.da.get(SerializeListAsJsonObjectId.class, insertedData._id); + SerializeListAsJsonObjectId retrieve = ConfigureDb.da.get(SerializeListAsJsonObjectId.class, insertedData.oid); Assertions.assertNotNull(retrieve); - Assertions.assertNotNull(retrieve._id); + Assertions.assertNotNull(retrieve.oid); Assertions.assertNotNull(retrieve.data); Assertions.assertEquals(3, retrieve.data.size()); Assertions.assertEquals(firstDataInserted1, retrieve.data.get(0)); Assertions.assertEquals(firstDataInserted2, retrieve.data.get(1)); Assertions.assertEquals(firstDataInserted3, retrieve.data.get(2)); - AddOnDataJson.removeLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData._id, "data", + AddOnDataJson.removeLink(ConfigureDb.da, SerializeListAsJsonObjectId.class, "_id", insertedData.oid, "data", firstDataInserted2); // Try to retrieve all the data: - retrieve = ConfigureDb.da.get(SerializeListAsJsonObjectId.class, insertedData._id); + retrieve = ConfigureDb.da.get(SerializeListAsJsonObjectId.class, insertedData.oid); Assertions.assertNotNull(retrieve); - Assertions.assertNotNull(retrieve._id); + Assertions.assertNotNull(retrieve.oid); Assertions.assertNotNull(retrieve.data); Assertions.assertEquals(2, retrieve.data.size()); Assertions.assertEquals(firstDataInserted1, retrieve.data.get(0));