Commit af4bd99c authored by LAVENIER's avatar LAVENIER
Browse files

Merge branch 'release/1.7.0'

parents 8919db0d d095f4b7
......@@ -3,7 +3,7 @@
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.6.6</version>
<version>1.7.0</version>
<packaging>pom</packaging>
<name>SUMARiS</name>
<description>SUMARiS :: Maven parent</description>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.6.6</version>
<version>1.7.0</version>
</parent>
<artifactId>sumaris-core-extraction</artifactId>
......
......@@ -299,6 +299,12 @@ public class AggregationServiceImpl implements AggregationService {
}
@Override
@Caching(
evict = {
@CacheEvict(cacheNames = ExtractionCacheNames.AGGREGATION_TYPE_BY_ID, allEntries = true),
@CacheEvict(cacheNames = ExtractionCacheNames.AGGREGATION_TYPE_BY_FORMAT, allEntries = true)
}
)
public CompletableFuture<AggregationTypeVO> asyncSave(AggregationTypeVO type, @Nullable ExtractionFilterVO filter) {
return CompletableFuture.completedFuture(save(type, filter));
}
......@@ -308,9 +314,6 @@ public class AggregationServiceImpl implements AggregationService {
evict = {
@CacheEvict(cacheNames = ExtractionCacheNames.AGGREGATION_TYPE_BY_ID, allEntries = true),
@CacheEvict(cacheNames = ExtractionCacheNames.AGGREGATION_TYPE_BY_FORMAT, allEntries = true)
},
put = {
@CachePut(cacheNames= ExtractionCacheNames.AGGREGATION_TYPE_BY_ID, key="#result.id", condition = " #result.id != null")
}
)
public AggregationTypeVO save(AggregationTypeVO type, @Nullable ExtractionFilterVO filter) {
......@@ -324,9 +327,6 @@ public class AggregationServiceImpl implements AggregationService {
if (type.getId() != null) {
target = productService.findById(type.getId(), ExtractionProductFetchOptions.FOR_UPDATE).orElse(null);
}
boolean isNew = target == null;
if (isNew) {
target = new ExtractionProductVO();
......@@ -371,6 +371,7 @@ public class AggregationServiceImpl implements AggregationService {
target.setName(type.getName());
target.setUpdateDate(type.getUpdateDate());
target.setDescription(type.getDescription());
target.setDocumentation(type.getDocumentation());
target.setStatusId(type.getStatusId());
target.setRecorderDepartment(type.getRecorderDepartment());
target.setRecorderPerson(type.getRecorderPerson());
......@@ -382,6 +383,7 @@ public class AggregationServiceImpl implements AggregationService {
target.setName(type.getName());
target.setUpdateDate(type.getUpdateDate());
target.setDescription(type.getDescription());
target.setDocumentation(type.getDocumentation());
target.setComments(type.getComments());
target.setStatusId(type.getStatusId());
target.setUpdateDate(type.getUpdateDate());
......
......@@ -58,6 +58,9 @@ public interface ExtractionService {
@Transactional(readOnly = true)
List<ExtractionTypeVO> findByFilter(@Nullable ExtractionTypeFilterVO filter);
@Transactional(readOnly = true)
List<ExtractionTypeVO> getLiveExtractionTypes();
ExtractionContextVO execute(IExtractionFormat format, @Nullable ExtractionFilterVO filter);
ExtractionResultVO read(ExtractionContextVO context,
......
......@@ -165,6 +165,25 @@ public class ExtractionServiceImpl implements ExtractionService {
return ExtractionFormats.findOneMatch(this.getAllTypes(), format);
}
@Override
public List<ExtractionTypeVO> getLiveExtractionTypes() {
MutableInt id = new MutableInt(-1);
return Arrays.stream(LiveFormatEnum.values())
.map(format -> {
ExtractionTypeVO type = new ExtractionTypeVO();
type.setId(id.getValue());
type.setLabel(format.getLabel().toLowerCase());
type.setCategory(ExtractionCategoryEnum.LIVE);
type.setSheetNames(format.getSheetNames());
type.setStatusId(StatusEnum.TEMPORARY.getId()); // = not public by default
type.setVersion(format.getVersion());
type.setLiveFormat(format);
id.decrement();
return type;
})
.collect(Collectors.toList());
}
@Override
public List<ExtractionTypeVO> findByFilter(ExtractionTypeFilterVO filter) {
ImmutableList.Builder<ExtractionTypeVO> builder = ImmutableList.builder();
......@@ -177,14 +196,14 @@ public class ExtractionServiceImpl implements ExtractionService {
boolean includeLiveTypes = ArrayUtils.contains(filter.getStatusIds(), StatusEnum.TEMPORARY.getId()) &&
filter.getRecorderPersonId() == null;
ExtractionCategoryEnum filterCategory = ExtractionCategoryEnum.fromString(filter.getCategory()).orElse(null);
// Add live extraction types (= private by default)
if (includeLiveTypes && (filter.getCategory() == null || filter.getCategory().equalsIgnoreCase(ExtractionCategoryEnum.LIVE.name()))) {
if (includeLiveTypes && (filterCategory == null || filterCategory == ExtractionCategoryEnum.LIVE)) {
builder.addAll(getLiveExtractionTypes());
}
// Add product types
ExtractionCategoryEnum filterCategory = ExtractionCategoryEnum.fromString(filter.getCategory()).orElse(null);
if (filterCategory == null || filterCategory == ExtractionCategoryEnum.PRODUCT) {
builder.addAll(getProductExtractionTypes(filter));
}
......@@ -464,10 +483,15 @@ public class ExtractionServiceImpl implements ExtractionService {
return findByFilter(null);
}
/**
* @deprecated
* @param filter
* @return
*/
@Deprecated
protected List<ExtractionTypeVO> getProductExtractionTypes(ExtractionTypeFilterVO filter) {
Preconditions.checkNotNull(filter);
return ListUtils.emptyIfNull(
extractionProductRepository.findAll(filter, ExtractionProductFetchOptions.builder()
.withRecorderDepartment(true)
......@@ -478,23 +502,6 @@ public class ExtractionServiceImpl implements ExtractionService {
.collect(Collectors.toList());
}
protected List<ExtractionTypeVO> getLiveExtractionTypes() {
MutableInt id = new MutableInt(-1);
return Arrays.stream(LiveFormatEnum.values())
.map(format -> {
ExtractionTypeVO type = new ExtractionTypeVO();
type.setId(id.getValue());
type.setLabel(format.getLabel().toLowerCase());
type.setCategory(ExtractionCategoryEnum.LIVE);
type.setSheetNames(format.getSheetNames());
type.setStatusId(StatusEnum.TEMPORARY.getId()); // = not public by default
type.setVersion(format.getVersion());
type.setLiveFormat(format);
id.decrement();
return type;
})
.collect(Collectors.toList());
}
protected ExtractionResultVO extractLiveAndRead(ExtractionTypeVO type,
......
......@@ -248,7 +248,10 @@ public class AggregationGraphQLService {
// Columns not need
.withColumns(false)
// Stratum
.withStratum(fields.contains(AggregationTypeVO.Fields.STRATUM))
.withStratum(
fields.contains(StringUtils.slashing(AggregationTypeVO.Fields.STRATUM, IEntity.Fields.ID))
|| fields.contains(StringUtils.slashing(AggregationTypeVO.Fields.STRATUM, ExtractionProductStrataVO.Fields.SPATIAL_COLUMN_NAME))
)
.build();
}
......
......@@ -57,7 +57,7 @@ public class ExtractionGraphQLService {
@Autowired
private ExtractionSecurityService securityService;
@GraphQLQuery(name = "extractionTypes", description = "Get all available extraction types")
@GraphQLQuery(name = "extractionTypes", description = "Get all available extraction types", deprecationReason = "Use liveExtractionTypes and aggregationTypes")
@Transactional(readOnly = true)
public List<ExtractionTypeVO> getAllExtractionTypes(@GraphQLArgument(name = "filter") ExtractionTypeFilterVO filter) {
......@@ -66,6 +66,15 @@ public class ExtractionGraphQLService {
return extractionService.findByFilter(filter);
}
@GraphQLQuery(name = "liveExtractionTypes", description = "Get all live extraction types")
@Transactional(readOnly = true)
public List<ExtractionTypeVO> getLiveExtractionTypes(@GraphQLArgument(name = "filter") ExtractionTypeFilterVO filter) {
filter = securityService.sanitizeFilter(filter);
return extractionService.findByFilter(filter);
}
@GraphQLQuery(name = "extractionRows", description = "Preview some extraction rows")
@Transactional
public ExtractionResultVO getExtractionRows(@GraphQLArgument(name = "type") ExtractionTypeVO type,
......
......@@ -163,7 +163,7 @@ public class ExtractionSecurityServiceImpl implements ExtractionSecurityService
if (canReadAll()) return result;
return getAuthenticatedUser().filter(Objects::nonNull)
return getAuthenticatedUser()
// Known user: restrict to self data - issue #199
.map(user -> {
......
......@@ -28,16 +28,16 @@
<subquery>
<subselect alias="TRIP_CODE" type="number">T.TRIP_CODE</subselect>
<subselect alias="VESSEL_IDENTIFIER" type="number">T.VESSEL_IDENTIFIER</subselect>
<subselect alias="VESSEL_LENGTH_CLASS" type="text">
<subselect alias="VESSEL_LENGTH_CLASS" type="text"><![CDATA[
CASE
WHEN (T.VESSEL_LENGTH &lt; 6) THEN '0-6'
WHEN (T.VESSEL_LENGTH &lt; 10) THEN '6-10'
WHEN (T.VESSEL_LENGTH &lt; 12) THEN '10-12'
WHEN (T.VESSEL_LENGTH &lt; 15) THEN '12-15'
WHEN (T.VESSEL_LENGTH &lt; 24) THEN '15-24'
WHEN (T.VESSEL_LENGTH &lt; 40) THEN '24-40'
WHEN (T.VESSEL_LENGTH &gt;= 40) THEN '&gt;=40'
END CASE</subselect>
WHEN (T.VESSEL_LENGTH < 6) THEN '0-6'
WHEN (T.VESSEL_LENGTH < 10) THEN '6-10'
WHEN (T.VESSEL_LENGTH < 12) THEN '10-12'
WHEN (T.VESSEL_LENGTH < 15) THEN '12-15'
WHEN (T.VESSEL_LENGTH < 24) THEN '15-24'
WHEN (T.VESSEL_LENGTH < 40) THEN '24-40'
WHEN (T.VESSEL_LENGTH >= 40) THEN '>=40'
END CASE]]></subselect>
<subselect alias="NUMBER_OF_SETS" type="number">T.NUMBER_OF_SETS</subselect>
<subselect alias="FISHING_TIME" type="number">(SELECT SUM(FISHING_TIME) FROM &amp;rawStationTableName WHERE TRIP_CODE=T.TRIP_CODE)</subselect>
......
......@@ -3,7 +3,7 @@
<parent>
<artifactId>sumaris-pod</artifactId>
<groupId>net.sumaris</groupId>
<version>1.6.6</version>
<version>1.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -3,7 +3,7 @@
<parent>
<artifactId>sumaris-pod</artifactId>
<groupId>net.sumaris</groupId>
<version>1.6.6</version>
<version>1.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.6.6</version>
<version>1.7.0</version>
</parent>
<artifactId>sumaris-core-shared</artifactId>
......
......@@ -27,6 +27,7 @@ package net.sumaris.core.dao.technical;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import net.sumaris.core.config.SumarisConfiguration;
import net.sumaris.core.dao.technical.model.IEntity;
import net.sumaris.core.dao.technical.model.IUpdateDateEntityBean;
import net.sumaris.core.exception.BadUpdateDateException;
import net.sumaris.core.exception.SumarisTechnicalException;
......@@ -1606,15 +1607,29 @@ public class Daos {
Timestamp sourceUpdateDtNoMillisecond = Dates.resetMillisecond(source.getUpdateDate());
if (!Objects.equals(sourceUpdateDtNoMillisecond, serverUpdateDtNoMillisecond)) {
throw new BadUpdateDateException(I18n.t("sumaris.persistence.error.badUpdateDate",
getTableName(entity.getClass().getSimpleName()), source.getId(), serverUpdateDtNoMillisecond,
getTableName(entity), source.getId(), serverUpdateDtNoMillisecond,
sourceUpdateDtNoMillisecond));
}
}
}
public static <T extends IEntity<?>> String getTableName(T source) {
String entityName = getEntityName(source);
return getTableName(entityName);
}
public static String getTableName(String entityName) {
String firstLetterLowercase = entityName.substring(0,1).toLowerCase() + entityName.substring(1);
return I18n.t("sumaris.persistence.table." + firstLetterLowercase);
}
return I18n.t("sumaris.persistence.table."+ entityName.substring(0,1).toLowerCase() + entityName.substring(1));
public static <T extends IEntity<?>> String getEntityName(T source) {
String classname = source.getClass().getSimpleName();
int index = classname.indexOf("$HibernateProxy");
if (index > 0) {
return classname.substring(0, index);
}
return classname;
}
public static String getEscapedSearchText(String searchText) {
......
......@@ -146,7 +146,7 @@ public abstract class SumarisJpaRepositoryImpl<E extends IEntity<ID>, ID extends
onBeforeSaveEntity(vo, entity, isNew);
// Save entity
E savedEntity = save(entity);
E savedEntity = super.save(entity);
// Update VO
onAfterSaveEntity(vo, savedEntity, isNew);
......@@ -400,6 +400,15 @@ public abstract class SumarisJpaRepositoryImpl<E extends IEntity<ID>, ID extends
BindableSpecification<S> specificationWithParameters = (BindableSpecification<S>) specification;
specificationWithParameters.getBindings().forEach(binding -> binding.accept(query));
}
else if (specification != null){
String message = "DEPRECATED use of Specification. Please use BindableSpecification instead, to be able to bind parameters";
if (log.isDebugEnabled()) {
log.warn(message, new Exception(message));
}
else {
log.warn(message);
}
}
return query;
}
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>net.sumaris</groupId>
<artifactId>sumaris-pod</artifactId>
<version>1.6.6</version>
<version>1.7.0</version>
</parent>
<artifactId>sumaris-core</artifactId>
......
......@@ -48,6 +48,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.dao.DataIntegrityViolationException;
......@@ -114,7 +115,11 @@ public class StrategyRepositoryImpl
@Override
@Caching(
evict = {
@CacheEvict(cacheNames = CacheNames.PMFM_BY_STRATEGY_ID, allEntries = true),
@CacheEvict(cacheNames = CacheNames.STRATEGIES_BY_PROGRAM_ID, allEntries = true)
},
put = {
@CachePut(cacheNames = CacheNames.STRATEGIES_BY_PROGRAM_ID, key="#programId"),
}
)
public List<StrategyVO> saveByProgramId(int programId, List<StrategyVO> sources) {
......
......@@ -23,6 +23,7 @@ package net.sumaris.core.dao.administration.user;
*/
import com.google.common.base.Preconditions;
import net.sumaris.core.dao.technical.jpa.BindableSpecification;
import net.sumaris.core.dao.technical.jpa.SumarisJpaRepositoryImpl;
import net.sumaris.core.model.administration.user.UserSettings;
import net.sumaris.core.vo.administration.user.UserSettingsVO;
......@@ -46,7 +47,8 @@ public class UserSettingsRepositoryImpl
@Override
public Optional<UserSettingsVO> findByIssuer(String issuer) {
List<UserSettings> settings = findAll((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get(UserSettingsVO.Fields.ISSUER), issuer));
List<UserSettings> settings = findAll(BindableSpecification.where((root, query, criteriaBuilder) ->
criteriaBuilder.equal(root.get(UserSettingsVO.Fields.ISSUER), issuer)));
if (CollectionUtils.isEmpty(settings)) {
return Optional.empty();
}
......
......@@ -34,6 +34,7 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.lang.Nullable;
import java.util.Date;
import java.util.List;
import java.util.Optional;
......@@ -82,12 +83,24 @@ public interface DataRepository<
V control(V vo);
default Date control(Integer id, Date updateDate) {
V vo = get(id);
vo = control(vo);
return vo.getUpdateDate();
}
V validate(V vo);
V unvalidate(V vo);
//Date validate(Integer id, Date updateDate);
V unValidate(V vo);
//Date unValidate(Integer id, Date updateDate);
V qualify(V vo);
//Date qualify(Integer id, Date updateDate);
V toVO(E source, O fetchOptions);
}
......@@ -188,10 +188,10 @@ public abstract class DataRepositoryImpl<E extends IDataEntity<Integer>, V exten
E entity = getOne(vo.getId());
// Check update date
Daos.checkUpdateDateForUpdate(vo, entity);
if (isCheckUpdateDate()) Daos.checkUpdateDateForUpdate(vo, entity);
// Lock entityName
lockForUpdate(entity);
if (isLockForUpdate()) lockForUpdate(entity);
// TODO CONTROL PROCESS HERE
Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
......@@ -203,6 +203,7 @@ public abstract class DataRepositoryImpl<E extends IDataEntity<Integer>, V exten
// Save entityName
getEntityManager().merge(entity);
// Update source
vo.setControlDate(newUpdateDate);
vo.setUpdateDate(newUpdateDate);
......@@ -216,7 +217,7 @@ public abstract class DataRepositoryImpl<E extends IDataEntity<Integer>, V exten
}
@Override
public V unvalidate(V vo) {
public V unValidate(V vo) {
throw new NotImplementedException("Not implemented yet");
}
......
......@@ -37,7 +37,7 @@ public interface DataSpecifications<E extends IDataEntity<? extends Serializable
String RECORDER_DEPARTMENT_ID_PARAM = "recorderDepartmentId";
default Specification<E> hasRecorderDepartmentId(Integer recorderDepartmentId) {
default BindableSpecification<E> hasRecorderDepartmentId(Integer recorderDepartmentId) {
BindableSpecification<E> specification = BindableSpecification.where((root, query, criteriaBuilder) -> {
query.distinct(true); // Set distinct here because hasRecorderDepartmentId is always used (usually ...)
ParameterExpression<Integer> param = criteriaBuilder.parameter(Integer.class, RECORDER_DEPARTMENT_ID_PARAM);
......
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