Commit 731d6aa8 authored by PECQUOT's avatar PECQUOT
Browse files

Merge branch 'develop' into feature/obsdeb

# Conflicts:
#	pom.xml
#	sumaris-core-extraction/pom.xml
#	sumaris-core-importation/pom.xml
#	sumaris-core-rdf/pom.xml
#	sumaris-core-shared/pom.xml
#	sumaris-core/pom.xml
#	sumaris-server/pom.xml
#	sumaris-test-shared/pom.xml
parents c2a40875 8e7d76e1
......@@ -3,7 +3,7 @@
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.9.0-SNAPSHOT</version>
<version>1.9.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>SUMARiS</name>
<description>SUMARiS :: Maven parent</description>
......
......@@ -8,31 +8,23 @@ if [[ "_" == "_${PROJECT_DIR}" ]]; then
fi;
cd ${PROJECT_DIR}
### Control that the script is run on `dev` branch
branch=`git rev-parse --abbrev-ref HEAD`
if [[ ! "$branch" = "release/$version" ]];
then
echo ">> This script must be run under a release branch (release/$version)"
exit 1
fi
### Variables
task=$1
version=$2
release_description=$3
release_description=$2
PROJECT_NAME=sumaris-pod
REPO="sumaris-net/sumaris-pod"
REPO_API_URL=https://api.github.com/repos/$REPO
REPO_PUBLIC_URL=https://github.com/$REPO
### Get version to release
current=`grep -m1 -P "\<version>[0-9A−Z.]+(-\w*)?</version>" pom.xml | grep -oP "\d+.\d+.\d+(-\w*)?"`
if [[ "_$current" == "_" ]]; then
version=`grep -m1 -P "\<version>[0-9A−Z.]+(-\w*)?</version>" pom.xml | grep -oP "\d+.\d+.\d+(-\w*)?"`
if [[ "_$version" == "_" ]]; then
echo "ERROR: Unable to read 'version' in the file 'pom.xml'."
echo " - Make sure the file 'pom.xml' exists and is readable."
exit 1
fi
echo "Current version: $current"
echo "Project version (pom.xml): $version"
### get auth token
if [[ "_${GITHUB_TOKEN}" == "_" ]]; then
......@@ -51,7 +43,7 @@ fi
case "$task" in
del)
result=`curl -i "$REPO_API_URL/releases/tags/$current"`
result=`curl -i "$REPO_API_URL/releases/tags/$version"`
release_url=`echo "$result" | grep -P "\"url\": \"[^\"]+" | grep -oP "$REPO_API_URL/releases/\d+"`
if [[ $release_url != "" ]]; then
echo "Deleting existing release..."
......@@ -61,6 +53,15 @@ case "$task" in
pre|rel)
### Control that the script is run on `dev` branch
branch=`git rev-parse --abbrev-ref HEAD`
echo "GIT branch: $branch"
if [[ ! "$branch" = "release/$version" ]];
then
echo ">> This script must be run under a release branch (release/$version)"
exit 1
fi
if [[ $1 = "pre" ]]; then
prerelease="true"
else
......@@ -69,10 +70,10 @@ case "$task" in
description=`echo $release_description`
if [[ "_$description" = "_" ]]; then
description="Release $current"
description="Release $version"
fi
result=`curl -s -H ''"$GITHUT_AUTH"'' "$REPO_API_URL/releases/tags/$current"`
result=`curl -s -H ''"$GITHUT_AUTH"'' "$REPO_API_URL/releases/tags/$version"`
release_url=`echo "$result" | grep -P "\"url\": \"[^\"]+" | grep -oP "https://[A-Za-z0-9/.-]+/releases/\d+"`
if [[ "_$release_url" != "_" ]]; then
echo "Deleting existing release... $release_url"
......@@ -87,9 +88,9 @@ case "$task" in
fi
echo "Creating new release..."
echo " - tag: $current"
echo " - tag: $version"
echo " - description: $description"
result=`curl -H ''"$GITHUT_AUTH"'' -s $REPO_API_URL/releases -d '{"tag_name": "'"$current"'","target_commitish": "master","name": "'"$current"'","body": "'"$description"'","draft": false,"prerelease": '"$prerelease"'}'`
result=`curl -H ''"$GITHUT_AUTH"'' -s $REPO_API_URL/releases -d '{"tag_name": "'"$version"'","target_commitish": "master","name": "'"$version"'","body": "'"$description"'","draft": false,"prerelease": '"$prerelease"'}'`
upload_url=`echo "$result" | grep -P "\"upload_url\": \"[^\"]+" | grep -oP "https://[A-Za-z0-9/.-]+"`
if [[ "_$upload_url" = "_" ]]; then
......@@ -102,12 +103,12 @@ case "$task" in
### Sending files
echo "Uploading files to $upload_url ..."
WAR_FILE="${PROJECT_DIR}/sumaris-server/target/sumaris-server-$current.war"
WAR_FILE="${PROJECT_DIR}/sumaris-server/target/sumaris-server-$version.war"
if [[ ! -f "${WAR_FILE}" ]]; then
echo "ERROR: Missing WAR artifact: ${WAR_FILE}. Skipping upload"
missing_file=true
else
artifact_name="sumaris-pod-$current.war"
artifact_name="sumaris-pod-$version.war"
result=$(curl -s -H ''"$GITHUT_AUTH"'' -H 'Content-Type: application/zip' -T "${WAR_FILE}" "${upload_url}?name=${artifact_name}")
browser_download_url=`echo "$result" | grep -P "\"browser_download_url\":[ ]?\"[^\"]+" | grep -oP "\"browser_download_url\":[ ]?\"[^\"]+" | grep -oP "https://[A-Za-z0-9/.-]+"`
SHA256=$(sha256sum "${WAR_FILE}" | sed 's/ /\n/gi' | head -n 1)
......@@ -117,12 +118,12 @@ case "$task" in
result=$(curl -s -H ''"$GITHUT_AUTH"'' -H 'Content-Type: text/plain' -T "${WAR_FILE}.sha256" "${upload_url}?name=${artifact_name}.sha256")
fi
ZIP_FILE="${PROJECT_DIR}/sumaris-server/target/sumaris-server-$current-standalone.zip"
ZIP_FILE="${PROJECT_DIR}/sumaris-server/target/sumaris-server-$version-standalone.zip"
if [[ ! -f "${ZIP_FILE}" ]]; then
echo "ERROR: Missing ZIP artifact: ${ZIP_FILE}. Skipping upload"
missing_file=true
else
artifact_name="sumaris-pod-$current.zip"
artifact_name="sumaris-pod-$version.zip"
result=$(curl -s -H ''"$GITHUT_AUTH"'' -H 'Content-Type: application/zip' -T "${ZIP_FILE}" "${upload_url}?name=${ZIP_FILENAME}")
browser_download_url=`echo "$result" | grep -P "\"browser_download_url\":[ ]?\"[^\"]+" | grep -oP "\"browser_download_url\":[ ]?\"[^\"]+" | grep -oP "https://[A-Za-z0-9/.-]+"`
SHA256=$(sha256sum "${ZIP_FILE}" | sed 's/ /\n/gi' | head -n 1)
......@@ -132,12 +133,12 @@ case "$task" in
result=$(curl -s -H ''"$GITHUT_AUTH"'' -H 'Content-Type: text/plain' -T "${ZIP_FILE}.sha256" "${upload_url}?name=${artifact_name}.sha256")
fi
DB_FILE="${PROJECT_DIR}/sumaris-core/target/sumaris-db-$current.zip"
DB_FILE="${PROJECT_DIR}/sumaris-core/target/sumaris-db-$version.zip"
if [[ ! -f "${DB_FILE}" ]]; then
echo "ERROR: Missing DB ZIP artifact: ${DB_FILE}. Skipping uppload"
missing_file=true
else
artifact_name="sumaris-db-$current.zip"
artifact_name="sumaris-db-$version.zip"
result=$(curl -s -H ''"$GITHUT_AUTH"'' -H 'Content-Type: application/zip' -T "${DB_FILE}" "${upload_url}?name=${artifact_name}")
browser_download_url=`echo "$result" | grep -P "\"browser_download_url\":[ ]?\"[^\"]+" | grep -oP "\"browser_download_url\":[ ]?\"[^\"]+" | grep -oP "https://[A-Za-z0-9/.-]+"`
SHA256=$(sha256sum "${DB_FILE}" | sed 's/ /\n/gi' | head -n 1)
......@@ -150,13 +151,13 @@ case "$task" in
if [[ ${missing_file} == true ]]; then
echo "-----------------------------------------"
echo "ERROR: missing some artifacts (see logs)"
echo " -> Release url: ${REPO_PUBLIC_URL}/releases/tag/${current}"
echo " -> Release url: ${REPO_PUBLIC_URL}/releases/tag/${version}"
# Continue if error
exit 1
else
echo "-----------------------------------------"
echo "Successfully uploading files !"
echo " -> Release url: ${REPO_PUBLIC_URL}/releases/tag/${current}"
echo " -> Release url: ${REPO_PUBLIC_URL}/releases/tag/${version}"
exit 0
fi
......
......@@ -33,7 +33,7 @@ if [[ ! $task =~ ^(pre|rel)$ || ! $version =~ ^[0-9]+.[0-9]+.[0-9]+(-(alpha|beta
exit 1
fi
echo "---- Starting release $version ($task)"...
echo "---- Creating release $version ($task)"...
echo ""
# Removing existing release branche
......@@ -79,6 +79,17 @@ git branch -d "release/$version"
echo "---- Push changes to upstream [OK]"
echo ""
# Uploading artifacts to Github
echo "---- Uploading artifacts to Github..."
# Pause (wait propagation to from gitlab to github)
echo " Waiting 40s, for propagation to github..." && sleep 40s
. ${PROJECT_DIR}/src/scripts/release-to-github.sh $task ''"$release_description"''
[[ $? -ne 0 ]] && exit 1
echo "---- Uploading artifacts to Github [OK]"
echo ""
echo "----------------------------------"
echo "RELEASE finished!"
echo "----------------------------------"
Subproject commit 3b6e149ac009099f8234c3825cf8bb3bacb01f97
Subproject commit 7a81f76fac53e140fcd83394212b153bc9de24a0
......@@ -148,7 +148,7 @@ To change the Pod's configuration, follow this steps:
Your configuration file should have been processed.
## Build from source (database + Pod)
## Build from source
1. Installe project dependencies:
* Install build tools (Make, GCC, Git)
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.9.0-SNAPSHOT</version>
<version>1.9.1-SNAPSHOT</version>
</parent>
<artifactId>sumaris-core-extraction</artifactId>
......
......@@ -255,6 +255,7 @@ public class ExtractionStrategyDaoImpl<C extends ExtractionStrategyContextVO, F
// Bind some referential ids
xmlQuery.bind("strategyLabelPmfmId", String.valueOf(PmfmEnum.STRATEGY_LABEL.getId()));
xmlQuery.bind("tagIdPmfmId", String.valueOf(PmfmEnum.TAG_ID.getId()));
return xmlQuery;
}
......
......@@ -35,7 +35,7 @@
<!-- TODO: EFFORT à renommer en ??? -->
<select alias="EXPECTED_EFFORT" type="number">APP.ACQUISITION_NUMBER</select>
<select alias="REALIZED_EFFORT" type="number">count(distinct S.ID)</select>
<select alias="REALIZED_EFFORT" type="number">count(distinct SM.ID)</select>
<!--<select alias="SAMPLE_COUNT" type="number">count(distinct S.ID)</select>-->
<select alias="LANDING_COUNT" type="number">count(distinct L.ID)</select>
......@@ -61,6 +61,7 @@
)
</from>
<from join="true">LEFT OUTER JOIN SAMPLE S ON S.LANDING_FK = L.ID</from>
<from join="true">LEFT OUTER JOIN SAMPLE_MEASUREMENT SM ON SM.SAMPLE_FK = S.ID AND SM.PMFM_FK = &amp;tagIdPmfmId</from>
<groupby>
ST.PROJECT, ST.STRATEGY,
......
......@@ -3,7 +3,7 @@
<parent>
<artifactId>sumaris-pod</artifactId>
<groupId>net.sumaris</groupId>
<version>1.9.0-SNAPSHOT</version>
<version>1.9.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -3,7 +3,7 @@
<parent>
<artifactId>sumaris-pod</artifactId>
<groupId>net.sumaris</groupId>
<version>1.9.0-SNAPSHOT</version>
<version>1.9.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.9.0-SNAPSHOT</version>
<version>1.9.1-SNAPSHOT</version>
</parent>
<artifactId>sumaris-core-shared</artifactId>
......
......@@ -900,6 +900,10 @@ public class SumarisConfiguration extends PropertyPlaceholderConfigurer {
return applicationConfig.getOptionAsBoolean(SumarisConfigurationOption.ENABLE_SAMPLE_HASH_OPTIMIZATION.getKey());
}
public boolean enableSampleUniqueTag() {
return applicationConfig.getOptionAsBoolean(SumarisConfigurationOption.ENABLE_SAMPLE_UNIQUE_TAG.getKey());
}
public String getVesselDefaultProgramLabel() {
return applicationConfig.getOption(SumarisConfigurationOption.VESSEL_DEFAULT_PROGRAM_LABEL.getKey());
}
......
......@@ -571,6 +571,13 @@ public enum SumarisConfigurationOption implements ConfigOptionDef {
Boolean.class,
false),
ENABLE_SAMPLE_UNIQUE_TAG(
"sumaris.persistence.sample.uniqueTag",
n("sumaris.config.option.persistence.sample.uniqueTag.description"),
Boolean.FALSE.toString(),
Boolean.class,
false),
VESSEL_DEFAULT_PROGRAM_LABEL(
"sumaris.persistence.vessel.defaultProgram.label",
n("sumaris.config.option.persistence.vessel.defaultProgram.label.description"),
......
package net.sumaris.core.dao.technical.jdbc;
/*-
* #%L
* SUMARiS:: Core shared
* %%
* Copyright (C) 2018 - 2021 SUMARiS Consortium
* %%
* 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 java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
......
......@@ -70,6 +70,7 @@ sumaris.config.option.persistence.jndi-name.description=
sumaris.config.option.persistence.qualityFlagId.default.description=
sumaris.config.option.persistence.qualityFlagId.description=
sumaris.config.option.persistence.sample.hashOptimization.description=
sumaris.config.option.persistence.sample.uniqueTag.description=
sumaris.config.option.persistence.sequence.increment.description=
sumaris.config.option.persistence.sequence.startWith.description=
sumaris.config.option.persistence.sequence.suffix.description=
......
......@@ -70,6 +70,7 @@ sumaris.config.option.persistence.jndi-name.description=
sumaris.config.option.persistence.qualityFlagId.default.description=
sumaris.config.option.persistence.qualityFlagId.description=
sumaris.config.option.persistence.sample.hashOptimization.description=Enable save optimization (table SAMPLE) using hash code (beta)
sumaris.config.option.persistence.sample.uniqueTag.description=
sumaris.config.option.persistence.sequence.increment.description=
sumaris.config.option.persistence.sequence.startWith.description=
sumaris.config.option.persistence.sequence.suffix.description=
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.9.0-SNAPSHOT</version>
<version>1.9.1-SNAPSHOT</version>
</parent>
<artifactId>sumaris-core</artifactId>
......
......@@ -98,6 +98,8 @@ public class SampleRepositoryImpl
.and(hasLandingId(filter.getLandingId()))
.and(hasObservedLocationId(filter.getObservedLocationId()))
.and(inObservedLocationIds(filter.getObservedLocationIds()))
.and(hasTagId(filter.getTagId()))
.and(withTagId(filter.getWithTagId()))
.and(addJoinFetch(fetchOptions, true));
}
......
......@@ -27,12 +27,15 @@ import net.sumaris.core.dao.technical.jpa.BindableSpecification;
import net.sumaris.core.dao.technical.model.IEntity;
import net.sumaris.core.model.data.Landing;
import net.sumaris.core.model.data.Sample;
import net.sumaris.core.model.data.SampleMeasurement;
import net.sumaris.core.model.referential.pmfm.PmfmEnum;
import net.sumaris.core.vo.data.LandingVO;
import net.sumaris.core.vo.data.sample.SampleFetchOptions;
import net.sumaris.core.vo.data.sample.SampleVO;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ParameterExpression;
import java.util.Arrays;
......@@ -45,6 +48,8 @@ import java.util.List;
public interface SampleSpecifications extends RootDataSpecifications<Sample> {
String OBSERVED_LOCATION_IDS = "observedLocationIds";
String TAG_ID_PMFM_ID = "tagIdPmfmId";
String TAG_ID = "tagId";
default Specification<Sample> hasOperationId(Integer operationId) {
if (operationId == null) return null;
......@@ -76,7 +81,11 @@ public interface SampleSpecifications extends RootDataSpecifications<Sample> {
BindableSpecification<Sample> specification = BindableSpecification.where((root, query, criteriaBuilder) -> {
query.orderBy(criteriaBuilder.asc(root.get(Sample.Fields.RANK_ORDER)));
ParameterExpression<Integer> param = criteriaBuilder.parameter(Integer.class, LandingVO.Fields.OBSERVED_LOCATION_ID);
return criteriaBuilder.equal(root.get(Sample.Fields.LANDING).get(Landing.Fields.OBSERVED_LOCATION).get(IEntity.Fields.ID), param);
return criteriaBuilder.equal(
root.join(Sample.Fields.LANDING, JoinType.INNER)
.join(Landing.Fields.OBSERVED_LOCATION, JoinType.INNER)
.get(IEntity.Fields.ID),
param);
});
specification.addBind(LandingVO.Fields.OBSERVED_LOCATION_ID, observedLocationId);
return specification;
......@@ -87,12 +96,45 @@ public interface SampleSpecifications extends RootDataSpecifications<Sample> {
BindableSpecification<Sample> specification = BindableSpecification.where((root, query, criteriaBuilder) -> {
query.orderBy(criteriaBuilder.asc(root.get(Sample.Fields.RANK_ORDER)));
ParameterExpression<Collection> param = criteriaBuilder.parameter(Collection.class, OBSERVED_LOCATION_IDS);
return criteriaBuilder.in(root.get(Sample.Fields.LANDING).get(Landing.Fields.OBSERVED_LOCATION).get(IEntity.Fields.ID)).value(param);
return criteriaBuilder.in(
root.join(Sample.Fields.LANDING, JoinType.INNER)
.join(Landing.Fields.OBSERVED_LOCATION, JoinType.INNER)
.get(IEntity.Fields.ID))
.value(param);
});
specification.addBind(OBSERVED_LOCATION_IDS, Arrays.asList(observedLocationIds));
return specification;
}
default Specification<Sample> hasTagId(String tagId) {
if (tagId == null) return null;
BindableSpecification<Sample> specification = BindableSpecification.where((root, query, criteriaBuilder) -> {
query.orderBy(criteriaBuilder.asc(root.get(Sample.Fields.RANK_ORDER)));
ParameterExpression<Integer> tagIdPmfmIdParam = criteriaBuilder.parameter(Integer.class, TAG_ID_PMFM_ID);
ParameterExpression<String> tagIdParam = criteriaBuilder.parameter(String.class, TAG_ID);
Join<Sample, SampleMeasurement> tagIdInnerJoin = root.joinList(Sample.Fields.MEASUREMENTS, JoinType.INNER);
return criteriaBuilder.and(
criteriaBuilder.equal(tagIdInnerJoin.get(SampleMeasurement.Fields.PMFM).get(IEntity.Fields.ID), tagIdPmfmIdParam),
criteriaBuilder.equal(tagIdInnerJoin.get(SampleMeasurement.Fields.ALPHANUMERICAL_VALUE), tagIdParam)
);
});
specification.addBind(TAG_ID_PMFM_ID, PmfmEnum.TAG_ID.getId());
specification.addBind(TAG_ID, tagId);
return specification;
}
default Specification<Sample> withTagId(Boolean withTagId) {
if (!Boolean.TRUE.equals(withTagId)) return null;
BindableSpecification<Sample> specification = BindableSpecification.where((root, query, criteriaBuilder) -> {
query.orderBy(criteriaBuilder.asc(root.get(Sample.Fields.RANK_ORDER)));
ParameterExpression<Integer> tagIdPmfmIdParam = criteriaBuilder.parameter(Integer.class, TAG_ID_PMFM_ID);
Join<Sample, SampleMeasurement> tagIdInnerJoin = root.joinList(Sample.Fields.MEASUREMENTS, JoinType.INNER);
return criteriaBuilder.equal(tagIdInnerJoin.get(SampleMeasurement.Fields.PMFM).get(IEntity.Fields.ID), tagIdPmfmIdParam);
});
specification.addBind(TAG_ID_PMFM_ID, PmfmEnum.TAG_ID.getId());
return specification;
}
default Specification<Sample> addJoinFetch(SampleFetchOptions fetchOptions, boolean addQueryDistinct) {
if (fetchOptions == null || !fetchOptions.isWithMeasurementValues()) return null;
......
......@@ -25,11 +25,14 @@ package net.sumaris.core.service.data;
import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import net.sumaris.core.config.SumarisConfiguration;
import net.sumaris.core.dao.data.MeasurementDao;
import net.sumaris.core.dao.data.sample.SampleRepository;
import net.sumaris.core.exception.NotUniqueException;
import net.sumaris.core.model.data.IMeasurementEntity;
import net.sumaris.core.model.data.SampleMeasurement;
import net.sumaris.core.model.referential.pmfm.MatrixEnum;
import net.sumaris.core.model.referential.pmfm.PmfmEnum;
import net.sumaris.core.util.Beans;
import net.sumaris.core.vo.data.MeasurementVO;
import net.sumaris.core.vo.data.sample.SampleFetchOptions;
......@@ -48,6 +51,9 @@ import java.util.stream.Collectors;
@Slf4j
public class SampleServiceImpl implements SampleService {
@Autowired
private SumarisConfiguration configuration;
@Autowired
protected SampleRepository sampleRepository;
......@@ -168,6 +174,7 @@ public class SampleServiceImpl implements SampleService {
protected void saveMeasurements(List<SampleVO> result) {
result.forEach(savedSample -> {
checkUniqueTag(savedSample);
if (savedSample.getMeasurementValues() != null) {
measurementDao.saveSampleMeasurementsMap(savedSample.getId(), savedSample.getMeasurementValues());
}
......@@ -180,6 +187,33 @@ public class SampleServiceImpl implements SampleService {
});
}
private void checkUniqueTag(SampleVO savedSample) {
if (!configuration.enableSampleUniqueTag()) return;
String savedSampleTagId = null;
// Get tag_id measurement
if (savedSample.getMeasurementValues() != null) {
savedSampleTagId = savedSample.getMeasurementValues().get(PmfmEnum.TAG_ID.getId());
} else if (savedSample.getMeasurements() != null) {
savedSampleTagId = savedSample.getMeasurements().stream()
.filter(m -> m.getId() == PmfmEnum.TAG_ID.getId())
.map(m -> m.getAlphanumericalValue())
.findFirst().orElse(null);
}
// Check if tag_id is unique by program
if (savedSampleTagId != null) {
long count = sampleRepository.findAll(SampleFilterVO.builder()
.programLabel(savedSample.getProgram().getLabel()).tagId(savedSampleTagId).build())
.stream()
.filter(s -> savedSample.getId() == null || !Objects.equals(s.getId(), savedSample.getId()))
.count();
if (count > 0) {
throw new NotUniqueException(String.format("Sample tag measurement '%s' already exists", savedSampleTagId));
}
}
}
protected void fillDefaultProperties(SampleVO parent, MeasurementVO measurement, Class<? extends IMeasurementEntity> entityClass) {
if (measurement == null) return;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment