This is an automated email from the git hooks/post-receive script. New commit to branch feature/7739 in repository observe. See http://git.codelutin.com/observe.git commit b5f2d85b26c11d5ec0325c9f1259e70c0f034b56 Author: Kevin Morin <morin@codelutin.com> Date: Fri Nov 20 17:15:50 2015 +0100 construction du différentiel de référéntiel dans les services (refs #7739) --- .../synchro/SynchronizationServiceController.java | 23 +++ .../service/actions/synchro/ObserveDiffState.java | 64 +++++++ .../actions/synchro/SynchronizationService.java | 13 ++ .../synchro/SynchronizationServiceTopia.java | 192 +++++++++++++++++++++ .../ird/observe/services/DataSourceResource.java | 19 +- .../services/service/AbstractServiceTopiaTest.java | 69 +++++--- .../synchro/SynchronizationServiceTopiaTest.java | 106 ++++++++++++ 7 files changed, 457 insertions(+), 29 deletions(-) diff --git a/observe-application-web/src/main/java/fr/ird/observe/application/web/controller/v1/actions/synchro/SynchronizationServiceController.java b/observe-application-web/src/main/java/fr/ird/observe/application/web/controller/v1/actions/synchro/SynchronizationServiceController.java new file mode 100644 index 0000000..c2eef2d --- /dev/null +++ b/observe-application-web/src/main/java/fr/ird/observe/application/web/controller/v1/actions/synchro/SynchronizationServiceController.java @@ -0,0 +1,23 @@ +package fr.ird.observe.application.web.controller.v1.actions.synchro; + +import fr.ird.observe.application.web.controller.v1.ObserveAuthenticatedServiceControllerSupport; +import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; +import fr.ird.observe.services.service.actions.synchro.ObserveDiffState; +import fr.ird.observe.services.service.actions.synchro.SynchronizationService; + +/** + * @author Kevin Morin (Code Lutin) + * @since 5.0 + */ +public class SynchronizationServiceController extends ObserveAuthenticatedServiceControllerSupport<SynchronizationService> + implements SynchronizationService { + + protected SynchronizationServiceController() { + super(SynchronizationService.class); + } + + @Override + public ObserveDiffState.ObserveDiffStateMap buildReferentielDifferentiel(ObserveDataSourceConfiguration dstDSC) { + return service.buildReferentielDifferentiel(dstDSC); + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/ObserveDiffState.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/ObserveDiffState.java new file mode 100644 index 0000000..9308e3d --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/ObserveDiffState.java @@ -0,0 +1,64 @@ +package fr.ird.observe.services.service.actions.synchro; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +/** + * Pour qualifier l'etat d'une entite lors du calcul d'un differentiel entre + * deux entites. + * + * @author Kevin Morin (Code Lutin) + * @since 5.0 + */ +public enum ObserveDiffState { + + /** + * nouvel entite dans le storage de reference. + * <p/> + * A ajouter dans le storage local. + */ + NEW, + /** + * entite modifie dans le storage de reference (voir topiaVersion). + * <p/> + * A mettre a jour dans le storage local. + */ + MODIFIED, + /** + * entité supprimée dans le storage de reference. + * <p/> + * A supprimer du storage local (apres remplacement par autre chose...) + */ + REMOVED; + + /** + * Construit un dictionnaire avec pour tous les états une liste vide. + * + * @return le dictionnaire crée + */ + public static ObserveDiffStateMap newMap() { + ObserveDiffStateMap result = new ObserveDiffStateMap(); + for (ObserveDiffState state : values()) { + result.put(state, new ArrayList<String>()); + } + return result; + } + + public static class ObserveDiffStateMap extends EnumMap<ObserveDiffState, List<String>> { + private static final long serialVersionUID = 1L; + + public ObserveDiffStateMap() { + super(ObserveDiffState.class); + } + + public ObserveDiffStateMap(EnumMap<ObserveDiffState, ? extends List<String>> m) { + super(m); + } + + public ObserveDiffStateMap(Map<ObserveDiffState, ? extends List<String>> m) { + super(m); + } + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/SynchronizationService.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/SynchronizationService.java new file mode 100644 index 0000000..16e38ef --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/synchro/SynchronizationService.java @@ -0,0 +1,13 @@ +package fr.ird.observe.services.service.actions.synchro; + +import fr.ird.observe.services.ObserveService; +import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; + +/** + * @author Kevin Morin (Code Lutin) + * @since 5.0 + */ +public interface SynchronizationService extends ObserveService { + + ObserveDiffState.ObserveDiffStateMap buildReferentielDifferentiel(ObserveDataSourceConfiguration dstDSC); +} diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/SynchronizationServiceTopia.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/SynchronizationServiceTopia.java new file mode 100644 index 0000000..8be7431 --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/synchro/SynchronizationServiceTopia.java @@ -0,0 +1,192 @@ +package fr.ird.observe.services.service.actions.synchro; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import fr.ird.observe.ObserveTopiaApplicationContext; +import fr.ird.observe.ObserveTopiaPersistenceContext; +import fr.ird.observe.entities.Entities; +import fr.ird.observe.entities.referentiel.ReferenceEntities; +import fr.ird.observe.services.ObserveServiceTopia; +import fr.ird.observe.services.ObserveTopiaApplicationContextFactory; +import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; +import fr.ird.observe.services.configuration.ObserveDataSourceConfigurationTopiaSupport; +import fr.ird.observe.services.configuration.ObserveDataSourceConnection; +import fr.ird.observe.services.service.DataSourceService; +import org.apache.commons.io.IOUtils; +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 org.nuiton.topia.persistence.util.DiffState; +import org.nuiton.topia.persistence.util.TopiaEntityBinder; +import org.nuiton.topia.persistence.util.TopiaEntityHelper; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Kevin Morin (Code Lutin) + * @since 5.0 + */ +public class SynchronizationServiceTopia extends ObserveServiceTopia implements SynchronizationService { + + /** + * Logger. + */ + private static final Log log = LogFactory.getLog(SynchronizationServiceTopia.class); + + @Override + public ObserveDiffState.ObserveDiffStateMap buildReferentielDifferentiel(final ObserveDataSourceConfiguration dstDSC) { + + ObserveDiffState.ObserveDiffStateMap result = ObserveDiffState.newMap(); + final DiffState.DiffStateMap diffStateMap = DiffState.newMap(); + + ObserveTopiaPersistenceContext dstPersistenceContext = null; + DataSourceService dataSourceService = serviceContext.newService(DataSourceService.class); + + try { + + final ObserveDataSourceConnection dstDataSourceConnection = dataSourceService.open(dstDSC); + + ObserveTopiaApplicationContext dstTopiaApplicationContext = + ObserveTopiaApplicationContextFactory.getOrCreateTopiaApplicationContext( + (ObserveDataSourceConfigurationTopiaSupport) dstDSC); + + dstPersistenceContext = dstTopiaApplicationContext.newPersistenceContext(); + final ObserveTopiaPersistenceContext dstPersistenceContextFinal = + dstTopiaApplicationContext.newPersistenceContext(); + + ReferenceEntities.walk(new ReferenceEntities.ReferentielWalker() { + + + public <E extends TopiaEntity> void walk( + Class<E> contractClass) throws Exception { + + // String s = t(DecoratorService.getEntityLabel(contractClass)); + // String message = + // t("observe.service.build.synchro.referentiel", s); + // if (messanger != null) { + // messanger.sendMessage(message); + // } + // if (log.isInfoEnabled()) { + // log.info(message); + // } + + List<E> list = loadEntities(contractClass); + List<E> list2 = getList(dstDataSourceConnection, dstPersistenceContextFinal, contractClass); + + DiffState.DiffStateMap tmp; + // recuperation du differentiel pour le type d'entitétmp = + tmp = TopiaEntityHelper.buildDifferentiel(list, list2); + // ajout au resultat + DiffState.addAll(diffStateMap, tmp); + // on nettoie + DiffState.clear(tmp); + } + }); + + } catch (Exception e) { + //FIXME kmorin on fait quoi ? + if (log.isErrorEnabled()) { + log.error("", e); + } + + } finally { + + IOUtils.closeQuietly(dstPersistenceContext); + } + + + DiffState.removeEmptyStates(diffStateMap); + + // convert topia DiffStateMap into observe DiffStateMap + for (DiffState diffState : diffStateMap.keySet()) { + ObserveDiffState observeDiffState = ObserveDiffState.valueOf(diffState.name()); + result.put(observeDiffState, diffStateMap.get(diffState)); + } + + return result; + } + + public <E extends TopiaEntity> List<E> getList(ObserveDataSourceConnection dataSourceConnection, + ObserveTopiaPersistenceContext persistenceContext, + Class<E> klass) { + + + List<E> list = getList(dataSourceConnection, persistenceContext, klass, null, null); + return list; + } + + public <E extends TopiaEntity> List<E> getList(ObserveDataSourceConnection dataSourceConnection, + ObserveTopiaPersistenceContext persistenceContext, + Class<E> klass, Predicate<E> predicate) { + List<E> result = getList(dataSourceConnection, persistenceContext, klass, predicate, null); + return result; + } + + public <E extends TopiaEntity> List<E> getList(ObserveDataSourceConnection dataSourceConnection, + ObserveTopiaPersistenceContext persistenceContext, + Class<E> klass, + TopiaEntityBinder<E> loador) { + List<E> result = getList(dataSourceConnection, persistenceContext, klass, null, loador); + return result; + } + + public <E extends TopiaEntity> List<E> getList(ObserveDataSourceConnection dataSourceConnection, + ObserveTopiaPersistenceContext persistenceContext, + Class<E> klass, + Predicate<E> predicate, + TopiaEntityBinder<E> loador) { + + + if (Entities.isDataClass(klass)) { + // on verifie que l'on a le droit de lire la donnee + if (!dataSourceConnection.canReadData()) { + if (log.isDebugEnabled()) { + log.debug("Can not read data, no read credential"); + } + return new ArrayList<E>(); + } + } + + if (Entities.isReferentielClass(klass)) { + // on verifie que l'on a le droit de lire la donnee + if (!dataSourceConnection.canReadReferential()) { + if (log.isDebugEnabled()) { + log.debug("Can not read referentiel, no read credential"); + } + return new ArrayList<E>(); + } + } + + List<E> result = getList0(persistenceContext, klass, predicate, loador); + + //TC-20100208 : on peut modifier la liste (pour supprimer par + // exemple les entites non active), on doit donc toujours travailler + // sur une copie de la liste + return new ArrayList<E>(result); + } + + protected <E extends TopiaEntity> List<E> getList0(ObserveTopiaPersistenceContext persistenceContext, + Class<E> klass, + Predicate<E> predicate, + TopiaEntityBinder<E> loador) { + + TopiaDao<E> dao = persistenceContext.getDao(klass); + List<E> result = dao.findAll(); + + if (predicate != null) { + + // use a filter + result = Lists.newArrayList(Iterables.filter(result, predicate)); + + } + if (loador != null) { + for (E e : result) { + loador.obtainProperties(e); + } + } + return result; + } +} diff --git a/observe-services-topia/src/test/java/fr/ird/observe/services/DataSourceResource.java b/observe-services-topia/src/test/java/fr/ird/observe/services/DataSourceResource.java index 4f57135..c1578f7 100644 --- a/observe-services-topia/src/test/java/fr/ird/observe/services/DataSourceResource.java +++ b/observe-services-topia/src/test/java/fr/ird/observe/services/DataSourceResource.java @@ -71,10 +71,25 @@ public class DataSourceResource implements TestRule { protected String scriptName; - public DataSourceResource(ApplicationContextResource applicationContextResource, Set<String> testNamesChangeDataBase, String scriptName) { + protected String databaseDirectoryName; + + public DataSourceResource(ApplicationContextResource applicationContextResource, + Set<String> testNameChangeDataBase, + String scriptName) { + + this(applicationContextResource, testNameChangeDataBase, scriptName,scriptName); + + } + + public DataSourceResource(ApplicationContextResource applicationContextResource, + Set<String> testNamesChangeDataBase, + String scriptName, + String databaseDirectoryName) { + this.applicationContextResource = applicationContextResource; this.testNamesChangeDataBase = testNamesChangeDataBase; this.scriptName = scriptName; + this.databaseDirectoryName = databaseDirectoryName; } public ObserveDataSourceConfigurationTopiaH2 getDataSourceConfiguration() { @@ -200,7 +215,7 @@ public class DataSourceResource implements TestRule { //if (testNamesChangeDataBase.contains(methodName)) { - File dataBaseDirectory = new File (testDirectory, scriptName); + File dataBaseDirectory = new File (testDirectory, databaseDirectoryName); applicationContextResource.setDataBaseDirectory(dataBaseDirectory); diff --git a/observe-services-topia/src/test/java/fr/ird/observe/services/service/AbstractServiceTopiaTest.java b/observe-services-topia/src/test/java/fr/ird/observe/services/service/AbstractServiceTopiaTest.java index b6fe60f..485a81e 100644 --- a/observe-services-topia/src/test/java/fr/ird/observe/services/service/AbstractServiceTopiaTest.java +++ b/observe-services-topia/src/test/java/fr/ird/observe/services/service/AbstractServiceTopiaTest.java @@ -54,6 +54,10 @@ public abstract class AbstractServiceTopiaTest { private static final Log log = LogFactory.getLog(AbstractServiceTopiaTest.class); + public static final String DATA_FOR_TEST_SEINE_SCRIPT_NAME = "dataForTestSeine"; + public static final String DATA_FOR_TEST_LONGLINE_SCRIPT_NAME = "dataForTestLongline"; + public static final String REFERENTIEL_SCRIPT_NAME = "referentiel"; + public static final String TRIP_SEINE_ID_1 = "fr.ird.observe.entities.seine.TripSeine#1359167789871#0.6765335978809843"; public static final String TRIP_SEINE_ID_2 = "fr.ird.observe.entities.seine.TripSeine#1359280279156#0.41771067982188215"; public static final String TRIP_SEINE_ID_3 = "fr.ird.observe.entities.seine.TripSeine#1360156698296#0.6097793743126777"; @@ -72,33 +76,7 @@ public abstract class AbstractServiceTopiaTest { @Before public void setUp() throws Exception { - File dataBaseDirectory = applicationContextResource.getDataBaseDirectory(); - - if (! dataBaseDirectory.isDirectory()) { - - File dataBaseCommonRefDirectory = applicationContextResource.getDataBaseCommonRefDirectory(); - - if (!dataBaseCommonRefDirectory.isDirectory()) { - - if (log.isInfoEnabled()) { - log.info("create Database on " + dataBaseDirectory + " from script " + getScriptName()); - } - - Files.createDirectories(dataBaseDirectory.toPath()); - - // Create database from script - String scriptPath = applicationContextResource.getScriptPath(getScriptName(), H2DataSourceMigration.V_4_0_1); - - dataSourceResource.createCommonsDataSourceFromScript(scriptPath); - } - - if (! dataBaseCommonRefDirectory.equals(dataBaseDirectory)) { - - FileUtil.copyAndRenameRecursively(dataBaseCommonRefDirectory, dataBaseDirectory, false, (String) null, (String) null, false); - - } - - } + setUp(applicationContextResource, dataSourceResource, getScriptName()); } @@ -124,6 +102,43 @@ public abstract class AbstractServiceTopiaTest { return service; } + protected void setUp(ApplicationContextResource applicationContextResource, + DataSourceResource dataSourceResource, + String dbName) throws Exception { + + File dataBaseDirectory = applicationContextResource.getDataBaseDirectory(); + + if (! dataBaseDirectory.isDirectory()) { + + File dataBaseCommonRefDirectory = applicationContextResource.getDataBaseCommonRefDirectory(); + + if (!dataBaseCommonRefDirectory.isDirectory()) { + + if (log.isInfoEnabled()) { + log.info("create Database on " + dataBaseDirectory + " from script " + dbName); + } + + Files.createDirectories(dataBaseDirectory.toPath()); + + // Create database from script + String scriptPath = applicationContextResource.getScriptPath(dbName, H2DataSourceMigration.V_4_0_1); + + dataSourceResource.createCommonsDataSourceFromScript(scriptPath); + } + + if (! dataBaseCommonRefDirectory.equals(dataBaseDirectory)) { + + FileUtil.copyAndRenameRecursively(dataBaseCommonRefDirectory, + dataBaseDirectory, + false, + (String) null, + (String) null, + false); + + } + + } + } protected void assertEntityEqualsReferenceDto(TopiaEntity entity, ReferenceDto referenceDto) { if (entity == null) { diff --git a/observe-services-topia/src/test/java/fr/ird/observe/services/service/actions/synchro/SynchronizationServiceTopiaTest.java b/observe-services-topia/src/test/java/fr/ird/observe/services/service/actions/synchro/SynchronizationServiceTopiaTest.java new file mode 100644 index 0000000..8449022 --- /dev/null +++ b/observe-services-topia/src/test/java/fr/ird/observe/services/service/actions/synchro/SynchronizationServiceTopiaTest.java @@ -0,0 +1,106 @@ +package fr.ird.observe.services.service.actions.synchro; + +import com.google.common.collect.ImmutableSet; +import fr.ird.observe.services.ApplicationContextResource; +import fr.ird.observe.services.DataSourceResource; +import fr.ird.observe.services.configuration.ObserveDataSourceConfigurationTopiaH2; +import fr.ird.observe.services.dto.FormDto; +import fr.ird.observe.services.dto.referential.VesselDto; +import fr.ird.observe.services.service.AbstractServiceTopiaTest; +import fr.ird.observe.services.service.ReferentialService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; + +import java.util.Date; +import java.util.Set; + +/** + * @author Kevin Morin (Code Lutin) + * @since x.x + */ +public class SynchronizationServiceTopiaTest extends AbstractServiceTopiaTest { + + /** + * Logger. + */ + private static final Log log = LogFactory.getLog(SynchronizationServiceTopiaTest.class); + + protected SynchronizationService service; + + @Override + public Set<String> getTestNamesChangeDataBase() { + return ImmutableSet.of("testBuildReferentielDifferentiel"); + } + + @Override + public String getScriptName() { + return REFERENTIEL_SCRIPT_NAME; + } + + public static final ApplicationContextResource applicationContextResourceReferentielClone = + new ApplicationContextResource(); + + @Rule + public final DataSourceResource dataSourceResourceReferentielClone = + new DataSourceResource(applicationContextResourceReferentielClone, + getTestNamesChangeDataBase(), + REFERENTIEL_SCRIPT_NAME, + "copyOf" + REFERENTIEL_SCRIPT_NAME); + + @Override + public void setUp() throws Exception { + super.setUp(); + + setUp(applicationContextResourceReferentielClone, + dataSourceResourceReferentielClone, + DATA_FOR_TEST_SEINE_SCRIPT_NAME); + + + service = newService(SynchronizationService.class); + } + + @Test + public void testBuildSameReferentielDifferentiel() throws Exception { + + ObserveDataSourceConfigurationTopiaH2 dstConfiguration = + dataSourceResourceReferentielClone.getDataSourceConfiguration(); + + ObserveDiffState.ObserveDiffStateMap observeDiffStateMap = + service.buildReferentielDifferentiel(dstConfiguration); + + Assert.assertTrue(observeDiffStateMap.get(ObserveDiffState.NEW).isEmpty()); + Assert.assertTrue(observeDiffStateMap.get(ObserveDiffState.MODIFIED).isEmpty()); + Assert.assertTrue(observeDiffStateMap.get(ObserveDiffState.REMOVED).isEmpty()); + + } + + @Test + public void testBuildAddReferentielDifferentiel() throws Exception { + + ReferentialService referentialService = newService(ReferentialService.class); + + FormDto<VesselDto> vesselFormDto = referentialService.preCreate(VesselDto.class); + VesselDto vesselDto = vesselFormDto.getForm(); + vesselDto.setLabel1("test"); + vesselDto.setLabel2("test"); + vesselDto.setLabel3("test"); + vesselDto.setCode("TEST"); + vesselDto.setLastUpdate(new Date()); + + String vesselId = referentialService.save(vesselDto); + + ObserveDataSourceConfigurationTopiaH2 dstConfiguration = + dataSourceResourceReferentielClone.getDataSourceConfiguration(); + + ObserveDiffState.ObserveDiffStateMap observeDiffStateMap = + service.buildReferentielDifferentiel(dstConfiguration); + + Assert.assertEquals(1, observeDiffStateMap.get(ObserveDiffState.NEW).size()); + Assert.assertEquals(vesselId, observeDiffStateMap.get(ObserveDiffState.NEW).get(0)); + + } + +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.