Commit 5e75ad3d authored by LAVENIER's avatar LAVENIER
Browse files

[enh] New extraction type 'Pmfm Trip'. Extract all PMFM on acquisition levels TRIP and OPERATION

[fix] Simplify PmfmStrategy read and cache, by using a new PmfmStrategyFilterVO, and PmfmStrategyFetchOptions
parent ac394bd8
......@@ -29,17 +29,18 @@ import net.sumaris.core.extraction.dao.trip.rdb.ExtractionRdbTripDaoImpl;
import net.sumaris.core.extraction.format.LiveFormatEnum;
import net.sumaris.core.extraction.specification.data.trip.PmfmTripSpecification;
import net.sumaris.core.extraction.vo.ExtractionFilterVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmColumnVO;
import net.sumaris.core.extraction.vo.trip.rdb.ExtractionRdbTripContextVO;
import net.sumaris.core.model.administration.programStrategy.AcquisitionLevelEnum;
import net.sumaris.core.model.referential.pmfm.PmfmEnum;
import net.sumaris.core.model.technical.extraction.IExtractionFormat;
import net.sumaris.core.service.administration.programStrategy.StrategyService;
import net.sumaris.core.util.StringUtils;
import net.sumaris.core.vo.referential.PmfmValueType;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
......@@ -54,9 +55,6 @@ public class ExtractionPmfmTripDaoImpl<C extends ExtractionRdbTripContextVO, F e
extends ExtractionRdbTripDaoImpl<C, F>
implements PmfmTripSpecification {
@Autowired
protected StrategyService strategyService;
private static final String XML_QUERY_PMFM_PATH = "pmfm/v%s/%s";
private static final String XML_QUERY_PMFM_V1_0_PATH = String.format(XML_QUERY_PMFM_PATH,
VERSION_1_0.replaceAll("[.]", "_"), "%s");
......@@ -82,14 +80,14 @@ public class ExtractionPmfmTripDaoImpl<C extends ExtractionRdbTripContextVO, F e
XMLQuery xmlQuery = super.createTripQuery(context);
// Hide already pmfm columns
//xmlQuery.setGroup("xxx", false);
// Add PMFM from program, if on program has been set
String programLabel = context.getTripFilter().getProgramLabel();
if (StringUtils.isNotBlank(programLabel)) {
injectPmfmColumns(context, xmlQuery,
Collections.singletonList(programLabel),
AcquisitionLevelEnum.TRIP,
PmfmEnum.NB_OPERATION);
// Excluded PMFM (already exists as RDB format columns)
PmfmEnum.NB_OPERATION.getId());
}
return xmlQuery;
......@@ -107,7 +105,12 @@ public class ExtractionPmfmTripDaoImpl<C extends ExtractionRdbTripContextVO, F e
injectPmfmColumns(context, xmlQuery,
getTripProgramLabels(context),
AcquisitionLevelEnum.OPERATION,
PmfmEnum.NB_OPERATION);
// Excluded PMFM (already exists as RDB format columns)
PmfmEnum.SMALLER_MESH_GAUGE_MM.getId(),
PmfmEnum.GEAR_DEPTH_M.getId(),
PmfmEnum.BOTTOM_DEPTH_M.getId(),
PmfmEnum.SELECTIVITY_DEVICE.getId(),
PmfmEnum.TRIP_PROGRESS.getId());
return xmlQuery;
}
......@@ -132,7 +135,8 @@ public class ExtractionPmfmTripDaoImpl<C extends ExtractionRdbTripContextVO, F e
Preconditions.checkNotNull(context.getVersion());
switch (queryName) {
case "injectionPmfm":
case "injectionTripPmfm":
case "injectionOperationPmfm":
return String.format(XML_QUERY_PMFM_V1_0_PATH, queryName);
default:
return super.getQueryFullName(context, queryName);
......@@ -144,13 +148,52 @@ public class ExtractionPmfmTripDaoImpl<C extends ExtractionRdbTripContextVO, F e
XMLQuery xmlQuery,
List<String> programLabels,
AcquisitionLevelEnum acquisitionLevel,
PmfmEnum... excludedPmfms
Integer... excludedPmfmIds
) {
fillPmfmInfos(context, programLabels, acquisitionLevel);
if (CollectionUtils.isEmpty(context.getPmfmInfos())) return;
// Load PMFM columns to inject
List<ExtractionPmfmColumnVO> pmfmColumns = loadPmfmColumns(context, programLabels, acquisitionLevel);
if (CollectionUtils.isEmpty(pmfmColumns)) return; // Skip if empty
// Compute the injection query
URL injectionQuery = getInjectionQueryByAcquisitionLevel(context, acquisitionLevel);
if (injectionQuery == null) {
log.warn("No XML query found, for Pmfm injection on acquisition level: " + acquisitionLevel.name());
return;
}
xmlQuery.injectQuery(getXMLQueryURL(context, "injectionPmfm"));
//xmlQuery.bind();
List<Integer> excludedPmfmIdsList = Arrays.asList(excludedPmfmIds);
pmfmColumns.stream()
.filter(pmfm -> !excludedPmfmIdsList.contains(pmfm.getPmfmId()))
.forEach(pmfm -> injectPmfmColumn(context, xmlQuery, injectionQuery, pmfm));
}
protected URL getInjectionQueryByAcquisitionLevel(C context, AcquisitionLevelEnum acquisitionLevel) {
switch (acquisitionLevel) {
case TRIP:
return getXMLQueryURL(context, "injectionTripPmfm");
case OPERATION:
return getXMLQueryURL(context, "injectionOperationPmfm");
default:
return null;
}
}
protected void injectPmfmColumn(C context,
XMLQuery xmlQuery,
URL injectionPmfmQuery,
ExtractionPmfmColumnVO pmfm
) {
xmlQuery.injectQuery(injectionPmfmQuery, "%pmfmAlias%", pmfm.getAlias());
xmlQuery.bind("pmfmId" + pmfm.getAlias(), String.valueOf(pmfm.getPmfmId()));
xmlQuery.bind("pmfmLabel" + pmfm.getAlias(), pmfm.getLabel());
// ForDisable groups of unused pmfm type
for (PmfmValueType enumType: PmfmValueType.values()) {
xmlQuery.setGroup(enumType.name().toLowerCase() + pmfm.getAlias(), enumType == pmfm.getType());
}
}
}
......@@ -23,7 +23,7 @@ package net.sumaris.core.extraction.dao.trip.rdb;
*/
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import net.sumaris.core.dao.technical.DatabaseType;
import net.sumaris.core.exception.DataNotFoundException;
......@@ -35,7 +35,7 @@ import net.sumaris.core.extraction.dao.trip.ExtractionTripDao;
import net.sumaris.core.extraction.format.LiveFormatEnum;
import net.sumaris.core.extraction.specification.data.trip.RdbSpecification;
import net.sumaris.core.extraction.vo.ExtractionFilterVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmInfoVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmColumnVO;
import net.sumaris.core.extraction.vo.trip.ExtractionTripFilterVO;
import net.sumaris.core.extraction.vo.trip.rdb.ExtractionRdbTripContextVO;
import net.sumaris.core.model.administration.programStrategy.AcquisitionLevelEnum;
......@@ -46,10 +46,12 @@ import net.sumaris.core.model.referential.pmfm.QualitativeValueEnum;
import net.sumaris.core.model.referential.pmfm.UnitEnum;
import net.sumaris.core.service.administration.programStrategy.ProgramService;
import net.sumaris.core.service.administration.programStrategy.StrategyService;
import net.sumaris.core.util.Beans;
import net.sumaris.core.util.StringUtils;
import net.sumaris.core.vo.administration.programStrategy.PmfmStrategyVO;
import net.sumaris.core.vo.administration.programStrategy.ProgramVO;
import net.sumaris.core.vo.administration.programStrategy.StrategyFetchOptions;
import net.sumaris.core.vo.administration.programStrategy.*;
import net.sumaris.core.vo.filter.PmfmStrategyFilterVO;
import net.sumaris.core.vo.filter.StrategyFilterVO;
import net.sumaris.core.vo.referential.PmfmValueType;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
......@@ -57,12 +59,14 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import javax.persistence.PersistenceException;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.nuiton.i18n.I18n.t;
......@@ -482,51 +486,51 @@ public class ExtractionRdbTripDaoImpl<C extends ExtractionRdbTripContextVO, F ex
* Fill the context's pmfm infos (e.g. used to generate
* @param context
*/
protected void fillPmfmInfos(C context,
List<String> programLabels,
AcquisitionLevelEnum... acquisitionLevels){
protected List<ExtractionPmfmColumnVO> loadPmfmColumns(C context,
List<String> programLabels,
AcquisitionLevelEnum acquisitionLevel) {
if (CollectionUtils.isEmpty(programLabels)) {
context.setPmfmInfos(ImmutableList.of());
return;
if (CollectionUtils.isEmpty(programLabels)) return Collections.emptyList(); // no selected programs: skip
// Create the map that holds the result
Map<AcquisitionLevelEnum, List<ExtractionPmfmColumnVO>> pmfmColumns = context.getPmfmsByAcquisitionLevel();
if (pmfmColumns == null) {
pmfmColumns = Maps.newHashMap();
context.setPmfmsByAcquisitionLevel(pmfmColumns);
}
// Already loaded: use the cached values
if (pmfmColumns.containsKey(acquisitionLevel)) return pmfmColumns.get(acquisitionLevel);
if (log.isDebugEnabled()) {
log.debug(String.format("Loading PMFM for {program: %s, acquisitionLevel: %s}",
log.debug(String.format("Loading PMFM for {program: %s, acquisitionLevel: %s} ...",
programLabels,
acquisitionLevels != null ? acquisitionLevels : "all"
acquisitionLevel
));
}
// Get PMFMs from strategies
final MultiValuedMap<Integer, PmfmStrategyVO> pmfmStrategiesByProgramId = new ArrayListValuedHashMap<>();
programLabels.stream()
.map(programService::getByLabel)
.map(ProgramVO::getId)
.forEach(programId -> {
// Load pmfm, filtered by acquisition levels
if (acquisitionLevels != null && acquisitionLevels.length > 0) {
for (AcquisitionLevelEnum acquisitionLevel : acquisitionLevels) {
// TODO: filter strategies by filter period
Collection<PmfmStrategyVO> pmfms = strategyService.findPmfmsByProgramAndAcquisitionLevel(
programId,
acquisitionLevel.getId(),
StrategyFetchOptions.builder().withDenormalizedPmfms(true).build()
);
pmfmStrategiesByProgramId.putAll(programId, pmfms);
}
}
// Load all pmfms
else {
Collection<PmfmStrategyVO> pmfms = strategyService.findPmfmsByProgram(
programId,
StrategyFetchOptions.builder().withDenormalizedPmfms(true).build()
);
pmfmStrategiesByProgramId.putAll(programId, pmfms);
}
});
List<ExtractionPmfmInfoVO> pmfmInfos = getPmfmInfos(context, pmfmStrategiesByProgramId);
context.setPmfmInfos(pmfmInfos);
// Load strategies
List<ExtractionPmfmColumnVO> result = strategyService.findByFilter(StrategyFilterVO.builder()
.levelLabels(programLabels.toArray(new String[0]))
// TODO: filtrer les strategies via la periode du filtre (si présente) ?
// .startDate(...).endDate(...)
.build(), Pageable.unpaged(), StrategyFetchOptions.DEFAULT)
.stream()
// Then, load PmfmStretegy
.flatMap(strategy -> strategyService.findDenormalizedPmfmsByFilter(
PmfmStrategyFilterVO.builder()
.strategyId(strategy.getId())
.acquisitionLevelId(acquisitionLevel.getId())
.build(),
PmfmStrategyFetchOptions.builder().withCompleteName(false).build()
).stream())
.map(pmfmStrategy -> toPmfmColumnVO(pmfmStrategy, null))
.collect(Collectors.toList());
// save result into the context map
pmfmColumns.put(acquisitionLevel, result);
return result;
}
protected List<String> getTripProgramLabels(C context) {
......@@ -537,33 +541,40 @@ public class ExtractionRdbTripDaoImpl<C extends ExtractionRdbTripContextVO, F ex
return query(xmlQuery.getSQLQueryAsString(), String.class);
}
private List<ExtractionPmfmInfoVO> getPmfmInfos(C context, MultiValuedMap<Integer, PmfmStrategyVO> pmfmStrategiesByProgramId) {
private List<ExtractionPmfmColumnVO> toPmfmColumnVO(List<DenormalizedPmfmStrategyVO> pmfmStrategies) {
Map<String, String> acquisitionLevelAliases = buildAcquisitionLevelAliases(
pmfmStrategiesByProgramId.values().stream()
.map(PmfmStrategyVO::getAcquisitionLevel)
.collect(Collectors.toSet()));
Set<String> acquisitionLevels = Beans.collectDistinctProperties(pmfmStrategies, DenormalizedPmfmStrategyVO.Fields.ACQUISITION_LEVEL);
// Create prefix map, by acquisition level (used to generate the pmfm alias)
Map<String, String> aliasPrefixesByAcquisitionLevel = buildAcquisitionLevelPrefixes(acquisitionLevels);
return pmfmStrategies.stream().map(source ->
toPmfmColumnVO(source, aliasPrefixesByAcquisitionLevel.get(source.getAcquisitionLevel()))
)
.collect(Collectors.toList());
}
List<ExtractionPmfmInfoVO> pmfmInfos = new ArrayList<>();
for (Integer programId : pmfmStrategiesByProgramId.keySet()) {
for (PmfmStrategyVO pmfmStrategy : pmfmStrategiesByProgramId.get(programId)) {
ExtractionPmfmInfoVO pmfmInfo = new ExtractionPmfmInfoVO();
pmfmInfo.setProgramId(programId);
pmfmInfo.setAcquisitionLevel(pmfmStrategy.getAcquisitionLevel());
pmfmInfo.setPmfmId(pmfmStrategy.getPmfmId());
pmfmInfo.setRankOrder(pmfmStrategy.getRankOrder());
private ExtractionPmfmColumnVO toPmfmColumnVO(DenormalizedPmfmStrategyVO source, String aliasPrefix) {
ExtractionPmfmColumnVO target = new ExtractionPmfmColumnVO();
pmfmInfo.setAlias(acquisitionLevelAliases.get(pmfmInfo.getAcquisitionLevel()) + pmfmInfo.getPmfmId());
//pmfmInfo.setTableName(String.format(PMFM_TABLE_NAME_PATTERN, context.getId(), pmfmInfo.getAlias()));
pmfmInfos.add(pmfmInfo);
}
}
target.setAcquisitionLevel(source.getAcquisitionLevel());
target.setPmfmId(source.getId());
target.setLabel(source.getLabel());
target.setRankOrder(source.getRankOrder());
target.setType(PmfmValueType.fromString(source.getType()));
return pmfmInfos;
target.setAlias(
(aliasPrefix != null ? aliasPrefix : "T_")
+ target.getPmfmId());
return target;
}
private Map<String, String> buildAcquisitionLevelAliases(Set<String> acquisitionLevels) {
/**
* Build a map of unique alias, by acquisition level.
* Will use the first letter if unique, or two letters, or tree, etc.
* @param acquisitionLevels
* @return
*/
private Map<String, String> buildAcquisitionLevelPrefixes(Set<String> acquisitionLevels) {
Map<String, String> aliases = new HashMap<>();
for (String acquisitionLevel : acquisitionLevels) {
String alias = buildAlias(acquisitionLevel, "_");
......
......@@ -25,26 +25,23 @@ package net.sumaris.core.extraction.vo;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import net.sumaris.core.vo.referential.PmfmValueType;
/**
* @author peck7 on 18/12/2018.
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ExtractionPmfmInfoVO {
public class ExtractionPmfmColumnVO {
int pmfmId;
/**
* the table name owning the result and its extraction alias
*/
String tableName;
//String name;
String alias;
String label;
PmfmValueType type;
/**
* program, acquisition level and rank order from the strategy
*/
int programId;
String acquisitionLevel;
int rankOrder;
}
......@@ -28,7 +28,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldDefaults;
import net.sumaris.core.extraction.vo.AggregationContextVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmInfoVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmColumnVO;
import net.sumaris.core.vo.filter.TripFilterVO;
import net.sumaris.core.vo.technical.extraction.AggregationStrataVO;
import org.apache.commons.lang3.StringUtils;
......@@ -49,7 +49,7 @@ public abstract class AggregationTripContextVO extends AggregationContextVO {
AggregationStrataVO strata;
List<ExtractionPmfmInfoVO> pmfmInfos;
List<ExtractionPmfmColumnVO> pmfmInfos;
public List<String> getProgramLabels() {
return tripFilter != null && StringUtils.isNotBlank(tripFilter.getProgramLabel()) ? ImmutableList.of(tripFilter.getProgramLabel()) : null;
......
......@@ -28,12 +28,14 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldDefaults;
import net.sumaris.core.extraction.vo.AggregationContextVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmInfoVO;
import net.sumaris.core.extraction.vo.ExtractionPmfmColumnVO;
import net.sumaris.core.model.administration.programStrategy.AcquisitionLevelEnum;
import net.sumaris.core.vo.filter.TripFilterVO;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author Ludovic Pecquot <ludovic.pecquot>
......@@ -46,7 +48,7 @@ public class ExtractionTripContextVO extends AggregationContextVO {
TripFilterVO tripFilter;
List<ExtractionPmfmInfoVO> pmfmInfos;
Map<AcquisitionLevelEnum, List<ExtractionPmfmColumnVO>> pmfmsByAcquisitionLevel;
public Date getStartDate() {
return tripFilter != null ? tripFilter.getStartDate() : null;
......
<?xml version="1.0" encoding="UTF-8"?>
<query type="select">
<!-- double -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="double%pmfmAlias%" type="number">
(SELECT NUMERICAL_VALUE
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.TRIP_FK=O.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- integer -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="integer%pmfmAlias%" type="number">
(SELECT
CAST(NUMERICAL_VALUE AS INT)
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.OPERATION_FK=O.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- text -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="string%pmfmAlias%" type="text">(SELECT ALPHANUMERICAL_VALUE FROM VESSEL_USE_MEASUREMENT VUM WHERE VUM.OPERATION_FK=O.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)</select>
<!-- qualitative value -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="qualitative_value%pmfmAlias%" type="text">
(SELECT QV.LABEL
FROM VESSEL_USE_MEASUREMENT VUM
INNER JOIN QUALITATIVE_VALUE QV on QV.ID = VUM.QUALITATIVE_VALUE_FK
WHERE VUM.OPERATION_FK=O.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- boolean -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="boolean%pmfmAlias%" type="text">
(SELECT DECODE(VUM.NUMERICAL_VALUE, 1, 'Y', 0, 'N')
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.OPERATION_FK=O.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- date -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="date%pmfmAlias%" type="text"><![CDATA[
(SELECT
TO_CHAR(TIMESTAMP(REPLACE(REPLACE(VUM.ALPHANUMERICAL_VALUE, 'T', ' '), 'Z', '')), 'YYYY-DD-MM')
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.OPERATION_FK=O.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
]]>
</select>
</query>
<?xml version="1.0" encoding="UTF-8"?>
<!--
#%L
Dali :: Core
%%
Copyright (C) 2017 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%
-->
<query type="select">
<!-- insert PMFM columns -->
<!-- TODO -->
<!--<select alias="PMFM" group="pmfm_numerical" type="number">(SELECT NUMERICAL_VALUE FROM &amp;measurementTable WHERE &amp;)</select>-->
<select alias="PMFM" group="pmfm_numerical" type="number">1</select>
</query>
<?xml version="1.0" encoding="UTF-8"?>
<query type="select">
<!-- double -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="double%pmfmAlias%" type="number">(SELECT NUMERICAL_VALUE FROM VESSEL_USE_MEASUREMENT VUM WHERE VUM.TRIP_FK=T.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)</select>
<!-- integer -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="integer%pmfmAlias%" type="number">
(SELECT
CAST(NUMERICAL_VALUE AS INT)
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.TRIP_FK=T.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- text -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="string%pmfmAlias%" type="text">(SELECT ALPHANUMERICAL_VALUE FROM VESSEL_USE_MEASUREMENT VUM WHERE VUM.TRIP_FK=T.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)</select>
<!-- qualitative value -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="qualitative_value%pmfmAlias%" type="text">
(SELECT QV.LABEL
FROM VESSEL_USE_MEASUREMENT VUM
INNER JOIN QUALITATIVE_VALUE QV on QV.ID = VUM.QUALITATIVE_VALUE_FK
WHERE VUM.TRIP_FK=T.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- boolean -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="boolean%pmfmAlias%" type="text">
(SELECT DECODE(VUM.NUMERICAL_VALUE, 1, 'Y', 0, 'N')
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.TRIP_FK=T.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
</select>
<!-- date -->
<select alias="&amp;pmfmLabel%pmfmAlias%" group="date%pmfmAlias%" type="text"><![CDATA[
(SELECT
TO_CHAR(TIMESTAMP(REPLACE(REPLACE(VUM.ALPHANUMERICAL_VALUE, 'T', ' '), 'Z', '')), 'YYYY-DD-MM')
FROM VESSEL_USE_MEASUREMENT VUM
WHERE VUM.TRIP_FK=T.ID and VUM.PMFM_FK=&amp;pmfmId%pmfmAlias%)
]]>
</select>
</query>
......@@ -226,6 +226,18 @@ public class Beans {
return transformCollection(list, IEntity::getId);
}
/**
* <p>splitByProperty.</p>
*
* @param entities list of entities.
* @param <K> a K object.
* @param <V> a V object.
* @return a {@link Map} object.
*/
public static <K extends Serializable, V extends IEntity<K>> List<K> collectIds(V... entities) {
return transformCollection(Arrays.asList(entities), IEntity::getId);
}
/**
* <p>collectProperties.</p>
*
......@@ -239,7 +251,21 @@ public class Beans {
if (CollectionUtils.isEmpty(collection)) return new ArrayList<>();
Preconditions.checkArgument(StringUtils.isNotBlank(propertyName));
return collection.stream().map((Function<V, K>) v -> getProperty(v, propertyName)).collect(Collectors.toList());
}
/**
* <p>collectProperties.</p>
*
* @param collection a {@link Collection} object.
* @param propertyName a {@link String} object.
* @param <K> a K object.
* @param <V> a V object.
* @return a {@link List} object.
*/
public static <K, V> Set<K