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

net.intelie.liverig.plugin.widgets.PipesExpressions Maven / Gradle / Ivy

The newest version!
package net.intelie.liverig.plugin.widgets;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import net.intelie.liverig.plugin.curves.CalculatedCurve;
import net.intelie.liverig.plugin.curves.CalculatedCurves;
import net.intelie.pipes.util.Escapes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.stream.Collectors;

public class PipesExpressions {

    public static final String LOOKUP_VALUE_MACRO = "@@lookupValue";

    private static final Joiner COMMA_JOINER = Joiner.on(",");
    private static final String LOOKUP_VALUE_DEF = "def " + LOOKUP_VALUE_MACRO + ": @@lookup.%s ?? ();\n";
    private static final String VALUE_FN_DEF = "def* value(channel): def @@channel: channel; (mnemonic:lower == @@channel:lower) ? value, null as (channel);\n";
    private static final String AGG_FN_DEF = "def* agg(channel): def @@channel: channel; lastv(value):if(mnemonic:lower == @@channel:lower) as (channel);\n";
    private static final String EMPTY_FN_IMPL = "  => @empty over last 5 minutes\n";
    private static final String META_IMPL_TEMPLATE = "  => @meta (@@channels |> map(_, :curve_color)):const%s as __color,\n" +
            "    (@@channels |> map(_, @@display_units[_] ?? :curve_unit)):const%s as __uom,\n" +
            "    (@@channels |> map(_, @@display_precisions[_] ?? :curve_precision)):const%s as __precision,\n" +
            "    (@@channels |> map(_, :curve_description)):const%s as __description";

    private static final String ASSET_CONFIG_META_TEMPLATE = "%s as __assetConfig";
    private static final String ASSET_ID_META_TEMPLATE = "%s as __assetId";
    private static final String ASSET_NAME_META_TEMPLATE = "%s as __assetName";
    private static final String LOOKUP_NAME_META_TEMPLATE = "%s as __lookup";
    private static final String DEFAULT_VALUE_IMPL = "  => value(@@channels!)!\n";
    private static final String AGG_IMPL_TEMPLATE = "  => agg(@@channels!)!%s %s\n";

    private final CalculatedCurves calculatedCurves;

    public PipesExpressions(CalculatedCurves calculatedCurves) {
        this.calculatedCurves = calculatedCurves;
    }

    @NotNull
    public static String lookupImpl(String lookup) {
        return lookup != null ? String.format((Locale) null, LOOKUP_VALUE_DEF, lookup) : "";
    }

    @Nullable
    public String expressionForChannelsValueHistorical(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull Set channels, @Nullable DisplayUnit displayUnit, AssetRequest assetRequest) {
        if (channels.isEmpty()) return null;

        String metaImpl = metaImpl(queryDetails.getAssetId(), null, null, null, null, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, channels);

        return makeExpression(queryDetails.getFilter() + " .flags:reversed .partial:1", "adjusted_index_timestamp", channelsDef(channels, null),
                VALUE_FN_DEF, convertFnDef(displayUnit, channels, false),
                DEFAULT_VALUE_IMPL + EMPTY_FN_IMPL,
                metaImpl, lookupImpl(queryDetails.getLookup()),
                "  => convert(@@channels!)! every item\n"
        );
    }

    @Nullable
    public String expressionForChannelsValueRealTime(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull Set channels, @Nullable DisplayUnit displayUnit, AssetRequest assetRequest) {
        if (channels.isEmpty()) return null;

        String metaImpl = metaImpl(queryDetails.getAssetId(), null, null, null, null, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, channels);

        return makeExpression(queryDetails.getFilter(), "adjusted_index_timestamp", channelsDef(channels, null),
                VALUE_FN_DEF, convertFnDef(displayUnit, channels, false),
                DEFAULT_VALUE_IMPL,
                metaImpl, lookupImpl(queryDetails.getLookup()),
                "  => convert(@@channels!)! every item\n"
        );
    }

