package com.zhitan.realtimedata.service.impl;
|
|
import com.zhitan.common.enums.Quality;
|
import com.zhitan.common.enums.StatisticType;
|
import com.zhitan.common.enums.TimeType;
|
import com.zhitan.common.utils.StringUtils;
|
import com.zhitan.common.utils.time.TimeManager;
|
import com.zhitan.model.domain.EnergyIndex;
|
import com.zhitan.realtimedata.domain.*;
|
import com.zhitan.realtimedata.mapper.PeriodDataMapper;
|
import com.zhitan.model.service.IEnergyIndexService;
|
import com.zhitan.realtimedata.service.IPeriodDataService;
|
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.Logger;
|
import org.joda.time.DateTime;
|
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormatter;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* Created by chongru on 2016-1-22.
|
*/
|
@Service
|
public class PeriodDataServiceImpl implements IPeriodDataService {
|
private Logger logger = LogManager.getLogger(PeriodDataServiceImpl.class);
|
@Autowired
|
private PeriodDataMapper periodDataMapper;
|
|
@Autowired
|
private IEnergyIndexService energyIndexService;
|
|
@Override
|
public void save(DataItem data) {
|
String item = periodDataMapper.hasExist(data.getIndexId(), data.getTimeCode());
|
if (StringUtils.isEmpty(item)) {
|
periodDataMapper.insert(data);
|
} else {
|
update(data);
|
}
|
}
|
|
@Override
|
public void saveTOUData(ElectricityDataDetail data) {
|
periodDataMapper.insertTOUData(data);
|
}
|
|
@Override
|
public void saveTOUData(List<ElectricityDataDetail> dataItems) {
|
List<List<ElectricityDataDetail>> splitData = splitList(dataItems, 100);
|
splitData.parallelStream().forEach(dataPart -> {
|
try {
|
periodDataMapper.insertTOUDataItems(dataPart);
|
} catch (Exception ex) {
|
logger.error("批量保存数据失败", ex);
|
dataPart.parallelStream().forEach(dataItem -> {
|
try {
|
periodDataMapper.insertTOUData(dataItem);
|
} catch (Exception singleEx) {
|
logger.error("单个指标数据保存失败!【" + dataItem + "】", singleEx);
|
}
|
});
|
}
|
});
|
}
|
|
@Override
|
public void save(List<DataItem> dataItems) {
|
List<List<DataItem>> splitData = splitList(dataItems, 100);
|
splitData.parallelStream().forEach(dataPart -> {
|
try {
|
periodDataMapper.saveDataList(dataPart);
|
} catch (Exception ex) {
|
logger.error("批量保存数据失败", ex);
|
dataPart.parallelStream().forEach(dataItem -> {
|
try {
|
periodDataMapper.save(dataItem);
|
} catch (Exception singleEx) {
|
logger.error("单个指标数据保存失败!【" + dataItem + "】", singleEx);
|
}
|
});
|
}
|
});
|
}
|
|
@Override
|
public void savePeriodData(List<DataItem> dataItems) {
|
Map<String, List<String>> map = dataItems.stream()
|
.collect(Collectors.groupingBy(DataItem::getTimeCode,
|
Collectors.mapping(DataItem::getIndexId, Collectors.toList())));
|
List<String> keys = periodDataMapper.queryDataItemIsExist(map);
|
List<DataItem> insertData = dataItems.stream()
|
.filter(
|
item -> !keys.contains(String.format("%s:%s", item.getTimeCode(), item.getIndexId())))
|
.collect(Collectors.toList());
|
if (!insertData.isEmpty()) {
|
periodDataMapper.insertDataList(insertData);
|
}
|
|
List<DataItem> updateData = dataItems.stream()
|
.filter(
|
item -> keys.contains(String.format("%s:%s", item.getTimeCode(), item.getIndexId())))
|
.collect(Collectors.toList());
|
if (!updateData.isEmpty()) {
|
periodDataMapper.saveDataList(updateData);
|
}
|
}
|
|
@Override
|
public void update(DataItem data) {
|
periodDataMapper.update(data);
|
}
|
|
@Override
|
public DataItem getDataByIndex(String indexId, String timeCode) {
|
if (StringUtils.isEmpty(indexId)) {
|
return null;
|
}
|
|
return periodDataMapper.getDataByIndex(indexId, timeCode);
|
}
|
|
@Override
|
public DataItem getDataByIndex(String indexId, Date dataTime, TimeType timeType) {
|
if (StringUtils.isEmpty(indexId)) {
|
return null;
|
}
|
|
String timeCode = TimeManager.getTimeCode(dataTime, timeType);
|
return getDataByIndex(indexId, timeCode);
|
}
|
|
@Override
|
public List<DataItem> getDataItemsByIndex(List<String> indexIds, String timeCode) {
|
if (indexIds != null && !indexIds.isEmpty()) {
|
return periodDataMapper.getDatasByIndex(indexIds, timeCode);
|
}
|
|
return Collections.emptyList();
|
}
|
|
@Override
|
public List<DataItem> getDataItemsByIndex(List<String> indexIds, Date dataTime, TimeType timeType) {
|
if (indexIds != null && !indexIds.isEmpty()) {
|
String timeCode = TimeManager.getTimeCode(dataTime, timeType);
|
return periodDataMapper.getDatasByIndex(indexIds, timeCode);
|
}
|
|
return Collections.emptyList();
|
}
|
|
@Override
|
public List<DataItem> getDataItemsByIndex(List<String> indexIds, Date beginTime,
|
Date endTime, TimeType timeType) {
|
if (indexIds != null && !indexIds.isEmpty()) {
|
return periodDataMapper.getPeriodDatasByIndex(indexIds, beginTime, endTime, timeType);
|
}
|
|
return Collections.emptyList();
|
}
|
|
@Override
|
public List<DataItem> getDataItemsByIndex(String indexId,
|
Date beginTime,
|
Date endTime,
|
TimeType timeType) {
|
if (StringUtils.isEmpty(indexId)) {
|
return Collections.emptyList();
|
}
|
|
List<String> indexIds = new ArrayList<>();
|
indexIds.add(indexId);
|
return periodDataMapper.getPeriodDatasByIndex(indexIds, beginTime, endTime, timeType);
|
}
|
|
@Override
|
public List<DataItem> getDataItemsByIndex(List<String> indexIds, Date beginTime, Date endTime,
|
TimeType timeType, Quality quality) {
|
if (indexIds != null && !indexIds.isEmpty()) {
|
return periodDataMapper.getPeriodDatasByIndexAndQuality(indexIds,
|
beginTime,
|
endTime,
|
timeType,
|
quality);
|
}
|
|
return Collections.emptyList();
|
}
|
|
@Override
|
public double dataStatisticsByIndex(String indexId,
|
StatisticType statisticType,
|
TimeType timeType,
|
Date beginTime,
|
Date endTime) {
|
if (StringUtils.isEmpty(indexId)) {
|
return 0;
|
}
|
|
Double value = periodDataMapper.dataStatisticsByIndex(
|
indexId,
|
statisticType,
|
timeType,
|
beginTime,
|
endTime);
|
|
return value == null ? 0 : value;
|
}
|
|
@Override
|
public List<DataItem> dataStatisticsByIndexes(List<String> indexIds, StatisticType
|
statisticType, TimeType timeType, Date beginTime, Date endTime) {
|
if (indexIds == null || indexIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
return periodDataMapper.dataStatisticsByIndexs(
|
indexIds,
|
statisticType,
|
timeType,
|
beginTime,
|
endTime);
|
}
|
|
@Override
|
public double dataStatisticsByCode(String indexCode, StatisticType
|
statisticType, TimeType timeType, Date beginTime, Date endTime) {
|
if (StringUtils.isEmpty(indexCode)) {
|
return 0;
|
}
|
|
List<String> indexCodes = Collections.singletonList(indexCode);
|
List<DataItem> dataItems = dataStatisticsByCodes(
|
indexCodes,
|
statisticType,
|
timeType,
|
beginTime,
|
endTime);
|
if (!dataItems.isEmpty()) {
|
return dataItems.get(0).getValue();
|
}
|
|
return 0;
|
}
|
|
@Override
|
public List<DataItem> dataStatisticsByCodes(List<String> indexCodes,
|
StatisticType statisticType, TimeType timeType,
|
Date beginTime, Date endTime) {
|
if (indexCodes == null || indexCodes.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
return periodDataMapper.dataStatisticsByCodes(
|
indexCodes,
|
statisticType,
|
timeType,
|
beginTime,
|
endTime);
|
}
|
|
@Override
|
public List<DataItem> dataStatisticsByCodes(List<String> indexCodes,
|
StatisticType statisticType,
|
TimeType timeType,
|
Date beginTime, Date endTime,
|
boolean isFilter) {
|
if (indexCodes == null || indexCodes.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
return periodDataMapper.dataStatisticsFilterByCodes(
|
indexCodes,
|
statisticType,
|
timeType,
|
beginTime,
|
endTime,
|
isFilter);
|
}
|
|
@Override
|
public StatisticResult statisticById(String indexId, TimeType timeType, Date dataTime) {
|
if (StringUtils.isEmpty(indexId)) {
|
return null;
|
}
|
|
List<String> indexIds = Collections.singletonList(indexId);
|
List<StatisticResult> results = statisticById(indexIds, timeType, dataTime);
|
if (!results.isEmpty()) {
|
return results.get(0);
|
}
|
|
return new StatisticResult();
|
}
|
|
@Override
|
public List<StatisticResult> statisticById(List<String> indexIds, TimeType timeType, Date dataTime) {
|
if (indexIds == null || indexIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
String timeCode = TimeManager.getTimeCode(dataTime, timeType);
|
return statisticById(indexIds, timeType,
|
TimeManager.getBeginTime(timeCode), TimeManager.getEndTime(timeCode));
|
}
|
|
@Override
|
public List<StatisticResult> statisticById(String indexId, TimeType timeType,
|
Date beginTime, Date endTime) {
|
if (StringUtils.isEmpty(indexId)) {
|
return Collections.emptyList();
|
}
|
|
List<String> indexIds = Collections.singletonList(indexId);
|
return statisticById(indexIds, timeType, beginTime, endTime);
|
}
|
|
@Override
|
public List<StatisticResult> statisticById(List<String> indexIds, TimeType timeType,
|
Date beginTime, Date endTime) {
|
if (indexIds == null || indexIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
ReBuildTime reBuildTime = new ReBuildTime(timeType, beginTime, endTime).invoke();
|
DateTime begin = reBuildTime.getBegin();
|
DateTime end = reBuildTime.getEnd();
|
|
DateTime lastYearOfBeginTime = begin.plusYears(-1);
|
DateTime lastYearOfEndTime = end.plusYears(-1);
|
DateTime previousOfBeginTime = getTime(begin, timeType, -1, STATISTIC_QUERY_TYPE);
|
DateTime previousOfEndTime = getTime(end, timeType, -1, STATISTIC_QUERY_TYPE);
|
|
List<EnergyIndex> aggregateIndexList = energyIndexService.getEnergyIndexByIds(indexIds);
|
List<DataItem> currentValues = periodDataMapper.statistic(indexIds,
|
timeType,
|
begin.toDate(),
|
end.toDate());
|
List<DataItem> previousValues = periodDataMapper.statistic(indexIds,
|
timeType,
|
previousOfBeginTime.toDate(),
|
previousOfEndTime.toDate());
|
List<DataItem> lastYearValues = periodDataMapper.statistic(indexIds,
|
timeType,
|
lastYearOfBeginTime.toDate(),
|
lastYearOfEndTime.toDate());
|
|
List<StatisticResult> statisticResults =
|
periodDataMapper.getStatisticDatasById(indexIds, timeType);
|
|
return buildNewDatas(aggregateIndexList, timeType, currentValues, previousValues,
|
lastYearValues, statisticResults, begin, end, STATISTIC_QUERY_TYPE);
|
}
|
|
/**
|
* 统计一段时间周期内指标每个数据时间的本期值、上期值
|
* 这里是上期数值略有不同,小时的是昨天的,日数据是上个月的,月是去年的
|
*
|
* @param indexIds 指标主键
|
* @param timeType 时间周期类型
|
* @param beginTime 开始时间
|
* @param endTime 结束时间
|
* @return 统计结果
|
*/
|
@Override
|
public List<StatisticResult> statisticOtherCycle(List<String> indexIds, TimeType timeType, Date beginTime, Date endTime) {
|
if (indexIds == null || indexIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
String type = "other";
|
ReBuildTime reBuildTime = new ReBuildTime(timeType, beginTime, endTime).invoke();
|
DateTime begin = reBuildTime.getBegin();
|
DateTime end = reBuildTime.getEnd();
|
DateTime previousOfBeginTime = getTime(begin, timeType, -1, type);
|
DateTime previousOfEndTime = getTime(end, timeType, -1, type);
|
List<EnergyIndex> aggregateIndexList = energyIndexService.getEnergyIndexByIds(indexIds);
|
List<DataItem> currentValues = periodDataMapper.statistic(indexIds,
|
timeType,
|
begin.toDate(),
|
end.toDate());
|
List<DataItem> previousValues = periodDataMapper.statistic(indexIds,
|
timeType,
|
previousOfBeginTime.toDate(),
|
previousOfEndTime.toDate());
|
return buildNewDatas(aggregateIndexList, timeType, currentValues, previousValues,
|
new ArrayList<>(), null, begin, end, type);
|
}
|
|
@Override
|
public StatisticResult statisticByCode(String indexCode,
|
TimeType timeType, Date dataTime) {
|
if (StringUtils.isEmpty(indexCode)) {
|
return null;
|
}
|
|
List<String> indexCodes = Collections.singletonList(indexCode);
|
List<StatisticResult> results = statisticByCode(indexCodes, timeType, dataTime);
|
if (!results.isEmpty()) {
|
return results.get(0);
|
}
|
|
return new StatisticResult();
|
}
|
|
@Override
|
public List<StatisticResult> statisticByCode(List<String> indexCodes,
|
TimeType timeType, Date dataTime) {
|
if (indexCodes == null || indexCodes.isEmpty()
|
) {
|
return Collections.emptyList();
|
}
|
|
String timeCode = TimeManager.getTimeCode(dataTime, timeType);
|
return statisticByCode(indexCodes, timeType,
|
TimeManager.getBeginTime(timeCode), TimeManager.getEndTime(timeCode));
|
}
|
|
@Override
|
public List<StatisticResult> statisticByCode(String indexCode, TimeType timeType,
|
Date beginTime, Date endTime) {
|
if (StringUtils.isEmpty(indexCode)) {
|
return Collections.emptyList();
|
}
|
|
List<String> indexCodes = Collections.singletonList(indexCode);
|
return statisticByCode(indexCodes, timeType, beginTime, endTime);
|
}
|
|
private final static String STATISTIC_QUERY_TYPE = "normal";
|
|
@Override
|
public List<StatisticResult> statisticByCode(List<String> indexCodes,
|
TimeType timeType, Date beginTime, Date endTime) {
|
if (indexCodes == null || indexCodes.isEmpty()) {
|
return Collections.emptyList();
|
}
|
|
ReBuildTime reBuildTime = new ReBuildTime(timeType, beginTime, endTime).invoke();
|
DateTime begin = reBuildTime.getBegin();
|
DateTime end = reBuildTime.getEnd();
|
|
List<EnergyIndex> aggregateIndexList =
|
energyIndexService.getEnergyIndexByCodes(indexCodes);
|
DateTime lastYearOfBeginTime = begin.plusYears(-1);
|
DateTime lastYearOfEndTime = end.plusYears(-1);
|
DateTime previousOfBeginTime = getTime(begin, timeType, -1, STATISTIC_QUERY_TYPE);
|
DateTime previousOfEndTime = getTime(end, timeType, -1, STATISTIC_QUERY_TYPE);
|
|
List<DataItem> currentValues = periodDataMapper.statisticByCode(
|
indexCodes,
|
timeType,
|
begin.toDate(),
|
end.toDate());
|
List<DataItem> previousValues = periodDataMapper.statisticByCode(
|
indexCodes,
|
timeType,
|
previousOfBeginTime.toDate(),
|
previousOfEndTime.toDate());
|
List<DataItem> lastYearValues = periodDataMapper.statisticByCode(
|
indexCodes,
|
timeType,
|
lastYearOfBeginTime.toDate(),
|
lastYearOfEndTime.toDate());
|
|
List<StatisticResult> statisticResults =
|
periodDataMapper.getStatisticDatasByCode(indexCodes, timeType);
|
|
return buildNewDatas(aggregateIndexList,
|
timeType,
|
currentValues,
|
previousValues,
|
lastYearValues,
|
statisticResults, begin, end, STATISTIC_QUERY_TYPE);
|
}
|
|
@Override
|
public DataItem getDataByIndexCode(String indexCode, String timeCode) {
|
return periodDataMapper.getDataByIndexCode(indexCode, timeCode);
|
}
|
|
private DataItem findValue(List<DataItem> items, String indexId, DateTime dataTime) {
|
Optional<DataItem> value = items.stream()
|
.filter(f -> StringUtils.equalsIgnoreCase(f.getIndexId(), indexId)
|
&& dataTime.equals(new DateTime(f.getDataTime())))
|
.findAny();
|
return value.orElseGet(DataItem::new);
|
|
}
|
|
private DateTime getTime(DateTime time, TimeType timeType, int offset, String type) {
|
if (STATISTIC_QUERY_TYPE.equalsIgnoreCase(type)) {
|
if (timeType == TimeType.HOUR) {
|
return time.plusHours(offset);
|
} else if (timeType == TimeType.DAY) {
|
return time.plusDays(offset);
|
} else if (timeType == TimeType.MONTH) {
|
return time.plusMonths(offset);
|
} else if (timeType == TimeType.YEAR) {
|
return time.plusYears(offset);
|
}
|
return time;
|
} else {
|
switch (timeType) {
|
case HOUR:
|
return time.plusDays(offset);
|
case DAY:
|
return time.plusMonths(offset);
|
case MONTH:
|
case YEAR:
|
return time.plusYears(offset);
|
default:
|
return time;
|
}
|
}
|
}
|
|
|
private List<StatisticResult> buildNewDatas(List<EnergyIndex> indexList, TimeType timeType,
|
List<DataItem> currentValues,
|
List<DataItem> previousValues,
|
List<DataItem> lastYearValues,
|
List<StatisticResult> statisticResults,
|
DateTime beginTime,
|
DateTime endTime, String type) {
|
List<StatisticResult> results = new ArrayList<>();
|
indexList.forEach(index -> {
|
DateTime tmpTime = beginTime;
|
String indexId = index.getIndexId();
|
Optional<StatisticResult> statisticResult;
|
if (statisticResults == null) {
|
statisticResult = Optional.empty();
|
} else {
|
statisticResult = statisticResults.stream()
|
.filter(f -> StringUtils.equalsIgnoreCase(f.getIndexId(), indexId))
|
.findFirst();
|
}
|
|
while (tmpTime.isBefore(endTime)) {
|
StatisticResult result = new StatisticResult();
|
result.setIndexId(indexId);
|
result.setIndexCode(index.getCode());
|
result.setIndexName(index.getName());
|
result.setUnitId(index.getUnitId());
|
|
if (statisticResult.isPresent()) {
|
result.setMaxValue(statisticResult.get().getMaxValue());
|
result.setMinValue(statisticResult.get().getMinValue());
|
result.setAvgValue(statisticResult.get().getAvgValue());
|
}
|
|
result.setDataTime(tmpTime.toDate());
|
DataItem currentValue = findValue(currentValues, indexId, tmpTime);
|
result.setCurrentValue(currentValue.getValue() == null ? 0 : currentValue.getValue());
|
|
DateTime preTime = getTime(tmpTime, timeType, -1, type);
|
DataItem previousValue = findValue(previousValues, indexId, preTime);
|
result.setPreviousValue(previousValue.getValue() == null ? 0 : previousValue.getValue());
|
|
DateTime lastYearTime = tmpTime.plusYears(-1);
|
DataItem lastYearValue = findValue(lastYearValues, indexId, lastYearTime);
|
result.setLastYearValue(lastYearValue.getValue() == null ? 0 : lastYearValue.getValue());
|
results.add(result);
|
tmpTime = getTime(tmpTime, timeType, 1, STATISTIC_QUERY_TYPE);
|
}
|
});
|
|
return results;
|
}
|
|
public static <E> List<List<E>> splitList(List<E> targetList, Integer splitSize) {
|
if (targetList == null) {
|
return Collections.emptyList();
|
}
|
|
int size = targetList.size();
|
List<List<E>> resultList = new ArrayList<>();
|
if (size <= splitSize) {
|
resultList.add(targetList);
|
} else {
|
for (int i = 0; i < size; i += splitSize) {
|
//用于限制最后一部分size小于splitSize的list
|
int limit = i + splitSize;
|
if (limit > size) {
|
limit = size;
|
}
|
resultList.add(targetList.subList(i, limit));
|
}
|
}
|
return resultList;
|
}
|
|
private static class ReBuildTime {
|
private TimeType timeType;
|
private Date beginTime;
|
private Date endTime;
|
private DateTime begin;
|
private DateTime end;
|
|
public ReBuildTime(TimeType timeType, Date beginTime, Date endTime) {
|
this.timeType = timeType;
|
this.beginTime = beginTime;
|
this.endTime = endTime;
|
}
|
|
public DateTime getBegin() {
|
return begin;
|
}
|
|
public DateTime getEnd() {
|
return end;
|
}
|
|
public ReBuildTime invoke() {
|
begin = new DateTime(beginTime);
|
end = new DateTime(endTime);
|
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:00:00");
|
if (timeType == TimeType.HOUR) {
|
formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:00:00");
|
} else if (timeType == TimeType.DAY) {
|
formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
|
} else if (timeType == TimeType.MONTH) {
|
formatter = DateTimeFormat.forPattern("yyyy-MM-01");
|
} else if (timeType == TimeType.YEAR) {
|
formatter = DateTimeFormat.forPattern("yyyy-01-01");
|
}
|
|
begin = formatter.parseDateTime(begin.toString(formatter));
|
end = formatter.parseDateTime(end.toString(formatter));
|
return this;
|
}
|
}
|
}
|