2023-11-23 09:26:40 +01:00
package eu.old.eudat.migration ;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties ;
2024-04-26 16:12:29 +02:00
import org.opencdmp.commons.JsonHandlingService ;
import org.opencdmp.commons.XmlHandlingService ;
import org.opencdmp.commons.enums.IsActive ;
import org.opencdmp.data.DmpBlueprintEntity ;
import org.opencdmp.data.DmpDescriptionTemplateEntity ;
import org.opencdmp.query.DmpBlueprintQuery ;
import org.opencdmp.query.DmpDescriptionTemplateQuery ;
2023-11-23 13:40:44 +01:00
import eu.old.eudat.data.dao.entities.DmpDatasetProfileDao ;
2023-11-23 09:26:40 +01:00
import eu.old.eudat.data.entities.DMPDatasetProfile ;
import eu.old.eudat.logic.services.operations.DatabaseRepository ;
2023-11-23 13:40:44 +01:00
import gr.cite.tools.data.query.QueryFactory ;
import gr.cite.tools.exception.MyApplicationException ;
import gr.cite.tools.logging.LoggerService ;
2023-11-23 09:26:40 +01:00
import jakarta.persistence.EntityManager ;
2023-11-24 15:46:30 +01:00
import jakarta.persistence.Tuple ;
import jakarta.persistence.criteria.CriteriaBuilder ;
2023-11-24 16:19:20 +01:00
import jakarta.persistence.criteria.CriteriaDelete ;
2023-11-24 15:46:30 +01:00
import jakarta.persistence.criteria.CriteriaQuery ;
import jakarta.persistence.criteria.Root ;
2023-11-23 13:40:44 +01:00
import jakarta.xml.bind.JAXBException ;
import org.slf4j.LoggerFactory ;
2023-11-23 09:26:40 +01:00
import org.springframework.stereotype.Service ;
2023-11-23 13:40:44 +01:00
import org.xml.sax.SAXException ;
2024-04-26 16:12:29 +02:00
import org.opencdmp.commons.types.dmpblueprint.DefinitionEntity ;
2023-11-23 09:26:40 +01:00
2023-11-23 13:40:44 +01:00
import javax.xml.parsers.ParserConfigurationException ;
import java.io.IOException ;
2023-11-24 16:19:20 +01:00
import java.security.SecureRandom ;
2023-11-23 09:26:40 +01:00
import java.time.Instant ;
2023-11-23 13:40:44 +01:00
import java.util.* ;
2023-11-23 09:26:40 +01:00
@Service
public class DmpDatasetProfileMigrationService {
2023-11-23 13:40:44 +01:00
private static final LoggerService logger = new LoggerService ( LoggerFactory . getLogger ( DmpDatasetProfileMigrationService . class ) ) ;
2023-11-23 09:26:40 +01:00
private final DatabaseRepository databaseRepository ;
private final JsonHandlingService jsonHandlingService ;
2023-11-23 13:40:44 +01:00
private final QueryFactory queryFactory ;
private final XmlHandlingService xmlHandlingService ;
private static final int PageSize = 500 ;
private static final boolean TestMode = false ;
2023-11-23 09:26:40 +01:00
private final EntityManager entityManager ;
2023-11-23 13:40:44 +01:00
public DmpDatasetProfileMigrationService ( DatabaseRepository databaseRepository , JsonHandlingService jsonHandlingService , QueryFactory queryFactory , XmlHandlingService xmlHandlingService , EntityManager entityManager ) {
2023-11-23 09:26:40 +01:00
this . databaseRepository = databaseRepository ;
this . jsonHandlingService = jsonHandlingService ;
2023-11-23 13:40:44 +01:00
this . queryFactory = queryFactory ;
this . xmlHandlingService = xmlHandlingService ;
2023-11-23 09:26:40 +01:00
this . entityManager = entityManager ;
}
2023-11-23 13:40:44 +01:00
public void migrate ( ) throws IOException , JAXBException , ParserConfigurationException , InstantiationException , IllegalAccessException , SAXException {
DmpDatasetProfileDao dmpDatasetProfileDao = databaseRepository . getDmpDatasetProfileDao ( ) ;
long total = dmpDatasetProfileDao . asQueryable ( ) . count ( ) ;
logger . debug ( " Migrate DmpDatasetProfile Total : " + total ) ;
int page = 0 ;
List < DMPDatasetProfile > items ;
do {
items = dmpDatasetProfileDao . asQueryable ( ) . orderBy ( ( builder , root ) - > builder . asc ( root . get ( " ID " ) ) ) . skip ( page * PageSize ) . take ( PageSize ) . toList ( ) ;
if ( items ! = null & & ! items . isEmpty ( ) ) {
logger . debug ( " Migrate DmpDatasetProfile " + page * PageSize + " of " + total ) ;
List < DmpBlueprintEntity > dmpBlueprints = this . queryFactory . query ( DmpBlueprintQuery . class ) . ids ( items . stream ( ) . map ( x - > x . getDmp ( ) . getProfile ( ) . getId ( ) ) . distinct ( ) . toList ( ) ) . collect ( ) ;
Map < UUID , DefinitionEntity > dmpBlueprintsMap = new HashMap < > ( ) ;
for ( DmpBlueprintEntity dmpBlueprint : dmpBlueprints ) {
DefinitionEntity definitionEntity = this . xmlHandlingService . fromXml ( DefinitionEntity . class , dmpBlueprint . getDefinition ( ) ) ;
dmpBlueprintsMap . put ( dmpBlueprint . getId ( ) , definitionEntity ) ;
}
for ( DMPDatasetProfile item : items ) {
entityManager . detach ( item ) ;
DmpDatasetProfileData profileData = jsonHandlingService . fromJson ( DmpDatasetProfileData . class , item . getData ( ) ) ;
if ( profileData = = null | | profileData . dmpSectionIndex = = null | | profileData . dmpSectionIndex . isEmpty ( ) ) {
2024-04-24 17:28:13 +02:00
if ( profileData ! = null & & item . getDmp ( ) ! = null & & item . getDmp ( ) . getProfile ( ) ! = null & & item . getDmp ( ) . getProfile ( ) . getId ( ) ! = null & & item . getDmp ( ) . getProfile ( ) . getId ( ) . equals ( UUID . fromString ( " 86635178-36a6-484f-9057-a934e4eeecd5 " ) ) ) {
profileData . dmpSectionIndex = new ArrayList < > ( ) ;
profileData . dmpSectionIndex . add ( 3 ) ;
logger . warn ( " Migrate DmpDatasetProfile " + item . getId ( ) + " failed no section info set to 3 " ) ;
} else {
throw new MyApplicationException ( " Migrate DmpDatasetProfile " + item . getId ( ) + " failed no section info " ) ;
}
2023-11-23 13:40:44 +01:00
}
DefinitionEntity definition = dmpBlueprintsMap . getOrDefault ( item . getDmp ( ) . getProfile ( ) . getId ( ) , null ) ;
if ( definition = = null ) {
2023-11-23 17:09:17 +01:00
throw new MyApplicationException ( " Migrate DmpDatasetProfile " + item . getId ( ) + " failed blueprint definition not found for blueprint " + item . getDmp ( ) . getProfile ( ) . getId ( ) ) ;
2023-11-23 13:40:44 +01:00
}
for ( int sectionIndex : profileData . dmpSectionIndex ) {
2023-11-29 15:56:25 +01:00
if ( definition . getSections ( ) = = null | | definition . getSections ( ) . size ( ) < = sectionIndex ) {
2023-11-23 17:09:17 +01:00
throw new MyApplicationException ( " Migrate DmpDatasetProfile " + item . getId ( ) + " cannot found section id for section " + sectionIndex ) ;
2023-11-23 13:40:44 +01:00
}
UUID sectionId = definition . getSections ( ) . get ( sectionIndex ) . getId ( ) ;
if ( sectionId = = null ) {
2023-11-23 17:09:17 +01:00
throw new MyApplicationException ( " Migrate DmpDatasetProfile " + item . getId ( ) + " cannot found section id for section " + sectionIndex ) ;
2023-11-23 13:40:44 +01:00
}
DmpDescriptionTemplateEntity data = new DmpDescriptionTemplateEntity ( ) ;
data . setId ( UUID . randomUUID ( ) ) ;
2023-11-24 16:18:28 +01:00
data . setDescriptionTemplateGroupId ( item . getDatasetprofile ( ) . getGroupId ( ) ) ;
2023-11-23 13:40:44 +01:00
data . setDmpId ( item . getDmp ( ) . getId ( ) ) ;
data . setCreatedAt ( Instant . now ( ) ) ;
data . setUpdatedAt ( Instant . now ( ) ) ;
data . setSectionId ( sectionId ) ;
data . setIsActive ( IsActive . Active ) ;
this . entityManager . persist ( data ) ;
}
}
this . entityManager . flush ( ) ;
page + + ;
}
} while ( items ! = null & & ! items . isEmpty ( ) & & ! TestMode ) ;
2023-11-23 17:09:17 +01:00
2023-11-24 17:19:22 +01:00
removeDuplicates ( ) ;
2023-11-24 11:15:57 +01:00
}
private void removeDuplicates ( ) {
logger . debug ( " Checking for duplicates on DmpDescriptionTemplate table after migration " ) ;
2023-11-23 17:09:17 +01:00
2023-11-24 11:15:57 +01:00
DmpDescriptionTemplateQuery dmpDescriptionTemplateQuery = this . queryFactory . query ( DmpDescriptionTemplateQuery . class ) ;
2023-11-24 11:45:29 +01:00
long total = dmpDescriptionTemplateQuery . count ( ) ;
2023-11-24 15:46:30 +01:00
logger . debug ( " Record count to check: {} " , total ) ;
CriteriaBuilder b = this . entityManager . getCriteriaBuilder ( ) ;
CriteriaQuery < Tuple > criteria = b . createQuery ( Tuple . class ) ;
Root < DmpDescriptionTemplateEntity > root = criteria . from ( DmpDescriptionTemplateEntity . class ) ;
2023-11-24 17:19:22 +01:00
criteria . groupBy ( Arrays . asList ( root . get ( DmpDescriptionTemplateEntity . _dmpId ) , root . get ( DmpDescriptionTemplateEntity . _descriptionTemplateGroupId ) , root . get ( DmpDescriptionTemplateEntity . _sectionId ) ) ) ;
criteria . multiselect ( root . get ( DmpDescriptionTemplateEntity . _dmpId ) , root . get ( DmpDescriptionTemplateEntity . _descriptionTemplateGroupId ) , root . get ( DmpDescriptionTemplateEntity . _sectionId ) , b . count ( root ) ) ;
2023-11-24 15:46:30 +01:00
List < Tuple > resultList = this . entityManager . createQuery ( criteria ) . getResultList ( ) ;
List < Tuple > duplicatesList = resultList . stream ( ) . filter ( x - > ( long ) x . get ( 3 ) > 1 ) . toList ( ) ;
2023-11-24 16:19:20 +01:00
CriteriaDelete < DmpDescriptionTemplateEntity > delete = b . createCriteriaDelete ( DmpDescriptionTemplateEntity . class ) ;
Root < DmpDescriptionTemplateEntity > root1 = delete . from ( DmpDescriptionTemplateEntity . class ) ;
2023-11-24 15:46:30 +01:00
for ( Tuple duplicate : duplicatesList ) {
List < DmpDescriptionTemplateEntity > duplicateEntities = dmpDescriptionTemplateQuery
. dmpIds ( ( UUID ) duplicate . get ( 0 ) )
. descriptionTemplateGroupIds ( ( UUID ) duplicate . get ( 1 ) )
. sectionIds ( ( UUID ) duplicate . get ( 2 ) )
. collect ( ) ;
2023-11-24 16:19:20 +01:00
List < UUID > toDelete = new ArrayList < > ( duplicateEntities . stream ( ) . map ( DmpDescriptionTemplateEntity : : getId ) . toList ( ) ) ;
2023-11-24 17:19:22 +01:00
toDelete . remove ( 0 ) ;
delete . where ( root1 . get ( DmpDescriptionTemplateEntity . _id ) . in ( toDelete ) ) ;
2023-11-24 16:19:20 +01:00
this . entityManager . createQuery ( delete ) . executeUpdate ( ) ;
2023-11-24 15:46:30 +01:00
}
2023-11-23 17:09:17 +01:00
2023-11-24 15:46:30 +01:00
entityManager . flush ( ) ;
2023-11-23 09:26:40 +01:00
}
2023-11-23 17:09:17 +01:00
2023-11-23 09:26:40 +01:00
@JsonIgnoreProperties ( { " validationErrorModel " } )
public static class DmpDatasetProfileData {
private List < Integer > dmpSectionIndex ;
public List < Integer > getDmpSectionIndex ( ) {
return dmpSectionIndex ;
}
public void setDmpSectionIndex ( List < Integer > dmpSectionIndex ) {
this . dmpSectionIndex = dmpSectionIndex ;
}
}
}