    @Nullable
    public String expressionForChannelsSeries(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, @NotNull Set channels,
                                              @Nullable DisplayUnit displayUnit, @NotNull AssetRequest assetRequest, CompressionDetails compressionDetails,
                                              @NotNull String valueConvertCall, @Nullable String indexConvertCall, boolean isText
    ) {
        if (channels.isEmpty()) return null;

        String metaImpl = metaImpl(queryDetails.getAssetId(), null, null, null, null, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, channels) + ",\n    (\"mnemonic\",):seq as pipes.group";

        return makeExpression(queryDetails.getFilter(), indexProperty, channelsDef(channels, null),
                VALUE_FN_DEF, convertFnDef(displayUnit, channels, true),
                compressionPipe(compressionDetails, isText) +
                        valuePipe(isText),
                metaImpl, lookupImpl(queryDetails.getLookup()),
                convertCallPipe(valueConvertCall, indexConvertCall, isText)
        );
    }

    @Nullable
    public String expressionForChannelsSeries(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, @NotNull Set channels,
                                              @Nullable DisplayUnit displayUnit, @NotNull AssetRequest assetRequest, CompressionDetails compressionDetails,
                                              boolean isText
    ) {
        return expressionForChannelsSeries(
                queryDetails, indexProperty, channels, displayUnit, assetRequest, compressionDetails, "  => convert(value, mnemonic), mnemonic every item\n", null, isText
        );
    }

    @Nullable
    public String expressionForThrottledChannelsSeries(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, @NotNull Set channels,
                                                       @Nullable DisplayUnit displayUnit, @NotNull AssetRequest assetRequest, CompressionDetails compressionDetails,
                                                       @NotNull String valueConvertCall, @Nullable String indexConvertCall, boolean isText
    ) {
        if (channels.isEmpty()) return null;

        String metaImpl = metaImpl(queryDetails.getAssetId(), null, null, null, null, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, channels) + ",\n    (\"mnemonic\",):seq as pipes.group";

        return makeExpression(
                queryDetails.getFilter(),
                indexProperty,
                "def @@throttleChannel: period(max((span(sys.timestamp(), @@span)->(end-start)) / 20, 1), 'ms'):const;\n" + channelsDef(channels, null),
                VALUE_FN_DEF,
                convertFnDef(displayUnit, channels, true),
                compressionPipe(compressionDetails, isText) + valuePipe(isText),
                metaImpl,
                lookupImpl(queryDetails.getLookup()),
                convertCallPipe(valueConvertCall, indexConvertCall, isText) + "  => @throttle @@throttleChannel by mnemonic\n"
        );
    }

    @Nullable
    public String expressionForThrottledChannelsSeries(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty,
                                                       @NotNull Set channels, @Nullable DisplayUnit displayUnit,
                                                       @NotNull AssetRequest assetRequest, CompressionDetails compressionDetails,
                                                       boolean isText) {
        return expressionForThrottledChannelsSeries(
                queryDetails, indexProperty, channels, displayUnit,
                assetRequest, compressionDetails,
                "  => convert(value, mnemonic), mnemonic every item\n", null, isText
        );
    }

