...
 
Commits (7)
## Sprint 91 - v3.9.9
- Pas de mise à jour de modèle
## Sprint 90 - v3.9.8 ## Sprint 90 - v3.9.8
- Pas de mise à jour de modèle - Pas de mise à jour de modèle
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<groupId>fr.ifremer.reefdb</groupId> <groupId>fr.ifremer.reefdb</groupId>
<artifactId>reefdb</artifactId> <artifactId>reefdb</artifactId>
<version>3.9.8</version> <version>3.9.9</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Reef DB</name> <name>Reef DB</name>
...@@ -171,7 +171,7 @@ ...@@ -171,7 +171,7 @@
<maven.compiler.debug>true</maven.compiler.debug> <maven.compiler.debug>true</maven.compiler.debug>
<!-- Quadrige3 Core version --> <!-- Quadrige3 Core version -->
<quadrige3-core.version>3.6.13</quadrige3-core.version> <quadrige3-core.version>3.6.14</quadrige3-core.version>
<!-- Last ReefDb launcher version --> <!-- Last ReefDb launcher version -->
<launcherVersion>3.0.3</launcherVersion> <launcherVersion>3.0.3</launcherVersion>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>fr.ifremer.reefdb</groupId> <groupId>fr.ifremer.reefdb</groupId>
<artifactId>reefdb</artifactId> <artifactId>reefdb</artifactId>
<version>3.9.8</version> <version>3.9.9</version>
</parent> </parent>
<artifactId>reefdb-core</artifactId> <artifactId>reefdb-core</artifactId>
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
# Please fill the missing licenses for dependencies : # Please fill the missing licenses for dependencies :
# #
# #
#Mon Mar 30 15:21:02 CEST 2020 #Tue Apr 07 17:42:52 CEST 2020
com.oracle--ojdbc7--12.1.0.2.0=OTN license com.oracle--ojdbc7--12.1.0.2.0=OTN license
commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0
dom4j--dom4j--1.6.1=BSD License dom4j--dom4j--1.6.1=BSD License
......
...@@ -24,11 +24,14 @@ package fr.ifremer.reefdb.dto; ...@@ -24,11 +24,14 @@ package fr.ifremer.reefdb.dto;
*/ */
import fr.ifremer.quadrige3.core.dao.referential.UnitId; import fr.ifremer.quadrige3.core.dao.referential.UnitId;
import fr.ifremer.reefdb.dto.data.measurement.MeasurementDTO;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author ludovic.pecquot@e-is.pro on 13/04/2017. * @author ludovic.pecquot@e-is.pro on 13/04/2017.
...@@ -54,4 +57,38 @@ public class ReefDbBeansTest { ...@@ -54,4 +57,38 @@ public class ReefDbBeansTest {
Assert.assertEquals(60, result.intValue()); Assert.assertEquals(60, result.intValue());
} }
@Test
public void testReduce() {
List<MeasurementDTO> beans = new ArrayList<>();
{
MeasurementDTO bean = ReefDbBeanFactory.newMeasurementDTO();
bean.setId(1);
beans.add(bean);
}
{
MeasurementDTO bean = ReefDbBeanFactory.newMeasurementDTO();
bean.setId(-2);
beans.add(bean);
}
{
MeasurementDTO bean = ReefDbBeanFactory.newMeasurementDTO();
bean.setId(null);
beans.add(bean);
}
{
MeasurementDTO bean = ReefDbBeanFactory.newMeasurementDTO();
bean.setId(4);
beans.add(bean);
}
int minNegativeId = beans.stream()
.filter(measurementDTO -> measurementDTO.getId() != null)
.mapToInt(MeasurementDTO::getId)
.min().orElse(0);
Assert.assertEquals(-2, minNegativeId);
}
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>fr.ifremer.reefdb</groupId> <groupId>fr.ifremer.reefdb</groupId>
<artifactId>reefdb</artifactId> <artifactId>reefdb</artifactId>
<version>3.9.8</version> <version>3.9.9</version>
</parent> </parent>
<artifactId>reefdb-ui-swing</artifactId> <artifactId>reefdb-ui-swing</artifactId>
......
...@@ -82,10 +82,13 @@ public class SaveAction extends AbstractReefDbSaveAction<ObservationUIModel, Obs ...@@ -82,10 +82,13 @@ public class SaveAction extends AbstractReefDbSaveAction<ObservationUIModel, Obs
return false; return false;
} }
// TODO Must save partial models from tabs // Save partial models from tabs
getUI().getSurveyDetailsTabUI().getHandler().saveActualModel(); getUI().getSurveyDetailsTabUI().getHandler().save();
// getUI().getPrelevementGeneralTabUI().getHandler().saveActualModel(); getUI().getPhotosTabUI().getHandler().save();
getUI().getPhotosTabUI().getHandler().saveActualModel();
// Save and control measurements tabs (Mantis #51725)
getUI().getSurveyMeasurementsTabUI().getHandler().save();
getUI().getOperationMeasurementsTabUI().getHandler().save();
return true; return true;
} }
...@@ -142,11 +145,11 @@ public class SaveAction extends AbstractReefDbSaveAction<ObservationUIModel, Obs ...@@ -142,11 +145,11 @@ public class SaveAction extends AbstractReefDbSaveAction<ObservationUIModel, Obs
public void postSuccessAction() { public void postSuccessAction() {
super.postSuccessAction(); super.postSuccessAction();
getHandler().refreshModels();
// show error messages // show error messages
showControlResult(controlMessages, false); showControlResult(controlMessages, false);
getHandler().refreshModels();
// Postpone model modify state (Mantis #50915) // Postpone model modify state (Mantis #50915)
SwingUtilities.invokeLater(() -> getModel().setModify(false)); SwingUtilities.invokeLater(() -> getModel().setModify(false));
......
...@@ -23,6 +23,7 @@ package fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement; ...@@ -23,6 +23,7 @@ package fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement;
* #L% * #L%
*/ */
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import fr.ifremer.quadrige3.ui.swing.table.SwingTable; import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
...@@ -56,10 +57,7 @@ import org.nuiton.jaxx.application.swing.tab.TabHandler; ...@@ -56,10 +57,7 @@ import org.nuiton.jaxx.application.swing.tab.TabHandler;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Comparator; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.nuiton.i18n.I18n.t; import static org.nuiton.i18n.I18n.t;
...@@ -114,16 +112,16 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -114,16 +112,16 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
// Initialisation des prelevements // Initialisation des prelevements
initBeanFilterableComboBox( initBeanFilterableComboBox(
getUI().getSelectionPrelevementsCombo(), getUI().getSelectionPrelevementsCombo(),
getModel().getSamplings(), getModel().getSamplingOperations(),
getModel().getSampling(), getModel().getSampling(),
DecoratorService.CONCAT); DecoratorService.CONCAT);
// Initialisation des groupe de taxons // Initialisation des groupe de taxons
initBeanFilterableComboBox( initBeanFilterableComboBox(
getUI().getSelectionGroupeTaxonCombo(), getUI().getSelectionGroupeTaxonCombo(),
null, null,
null, DecoratorService.NAME); null, DecoratorService.NAME);
getUI().getSelectionGroupeTaxonCombo().setActionEnabled(getContext().getDataContext().isContextFiltered(FilterTypeValues.TAXON_GROUP)); getUI().getSelectionGroupeTaxonCombo().setActionEnabled(getContext().getDataContext().isContextFiltered(FilterTypeValues.TAXON_GROUP));
getUI().getSelectionGroupeTaxonCombo().setActionListener(e -> { getUI().getSelectionGroupeTaxonCombo().setActionListener(e -> {
...@@ -135,9 +133,9 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -135,9 +133,9 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
// Intialisation des taxons // Intialisation des taxons
initBeanFilterableComboBox( initBeanFilterableComboBox(
getUI().getSelectionTaxonCombo(), getUI().getSelectionTaxonCombo(),
null, null,
null); null);
getUI().getSelectionTaxonCombo().setActionEnabled(getContext().getDataContext().isContextFiltered(FilterTypeValues.TAXON)); getUI().getSelectionTaxonCombo().setActionEnabled(getContext().getDataContext().isContextFiltered(FilterTypeValues.TAXON));
getUI().getSelectionTaxonCombo().setActionListener(e -> { getUI().getSelectionTaxonCombo().setActionListener(e -> {
...@@ -180,17 +178,37 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -180,17 +178,37 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
getModel().setAdjusting(false); getModel().setAdjusting(false);
}); });
PropertyChangeListener loadListener = new PropertyChangeListener() {
Map<String, Boolean> eventMap = new HashMap<>(ImmutableMap.of(
OperationMeasurementsUngroupedTableUIModel.EVENT_MEASUREMENTS_LOADED, false,
OperationMeasurementsGroupedTableUIModel.EVENT_INDIVIDUAL_MEASUREMENTS_LOADED, false
));
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (isEventComplete(evt.getPropertyName())) {
// detect if the triplet of PMFM for transition length
detectPmfmForTransitionCalculator();
detectPitPmfmForGridInitialization();
resetEventMap();
}
}
private boolean isEventComplete(String propertyName) {
if (eventMap.containsKey(propertyName))
eventMap.put(propertyName, true);
return eventMap.values().stream().allMatch(aBoolean -> aBoolean);
}
private void resetEventMap() {
eventMap.keySet().forEach(key -> eventMap.put(key, false));
}
};
// add listeners on table models // add listeners on table models
getModel().getUngroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsUngroupedTableUIModel.EVENT_MEASUREMENTS_LOADED, evt -> { getModel().getUngroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsUngroupedTableUIModel.EVENT_MEASUREMENTS_LOADED, loadListener);
// detect if the triplet of PMFM for transition length getModel().getGroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsGroupedTableUIModel.EVENT_INDIVIDUAL_MEASUREMENTS_LOADED, loadListener);
detectPmfmForTransitionCalculator();
detectPitPmfmForGridInitialization();
});
getModel().getGroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsGroupedTableUIModel.EVENT_MEASUREMENTS_LOADED, evt -> {
// detect if the triplet of PMFM for transition length
detectPmfmForTransitionCalculator();
detectPitPmfmForGridInitialization();
});
// Add listeners on PROPERTY_ROWS_IN_ERROR to catch modifications and revalidate // Add listeners on PROPERTY_ROWS_IN_ERROR to catch modifications and revalidate
getModel().getUngroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsUngroupedTableUIModel.PROPERTY_ROWS_IN_ERROR, evt -> { getModel().getUngroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsUngroupedTableUIModel.PROPERTY_ROWS_IN_ERROR, evt -> {
...@@ -218,7 +236,7 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -218,7 +236,7 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
getUI().getSelectionGroupeTaxonCombo().setActionEnabled(!forceNoFilter && getContext().getDataContext().isContextFiltered(FilterTypeValues.TAXON_GROUP)); getUI().getSelectionGroupeTaxonCombo().setActionEnabled(!forceNoFilter && getContext().getDataContext().isContextFiltered(FilterTypeValues.TAXON_GROUP));
List<TaxonGroupDTO> taxonGroups = getModel().getObservationUIHandler().getAvailableTaxonGroups(taxon,forceNoFilter); List<TaxonGroupDTO> taxonGroups = getModel().getObservationUIHandler().getAvailableTaxonGroups(taxon, forceNoFilter);
getUI().getSelectionGroupeTaxonCombo().setData(taxonGroups); getUI().getSelectionGroupeTaxonCombo().setData(taxonGroups);
...@@ -287,7 +305,7 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -287,7 +305,7 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
List<PmfmStrategyDTO> pmfmStrategies = ReefDbBeans.filterCollection(survey.getPmfmStrategies(), input -> input != null && input.isSampling()); List<PmfmStrategyDTO> pmfmStrategies = ReefDbBeans.filterCollection(survey.getPmfmStrategies(), input -> input != null && input.isSampling());
// list available samplings // list available samplings
getUI().getSelectionPrelevementsCombo().setData(getModel().getSamplings()); getUI().getSelectionPrelevementsCombo().setData(getModel().getSamplingOperations());
// Load ungrouped data (up table) // Load ungrouped data (up table)
{ {
...@@ -301,9 +319,9 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -301,9 +319,9 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
} }
// Load other Pmfms in sampling operations // Load other Pmfms in sampling operations
if (CollectionUtils.isNotEmpty(getModel().getSamplings())) { if (CollectionUtils.isNotEmpty(getModel().getSamplingOperations())) {
// populate pmfms from strategy to sampling operation and vice versa // populate pmfms from strategy to sampling operation and vice versa
for (SamplingOperationDTO samplingOperation : getModel().getSamplings()) { for (SamplingOperationDTO samplingOperation : getModel().getSamplingOperations()) {
ReefDbBeans.fillListsEachOther(samplingOperation.getPmfms(), pmfms); ReefDbBeans.fillListsEachOther(samplingOperation.getPmfms(), pmfms);
} }
} }
...@@ -330,9 +348,9 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -330,9 +348,9 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
} }
// Load other Pmfms in sampling operations // Load other Pmfms in sampling operations
if (CollectionUtils.isNotEmpty(getModel().getSamplings())) { if (CollectionUtils.isNotEmpty(getModel().getSamplingOperations())) {
// populate pmfms from strategy to sampling operation and vice versa // populate pmfms from strategy to sampling operation and vice versa
for (SamplingOperationDTO samplingOperation : getModel().getSamplings()) { for (SamplingOperationDTO samplingOperation : getModel().getSamplingOperations()) {
ReefDbBeans.fillListsEachOther(samplingOperation.getIndividualPmfms(), individualPmfms); ReefDbBeans.fillListsEachOther(samplingOperation.getIndividualPmfms(), individualPmfms);
} }
} }
...@@ -345,8 +363,8 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -345,8 +363,8 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
} }
//update selected sampling //update selected sampling
if (getContext().getSelectedSamplingOperationId() != null && getModel().getSamplings() != null) { if (getContext().getSelectedSamplingOperationId() != null && getModel().getSamplingOperations() != null) {
for (SamplingOperationDTO samplingOperation : getModel().getSamplings()) { for (SamplingOperationDTO samplingOperation : getModel().getSamplingOperations()) {
if (getContext().getSelectedSamplingOperationId().equals(samplingOperation.getId())) { if (getContext().getSelectedSamplingOperationId().equals(samplingOperation.getId())) {
getModel().setSampling(samplingOperation); getModel().setSampling(samplingOperation);
break; break;
...@@ -394,13 +412,13 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -394,13 +412,13 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
private void detectPmfmForTransitionCalculator() { private void detectPmfmForTransitionCalculator() {
if (CollectionUtils.isEmpty(getModel().getUngroupedTableUIModel().getPmfmColumns()) if (CollectionUtils.isEmpty(getModel().getUngroupedTableUIModel().getPmfmColumns())
|| CollectionUtils.isEmpty(getModel().getGroupedTableUIModel().getPmfmColumns())) { || CollectionUtils.isEmpty(getModel().getGroupedTableUIModel().getPmfmColumns())) {
// both tables must have pmfm columns // both tables must have pmfm columns
return; return;
} }
List<Integer[]> transitionLengthPmfmTriplets = getConfig().getCalculatedTransitionLengthPmfmTriplets(); List<Integer[]> transitionLengthPmfmTriplets = getConfig().getCalculatedTransitionLengthPmfmTriplets();
for (Integer[] transitionLengthPmfmTriplet: transitionLengthPmfmTriplets) { for (Integer[] transitionLengthPmfmTriplet : transitionLengthPmfmTriplets) {
int transitionLengthPmfmId = transitionLengthPmfmTriplet[0]; int transitionLengthPmfmId = transitionLengthPmfmTriplet[0];
int startPositionPmfmId = transitionLengthPmfmTriplet[1]; int startPositionPmfmId = transitionLengthPmfmTriplet[1];
...@@ -435,7 +453,6 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -435,7 +453,6 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
getModel().getGroupedTableUIModel().setCalculatedLengthEndPositionPmfmId(endPositionPmfmId); getModel().getGroupedTableUIModel().setCalculatedLengthEndPositionPmfmId(endPositionPmfmId);
getModel().getGroupedTableUIModel().setCalculatedLengthTransitionPmfmId(transitionLengthPmfmId); getModel().getGroupedTableUIModel().setCalculatedLengthTransitionPmfmId(transitionLengthPmfmId);
// set the transition length column non editable // set the transition length column non editable
transitionLengthColumn.setEditable(false); transitionLengthColumn.setEditable(false);
transitionLengthColumn.getPmfmIdentifier().setNotMandatory(); transitionLengthColumn.getPmfmIdentifier().setNotMandatory();
...@@ -450,17 +467,22 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -450,17 +467,22 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
map.put(ungroupedRow.getName(), (BigDecimal) startPositionColumn.getPmfmIdentifier().getValue(ungroupedRow)); map.put(ungroupedRow.getName(), (BigDecimal) startPositionColumn.getPmfmIdentifier().getValue(ungroupedRow));
} }
// Remove previous calculator
if (transitionLengthCalculator != null) {
getModel().getGroupedTableUIModel().removePropertyChangeListener(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, transitionLengthCalculator);
}
// create calculator // create calculator
TransitionLengthCalculator calculator = new TransitionLengthCalculator(map, transitionLengthCalculator = new TransitionLengthCalculator(map,
startPositionColumn.getPmfmIdentifier(), startPositionColumn.getPmfmIdentifier(),
endPositionColumn.getPmfmIdentifier(), endPositionColumn.getPmfmIdentifier(),
transitionLengthColumn.getPmfmIdentifier()); transitionLengthColumn.getPmfmIdentifier());
startPositionColumn.getPmfmIdentifier().addPropertyChangeListener(calculator); startPositionColumn.getPmfmIdentifier().addPropertyChangeListener(transitionLengthCalculator);
endPositionColumn.getPmfmIdentifier().addPropertyChangeListener(calculator); endPositionColumn.getPmfmIdentifier().addPropertyChangeListener(transitionLengthCalculator);
// add also property change listener on sampling operation column (when a sampling operation in a row has changed) (Mantis #0027395) // add also property change listener on sampling operation column (when a sampling operation in a row has changed) (Mantis #0027395)
getModel().getGroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, calculator); getModel().getGroupedTableUIModel().addPropertyChangeListener(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, transitionLengthCalculator);
} }
} }
...@@ -533,6 +555,8 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -533,6 +555,8 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
return false; return false;
} }
private TransitionLengthCalculator transitionLengthCalculator;
private class TransitionLengthCalculator implements PropertyChangeListener { private class TransitionLengthCalculator implements PropertyChangeListener {
private final Map<String, BigDecimal> startPositionMap; private final Map<String, BigDecimal> startPositionMap;
...@@ -625,4 +649,25 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O ...@@ -625,4 +649,25 @@ public class OperationMeasurementsTabUIHandler extends AbstractReefDbUIHandler<O
getUI().getGroupedTable().getOperationGroupedMeasurementTable().repaint(); getUI().getGroupedTable().getOperationGroupedMeasurementTable().repaint();
} }
} }
public void save() {
try {
// Disable filter
getModel().getUngroupedTableUIModel().setSamplingFilter(null);
getModel().getGroupedTableUIModel().setMeasurementFilter(new MeasurementsFilter());
// save ungrouped measurements
getUI().getUngroupedTable().getHandler().save();
// save grouped measurements
getUI().getGroupedTable().getHandler().save();
} finally {
doSearch();
}
}
} }
...@@ -122,11 +122,11 @@ public class OperationMeasurementsTabUIModel extends AbstractEmptyUIModel<Operat ...@@ -122,11 +122,11 @@ public class OperationMeasurementsTabUIModel extends AbstractEmptyUIModel<Operat
} }
/** /**
* <p>getSamplings.</p> * <p>getSamplingOperations.</p>
* *
* @return a {@link java.util.List} object. * @return a {@link java.util.List} object.
*/ */
public List<SamplingOperationDTO> getSamplings() { public List<SamplingOperationDTO> getSamplingOperations() {
return observationModel == null ? null : (List<SamplingOperationDTO>) observationModel.getSamplingOperations(); return observationModel == null ? null : (List<SamplingOperationDTO>) observationModel.getSamplingOperations();
} }
......
...@@ -24,7 +24,6 @@ package fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement.gro ...@@ -24,7 +24,6 @@ package fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement.gro
*/ */
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import fr.ifremer.quadrige3.core.dao.technical.AlphanumericComparator; import fr.ifremer.quadrige3.core.dao.technical.AlphanumericComparator;
import fr.ifremer.quadrige3.ui.swing.table.ColumnIdentifier; import fr.ifremer.quadrige3.ui.swing.table.ColumnIdentifier;
import fr.ifremer.quadrige3.ui.swing.table.SwingTable; import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
...@@ -51,8 +50,6 @@ import javax.swing.RowFilter; ...@@ -51,8 +50,6 @@ import javax.swing.RowFilter;
import javax.swing.border.Border; import javax.swing.border.Border;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
...@@ -226,23 +223,17 @@ public class OperationMeasurementsGroupedTableUIHandler ...@@ -226,23 +223,17 @@ public class OperationMeasurementsGroupedTableUIHandler
// remove measurement from old sampling // remove measurement from old sampling
if (oldValue != null) { if (oldValue != null) {
SamplingOperationDTO oldSamplingOperation = (SamplingOperationDTO) oldValue; SamplingOperationDTO oldSamplingOperation = (SamplingOperationDTO) oldValue;
oldSamplingOperation.removeAllIndividualMeasurements(row.getIndividualMeasurements());
oldSamplingOperation.setDirty(true);
resetIndividualMeasurementIds(row); resetIndividualMeasurementIds(row);
setDirty(oldSamplingOperation);
} }
// recalculate individual id // recalculate individual id
if (newValue != null) { if (newValue != null) {
// affect new sampling operation now // affect new sampling operation now
row.setSamplingOperation((SamplingOperationDTO) newValue); SamplingOperationDTO newSamplingOperation = (SamplingOperationDTO) newValue;
row.setSamplingOperation(newSamplingOperation);
// calculate new individual ids setDirty(newSamplingOperation);
calculateIndividualIds(row);
// fire event for parent listener
getModel().firePropertyChanged(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, null, newValue);
} }
} }
...@@ -250,36 +241,6 @@ public class OperationMeasurementsGroupedTableUIHandler ...@@ -250,36 +241,6 @@ public class OperationMeasurementsGroupedTableUIHandler
super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue); super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
} }
@Override
protected void onDuplicatedRowAdded(OperationMeasurementsGroupedRowModel row) {
// send update event on sampling operation
if (row.getSamplingOperation() != null) {
getModel().firePropertyChanged(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, null, row.getSamplingOperation());
}
}
@Override
protected void resetIndividualMeasurementIds(OperationMeasurementsGroupedRowModel row) {
// before, remove those measurements from sampling operation
if (row.getSamplingOperation() != null) {
row.getSamplingOperation().removeAllIndividualMeasurements(row.getIndividualMeasurements());
}
super.resetIndividualMeasurementIds(row);
}
/**
* the predicate test if the row is attached to the bean (=SamplingOperationDTO)
*
* @param bean the bean
* @return the predicate for sampling operation
*/
@Override
protected Predicate<? super OperationMeasurementsGroupedRowModel> getRowForBeanPredicate(MeasurementAware bean) {
return (Predicate<OperationMeasurementsGroupedRowModel>) row -> Objects.equals(bean, row.getSamplingOperation());
}
@Override @Override
protected MeasurementAware getMeasurementAwareModelForRow(OperationMeasurementsGroupedRowModel row) { protected MeasurementAware getMeasurementAwareModelForRow(OperationMeasurementsGroupedRowModel row) {
return row.getSamplingOperation(); return row.getSamplingOperation();
...@@ -381,30 +342,15 @@ public class OperationMeasurementsGroupedTableUIHandler ...@@ -381,30 +342,15 @@ public class OperationMeasurementsGroupedTableUIHandler
} }
@Override @Override
protected void removeIndividualMeasurements(List<MeasurementDTO> measurementToDelete) { protected boolean isMeasurementNotEmpty(MeasurementDTO measurement) {
return !measurement.getPmfm().getId().equals(getModel().getPitTransitionLengthPmfmId()) && super.isMeasurementNotEmpty(measurement);
// updated sampling operation
Set<SamplingOperationDTO> updatedSamplingOperations = Sets.newHashSet();
// Remove from model
for (MeasurementDTO deletedMeasurement : measurementToDelete) {
if (deletedMeasurement.getSamplingOperation() != null) {
deletedMeasurement.getSamplingOperation().removeIndividualMeasurements(deletedMeasurement);
updatedSamplingOperations.add(deletedMeasurement.getSamplingOperation());
}
}
getModel().setModify(true);
// final update
for (SamplingOperationDTO updatedSamplingOperation : updatedSamplingOperations) {
updatedSamplingOperation.setDirty(true);
getModel().firePropertyChanged(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, null, updatedSamplingOperation);
}
} }
@Override @Override
protected boolean isMeasurementNotEmpty(MeasurementDTO measurement) { protected void setDirty(MeasurementAware bean) {
return !measurement.getPmfm().getId().equals(getModel().getPitTransitionLengthPmfmId()) && super.isMeasurementNotEmpty(measurement); super.setDirty(bean);
if (bean instanceof SamplingOperationDTO)
getModel().firePropertyChanged(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, null, bean);
} }
/** /**
...@@ -440,16 +386,11 @@ public class OperationMeasurementsGroupedTableUIHandler ...@@ -440,16 +386,11 @@ public class OperationMeasurementsGroupedTableUIHandler
List<OperationMeasurementsGroupedRowModel> rows = Lists.newArrayList(); List<OperationMeasurementsGroupedRowModel> rows = Lists.newArrayList();
for (SamplingOperationDTO samplingOperation : initModel.getResultMap().keySet()) { for (SamplingOperationDTO samplingOperation : initModel.getResultMap().keySet()) {
AtomicInteger individualId = new AtomicInteger();
for (Integer transition : initModel.getResultMap().get(samplingOperation)) { for (Integer transition : initModel.getResultMap().get(samplingOperation)) {
// Compute next individual id
incrementNextIndividualId(samplingOperation, individualId);
// Initialize the row // Initialize the row
OperationMeasurementsGroupedRowModel row = createNewRow(false, samplingOperation); OperationMeasurementsGroupedRowModel row = createNewRow(false, samplingOperation);
// Set the individualId
row.setIndividualId(individualId.get());
// Affect individual pmfms from parent model // Affect individual pmfms from parent model
row.setIndividualPmfms(new ArrayList<>(getModel().getPmfms())); row.setIndividualPmfms(new ArrayList<>(getModel().getPmfms()));
// Create empty measurements // Create empty measurements
...@@ -459,13 +400,12 @@ public class OperationMeasurementsGroupedTableUIHandler ...@@ -459,13 +400,12 @@ public class OperationMeasurementsGroupedTableUIHandler
if (measurement == null) { if (measurement == null) {
throw new ReefDbTechnicalException("No transition measurement found"); throw new ReefDbTechnicalException("No transition measurement found");
} }
// Set its value and individualId // Set its value
measurement.setNumericalValue(BigDecimal.valueOf(transition)); measurement.setNumericalValue(BigDecimal.valueOf(transition));
measurement.setIndividualId(individualId.get());
row.setValid(true); row.setValid(true);
rows.add(row); rows.add(row);
} }
samplingOperation.setDirty(true); setDirty(samplingOperation);
} }
resetCellEditors(); resetCellEditors();
...@@ -474,6 +414,20 @@ public class OperationMeasurementsGroupedTableUIHandler ...@@ -474,6 +414,20 @@ public class OperationMeasurementsGroupedTableUIHandler
} }
} }
@Override
protected boolean isRowToSave(OperationMeasurementsGroupedRowModel row) {
boolean toSave = super.isRowToSave(row);
if (toSave && getModel().getPitTransitionLengthPmfmId() != null) {
// If this row has been initialized but nothing else has been set, it can be ignored
Set<Integer> pmfmIds = ReefDbBeans.getPmfmIdsOfNonEmptyIndividualMeasurements(row);
pmfmIds.remove(getModel().getPitTransitionLengthPmfmId());
toSave = !pmfmIds.isEmpty() || row.hasTaxonInformation();
}
return toSave;
}
public void editSelectedMeasurements() { public void editSelectedMeasurements() {
OperationMeasurementsMultiEditUI editUI = new OperationMeasurementsMultiEditUI(getUI()); OperationMeasurementsMultiEditUI editUI = new OperationMeasurementsMultiEditUI(getUI());
......
...@@ -31,6 +31,7 @@ import fr.ifremer.reefdb.dto.data.measurement.MeasurementDTO; ...@@ -31,6 +31,7 @@ import fr.ifremer.reefdb.dto.data.measurement.MeasurementDTO;
import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO; import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO;
import fr.ifremer.reefdb.dto.enums.FilterTypeValues; import fr.ifremer.reefdb.dto.enums.FilterTypeValues;
import fr.ifremer.reefdb.dto.referential.DepartmentDTO; import fr.ifremer.reefdb.dto.referential.DepartmentDTO;
import fr.ifremer.reefdb.service.ReefDbTechnicalException;
import fr.ifremer.reefdb.ui.swing.util.table.AbstractReefDbTableUIHandler; import fr.ifremer.reefdb.ui.swing.util.table.AbstractReefDbTableUIHandler;
import jaxx.runtime.SwingUtil; import jaxx.runtime.SwingUtil;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
...@@ -38,6 +39,8 @@ import org.jdesktop.swingx.table.TableColumnExt; ...@@ -38,6 +39,8 @@ import org.jdesktop.swingx.table.TableColumnExt;
import javax.swing.RowFilter; import javax.swing.RowFilter;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import static org.nuiton.i18n.I18n.t; import static org.nuiton.i18n.I18n.t;
...@@ -115,7 +118,7 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -115,7 +118,7 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
private void updateDepartmentCellEditor(boolean forceNoFilter) { private void updateDepartmentCellEditor(boolean forceNoFilter) {
departmentCellEditor.getCombo().setActionEnabled(!forceNoFilter departmentCellEditor.getCombo().setActionEnabled(!forceNoFilter
&& getContext().getDataContext().isContextFiltered(FilterTypeValues.DEPARTMENT)); && getContext().getDataContext().isContextFiltered(FilterTypeValues.DEPARTMENT));
departmentCellEditor.getCombo().setData(getContext().getObservationService().getAvailableDepartments(forceNoFilter)); departmentCellEditor.getCombo().setData(getContext().getObservationService().getAvailableDepartments(forceNoFilter));
} }
...@@ -141,16 +144,16 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -141,16 +144,16 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
uninstallSaveTableStateListener(); uninstallSaveTableStateListener();
addPmfmColumns( addPmfmColumns(
getModel().getPmfms(), getModel().getPmfms(),
SamplingOperationDTO.PROPERTY_PMFMS, SamplingOperationDTO.PROPERTY_PMFMS,
DecoratorService.NAME_WITH_UNIT); // insert at the end DecoratorService.NAME_WITH_UNIT); // insert at the end
boolean notEmpty = CollectionUtils.isNotEmpty(getModel().getPmfms()); boolean notEmpty = CollectionUtils.isNotEmpty(getModel().getPmfms());
// tell the table model is editable or not // tell the table model is editable or not
getTableModel().setReadOnly(!getModel().getSurvey().isEditable()); getTableModel().setReadOnly(!getModel().getSurvey().isEditable());
getModel().setBeans(getModel().getSamplings()); getModel().setBeans(getModel().getSamplingOperations());
if (notEmpty) { if (notEmpty) {
for (OperationMeasurementsUngroupedRowModel row : getModel().getRows()) { for (OperationMeasurementsUngroupedRowModel row : getModel().getRows()) {
// set analyst from first non null measurement // set analyst from first non null measurement
...@@ -159,8 +162,8 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -159,8 +162,8 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
row.setAnalyst(measurementFound.get().getAnalyst()); row.setAnalyst(measurementFound.get().getAnalyst());
} else { } else {
row.setAnalyst(getContext().getProgramStrategyService().getAnalysisDepartmentOfAppliedStrategyBySurvey( row.setAnalyst(getContext().getProgramStrategyService().getAnalysisDepartmentOfAppliedStrategyBySurvey(
getModel().getSurvey(), getModel().getSurvey(),
getModel().getPmfms() getModel().getPmfms()
)); ));
} }
} }
...@@ -197,7 +200,7 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -197,7 +200,7 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
@Override @Override
public boolean include(Entry<? extends OperationMeasurementsUngroupedTableModel, ? extends Integer> entry) { public boolean include(Entry<? extends OperationMeasurementsUngroupedTableModel, ? extends Integer> entry) {
return getModel().getSamplingFilter() == null return getModel().getSamplingFilter() == null
|| getModel().getSamplingFilter().getName().equals(entry.getValue(getTable().getColumnExt(OperationMeasurementsUngroupedTableModel.NAME).getModelIndex())); || getModel().getSamplingFilter().getName().equals(entry.getValue(getTable().getColumnExt(OperationMeasurementsUngroupedTableModel.NAME).getModelIndex()));
} }
}); });
} }
...@@ -216,21 +219,26 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -216,21 +219,26 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue); super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
// save modifications to parent model row.setDirty(true);
// be careful, table beans can be filtered, so use detection to save measurements
for (SamplingOperationDTO samplingOperationToSave : getModel().getSurvey().getSamplingOperations()) {
// use QuadrigeBean comparator }
if (samplingOperationToSave.getId().equals(row.getId())) {
// update all measurements public void save() {
row.getMeasurements().forEach(measurement -> measurement.setAnalyst(row.getAnalyst()));
samplingOperationToSave.setMeasurements(row.getMeasurements()); Map<Integer, OperationMeasurementsUngroupedRowModel> rowById = new HashMap<>();
samplingOperationToSave.setDirty(true); getModel().getRows().forEach(row -> rowById.put(row.getId(), row));
break;
} getModel().getSamplingOperations().forEach(samplingOperation -> {
} OperationMeasurementsUngroupedRowModel row = rowById.get(samplingOperation.getId());
if (row == null)
throw new ReefDbTechnicalException("Unable to find the row for sampling operation id=" + samplingOperation.getId());
// update all measurements
row.getMeasurements().forEach(measurement -> measurement.setAnalyst(row.getAnalyst()));
// affect measurements
samplingOperation.setMeasurements(row.getMeasurements());
});
} }
...@@ -246,8 +254,8 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -246,8 +254,8 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
if (row.getAnalyst() == null && row.getMeasurements().stream().anyMatch(measurement -> !ReefDbBeans.isMeasurementEmpty(measurement))) { if (row.getAnalyst() == null && row.getMeasurements().stream().anyMatch(measurement -> !ReefDbBeans.isMeasurementEmpty(measurement))) {
ReefDbBeans.addError(row, ReefDbBeans.addError(row,
t("reefdb.validator.error.analyst.required"), t("reefdb.validator.error.analyst.required"),
OperationMeasurementsUngroupedRowModel.PROPERTY_ANALYST); OperationMeasurementsUngroupedRowModel.PROPERTY_ANALYST);
return false; return false;
} }
return true; return true;
...@@ -260,16 +268,16 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb ...@@ -260,16 +268,16 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
// Colonne mnemonique // Colonne mnemonique
final TableColumnExt colMnemonic = addColumn( final TableColumnExt colMnemonic = addColumn(
OperationMeasurementsUngroupedTableModel.NAME); OperationMeasurementsUngroupedTableModel.NAME);
colMnemonic.setSortable(true); colMnemonic.setSortable(true);
colMnemonic.setEditable(false); colMnemonic.setEditable(false);
setDefaultColumnMinWidth(colMnemonic); setDefaultColumnMinWidth(colMnemonic);
// Add analyst column (Mantis #42619) // Add analyst column (Mantis #42619)
TableColumnExt analystColumn = addColumn( TableColumnExt analystColumn = addColumn(
departmentCellEditor, departmentCellEditor,
newTableCellRender(OperationMeasurementsUngroupedTableModel.ANALYST), newTableCellRender(OperationMeasurementsUngroupedTableModel.ANALYST),
OperationMeasurementsUngroupedTableModel.ANALYST OperationMeasurementsUngroupedTableModel.ANALYST
); );
analystColumn.setMinWidth(100); analystColumn.setMinWidth(100);
......
...@@ -71,11 +71,11 @@ public class OperationMeasurementsUngroupedTableUIModel extends AbstractReefDbTa ...@@ -71,11 +71,11 @@ public class OperationMeasurementsUngroupedTableUIModel extends AbstractReefDbTa
} }
/** /**
* <p>getSamplings.</p> * <p>getSamplingOperations.</p>
* *
* @return a {@link java.util.List} object. * @return a {@link java.util.List} object.
*/ */
public List<SamplingOperationDTO> getSamplings() { public List<SamplingOperationDTO> getSamplingOperations() {
return survey == null ? null : (List<SamplingOperationDTO>) survey.getSamplingOperations(); return survey == null ? null : (List<SamplingOperationDTO>) survey.getSamplingOperations();
} }
...@@ -106,8 +106,8 @@ public class OperationMeasurementsUngroupedTableUIModel extends AbstractReefDbTa ...@@ -106,8 +106,8 @@ public class OperationMeasurementsUngroupedTableUIModel extends AbstractReefDbTa
*/ */
public List<MeasurementDTO> getAllMeasurements() { public List<MeasurementDTO> getAllMeasurements() {
List<MeasurementDTO> measurements = Lists.newArrayList(); List<MeasurementDTO> measurements = Lists.newArrayList();
if (getSamplings() != null) { if (getSamplingOperations() != null) {
for (SamplingOperationDTO samplingOperation : getSamplings()) { for (SamplingOperationDTO samplingOperation : getSamplingOperations()) {
measurements.addAll(samplingOperation.getMeasurements()); measurements.addAll(samplingOperation.getMeasurements());
} }
} }
......
...@@ -412,9 +412,9 @@ public class PhotosTabUIHandler extends AbstractReefDbTableUIHandler<PhotosTable ...@@ -412,9 +412,9 @@ public class PhotosTabUIHandler extends AbstractReefDbTableUIHandler<PhotosTable
} }
/** /**
* <p>saveActualModel.</p> * <p>save.</p>
*/ */
public void saveActualModel() { public void save() {
getModel().setModelAdjusting(true); getModel().setModelAdjusting(true);
getModel().getObservationModel().setPhotos(getModel().getBeans()); getModel().getObservationModel().setPhotos(getModel().getBeans());
getModel().setModelAdjusting(false); getModel().setModelAdjusting(false);
......
...@@ -319,6 +319,15 @@ public abstract class AbstractMeasurementsGroupedRowModel<B extends MeasurementD ...@@ -319,6 +319,15 @@ public abstract class AbstractMeasurementsGroupedRowModel<B extends MeasurementD
return Lists.newArrayList(PROPERTY_TAXON_GROUP, PROPERTY_TAXON); return Lists.newArrayList(PROPERTY_TAXON_GROUP, PROPERTY_TAXON);
} }
public boolean hasTaxonInformation() {
return getTaxonGroup() != null || getTaxon() != null;
}
public boolean hasNonEmptyMeasurements() {
return getIndividualMeasurements().stream().anyMatch(measurement -> !ReefDbBeans.isMeasurementEmpty(measurement));
}
/** /**
* Return a unique hashCode for the row * Return a unique hashCode for the row
* *
......
...@@ -24,14 +24,13 @@ package fr.ifremer.reefdb.ui.swing.content.observation.shared; ...@@ -24,14 +24,13 @@ package fr.ifremer.reefdb.ui.swing.content.observation.shared;
*/ */
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import fr.ifremer.quadrige3.core.dao.technical.Assert; import fr.ifremer.quadrige3.core.dao.technical.Assert;
import fr.ifremer.quadrige3.core.dao.technical.factorization.pmfm.AllowedQualitativeValuesMap; import fr.ifremer.quadrige3.core.dao.technical.factorization.pmfm.AllowedQualitativeValuesMap;
import fr.ifremer.quadrige3.ui.core.dto.DirtyAware; import fr.ifremer.quadrige3.ui.core.dto.DirtyAware;
import fr.ifremer.quadrige3.ui.swing.table.AbstractTableUIModel;
import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
import fr.ifremer.quadrige3.ui.swing.table.editor.ExtendedComboBoxCellEditor; import fr.ifremer.quadrige3.ui.swing.table.editor.ExtendedComboBoxCellEditor;
import fr.ifremer.reefdb.decorator.DecoratorService; import fr.ifremer.reefdb.decorator.DecoratorService;
import fr.ifremer.reefdb.dto.ErrorDTO; import fr.ifremer.reefdb.dto.ErrorDTO;
...@@ -51,8 +50,8 @@ import fr.ifremer.reefdb.dto.referential.TaxonDTO; ...@@ -51,8 +50,8 @@ import fr.ifremer.reefdb.dto.referential.TaxonDTO;
import fr.ifremer.reefdb.dto.referential.TaxonGroupDTO; import fr.ifremer.reefdb.dto.referential.TaxonGroupDTO;
import fr.ifremer.reefdb.dto.referential.pmfm.PmfmDTO; import fr.ifremer.reefdb.dto.referential.pmfm.PmfmDTO;
import fr.ifremer.reefdb.dto.referential.pmfm.QualitativeValueDTO; import fr.ifremer.reefdb.dto.referential.pmfm.QualitativeValueDTO;
import fr.ifremer.reefdb.service.ReefDbTechnicalException;
import fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement.grouped.OperationMeasurementsGroupedRowModel; import fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement.grouped.OperationMeasurementsGroupedRowModel;
import fr.ifremer.reefdb.ui.swing.util.OneShotListener;
import fr.ifremer.reefdb.ui.swing.util.ReefDbUI; import fr.ifremer.reefdb.ui.swing.util.ReefDbUI;
import fr.ifremer.reefdb.ui.swing.util.table.AbstractReefDbTableUIHandler; import fr.ifremer.reefdb.ui.swing.util.table.AbstractReefDbTableUIHandler;
import fr.ifremer.reefdb.ui.swing.util.table.PmfmTableColumn; import fr.ifremer.reefdb.ui.swing.util.table.PmfmTableColumn;
...@@ -71,7 +70,6 @@ import java.awt.Dimension; ...@@ -71,7 +70,6 @@ import java.awt.Dimension;
import java.awt.Insets; import java.awt.Insets;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.nuiton.i18n.I18n.t; import static org.nuiton.i18n.I18n.t;
...@@ -235,7 +233,7 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -235,7 +233,7 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
loadMeasurements(); loadMeasurements();
break; break;
case AbstractMeasurementsGroupedTableUIModel.EVENT_MEASUREMENTS_LOADED: case AbstractMeasurementsGroupedTableUIModel.EVENT_INDIVIDUAL_MEASUREMENTS_LOADED:
detectPreconditionedPmfms(); detectPreconditionedPmfms();
detectGroupedIdentifiers(); detectGroupedIdentifiers();
...@@ -453,14 +451,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -453,14 +451,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
// set default analyst from pmfm strategies (Mantis #42619) // set default analyst from pmfm strategies (Mantis #42619)
setDefaultAnalyst(newRow); setDefaultAnalyst(newRow);
// now calculate individual id after table is sorted
if (getTable().getRowSorter().getSortKeys().isEmpty()) {
// Also use a OneShotListener (Mantis #51586)
OneShotListener.create(getModel(), AbstractTableUIModel.PROPERTY_ROWS, propertyChangeEvent -> calculateIndividualIds(newRow));
} else {
OneShotListener.create(getTable(), SwingTable.PROPERTY_SORTED, propertyChangeEvent -> calculateIndividualIds(newRow));
}
// reset the cell editors // reset the cell editors
resetCellEditors(); resetCellEditors();
...@@ -493,59 +483,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -493,59 +483,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
rows.forEach(row -> row.setAnalyst(analyst)); rows.forEach(row -> row.setAnalyst(analyst));
} }
protected void calculateIndividualIds(R rowToUpdate) {
calculateIndividualIds(getMeasurementAwareModelForRow(rowToUpdate));
}
protected void calculateIndividualIds(MeasurementAware bean) {
if (bean == null) return;
Predicate<? super R> predicate = getRowForBeanPredicate(bean);
AtomicInteger individualId = new AtomicInteger();
// iterate over sorted rows and set incremental individualId (see Mantis #51520)
for (int i = 0; i < getTable().getRowCount(); i++) {
R row = getTableModel().getEntry(getTable().convertRowIndexToModel(i));
if (predicate.test(row)) {
// increment and set row individual id
row.setIndividualId(individualId.incrementAndGet());
// update all individual measurements
row.getIndividualMeasurements().forEach(measurement -> measurement.setIndividualId(individualId.get()));
}
}
setDirty(bean);
}
/**
* Increment the nextIndividualId to next unused individual id in rows
*
* @param bean the current bean
* @param nextIndividualId the counter to increment
*/
protected void incrementNextIndividualId(MeasurementAware bean, AtomicInteger nextIndividualId) {
do {
nextIndividualId.incrementAndGet();
} while (getModel().getRows().stream()
.filter(getRowForBeanPredicate(bean))
.anyMatch(row -> Objects.equals(nextIndividualId.get(), row.getIndividualId())));
Assert.isTrue(nextIndividualId.get() > 0, "the next individual id must be > 0");
}
/**
* return a predicate to tell if the row is associated to the bean (true by default)
*
* @param bean the bean
* @return a predicate
*/
protected Predicate<? super R> getRowForBeanPredicate(MeasurementAware bean) {
return (Predicate<R>) r -> true;
}
protected void initAddedRow(R row) { protected void initAddedRow(R row) {
if (getModel().getTaxonGroupFilter() != null) { if (getModel().getTaxonGroupFilter() != null) {
row.setTaxonGroup(getModel().getTaxonGroupFilter()); row.setTaxonGroup(getModel().getTaxonGroupFilter());
...@@ -604,7 +541,7 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -604,7 +541,7 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
if (oldValue != newValue) { if (oldValue != newValue) {
// save modifications ot the row to bean // save modifications ot the row to bean
saveMeasurementsInModel(row); // saveMeasurementsInModel(row);
// also recompute valid state on all rows // also recompute valid state on all rows
recomputeRowsValidState(); recomputeRowsValidState();
...@@ -614,54 +551,11 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -614,54 +551,11 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
protected void resetIndividualMeasurementIds(R row) { protected void resetIndividualMeasurementIds(R row) {
if (row != null && CollectionUtils.isNotEmpty(row.getIndividualMeasurements())) { if (row != null && CollectionUtils.isNotEmpty(row.getIndividualMeasurements())) {
for (MeasurementDTO individualMeasurement : row.getIndividualMeasurements()) { row.getIndividualMeasurements().forEach(measurement -> measurement.setId(null));
individualMeasurement.setId(null);
}
} }
} }
public void saveMeasurementsInModel(R row) { protected void setDirty(MeasurementAware bean) {
Assert.notNull(row);
if (!row.isValid()) return;
MeasurementAware bean = getMeasurementAwareModelForRow(row);
Assert.notNull(bean);
// existing measurements in bean (for this individualId)
List<MeasurementDTO> remainingMeasurements = ReefDbBeans.filterCollection(bean.getIndividualMeasurements(),
input -> input != null && input.getId() != null && Objects.equals(row.getIndividualId(), input.getIndividualId()));
// get stored individual measurement by id
List<Integer> existingIndividualMeasurementIds = ReefDbBeans.collectIds(bean.getIndividualMeasurements());
// get the minimum negative measurement id
int minNegativeId = CollectionUtils.isEmpty(existingIndividualMeasurementIds) ? 0 : Math.min(Collections.min(existingIndividualMeasurementIds), 0);
// iterate individual measurement in row
for (MeasurementDTO individualMeasurement : row.getIndividualMeasurements()) {
if (individualMeasurement.getId() == null) {
// this measurement was not in bean, so add it with next negative id
individualMeasurement.setId(--minNegativeId);
// add to bean
bean.getIndividualMeasurements().add(individualMeasurement);
}
// update this measurement
updateMeasurementFromRow(individualMeasurement, row);
// remove if existing
remainingMeasurements.remove(individualMeasurement);
}
// Remove remaining
bean.getIndividualMeasurements().removeAll(remainingMeasurements);
setDirty(bean);
}
private void setDirty(Object bean) {
if (bean instanceof DirtyAware) ((DirtyAware) bean).setDirty(true); if (bean instanceof DirtyAware) ((DirtyAware) bean).setDirty(true);
} }
...@@ -678,18 +572,10 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -678,18 +572,10 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
public void removeIndividualMeasurements() { public void removeIndividualMeasurements() {
if (getModel().getSelectedRows().isEmpty()) { if (getModel().getSelectedRows().isEmpty()) {
LOG.warn("Aucune mesure de selectionnee"); LOG.warn("Can't remove rows: no row selected");
return; return;
} }
// Selected measurement
List<MeasurementDTO> measurementToDelete = Lists.newArrayList();
for (final R row : getModel().getSelectedRows()) {
if (CollectionUtils.isNotEmpty(row.getIndividualMeasurements())) {
measurementToDelete.addAll(row.getIndividualMeasurements());
}
}
if (askBeforeDelete(t("reefdb.action.delete.survey.measurement.titre"), t("reefdb.action.delete.survey.measurement.message"))) { if (askBeforeDelete(t("reefdb.action.delete.survey.measurement.titre"), t("reefdb.action.delete.survey.measurement.message"))) {
// Get distinct models to update after rows removed // Get distinct models to update after rows removed
...@@ -700,25 +586,20 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -700,25 +586,20 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
// Remove from table // Remove from table
getModel().deleteSelectedRows(); getModel().deleteSelectedRows();
// Remove from model modelsToUpdate.forEach(this::setDirty);
removeIndividualMeasurements(measurementToDelete); getModel().setModify(true);
// Recalculate individual ids
modelsToUpdate.forEach(this::calculateIndividualIds);
recomputeRowsValidState(); recomputeRowsValidState();
} }
} }
protected abstract void removeIndividualMeasurements(List<MeasurementDTO> measurementToDelete);
public void duplicateSelectedRow() { public void duplicateSelectedRow() {
if (getModel().getSelectedRows().size() == 1 && getModel().getSingleSelectedRow() != null) { if (getModel().getSelectedRows().size() == 1 && getModel().getSingleSelectedRow() != null) {
R rowToDuplicate = getModel().getSingleSelectedRow(); R rowToDuplicate = getModel().getSingleSelectedRow();
R row = createNewRow(false, getMeasurementAwareModelForRow(rowToDuplicate)); MeasurementAware bean = getMeasurementAwareModelForRow(rowToDuplicate);
R row = createNewRow(false, bean);
row.setTaxonGroup(rowToDuplicate.getTaxonGroup()); row.setTaxonGroup(rowToDuplicate.getTaxonGroup());
row.setTaxon(rowToDuplicate.getTaxon()); row.setTaxon(rowToDuplicate.getTaxon());
row.setInputTaxonId(rowToDuplicate.getInputTaxonId()); row.setInputTaxonId(rowToDuplicate.getInputTaxonId());
...@@ -732,21 +613,14 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -732,21 +613,14 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
// Add duplicate measurement to table // Add duplicate measurement to table
getModel().insertRowAfterSelected(row); getModel().insertRowAfterSelected(row);
// save directly to sampling operation
saveMeasurementsInModel(row);
onDuplicatedRowAdded(row);
setDirty(bean);
recomputeRowsValidState(); recomputeRowsValidState();
getModel().setModify(true); getModel().setModify(true);
setFocusOnCell(row); setFocusOnCell(row);
} }
} }
protected void onDuplicatedRowAdded(R row) {
// nothing by default
}
/* validation section */ /* validation section */
/** /**
...@@ -823,59 +697,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -823,59 +697,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
AbstractMeasurementsGroupedRowModel.PROPERTY_INDIVIDUAL_PMFMS)); AbstractMeasurementsGroupedRowModel.PROPERTY_INDIVIDUAL_PMFMS));
})); }));
// old algo (too long with many rows)
// for (R row : getModel().getRows()) {
// for (R otherRow : getModel().getRows()) {
// if (otherRow == row /*|| (otherRow.getTaxonGroup() == null && otherRow.getTaxon() == null)*/) continue;
//
// if (row.isSameRow(otherRow)
// // Both measurements must have same non empty measurements (Mantis #42170)
// && ReefDbBeans.haveSameMeasurements(row.getIndividualMeasurements(), otherRow.getIndividualMeasurements())
// ) {
// // if rows equals, check all measurement values
// boolean allValuesEquals = true;
// Set<Integer> notNullMeasurementPmfmIds = Sets.newHashSet();
// for (MeasurementDTO measurement : row.getIndividualMeasurements()) {
//
// // find the measurement with same pmfm in the other row
// MeasurementDTO otherMeasurement = ReefDbBeans.getIndividualMeasurementByPmfmId(otherRow, measurement.getPmfm().getId());
//
// if (otherMeasurement != null) {
// if (measurement.getPmfm().getParameter().isQualitative()) {
// if (!Objects.equals(measurement.getQualitativeValue(), otherMeasurement.getQualitativeValue())) {
// allValuesEquals = false;
// break;
// }
// } else {
// if (!Objects.equals(measurement.getNumericalValue(), otherMeasurement.getNumericalValue())) {
// allValuesEquals = false;
// break;
// }
// }
// }
//
// // collect pmfm ids
// if (!ReefDbBeans.isMeasurementEmpty(measurement)) {
// notNullMeasurementPmfmIds.add(measurement.getPmfm().getId());
// }
// }
// if (allValuesEquals) {
//
// // Mantis #0026890 The check for perfect duplicates is now a warning
// ReefDbBeans.addWarning(row,
// t("reefdb.measurement.grouped.duplicates"), row.getDefaultProperties().toArray(new String[0]));
//
// for (Integer pmfmId : notNullMeasurementPmfmIds) {
// ReefDbBeans.addWarning(row,
// t("reefdb.measurement.grouped.duplicates"),
// pmfmId,
// AbstractMeasurementsGroupedRowModel.PROPERTY_INDIVIDUAL_PMFMS);
// }
// return;
// }
// }
// }
// }
} }
protected boolean hasNoUnicityDuplicates(R row) { protected boolean hasNoUnicityDuplicates(R row) {
...@@ -998,6 +819,14 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -998,6 +819,14 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
for (Map.Entry<RuleGroupDTO, ? extends ReefDbColumnIdentifier<R>> identifierByGroup : getModel().getIdentifiersByGroupedRuleMap().get(groupedRule)) { for (Map.Entry<RuleGroupDTO, ? extends ReefDbColumnIdentifier<R>> identifierByGroup : getModel().getIdentifiersByGroupedRuleMap().get(groupedRule)) {
RuleGroupDTO group = identifierByGroup.getKey(); RuleGroupDTO group = identifierByGroup.getKey();
ReefDbColumnIdentifier<R> identifier = identifierByGroup.getValue(); ReefDbColumnIdentifier<R> identifier = identifierByGroup.getValue();
if (row.getMultipleValuesOnIdentifier().contains(identifier)
|| (identifier instanceof ReefDbPmfmColumnIdentifier && row.getMultipleValuesOnPmfmIds().contains(((ReefDbPmfmColumnIdentifier) identifier).getPmfmId()))
) {
groupResult = true;
break;
}
// For now, assume logical operator is always OR // For now, assume logical operator is always OR
Assert.isTrue(group.isIsOr()); Assert.isTrue(group.isIsOr());
groupResult |= getContext().getControlRuleService().controlUniqueObject(group.getRule(), identifier.getValue(row)); groupResult |= getContext().getControlRuleService().controlUniqueObject(group.getRule(), identifier.getValue(row));
...@@ -1287,8 +1116,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -1287,8 +1116,6 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
} }
} }
// save modifications
saveMeasurementsInModel(row);
} }
// done // done
...@@ -1297,4 +1124,99 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler< ...@@ -1297,4 +1124,99 @@ public abstract class AbstractMeasurementsGroupedTableUIHandler<
} }
} }
/**
* Save grouped measurements on parent model(s)
* This replace inline save (see Mantis #51725)
*/
public void save() {
// Get all existing measurements in beans
List<? extends MeasurementAware> beansToSave = getMeasurementAwareModels();
List<MeasurementDTO> existingMeasurements = beansToSave.stream()
.flatMap(bean -> bean.getIndividualMeasurements().stream())
.collect(Collectors.toList());
// get the minimum negative measurement id
AtomicInteger minNegativeId = new AtomicInteger(
Math.min(
0,
existingMeasurements.stream()
.filter(measurement -> measurement != null && measurement.getId() != null)
.mapToInt(MeasurementDTO::getId)
.min()
.orElse(0)
)
);
Multimap<MeasurementAware, R> rowsByBean = ArrayListMultimap.create();
// Get ordered rows by bean
for (int i = 0; i < getTable().getRowCount(); i++) {
R row = getTableModel().getEntry(getTable().convertRowIndexToModel(i));
MeasurementAware bean = getMeasurementAwareModelForRow(row);
if (bean == null) {
throw new ReefDbTechnicalException("The parent bean is null for a grouped measurements row");
}
rowsByBean.put(bean, row);
}
rowsByBean.keySet().forEach(bean -> {
AtomicInteger individualId = new AtomicInteger();
List<MeasurementDTO> beanMeasurements = new ArrayList<>();
// Iterate over each row
rowsByBean.get(bean).forEach(row -> {
// Test is this row is to save or not
if (isRowToSave(row)) {
// Affect row individual ids according this order
row.setIndividualId(individualId.incrementAndGet());
// Iterate over row's measurements
row.getIndividualMeasurements().forEach(measurement -> {
if (measurement.getId() == null) {
// this measurement was not in bean, so add it with next negative id
measurement.setId(minNegativeId.decrementAndGet());
}
// update this measurement
updateMeasurementFromRow(measurement, row);
// Add to new list
beanMeasurements.add(measurement);
});
}
});
// Affect new list of measurements
bean.getIndividualMeasurements().clear();
bean.getIndividualMeasurements().addAll(beanMeasurements);
setDirty(bean);
// Remove this bean from the list
beansToSave.remove(bean);
});
// Clean remaining beans
beansToSave.forEach(bean -> {
// If a bean still in this map, it means there is no row of this bean, so remove all
bean.getIndividualMeasurements().clear();
setDirty(bean);
});
}
/**
* Determine if this row is to be saved
*
* @param row to test
* @return true if to save (default)
*/
protected boolean isRowToSave(R row) {
return
// The row must exists
row != null
// and contains at least 1 non empty individual measurement or a taxon group or a taxon
&& (row.hasTaxonInformation() || row.hasNonEmptyMeasurements());
}
} }
...@@ -53,7 +53,7 @@ public abstract class AbstractMeasurementsGroupedTableUIModel< ...@@ -53,7 +53,7 @@ public abstract class AbstractMeasurementsGroupedTableUIModel<
public static final String PROPERTY_SURVEY = "survey"; public static final String PROPERTY_SURVEY = "survey";
public static final String PROPERTY_MEASUREMENT_FILTER = "measurementFilter"; public static final String PROPERTY_MEASUREMENT_FILTER = "measurementFilter";
public static final String EVENT_MEASUREMENTS_LOADED = "measurementsLoaded"; public static final String EVENT_INDIVIDUAL_MEASUREMENTS_LOADED = "individualMeasurementsLoaded";
// the survey model // the survey model
private ObservationUIModel survey; private ObservationUIModel survey;
...@@ -189,6 +189,6 @@ public abstract class AbstractMeasurementsGroupedTableUIModel< ...@@ -189,6 +189,6 @@ public abstract class AbstractMeasurementsGroupedTableUIModel<
} }
public void fireMeasurementsLoaded() { public void fireMeasurementsLoaded() {
firePropertyChange(EVENT_MEASUREMENTS_LOADED, null, null); firePropertyChange(EVENT_INDIVIDUAL_MEASUREMENTS_LOADED, null, null);
} }
} }
...@@ -197,12 +197,6 @@ public abstract class AbstractMeasurementsMultiEditUIHandler< ...@@ -197,12 +197,6 @@ public abstract class AbstractMeasurementsMultiEditUIHandler<
// super.onRowsAdded(addedRows); // super.onRowsAdded(addedRows);
} }
@Override
public void saveMeasurementsInModel(R row) {
// Don't call super method; the selected rows will be saved after multi-line validation
// super.saveMeasurementsInModel(row);
}
@Override @Override
protected List<? extends MeasurementAware> getMeasurementAwareModels() { protected List<? extends MeasurementAware> getMeasurementAwareModels() {
// nothing to return, this handler don't save model // nothing to return, this handler don't save model
...@@ -219,10 +213,6 @@ public abstract class AbstractMeasurementsMultiEditUIHandler< ...@@ -219,10 +213,6 @@ public abstract class AbstractMeasurementsMultiEditUIHandler<
protected void filterMeasurements() { protected void filterMeasurements() {
} }
@Override
protected void removeIndividualMeasurements(List<MeasurementDTO> measurementToDelete) {
}
public void valid() { public void valid() {
if (getModel().isValid()) { if (getModel().isValid()) {
closeDialog(); closeDialog();
......
...@@ -43,6 +43,11 @@ NumberEditor { ...@@ -43,6 +43,11 @@ NumberEditor {
_selectOnFocus: {true}; _selectOnFocus: {true};
} }
#surveyDetailsBlockLayer {
blockingColor: {handler.getConfig().getColorBlockingLayer()};
block:{model.isLoading()};
}
#surveyDetailsTabUI { #surveyDetailsTabUI {
_panelType: {ReefDbUI.EDITION_PANEL_TYPE}; _panelType: {ReefDbUI.EDITION_PANEL_TYPE};
} }
......
...@@ -75,6 +75,7 @@ public class SurveyDetailsTabUIHandler extends AbstractReefDbUIHandler<SurveyDet ...@@ -75,6 +75,7 @@ public class SurveyDetailsTabUIHandler extends AbstractReefDbUIHandler<SurveyDet
@Override @Override
public void afterInit(final SurveyDetailsTabUI ui) { public void afterInit(final SurveyDetailsTabUI ui) {
initUI(ui); initUI(ui);
SwingUtil.setLayerUI(ui.getDetailsPanel(), ui.getSurveyDetailsBlockLayer());
// Initialisation des combobox // Initialisation des combobox
initComboBox(); initComboBox();
...@@ -378,9 +379,9 @@ public class SurveyDetailsTabUIHandler extends AbstractReefDbUIHandler<SurveyDet ...@@ -378,9 +379,9 @@ public class SurveyDetailsTabUIHandler extends AbstractReefDbUIHandler<SurveyDet
} }
/** /**
* <p>saveActualModel.</p> * <p>save.</p>
*/ */
public void saveActualModel() { public void save() {
getModel().setAdjusting(true); getModel().setAdjusting(true);
......
...@@ -336,4 +336,24 @@ public class SurveyMeasurementsTabUIHandler extends AbstractReefDbUIHandler<Surv ...@@ -336,4 +336,24 @@ public class SurveyMeasurementsTabUIHandler extends AbstractReefDbUIHandler<Surv
public boolean onRemoveTab() { public boolean onRemoveTab() {
return false; return false;
} }