Tony CHEMIT pushed to branch develop at ultreiaio / ird-observe Commits: 72605589 by Tony CHEMIT at 2017-08-02T20:42:15+02:00 Ajout de la consolidation des dcp (calcul du SimplifiedObjectType) (See #810) - - - - - 9 changed files: - + persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/ObjectMaterialImpl.java - + persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/ObjectMaterialTopiaDao.java - + persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/SimplifiedObjectTypeNode.java - persistence/src/main/models/Observe.model - persistence/src/main/resources/db/migration/6.902/02_drop_object_type-H2.sql - services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidateDataServiceTopia.java - services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidationActivitySeineDataContext.java - + services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/SimplifiedObjectTypeManager.java - + services-topia/src/test/java/fr/ird/observe/services/topia/service/actions/consolidate/SimplifiedObjectTypeManagerTest.java Changes: ===================================== persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/ObjectMaterialImpl.java ===================================== --- /dev/null +++ b/persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/ObjectMaterialImpl.java @@ -0,0 +1,42 @@ +package fr.ird.observe.entities.referentiel.seine; + +/*- + * #%L + * ObServe :: Persistence + * %% + * Copyright (C) 2008 - 2017 IRD, Code Lutin, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +public class ObjectMaterialImpl extends ObjectMaterialAbstract { + + private static final long serialVersionUID = 7003158139439834679L; + + @Override + public ObjectMaterial getSimplifiedObjectMaterial() { + if (getStandardCode() != null) { + return this; + } + return getParent().getSimplifiedObjectMaterial(); + } + + @Override + public ObjectMaterial getSimplifiedParentObjectMaterial() { + return getParent()==null?null:getParent().getSimplifiedObjectMaterial(); + } +} + ===================================== persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/ObjectMaterialTopiaDao.java ===================================== --- /dev/null +++ b/persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/ObjectMaterialTopiaDao.java @@ -0,0 +1,31 @@ +package fr.ird.observe.entities.referentiel.seine; + +/*- + * #%L + * ObServe :: Persistence + * %% + * Copyright (C) 2008 - 2017 IRD, Code Lutin, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableMap; + +public class ObjectMaterialTopiaDao extends AbstractObjectMaterialTopiaDao<ObjectMaterial> { + public ImmutableMap<String, SimplifiedObjectTypeNode> createMaterialMapping() { + return SimplifiedObjectTypeNode.create(findAll()); + } +} ===================================== persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/SimplifiedObjectTypeNode.java ===================================== --- /dev/null +++ b/persistence/src/main/java/fr/ird/observe/entities/referentiel/seine/SimplifiedObjectTypeNode.java @@ -0,0 +1,160 @@ +package fr.ird.observe.entities.referentiel.seine; + +/*- + * #%L + * ObServe :: Persistence + * %% + * Copyright (C) 2008 - 2017 IRD, Code Lutin, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * Created by tchemit on 02/08/17. + * + * @author Tony Chemit - dev@tchemit.fr + */ +public class SimplifiedObjectTypeNode { + + static ImmutableMap<String, SimplifiedObjectTypeNode> create(List<ObjectMaterial> materials) { + TreeMap<String, SimplifiedObjectTypeNode> mappingBuilder = new TreeMap<>(); + + Set<ObjectMaterial> materialsDone = new LinkedHashSet<>(); + Set<ObjectMaterial> materialsTodo = new LinkedHashSet<>(materials); + + while (!materialsTodo.isEmpty()) { + + Set<ObjectMaterial> currentRoundMaterials; + if (materialsDone.isEmpty()) { + + // first round + currentRoundMaterials = materialsTodo.stream().filter(f -> f.getParent() == null).collect(Collectors.toSet()); + + } else { + currentRoundMaterials = materialsTodo.stream().filter(f -> materialsDone.contains(f.getParent())).collect(Collectors.toSet()); + } + + materialsDone.addAll(currentRoundMaterials); + materialsTodo.removeAll(currentRoundMaterials); + + for (ObjectMaterial currentRoundMaterial : currentRoundMaterials) { + + ObjectMaterial simplifiedObjectMaterial = currentRoundMaterial.getSimplifiedObjectMaterial(); + + SimplifiedObjectTypeNode node; + if (Objects.equals(currentRoundMaterial, simplifiedObjectMaterial)) { + + // new node + ObjectMaterial simplifiedParentObjectMaterial = currentRoundMaterial.getSimplifiedParentObjectMaterial(); + SimplifiedObjectTypeNode parentNode = simplifiedParentObjectMaterial == null ? null : mappingBuilder.get(simplifiedParentObjectMaterial.getTopiaId()); + node = new SimplifiedObjectTypeNode(currentRoundMaterial, parentNode); + + } else { + + // simplified object material is a parent, so must have been process in previous round + Objects.requireNonNull(simplifiedObjectMaterial); + + node = mappingBuilder.get(simplifiedObjectMaterial.getTopiaId()); + Objects.requireNonNull(node); + + } + + mappingBuilder.put(currentRoundMaterial.getTopiaId(), node); + + } + } + return ImmutableMap.copyOf(mappingBuilder); + } + + private final int level; + private final String id; + private final String standardCode; + private final SimplifiedObjectTypeNode parent; + + private SimplifiedObjectTypeNode(ObjectMaterial material, SimplifiedObjectTypeNode parent) { + this.id = material.getTopiaId(); + this.standardCode = material.getStandardCode(); + this.parent = parent; + this.level = (parent == null ? 0 : 1 + parent.getLevel()); + } + + public String getId() { + return id; + } + + public String getStandardCode() { + return standardCode; + } + + public SimplifiedObjectTypeNode getParent() { + return parent; + } + + public int getLevel() { + return level; + } + + public SimplifiedObjectTypeNode getSharedAncestor(SimplifiedObjectTypeNode other) { + ImmutableList<SimplifiedObjectTypeNode> pathsToRoot = getPathsToRoot(true); + ImmutableList<SimplifiedObjectTypeNode> otherPathsToRoot = other.getPathsToRoot(true); + List<SimplifiedObjectTypeNode> result = new LinkedList<>(pathsToRoot); + result.retainAll(otherPathsToRoot); + + // get the most precise on common paths + return result.get(0); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SimplifiedObjectTypeNode that = (SimplifiedObjectTypeNode) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public ImmutableList<SimplifiedObjectTypeNode> getPathsToRoot(boolean includeMe) { + List<SimplifiedObjectTypeNode> result = new LinkedList<>(); + if (includeMe) { + result.add(this); + } + if (parent != null) { + parent.getPathsToRoot0(result); + } + return ImmutableList.copyOf(result); + } + + private void getPathsToRoot0(List<SimplifiedObjectTypeNode> result) { + result.add(this); + if (parent != null) { + parent.getPathsToRoot0(result); + } + } +} ===================================== persistence/src/main/models/Observe.model ===================================== --- a/persistence/src/main/models/Observe.model +++ b/persistence/src/main/models/Observe.model @@ -658,6 +658,8 @@ childSelectionMandatory + {*:1} boolean | notNull parent {*:0..1} referentiel.seine.ObjectMaterial objectMaterialType {*:1} referentiel.seine.ObjectMaterialType | lazy=false validation + {*:1} String +getSimplifiedObjectMaterial() referentiel.seine.ObjectMaterial +getSimplifiedParentObjectMaterial() referentiel.seine.ObjectMaterial referentiel.seine.ObjectMaterialType > referentiel.I18nReferentialEntity | entity ===================================== persistence/src/main/resources/db/migration/6.902/02_drop_object_type-H2.sql ===================================== --- a/persistence/src/main/resources/db/migration/6.902/02_drop_object_type-H2.sql +++ b/persistence/src/main/resources/db/migration/6.902/02_drop_object_type-H2.sql @@ -20,4 +20,4 @@ -- #L% --- DROP TABLE observe_seine.ObjectType; -DELETE FROM observe_common.LastUpdateDate WHERE type = 'fr.ird.observe.entities.referentiel.seine.ObjectType'; \ No newline at end of file +DELETE FROM observe_common.LastUpdateDate WHERE type = 'fr.ird.observe.entities.referentiel.seine.ObjectType'; ===================================== services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidateDataServiceTopia.java ===================================== --- a/services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidateDataServiceTopia.java +++ b/services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidateDataServiceTopia.java @@ -22,6 +22,7 @@ package fr.ird.observe.services.topia.service.actions.consolidate; * #L% */ +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import fr.ird.observe.common.constants.seine.DcpComputedValue; import fr.ird.observe.common.constants.seine.NonTargetCatchComputedValueSource; @@ -33,6 +34,7 @@ import fr.ird.observe.entities.referentiel.LengthWeightParameter; import fr.ird.observe.entities.referentiel.Sex; import fr.ird.observe.entities.referentiel.SizeMeasureType; import fr.ird.observe.entities.referentiel.Species; +import fr.ird.observe.entities.referentiel.seine.SimplifiedObjectTypeNode; import fr.ird.observe.entities.seine.ActivitySeine; import fr.ird.observe.entities.seine.FloatingObject; import fr.ird.observe.entities.seine.FloatingObjectPart; @@ -58,6 +60,8 @@ import fr.ird.observe.services.topia.service.ObserveServiceTopia; import java.util.Collection; import java.util.Locale; import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -118,7 +122,10 @@ public class ConsolidateDataServiceTopia extends ObserveServiceTopia implements ObserveTopiaPersistenceContext persistenceContext = getTopiaPersistenceContext(); - ImmutableSet.Builder<ConsolidateActivitySeineDataResult> actititiesResultBuilder = new ImmutableSet.Builder<>(); + ImmutableMap<String, SimplifiedObjectTypeNode> materialMapping = persistenceContext.getObjectMaterialDao().createMaterialMapping(); + SimplifiedObjectTypeManager simplifiedObjectTypeManager = new SimplifiedObjectTypeManager(materialMapping); + + ImmutableSet.Builder<ConsolidateActivitySeineDataResult> activitiesResultBuilder = new ImmutableSet.Builder<>(); for (Route route : tripSeine.getRoute()) { @@ -145,6 +152,7 @@ public class ConsolidateDataServiceTopia extends ObserveServiceTopia implements activityContext.nonTargetLengthMonitor = nonTargetSampleMonitor; activityContext.nonTargetCatchMonitor = nonTargetCatchMonitor; activityContext.dcpMonitor = dcpMonitor; + activityContext.simplifiedObjectTypeManager = simplifiedObjectTypeManager; consolidateActivitySeine(activityContext); @@ -156,7 +164,7 @@ public class ConsolidateDataServiceTopia extends ObserveServiceTopia implements if (log.isInfoEnabled()) { log.info("Found some modifications on activity: " + consolidateActivitySeineDataResult.getActivitySeineLabel()); } - actititiesResultBuilder.add(consolidateActivitySeineDataResult); + activitiesResultBuilder.add(consolidateActivitySeineDataResult); } @@ -164,7 +172,7 @@ public class ConsolidateDataServiceTopia extends ObserveServiceTopia implements } - ImmutableSet<ConsolidateActivitySeineDataResult> consolidateActivitySeineDataResults = actititiesResultBuilder.build(); + ImmutableSet<ConsolidateActivitySeineDataResult> consolidateActivitySeineDataResults = activitiesResultBuilder.build(); ConsolidateTripSeineDataResult consolidateTripSeineDataResult; @@ -278,19 +286,15 @@ public class ConsolidateDataServiceTopia extends ObserveServiceTopia implements computeDcpBiodegradable(dcp); computeDcpNonEntangling(dcp); - computeDcpSimplifiedObjectType(dcp); + computeDcpSimplifiedObjectType(dcp, activityContext.simplifiedObjectTypeManager); activityContext.flushDcp(); } - private void computeDcpSimplifiedObjectType(FloatingObject dcp) { - String value = "FOB"; - if (dcp.isFloatingObjectPartNotEmpty()) { - for (FloatingObjectPart floatingObjectPart : dcp.getFloatingObjectPart()) { - //TODO - } - } + private void computeDcpSimplifiedObjectType(FloatingObject dcp, SimplifiedObjectTypeManager simplifiedObjectTypeManager) { + Set<String> objectMaterialIds = dcp.getFloatingObjectPart().stream().map(p -> p.getObjectMaterial().getTopiaId()).collect(Collectors.toSet()); + String value = simplifiedObjectTypeManager.getStandardCode(objectMaterialIds); dcp.setComputedSimplifiedObjectType(value); } ===================================== services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidationActivitySeineDataContext.java ===================================== --- a/services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidationActivitySeineDataContext.java +++ b/services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/ConsolidationActivitySeineDataContext.java @@ -72,6 +72,8 @@ class ConsolidationActivitySeineDataContext { ConsolidateActivitySeineDataResultBuilder resultBuilder; + SimplifiedObjectTypeManager simplifiedObjectTypeManager; + public Ocean getOcean() { return tripSeine.getOcean(); } ===================================== services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/SimplifiedObjectTypeManager.java ===================================== --- /dev/null +++ b/services-topia/src/main/java/fr/ird/observe/services/topia/service/actions/consolidate/SimplifiedObjectTypeManager.java @@ -0,0 +1,82 @@ +package fr.ird.observe.services.topia.service.actions.consolidate; + +/*- + * #%L + * ObServe :: Services ToPIA Implementation + * %% + * Copyright (C) 2008 - 2017 IRD, Code Lutin, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableMap; +import fr.ird.observe.entities.referentiel.seine.SimplifiedObjectTypeNode; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Created by tchemit on 02/08/17. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 7.0 + */ +class SimplifiedObjectTypeManager { + + + // For each object material, get his simplified object type node + private final ImmutableMap<String, SimplifiedObjectTypeNode> mapping; + + SimplifiedObjectTypeManager(ImmutableMap<String, SimplifiedObjectTypeNode> mapping) { + this.mapping = mapping; + } + + SimplifiedObjectTypeNode getNodeForStandardCode(String standardCode) { + return mapping.values().stream().filter(n -> n.getStandardCode().equals(standardCode)).findFirst().orElseThrow(IllegalArgumentException::new); + } + + String getStandardCode(Set<String> objectMaterialIds) { + List<SimplifiedObjectTypeNode> availableNodes = new LinkedList<>(); + for (String objectMaterialId : objectMaterialIds) { + availableNodes.add(mapping.get(objectMaterialId)); + } + // get highest level first + availableNodes.sort(Comparator.comparing(SimplifiedObjectTypeNode::getLevel).reversed()); + + // remove from available nodes, all nodes in the path of other ones + List<SimplifiedObjectTypeNode> mainNodes = new LinkedList<>(availableNodes); + + for (SimplifiedObjectTypeNode availableNode : availableNodes) { + if (mainNodes.contains(availableNode)) { + mainNodes.removeAll(availableNode.getPathsToRoot(false)); + } + } + + // now each node is on a different path, get the shared common ancestor + Iterator<SimplifiedObjectTypeNode> iterator = mainNodes.iterator(); + SimplifiedObjectTypeNode result = iterator.next(); + while (iterator.hasNext()) { + result = result.getSharedAncestor(iterator.next()); + } + Objects.requireNonNull(result); + return result.getStandardCode(); + } + + +} ===================================== services-topia/src/test/java/fr/ird/observe/services/topia/service/actions/consolidate/SimplifiedObjectTypeManagerTest.java ===================================== --- /dev/null +++ b/services-topia/src/test/java/fr/ird/observe/services/topia/service/actions/consolidate/SimplifiedObjectTypeManagerTest.java @@ -0,0 +1,87 @@ +package fr.ird.observe.services.topia.service.actions.consolidate; + +/*- + * #%L + * ObServe :: Services ToPIA Implementation + * %% + * Copyright (C) 2008 - 2017 IRD, Code Lutin, Ultreia.io + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/gpl-3.0.html>. + * #L% + */ + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import fr.ird.observe.entities.referentiel.seine.SimplifiedObjectTypeNode; +import fr.ird.observe.persistence.ObserveTopiaPersistenceContext; +import fr.ird.observe.services.topia.service.AbstractServiceTopiaTest; +import fr.ird.observe.test.DatabaseName; +import fr.ird.observe.test.spi.DatabaseNameConfiguration; +import java.util.stream.Collectors; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by tchemit on 02/08/17. + * + * @author Tony Chemit - dev@tchemit.fr + */ +@DatabaseNameConfiguration(DatabaseName.referentiel) +public class SimplifiedObjectTypeManagerTest extends AbstractServiceTopiaTest { + + private SimplifiedObjectTypeManager simplifiedObjectTypeManager; + + @Before + public void setUp() throws Exception { + try (ObserveTopiaPersistenceContext persistenceContext = topiaTestMethodResource.newPersistenceContext()) { + + ImmutableMap<String, SimplifiedObjectTypeNode> materialMapping = persistenceContext.getObjectMaterialDao().createMaterialMapping(); + simplifiedObjectTypeManager = new SimplifiedObjectTypeManager(materialMapping); + } + + + } + + @Test + public void getStandardCode() { + + SimplifiedObjectTypeNode fob = simplifiedObjectTypeManager.getNodeForStandardCode("FOB"); + SimplifiedObjectTypeNode fad = simplifiedObjectTypeManager.getNodeForStandardCode("FAD"); + SimplifiedObjectTypeNode dfad = simplifiedObjectTypeManager.getNodeForStandardCode("DFAD"); + SimplifiedObjectTypeNode log = simplifiedObjectTypeManager.getNodeForStandardCode("LOG"); + SimplifiedObjectTypeNode alog = simplifiedObjectTypeManager.getNodeForStandardCode("ALOG"); + SimplifiedObjectTypeNode nlog = simplifiedObjectTypeManager.getNodeForStandardCode("NLOG"); + SimplifiedObjectTypeNode vnlog = simplifiedObjectTypeManager.getNodeForStandardCode("VNLOG"); + SimplifiedObjectTypeNode falog = simplifiedObjectTypeManager.getNodeForStandardCode("FALOG"); + SimplifiedObjectTypeNode halog = simplifiedObjectTypeManager.getNodeForStandardCode("HALOG"); + + assertStandardCode(fob, fob); + assertStandardCode(fad, fob, fad); + assertStandardCode(dfad, fad, dfad, dfad); + assertStandardCode(falog, log, alog, falog); + assertStandardCode(fob, dfad, log, nlog); + assertStandardCode(falog, alog, falog, falog); + assertStandardCode(alog, alog, falog, halog); + assertStandardCode(log, falog, vnlog); + + } + + private void assertStandardCode(SimplifiedObjectTypeNode expectedStandardCode, SimplifiedObjectTypeNode... objectMaterialIds) { + String actualStandardCode = simplifiedObjectTypeManager.getStandardCode(ImmutableSet.copyOf(objectMaterialIds).stream().map(SimplifiedObjectTypeNode::getId).collect(Collectors.toSet())); + Assert.assertEquals(expectedStandardCode.getStandardCode(), actualStandardCode); + } + +} View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/commit/7260558999fee85d92fd57907b89... --- View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/commit/7260558999fee85d92fd57907b89... You're receiving this email because of your account on gitlab.com.