01/26: Introduction des deux services à utiliser pour effectuer la synchronisation unidirectionnelle de référentiel (See #7739)
This is an automated email from the git hooks/post-receive script. New commit to branch feature/7739 in repository tutti. See https://gitlab.nuiton.org/codelutin/tutti.git commit 08ac53efda9e3fad717ff53f4a1d984a8effee2f Author: Tony CHEMIT <chemit@codelutin.com> Date: Tue Jun 28 10:47:44 2016 +0200 Introduction des deux services à utiliser pour effectuer la synchronisation unidirectionnelle de référentiel (See #7739) --- .../actions/synchro/LocalReferentialStates.java | 73 +++++++++++++ .../actions/synchro/RemoteReferentialDiff.java | 78 ++++++++++++++ ...ectionalReferentialSynchronizeLocalService.java | 47 ++++++++ ...ctionalReferentialSynchronizeRemoteService.java | 24 +++++ ...nalReferentialSynchronizeLocalServiceTopia.java | 118 +++++++++++++++++++++ ...alReferentialSynchronizeRemoteServiceTopia.java | 92 ++++++++++++++++ 6 files changed, 432 insertions(+) diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/LocalReferentialStates.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/LocalReferentialStates.java new file mode 100644 index 0000000..d770f36 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/LocalReferentialStates.java @@ -0,0 +1,73 @@ +package fr.ird.observe.services.service.actions.synchro; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; + +/** + * Contient les états des référentiels de la source locale à synchroniser. + * + * Created on 27/06/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +public class LocalReferentialStates implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Contient pour chaque type de référentiel la version de chaque référentiel indexé par son nom. + */ + private final Map<String, Map<String, Long>> referentialVersionsByType; + + /** + * Contient la liste des identifiants des référentiels désactivés indexé par son nom. + */ + private final Multimap<String, String> referentialDisabledIdsByType; + + public LocalReferentialStates() { + this.referentialVersionsByType = new TreeMap<>(); + this.referentialDisabledIdsByType = ArrayListMultimap.create(); + } + + /** + * @param referentialName le nom de référentiel + * @return la collection des versions de référentiel du nom demandé. + */ + public Map<String, Long> getReferentialVersions(String referentialName) { + return referentialVersionsByType.get(referentialName); + } + + /** + * @param referentialName le nom de référentiel + * @return la collection des identifiants de référentiel désactivés du nom demandé. + */ + public Collection<String> getReferentialDisabled(String referentialName) { + return referentialDisabledIdsByType.get(referentialName); + } + + /** + * Pour ajouter un référentiel. + * + * @param referentialName le nom du référentiel + * @param id l'identifiant du référentiel à ajouter + * @param version la version du référentiel à ajouter + * @param disabled {@code true} si le référentiel est désactivé + */ + void addReferentialVersion(String referentialName, String id, long version, boolean disabled) { + Map<String, Long> map = referentialVersionsByType.get(referentialName); + if (map == null) { + map = new TreeMap<>(); + referentialVersionsByType.put(referentialName, map); + } + map.put(id, version); + if (disabled) { + referentialDisabledIdsByType.put(referentialName, id); + } + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/RemoteReferentialDiff.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/RemoteReferentialDiff.java new file mode 100644 index 0000000..2aa4b8d --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/RemoteReferentialDiff.java @@ -0,0 +1,78 @@ +package fr.ird.observe.services.service.actions.synchro; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import fr.ird.observe.services.dto.referential.ReferentialDto; +import fr.ird.observe.services.dto.referential.ReferentialReference; + +import java.io.Serializable; +import java.util.Collection; + +/** + * Contient le différentiel de référentiels calculé sur la source centrale à partir des états de la source à synchroniser. + * + * Created on 27/06/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +public class RemoteReferentialDiff implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Les référentiels à ajouter (indexé par nom de référentiel). + */ + private final Multimap<String, ReferentialDto> referentialsToAdd; + /** + * Les référentiels à mettre à jour (indexé par nom de référentiel). + */ + private final Multimap<String, ReferentialDto> referentialsToUpdate; + /** + * Les références de référentiels à supprimer (indexé par nom de référentiel). + */ + private final Multimap<String, ReferentialReference> referentialsToRemove; + /** + * Les références de référentiels à changer (ils sont devenus obsolètes) (indexé par nom de référentiel). + */ + private final Multimap<String, ReferentialReference> referentialsToFix; + + public RemoteReferentialDiff() { + referentialsToAdd = ArrayListMultimap.create(); + referentialsToUpdate = ArrayListMultimap.create(); + referentialsToRemove = ArrayListMultimap.create(); + referentialsToFix = ArrayListMultimap.create(); + } + + public Collection<ReferentialDto> getReferentialsToAdd(String referentialName) { + return referentialsToAdd.get(referentialName); + } + + public Collection<ReferentialDto> getReferentialsToUpdate(String referentialName) { + return referentialsToUpdate.get(referentialName); + } + + public Collection<ReferentialReference> getReferentialsToRemove(String referentialName) { + return referentialsToRemove.get(referentialName); + } + + public Collection<ReferentialReference> getReferentialsToFix(String referentialName) { + return referentialsToFix.get(referentialName); + } + + void addReferentialToAdd(String referentialName, ReferentialDto referentialDto) { + referentialsToAdd.put(referentialName, referentialDto); + } + + void addReferentialToUpdate(String referentialName, ReferentialDto referentialDto) { + referentialsToUpdate.put(referentialName, referentialDto); + } + + void addReferentialToDelete(String referentialName, ReferentialReference referentialReference) { + referentialsToRemove.put(referentialName, referentialReference); + } + + void addReferentialToFix(String entityName, ReferentialReference referentialReference) { + referentialsToFix.put(entityName, referentialReference); + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeLocalService.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeLocalService.java new file mode 100644 index 0000000..3c3f570 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeLocalService.java @@ -0,0 +1,47 @@ +package fr.ird.observe.services.service.actions.synchro; + +import fr.ird.observe.services.dto.referential.ReferentialReferenceSet; +import fr.ird.observe.services.spi.ReadReferentialPermission; + +import java.util.Collection; +import java.util.Set; + +/** + * Service pour effectuer une synchronisation de référentiel unidirectionnelle du côte de la source centrale. + * + * Created on 27/06/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +public interface UnidirectionalReferentialSynchronizeLocalService { + + /** + * Récupération sur la source à synchroniser des versions de ses référentiels. + * + * @return les versions de tous les référentiels de la base à synchroniser. + */ + @ReadReferentialPermission + LocalReferentialStates getLocalSourceReferentialStates(); + + /** + * Pour un référentiel d'un type donné (son nom est donné), détecte les référentiels dont + * les identifiants sont passés en paramètres qui sont réellement utilisés dans la source locale. + * + * @param referentialName le nom du référentiel + * @param ids l'identifiant du référentiel dont on recherche le nombre d'utilisation + * @return les identifiants des référentiels passés en paramètres qui sont réellement utilisés dans la source locale. + */ + @ReadReferentialPermission + Set<String> filterIdsUsedInLocalSource(String referentialName, Collection<String> ids); + + /** + * Pour récupérer un ensemble de référentiels non désactivés pour un type donné (et ceci afin de remplacer + * un référentiel de même type supprimé ou désactivé). + * + * @param referentialName le nom du référentiel + * @return l'ensemble des référentiels non désactivés du type demandé + */ + @ReadReferentialPermission + ReferentialReferenceSet getLocalSourceEnabledReferenceSet(String referentialName); +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeRemoteService.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeRemoteService.java new file mode 100644 index 0000000..66983a3 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeRemoteService.java @@ -0,0 +1,24 @@ +package fr.ird.observe.services.service.actions.synchro; + +import fr.ird.observe.services.spi.ReadReferentialPermission; + +/** + * Service pour effectuer une synchronisation de référentiel unidirectionnelle. + * + * Created on 27/06/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +public interface UnidirectionalReferentialSynchronizeRemoteService { + + /** + * Récupération sur la source centrale du différentiel des référentiel. + * + * @param localReferentialStates les états de référentiel de la source à synchroniser. + * @return le résultat de calcul de différentiel de référentiel. + */ + @ReadReferentialPermission + RemoteReferentialDiff getReferentialDifferential(LocalReferentialStates localReferentialStates); + +} diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeLocalServiceTopia.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeLocalServiceTopia.java new file mode 100644 index 0000000..69c87f7 --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeLocalServiceTopia.java @@ -0,0 +1,118 @@ +package fr.ird.observe.services.service.actions.synchro; + +import fr.ird.observe.ObserveEntityEnum; +import fr.ird.observe.ObserveTopiaPersistenceContext; +import fr.ird.observe.entities.Entities; +import fr.ird.observe.entities.constants.ReferenceStatusPersist; +import fr.ird.observe.entities.referentiel.ObserveReferentialEntity; +import fr.ird.observe.services.ObserveServiceTopia; +import fr.ird.observe.services.binder.BinderEngine; +import fr.ird.observe.services.dto.referential.ReferentialDto; +import fr.ird.observe.services.dto.referential.ReferentialReferenceSet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.persistence.TopiaDao; +import org.nuiton.topia.persistence.TopiaEntity; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created on 27/06/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +public class UnidirectionalReferentialSynchronizeLocalServiceTopia extends ObserveServiceTopia implements UnidirectionalReferentialSynchronizeLocalService { + + /** Logger. */ + private static final Log log = LogFactory.getLog(UnidirectionalReferentialSynchronizeLocalServiceTopia.class); + + @Override + public LocalReferentialStates getLocalSourceReferentialStates() { + + if (log.isTraceEnabled()) { + log.trace("getLocalSourceReferentialStates()"); + } + + LocalReferentialStates localReferentialStates = new LocalReferentialStates(); + for (ObserveEntityEnum referenceEntity : Entities.REFERENCE_ENTITIES) { + Class entityType = referenceEntity.getContract(); + getLocalSourceReferentialVersions0(referenceEntity.name(), entityType, localReferentialStates); + } + return localReferentialStates; + + } + + @Override + public Set<String> filterIdsUsedInLocalSource(String referentialName, Collection<String> ids) { + + if (log.isTraceEnabled()) { + log.trace("filterIdsUsedInLocalSource(" + referentialName + ", " + ids + ")"); + } + + ObserveEntityEnum entityEnum = ObserveEntityEnum.valueOf(referentialName); + Class entityType = entityEnum.getContract(); + Set<String> result = new LinkedHashSet<>(); + for (String id : ids) { + int count = countUsage0(entityType, id); + if (count > 0) { + result.add(id); + } + } + return result; + + } + + @Override + public ReferentialReferenceSet getLocalSourceEnabledReferenceSet(String referentialName) { + + if (log.isTraceEnabled()) { + log.trace("getLocalSourceEnabledReferenceSet(" + referentialName + ")"); + } + + ObserveEntityEnum entityEnum = ObserveEntityEnum.valueOf(referentialName); + Class entityType = entityEnum.getContract(); + Class dtoType = BinderEngine.get().getReferentialDtoType(entityType); + ReferentialReferenceSet result = getLocalSourceEnabledReferenceSet0(entityType, dtoType); + return result; + + } + + private <E extends ObserveReferentialEntity> void getLocalSourceReferentialVersions0(String entityName, Class<E> entityType, LocalReferentialStates localReferentialStates) { + + TopiaDao<E> dao = getTopiaPersistenceContext().getDao(entityType); + for (E e : dao) { + localReferentialStates.addReferentialVersion(entityName, e.getTopiaId(), e.getTopiaVersion(), e.isDisabled()); + } + + } + + private <E extends ObserveReferentialEntity> int countUsage0(Class<E> entityType, String id) { + + TopiaDao<E> dao = getTopiaPersistenceContext().getDao(entityType); + E e = dao.forTopiaIdEquals(id).findUnique(); + Map<Class<? extends TopiaEntity>, List<? extends TopiaEntity>> allUsages = dao.findAllUsages(e); + int count = 0; + for (List<? extends TopiaEntity> entities : allUsages.values()) { + count += entities.size(); + } + return count; + + } + + private <E extends ObserveReferentialEntity, R extends ReferentialDto> ReferentialReferenceSet<R> getLocalSourceEnabledReferenceSet0(Class<E> entityType, Class<R> dtoType) { + + ObserveTopiaPersistenceContext persistenceContext = getTopiaPersistenceContext(); + TopiaDao<E> dao = persistenceContext.getDao(entityType); + List<E> entities = dao.forEquals(ObserveReferentialEntity.PROPERTY_STATUS, ReferenceStatusPersist.enabled).findAll(); + ReferentialReferenceSet<R> result = toReferentialReferenceSet(dtoType, entities, null); + return result; + + } + + +} diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeRemoteServiceTopia.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeRemoteServiceTopia.java new file mode 100644 index 0000000..3d9cba1 --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/UnidirectionalReferentialSynchronizeRemoteServiceTopia.java @@ -0,0 +1,92 @@ +package fr.ird.observe.services.service.actions.synchro; + +import fr.ird.observe.ObserveEntityEnum; +import fr.ird.observe.entities.Entities; +import fr.ird.observe.entities.referentiel.ObserveReferentialEntity; +import fr.ird.observe.services.ObserveServiceTopia; +import fr.ird.observe.services.binder.BinderEngine; +import fr.ird.observe.services.dto.constants.ReferentialLocale; +import fr.ird.observe.services.dto.referential.ReferentialDto; +import fr.ird.observe.services.dto.referential.ReferentialReference; +import org.nuiton.topia.persistence.TopiaDao; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created on 27/06/16. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 5.0 + */ +public class UnidirectionalReferentialSynchronizeRemoteServiceTopia extends ObserveServiceTopia implements UnidirectionalReferentialSynchronizeRemoteService { + + @Override + public RemoteReferentialDiff getReferentialDifferential(LocalReferentialStates localReferentialStates) { + + RemoteReferentialDiff result = new RemoteReferentialDiff(); + for (ObserveEntityEnum referenceEntity : Entities.REFERENCE_ENTITIES) { + Class entityType = referenceEntity.getContract(); + getReferentialDifferential0(referenceEntity.name(), entityType, localReferentialStates, result); + } + return result; + + } + + private <E extends ObserveReferentialEntity> void getReferentialDifferential0(String entityName, Class<E> entityType, LocalReferentialStates localReferentialStates, RemoteReferentialDiff result) { + + ReferentialLocale referentialLocale = getReferentialLocale(); + BinderEngine binderEngine = BinderEngine.get(); + Class<ReferentialDto> referentialDtoType = binderEngine.getReferentialDtoType(entityType); + Map<String, Long> localReferentialVersions = localReferentialStates.getReferentialVersions(entityName); + Collection<String> localReferentialDisabled = localReferentialStates.getReferentialDisabled(entityName); + TopiaDao<E> dao = getTopiaPersistenceContext().getDao(entityType); + for (E centralReferentialEntity : dao) { + + String id = centralReferentialEntity.getTopiaId(); + Long localVersion = localReferentialVersions.get(id); + + if (localVersion == null) { + + // nouvelle entité + ReferentialDto dto = binderEngine.transformEntityToReferentialDto(referentialLocale, centralReferentialEntity); + result.addReferentialToAdd(entityName, dto); + continue; + } + + long centralVersion = centralReferentialEntity.getTopiaVersion(); + + if (centralVersion > localVersion) { + + // entité à mettre à jour + ReferentialDto dto = binderEngine.transformEntityToReferentialDto(referentialLocale, centralReferentialEntity); + result.addReferentialToUpdate(entityName, dto); + } + + if (centralReferentialEntity.isDisabled() && !localReferentialDisabled.contains(id)) { + + // entité qui passe en mode désactivé, il faudra que l'utilisateur la change + ReferentialReference<ReferentialDto> referentialReference = binderEngine.transformEntityToReferentialReferenceDto(referentialLocale, centralReferentialEntity); + result.addReferentialToFix(entityName, referentialReference); + } + + } + + // entités supprimées + Set<String> idsToDelete = new LinkedHashSet<>(localReferentialVersions.keySet()); + + List<String> centralIds = dao.findAllIds(); + idsToDelete.removeAll(centralIds); + + for (String id : idsToDelete) { + E e = dao.forTopiaIdEquals(id).findUnique(); + ReferentialReference<ReferentialDto> referentialReference = binderEngine.transformEntityToReferentialReferenceDto(referentialLocale, e); + result.addReferentialToDelete(entityName, referentialReference); + } + + } + +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm