Github user cestella commented on a diff in the pull request:
https://github.com/apache/metron/pull/823#discussion_r153913510
--- Diff:
metron-stellar/stellar-common/src/main/java/org/apache/metron/stellar/dsl/functions/OrdinalFunctions.java
---
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.metron.stellar.dsl.functions;
+
+import org.apache.metron.stellar.dsl.BaseStellarFunction;
+import org.apache.metron.stellar.dsl.Stellar;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class OrdinalFunctions {
+
+ /**
+ * Stellar Function: MAX
+ * <p>
+ * Return the maximum value of a list of input values in a Stellar list
+ */
+ @Stellar(name = "MAX"
+ , description = "Returns the maximum value of a list of input
values"
+ , params = {"list_of_values - Stellar list of values to
evaluate. The list may only contain 1 type of object (only strings or only
numbers)" +
+ " and the objects must be comparable / ordinal"}
+ , returns = "The highest value in the list, null if the list
is empty or the input values could not be ordered")
+ public static class Max extends BaseStellarFunction {
+
+ @Override
+ public Object apply(List<Object> args) {
+ if (args.size() < 1 || args.get(0) == null) {
+ throw new IllegalStateException("MAX function requires at
least a Stellar list of values");
+ }
+ List list = (List<Object>) args.get(0);
+ return orderList(list, true);
+ }
+ }
+
+ /**
+ * Stellar Function: MIN
+ * <p>
+ * Return the minimum value of a list of input values in a Stellar list
+ */
+ @Stellar(name = "MIN"
+ , description = "Returns the minimum value of a list of input
values"
+ , params = {"list_of_values - Stellar list of values to
evaluate. The list may only contain 1 type of object (only strings or only
numbers)" +
+ " and the objects must be comparable / ordinal"}
+ , returns = "The lowest value in the list, null if the list is
empty or the input values could not be ordered")
+ public static class Min extends BaseStellarFunction {
+ @Override
+ public Object apply(List<Object> args) {
+ if (args.size() < 1 || args.get(0) == null) {
+ throw new IllegalStateException("MIN function requires at
least a Stellar list of values");
+ }
+ List list = (List<Object>) args.get(0);
+ return orderList(list, false);
+ }
+ }
+
+ private static Object orderList(List<Object> list, Boolean max) {
+ if (list.isEmpty()) {
+ return null;
+ }
+ List filteredList = (List<Object>) list.stream().filter(index ->
!(index == null)).collect(Collectors.toList());
+ if (filteredList.isEmpty()) {
+ return null;
+ }
+ try {
+ if (max) {
+ Collections.sort(filteredList,Collections.reverseOrder());
--- End diff --
This bears answering. The only issue with Collections.min/max is that they
don't handle nulls, so you have to iterate over the list first (2 passes) and
also don't handle mutually comparable types that aren't exactly the same class
(e.g. a list of mixed numeric types). I submitted a
[PR](https://github.com/jasper-k/metron-apache/pull/1) against this PR to flesh
this out a bit.
---