/*
***************************************************************************************
* 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.epl.rettype;
import com.espertech.esper.client.EventType;
import com.espertech.esper.epl.expression.core.ExprEvaluatorEnumeration;
import com.espertech.esper.epl.expression.core.ExprNode;
import com.espertech.esper.epl.expression.core.ExprValidationException;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.util.JavaClassHelper;
import java.lang.reflect.Method;
import java.util.Collection;
/**
* Carries return type information related to the return values returned by expressions.
* <p>
* Use factory methods to initialize return type information according to the return values
* that your expression is going to provide.
* </p>
* <ol>
* <li>
* Use {@link EPTypeHelper#collectionOfEvents(com.espertech.esper.client.EventType)}
* to indicate that the expression returns a collection of events.
* </li>
* <li>
* Use {@link EPTypeHelper#singleEvent(com.espertech.esper.client.EventType)}
* to indicate that the expression returns a single event.
* </li>
* <li>
* Use {@link EPTypeHelper#collectionOfSingleValue(Class)}
* to indicate that the expression returns a collection of single values.
* A single value can be any object including null.
* </li>
* <li>
* Use {@link EPTypeHelper#array(Class)}
* to indicate that the expression returns an array of single values.
* A single value can be any object including null.
* </li>
* <li>
* Use {@link EPTypeHelper#singleValue(Class)}
* to indicate that the expression returns a single value.
* A single value can be any object including null.
* Such expression results cannot be used as input to enumeration methods, for example.
* </li>
* </ol>
*/
public class EPTypeHelper {
public static EventType getEventTypeSingleValued(EPType type) {
if (type instanceof EventEPType) {
return ((EventEPType) type).getType();
}
return null;
}
public static EventType getEventTypeMultiValued(EPType type) {
if (type instanceof EventMultiValuedEPType) {
return ((EventMultiValuedEPType) type).getComponent();
}
return null;
}
public static Class getClassMultiValued(EPType type) {
if (type instanceof ClassMultiValuedEPType) {
return ((ClassMultiValuedEPType) type).getComponent();
}
return null;
}
public static Class getClassSingleValued(EPType type) {
if (type instanceof ClassEPType) {
return ((ClassEPType) type).getType();
}
return null;
}
public static boolean isCarryEvent(EPType epType) {
return epType instanceof EventMultiValuedEPType || epType instanceof EventEPType;
}
public static EventType getEventType(EPType epType) {
if (epType instanceof EventMultiValuedEPType) {
return ((EventMultiValuedEPType) epType).getComponent();
}
if (epType instanceof EventEPType) {
return ((EventEPType) epType).getType();
}
return null;
}
/**
* Indicate that the expression return type is an array of a given component type.
*
* @param arrayComponentType array component type
* @return array of single value expression result type
*/
public static EPType array(Class arrayComponentType) {
if (arrayComponentType == null) {
throw new IllegalArgumentException("Invalid null array component type");
}
return new ClassMultiValuedEPType(JavaClassHelper.getArrayType(arrayComponentType), arrayComponentType);
}
/**
* Indicate that the expression return type is a single (non-enumerable) value of the given type.
* The expression can still return an array or collection or events however
* since the engine would not know the type of such objects and may not use runtime reflection
* it may not allow certain operations on expression results.
*
* @param singleValueType type of single value returned, or null to indicate that the expression always returns null
* @return single-value expression result type
*/
public static EPType singleValue(Class singleValueType) {
// null value allowed
if (singleValueType != null && singleValueType.isArray()) {
return new ClassMultiValuedEPType(singleValueType, singleValueType.getComponentType());
}
return new ClassEPType(singleValueType);
}
public static EPType nullValue() {
return NullEPType.INSTANCE;
}
/**
* Indicate that the expression return type is a collection of a given component type.
*
* @param collectionComponentType collection component type
* @return collection of single value expression result type
*/
public static EPType collectionOfSingleValue(Class collectionComponentType) {
if (collectionComponentType == null) {
throw new IllegalArgumentException("Invalid null collection component type");
}
return new ClassMultiValuedEPType(Collection.class, collectionComponentType);
}
/**
* Indicate that the expression return type is a collection of a given type of events.
*
* @param eventTypeOfCollectionEvents the event type of the events that are part of the collection
* @return collection of events expression result type
*/
public static EPType collectionOfEvents(EventType eventTypeOfCollectionEvents) {
if (eventTypeOfCollectionEvents == null) {
throw new IllegalArgumentException("Invalid null event type");
}
return new EventMultiValuedEPType(Collection.class, eventTypeOfCollectionEvents);
}
/**
* Indicate that the expression return type is single event of a given event type.
*
* @param eventTypeOfSingleEvent the event type of the event returned
* @return single-event expression result type
*/
public static EPType singleEvent(EventType eventTypeOfSingleEvent) {
if (eventTypeOfSingleEvent == null) {
throw new IllegalArgumentException("Invalid null event type");
}
return new EventEPType(eventTypeOfSingleEvent);
}
/**
* Interrogate the provided method and determine whether it returns
* single-value, array of single-value or collection of single-value and
* their component type.
*
* @param method the class methods
* @return expression return type
*/
public static EPType fromMethod(Method method) {
Class returnType = method.getReturnType();
if (JavaClassHelper.isImplementsInterface(returnType, Collection.class)) {
Class componentType = JavaClassHelper.getGenericReturnType(method, true);
return EPTypeHelper.collectionOfSingleValue(componentType);
}
if (method.getReturnType().isArray()) {
Class componentType = method.getReturnType().getComponentType();
return EPTypeHelper.array(componentType);
}
return EPTypeHelper.singleValue(method.getReturnType());
}
/**
* Returns a nice text detailing the expression result type.
*
* @param epType type
* @return descriptive text
*/
public static String toTypeDescriptive(EPType epType) {
if (epType instanceof EventEPType) {
EventEPType type = (EventEPType) epType;
return "event type '" + type.getType().getName() + "'";
} else if (epType instanceof EventMultiValuedEPType) {
EventMultiValuedEPType type = (EventMultiValuedEPType) epType;
if (type.getContainer() == EventType[].class) {
return "array of events of type '" + type.getComponent().getName() + "'";
} else {
return "collection of events of type '" + type.getComponent().getName() + "'";
}
} else if (epType instanceof ClassMultiValuedEPType) {
ClassMultiValuedEPType type = (ClassMultiValuedEPType) epType;
if (type.getContainer().isArray()) {
return "array of " + type.getComponent().getSimpleName();
} else {
return "collection of " + type.getComponent().getSimpleName();
}
} else if (epType instanceof ClassEPType) {
ClassEPType type = (ClassEPType) epType;
return "class " + JavaClassHelper.getClassNameFullyQualPretty(type.getType());
} else if (epType instanceof NullEPType) {
return "null type";
} else {
throw new IllegalArgumentException("Unrecognized type " + epType);
}
}
public static Class getNormalizedClass(EPType theType) {
if (theType instanceof EventMultiValuedEPType) {
EventMultiValuedEPType type = (EventMultiValuedEPType) theType;
return JavaClassHelper.getArrayType(type.getComponent().getUnderlyingType());
} else if (theType instanceof EventEPType) {
EventEPType type = (EventEPType) theType;
return type.getType().getUnderlyingType();
} else if (theType instanceof ClassMultiValuedEPType) {
ClassMultiValuedEPType type = (ClassMultiValuedEPType) theType;
return type.getContainer();
} else if (theType instanceof ClassEPType) {
ClassEPType type = (ClassEPType) theType;
return type.getType();
} else if (theType instanceof NullEPType) {
return null;
}
throw new IllegalArgumentException("Unrecognized type " + theType);
}
public static EPType optionalFromEnumerationExpr(int statementId, EventAdapterService eventAdapterService, ExprNode exprNode)
throws ExprValidationException {
if (!(exprNode instanceof ExprEvaluatorEnumeration)) {
return null;
}
ExprEvaluatorEnumeration enumInfo = (ExprEvaluatorEnumeration) exprNode;
if (enumInfo.getComponentTypeCollection() != null) {
return EPTypeHelper.collectionOfSingleValue(enumInfo.getComponentTypeCollection());
}
EventType eventTypeSingle = enumInfo.getEventTypeSingle(eventAdapterService, statementId);
if (eventTypeSingle != null) {
return EPTypeHelper.singleEvent(eventTypeSingle);
}
EventType eventTypeColl = enumInfo.getEventTypeCollection(eventAdapterService, statementId);
if (eventTypeColl != null) {
return EPTypeHelper.collectionOfEvents(eventTypeColl);
}
return null;
}
public static EventType optionalIsEventTypeColl(EPType type) {
if (type != null && type instanceof EventMultiValuedEPType) {
return ((EventMultiValuedEPType) type).getComponent();
}
return null;
}
public static Class optionalIsComponentTypeColl(EPType type) {
if (type != null && type instanceof ClassMultiValuedEPType) {
return ((ClassMultiValuedEPType) type).getComponent();
}
return null;
}
public static EventType optionalIsEventTypeSingle(EPType type) {
if (type != null && type instanceof EventEPType) {
return ((EventEPType) type).getType();
}
return null;
}
}