Commit 9d4613f1 authored by PECQUOT's avatar PECQUOT

Merge branch 'release/3.9.7'

parents 29e4e3a9 f12d7bf4
## Sprint 89 - v3.9.7
- Pas de mise à jour de modèle
## Sprint 88 - v3.9.5 & v3.9.6
- Pas de mise à jour de modèle
......
......@@ -10,7 +10,7 @@
<groupId>fr.ifremer.reefdb</groupId>
<artifactId>reefdb</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
<packaging>pom</packaging>
<name>Reef DB</name>
......@@ -171,7 +171,7 @@
<maven.compiler.debug>true</maven.compiler.debug>
<!-- Quadrige3 Core version -->
<quadrige3-core.version>3.6.11</quadrige3-core.version>
<quadrige3-core.version>3.6.13</quadrige3-core.version>
<!-- Last ReefDb launcher version -->
<launcherVersion>3.0.3</launcherVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>fr.ifremer.reefdb</groupId>
<artifactId>reefdb</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
</parent>
<artifactId>reefdb-core</artifactId>
......
......@@ -35,7 +35,7 @@
# Please fill the missing licenses for dependencies :
#
#
#Fri Mar 06 16:15:32 CET 2020
#Mon Mar 23 12:33:10 CET 2020
com.oracle--ojdbc7--12.1.0.2.0=OTN license
commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0
dom4j--dom4j--1.6.1=BSD License
......
......@@ -905,9 +905,9 @@ public final class ReefDbConfiguration extends QuadrigeCoreConfiguration {
String configOption = applicationConfig.getOption(ReefDbConfigurationOption.PMFM_IDS_TRANSITION_LENGTH.getKey());
if (StringUtils.isBlank(configOption)) return result;
List<String> triplets = Splitter.on(";").splitToList(configOption);
List<String> triplets = Splitter.on(";").omitEmptyStrings().splitToList(configOption);
for (String triplet : triplets) {
List<String> pmfmsIdsStr = Splitter.on(",").splitToList(triplet);
List<String> pmfmsIdsStr = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(triplet);
if (CollectionUtils.size(pmfmsIdsStr) == 3) {
try {
Integer[] pmfmIds = new Integer[3];
......
......@@ -42,6 +42,7 @@ import fr.ifremer.reefdb.dto.configuration.programStrategy.PmfmStrategyDTO;
import fr.ifremer.reefdb.dto.configuration.programStrategy.ProgramDTO;
import fr.ifremer.reefdb.dto.data.measurement.MeasurementAware;
import fr.ifremer.reefdb.dto.data.measurement.MeasurementDTO;
import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO;
import fr.ifremer.reefdb.dto.data.survey.CampaignDTO;
import fr.ifremer.reefdb.dto.data.survey.SurveyDTO;
import fr.ifremer.reefdb.dto.enums.*;
......@@ -90,36 +91,6 @@ public class ReefDbBeans extends QuadrigeBeans {
}
}
/**
* <p>computeAddress.</p>
*
* @param street a {@link String} object.
* @param zipCode a {@link String} object.
* @param city a {@link String} object.
* @return a {@link String} object.
*/
public static String computeAddress(String street, String zipCode, String city) {
StringBuilder addressBuilder = new StringBuilder();
if (StringUtils.isNotBlank(street)) {
addressBuilder.append(street.replaceAll("[ ]+", " "));
if (StringUtils.isNotBlank(zipCode) || StringUtils.isNotBlank(city)) {
addressBuilder.append(", ");
}
}
if (StringUtils.isNotBlank(zipCode)) {
addressBuilder.append(zipCode);
if (StringUtils.isNotBlank(city)) {
addressBuilder.append(" ");
}
}
if (StringUtils.isNotBlank(city)) {
addressBuilder.append(city);
}
return addressBuilder.toString();
}
public static String toQuotedString(String string) {
return "'" + string.replaceAll("'", "''") + "'";
}
......@@ -189,6 +160,47 @@ public class ReefDbBeans extends QuadrigeBeans {
return bean.toString();
}
public static List<MeasurementDTO> duplicate(List<MeasurementDTO> measurements) {
if (measurements == null)
return new ArrayList<>();
return measurements.stream().map(ReefDbBeans::duplicate).collect(Collectors.toList());
}
public static MeasurementDTO duplicate(MeasurementDTO measurement) {
// Clone object
MeasurementDTO clone = clone(measurement);
// Remove Id & individualId
clone.setId(null);
clone.setIndividualId(null);
// remove errors
clone.setErrors(null);
return clone;
}
public static SamplingOperationDTO duplicate(final SamplingOperationDTO samplingOperation) {
// Clone object
final SamplingOperationDTO clone = clone(samplingOperation);
// Remove ID
clone.setId(null);
// clone coordinate
clone.setCoordinate(clone(samplingOperation.getCoordinate()));
// remove errors
clone.setErrors(null);
// duplicate measurements
clone.setMeasurements(duplicate(samplingOperation.getMeasurements()));
clone.setIndividualMeasurements(duplicate(samplingOperation.getIndividualMeasurements()));
return clone;
}
/**
* <p>filterNotEmptyAppliedPeriod.</p>
*
......
......@@ -26,7 +26,6 @@ package fr.ifremer.reefdb.service.observation;
import fr.ifremer.quadrige3.core.ProgressionCoreModel;
import fr.ifremer.reefdb.dto.configuration.programStrategy.ProgStratDTO;
import fr.ifremer.reefdb.dto.configuration.programStrategy.ProgramDTO;
import fr.ifremer.reefdb.dto.data.measurement.MeasurementDTO;
import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO;
import fr.ifremer.reefdb.dto.data.survey.CampaignDTO;
import fr.ifremer.reefdb.dto.data.survey.SurveyDTO;
......@@ -128,24 +127,6 @@ public interface ObservationService {
@PreAuthorize("hasPermission(null, T(fr.ifremer.quadrige3.core.security.QuadrigeUserAuthority).USER)")
SurveyDTO duplicateSurvey(SurveyDTO survey, boolean fullDuplication, boolean copyCoordinates, boolean duplicateSurveyMeasurements);
/**
* Duplicate prelevement.
*
* @param samplingOperation Prelevement to duplicate
* @return Prelvement duplicated
*/
@PreAuthorize("hasPermission(null, T(fr.ifremer.quadrige3.core.security.QuadrigeUserAuthority).USER)")
SamplingOperationDTO duplicateSamplingOperation(SamplingOperationDTO samplingOperation);
/**
* Duplicate a list of measurements.
*
* @param measurements Measurements to duplicate
* @return Measurements duplicate
*/
@PreAuthorize("hasPermission(null, T(fr.ifremer.quadrige3.core.security.QuadrigeUserAuthority).USER)")
List<MeasurementDTO> duplicateMeasurements(List<MeasurementDTO> measurements);
/**
* <p>getAvailablePrograms.</p>
*
......
......@@ -538,59 +538,6 @@ public class ObservationServiceImpl implements ObservationInternalService {
}
/**
* {@inheritDoc}
*/
@Override
public SamplingOperationDTO duplicateSamplingOperation(final SamplingOperationDTO samplingOperation) {
// Duplicate sampling operation
final SamplingOperationDTO duplicatedSamplingOperation = ReefDbBeans.clone(samplingOperation);
// Remove ID
duplicatedSamplingOperation.setId(null);
// duplicate coordinate
duplicatedSamplingOperation.setCoordinate(ReefDbBeans.clone(samplingOperation.getCoordinate()));
// remove errors
duplicatedSamplingOperation.setErrors(null);
// duplicate measurements
duplicatedSamplingOperation.setMeasurements(duplicateMeasurements(samplingOperation.getMeasurements()));
duplicatedSamplingOperation.setIndividualMeasurements(duplicateMeasurements(samplingOperation.getIndividualMeasurements()));
return duplicatedSamplingOperation;
}
/**
* {@inheritDoc}
*/
@Override
public List<MeasurementDTO> duplicateMeasurements(List<MeasurementDTO> measurements) {
List<MeasurementDTO> duplicatedMeasurements = Lists.newArrayList();
if (CollectionUtils.isNotEmpty(measurements)) {
for (MeasurementDTO measurement : measurements) {
// duplicated measurement
final MeasurementDTO duplicatedMeasurement = ReefDbBeans.clone(measurement);
// Remove Id & individualId
duplicatedMeasurement.setId(null);
duplicatedMeasurement.setIndividualId(null);
// remove errors
duplicatedMeasurement.setErrors(null);
duplicatedMeasurements.add(duplicatedMeasurement);
}
}
return duplicatedMeasurements;
}
/**
* {@inheritDoc}
*/
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>fr.ifremer.reefdb</groupId>
<artifactId>reefdb</artifactId>
<version>3.9.6</version>
<version>3.9.7</version>
</parent>
<artifactId>reefdb-ui-swing</artifactId>
......
......@@ -23,12 +23,15 @@ package fr.ifremer.reefdb.ui.swing.content.home.operation;
* #L%
*/
import fr.ifremer.reefdb.dto.ReefDbBeans;
import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO;
import fr.ifremer.reefdb.ui.swing.action.AbstractReefDbAction;
/**
* Duplicate sampling operation action.
* {@link Deprecated} Use fr.ifremer.reefdb.dto.ReefDbBeans#duplicate(fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO) outside an action
*/
@Deprecated
public class DuplicateOperationAction extends AbstractReefDbAction<OperationsTableUIModel, OperationsTableUI, OperationsTableUIHandler> {
/**
......@@ -60,12 +63,10 @@ public class DuplicateOperationAction extends AbstractReefDbAction<OperationsTab
if (operationsTableRowModel != null) {
// Duplicate operation
final SamplingOperationDTO duplicatePrelevement = getContext().getObservationService().duplicateSamplingOperation(operationsTableRowModel.toBean());
if (duplicatePrelevement != null) {
// Add duplicate operation to table
newRow = getModel().addNewRow(duplicatePrelevement);
}
final SamplingOperationDTO duplicateOperation = ReefDbBeans.duplicate(operationsTableRowModel.toBean());
// Add duplicate operation to table
newRow = getModel().addNewRow(duplicateOperation);
}
}
......
......@@ -252,7 +252,7 @@ public class OperationsTableUIHandler extends AbstractReefDbTableUIHandler<Opera
}
// save actual table context before loading new survey
getContext().saveComponentInSwingSession(getTable(), getTableModel().getStateContext());
saveTableState();
// affect new selected survey
getModel().setSurvey(survey);
......@@ -739,7 +739,7 @@ public class OperationsTableUIHandler extends AbstractReefDbTableUIHandler<Opera
forceRevalidateModel();
// restore table state from swing session
getContext().restoreComponentFromSwingSession(getTable());
restoreTableState();
// hide analyst column if no pmfm (Mantis #42619)
// forceColumnVisibleAtLastPosition(OperationsTableModel.ANALYST, notEmpty);
......
......@@ -439,13 +439,11 @@ public class AddOperationTableUIHandler extends AbstractReefDbTableUIHandler<Ope
for (int i = 0; i < nbOperation; i++) {
// Ajout du prelevement dans la liste
final SamplingOperationDTO newOperation = getContext().getObservationService().duplicateSamplingOperation(operation);
if (newOperation != null) {
operations.add(newOperation);
final SamplingOperationDTO newOperation = ReefDbBeans.duplicate(operation);
operations.add(newOperation);
// do it at creation time
newOperation.setMeasurementsLoaded(true);
}
// do it at creation time
newOperation.setMeasurementsLoaded(true);
}
// Ajout des prelevements
......
package fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement.grouped;
/*
* #%L
* Reef DB :: UI
* $Id:$
* $HeadURL:$
* %%
* Copyright (C) 2014 - 2015 Ifremer
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import fr.ifremer.reefdb.ui.swing.action.AbstractReefDbAction;
/**
* Action dupliquer mesure (ecran prelevements/mesure).
*/
public class DuplicateOperationMeasurementsAction extends AbstractReefDbAction<OperationMeasurementsGroupedTableUIModel, OperationMeasurementsGroupedTableUI, OperationMeasurementsGroupedTableUIHandler> {
/**
* La ligne ajoutee.
*/
private OperationMeasurementsGroupedRowModel row;
/**
* Constrcuteur.
*
* @param handler Controller
*/
public DuplicateOperationMeasurementsAction(final OperationMeasurementsGroupedTableUIHandler handler) {
super(handler, false);
}
/** {@inheritDoc} */
@Override
public boolean prepareAction() throws Exception {
return super.prepareAction() && getModel().getSelectedRows().size() == 1;
}
/** {@inheritDoc} */
@Override
public void doAction() {
// Selected measurement
final OperationMeasurementsGroupedRowModel rowToDuplicate = getModel().getSelectedRows().iterator().next();
if (rowToDuplicate != null) {
row = new OperationMeasurementsGroupedRowModel(false);
row.setSamplingOperation(rowToDuplicate.getSamplingOperation());
row.setTaxonGroup(rowToDuplicate.getTaxonGroup());
row.setTaxon(rowToDuplicate.getTaxon());
row.setInputTaxonId(rowToDuplicate.getInputTaxonId());
row.setInputTaxonName(rowToDuplicate.getInputTaxonName());
row.setComment(rowToDuplicate.getComment());
row.setIndividualPmfms(rowToDuplicate.getIndividualPmfms());
// add also analyst (MAntis #45054)
row.setAnalyst(rowToDuplicate.getAnalyst());
// duplicate measurements by service
row.setIndividualMeasurements(getContext().getObservationService().duplicateMeasurements(rowToDuplicate.getIndividualMeasurements()));
}
}
/** {@inheritDoc} */
@Override
public void postSuccessAction() {
super.postSuccessAction();
// Add duplicate measurement to table
getModel().insertRowAfterSelected(row);
// save directly to sampling operation
getHandler().saveMeasurementsInModel(row);
// send update event on sampling operation
if (row.getSamplingOperation() != null) {
getModel().firePropertyChanged(OperationMeasurementsGroupedTableUIModel.PROPERTY_SAMPLING_OPERATION, null, row.getSamplingOperation());
}
getHandler().recomputeRowsValidState();
getModel().setModify(true);
// Ajouter le focus sur la cellule de la ligne cree
getHandler().setFocusOnCell(row);
}
}
......@@ -60,7 +60,7 @@
<JPanel id='tableauBasPanelButtons' layout='{new BorderLayout()}' constraints="BorderLayout.PAGE_END">
<JPanel layout='{new FlowLayout()}' constraints='BorderLayout.LINE_START'>
<JButton id='addButton' alignmentX='{Component.CENTER_ALIGNMENT}' onActionPerformed="model.insertNewRowAfterSelected()"/>
<JButton id='duplicateButton' alignmentX='{Component.CENTER_ALIGNMENT}'/>
<JButton id='duplicateButton' alignmentX='{Component.CENTER_ALIGNMENT}' onActionPerformed="handler.duplicateSelectedRow()"/>
<JButton id='initDataGridButton' alignmentX='{Component.CENTER_ALIGNMENT}' onActionPerformed="handler.initializeDataGrid()"/>
<JButton id='multiEditButton' alignmentX='{Component.CENTER_ALIGNMENT}' onActionPerformed="handler.editSelectedMeasurements()"/>
<JButton id='deleteButton' alignmentX='{Component.CENTER_ALIGNMENT}' onActionPerformed="handler.removeIndividualMeasurements()"/>
......
......@@ -52,7 +52,6 @@
actionIcon: copy;
text: "reefdb.action.duplicate.label";
toolTipText: "reefdb.action.duplicate.measurement.tip";
_applicationAction: {DuplicateOperationMeasurementsAction.class};
enabled: {model.getSurvey().isEditable() && !model.getSelectedRows().isEmpty() && (model.getSelectedRows().size() == 1) && !model.getPmfms().isEmpty()};
}
......
......@@ -150,6 +150,22 @@ public class OperationMeasurementsGroupedTableUIHandler
// update some controls
getUI().processDataBinding(OperationMeasurementsGroupedTableUI.BINDING_INIT_DATA_GRID_BUTTON_ENABLED);
break;
// TODO ? force sort on sampling operation and transition column
// case OperationMeasurementsGroupedTableUIModel.PROPERTY_PIT_TRANSITION_LENGTH_PMFM_ID:
//
// // Try to apply sort on sampling operation and transition column
// if (getModel().getPitTransitionLengthPmfmId() != null) {
// TableColumnExt samplingColumn = getTable().getColumnExt(OperationMeasurementsGroupedTableModel.SAMPLING);
// PmfmTableColumn transitionColumn = findPmfmColumnByPmfmId(getModel().getPmfmColumns(), getModel().getPitTransitionLengthPmfmId());
// if (samplingColumn != null && transitionColumn != null) {
// getTable().getRowSorter().setSortKeys(ImmutableList.of(
// new RowSorter.SortKey(samplingColumn.getModelIndex(), SortOrder.ASCENDING),
// new RowSorter.SortKey(transitionColumn.getModelIndex(), SortOrder.ASCENDING)
// ));
// }
// }
// break;
}
});
......@@ -185,11 +201,10 @@ public class OperationMeasurementsGroupedTableUIHandler
@Override
protected List<? extends MeasurementAware> getMeasurementAwareModels() {
List<SamplingOperationDTO> samplingOperations = Lists.newArrayList(getModel().getSamplingOperations());
// sort by name
samplingOperations.sort(Comparator.comparing(SamplingOperationDTO::getName));
return samplingOperations;
return getModel().getSamplingOperations().stream()
// sort by name
.sorted(Comparator.comparing(SamplingOperationDTO::getName))
.collect(Collectors.toList());
}
@Override
......@@ -205,7 +220,7 @@ public class OperationMeasurementsGroupedTableUIHandler
@Override
protected void onRowModified(int rowIndex, OperationMeasurementsGroupedRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
// update individual id when sampling operation changes
// when sampling operation changes
if (OperationMeasurementsGroupedRowModel.PROPERTY_SAMPLING_OPERATION.equals(propertyName)) {
// remove measurement from old sampling
......@@ -235,6 +250,14 @@ public class OperationMeasurementsGroupedTableUIHandler
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) {
......@@ -421,15 +444,14 @@ public class OperationMeasurementsGroupedTableUIHandler
for (Integer transition : initModel.getResultMap().get(samplingOperation)) {
// Compute next individual id
incrementNextIndividualId(samplingOperation, individualId);
OperationMeasurementsGroupedRowModel row = getTableModel().createNewRow();
// Initialize the row
row.setSamplingOperation(samplingOperation);
// Affect individual pmfms from parent model
row.setIndividualPmfms(new ArrayList<>(getModel().getPmfms()));
OperationMeasurementsGroupedRowModel row = createNewRow(false, samplingOperation);
// Set the individualId
row.setIndividualId(individualId.get());
// Affect individual pmfms from parent model
row.setIndividualPmfms(new ArrayList<>(getModel().getPmfms()));
// Create empty measurements
ReefDbBeans.createEmptyMeasurements(row);
// Get the measurement
......@@ -452,14 +474,6 @@ public class OperationMeasurementsGroupedTableUIHandler
}
}
private void incrementNextIndividualId(SamplingOperationDTO samplingOperation, AtomicInteger nextIndividualId) {
do {
nextIndividualId.incrementAndGet();
} while (getModel().getRows().stream().anyMatch(row ->
samplingOperation.equals(row.getSamplingOperation()) && nextIndividualId.get() == row.getIndividualId()));
}
public void editSelectedMeasurements() {
OperationMeasurementsMultiEditUI editUI = new OperationMeasurementsMultiEditUI(getUI());
......
......@@ -44,6 +44,7 @@ public class OperationMeasurementsGroupedTableUIModel
* property identifier used to propagate row sampling operation property change to parent
*/
public static final String PROPERTY_SAMPLING_OPERATION = "samplingOperation";
public static final String PROPERTY_PIT_TRANSITION_LENGTH_PMFM_ID = "pitTransitionLengthPmfmId";
// pmfm ids for grid initialization (pit protocol)
private Integer pitTransectOriginPmfmId;
......@@ -85,6 +86,7 @@ public class OperationMeasurementsGroupedTableUIModel
public void setPitTransitionLengthPmfmId(Integer pitTransitionLengthPmfmId) {
this.pitTransitionLengthPmfmId = pitTransitionLengthPmfmId;
firePropertyChange(PROPERTY_PIT_TRANSITION_LENGTH_PMFM_ID, null, pitTransitionLengthPmfmId);
}
public boolean isPitTransitionGridInitializationEnabled() {
......
......@@ -170,7 +170,7 @@ public class OperationMeasurementsUngroupedTableUIHandler extends AbstractReefDb
filterSamplingOperations();
// restore table from swing session
getContext().restoreComponentFromSwingSession(getTable());
restoreTableState();
// hide analyst if no pmfm
// forceColumnVisibleAtLastPosition(OperationMeasurementsUngroupedTableModel.ANALYST, notEmpty);
......
package fr.ifremer.reefdb.ui.swing.content.observation.survey.measurement.grouped;
/*
* #%L
* Reef DB :: UI
* $Id:$
* $HeadURL:$
* %%
* Copyright (C) 2014 - 2015 Ifremer
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import fr.ifremer.reefdb.ui.swing.action.AbstractReefDbAction;
/**
* Action dupliquer mesure (ecran observation/mesure).
*/
public class DuplicateSurveyMeasurementsAction extends AbstractReefDbAction<SurveyMeasurementsGroupedTableUIModel, SurveyMeasurementsGroupedTableUI, SurveyMeasurementsGroupedTableUIHandler> {
/**
* La ligne ajoutee.
*/
private SurveyMeasurementsGroupedRowModel row;
/**
* Constrcuteur.
*
* @param handler Controller
*/
public DuplicateSurveyMeasurementsAction(final SurveyMeasurementsGroupedTableUIHandler handler) {
super(handler, false);
}