diff --git a/src/org/kar/archidata/dataAccess/DBAccessMorphia.java b/src/org/kar/archidata/dataAccess/DBAccessMorphia.java index dc7f4f5..3bc8191 100644 --- a/src/org/kar/archidata/dataAccess/DBAccessMorphia.java +++ b/src/org/kar/archidata/dataAccess/DBAccessMorphia.java @@ -18,6 +18,7 @@ import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; import org.kar.archidata.annotation.AnnotationTools; +import org.kar.archidata.annotation.AnnotationTools.FieldName; import org.kar.archidata.annotation.CreationTimestamp; import org.kar.archidata.annotation.UpdateTimestamp; import org.kar.archidata.dataAccess.addOnMongo.AddOnManyToOne; @@ -27,6 +28,7 @@ import org.kar.archidata.dataAccess.options.CheckFunction; import org.kar.archidata.dataAccess.options.Condition; import org.kar.archidata.dataAccess.options.FilterValue; import org.kar.archidata.dataAccess.options.Limit; +import org.kar.archidata.dataAccess.options.OptionSpecifyType; import org.kar.archidata.dataAccess.options.OrderBy; import org.kar.archidata.dataAccess.options.QueryOption; import org.kar.archidata.db.DbIoMorphia; @@ -128,7 +130,7 @@ public class DBAccessMorphia extends DBAccess { return groups; } - protected void setValuedb( + protected void setValueToDb( final Class type, final T data, final Field field, @@ -136,7 +138,9 @@ public class DBAccessMorphia extends DBAccess { final Document docSet, final Document docUnSet) throws Exception { if (field.get(data) == null) { - docUnSet.append(fieldName, ""); + if (docUnSet != null) { + docUnSet.append(fieldName, ""); + } return; } if (type == long.class) { @@ -151,7 +155,7 @@ public class DBAccessMorphia extends DBAccess { docSet.append(fieldName, field.getFloat(data)); return; } - if (type == Double.class) { + if (type == double.class) { docSet.append(fieldName, field.getDouble(data)); return; } @@ -196,56 +200,40 @@ public class DBAccessMorphia extends DBAccess { docSet.append(fieldName, tmp); return; } + if (type == ObjectId.class) { + docSet.append(fieldName, tmp); + return; + } if (type == UUID.class) { docSet.append(fieldName, tmp); return; } if (type == Date.class) { - // TODO ... /* - final Object tmp = field.get(data); - if (tmp == null) { - ps.setNull(iii.value, Types.INTEGER); - } else { final Timestamp sqlDate = java.sql.Timestamp.from(((Date) tmp).toInstant()); ps.setTimestamp(iii.value, sqlDate); - }*/ + */ } if (type == Instant.class) { /* - final Object tmp = field.get(data); - if (tmp == null) { - ps.setNull(iii.value, Types.INTEGER); - } else { final String sqlDate = ((Instant) tmp).toString(); ps.setString(iii.value, sqlDate); - } */ } if (type == LocalDate.class) { /* - final Object tmp = field.get(data); - if (tmp == null) { - ps.setNull(iii.value, Types.INTEGER); - } else { final java.sql.Date sqlDate = java.sql.Date.valueOf((LocalDate) tmp); ps.setDate(iii.value, sqlDate); - } */ } if (type == LocalTime.class) { /* - final Object tmp = field.get(data); - if (tmp == null) { - ps.setNull(iii.value, Types.INTEGER); - } else { final java.sql.Time sqlDate = java.sql.Time.valueOf((LocalTime) tmp); ps.setTime(iii.value, sqlDate); - } */ } - throw new DataAccessException("Unknown Field Type"); - + docSet.append(fieldName, tmp); + //throw new DataAccessException("Unknown Field Type"); } public void setValueFromDoc( @@ -265,6 +253,11 @@ public class DBAccessMorphia extends DBAccess { field.set(data, value); return; } + if (type == ObjectId.class) { + final ObjectId value = doc.get(fieldName, ObjectId.class); + field.set(data, value); + return; + } if (type == Long.class || type == long.class) { final Long value = doc.getLong(fieldName); field.set(data, value); @@ -349,8 +342,8 @@ public class DBAccessMorphia extends DBAccess { final Object value = doc.get(fieldName, field.getType()); field.set(data, value); } else { - final Object value = createObjectFromDocument(doc.get(fieldName, Document.class), field.getType(), null, - lazyCall); + final Object value = createObjectFromDocument(doc.get(fieldName, Document.class), field.getType(), + new QueryOptions(), lazyCall); field.set(data, value); } @@ -459,32 +452,45 @@ public class DBAccessMorphia extends DBAccess { Object uniqueId = null; // real add in the BDD: ObjectId insertedId = null; + final List specificTypes = options.get(OptionSpecifyType.class); try { final MongoCollection collection = this.db.getDatastore().getDatabase() .getCollection(collectionName); - final Document doc = new Document(); + final Document docSet = new Document(); + final Document docUnSet = new Document(); for (final Field field : clazz.getFields()) { // static field is only for internal global declaration ==> remove it .. if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { continue; } - final String tableFieldName = AnnotationTools.getFieldName(field, options).inTable(); + final FieldName tableFieldName = AnnotationTools.getFieldName(field, options); Object currentInsertValue = field.get(data); if (AnnotationTools.isPrimaryKey(field)) { primaryKeyField = field; if (primaryKeyField.getType() == UUID.class) { final UUID uuid = UuidUtils.nextUUID(); uniqueId = uuid; - doc.append(tableFieldName, uuid); + docSet.append(tableFieldName.inTable(), uuid); continue; } else if (primaryKeyField.getType() == Long.class || primaryKeyField.getType() == long.class) { // By default the MongoDB does not manage the - final long id = getNextSequenceLongValue(collectionName, tableFieldName); + final long id = getNextSequenceLongValue(collectionName, tableFieldName.inTable()); uniqueId = id; - doc.append(tableFieldName, id); + docSet.append(tableFieldName.inTable(), id); continue; } - LOGGER.error("TODO: Manage the ID primary key for type: "); + LOGGER.error("TODO: Manage the ID primary key for type: {}=>{}", clazz.getCanonicalName(), + primaryKeyField.getType()); + continue; + } + final boolean createTime = field.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; + if (createTime) { + docSet.append(tableFieldName.inTable(), Date.from(Instant.now())); + continue; + } + final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; + if (updateTime) { + docSet.append(tableFieldName.inTable(), Date.from(Instant.now())); continue; } final DataAccessAddOn addOn = findAddOnforField(field); @@ -495,19 +501,8 @@ public class DBAccessMorphia extends DBAccess { } continue; } - final boolean createTime = field.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; - if (createTime) { - doc.append(tableFieldName, Date.from(Instant.now())); - continue; - } - final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; - if (updateTime) { - doc.append(tableFieldName, Date.from(Instant.now())); - continue; - } if (currentInsertValue == null && !field.getClass().isPrimitive()) { final DefaultValue[] defaultValue = field.getDeclaredAnnotationsByType(DefaultValue.class); - LOGGER.error("TODO: convert default value in the correct value for the DB..."); if (defaultValue.length == 0) { continue; } else { @@ -518,9 +513,24 @@ public class DBAccessMorphia extends DBAccess { currentInsertValue = convertDefaultField(value, field); } } - doc.append(tableFieldName, currentInsertValue); + // conversion table ... + //doc.append(tableFieldName, currentInsertValue); + if (addOn != null) { + addOn.insertData(this, field, data, options, docSet, docUnSet); + } else { + final Class type = field.getType(); + if (!type.isPrimitive()) { + if (field.get(data) == null) { + if (currentInsertValue != null) { + docSet.append(tableFieldName.inTable(), currentInsertValue); + } + continue; + } + } + setValueToDb(type, data, field, tableFieldName.inTable(), docSet, null); + } } - final InsertOneResult result = collection.insertOne(doc); + final InsertOneResult result = collection.insertOne(docSet); // Get the Object of inserted object: insertedId = result.getInsertedId().asObjectId().getValue(); LOGGER.info("Document inserted with ID: " + insertedId); @@ -587,14 +597,14 @@ public class DBAccessMorphia extends DBAccess { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { continue; } - final String fieldName = AnnotationTools.getFieldName(field, options).inTable(); + final FieldName fieldName = AnnotationTools.getFieldName(field, options); // update field is not conditioned by filter: final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; if (updateTime) { - docSet.append(fieldName, Date.from(Instant.now())); + docSet.append(fieldName.inTable(), Date.from(Instant.now())); continue; } - if (!filterKey.getValues().contains(fieldName)) { + if (!filterKey.getValues().contains(fieldName.inStruct())) { continue; } else if (AnnotationTools.isGenericField(field)) { continue; @@ -624,12 +634,10 @@ public class DBAccessMorphia extends DBAccess { continue; } } - setValuedb(type, data, field, fieldName, docSet, docUnSet); + setValueToDb(type, data, field, fieldName.inTable(), docSet, docUnSet); } - } // Do the query ... - final MongoCollection collection = this.db.getDatastore().getDatabase() .getCollection(collectionName); final Document actions = new Document(); @@ -652,7 +660,6 @@ public class DBAccessMorphia extends DBAccess { } public List generateSelectField(final Class clazz, final QueryOptions options) throws Exception { - // TODO: list of user select fields. final boolean readAllfields = QueryOptions.readAllColomn(options); final List fieldsName = new ArrayList<>(); @@ -776,6 +783,8 @@ public class DBAccessMorphia extends DBAccess { final Class clazz, final QueryOptions options, final List lazyCall) throws Exception { + final List specificTypes = options.get(OptionSpecifyType.class); + LOGGER.info("createObjectFromDocument: {}", clazz.getCanonicalName()); final boolean readAllfields = QueryOptions.readAllColomn(options); // TODO: manage class that is defined inside a class ==> Not manage for now... Object data = null; @@ -790,23 +799,37 @@ public class DBAccessMorphia extends DBAccess { "Can not find the default constructor for the class: " + clazz.getCanonicalName()); } for (final Field elem : clazz.getFields()) { + LOGGER.info(" Inspect field: name='{}' type='{}'", elem.getName(), elem.getType().getCanonicalName()); // static field is only for internal global declaration ==> remove it .. if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) { + LOGGER.info(" ==> static"); continue; } final DataAccessAddOn addOn = findAddOnforField(elem); if (addOn != null && !addOn.canRetrieve(elem)) { + LOGGER.info(" ==> Can not retreive this field"); continue; } final boolean notRead = AnnotationTools.isDefaultNotRead(elem); if (!readAllfields && notRead) { + LOGGER.info(" ==> Not read this element"); continue; } if (addOn != null) { - LOGGER.error("TODO: Add on not managed .6. "); addOn.fillFromDoc(this, doc, elem, data, options, lazyCall); } else { - setValueFromDoc(elem.getType(), data, elem, doc, lazyCall, options); + Class type = elem.getType(); + if (type == Object.class) { + for (final OptionSpecifyType specify : specificTypes) { + if (specify.name.equals(elem.getName())) { + type = specify.clazz; + LOGGER.info("Detect overwrite of typing var={} ... '{}' => '{}'", elem.getName(), + elem.getType().getCanonicalName(), specify.clazz.getCanonicalName()); + break; + } + } + } + setValueFromDoc(type, data, elem, doc, lazyCall, options); } } return data; diff --git a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnDataJson.java b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnDataJson.java index c462c80..370aea3 100644 --- a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnDataJson.java +++ b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnDataJson.java @@ -6,7 +6,6 @@ import java.util.List; import org.bson.Document; import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.DataJson; -import org.kar.archidata.dataAccess.CountInOut; import org.kar.archidata.dataAccess.DBAccessMorphia; import org.kar.archidata.dataAccess.DataFactory; import org.kar.archidata.dataAccess.LazyGetter; @@ -17,8 +16,6 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonValue; -import jakarta.validation.constraints.NotNull; - public class AddOnDataJson implements DataAccessAddOn { static final Logger LOGGER = LoggerFactory.getLogger(AddOnDataJson.class); @@ -74,24 +71,6 @@ public class AddOnDataJson implements DataAccessAddOn { return true; } - @Override - public void generateQuery( - @NotNull final String tableName, - @NotNull final String primaryKey, - @NotNull final Field field, - @NotNull final StringBuilder querySelect, - @NotNull final StringBuilder query, - @NotNull final String name, - @NotNull final CountInOut count, - final QueryOptions options) throws Exception { - querySelect.append(" "); - querySelect.append(tableName); - querySelect.append("."); - querySelect.append(name); - count.inc(); - return; - } - @Override public void fillFromDoc( final DBAccessMorphia ioDb, diff --git a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToMany.java b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToMany.java index 64b1874..039ec02 100644 --- a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToMany.java +++ b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToMany.java @@ -173,34 +173,6 @@ public class AddOnManyToMany implements DataAccessAddOn { count.inc(); } - @Override - public void generateQuery( - @NotNull final String tableName, - @NotNull final String primaryKey, - @NotNull final Field field, - @NotNull final StringBuilder querySelect, - @NotNull final StringBuilder query, - @NotNull final String name, - @NotNull final CountInOut count, - final QueryOptions options) throws Exception { - if (field.getType() != List.class) { - return; - } - final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) - .getActualTypeArguments()[0]; - if (objectClass == Long.class || objectClass == UUID.class) { - generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options); - } - final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class); - if (decorators == null) { - return; - } - if (objectClass == decorators.targetEntity()) { - generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options); - - } - } - @Override public void fillFromDoc( final DBAccessMorphia ioDb, diff --git a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToOne.java b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToOne.java index 6810ffc..b295436 100644 --- a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToOne.java +++ b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnManyToOne.java @@ -5,9 +5,9 @@ import java.util.List; import java.util.UUID; import org.bson.Document; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools.FieldName; -import org.kar.archidata.dataAccess.CountInOut; import org.kar.archidata.dataAccess.DBAccessMorphia; import org.kar.archidata.dataAccess.DataFactory; import org.kar.archidata.dataAccess.LazyGetter; @@ -16,7 +16,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jakarta.persistence.ManyToOne; -import jakarta.validation.constraints.NotNull; public class AddOnManyToOne implements DataAccessAddOn { static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class); @@ -52,7 +51,7 @@ public class AddOnManyToOne implements DataAccessAddOn { final Document docUnSet) throws Exception { final FieldName fieldName = AnnotationTools.getFieldName(field, options); final Object data = field.get(rootObject); - if (field.get(data) == null) { + if (data == null) { docUnSet.append(fieldName.inTable(), ""); return; } else if (field.getType() == Long.class) { @@ -70,6 +69,9 @@ public class AddOnManyToOne implements DataAccessAddOn { } else if (field.getType() == UUID.class) { final UUID dataTyped = (UUID) data; docSet.append(fieldName.inTable(), dataTyped); + } else if (field.getType() == ObjectId.class) { + final ObjectId dataTyped = (ObjectId) data; + docSet.append(fieldName.inTable(), dataTyped); } else { final Field idField = AnnotationTools.getFieldOfId(field.getType()); final Object uid = idField.get(data); @@ -84,7 +86,8 @@ public class AddOnManyToOne implements DataAccessAddOn { @Override public boolean canInsert(final Field field) { if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class - || field.getType() == String.class || field.getType() == UUID.class) { + || field.getType() == String.class || field.getType() == UUID.class + || field.getType() == ObjectId.class) { return true; } final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); @@ -103,7 +106,7 @@ public class AddOnManyToOne implements DataAccessAddOn { public boolean canRetrieve(final Field field) { final Class classType = field.getType(); if (classType == Long.class || classType == Integer.class || classType == Short.class - || classType == String.class || classType == UUID.class) { + || classType == String.class || classType == UUID.class || classType == ObjectId.class) { return true; } final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); @@ -113,36 +116,6 @@ public class AddOnManyToOne implements DataAccessAddOn { return false; } - @Override - public void generateQuery( - @NotNull final String tableName, - @NotNull final String primaryKey, - @NotNull final Field field, - @NotNull final StringBuilder querySelect, - @NotNull final StringBuilder query, - @NotNull final String name, - @NotNull final CountInOut count, - final QueryOptions options) throws Exception { - if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class - || field.getType() == String.class || field.getType() == UUID.class) { - querySelect.append(" "); - querySelect.append(tableName); - querySelect.append("."); - querySelect.append(name); - count.inc(); - return; - } - final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); - if (field.getType() == decorators.targetEntity()) { - // no eager possible for no sql - querySelect.append(" "); - querySelect.append(tableName); - querySelect.append("."); - querySelect.append(name); - count.inc(); - } - } - @Override public void fillFromDoc( final DBAccessMorphia ioDb, @@ -159,7 +132,8 @@ public class AddOnManyToOne implements DataAccessAddOn { } // local field to manage no remote object to retrieve. if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class - || field.getType() == String.class || field.getType() == UUID.class) { + || field.getType() == String.class || field.getType() == UUID.class + || field.getType() == ObjectId.class) { ioDb.setValueFromDoc(field.getType(), data, field, doc, lazyCall, options); return; } @@ -174,9 +148,8 @@ public class AddOnManyToOne implements DataAccessAddOn { final Class remotePrimaryKeyType = remotePrimaryKeyField.getType(); if (remotePrimaryKeyType == Long.class) { // here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ... - final Long foreignKey = doc.getLong(fieldName); + final Long foreignKey = doc.getLong(fieldName.inTable()); if (foreignKey != null) { - // In the lazy mode, the request is done in asynchronous mode, they will be done after... final LazyGetter lambda = () -> { // TODO: update to have get with abstract types .... final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey); @@ -189,9 +162,22 @@ public class AddOnManyToOne implements DataAccessAddOn { } } else if (remotePrimaryKeyType == UUID.class) { // here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ... - final UUID foreignKey = doc.get(fieldName, UUID.class); + final UUID foreignKey = doc.get(fieldName.inTable(), UUID.class); + if (foreignKey != null) { + final LazyGetter lambda = () -> { + // TODO: update to have get with abstract types .... + final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey); + if (foreignData == null) { + return; + } + field.set(data, foreignData); + }; + lazyCall.add(lambda); + } + } else if (remotePrimaryKeyType == ObjectId.class) { + // here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ... + final ObjectId foreignKey = doc.get(fieldName.inTable(), ObjectId.class); if (foreignKey != null) { - // In the lazy mode, the request is done in asynchronous mode, they will be done after... final LazyGetter lambda = () -> { // TODO: update to have get with abstract types .... final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey); @@ -221,7 +207,7 @@ public class AddOnManyToOne implements DataAccessAddOn { final QueryOptions options) throws Exception { final Class classType = field.getType(); if (classType == Long.class || classType == Integer.class || classType == Short.class - || classType == String.class || classType == UUID.class) { + || classType == String.class || classType == UUID.class || classType == ObjectId.class) { DataFactory.createTablesSpecificType(tableName, primaryField, field, mainTableBuilder, preActionList, postActionList, createIfNotExist, createDrop, fieldId, classType, options); } else { diff --git a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnOneToMany.java b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnOneToMany.java index 3cdfa2e..7c0ac93 100644 --- a/src/org/kar/archidata/dataAccess/addOnMongo/AddOnOneToMany.java +++ b/src/org/kar/archidata/dataAccess/addOnMongo/AddOnOneToMany.java @@ -2,62 +2,28 @@ package org.kar.archidata.dataAccess.addOnMongo; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; import org.bson.Document; +import org.bson.types.ObjectId; import org.kar.archidata.annotation.AnnotationTools; import org.kar.archidata.annotation.AnnotationTools.FieldName; -import org.kar.archidata.dataAccess.CountInOut; import org.kar.archidata.dataAccess.DBAccessMorphia; import org.kar.archidata.dataAccess.LazyGetter; import org.kar.archidata.dataAccess.QueryCondition; import org.kar.archidata.dataAccess.QueryOptions; import org.kar.archidata.dataAccess.options.Condition; -import org.kar.archidata.exception.DataAccessException; -import org.kar.archidata.tools.ConfigBaseVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import jakarta.persistence.FetchType; import jakarta.persistence.OneToMany; -import jakarta.validation.constraints.NotNull; public class AddOnOneToMany implements DataAccessAddOn { static final Logger LOGGER = LoggerFactory.getLogger(AddOnOneToMany.class); static final String SEPARATOR_LONG = "-"; - /** Convert the list if external id in a string '-' separated - * @param ids List of value (null are removed) - * @return '-' string separated */ - protected static String getStringOfIds(final List ids) { - final List tmp = new ArrayList<>(ids); - return tmp.stream().map(String::valueOf).collect(Collectors.joining("-")); - } - - /** extract a list of "-" 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. */ - protected static List getListOfIds(final ResultSet rs, final int iii) throws SQLException { - final String trackString = rs.getString(iii); - if (rs.wasNull()) { - return null; - } - final List out = new ArrayList<>(); - final String[] elements = trackString.split("-"); - for (final String elem : elements) { - final Long tmp = Long.parseLong(elem); - out.add(tmp); - } - return out; - } - @Override public Class getAnnotationClass() { return OneToMany.class; @@ -98,7 +64,7 @@ public class AddOnOneToMany implements DataAccessAddOn { } final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; - if (objectClass == Long.class || objectClass == UUID.class) { + if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) { return true; } final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class); @@ -111,104 +77,7 @@ public class AddOnOneToMany implements DataAccessAddOn { return false; } - public void generateConcatQuery( - @NotNull final String tableName, - @NotNull final String primaryKey, - @NotNull final Field field, - @NotNull final StringBuilder querySelect, - @NotNull final StringBuilder query, - @NotNull final String name, - @NotNull final CountInOut count, - final QueryOptions options, - final Class targetEntity, - final String mappedBy) throws Exception { - final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) - .getActualTypeArguments()[0]; - final String remoteTableName = AnnotationTools.getTableName(targetEntity); - final FieldName remoteTablePrimaryKeyName = AnnotationTools - .getFieldName(AnnotationTools.getPrimaryKeyField(targetEntity), options); - final String tmpRemoteVariable = "tmp_" + Integer.toString(count.value); - final String remoteDeletedFieldName = AnnotationTools.getDeletedFieldName(targetEntity); - - querySelect.append(" (SELECT GROUP_CONCAT("); - querySelect.append(tmpRemoteVariable); - querySelect.append("."); - querySelect.append(remoteTablePrimaryKeyName.inTable()); - querySelect.append(" "); - if ("sqlite".equals(ConfigBaseVariable.getDBType())) { - querySelect.append(", "); - } else { - querySelect.append("SEPARATOR "); - } - querySelect.append("'"); - if (objectClass == Long.class) { - querySelect.append(SEPARATOR_LONG); - } - querySelect.append("') FROM "); - querySelect.append(remoteTableName); - querySelect.append(" "); - querySelect.append(tmpRemoteVariable); - querySelect.append(" WHERE "); - if (remoteDeletedFieldName != null) { - querySelect.append(tmpRemoteVariable); - querySelect.append("."); - querySelect.append(remoteDeletedFieldName); - querySelect.append(" = false"); - querySelect.append(" AND "); - } - querySelect.append(tableName); - querySelect.append("."); - querySelect.append(primaryKey); - querySelect.append(" = "); - querySelect.append(tmpRemoteVariable); - querySelect.append("."); - querySelect.append(mappedBy); - querySelect.append(" "); - querySelect.append(") AS "); - querySelect.append(name); - querySelect.append(" "); - } - - @Override - public void generateQuery( - @NotNull final String tableName, - @NotNull final String primaryKey, - @NotNull final Field field, - @NotNull final StringBuilder querySelect, - @NotNull final StringBuilder query, - @NotNull final String name, - @NotNull final CountInOut count, - final QueryOptions options) throws Exception { - if (field.getType() != List.class) { - return; - } - final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) - .getActualTypeArguments()[0]; - final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class); - if (decorators == null) { - return; - } - // TODO: manage better the eager and lazy !! - if (objectClass == Long.class || objectClass == UUID.class) { - generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options, - decorators.targetEntity(), decorators.mappedBy()); - return; - } - if (objectClass == decorators.targetEntity()) { - if (decorators.fetch() == FetchType.EAGER) { - throw new DataAccessException("EAGER is not supported for list of element..."); - } else { - // Force a copy of the primaryKey to permit the async retrieve of the data - querySelect.append(" "); - querySelect.append(tableName); - querySelect.append("."); - querySelect.append(primaryKey); - querySelect.append(" AS tmp_"); - querySelect.append(Integer.toString(count.value)); - } - } - } - + // in first implementation we did not keep the data in the 2 Objects, bun we will do it after to have a faster table interactions. @Override public void fillFromDoc( final DBAccessMorphia ioDb, @@ -222,11 +91,12 @@ public class AddOnOneToMany implements DataAccessAddOn { return; } - final String fieldName = AnnotationTools.getFieldName(field, options).inTable(); - if (!doc.containsKey(fieldName)) { - field.set(data, null); - return; - } + final FieldName fieldName = AnnotationTools.getFieldName(field, options); + // in step 1 the fields are not stored in the local element + // if (!doc.containsKey(fieldName.inTable())) { + // field.set(data, null); + // return; + // } final Class objectClass = (Class) ((ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; @@ -234,62 +104,46 @@ public class AddOnOneToMany implements DataAccessAddOn { if (decorators == null) { return; } - if (objectClass == Long.class || objectClass == UUID.class) { - final Object value = doc.get(fieldName, field.getType()); - field.set(data, value); + if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) { + if (true) { + // DEVELOPMENT step 1 we search all the element in the list: + // get the curentObject primary key + final Field primaryField = AnnotationTools.getPrimaryKeyField(data.getClass()); + final String primaryKeyName = AnnotationTools.getFieldNameRaw(primaryField); + final Object primaryKey = doc.get(primaryKeyName, primaryField.getType()); + // get the remotes objects + final List returnValue = ioDb.getsWhere(decorators.targetEntity(), + new Condition(new QueryCondition(decorators.mappedBy(), "=", primaryKey))); + // extract the primary key of the remote objects + final Field remotePrimaryField = AnnotationTools.getPrimaryKeyField(decorators.targetEntity()); + final String remotePrimaryKeyName = AnnotationTools.getFieldNameRaw(remotePrimaryField); + final List listOfRemoteKeys = new ArrayList<>(); + for (final var item : returnValue) { + listOfRemoteKeys.add(remotePrimaryField.get(item)); + } + // inject in the current data field + if (listOfRemoteKeys.size() != 0) { + field.set(data, listOfRemoteKeys); + } + } else { + // DEVELOPMENT In step 2 this will work well: + final Object value = doc.get(fieldName.inTable(), field.getType()); + field.set(data, value); + } return; } if (objectClass == decorators.targetEntity()) { - - Long parentIdTmp = null; - UUID parendUuidTmp = null; - try { - final Object value = doc.get(fieldName); - if (value instanceof final Long valueCasted) { - parentIdTmp = valueCasted; - } else if (value instanceof final UUID valueCasted) { - parendUuidTmp = valueCasted; - } - } catch (final Exception ex) { - LOGGER.error("fail to find the correct type... {}", ex.getMessage()); - } - final Long parentId = parentIdTmp; - final UUID parendUuid = parendUuidTmp; - final String mappingKey = decorators.mappedBy(); - // We get the parent ID ... ==> need to request the list of elements - if (objectClass == Long.class) { - LOGGER.error("Need to retreive all primary key of all elements"); - //field.set(data, idList); - return; - } else if (objectClass == UUID.class) { - LOGGER.error("Need to retreive all primary key of all elements"); - //field.set(data, idList); - return; - } - if (objectClass == decorators.targetEntity()) { - if (parentId != null) { - final LazyGetter lambda = () -> { - @SuppressWarnings("unchecked") - final Object foreignData = ioDb.getsWhere(decorators.targetEntity(), - new Condition(new QueryCondition(mappingKey, "=", parentId))); - if (foreignData == null) { - return; - } - field.set(data, foreignData); - }; - lazyCall.add(lambda); - } else if (parendUuid != null) { - final LazyGetter lambda = () -> { - @SuppressWarnings("unchecked") - final Object foreignData = ioDb.getsWhere(decorators.targetEntity(), - new Condition(new QueryCondition(mappingKey, "=", parendUuid))); - if (foreignData == null) { - return; - } - field.set(data, foreignData); - }; - lazyCall.add(lambda); - } + // Maybe in a second step we do not like this but this way is efficient too. + // get the curentObject primary key + final Field primaryField = AnnotationTools.getPrimaryKeyField(data.getClass()); + final String primaryKeyName = AnnotationTools.getFieldNameRaw(primaryField); + final Object primaryKey = doc.get(primaryKeyName, primaryField.getType()); + // get the remotes objects + final List returnValue = ioDb.getsWhere(decorators.targetEntity(), + new Condition(new QueryCondition(decorators.mappedBy(), "=", primaryKey))); + // inject in the current data field + if (returnValue.size() != 0) { + field.set(data, returnValue); } } } diff --git a/src/org/kar/archidata/dataAccess/addOnMongo/DataAccessAddOn.java b/src/org/kar/archidata/dataAccess/addOnMongo/DataAccessAddOn.java index a89f5f0..d3e1dbc 100644 --- a/src/org/kar/archidata/dataAccess/addOnMongo/DataAccessAddOn.java +++ b/src/org/kar/archidata/dataAccess/addOnMongo/DataAccessAddOn.java @@ -5,13 +5,10 @@ import java.sql.SQLException; import java.util.List; import org.bson.Document; -import org.kar.archidata.dataAccess.CountInOut; import org.kar.archidata.dataAccess.DBAccessMorphia; import org.kar.archidata.dataAccess.LazyGetter; import org.kar.archidata.dataAccess.QueryOptions; -import jakarta.validation.constraints.NotNull; - public interface DataAccessAddOn { /** Get the Class of the declaration annotation * @return The annotation class */ @@ -57,16 +54,6 @@ public interface DataAccessAddOn { return false; } - void generateQuery( - @NotNull String tableName, - @NotNull final String primaryKey, - @NotNull Field field, - @NotNull final StringBuilder querySelect, - @NotNull final StringBuilder query, - @NotNull String name, - @NotNull CountInOut count, - QueryOptions options) throws Exception; - // Return the number of colomn read void fillFromDoc( final DBAccessMorphia ioDb, diff --git a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnDataJson.java b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnDataJson.java index 0b6ffdf..bbff0b8 100644 --- a/src/org/kar/archidata/dataAccess/addOnSQL/AddOnDataJson.java +++ b/src/org/kar/archidata/dataAccess/addOnSQL/AddOnDataJson.java @@ -16,7 +16,6 @@ import org.kar.archidata.annotation.AnnotationTools.FieldName; import org.kar.archidata.annotation.DataJson; import org.kar.archidata.dataAccess.CountInOut; import org.kar.archidata.dataAccess.DBAccess; -import org.kar.archidata.dataAccess.DBAccessMorphia; import org.kar.archidata.dataAccess.DBAccessSQL; import org.kar.archidata.dataAccess.DataFactory; import org.kar.archidata.dataAccess.LazyGetter; @@ -254,34 +253,28 @@ public class AddOnDataJson implements DataAccessAddOn { final Object id, final String columnList, final Object remoteKey) throws Exception { - if (ioDb instanceof final DBAccessSQL daSQL) { - final String tableName = AnnotationTools.getTableName(clazz); - final QueryOptions options = new QueryOptions(new OverrideTableName(tableName), - new OptionSpecifyType("id", id.getClass()), - new OptionSpecifyType("covers", remoteKey.getClass(), true)); - if (columnId != null && !columnId.equals("id")) { - options.add(new OptionRenameColumn("id", columnId)); - } - if (columnList != null && !columnList.equals("covers")) { - options.add(new OptionRenameColumn("covers", columnList)); - } - final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, id, options.getAllArray()); - if (data.covers == null) { - return; - } - final List newList = new ArrayList<>(); - for (final Object elem : data.covers) { - if (elem.equals(remoteKey)) { - continue; - } - newList.add(elem); - } - data.covers = newList; - ioDb.update(data, data.id, List.of("covers"), options.getAllArray()); - } else if (ioDb instanceof final DBAccessMorphia dam) { - - } else { - throw new DataAccessException("DataAccess Not managed"); + final String tableName = AnnotationTools.getTableName(clazz); + final QueryOptions options = new QueryOptions(new OverrideTableName(tableName), + new OptionSpecifyType("id", id.getClass()), + new OptionSpecifyType("covers", remoteKey.getClass(), true)); + if (columnId != null && !columnId.equals("id")) { + options.add(new OptionRenameColumn("id", columnId)); } + if (columnList != null && !columnList.equals("covers")) { + options.add(new OptionRenameColumn("covers", columnList)); + } + final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, id, options.getAllArray()); + if (data.covers == null) { + return; + } + final List newList = new ArrayList<>(); + for (final Object elem : data.covers) { + if (elem.equals(remoteKey)) { + continue; + } + newList.add(elem); + } + data.covers = newList; + ioDb.update(data, data.id, List.of("covers"), options.getAllArray()); } } diff --git a/test/src/test/kar/archidata/dataAccess/model/TypeManyToOneLongRootExpand.java b/test/src/test/kar/archidata/dataAccess/model/TypeManyToOneLongRootExpand.java index aadbf16..32c5f05 100644 --- a/test/src/test/kar/archidata/dataAccess/model/TypeManyToOneLongRootExpand.java +++ b/test/src/test/kar/archidata/dataAccess/model/TypeManyToOneLongRootExpand.java @@ -9,7 +9,7 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; @Table(name = "TypeManyToOneLongRoot") -//for Mongo +//for Morphia @Entity(value = "TypeManyToOneLongRoot") public class TypeManyToOneLongRootExpand extends GenericData {