/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.util;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.collection.MultiKey;
import com.espertech.esper.collection.NullIterator;
import com.espertech.esper.epl.expression.core.ExprEvaluator;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.util.*;
/**
* Utility for handling collection or array tasks.
*/
public class CollectionUtil {
public final static Iterator<EventBean> NULL_EVENT_ITERATOR = new NullIterator<EventBean>();
public final static Iterable<EventBean> NULL_EVENT_ITERABLE = new Iterable<EventBean>() {
public Iterator<EventBean> iterator() {
return NULL_EVENT_ITERATOR;
}
};
public final static SortedMap EMPTY_SORTED_MAP = new TreeMap();
public final static Set<MultiKey<EventBean>> EMPTY_ROW_SET = new HashSet<MultiKey<EventBean>>();
public final static EventBean[] EVENTBEANARRAY_EMPTY = new EventBean[0];
public final static Set<EventBean> SINGLE_NULL_ROW_EVENT_SET = new HashSet<EventBean>();
public final static String[] EMPTY_STRING_ARRAY = new String[0];
static {
SINGLE_NULL_ROW_EVENT_SET.add(null);
}
public final static StopCallback STOP_CALLBACK_NONE;
static {
STOP_CALLBACK_NONE = new StopCallback() {
public void stop() {
// no action
}
};
}
public static Comparator<Object> getComparator(ExprEvaluator[] sortCriteriaEvaluators, boolean isSortUsingCollator, boolean[] isDescendingValues) {
// determine string-type sorting
boolean hasStringTypes = false;
boolean[] stringTypes = new boolean[sortCriteriaEvaluators.length];
int count = 0;
for (ExprEvaluator node : sortCriteriaEvaluators) {
if (node.getType() == String.class) {
hasStringTypes = true;
stringTypes[count] = true;
}
count++;
}
if (sortCriteriaEvaluators.length > 1) {
if ((!hasStringTypes) || (!isSortUsingCollator)) {
MultiKeyComparator comparatorMK = new MultiKeyComparator(isDescendingValues);
return new MultiKeyCastingComparator(comparatorMK);
} else {
MultiKeyCollatingComparator comparatorMk = new MultiKeyCollatingComparator(isDescendingValues, stringTypes);
return new MultiKeyCastingComparator(comparatorMk);
}
} else {
if ((!hasStringTypes) || (!isSortUsingCollator)) {
return new ObjectComparator(isDescendingValues[0]);
} else {
return new ObjectCollatingComparator(isDescendingValues[0]);
}
}
}
public static String toString(Collection<Integer> stack, String delimiterChars) {
if (stack.isEmpty()) {
return "";
}
if (stack.size() == 1) {
return Integer.toString(stack.iterator().next());
}
StringWriter writer = new StringWriter();
String delimiter = "";
for (Integer item : stack) {
writer.append(delimiter);
writer.append(Integer.toString(item));
delimiter = delimiterChars;
}
return writer.toString();
}
public static Object arrayExpandAddElements(Object array, Object[] elementsToAdd) {
Class cl = array.getClass();
if (!cl.isArray()) return null;
int length = Array.getLength(array);
int newLength = length + elementsToAdd.length;
Class componentType = array.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(array, 0, newArray, 0, length);
for (int i = 0; i < elementsToAdd.length; i++) {
Array.set(newArray, length + i, elementsToAdd[i]);
}
return newArray;
}
public static Object arrayShrinkRemoveSingle(Object array, int index) {
Class cl = array.getClass();
if (!cl.isArray()) return null;
int length = Array.getLength(array);
int newLength = length - 1;
Class componentType = array.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, newLength);
if (index > 0) {
System.arraycopy(array, 0, newArray, 0, index);
}
if (index < newLength) {
System.arraycopy(array, index + 1, newArray, index, newLength - index);
}
return newArray;
}
public static Object arrayExpandAddElements(Object array, Collection elementsToAdd) {
Class cl = array.getClass();
if (!cl.isArray()) return null;
int length = Array.getLength(array);
int newLength = length + elementsToAdd.size();
Class componentType = array.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(array, 0, newArray, 0, length);
int count = 0;
for (Object element : elementsToAdd) {
Array.set(newArray, length + count, element);
count++;
}
return newArray;
}
public static Object arrayExpandAddSingle(Object array, Object elementsToAdd) {
Class cl = array.getClass();
if (!cl.isArray()) return null;
int length = Array.getLength(array);
int newLength = length + 1;
Class componentType = array.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(array, 0, newArray, 0, length);
Array.set(newArray, length, elementsToAdd);
return newArray;
}
public static int[] addValue(int[] ints, int i) {
int[] copy = new int[ints.length + 1];
System.arraycopy(ints, 0, copy, 0, ints.length);
copy[ints.length] = i;
return copy;
}
public static int findItem(String[] items, String item) {
for (int i = 0; i < items.length; i++) {
if (items[i].equals(item)) {
return i;
}
}
return -1;
}
/**
* Returns an array of integer values from the set of integer values
*
* @param set to return array for
* @return array
*/
public static int[] intArray(Collection<Integer> set) {
if (set == null) {
return new int[0];
}
int[] result = new int[set.size()];
int index = 0;
for (Integer value : set) {
result[index++] = value;
}
return result;
}
public static String[] copySortArray(String[] values) {
if (values == null) {
return null;
}
String[] copy = new String[values.length];
System.arraycopy(values, 0, copy, 0, values.length);
Arrays.sort(copy);
return copy;
}
public static boolean sortCompare(String[] valuesOne, String[] valuesTwo) {
if (valuesOne == null) {
return valuesTwo == null;
}
if (valuesTwo == null) {
return false;
}
String[] copyOne = copySortArray(valuesOne);
String[] copyTwo = copySortArray(valuesTwo);
return Arrays.equals(copyOne, copyTwo);
}
/**
* Returns a list of the elements invoking toString on non-null elements.
*
* @param collection to render
* @param <T> type
* @return comma-separate list of values (no escape)
*/
public static <T> String toString(Collection<T> collection) {
if (collection == null) {
return "null";
}
if (collection.isEmpty()) {
return "";
}
StringBuilder buf = new StringBuilder();
String delimiter = "";
for (T t : collection) {
if (t == null) {
continue;
}
buf.append(delimiter);
buf.append(t);
delimiter = ", ";
}
return buf.toString();
}
public static boolean compare(String[] otherIndexProps, String[] thisIndexProps) {
if (otherIndexProps != null && thisIndexProps != null) {
return Arrays.equals(otherIndexProps, thisIndexProps);
}
return otherIndexProps == null && thisIndexProps == null;
}
public static boolean isAllNullArray(Object array) {
if (array == null) {
throw new NullPointerException();
}
if (!array.getClass().isArray()) {
throw new IllegalArgumentException("Expected array but received " + array.getClass());
}
for (int i = 0; i < Array.getLength(array); i++) {
if (Array.get(array, i) != null) {
return false;
}
}
return true;
}
public static String toStringArray(Object[] received) {
StringBuilder buf = new StringBuilder();
String delimiter = "";
buf.append("[");
for (Object t : received) {
buf.append(delimiter);
if (t == null) {
buf.append("null");
} else if (t instanceof Object[]) {
buf.append(toStringArray((Object[]) t));
} else {
buf.append(t);
}
delimiter = ", ";
}
buf.append("]");
return buf.toString();
}
public static Map<String, Object> populateNameValueMap(Object... values) {
Map<String, Object> result = new LinkedHashMap<String, Object>();
int count = values.length / 2;
if (values.length != count * 2) {
throw new IllegalArgumentException("Expected an event number of name-value pairs");
}
for (int i = 0; i < count; i++) {
int index = i * 2;
Object keyValue = values[index];
if (!(keyValue instanceof String)) {
throw new IllegalArgumentException("Expected string-type key value at index " + index + " but found " + keyValue);
}
String key = (String) keyValue;
Object value = values[index + 1];
if (result.containsKey(key)) {
throw new IllegalArgumentException("Found two or more values for key '" + key + "'");
}
result.put(key, value);
}
return result;
}
public static Object addArrays(Object first, Object second) {
if (first != null && !first.getClass().isArray()) {
throw new IllegalArgumentException("Parameter is not an array: " + first);
}
if (second != null && !second.getClass().isArray()) {
throw new IllegalArgumentException("Parameter is not an array: " + second);
}
if (first == null) {
return second;
}
if (second == null) {
return first;
}
int firstLength = Array.getLength(first);
int secondLength = Array.getLength(second);
int total = firstLength + secondLength;
Object dest = Array.newInstance(first.getClass().getComponentType(), total);
System.arraycopy(first, 0, dest, 0, firstLength);
System.arraycopy(second, 0, dest, firstLength, secondLength);
return dest;
}
public static EventBean[] addArrayWithSetSemantics(EventBean[] arrayOne, EventBean[] arrayTwo) {
if (arrayOne.length == 0) {
return arrayTwo;
}
if (arrayTwo.length == 0) {
return arrayOne;
}
if (arrayOne.length == 1 && arrayTwo.length == 1) {
if (arrayOne[0].equals(arrayTwo[0])) {
return arrayOne;
} else {
return new EventBean[]{arrayOne[0], arrayOne[0]};
}
}
if (arrayOne.length == 1 && arrayTwo.length > 1) {
if (searchArray(arrayTwo, arrayOne[0]) != -1) {
return arrayTwo;
}
}
if (arrayOne.length > 1 && arrayTwo.length == 1) {
if (searchArray(arrayOne, arrayTwo[0]) != -1) {
return arrayOne;
}
}
Set<EventBean> set = new HashSet<EventBean>();
for (EventBean event : arrayOne) {
set.add(event);
}
for (EventBean event : arrayTwo) {
set.add(event);
}
return set.toArray(new EventBean[set.size()]);
}
public static String[] toArray(Collection<String> strings) {
if (strings.isEmpty()) {
return EMPTY_STRING_ARRAY;
}
return strings.toArray(new String[strings.size()]);
}
public static <T> int searchArray(T[] array, T item) {
for (int i = 0; i < array.length; i++) {
if (array[i].equals(item)) {
return i;
}
}
return -1;
}
public static boolean removeEventByKeyLazyListMap(Object key, EventBean bean, Map<Object, Object> eventMap) {
Object listOfBeans = eventMap.get(key);
if (listOfBeans == null) {
return false;
}
if (listOfBeans instanceof List) {
List<EventBean> events = (List<EventBean>) listOfBeans;
boolean result = events.remove(bean);
if (events.isEmpty()) {
eventMap.remove(key);
}
return result;
} else if (listOfBeans != null && listOfBeans.equals(bean)) {
eventMap.remove(key);
return true;
}
return false;
}
public static void addEventByKeyLazyListMapBack(Object sortKey, EventBean eventBean, Map<Object, Object> eventMap) {
Object existing = eventMap.get(sortKey);
if (existing == null) {
eventMap.put(sortKey, eventBean);
} else {
if (existing instanceof List) {
List<EventBean> existingList = (List<EventBean>) existing;
existingList.add(eventBean);
} else {
List<EventBean> existingList = new LinkedList<EventBean>();
existingList.add((EventBean) existing);
existingList.add(eventBean);
eventMap.put(sortKey, existingList);
}
}
}
public static void addEventByKeyLazyListMapFront(Object key, EventBean bean, Map<Object, Object> eventMap) {
Object current = eventMap.get(key);
if (current != null) {
if (current instanceof List) {
List<EventBean> events = (List<EventBean>) current;
events.add(0, bean); // add to front, newest are listed first
} else {
EventBean theEvent = (EventBean) current;
List<EventBean> events = new LinkedList<EventBean>();
events.add(bean);
events.add(theEvent);
eventMap.put(key, events);
}
} else {
eventMap.put(key, bean);
}
}
public static boolean isAnySet(boolean[] array) {
for (int i = 0; i < array.length; i++) {
if (array[i]) {
return true;
}
}
return false;
}
public static <K, V> Map<K, V> twoEntryMap(K k1, V v1, K k2, V v2) {
Map<K, V> map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
return map;
}
}