    @Nullable
    public String expressionForCalculatedChannels(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, Set channels,
                                                  @Nullable DisplayUnit displayUnit, AssetRequest assetRequest, String indexConvertCall, boolean isText) {
        LinkedHashSet inputChannels = new LinkedHashSet<>();
        LinkedHashSet functionCalls = new LinkedHashSet<>();
        LinkedHashMap colors = new LinkedHashMap<>();
        LinkedHashMap uoms = new LinkedHashMap<>();
        LinkedHashMap precisions = new LinkedHashMap<>();
        LinkedHashMap descriptions = new LinkedHashMap<>();

        for (String channel : channels) {
            CalculatedCurve curve = calculatedCurves.getCurve(channel);

            if (curve != null) {
                String color = curve.color();
                if (!Strings.isNullOrEmpty(color))
                    colors.put(channel, color);

                String defaultUom = curve.unit();
                Integer defaultPrecision = curve.precision() != null ? curve.precision().intValue() : null;

                String displayUnitUom = null;
                Integer displayUnitPrecision = null;

                if (!Strings.isNullOrEmpty(defaultUom) || defaultPrecision != null) {
                    if (displayUnit != null) {
                        DisplayUnitData dataForMnemonic = displayUnit.getDataForMnemonic(channel);

                        if (dataForMnemonic != null) {
                            displayUnitUom = dataForMnemonic.getUnit();
                            displayUnitPrecision = dataForMnemonic.getPrecision();
                        }
                    }

                    if (defaultUom != null || displayUnitUom != null) {
                        uoms.put(channel, displayUnitUom != null ? displayUnitUom : defaultUom);
                    }

                    if (defaultPrecision != null || displayUnitPrecision != null) {
                        precisions.put(channel, displayUnitPrecision != null ? displayUnitPrecision.toString() : defaultPrecision.toString());
                    }
                }

                String description = curve.description();
                if (!Strings.isNullOrEmpty(description))
                    descriptions.put(channel, description);

                Set parameters = calculatedCurves.getCurveParameters(curve);

                inputChannels.addAll(parameters);

                Integer finalPrecision = displayUnitPrecision != null ? displayUnitPrecision : defaultPrecision;

                functionCalls.add(fnCall(channel, parameters, defaultUom, displayUnitUom, finalPrecision));
            }
        }

        String outputImpl = "\n  => " + COMMA_JOINER.join(functionCalls);
        if (inputChannels.isEmpty()) {
            if (channels.isEmpty())
                return null;

            outputImpl += " every second";
        }

        return makeExpression(queryDetails.getFilter(), indexProperty, channelsDef(inputChannels, channels), AGG_FN_DEF, convertFnDef(displayUnit, inputChannels, false),
                aggImpl("over last minute every item", inputChannels.contains("extra")),
                metaImpl(queryDetails.getAssetId(), colors, uoms, precisions, descriptions, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, channels),
                lookupImpl(queryDetails.getLookup()),
                convertCallPipe(null, indexConvertCall, isText)
        ) + outputImpl;
    }

    public String expressionForCalculatedChannels(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, Set channels,
                                                  @Nullable DisplayUnit displayUnit, AssetRequest assetRequest) {
        return expressionForCalculatedChannels(queryDetails, indexProperty, channels, displayUnit, assetRequest, "", false);
    }

    @Nullable
    public String expressionForThrottledCalculatedChannels(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, Set channels,
                                                           @Nullable DisplayUnit displayUnit, AssetRequest assetRequest, String valueConvertCall, String indexConvertCall, boolean isText) {
        LinkedHashSet inputChannels = new LinkedHashSet<>();
        LinkedHashSet functionCalls = new LinkedHashSet<>();
        LinkedHashMap colors = new LinkedHashMap<>();
        LinkedHashMap uoms = new LinkedHashMap<>();
        LinkedHashMap precisions = new LinkedHashMap<>();
        LinkedHashMap descriptions = new LinkedHashMap<>();

        for (String channel : channels) {
            CalculatedCurve curve = calculatedCurves.getCurve(channel);

            if (curve != null) {
                String color = curve.color();
                if (!Strings.isNullOrEmpty(color))
                    colors.put(channel, color);

                String defaultUom = curve.unit();
                Integer defaultPrecision = curve.precision() != null ? curve.precision().intValue() : null;

                String displayUnitUom = null;
                Integer displayUnitPrecision = null;

                if (!Strings.isNullOrEmpty(defaultUom) || defaultPrecision != null) {
                    if (displayUnit != null) {
                        DisplayUnitData dataForMnemonic = displayUnit.getDataForMnemonic(channel);

                        if (dataForMnemonic != null) {
                            displayUnitUom = dataForMnemonic.getUnit();
                            displayUnitPrecision = dataForMnemonic.getPrecision();
                        }
                    }

                    if (defaultUom != null || displayUnitUom != null) {
                        uoms.put(channel, displayUnitUom != null ? displayUnitUom : defaultUom);
                    }

                    if (defaultPrecision != null || displayUnitPrecision != null) {
                        precisions.put(channel, displayUnitPrecision != null ? displayUnitPrecision.toString() : defaultPrecision.toString());
                    }
                }

                String description = curve.description();
                if (!Strings.isNullOrEmpty(description))
                    descriptions.put(channel, description);

                Set parameters = calculatedCurves.getCurveParameters(curve);

                inputChannels.addAll(parameters);

                Integer finalPrecision = displayUnitPrecision != null ? displayUnitPrecision : defaultPrecision;

                functionCalls.add(fnCall(channel, parameters, defaultUom, displayUnitUom, finalPrecision));
            }
        }

        String outputImpl = "\n  => " + COMMA_JOINER.join(functionCalls);
        if (inputChannels.isEmpty()) {
            if (channels.isEmpty())
                return null;

            outputImpl += " every second";
        }

        return makeExpression(
                queryDetails.getFilter(),
                indexProperty,
                "def @@throttleChannel: period(max((span(sys.timestamp(), @@span)->(end-start)) / 20, 1), 'ms'):const;\n" + channelsDef(inputChannels, channels), AGG_FN_DEF, convertFnDef(displayUnit, inputChannels, false),
                aggImpl("over last minute every item", inputChannels.contains("extra")),
                metaImpl(queryDetails.getAssetId(), colors, uoms, precisions, descriptions, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, channels),
                lookupImpl(queryDetails.getLookup()),
                convertCallPipe(valueConvertCall, indexConvertCall, isText)
        ) + outputImpl + "\n  => @throttle @@throttleChannel by @@outputChannels";
    }

