From adeae2a07017fb542cf81475acc4f9c5bcf4f81a Mon Sep 17 00:00:00 2001 From: liuwy <1421132346@qq.com> Date: Fri, 16 Jun 2023 10:29:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=98=A0=E5=B0=84=E5=99=A8=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4=EF=BC=9A=20=20TrimMapper?= =?UTF-8?q?=20-=20=E8=A3=81=E5=89=AA=E6=98=A0=E5=B0=84=E5=99=A8=20=20ToBoo?= =?UTF-8?q?leanMapper=20-=20=E5=B8=83=E5=B0=94=E6=98=A0=E5=B0=84=E5=99=A8?= =?UTF-8?q?=20=20EnableRatioMapper=20-=20=E4=BD=BF=E8=83=BD=E6=AF=94?= =?UTF-8?q?=E4=BE=8B=E6=98=A0=E5=B0=84=E5=99=A8=20=20HighPassMapper=20-=20?= =?UTF-8?q?=E9=AB=98=E9=80=9A=E6=98=A0=E5=B0=84=E5=99=A8=20=20LowPassMappe?= =?UTF-8?q?r=20-=20=E4=BD=8E=E9=80=9A=E6=98=A0=E5=B0=84=E5=99=A8=20=20High?= =?UTF-8?q?PassCounterMapper=20-=20=E9=AB=98=E9=80=9A=E8=AE=A1=E6=95=B0?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E5=99=A8=20=20LowPassCounterMapper=20-=20?= =?UTF-8?q?=E4=BD=8E=E9=80=9A=E8=AE=A1=E6=95=B0=E6=98=A0=E5=B0=84=E5=99=A8?= =?UTF-8?q?=20=20HighPassExistenceMapper=20-=20=E9=AB=98=E9=80=9A=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E6=98=A0=E5=B0=84=E5=99=A8=20=20LowPassExistenceMappe?= =?UTF-8?q?r=20-=20=E4=BD=8E=E9=80=9A=E5=AD=98=E5=9C=A8=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/EnableRatioMapperRegistry.java | 196 ++++++++++++++ .../mapper/HighPassCounterMapperRegistry.java | 178 +++++++++++++ .../HighPassExistenceMapperRegistry.java | 215 ++++++++++++++++ .../mapper/HighPassMapperRegistry.java | 221 ++++++++++++++++ .../mapper/LowPassCounterMapperRegistry.java | 178 +++++++++++++ .../LowPassExistenceMapperRegistry.java | 215 ++++++++++++++++ .../handler/mapper/LowPassMapperRegistry.java | 220 ++++++++++++++++ .../mapper/ToBooleanMapperRegistry.java | 239 ++++++++++++++++++ .../handler/mapper/TrimMapperRegistry.java | 144 +++++++++++ 9 files changed, 1806 insertions(+) create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/EnableRatioMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassCounterMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassExistenceMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassCounterMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassExistenceMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/ToBooleanMapperRegistry.java create mode 100644 fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/TrimMapperRegistry.java diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/EnableRatioMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/EnableRatioMapperRegistry.java new file mode 100644 index 00000000..845a7a71 --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/EnableRatioMapperRegistry.java @@ -0,0 +1,196 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.sdk.util.CompareUtil; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Date; +import java.util.List; + +/** + * 使能比例映射器。 + * + * @author mooyuan + * @since 2.0.0 + */ +@Component +public class EnableRatioMapperRegistry extends AbstractMapperRegistry{ + + public static final String MAPPER_TYPE = "enable_ratio_mapper"; + + private final ApplicationContext ctx; + + public EnableRatioMapperRegistry(ApplicationContext ctx) { + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "使能比例映射器!"; + } + + @Override + public String provideDescription() { + return "用于计算布尔类型数据的使能比例,即数据中真值的占用时间与序列的总时间的比值: \n" + + "`invert` 用于控制计算的是真值的比例还是假值的比例: \n" + + " false:计算的是真值的比例 \n" + + " true:计算的是假值的比例 \n"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(EnableRatioMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "EnableRatioMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class EnableRatioMapper extends AggregateMapper { + + @Override + protected Object doAggregate(MapParam mapParam, List items, Date startDate, Date endDate) { + + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + boolean invert = config.getInvert(); + + // 对数据点进行时间排序(正序) + items.sort(CompareUtil.DATA_HAPPENED_DATE_ASC_COMPARATOR); + + //更新开始时间,去掉真空期 + startDate = items.get(0).getHappenedDate(); + + // 判断中间存在不为boolean类型的数据抛出异常 + for (Item item : items) { + if(!(item.getValue() instanceof Boolean)){ + throw new IllegalStateException("存在数据点值不为boolean类型"); + } + } + + // 计算占比 + return calRatioByItems(items, startDate, endDate, invert); + } + + /** + * 计算占比 + * @param items 排完序的数据点数组 + * @param startDate 序列开始时间 + * @param endDate 序列结束时间 + * @param invert true 计算false的占比、false 计算true的占比 + * @return 获取占比 + */ + public double calRatioByItems(List items, Date startDate, Date endDate, boolean invert){ + // 符合时间 + BigDecimal calTime = BigDecimal.ZERO; + boolean calFlag = false; + + BigDecimal startDateTime = BigDecimal.valueOf(startDate.getTime()); + BigDecimal endDateTime = BigDecimal.valueOf(endDate.getTime()); + // 总时间 + BigDecimal allTime = endDateTime.subtract(startDateTime); + + // 上一次符合的时间 + BigDecimal preTime = BigDecimal.ZERO; + + for (Item item : items) { + if(item.getValue() instanceof Boolean && !invert == (Boolean) item.getValue()){ + + if(calFlag){ + continue; + } + + preTime = BigDecimal.valueOf(item.getHappenedDate().getTime()); + calFlag = true; + }else { + if(!calFlag){ + continue; + } + + calTime = calTime.add(BigDecimal.valueOf(item.getHappenedDate().getTime()).subtract(preTime)); + calFlag = false; + } + } + + // 处理结束的时间,当最后时间的calFlag还是true时处理 + if(calFlag){ + calTime = calTime.add(endDateTime.subtract(preTime)); + } + + return calTime.divide(allTime,4, RoundingMode.HALF_UP).doubleValue(); + } + + @Override + public String toString() { + return "EnableRatioMapper{}"; + } + } + + public static class Config implements Bean { + + private static final long serialVersionUID = 6070172089803753764L; + + @JSONField(name = "invert", ordinal = 1) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 2, deserialize = false) + private String invertRem = "true:计算的是假值的比例;false:计算的是真值的比例"; + + public Config() { + } + + public Config(boolean invert) { + this.invert = invert; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassCounterMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassCounterMapperRegistry.java new file mode 100644 index 00000000..9fcb5293 --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassCounterMapperRegistry.java @@ -0,0 +1,178 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import com.dwarfeng.subgrade.stack.bean.key.LongIdKey; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; + +/** + * 计算高于阈值的数据的个数。 + * + * @author mooyuan + * @since 2.0.0 + */ +public class HighPassCounterMapperRegistry extends AbstractMapperRegistry{ + + public static final String MAPPER_TYPE = "high_pass_counter_mapper"; + + private final ApplicationContext ctx; + + public HighPassCounterMapperRegistry(ApplicationContext ctx){ + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "高通计数映射器!"; + } + + @Override + public String provideDescription() { + return "用于计算高于阈值的数据的个数: \n" + + "invert`用于控制计算的是低于阈值的数据还是高于阈值的数据: \n" + + "--false:过滤的是高于阈值的数据 \n" + + "--true:过滤的是低于阈值的数据 \n" + + "threshold用于过滤的阈值 \n" + + "can_equal是否包含等于阈值的数据"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(0.00, true, false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(HighPassCounterMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "HighPassCounterMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class HighPassCounterMapper extends AggregateMapper { + + @Override + protected Object doAggregate(MapParam mapParam, List items, Date startDate, Date endDate) { + Sequence s = HighPassMapperRegistry.HighPassMapper.highPass(mapParam, new Sequence(new LongIdKey(0L), items, startDate, endDate)); + return s.getItems().size(); + } + + @Override + public String toString() { + return "HighPassCounterMapper{}"; + } + } + + public static class Config implements Bean { + + private static final long serialVersionUID = 4334109826634237727L; + + @JSONField(name = "threshold", ordinal = 1) + private double threshold; + + @JSONField(name = "#threshold", ordinal = 2, deserialize = false) + private String thresholdRem = "阈值,对数据进行筛选的标准"; + + @JSONField(name = "can_equal", ordinal = 3) + private boolean canEqual; + + @JSONField(name = "#can_equal", ordinal = 4, deserialize = false) + private String canEqualRem = "true:包含阈值,false:不包含阈值"; + + @JSONField(name = "invert", ordinal = 5) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 6, deserialize = false) + private String invertRem = "true:过滤掉高于阈值的数据,false:过滤掉低于阈值的数据"; + + public Config() { + } + + public Config(double threshold, boolean canEqual, boolean invert) { + this.threshold = threshold; + this.canEqual = canEqual; + this.invert = invert; + } + + public double getThreshold() { + return threshold; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public String getThresholdRem() { + return thresholdRem; + } + + public void setThresholdRem(String thresholdRem) { + this.thresholdRem = thresholdRem; + } + + public boolean getCanEqual() { + return canEqual; + } + + public void setCanEqual(boolean canEqual) { + this.canEqual = canEqual; + } + + public String getCanEqualRem() { + return canEqualRem; + } + + public void setCanEqualRem(String canEqualRem) { + this.canEqualRem = canEqualRem; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "threshold=" + threshold + + ", thresholdRem='" + thresholdRem + '\'' + + ", canEqual=" + canEqual + + ", canEqualRem='" + canEqualRem + '\'' + + ", invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassExistenceMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassExistenceMapperRegistry.java new file mode 100644 index 00000000..396663be --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassExistenceMapperRegistry.java @@ -0,0 +1,215 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; +import java.util.Objects; + +/** + * 高通存在映射器,用于判断是否存在高于阈值的数据。 + * + * @author mooyuan + * @since 2.0.0 + */ +public class HighPassExistenceMapperRegistry extends AbstractMapperRegistry{ + + public static final String MAPPER_TYPE = "high_pass_existence_mapper"; + + private final ApplicationContext ctx; + + public HighPassExistenceMapperRegistry(ApplicationContext ctx){ + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "高通存在映射器!"; + } + + @Override + public String provideDescription() { + return "用于判断是否存在高于阈值的数据: \n" + + "invert`用于控制计算的是低于阈值的数据还是高于阈值的数据: \n" + + "--false:过滤的是高于阈值的数据 \n" + + "--true:过滤的是低于阈值的数据 \n" + + "threshold用于过滤的阈值 \n" + + "can_equal是否包含等于阈值的数据"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(0.00, true, false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(HighPassExistenceMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "HighPassExistenceMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class HighPassExistenceMapper extends AggregateMapper { + + @Override + protected Object doAggregate(MapParam mapParam, List items, Date startDate, Date endDate) { + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + double threshold = config.getThreshold(); + + boolean canEqual = config.getCanEqual(); + + boolean invert = config.getInvert(); + + return doDetermine(items, threshold, invert, canEqual); + } + + // 为了保证代码的可读性,此处代码不做简化。 + @SuppressWarnings("ConstantConditions") + private boolean doDetermine(List items, double threshold, boolean invert, boolean canEqual){ + for(Item item : items){ + if(invert && canEqual){ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) <= threshold){ + return true; + } + }else if(invert && !canEqual){ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) < threshold){ + return true; + } + }else if(!invert && canEqual){ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) >= threshold){ + return true; + } + }else{ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) > threshold){ + return true; + } + } + } + + return false; + } + + @Override + public String toString() { + return "HighPassExistenceMapper{}"; + } + } + + + public static class Config implements Bean { + + private static final long serialVersionUID = 2358214849837705523L; + + @JSONField(name = "threshold", ordinal = 1) + private double threshold; + + @JSONField(name = "#threshold", ordinal = 2, deserialize = false) + private String thresholdRem = "阈值,对数据进行筛选的标准"; + + @JSONField(name = "can_equal", ordinal = 3) + private boolean canEqual; + + @JSONField(name = "#can_equal", ordinal = 4, deserialize = false) + private String canEqualRem = "true:包含阈值,false:不包含阈值"; + + @JSONField(name = "invert", ordinal = 5) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 6, deserialize = false) + private String invertRem = "true:过滤掉高于阈值的数据,false:过滤掉低于阈值的数据"; + + public Config() { + } + + public Config(double threshold, boolean canEqual, boolean invert) { + this.threshold = threshold; + this.canEqual = canEqual; + this.invert = invert; + } + + public double getThreshold() { + return threshold; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public String getThresholdRem() { + return thresholdRem; + } + + public void setThresholdRem(String thresholdRem) { + this.thresholdRem = thresholdRem; + } + + public boolean getCanEqual() { + return canEqual; + } + + public void setCanEqual(boolean canEqual) { + this.canEqual = canEqual; + } + + public String getCanEqualRem() { + return canEqualRem; + } + + public void setCanEqualRem(String canEqualRem) { + this.canEqualRem = canEqualRem; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "threshold=" + threshold + + ", thresholdRem='" + thresholdRem + '\'' + + ", canEqual=" + canEqual + + ", canEqualRem='" + canEqualRem + '\'' + + ", invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } + +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassMapperRegistry.java new file mode 100644 index 00000000..4662170e --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/HighPassMapperRegistry.java @@ -0,0 +1,221 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 保留高于阈值的数据。 + * + * @author mooyuan + * @since 2.0.0 + */ +public class HighPassMapperRegistry extends AbstractMapperRegistry{ + public static final String MAPPER_TYPE = "high_pass_mapper"; + + private final ApplicationContext ctx; + + public HighPassMapperRegistry(ApplicationContext ctx) { + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "高通映射器!"; + } + + @Override + public String provideDescription() { + return "用于保留高于阈值的数据: \n" + + "invert`用于控制计算的是低于阈值的数据还是高于阈值的数据: \n" + + "--false:过滤的是高于阈值的数据 \n" + + "--true:过滤的是低于阈值的数据 \n" + + "threshold用于过滤的阈值 \n" + + "can_equal是否包含等于阈值的数据"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(0.00, true, false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(HighPassMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "HighPassMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class HighPassMapper extends OneToOneMapper { + + @Override + protected Sequence doOneToOneMap(MapParam mapParam, Sequence sequence) { + + + return highPass(mapParam, sequence); + } + + @SuppressWarnings("DuplicatedCode") + public static Sequence highPass(MapParam mapParam, Sequence sequence){ + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + double threshold = config.getThreshold(); + + boolean canEqual = config.getCanEqual(); + + boolean invert = config.getInvert(); + + // 定义数据条目列表。 + List items; + + items = doFilter(sequence, threshold, canEqual, invert); + + return new Sequence(sequence.getPointKey(),items,sequence.getStartDate(),sequence.getEndDate()); + } + + // 为了保证代码的可读性,此处代码不做简化。 + @SuppressWarnings("ConstantConditions") + private static List doFilter(Sequence sequence, double threshold, boolean canEqual, boolean invert) { + List items; + if(invert && canEqual){ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) <= threshold + ).collect(Collectors.toList()); + }else if(invert && !canEqual){ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) < threshold + ).collect(Collectors.toList()); + }else if(!invert && canEqual){ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) >= threshold + ).collect(Collectors.toList()); + }else{ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) > threshold + ).collect(Collectors.toList()); + } + return items; + } + + @Override + public String toString() { + return "HighPassMapper{}"; + } + } + + public static class Config implements Bean { + + private static final long serialVersionUID = -3275585723620360134L; + + @JSONField(name = "threshold", ordinal = 1) + private double threshold; + + @JSONField(name = "#threshold", ordinal = 2, deserialize = false) + private String thresholdRem = "阈值,对数据进行筛选的标准"; + + @JSONField(name = "can_equal", ordinal = 3) + private boolean canEqual; + + @JSONField(name = "#can_equal", ordinal = 4, deserialize = false) + private String canEqualRem = "true:包含阈值,false:不包含阈值"; + + @JSONField(name = "invert", ordinal = 5) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 6, deserialize = false) + private String invertRem = "true:过滤掉高于阈值的数据,false:过滤掉低于阈值的数据"; + + public Config() { + } + + public Config(double threshold, boolean canEqual, boolean invert) { + this.threshold = threshold; + this.canEqual = canEqual; + this.invert = invert; + } + + public double getThreshold() { + return threshold; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public String getThresholdRem() { + return thresholdRem; + } + + public void setThresholdRem(String thresholdRem) { + this.thresholdRem = thresholdRem; + } + + public boolean getCanEqual() { + return canEqual; + } + + public void setCanEqual(boolean canEqual) { + this.canEqual = canEqual; + } + + public String getCanEqualRem() { + return canEqualRem; + } + + public void setCanEqualRem(String canEqualRem) { + this.canEqualRem = canEqualRem; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "threshold=" + threshold + + ", thresholdRem='" + thresholdRem + '\'' + + ", canEqual=" + canEqual + + ", canEqualRem='" + canEqualRem + '\'' + + ", invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassCounterMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassCounterMapperRegistry.java new file mode 100644 index 00000000..afd8f7ff --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassCounterMapperRegistry.java @@ -0,0 +1,178 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import com.dwarfeng.subgrade.stack.bean.key.LongIdKey; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; + +/** + * 计算低于阈值的数据的个数。 + * + * @author mooyuan + * @since 2.0.0 + */ +public class LowPassCounterMapperRegistry extends AbstractMapperRegistry{ + + public static final String MAPPER_TYPE = "low_pass_counter_mapper"; + + private final ApplicationContext ctx; + + public LowPassCounterMapperRegistry(ApplicationContext ctx){ + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "低通计数映射器!"; + } + + @Override + public String provideDescription() { + return "用于计算低于阈值的数据的个数: \n" + + "invert`用于控制计算的是低于阈值的数据还是高于阈值的数据: \n" + + "--false:过滤的是高于阈值的数据 \n" + + "--true:过滤的是低于阈值的数据 \n" + + "threshold用于过滤的阈值 \n" + + "can_equal是否包含等于阈值的数据"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(0.00, true, false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(LowPassCounterMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "LowPassCounterMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class LowPassCounterMapper extends AggregateMapper { + + @Override + protected Object doAggregate(MapParam mapParam, List items, Date startDate, Date endDate) { + Sequence s = LowPassMapperRegistry.LowPassMapper.lowPass(mapParam, new Sequence(new LongIdKey(0L), items, startDate, endDate)); + return s.getItems().size(); + } + + @Override + public String toString() { + return "LowPassCounterMapper{}"; + } + } + + public static class Config implements Bean { + + private static final long serialVersionUID = 1816088081525711050L; + + @JSONField(name = "threshold", ordinal = 1) + private double threshold; + + @JSONField(name = "#threshold", ordinal = 2, deserialize = false) + private String thresholdRem = "阈值,对数据进行筛选的标准"; + + @JSONField(name = "can_equal", ordinal = 3) + private boolean canEqual; + + @JSONField(name = "#can_equal", ordinal = 4, deserialize = false) + private String canEqualRem = "true:包含阈值,false:不包含阈值"; + + @JSONField(name = "invert", ordinal = 5) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 6, deserialize = false) + private String invertRem = "true:过滤掉低于阈值的数据,false:过滤掉高于阈值的数据"; + + public Config() { + } + + public Config(double threshold, boolean canEqual, boolean invert) { + this.threshold = threshold; + this.canEqual = canEqual; + this.invert = invert; + } + + public double getThreshold() { + return threshold; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public String getThresholdRem() { + return thresholdRem; + } + + public void setThresholdRem(String thresholdRem) { + this.thresholdRem = thresholdRem; + } + + public boolean getCanEqual() { + return canEqual; + } + + public void setCanEqual(boolean canEqual) { + this.canEqual = canEqual; + } + + public String getCanEqualRem() { + return canEqualRem; + } + + public void setCanEqualRem(String canEqualRem) { + this.canEqualRem = canEqualRem; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "threshold=" + threshold + + ", thresholdRem='" + thresholdRem + '\'' + + ", canEqual=" + canEqual + + ", canEqualRem='" + canEqualRem + '\'' + + ", invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassExistenceMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassExistenceMapperRegistry.java new file mode 100644 index 00000000..0c37d9df --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassExistenceMapperRegistry.java @@ -0,0 +1,215 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; +import java.util.Objects; + +/** + * 低通存在映射器,用于判断是否存在低于阈值的数据。 + * + * @author mooyuan + * @since 2.0.0 + */ +public class LowPassExistenceMapperRegistry extends AbstractMapperRegistry{ + + public static final String MAPPER_TYPE = "low_pass_existence_mapper"; + + private final ApplicationContext ctx; + + public LowPassExistenceMapperRegistry(ApplicationContext ctx){ + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "高通存在映射器!"; + } + + @Override + public String provideDescription() { + return "用于判断是否存在低于阈值的数据: \n" + + "invert`用于控制计算的是低于阈值的数据还是高于阈值的数据: \n" + + "--false:过滤的是低于阈值的数据 \n" + + "--true:过滤的是高于阈值的数据 \n" + + "threshold用于过滤的阈值 \n" + + "can_equal是否包含等于阈值的数据"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(0.00, true, false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(LowPassExistenceMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "LowPassExistenceMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class LowPassExistenceMapper extends AggregateMapper { + + @Override + protected Object doAggregate(MapParam mapParam, List items, Date startDate, Date endDate) { + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + double threshold = config.getThreshold(); + + boolean canEqual = config.getCanEqual(); + + boolean invert = config.getInvert(); + + return doDetermine(items, threshold, invert, canEqual); + } + + // 为了保证代码的可读性,此处代码不做简化。 + @SuppressWarnings("ConstantConditions") + private boolean doDetermine(List items, double threshold, boolean invert, boolean canEqual){ + for(Item item : items){ + if(invert && canEqual){ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) >= threshold){ + return true; + } + }else if(invert && !canEqual){ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) > threshold){ + return true; + } + }else if(!invert && canEqual){ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) <= threshold){ + return true; + } + }else{ + if((Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) < threshold){ + return true; + } + } + } + + return false; + } + + @Override + public String toString() { + return "LowPassExistenceMapper{}"; + } + } + + + public static class Config implements Bean { + + private static final long serialVersionUID = -5684552000019608904L; + + @JSONField(name = "threshold", ordinal = 1) + private double threshold; + + @JSONField(name = "#threshold", ordinal = 2, deserialize = false) + private String thresholdRem = "阈值,对数据进行筛选的标准"; + + @JSONField(name = "can_equal", ordinal = 3) + private boolean canEqual; + + @JSONField(name = "#can_equal", ordinal = 4, deserialize = false) + private String canEqualRem = "true:包含阈值,false:不包含阈值"; + + @JSONField(name = "invert", ordinal = 5) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 6, deserialize = false) + private String invertRem = "true:过滤掉低于阈值的数据,false:过滤掉高于阈值的数据"; + + public Config() { + } + + public Config(double threshold, boolean canEqual, boolean invert) { + this.threshold = threshold; + this.canEqual = canEqual; + this.invert = invert; + } + + public double getThreshold() { + return threshold; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public String getThresholdRem() { + return thresholdRem; + } + + public void setThresholdRem(String thresholdRem) { + this.thresholdRem = thresholdRem; + } + + public boolean getCanEqual() { + return canEqual; + } + + public void setCanEqual(boolean canEqual) { + this.canEqual = canEqual; + } + + public String getCanEqualRem() { + return canEqualRem; + } + + public void setCanEqualRem(String canEqualRem) { + this.canEqualRem = canEqualRem; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "threshold=" + threshold + + ", thresholdRem='" + thresholdRem + '\'' + + ", canEqual=" + canEqual + + ", canEqualRem='" + canEqualRem + '\'' + + ", invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } + +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassMapperRegistry.java new file mode 100644 index 00000000..b1bb3230 --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/LowPassMapperRegistry.java @@ -0,0 +1,220 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 保留高于阈值的数据。 + * + * @author mooyuan + * @since 2.0.0 + */ +public class LowPassMapperRegistry extends AbstractMapperRegistry{ + public static final String MAPPER_TYPE = "low_pass_mapper"; + + private final ApplicationContext ctx; + + public LowPassMapperRegistry(ApplicationContext ctx) { + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "低通映射器!"; + } + + @Override + public String provideDescription() { + return "用于保留高于阈值的数据: \n" + + "invert`用于控制计算的是低于阈值的数据还是高于阈值的数据: \n" + + "--false:过滤的是高于阈值的数据 \n" + + "--true:过滤的是低于阈值的数据 \n" + + "threshold用于过滤的阈值 \n" + + "can_equal是否包含等于阈值的数据"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(0.00, true, false)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(LowPassMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "LowPassMapper{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class LowPassMapper extends OneToOneMapper { + + @Override + protected Sequence doOneToOneMap(MapParam mapParam, Sequence sequence) { + + return lowPass(mapParam, sequence); + } + + @SuppressWarnings("DuplicatedCode") + public static Sequence lowPass(MapParam mapParam, Sequence sequence){ + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + double threshold = config.getThreshold(); + + boolean canEqual = config.getCanEqual(); + + boolean invert = config.getInvert(); + + // 定义数据条目列表。 + List items; + + items = doFilter(sequence, threshold, canEqual, invert); + + return new Sequence(sequence.getPointKey(),items,sequence.getStartDate(),sequence.getEndDate()); + } + + // 为了保证代码的可读性,此处代码不做简化。 + @SuppressWarnings("ConstantConditions") + private static List doFilter(Sequence sequence, double threshold, boolean canEqual, boolean invert) { + List items; + if(invert && canEqual){ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) >= threshold + ).collect(Collectors.toList()); + }else if(invert && !canEqual){ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) > threshold + ).collect(Collectors.toList()); + }else if(!invert && canEqual){ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) <= threshold + ).collect(Collectors.toList()); + }else{ + items = sequence.getItems().stream().filter( + item -> (Objects.isNull(item.getValue()) ? 0.00 : (double) item.getValue()) < threshold + ).collect(Collectors.toList()); + } + return items; + } + + @Override + public String toString() { + return "LowPassMapper{}"; + } + } + + public static class Config implements Bean { + + private static final long serialVersionUID = 6070172089803753766L; + + @JSONField(name = "threshold", ordinal = 1) + private double threshold; + + @JSONField(name = "#threshold", ordinal = 2, deserialize = false) + private String thresholdRem = "阈值,对数据进行筛选的标准"; + + @JSONField(name = "can_equal", ordinal = 3) + private boolean canEqual; + + @JSONField(name = "#can_equal", ordinal = 4, deserialize = false) + private String canEqualRem = "true:包含阈值,false:不包含阈值"; + + @JSONField(name = "invert", ordinal = 5) + private boolean invert; + + @JSONField(name = "#invert", ordinal = 6, deserialize = false) + private String invertRem = "true:过滤掉低于阈值的数据,false:过滤掉高于阈值的数据"; + + public Config() { + } + + public Config(double threshold, boolean canEqual, boolean invert) { + this.threshold = threshold; + this.canEqual = canEqual; + this.invert = invert; + } + + public double getThreshold() { + return threshold; + } + + public void setThreshold(double threshold) { + this.threshold = threshold; + } + + public String getThresholdRem() { + return thresholdRem; + } + + public void setThresholdRem(String thresholdRem) { + this.thresholdRem = thresholdRem; + } + + public boolean getCanEqual() { + return canEqual; + } + + public void setCanEqual(boolean canEqual) { + this.canEqual = canEqual; + } + + public String getCanEqualRem() { + return canEqualRem; + } + + public void setCanEqualRem(String canEqualRem) { + this.canEqualRem = canEqualRem; + } + + public boolean getInvert() { + return invert; + } + + public void setInvert(boolean invert) { + this.invert = invert; + } + + public String getInvertRem() { + return invertRem; + } + + public void setInvertRem(String invertRem) { + this.invertRem = invertRem; + } + + @Override + public String toString() { + return "Config{" + + "threshold=" + threshold + + ", thresholdRem='" + thresholdRem + '\'' + + ", canEqual=" + canEqual + + ", canEqualRem='" + canEqualRem + '\'' + + ", invert=" + invert + + ", invertRem='" + invertRem + '\'' + + '}'; + } + } +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/ToBooleanMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/ToBooleanMapperRegistry.java new file mode 100644 index 00000000..752d85a4 --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/ToBooleanMapperRegistry.java @@ -0,0 +1,239 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +/** + * 转化为布尔值。 + * + * @author mooyuan + * @since 2.0.0 + */ +@Component +public class ToBooleanMapperRegistry extends AbstractMapperRegistry { + + public static final String MAPPER_TYPE = "to_boolean_mapper"; + + private final ApplicationContext ctx; + + public ToBooleanMapperRegistry(ApplicationContext ctx) { + super(MAPPER_TYPE); + this.ctx = ctx; + } + + @Override + public String provideLabel() { + return "数据转换为布尔值的映射器!"; + } + + @Override + public String provideDescription() { + return "保留数据表中所有序列的开始时间和结束时间。对每个序列的数据条目做映射处理: \n" + + "是否为严格模式: \n" + + " 是:只有严格匹配真值或者假值的数据才会被转换为布尔类型的数据,如果序列中存在其它值的则抛出 `IllegalArgumentException` 异常 \n" + + " 字符串真值:true \n" + + " 字符串假值:false \n" + + " 数字真值:1.0 \n" + + " 数字假值:0.0 \n" + + " 否:数据匹配真值时,会被转换为布尔类型的真值,其余任何值都会被转换为布尔类型的假值 \n"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(false, true)); + } + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(ToDoubleMapperRegistry.ToDoubleMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String toString() { + return "ToBooleanMapperRegistry{" + + "mapperType='" + mapperType + '\'' + + '}'; + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class ToBooleanMapper extends OneToOneMapper { + + @Override + protected Sequence doOneToOneMap(MapParam mapParam, Sequence sequence) { + + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + // 遍历序列中的每个数据条目。 + List items = new ArrayList<>(sequence.getItems().size()); + for (Item item : sequence.getItems()) { + items.add(mapItem(config, item)); + } + + // 返回映射后的序列。 + return new Sequence(sequence.getPointKey(), items, sequence.getStartDate(), sequence.getEndDate()); + } + + // 处理具体的每条数据 + private Item mapItem(Config config, Item item) { + + // 是否忽略大小写 + boolean stringIgnoreCase = config.getStringIgnoreCase(); + boolean itemValue = false; + // 是否启用严格模式 + if (config.getStrict()) { + + if(!(item.getValue() instanceof String) && !(item.getValue() instanceof Number) && !(item.getValue() instanceof Boolean)){ + throw new IllegalStateException("严格模式:传入值格式不正确,请传入字符串、数值或者布尔"); + } + + if (item.getValue() instanceof String) { + + if ((stringIgnoreCase && "true".equalsIgnoreCase((String) item.getValue())) + || (!stringIgnoreCase && "true".equals(item.getValue()))) { + itemValue = true; + } else if ((stringIgnoreCase && !"false".equalsIgnoreCase((String) item.getValue())) + || (!stringIgnoreCase && !"false".equals(item.getValue()))) { + throw new IllegalStateException("严格模式:字符串格式不正确,请输入true或者false"); + } + } + + if (item.getValue() instanceof Number) { + if (BigDecimal.ONE.compareTo(BigDecimal.valueOf(((Number) item.getValue()).doubleValue())) == 0) { + itemValue = true; + } else if (BigDecimal.ZERO.compareTo(BigDecimal.valueOf(((Number) item.getValue()).doubleValue())) != 0) { + throw new IllegalStateException("严格模式:数值格式不正确,请输入1.0或者0.0"); + } + } + + } else { + + if (item.getValue() instanceof String) { + if ((stringIgnoreCase && "true".equalsIgnoreCase((String) item.getValue())) + || (!stringIgnoreCase && "true".equals(item.getValue()))) { + itemValue = true; + } + } + if (item.getValue() instanceof Number) { + if (BigDecimal.ONE.compareTo(BigDecimal.valueOf(((Number) item.getValue()).doubleValue())) == 0) { + itemValue = true; + } + } + } + if (item.getValue() instanceof Boolean) { + itemValue = (Boolean) item.getValue(); + } + + return new Item( + item.getPointKey(), + itemValue, + item.getHappenedDate() + ); + } + + @Override + public String toString() { + return "ToBooleanMapper{}"; + } + } + + public static class Config implements Bean { + + private static final long serialVersionUID = 6070172089803753762L; + + @JSONField(name = "strict", ordinal = 1) + private boolean strict; + + @JSONField(name = "#strict", ordinal = 2, deserialize = false) + private String onlyTrimStartRem = "true:启用严格模式,不符合直接抛出异常;false:不启用严格模式,不符合转为false"; + + @JSONField(name = "string_ignore_case", ordinal = 3) + private boolean stringIgnoreCase; + + @JSONField(name = "#string_ignore_case", ordinal = 4, deserialize = false) + private String stringIgnoreCaseRem = "true:忽略字符串大小写,false:不忽略大小写"; + + @JSONField(name = "#specification", ordinal = 5, deserialize = false) + private String specificationRem = + " 字符串真值:true \n" + + " 字符串假值:false \n" + + " 数字真值:1.0 \n" + + " 数字假值:0.0 \n"; + + public Config() { + } + + public Config(boolean strict, boolean stringIgnoreCase) { + this.strict = strict; + this.stringIgnoreCase = stringIgnoreCase; + } + + public boolean getStrict() { + return strict; + } + + public void setStrict(boolean strict) { + this.strict = strict; + } + + public String getOnlyTrimStartRem() { + return onlyTrimStartRem; + } + + public void setOnlyTrimStartRem(String onlyTrimStartRem) { + this.onlyTrimStartRem = onlyTrimStartRem; + } + + public boolean getStringIgnoreCase() { + return stringIgnoreCase; + } + + public void setStringIgnoreCase(boolean stringIgnoreCase) { + this.stringIgnoreCase = stringIgnoreCase; + } + + public String getStringIgnoreCaseRem() { + return stringIgnoreCaseRem; + } + + public void setStringIgnoreCaseRem(String stringIgnoreCaseRem) { + this.stringIgnoreCaseRem = stringIgnoreCaseRem; + } + + public String getSpecificationRem() { + return specificationRem; + } + + public void setSpecificationRem(String specificationRem) { + this.specificationRem = specificationRem; + } + + @Override + public String toString() { + return "Config{" + + "strict=" + strict + + ", onlyTrimStartRem='" + onlyTrimStartRem + '\'' + + ", stringIgnoreCase=" + stringIgnoreCase + + ", stringIgnoreCaseRem='" + stringIgnoreCaseRem + '\'' + + ", specificationRem='" + specificationRem + '\'' + + '}'; + } + } +} diff --git a/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/TrimMapperRegistry.java b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/TrimMapperRegistry.java new file mode 100644 index 00000000..fbb3bb74 --- /dev/null +++ b/fdr-impl/src/main/java/com/dwarfeng/fdr/impl/handler/mapper/TrimMapperRegistry.java @@ -0,0 +1,144 @@ +package com.dwarfeng.fdr.impl.handler.mapper; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; +import com.dwarfeng.fdr.sdk.util.CompareUtil; +import com.dwarfeng.fdr.stack.exception.MapperException; +import com.dwarfeng.fdr.stack.exception.MapperMakeException; +import com.dwarfeng.fdr.stack.handler.Mapper; +import com.dwarfeng.subgrade.stack.bean.Bean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + + +/** + * 用于裁剪序列的起始时间和结束时间。映射器工作时会寻找序列中发生时间最早和最晚的数据, + * 然后将这两个数据的发生时间作为序列的起始时间和结束时间。 + * + * @author mooyuan + * @since 2.0.0 + */ +@Component +public class TrimMapperRegistry extends AbstractMapperRegistry{ + + public static final String MAPPER_TYPE = "trim_mapper"; + + private final ApplicationContext ctx; + + public TrimMapperRegistry(ApplicationContext ctx) { + super(MAPPER_TYPE); + this.ctx = ctx; + } + + + @Override + public Mapper makeMapper() throws MapperException { + try { + return ctx.getBean(TrimMapper.class); + } catch (Exception e) { + throw new MapperMakeException(e); + } + } + + @Override + public String provideLabel() { + return "用于裁剪序列的起始时间和结束时间。"; + } + + @Override + public String provideDescription() { + return "映射器工作时会寻找序列中发生时间最早和最晚的数据,然后将这两个数据的发生时间作为序列的起始时间和结束时间,若使用 `only_trim_start` 配置项可以只裁剪序列的起始时间。"; + } + + @Override + public String provideExampleParam() { + return JSON.toJSONString(new Config(false)); + } + + @Component + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public static class TrimMapper extends OneToOneMapper { + + @Override + protected Sequence doOneToOneMap(MapParam mapParam, Sequence sequence) { + + // 获得配置。 + Config config = JSON.parseObject(mapParam.getParam(), Config.class); + + return trimSequence(sequence, config.getOnlyTrimStart()); + } + + // 排序并截取序列 + private Sequence trimSequence(Sequence sequence, boolean only_trim_start){ + // 获取序列的起始时间与结束时间。 + List items = new ArrayList<>(sequence.getItems()); + items.sort(CompareUtil.DATA_HAPPENED_DATE_ASC_COMPARATOR); + + Date startDate = items.get(0).getHappenedDate(); + Date endDate = items.get(items.size() - 1).getHappenedDate(); + + // 如果起始时间等于结束时间只取一个值即可 + if(only_trim_start){ + + endDate = sequence.getEndDate(); + } + + // 返回新的序列 + return new Sequence(sequence.getPointKey(), items, startDate, endDate); + } + + @Override + public String toString() { + return "TrimMapper{}"; + } + + } + + public static class Config implements Bean { + + private static final long serialVersionUID = 3688860693739279015L; + + @JSONField(name = "only_trim_start", ordinal = 1) + private boolean onlyTrimStart = false; + + @JSONField(name = "#only_trim_start", ordinal = 2, deserialize = false) + private String onlyTrimStartRem = "当onlyTrimStart为true时只剪裁序列的起始时间,false裁剪序列的起始时间和结束时间"; + + public Config() { + } + + public Config(boolean onlyTrimStart) { + this.onlyTrimStart = onlyTrimStart; + } + + public boolean getOnlyTrimStart() { + return onlyTrimStart; + } + + public void setOnlyTrimStart(boolean onlyTrimStart) { + this.onlyTrimStart = onlyTrimStart; + } + + public String getOnlyTrimStartRem() { + return onlyTrimStartRem; + } + + public void setOnlyTrimStartRem(String onlyTrimStartRem) { + this.onlyTrimStartRem = onlyTrimStartRem; + } + + @Override + public String toString() { + return "Config{" + + "onlyTrimStart=" + onlyTrimStart + + ", onlyTrimStartRem='" + onlyTrimStartRem + '\'' + + '}'; + } + } +} -- Gitee