/* *************************************************************************************** * 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.event; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventPropertyGetter; import com.espertech.esper.client.EventType; import com.espertech.esper.client.PropertyAccessException; import com.espertech.esper.event.arr.ObjectArrayEventPropertyGetter; import com.espertech.esper.event.bean.BeanEventPropertyGetter; import com.espertech.esper.event.bean.BeanEventType; import com.espertech.esper.event.map.MapEventPropertyGetter; import com.espertech.esper.event.map.MapEventType; import com.espertech.esper.event.property.IndexedProperty; import com.espertech.esper.event.property.MappedProperty; import com.espertech.esper.event.property.Property; import com.espertech.esper.event.property.PropertyParser; import com.espertech.esper.util.JavaClassHelper; import java.lang.reflect.Array; import java.util.HashSet; import java.util.Map; import java.util.Set; public class BaseNestableEventUtil { public static Map<String, Object> checkedCastUnderlyingMap(EventBean theEvent) throws PropertyAccessException { return (Map<String, Object>) theEvent.getUnderlying(); } public static Object[] checkedCastUnderlyingObjectArray(EventBean theEvent) throws PropertyAccessException { return (Object[]) theEvent.getUnderlying(); } public static Object handleNestedValueArrayWithMap(Object value, int index, MapEventPropertyGetter getter) { if (!value.getClass().isArray()) { return null; } if (Array.getLength(value) <= index) { return null; } Object valueMap = Array.get(value, index); if (!(valueMap instanceof Map)) { if (valueMap instanceof EventBean) { return getter.get((EventBean) valueMap); } return null; } return getter.getMap((Map<String, Object>) valueMap); } public static boolean handleNestedValueArrayWithMapExists(Object value, int index, MapEventPropertyGetter getter) { if (!value.getClass().isArray()) { return false; } if (Array.getLength(value) <= index) { return false; } Object valueMap = Array.get(value, index); if (!(valueMap instanceof Map)) { if (valueMap instanceof EventBean) { return getter.isExistsProperty((EventBean) valueMap); } return false; } return getter.isMapExistsProperty((Map<String, Object>) valueMap); } public static Object handleNestedValueArrayWithMapFragment(Object value, int index, MapEventPropertyGetter getter, EventAdapterService eventAdapterService, EventType fragmentType) { if (!value.getClass().isArray()) { return null; } if (Array.getLength(value) <= index) { return null; } Object valueMap = Array.get(value, index); if (!(valueMap instanceof Map)) { if (value instanceof EventBean) { return getter.getFragment((EventBean) value); } return null; } // If the map does not contain the key, this is allowed and represented as null EventBean eventBean = eventAdapterService.adapterForTypedMap((Map<String, Object>) valueMap, fragmentType); return getter.getFragment(eventBean); } public static Object handleNestedValueArrayWithObjectArray(Object value, int index, ObjectArrayEventPropertyGetter getter) { if (!value.getClass().isArray()) { return null; } if (Array.getLength(value) <= index) { return null; } Object valueArray = Array.get(value, index); if (!(valueArray instanceof Object[])) { if (valueArray instanceof EventBean) { return getter.get((EventBean) valueArray); } return null; } return getter.getObjectArray((Object[]) valueArray); } public static boolean handleNestedValueArrayWithObjectArrayExists(Object value, int index, ObjectArrayEventPropertyGetter getter) { if (!value.getClass().isArray()) { return false; } if (Array.getLength(value) <= index) { return false; } Object valueArray = Array.get(value, index); if (!(valueArray instanceof Object[])) { if (valueArray instanceof EventBean) { return getter.isExistsProperty((EventBean) valueArray); } return false; } return getter.isObjectArrayExistsProperty((Object[]) valueArray); } public static Object handleNestedValueArrayWithObjectArrayFragment(Object value, int index, ObjectArrayEventPropertyGetter getter, EventType fragmentType, EventAdapterService eventAdapterService) { if (!value.getClass().isArray()) { return null; } if (Array.getLength(value) <= index) { return null; } Object valueArray = Array.get(value, index); if (!(valueArray instanceof Object[])) { if (value instanceof EventBean) { return getter.getFragment((EventBean) value); } return null; } // If the map does not contain the key, this is allowed and represented as null EventBean eventBean = eventAdapterService.adapterForTypedObjectArray((Object[]) valueArray, fragmentType); return getter.getFragment(eventBean); } public static Object handleCreateFragmentMap(Object value, EventType fragmentEventType, EventAdapterService eventAdapterService) { if (!(value instanceof Map)) { if (value instanceof EventBean) { return value; } return null; } Map subEvent = (Map) value; return eventAdapterService.adapterForTypedMap(subEvent, fragmentEventType); } public static Object handleCreateFragmentObjectArray(Object value, EventType fragmentEventType, EventAdapterService eventAdapterService) { if (!(value instanceof Object[])) { if (value instanceof EventBean) { return value; } return null; } Object[] subEvent = (Object[]) value; return eventAdapterService.adapterForTypedObjectArray(subEvent, fragmentEventType); } public static Object getMappedPropertyValue(Object value, String key) { if (value == null) { return null; } if (!(value instanceof Map)) { return null; } Map innerMap = (Map) value; return innerMap.get(key); } public static boolean getMappedPropertyExists(Object value, String key) { if (value == null) { return false; } if (!(value instanceof Map)) { return false; } Map innerMap = (Map) value; return innerMap.containsKey(key); } public static MapIndexedPropPair getIndexedAndMappedProps(String[] properties) { Set<String> mapPropertiesToCopy = new HashSet<String>(); Set<String> arrayPropertiesToCopy = new HashSet<String>(); for (int i = 0; i < properties.length; i++) { Property prop = PropertyParser.parseAndWalkLaxToSimple(properties[i]); if (prop instanceof MappedProperty) { MappedProperty mappedProperty = (MappedProperty) prop; mapPropertiesToCopy.add(mappedProperty.getPropertyNameAtomic()); } if (prop instanceof IndexedProperty) { IndexedProperty indexedProperty = (IndexedProperty) prop; arrayPropertiesToCopy.add(indexedProperty.getPropertyNameAtomic()); } } return new MapIndexedPropPair(mapPropertiesToCopy, arrayPropertiesToCopy); } public static Object getIndexedValue(Object value, int index) { if (value == null) { return null; } if (!value.getClass().isArray()) { return null; } if (index >= Array.getLength(value)) { return null; } return Array.get(value, index); } public static boolean isExistsIndexedValue(Object value, int index) { if (value == null) { return false; } if (!value.getClass().isArray()) { return false; } if (index >= Array.getLength(value)) { return false; } return true; } public static EventBean getFragmentNonPojo(EventAdapterService eventAdapterService, Object fragmentUnderlying, EventType fragmentEventType) { if (fragmentUnderlying == null) { return null; } if (fragmentEventType instanceof MapEventType) { return eventAdapterService.adapterForTypedMap((Map<String, Object>) fragmentUnderlying, fragmentEventType); } return eventAdapterService.adapterForTypedObjectArray((Object[]) fragmentUnderlying, fragmentEventType); } public static Object getFragmentArray(EventAdapterService eventAdapterService, Object value, EventType fragmentEventType) { if (value instanceof Object[]) { Object[] subEvents = (Object[]) value; int countNull = 0; for (Object subEvent : subEvents) { if (subEvent != null) { countNull++; } } EventBean[] outEvents = new EventBean[countNull]; int count = 0; for (Object item : subEvents) { if (item != null) { outEvents[count++] = BaseNestableEventUtil.getFragmentNonPojo(eventAdapterService, item, fragmentEventType); } } return outEvents; } if (!(value instanceof Map[])) { return null; } Map[] mapTypedSubEvents = (Map[]) value; int countNull = 0; for (Map map : mapTypedSubEvents) { if (map != null) { countNull++; } } EventBean[] mapEvents = new EventBean[countNull]; int count = 0; for (Map map : mapTypedSubEvents) { if (map != null) { mapEvents[count++] = eventAdapterService.adapterForTypedMap(map, fragmentEventType); } } return mapEvents; } public static Object getBeanArrayValue(BeanEventPropertyGetter nestedGetter, Object value, int index) { if (value == null) { return null; } if (!value.getClass().isArray()) { return null; } if (Array.getLength(value) <= index) { return null; } Object arrayItem = Array.get(value, index); if (arrayItem == null) { return null; } return nestedGetter.getBeanProp(arrayItem); } public static Object getFragmentPojo(Object result, BeanEventType eventType, EventAdapterService eventAdapterService) { if (result == null) { return null; } if (result instanceof EventBean[]) { return result; } if (result instanceof EventBean) { return result; } if (result.getClass().isArray()) { int len = Array.getLength(result); EventBean[] events = new EventBean[len]; for (int i = 0; i < events.length; i++) { events[i] = eventAdapterService.adapterForTypedBean(Array.get(result, i), eventType); } return events; } return eventAdapterService.adapterForTypedBean(result, eventType); } public static Object getArrayPropertyValue(EventBean[] wrapper, int index, EventPropertyGetter nestedGetter) { if (wrapper == null) { return null; } if (wrapper.length <= index) { return null; } EventBean innerArrayEvent = wrapper[index]; return nestedGetter.get(innerArrayEvent); } public static Object getArrayPropertyFragment(EventBean[] wrapper, int index, EventPropertyGetter nestedGetter) { if (wrapper == null) { return null; } if (wrapper.length <= index) { return null; } EventBean innerArrayEvent = wrapper[index]; return nestedGetter.getFragment(innerArrayEvent); } public static Object getArrayPropertyUnderlying(EventBean[] wrapper, int index) { if (wrapper == null) { return null; } if (wrapper.length <= index) { return null; } return wrapper[index].getUnderlying(); } public static Object getArrayPropertyBean(EventBean[] wrapper, int index) { if (wrapper == null) { return null; } if (wrapper.length <= index) { return null; } return wrapper[index]; } public static Object getArrayPropertyAsUnderlyingsArray(Class underlyingType, EventBean[] wrapper) { if (wrapper != null) { Object array = Array.newInstance(underlyingType, wrapper.length); for (int i = 0; i < wrapper.length; i++) { Array.set(array, i, wrapper[i].getUnderlying()); } return array; } return null; } public static String comparePropType(String propName, Object setOneType, Object setTwoType, boolean setTwoTypeFound, String otherName) { // allow null for nested event types if ((setOneType instanceof String || setOneType instanceof EventType) && setTwoType == null) { return null; } if ((setTwoType instanceof String || setTwoType instanceof EventType) && setOneType == null) { return null; } if (!setTwoTypeFound) { return "The property '" + propName + "' is not provided but required"; } if (setTwoType == null) { return null; } if (setOneType == null) { return "Type by name '" + otherName + "' in property '" + propName + "' incompatible with null-type or property name not found in target"; } if ((setTwoType instanceof Class) && (setOneType instanceof Class)) { Class boxedOther = JavaClassHelper.getBoxedType((Class) setTwoType); Class boxedThis = JavaClassHelper.getBoxedType((Class) setOneType); if (!boxedOther.equals(boxedThis)) { if (!JavaClassHelper.isSubclassOrImplementsInterface(boxedOther, boxedThis)) { return "Type by name '" + otherName + "' in property '" + propName + "' expected " + boxedThis + " but receives " + boxedOther; } } } else if ((setTwoType instanceof BeanEventType) && (setOneType instanceof Class)) { Class boxedOther = JavaClassHelper.getBoxedType(((BeanEventType) setTwoType).getUnderlyingType()); Class boxedThis = JavaClassHelper.getBoxedType((Class) setOneType); if (!boxedOther.equals(boxedThis)) { return "Type by name '" + otherName + "' in property '" + propName + "' expected " + boxedThis + " but receives " + boxedOther; } } else if (setTwoType instanceof EventType[] && ((EventType[]) setTwoType)[0] instanceof BeanEventType && setOneType instanceof Class && ((Class) setOneType).isArray()) { Class boxedOther = JavaClassHelper.getBoxedType((((EventType[]) setTwoType)[0]).getUnderlyingType()); Class boxedThis = JavaClassHelper.getBoxedType(((Class) setOneType).getComponentType()); if (!boxedOther.equals(boxedThis)) { return "Type by name '" + otherName + "' in property '" + propName + "' expected " + boxedThis + " but receives " + boxedOther; } } else if ((setTwoType instanceof Map) && (setOneType instanceof Map)) { String messageIsDeepEquals = BaseNestableEventType.isDeepEqualsProperties(propName, (Map<String, Object>) setOneType, (Map<String, Object>) setTwoType); if (messageIsDeepEquals != null) { return messageIsDeepEquals; } } else if ((setTwoType instanceof EventType) && (setOneType instanceof EventType)) { boolean mismatch; if (setTwoType instanceof EventTypeSPI && setOneType instanceof EventTypeSPI) { mismatch = !((EventTypeSPI) setOneType).equalsCompareType((EventTypeSPI) setTwoType); } else { mismatch = !setOneType.equals(setTwoType); } if (mismatch) { EventType setOneEventType = (EventType) setOneType; EventType setTwoEventType = (EventType) setTwoType; return "Type by name '" + otherName + "' in property '" + propName + "' expected event type '" + setOneEventType.getName() + "' but receives event type '" + setTwoEventType.getName() + "'"; } } else if ((setTwoType instanceof String) && (setOneType instanceof EventType)) { EventType setOneEventType = (EventType) setOneType; String setTwoEventType = (String) setTwoType; if (!EventTypeUtility.isTypeOrSubTypeOf(setTwoEventType, setOneEventType)) { return "Type by name '" + otherName + "' in property '" + propName + "' expected event type '" + setOneEventType.getName() + "' but receives event type '" + setTwoEventType + "'"; } } else if ((setTwoType instanceof EventType) && (setOneType instanceof String)) { EventType setTwoEventType = (EventType) setTwoType; String setOneEventType = (String) setOneType; if (!EventTypeUtility.isTypeOrSubTypeOf(setOneEventType, setTwoEventType)) { return "Type by name '" + otherName + "' in property '" + propName + "' expected event type '" + setOneEventType + "' but receives event type '" + setTwoEventType.getName() + "'"; } } else if ((setTwoType instanceof String) && (setOneType instanceof String)) { if (!setTwoType.equals(setOneType)) { String setOneEventType = (String) setOneType; String setTwoEventType = (String) setTwoType; return "Type by name '" + otherName + "' in property '" + propName + "' expected event type '" + setOneEventType + "' but receives event type '" + setTwoEventType + "'"; } } else if ((setTwoType instanceof EventType[]) && (setOneType instanceof String)) { EventType[] setTwoTypeArr = (EventType[]) setTwoType; EventType setTwoFragmentType = setTwoTypeArr[0]; String setOneTypeString = (String) setOneType; if (!(setOneTypeString.endsWith("[]"))) { return "Type by name '" + otherName + "' in property '" + propName + "' expected event type '" + setOneType + "' but receives event type '" + setTwoFragmentType.getName() + "[]'"; } String setOneTypeNoArray = setOneTypeString.replaceAll("\\[\\]", ""); if (!(setTwoFragmentType.getName().equals(setOneTypeNoArray))) { return "Type by name '" + otherName + "' in property '" + propName + "' expected event type '" + setOneTypeNoArray + "[]' but receives event type '" + setTwoFragmentType.getName() + "'"; } } else { String typeOne = getTypeName(setOneType); String typeTwo = getTypeName(setTwoType); if (typeOne.equals(typeTwo)) { return null; } return "Type by name '" + otherName + "' in property '" + propName + "' expected " + typeOne + " but receives " + typeTwo; } return null; } private static String getTypeName(Object type) { if (type == null) { return "null"; } if (type instanceof Class) { return ((Class) type).getName(); } if (type instanceof EventType) { return "event type '" + ((EventType) type).getName() + "'"; } if (type instanceof String) { Class boxedType = JavaClassHelper.getBoxedType(JavaClassHelper.getPrimitiveClassForName((String) type)); if (boxedType != null) { return boxedType.getName(); } return (String) type; } return type.getClass().getName(); } public static class MapIndexedPropPair { private final Set<String> mapProperties; private final Set<String> arrayProperties; public MapIndexedPropPair(Set<String> mapProperties, Set<String> arrayProperties) { this.mapProperties = mapProperties; this.arrayProperties = arrayProperties; } public Set<String> getMapProperties() { return mapProperties; } public Set<String> getArrayProperties() { return arrayProperties; } } }