    public String expressionForThrottledCalculatedChannels(@NotNull AssetWidgetQueryDetails queryDetails, @NotNull String indexProperty, Set channels,
                                                           @Nullable DisplayUnit displayUnit, AssetRequest assetRequest) {
        return expressionForThrottledCalculatedChannels(queryDetails, indexProperty, channels, displayUnit, assetRequest, "", "", false);
    }


    @Nullable
    public String expressionForSampledChannels(@NotNull AssetWidgetQueryDetails queryDetails, String indexProperty, @NotNull Set channels, @NotNull Set calculatedChannels,
                                               @Nullable DisplayUnit displayUnit, AssetRequest assetRequest) {
        LinkedHashSet functionCalls = new LinkedHashSet<>();
        LinkedHashMap colors = new LinkedHashMap<>();
        LinkedHashMap uoms = new LinkedHashMap<>();
        LinkedHashMap precisions = new LinkedHashMap<>();
        LinkedHashMap descriptions = new LinkedHashMap<>();

        LinkedHashSet inputChannels = new LinkedHashSet<>(channels);
        LinkedHashSet outputChannels = new LinkedHashSet<>(channels);

        for (String channel : calculatedChannels) {
            CalculatedCurve curve = calculatedCurves.getCurve(channel);

            if (curve != null) {
                String color = curve.color();
                if (!Strings.isNullOrEmpty(color))
                    colors.put(channel, color);

                String defaultUom = curve.unit();
                Integer defaultPrecision = curve.precision() != null ? curve.precision().intValue() : null;

                String displayUnitUom = null;
                Integer displayUnitPrecision = null;

                if (!Strings.isNullOrEmpty(defaultUom) || defaultPrecision != null) {
                    if (displayUnit != null) {
                        DisplayUnitData dataForMnemonic = displayUnit.getDataForMnemonic(channel);

                        if (dataForMnemonic != null) {
                            displayUnitUom = dataForMnemonic.getUnit();
                            displayUnitPrecision = dataForMnemonic.getPrecision();
                        }
                    }

                    if (defaultUom != null || displayUnitUom != null) {
                        uoms.put(channel, displayUnitUom != null ? displayUnitUom : defaultUom);
                    }

                    if (defaultPrecision != null || displayUnitPrecision != null) {
                        Integer dp = displayUnitPrecision != null ? displayUnitPrecision : defaultPrecision;
                        precisions.put(channel, dp.toString());
                    }
                }

                String description = curve.description();
                if (!Strings.isNullOrEmpty(description))
                    descriptions.put(channel, description);

                Set parameters = calculatedCurves.getCurveParameters(curve);

                inputChannels.addAll(parameters);

                Integer finalPrecision = displayUnitPrecision != null ? displayUnitPrecision : defaultPrecision;

                functionCalls.add(fnCall(channel, parameters, defaultUom, displayUnitUom, finalPrecision));
            }
        }

        String outputImpl;
        if (inputChannels.isEmpty()) {
            if (calculatedChannels.isEmpty())
                return null;

            outputImpl = "\n  => " + COMMA_JOINER.join(functionCalls) + " every second";
        } else {
            outputImpl = "\n  => convert(@@outputChannels!)!" + (!functionCalls.isEmpty() ? "," + COMMA_JOINER.join(functionCalls) : "");
        }

        HashSet allChannels = new HashSet<>(channels);
        allChannels.addAll(calculatedChannels);

        return makeExpression(
                queryDetails.getFilter(),
                indexProperty, channelsDef(inputChannels, outputChannels),
                AGG_FN_DEF,
                convertFnDef(displayUnit, inputChannels, false),
                aggImpl("over last minute every second", inputChannels.contains("extra")),
                metaImpl(queryDetails.getAssetId(), colors, uoms, precisions, descriptions, queryDetails.getAssetName(), queryDetails.getLookup(), assetRequest, allChannels),
                lookupImpl(queryDetails.getLookup()),
                ""
        ) +
                outputImpl;
    }

