All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.wizzie.normalizer.funcs.impl.SplitterFlatMapper Maven / Gradle / Ivy

package io.wizzie.normalizer.funcs.impl;

import io.wizzie.metrics.MetricsManager;
import io.wizzie.normalizer.funcs.FlatMapperFunction;
import org.apache.kafka.streams.KeyValue;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Seconds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SplitterFlatMapper extends FlatMapperFunction {
    private static final Logger log = LoggerFactory.getLogger(SplitterFlatMapper.class);

    SplitterModel splitter;

    @Override
    public void prepare(Map properties, MetricsManager metricsManager) {
        splitter = new SplitterModel(
                (List) properties.get("dimensions"),
                (String) properties.get("timestampDim"),
                (String) properties.get("firstTimestampDim"),
                "60");
    }

    @Override
    public Iterable>> process(String key, Map value) {
        if (value != null) {
            List>> generatedPackets = new ArrayList<>();

            if (value.containsKey(splitter.getFirstTimestampDim()) && value.containsKey(splitter.getTimestampDim())) {

                DateTime packet_start = new DateTime(Long.parseLong(value.get(splitter.getFirstTimestampDim()).toString()) * 1000, DateTimeZone.UTC);
                DateTime packet_end = new DateTime(Long.parseLong(value.get(splitter.getTimestampDim()).toString()) * 1000, DateTimeZone.UTC);

                DateTime this_start;
                DateTime this_end = packet_start;

                long totalDiff = Seconds.secondsBetween(packet_start, packet_end).getSeconds();

                Map data_map = new HashMap<>();
                Map data_count = new HashMap<>();
                for (String dimension : splitter.getDimensions()) {

                    try {
                        if (value.containsKey(dimension)) {
                            data_map.put(dimension, Long.parseLong(value.get(dimension).toString()));
                            data_count.put(dimension, 0L);
                        }
                    } catch (NumberFormatException e) {
                        log.warn(e.getMessage(), e);
                        return generatedPackets;
                    }

                }

                do {
                    long diff, this_data;

                    this_start = this_end;
                    this_end = this_start.plusSeconds(splitter.getInterval() - this_start.getSecondOfMinute());
                    if (this_end.isAfter(packet_end)) this_end = packet_end;
                    diff = Seconds.secondsBetween(this_start, this_end).getSeconds();

                    Map to_send = new HashMap<>();
                    to_send.putAll(value);
                    to_send.put(splitter.getTimestampDim(), this_start.getMillis() / 1000);
                    to_send.remove(splitter.getFirstTimestampDim());

                    for (Map.Entry entry : data_map.entrySet()) {
                        if (totalDiff == 0) this_data = entry.getValue();
                        else this_data = (long) Math.ceil(entry.getValue() * diff / totalDiff);

                        Long data_dimension = data_count.get(entry.getKey());
                        data_dimension += this_data;
                        data_count.put(entry.getKey(), data_dimension);

                        to_send.put(entry.getKey(), this_data);
                    }

                    generatedPackets.add(new KeyValue<>(key, to_send));

                } while (this_end.isBefore(packet_end));

                for (Map.Entry data : data_map.entrySet()) {
                    if (data.getValue() != data_count.get(data.getKey())) {
                        int last_index = generatedPackets.size() - 1;
                        KeyValue> last = generatedPackets.get(last_index);
                        long new_data = ((long) last.value.get(data.getKey()) + (data.getValue() - data_count.get(data.getKey())));

                        if (new_data > 0) last.value.put(data.getKey(), new_data);
                    }
                }

            } else if (value.containsKey(splitter.getTimestampDim())) {
                try {
                    for (String dimension : splitter.getDimensions()) {
                        if (value.containsKey(dimension)) {
                            Long data = Long.parseLong(value.get(dimension).toString());
                            value.put(dimension, data);
                        }
                    }

                    generatedPackets.add(new KeyValue<>(key, value));

                } catch (NumberFormatException e) {
                    log.warn(e.getMessage(), e);
                    return generatedPackets;
                }
            } else {

                try {
                    for (String dimension : splitter.getDimensions()) {
                        if (value.containsKey(dimension)) {
                            Long data = Long.parseLong(value.get(dimension).toString());
                            value.put(dimension, data);
                        }
                    }
                    generatedPackets.add(new KeyValue<>(key, value));
                } catch (NumberFormatException e) {
                    log.warn(e.getMessage(), e);
                    return generatedPackets;
                }
            }


            return generatedPackets;
        } else {
            return null;
        }
    }

    @Override
    public void stop() {

    }

    @Override
    public String toString() {

        StringBuilder builder = new StringBuilder();

        builder.append("[");
        builder.append(splitter.toString());
        builder.append("]");

        return builder.toString();
    }

    public class SplitterModel {
        List dimensions;
        Integer interval;
        String firstTimestampDim = "last_timestamp";
        String timestampDim = "timestamp";

        SplitterModel(List dimensions, String timestamp, String firstTimestamp, String interval) {
            this.dimensions = dimensions;
            if (firstTimestamp != null) this.firstTimestampDim = firstTimestamp;
            if (timestamp != null) this.timestampDim = timestamp;
            this.interval = interval != null ? Integer.valueOf(interval) : 60;
        }

        public List getDimensions() {
            return dimensions;
        }

        public Integer getInterval() {
            return interval;
        }

        public String getFirstTimestampDim() {
            return firstTimestampDim;
        }

        public String getTimestampDim() {
            return timestampDim;
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append(" {")
                    .append("dimensions: ").append(dimensions).append(", ")
                    .append("timestampDim: ").append(timestampDim).append(", ")
                    .append("firstTimestampDim: ").append(firstTimestampDim).append(", ")
                    .append("interval: ").append(interval)
                    .append("} ");

            return builder.toString();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy