Commit b027565c authored by LAVENIER's avatar LAVENIER
Browse files

[fix] Vessel: start new vessel repository impl

parent 9b3cf57b
...@@ -48,7 +48,11 @@ public class DatabaseResource extends net.sumaris.core.test.DatabaseResource { ...@@ -48,7 +48,11 @@ public class DatabaseResource extends net.sumaris.core.test.DatabaseResource {
} }
protected DatabaseResource(String configName,boolean readOnly) { protected DatabaseResource(String configName,boolean readOnly) {
super(configName, readOnly); super(configName, null, readOnly);
}
protected DatabaseResource(String configName, String dataSourceType, boolean readOnly) {
super(configName, dataSourceType, readOnly);
} }
@Override @Override
......
...@@ -56,7 +56,11 @@ public class DatabaseResource extends net.sumaris.core.test.DatabaseResource { ...@@ -56,7 +56,11 @@ public class DatabaseResource extends net.sumaris.core.test.DatabaseResource {
} }
protected DatabaseResource(String configName, boolean readOnly) { protected DatabaseResource(String configName, boolean readOnly) {
super(configName, readOnly); super(configName, null, readOnly);
}
protected DatabaseResource(String configFileSuffix, String datasourceType, boolean readOnly) {
super(configFileSuffix, datasourceType, readOnly);
} }
@Override @Override
......
...@@ -51,12 +51,21 @@ public class ConfigurableEnvironments { ...@@ -51,12 +51,21 @@ public class ConfigurableEnvironments {
for (String key: source.getPropertyNames()) { for (String key: source.getPropertyNames()) {
Object value = source.getProperty(key); Object value = source.getProperty(key);
if (value != null) { if (value != null) {
log.info(" {}={}", key, value); //
target.setProperty(key, value.toString()); target.setProperty(key, value.toString());
} }
} }
} }
// DEBUG
if (log.isDebugEnabled()) {
target.keySet().stream().map(Object::toString)
.forEach(key -> {
Object value = target.getProperty(key);
log.debug(" {}={}", key, value);
});
}
return target; return target;
} }
} }
...@@ -38,16 +38,15 @@ public interface DataSpecifications<E extends IDataEntity<? extends Serializable ...@@ -38,16 +38,15 @@ public interface DataSpecifications<E extends IDataEntity<? extends Serializable
String RECORDER_DEPARTMENT_ID_PARAM = "recorderDepartmentId"; String RECORDER_DEPARTMENT_ID_PARAM = "recorderDepartmentId";
default BindableSpecification<E> hasRecorderDepartmentId(Integer recorderDepartmentId) { default BindableSpecification<E> hasRecorderDepartmentId(Integer recorderDepartmentId) {
BindableSpecification<E> specification = BindableSpecification.where((root, query, criteriaBuilder) -> { return BindableSpecification.where((root, query, criteriaBuilder) -> {
query.distinct(true); // Set distinct here because hasRecorderDepartmentId is always used (usually ...) query.distinct(true); // Set distinct here because hasRecorderDepartmentId is always used (usually ...)
ParameterExpression<Integer> param = criteriaBuilder.parameter(Integer.class, RECORDER_DEPARTMENT_ID_PARAM); ParameterExpression<Integer> param = criteriaBuilder.parameter(Integer.class, RECORDER_DEPARTMENT_ID_PARAM);
return criteriaBuilder.or( return criteriaBuilder.or(
criteriaBuilder.isNull(param), criteriaBuilder.isNull(param),
criteriaBuilder.equal(root.get(E.Fields.RECORDER_DEPARTMENT).get(IEntity.Fields.ID), param) criteriaBuilder.equal(root.get(E.Fields.RECORDER_DEPARTMENT).get(IEntity.Fields.ID), param)
); );
}); })
specification.addBind(RECORDER_DEPARTMENT_ID_PARAM, recorderDepartmentId); .addBind(RECORDER_DEPARTMENT_ID_PARAM, recorderDepartmentId);
return specification;
} }
} }
package net.sumaris.core.dao.data.vessel;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 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 net.sumaris.core.dao.data.RootDataRepository;
import net.sumaris.core.model.data.Vessel;
import net.sumaris.core.vo.data.DataFetchOptions;
import net.sumaris.core.vo.data.TripVO;
import net.sumaris.core.vo.data.VesselVO;
import net.sumaris.core.vo.filter.TripFilterVO;
import net.sumaris.core.vo.filter.VesselFilterVO;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface VesselRepository extends
RootDataRepository<Vessel, VesselVO, VesselFilterVO, DataFetchOptions>,
VesselSpecifications {
}
package net.sumaris.core.dao.data.vessel;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 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 lombok.extern.slf4j.Slf4j;
import net.sumaris.core.dao.data.RootDataRepositoryImpl;
import net.sumaris.core.dao.data.landing.LandingRepository;
import net.sumaris.core.dao.referential.location.LocationRepository;
import net.sumaris.core.model.data.Vessel;
import net.sumaris.core.vo.data.DataFetchOptions;
import net.sumaris.core.vo.data.VesselVO;
import net.sumaris.core.vo.filter.VesselFilterVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.EntityManager;
@Slf4j
public class VesselRepositoryImpl
extends RootDataRepositoryImpl<Vessel, VesselVO, VesselFilterVO, DataFetchOptions>
implements VesselSpecifications {
@Autowired
public VesselRepositoryImpl(EntityManager entityManager) {
super(Vessel.class, VesselVO.class, entityManager);
}
@Override
public Specification<Vessel> toSpecification(VesselFilterVO filter, DataFetchOptions fetchOptions) {
return super.toSpecification(filter, fetchOptions)
.and(id(filter.getVesselId()))
.and(betweenDate(filter.getStartDate(), filter.getEndDate()))
.and(vesselFeatures(filter.getVesselFeaturesId()))
.and(statusIds(filter.getStatusIds()))
.and(searchText(filter.getSearchAttributes(), filter.getSearchText()));
}
@Override
public void toVO(Vessel source, VesselVO target, DataFetchOptions fetchOptions, boolean copyIfNull) {
super.toVO(source, target, fetchOptions, copyIfNull);
}
@Override
public void toEntity(VesselVO source, Vessel target, boolean copyIfNull) {
super.toEntity(source, target, copyIfNull);
}
@Override
protected void onAfterSaveEntity(VesselVO vo, Vessel savedEntity, boolean isNew) {
super.onAfterSaveEntity(vo, savedEntity, isNew);
}
}
package net.sumaris.core.dao.data.vessel;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 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 net.sumaris.core.dao.data.RootDataSpecifications;
import net.sumaris.core.dao.technical.Daos;
import net.sumaris.core.dao.technical.jpa.BindableSpecification;
import net.sumaris.core.model.data.Vessel;
import net.sumaris.core.model.data.VesselFeatures;
import net.sumaris.core.model.data.VesselRegistrationPeriod;
import net.sumaris.core.model.referential.Status;
import net.sumaris.core.util.Dates;
import net.sumaris.core.util.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
import java.util.*;
import java.util.stream.Collectors;
public interface VesselSpecifications extends RootDataSpecifications<Vessel> {
Date NVL_END_DATE_TIME = Dates.fromISODateTimeString("2100-01-01T00:00:00.000Z");
String VESSEL_FEATURES_ID_PARAM = "vesselFeaturesId";
String STATUS_IDS_PARAM = "statusIds";
String SEARCH_TEXT_PREFIX_PARAM = "searchTextPrefix";
String SEARCH_TEXT_ANY_PARAM = "searchTextAny";
default Specification<Vessel> betweenDate(Date startDate, Date endDate) {
if (startDate == null && endDate == null) return null;
return (root, query, cb) -> {
Join<Vessel, VesselFeatures> features = root.join(Vessel.Fields.VESSEL_FEATURES, JoinType.LEFT);
Join<Vessel, VesselRegistrationPeriod> vrp = root.join(Vessel.Fields.VESSEL_REGISTRATION_PERIODS, JoinType.LEFT);
// Start + end date
if (startDate != null && endDate != null) {
return cb.and(
cb.not(
cb.or(
cb.lessThan(cb.coalesce(features.get(VesselFeatures.Fields.END_DATE), NVL_END_DATE_TIME), startDate),
cb.greaterThan(features.get(VesselFeatures.Fields.START_DATE), endDate)
)
),
cb.not(
cb.or(
cb.lessThan(cb.coalesce(vrp.get(VesselRegistrationPeriod.Fields.END_DATE), NVL_END_DATE_TIME), startDate),
cb.greaterThan(vrp.get(VesselRegistrationPeriod.Fields.START_DATE), endDate)
)
)
);
}
// Start date only
else if (startDate != null) {
return cb.and(
cb.or(
cb.isNull(features.get(VesselFeatures.Fields.END_DATE)),
cb.not(cb.lessThan(features.get(VesselFeatures.Fields.END_DATE), startDate))
),
cb.or(
cb.isNull(vrp.get(VesselRegistrationPeriod.Fields.END_DATE)),
cb.not(cb.lessThan(vrp.get(VesselRegistrationPeriod.Fields.END_DATE), startDate))
)
);
}
// End date only
else {
return cb.and(
cb.not(cb.greaterThan(features.get(VesselFeatures.Fields.START_DATE), endDate)),
cb.not(cb.greaterThan(vrp.get(VesselRegistrationPeriod.Fields.START_DATE), endDate))
);
}
};
}
default Specification<Vessel> statusIds(List<Integer> statusIds) {
if (CollectionUtils.isEmpty(statusIds)) return null;
return BindableSpecification.where((root, query, cb) -> {
ParameterExpression<Collection> param = cb.parameter(Collection.class, STATUS_IDS_PARAM);
return cb.in(root.get(Vessel.Fields.STATUS).get(Status.Fields.ID)).value(param);
})
.addBind(STATUS_IDS_PARAM, statusIds);
}
default Specification<Vessel> vesselFeatures(Integer vesselFeatureId) {
if (vesselFeatureId == null) return null;
BindableSpecification<Vessel> specification = BindableSpecification.where((root, query, cb) -> {
Join<Vessel, VesselFeatures> featuresJoin = root.join(Vessel.Fields.VESSEL_FEATURES, JoinType.LEFT);
ParameterExpression<Integer> param = cb.parameter(Integer.class, VESSEL_FEATURES_ID_PARAM);
return cb.equal(featuresJoin.get(VesselFeatures.Fields.ID), param);
});
specification.addBind(VESSEL_FEATURES_ID_PARAM, vesselFeatureId);
return specification;
}
default Specification<Vessel> searchText(String[] searchAttributes, String searchText) {
String searchTextAsPrefix = Daos.getEscapedSearchText(searchText);
if (searchTextAsPrefix == null) return null;
// If not defined, search on :
// - VesselFeatures.exteriorMarking (prefix match - e.g. '<searchText>%')
// - VesselRegistrationPeriod.registrationCode (prefix match - e.g. '<searchText>%')
// - VesselFeatures.exteriorMarking (any match - e.g. '%<searchText>%')
final String[] attributes = searchAttributes != null ? searchAttributes : new String[] {
// Label
Vessel.Fields.VESSEL_FEATURES + "." + VesselFeatures.Fields.EXTERIOR_MARKING,
Vessel.Fields.VESSEL_REGISTRATION_PERIODS + "." + VesselRegistrationPeriod.Fields.REGISTRATION_CODE,
// Name
Vessel.Fields.VESSEL_FEATURES + "." + VesselFeatures.Fields.NAME
};
boolean enableAnySearch = Arrays.stream(attributes)
.anyMatch(attr -> attr.endsWith(VesselFeatures.Fields.NAME));
boolean enablePrefixSearch = Arrays.stream(attributes)
.anyMatch(attr -> !attr.endsWith(VesselFeatures.Fields.NAME));
BindableSpecification<Vessel> specification = BindableSpecification.where((root, query, cb) -> {
final ParameterExpression<String> prefixParam = cb.parameter(String.class, SEARCH_TEXT_PREFIX_PARAM);
final ParameterExpression<String> anyParam = cb.parameter(String.class, SEARCH_TEXT_ANY_PARAM);
return cb.or(Arrays.stream(attributes)
.map(attr -> cb.like(
cb.upper(Daos.composePath(root, attr)),
attr.endsWith(VesselFeatures.Fields.NAME) ? anyParam : prefixParam)
)
.collect(Collectors.toList())
.toArray(new Predicate[0])
);
});
if (enablePrefixSearch) specification.addBind(SEARCH_TEXT_PREFIX_PARAM, searchTextAsPrefix.toUpperCase());
if (enableAnySearch) specification.addBind(SEARCH_TEXT_ANY_PARAM, "%" + searchTextAsPrefix.toUpperCase());
return specification;
}
}
...@@ -31,6 +31,10 @@ import java.util.Date; ...@@ -31,6 +31,10 @@ import java.util.Date;
public interface IWithVesselSnapshotEntity<T extends Serializable, V extends VesselSnapshotVO> extends IEntity<T> { public interface IWithVesselSnapshotEntity<T extends Serializable, V extends VesselSnapshotVO> extends IEntity<T> {
interface Fields {
String VESSEL_SNAPSHOT = "vesselSnapshot";
}
V getVesselSnapshot(); V getVesselSnapshot();
void setVesselSnapshot(V vesselSnapshot); void setVesselSnapshot(V vesselSnapshot);
......
package net.sumaris.core.service.data.vessel;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 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 net.sumaris.core.config.CacheConfiguration;
import net.sumaris.core.dao.technical.Page;
import net.sumaris.core.dao.technical.SortDirection;
import net.sumaris.core.vo.data.*;
import net.sumaris.core.vo.filter.VesselFilterVO;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* @author BLA
*
* Service in charge of importing csv file into DB
*
*/
@Transactional
public interface VesselService2 {
@Transactional(readOnly = true)
List<VesselVO> findAll(VesselFilterVO filter, Page page,
DataFetchOptions fetchOptions);
@Transactional(readOnly = true)
Long countByFilter(VesselFilterVO filter);
@Transactional(readOnly = true)
VesselVO get(int id);
/*@Transactional(readOnly = true)
List<VesselSnapshotVO> findSnapshotByFilter(VesselFilterVO filter, int offset, int size, String sortAttribute, SortDirection sortDirection);
@Transactional(readOnly = true)
@Cacheable(cacheNames = CacheConfiguration.Names.VESSEL_SNAPSHOT_BY_ID_AND_DATE)
VesselSnapshotVO getSnapshotByIdAndDate(int vesselId, Date date);
@Transactional(readOnly = true)
List<VesselVO> findVesselsByFilter(VesselFilterVO filter, int offset, int size, String sortAttribute, SortDirection sortDirection);
@Transactional(readOnly = true)
Long countVesselsByFilter(VesselFilterVO filter);
@Transactional(readOnly = true)
VesselVO getVesselById(int vesselId);
@Transactional(readOnly = true)
List<VesselFeaturesVO> getFeaturesByVesselId(int vesselId, int offset, int size, String sortAttribute, SortDirection sortDirection);
@Transactional(readOnly = true)
List<VesselRegistrationVO> getRegistrationsByVesselId(int vesselId, int offset, int size, String sortAttribute, SortDirection sortDirection);
@CacheEvict(cacheNames = CacheConfiguration.Names.VESSEL_SNAPSHOT_BY_ID_AND_DATE, allEntries = true)
VesselVO save(VesselVO source);
@CacheEvict(cacheNames = CacheConfiguration.Names.VESSEL_SNAPSHOT_BY_ID_AND_DATE, allEntries = true)
VesselVO save(VesselVO source, boolean checkUpdateDate);
@CacheEvict(cacheNames = CacheConfiguration.Names.VESSEL_SNAPSHOT_BY_ID_AND_DATE, allEntries = true)
List<VesselVO> save(List<VesselVO> sources);
@CacheEvict(cacheNames = CacheConfiguration.Names.VESSEL_SNAPSHOT_BY_ID_AND_DATE, allEntries = true)
void delete(int id);
@CacheEvict(cacheNames = CacheConfiguration.Names.VESSEL_SNAPSHOT_BY_ID_AND_DATE, allEntries = true)
void delete(List<Integer> ids);*/
}
package net.sumaris.core.service.data.vessel;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 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 lombok.extern.slf4j.Slf4j;
import net.sumaris.core.dao.data.vessel.VesselRepository;
import net.sumaris.core.dao.technical.Page;
import net.sumaris.core.vo.data.*;
import net.sumaris.core.vo.filter.VesselFilterVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("vesselService2")
@Slf4j
public class VesselServiceImpl implements VesselService2 {
@Autowired
protected VesselRepository vesselRepository;
@Override
public List<VesselVO> findAll(VesselFilterVO filter, Page page,
DataFetchOptions fetchOptions) {
return vesselRepository.findAll(
VesselFilterVO.nullToEmpty(filter),
page,
fetchOptions);
}
@Override
public Long countByFilter(VesselFilterVO filter) {
return vesselRepository.count(VesselFilterVO.nullToEmpty(filter));
}
@Override
public VesselVO get(int id) {
return vesselRepository.get(id);
}
}
...@@ -119,7 +119,7 @@ public class ConfigurationServiceImpl implements ConfigurationService { ...@@ -119,7 +119,7 @@ public class ConfigurationServiceImpl implements ConfigurationService {
this.dbVersion = event.getSchemaVersion(); this.dbVersion = event.getSchemaVersion();
if (!configuration.enableConfigurationDbPersistence()) { if (!configuration.enableConfigurationDbPersistence()) {
if (event instanceof SchemaReadyEvent) { if (event instanceof SchemaReadyEvent && configuration.isProduction()) {
publisher.publishEvent(new ConfigurationReadyEvent(configuration)); publisher.publishEvent(new ConfigurationReadyEvent(configuration));
} }
} }
......
...@@ -41,6 +41,7 @@ public class VesselFilterVO implements IRootDataFilter { ...@@ -41,6 +41,7 @@ public class VesselFilterVO implements IRootDataFilter {
private Integer vesselId; private Integer vesselId;
private Integer vesselFeaturesId; private Integer vesselFeaturesId;