    @NotNull
    private String compressionPipe(CompressionDetails compressionDetails, boolean isText) {
        return compressionDetails.isEnabled() && !isText ?
                "  => @compress.swingingDoor value#" +
                        (compressionDetails.getMaxVariation() != null ? ", " + compressionDetails.getMaxVariation() : "") +
                        (compressionDetails.getMaxOutputPeriod() != null ? ", " + compressionDetails.getMaxOutputPeriod() : "") +
                        " by mnemonic\n" :
                "";
    }

    @NotNull
    private String valuePipe(boolean isText) {
        return "  => value" + (isText ? "" : "#") + ", mnemonic \n";
    }

    @NotNull
    private String convertCallPipe(@Nullable String valueConvertCall, @Nullable String indexConvertCall, boolean isText) {
        return (isText ? "" : Strings.nullToEmpty(valueConvertCall)) + Strings.nullToEmpty(indexConvertCall);
    }

    @NotNull
    private String makeExpression(@NotNull String filter, @NotNull String indexProperty, @NotNull String channelsDef, @NotNull String aggFnDef, @NotNull String convertFnDef, @NotNull String aggImpl,
                                  @NotNull String metaImpl, @NotNull String lookupValueDef, @NotNull String convertCall) {
        return lookupValueDef + aggFnDef + channelsDef + convertFnDef + filterDef(filter, indexProperty) + aggImpl + convertCall + metaImpl;
    }

    private String channelsDef(Set inputChannels, Set outputChannels) {
        StringBuilder expression = new StringBuilder()
                .append("def @@channels: (")
                .append(COMMA_JOINER.join(inputChannels.stream()
                        .filter(s -> !"extra".equalsIgnoreCase(s))
                        .map(s -> String.format((Locale) null, "\"%s\"", s))
                        .collect(Collectors.toList())));

        if (inputChannels.size() == 1)
            expression.append(",");

        expression.append(");\n");

        if (outputChannels != null) {
            expression.append("def @@outputChannels: (")
                    .append(COMMA_JOINER.join(outputChannels.stream()
                            .map(s -> String.format((Locale) null, "\"%s\"", s))
                            .collect(Collectors.toList())));

            if (outputChannels.size() == 1)
                expression.append(",");

            expression.append(");\n");
        }

        return expression.toString();
    }

