/*
* Copyright (C) 2015 SoftIndex LLC.
*
* 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 io.datakernel.jmx;
import java.util.List;
import java.util.Objects;
import static io.datakernel.jmx.Utils.filterNulls;
public final class JmxReducers {
private JmxReducers() {}
public static final class JmxReducerDistinct implements JmxReducer<Object> {
@Override
public Object reduce(List<?> input) {
if (input.size() == 0) {
return null;
}
Object firstValue = input.get(0);
for (int i = 1; i < input.size(); i++) {
Object currentValue = input.get(i);
if (!Objects.equals(firstValue, currentValue)) {
return null;
}
}
return firstValue;
}
}
public static final class JmxReducerSum implements JmxReducer<Number> {
@Override
public Number reduce(List<? extends Number> input) {
List<? extends Number> inputListWithoutNulls = filterNulls(input);
if (inputListWithoutNulls.size() == 0) {
return null;
}
Number first = inputListWithoutNulls.get(0);
Class<?> numberClass = first.getClass();
if (isFloatingPointNumber(numberClass)) {
double floatingPointSum = first.doubleValue();
for (int i = 1; i < inputListWithoutNulls.size(); i++) {
floatingPointSum += inputListWithoutNulls.get(i).doubleValue();
}
return convert(floatingPointSum, numberClass);
} else if (isIntegerNumber(numberClass)) {
long integerSum = first.longValue();
for (int i = 1; i < inputListWithoutNulls.size(); i++) {
integerSum += inputListWithoutNulls.get(i).longValue();
}
return convert(integerSum, numberClass);
} else {
throw new IllegalArgumentException(
"Cannot calculate sum of objects of type: " + first.getClass().getName());
}
}
}
public static final class JmxReducerMin implements JmxReducer<Number> {
@Override
public Number reduce(List<? extends Number> input) {
List<? extends Number> inputListWithoutNulls = filterNulls(input);
if (inputListWithoutNulls.size() == 0) {
return null;
}
Number first = inputListWithoutNulls.get(0);
Class<?> numberClass = first.getClass();
if (isFloatingPointNumber(numberClass)) {
double floatingPointMin = first.doubleValue();
for (int i = 1; i < inputListWithoutNulls.size(); i++) {
double currentValue = inputListWithoutNulls.get(i).doubleValue();
if (currentValue < floatingPointMin) {
floatingPointMin = currentValue;
}
}
return convert(floatingPointMin, numberClass);
} else if (isIntegerNumber(numberClass)) {
long integerMin = first.longValue();
for (int i = 1; i < inputListWithoutNulls.size(); i++) {
long currentValue = inputListWithoutNulls.get(i).longValue();
if (currentValue < integerMin) {
integerMin = currentValue;
}
}
return convert(integerMin, numberClass);
} else {
throw new IllegalArgumentException(
"Cannot calculate min of objects of type: " + first.getClass().getName());
}
}
}
public static final class JmxReducerMax implements JmxReducer<Number> {
@Override
public Number reduce(List<? extends Number> input) {
List<? extends Number> inputListWithoutNulls = filterNulls(input);
if (inputListWithoutNulls.size() == 0) {
return null;
}
Number first = inputListWithoutNulls.get(0);
Class<?> numberClass = first.getClass();
if (isFloatingPointNumber(numberClass)) {
double floatingPointMax = first.doubleValue();
for (int i = 1; i < inputListWithoutNulls.size(); i++) {
double currentValue = inputListWithoutNulls.get(i).doubleValue();
if (currentValue > floatingPointMax) {
floatingPointMax = currentValue;
}
}
return convert(floatingPointMax, numberClass);
} else if (isIntegerNumber(numberClass)) {
long integerMax = first.longValue();
for (int i = 1; i < inputListWithoutNulls.size(); i++) {
long currentValue = inputListWithoutNulls.get(i).longValue();
if (currentValue > integerMax) {
integerMax = currentValue;
}
}
return convert(integerMax, numberClass);
} else {
throw new IllegalArgumentException(
"Cannot calculate max of objects of type: " + first.getClass().getName());
}
}
}
private static boolean isFloatingPointNumber(Class<?> numberClass) {
return Float.class.isAssignableFrom(numberClass) || Double.class.isAssignableFrom(numberClass);
}
private static boolean isIntegerNumber(Class<?> numberClass) {
return Byte.class.isAssignableFrom(numberClass) || Short.class.isAssignableFrom(numberClass)
|| Integer.class.isAssignableFrom(numberClass) || Long.class.isAssignableFrom(numberClass);
}
private static Number convert(Number number, Class<?> targetClass) {
if (Byte.class.isAssignableFrom(targetClass)) {
return number.byteValue();
} else if (Short.class.isAssignableFrom(targetClass)) {
return number.shortValue();
} else if (Integer.class.isAssignableFrom(targetClass)) {
return number.intValue();
} else if (Long.class.isAssignableFrom(targetClass)) {
return number.longValue();
} else if (Float.class.isAssignableFrom(targetClass)) {
return number.floatValue();
} else if (Double.class.isAssignableFrom(targetClass)) {
return number.doubleValue();
} else {
throw new IllegalArgumentException("target class is not a number class");
}
}
}