From 76856191e96ef3c5e65302ba662239fa77b42ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Ant=C3=B4nio=20Siqueira?= Date: Wed, 11 Jan 2023 15:54:09 -0300 Subject: [PATCH] KOGITO-8447:[Dashbuilder]Support MEDIAN aggregation function (#1406) * KOGITO-8447:[Dashbuilder]Support MEDIAN aggregation function * Fixing copyright header --- .../dataset/group/AggregateFunctionType.java | 5 +- .../AggregateFunctionManagerImpl.java | 1 + .../engine/function/MedianFunction.java | 75 +++++++++++++++++++ .../function/AggregateFunctionsTest.java | 16 ++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/MedianFunction.java diff --git a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/group/AggregateFunctionType.java b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/group/AggregateFunctionType.java index fc3f4f6135c..2b12efcce19 100644 --- a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/group/AggregateFunctionType.java +++ b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/group/AggregateFunctionType.java @@ -29,10 +29,11 @@ public enum AggregateFunctionType { AVERAGE, SUM, MIN, - MAX; + MAX, + MEDIAN; private static AggregateFunctionType[] _typeArray = values(); - private static List _numericOnly = Arrays.asList(AVERAGE, SUM, MAX, MIN); + private static List _numericOnly = Arrays.asList(AVERAGE, MEDIAN, SUM, MAX, MIN); public int getIndex() { for (int i = 0; i < _typeArray.length; i++) { diff --git a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/AggregateFunctionManagerImpl.java b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/AggregateFunctionManagerImpl.java index 424fe7cbd5d..99304f972f2 100755 --- a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/AggregateFunctionManagerImpl.java +++ b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/AggregateFunctionManagerImpl.java @@ -36,6 +36,7 @@ public AggregateFunctionManagerImpl() { registerFunction(new DistinctFunction()); registerFunction(new SumFunction()); registerFunction(new AverageFunction()); + registerFunction(new MedianFunction()); registerFunction(new MaxFunction()); registerFunction(new MinFunction()); } diff --git a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/MedianFunction.java b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/MedianFunction.java new file mode 100644 index 00000000000..db22583660e --- /dev/null +++ b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/main/java/org/dashbuilder/dataset/engine/function/MedianFunction.java @@ -0,0 +1,75 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.dashbuilder.dataset.engine.function; + +import java.util.List; +import java.util.stream.Collectors; + +import org.dashbuilder.dataset.group.AggregateFunctionType; + +/** + * It calculates the average value of a set of numbers. + */ +public class MedianFunction extends AbstractFunction { + + public MedianFunction() { + super(); + } + + public AggregateFunctionType getType() { + return AggregateFunctionType.MEDIAN; + } + + public Object aggregate(List values) { + if (values == null || values.isEmpty()) { + return 0d; + } + + var n = values.size(); + + if (n == 1) { + return ((Number) values.get(0)).doubleValue(); + } + + var sortedValues = values.stream().mapToDouble(v -> ((Number) v).doubleValue()).sorted().toArray(); + + if (n % 2 == 1) { + return sortedValues[n / 2]; + } + var middle = n / 2; + var ii = n == 2 ? 0 : middle - 1; + var is = n == 2 ? 1 : middle + 1; + var v = (sortedValues[ii] + sortedValues[is]) / 2d; + return round(v, precission); + } + + public Object aggregate(List values, List rows) { + if (rows == null) { + return aggregate(values); + } + if (rows.isEmpty()) { + return 0d; + } + if (values == null || values.isEmpty()) { + return 0d; + } + var _values = rows.stream() + .map(values::get) + .collect(Collectors.toList()); + return this.aggregate(_values); + } + +} diff --git a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/test/java/org/dashbuilder/dataset/engine/function/AggregateFunctionsTest.java b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/test/java/org/dashbuilder/dataset/engine/function/AggregateFunctionsTest.java index 85336a2b606..6dc1faf2f2a 100644 --- a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/test/java/org/dashbuilder/dataset/engine/function/AggregateFunctionsTest.java +++ b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-shared/src/test/java/org/dashbuilder/dataset/engine/function/AggregateFunctionsTest.java @@ -336,4 +336,20 @@ public void testAvgFunctionEmpty() { Object result = function.aggregate(EMPTY_LIST); assertEquals(result, 0d); } + + @Test + public void testMedianFunction() { + var function = new MedianFunction(); + var values = List.of(1, 2, 3); + var result = function.aggregate(values); + assertEquals(result, 2d); + + values = List.of(1, 4); + result = function.aggregate(values); + assertEquals(result, 2.5d); + + values = List.of(1); + result = function.aggregate(values); + assertEquals(result, 1.0d); + } }