    private String convertFnDef(DisplayUnit displayUnit, Set inputChannels, Boolean isDefaultChannel) {
        StringBuilder expression = new StringBuilder()
                .append("def @@display_units: newmap(")
                .append(
                        COMMA_JOINER.join(
                                inputChannels.stream().map(channel ->
                                        {
                                            String unit = null;
                                            if (displayUnit != null) {
                                                DisplayUnitData dataForMnemonic = displayUnit.getDataForMnemonic(channel);
                                                unit = dataForMnemonic != null ? dataForMnemonic.getUnit() : null;
                                            }

                                            return "\"" + channel + "\"," + (unit != null ? "\"" + unit + "\"" : "null");
                                        }
                                ).collect(Collectors.toList())
                        )
                ).append("); \n");

        expression
                .append("def @@display_precisions: newmap(")
                .append(
                        COMMA_JOINER.join(
                                inputChannels.stream().map(channel ->
                                        {
                                            Number precision = null;
                                            if (displayUnit != null) {
                                                DisplayUnitData dataForMnemonic = displayUnit.getDataForMnemonic(channel);
                                                precision = dataForMnemonic != null ? dataForMnemonic.getPrecision() : null;
                                            }


                                            return "\"" + channel + "\"," + (precision != null ? "" + precision + "" : "null");
                                        }
                                ).collect(Collectors.toList())
                        )
                ).append("); \n");


        expression.append("def convertValue(channel, value, sourceUnit): " +
                "(@@display_units[channel] ?? sourceUnit) != null ? " +
                "value#curve_unit_convert(sourceUnit ?? curve_unit(channel), @@display_units[channel] ?? curve_unit(channel)):round((@@display_precisions[channel] ?? curve_precision(channel) ?? 10):min(10))," +
                " value; \n");

        if (isDefaultChannel) {
            expression.append("def convert(value, channel): convertValue(channel, value, null) as value; \n");
        } else {
            expression.append("def* convert(channel): convertValue(channel, channel:property(), null)  as (channel); \n");
        }


        return expression.toString();
    }

    private String filterDef(String filter, final String indexProperty) {
        return filter + " .timestamp:" + indexProperty + " " + indexProperty + ":* mnemonic!:@@channels\n";
    }

    @NotNull
    private String fnCall(String qualifier, Set parameters, String fromUnit, String toUnit, Integer precision) {
        StringBuilder callBuilder = new StringBuilder("calc." + Escapes.safeIdentifier(qualifier) + "(");

        if (parameters != null)
            callBuilder.append(COMMA_JOINER.join(parameters.stream()
                    .map(Escapes::formatIdentifier)
                    .collect(Collectors.toList())));

        callBuilder.append(")");
        if (!Strings.isNullOrEmpty(fromUnit) && !Strings.isNullOrEmpty(toUnit)) {
            callBuilder.append("#curve_unit_convert('").append(fromUnit).append("','").append(toUnit).append("')");
        }

        if (precision != null && precision >= 0) {
            callBuilder.append(":round((").append(precision).append("):min(10))");
        }
        callBuilder.append(" as ");
        callBuilder.append(Escapes.formatIdentifier(qualifier));

        return callBuilder.toString();
    }

    @NotNull
    private String aggImpl(String window, boolean hasExtra) {
        return String.format((Locale) null, AGG_IMPL_TEMPLATE, hasExtra ? ", curve_extra(extra) as extra" : "", window);
    }

    @NotNull
    private String metaImpl(String assetId, LinkedHashMap colors, LinkedHashMap uoms, LinkedHashMap precisions, LinkedHashMap descriptions,
                            String assetName, String lookup, AssetRequest assetRequest, Set channels) {
        String meta = String.format((Locale) null, META_IMPL_TEMPLATE,
                (colors == null || colors.isEmpty() ? "" : " + newmap(" + zip(colors) + ")"),
                (uoms == null || uoms.isEmpty() ? "" : " + newmap(" + zip(uoms) + ")"),
                (precisions == null || precisions.isEmpty() ? "" : " + newmap(" + zipUnquotedValue(precisions) + ")"),
                (descriptions == null || descriptions.isEmpty() ? "" : " + newmap(" + zip(descriptions) + ")"));

        if (!Strings.isNullOrEmpty(assetId))
            meta += ",\n    " + String.format((Locale) null, ASSET_ID_META_TEMPLATE, assetId);
        if (!Strings.isNullOrEmpty(assetName))
            meta += ",\n    " + String.format((Locale) null, ASSET_NAME_META_TEMPLATE, assetName);
        if (!Strings.isNullOrEmpty(lookup))
            meta += ",\n    " + String.format((Locale) null, LOOKUP_NAME_META_TEMPLATE, "'" + lookup + "'");

        List allRequestChannels = new ArrayList<>(assetRequest.getChannels());
        allRequestChannels.addAll(assetRequest.getCalculatedChannels());

        List scopeChannels = allRequestChannels.stream().filter(c -> channels.contains(c.getQualifier())).collect(Collectors.toList());

        LinkedHashMap assetChannels = getAssetMetaConfig(scopeChannels);

        meta += ",\n    " + String.format((Locale) null, ASSET_CONFIG_META_TEMPLATE, "newmap(" + zipUnquotedValue(assetChannels) + ")");

        return meta;
    }

    private LinkedHashMap getAssetMetaConfig(List channels) {
        LinkedHashMap assetMetaConfig = new LinkedHashMap<>();
        LinkedHashMap assetChannelConfig = new LinkedHashMap<>();

        if (!channels.isEmpty()) {
            channels.forEach(assetChannel -> {
                LinkedHashMap channelsMetaConfig = new LinkedHashMap<>();

                String qualifier = assetChannel.getQualifier();

                AssetChannel.UnitValueWrapper thresholdMin = assetChannel.getThresholdMin();
                AssetChannel.UnitValueWrapper thresholdMax = assetChannel.getThresholdMax();
                AssetChannel.UnitValueWrapper axisMin = assetChannel.getAxisMin();
                AssetChannel.UnitValueWrapper axisMax = assetChannel.getAxisMax();

                if (thresholdMin.getValue() != null) {
                    channelsMetaConfig.put("thresholdMin", convertValueFn(qualifier, thresholdMin.getValue(), thresholdMin.getUnit()));
                }
                if (thresholdMax.getValue() != null) {
                    channelsMetaConfig.put("thresholdMax", convertValueFn(qualifier, thresholdMax.getValue(), thresholdMax.getUnit()));
                }
                if (axisMin.getValue() != null) {
                    channelsMetaConfig.put("axisMin", convertValueFn(qualifier, axisMin.getValue(), axisMin.getUnit()));
                }
                if (axisMax.getValue() != null) {
                    channelsMetaConfig.put("axisMax", convertValueFn(qualifier, axisMax.getValue(), axisMax.getUnit()));
                }

                assetChannelConfig.put(qualifier, "newmap(" + zipUnquotedValue(channelsMetaConfig) + ")");
            });
        }

        assetMetaConfig.put("channels", "newmap(" + zipUnquotedValue(assetChannelConfig) + ")");

        return assetMetaConfig;
    }

    private String convertValueFn(String qualifier, Double value) {
        return "(convertValue(\"" + qualifier + "\"," + value + ", null)):const";
    }

    private String convertValueFn(String qualifier, Double value, String sourceUnit) {
        if (Strings.isNullOrEmpty(sourceUnit)) return convertValueFn(qualifier, value);

        return "(convertValue(\"" + qualifier + "\"," + value + ", \"" + sourceUnit + "\")):const";
    }

    @NotNull
    private String zip(LinkedHashMap map) {
        return COMMA_JOINER.join(map.entrySet().stream()
                .map(e -> "'" + e.getKey() + "','" + e.getValue() + "'")
                .collect(Collectors.toList()));
    }

    @NotNull
    private String zipUnquotedValue(LinkedHashMap map) {
        return COMMA_JOINER.join(map.entrySet().stream()
                .map(e -> "'" + e.getKey() + "'," + e.getValue() + "")
                .collect(Collectors.toList()));
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy