Package com.espertech.esper.epl.property

Source Code of com.espertech.esper.epl.property.PropertyEvaluatorFactory

/*
* *************************************************************************************
*  Copyright (C) 2008 EsperTech, Inc. All rights reserved.                            *
*  http://esper.codehaus.org                                                          *
*  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.property;

import com.espertech.esper.client.EventBeanFactory;
import com.espertech.esper.client.EventPropertyGetter;
import com.espertech.esper.client.EventType;
import com.espertech.esper.client.FragmentEventType;
import com.espertech.esper.epl.core.*;
import com.espertech.esper.epl.expression.*;
import com.espertech.esper.epl.spec.*;
import com.espertech.esper.epl.variable.VariableService;
import com.espertech.esper.event.EventAdapterService;
import com.espertech.esper.event.EventAdapterServiceHelper;
import com.espertech.esper.schedule.TimeProvider;
import com.espertech.esper.util.JavaClassHelper;
import com.espertech.esper.util.UuidGenerator;

import java.lang.annotation.Annotation;
import java.util.*;

/**
* Factory for property evaluators.
*/
public class PropertyEvaluatorFactory
{
    /**
     * Makes the property evaluator.
     * @param spec is the property specification
     * @param sourceEventType the event type
     * @param optionalSourceStreamName the source stream name
     * @param eventAdapterService for event instances
     * @param methodResolutionService for resolving UDF
     * @param timeProvider provides time
     * @param variableService for resolving variables
     * @param engineURI engine URI
     * @return propert evaluator
     * @throws ExprValidationException if any expressions could not be verified
     */
    public static PropertyEvaluator makeEvaluator(PropertyEvalSpec spec,
                                                  EventType sourceEventType,
                                                  String optionalSourceStreamName,
                                                  EventAdapterService eventAdapterService,
                                                  MethodResolutionService methodResolutionService,
                                                  final TimeProvider timeProvider,
                                                  VariableService variableService,
                                                  String engineURI,
                                                  String statementId,
                                                  String statementName,
                                                  Annotation[] annotations,
                                                  Collection<Integer> assignedTypeNumberStack)
            throws ExprValidationException
    {
        int length = spec.getAtoms().size();
        ContainedEventEval[] containedEventEvals = new ContainedEventEval[length];
        FragmentEventType fragmentEventTypes[] = new FragmentEventType[length];
        EventType currentEventType = sourceEventType;
        ExprEvaluator whereClauses[] = new ExprEvaluator[length];

        List<EventType> streamEventTypes = new ArrayList<EventType>();
        List<String> streamNames = new ArrayList<String>();
        Map<String, Integer> streamNameAndNumber = new HashMap<String,Integer>();
        List<String> expressionTexts = new ArrayList<String>();
        ExprEvaluatorContext validateContext = new ExprEvaluatorContextTimeOnly(timeProvider);

        streamEventTypes.add(sourceEventType);
        streamNames.add(optionalSourceStreamName);
        streamNameAndNumber.put(optionalSourceStreamName, 0);
        expressionTexts.add(sourceEventType.getName());

        List<SelectClauseElementCompiled> cumulativeSelectClause = new ArrayList<SelectClauseElementCompiled>();
        for (int i = 0; i < length; i++)
        {
            PropertyEvalAtom atom = spec.getAtoms().get(i);
            ContainedEventEval containedEventEval = null;
            String expressionText = null;
            EventType streamEventType = null;
            FragmentEventType fragmentEventType = null;

            // Resolve directly as fragment event type if possible
            if (atom.getSplitterExpression() instanceof ExprIdentNode) {
                String propertyName = ((ExprIdentNode) atom.getSplitterExpression()).getFullUnresolvedName();
                fragmentEventType = currentEventType.getFragmentType(propertyName);
                if (fragmentEventType != null) {
                    EventPropertyGetter getter = currentEventType.getGetter(propertyName);
                    if (getter != null) {
                        containedEventEval = new ContainedEventEvalGetter(getter);
                        expressionText = propertyName;
                        streamEventType = fragmentEventType.getFragmentType();
                    }
                }
            }

            // evaluate splitter expression
            if (containedEventEval == null) {
                ExprNodeUtility.validatePlainExpression("contained-event expression", atom.getSplitterExpression());

                EventType[] availableTypes = streamEventTypes.toArray(new EventType[streamEventTypes.size()]);
                String[] availableStreamNames = streamNames.toArray(new String[streamNames.size()]);
                boolean[] isIStreamOnly = new boolean[streamNames.size()];
                Arrays.fill(isIStreamOnly, true);
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(availableTypes, availableStreamNames, isIStreamOnly, engineURI, false);
                ExprValidationContext validationContext = new ExprValidationContext(streamTypeService, methodResolutionService, null, timeProvider, variableService, validateContext, eventAdapterService, statementName, statementId, annotations, null);
                ExprNode validatedExprNode = ExprNodeUtility.getValidatedSubtree(atom.getSplitterExpression(), validationContext);
                ExprEvaluator evaluator = validatedExprNode.getExprEvaluator();

                // determine result type
                if (atom.getOptionalResultEventType() == null) {
                    throw new ExprValidationException("Missing @type(name) declaration providing the event type name of the return type for expression '" + atom.getSplitterExpression().toExpressionString() + "'");
                }
                streamEventType = eventAdapterService.getExistsTypeByName(atom.getOptionalResultEventType());
                if (streamEventType == null) {
                    throw new ExprValidationException("Event type by name '" + atom.getOptionalResultEventType() + "' could not be found");
                }
                EventBeanFactory eventBeanFactory = EventAdapterServiceHelper.getFactoryForType(streamEventType, eventAdapterService);

                // check expression result type against eventtype expected underlying type
                Class returnType = evaluator.getType();
                if (returnType.isArray()) {
                    if ((!JavaClassHelper.isSubclassOrImplementsInterface(returnType.getComponentType(), streamEventType.getUnderlyingType()))) {
                        throw new ExprValidationException("Event type '" + streamEventType.getName() + "' underlying type " + streamEventType.getUnderlyingType().getName() +
                                " cannot be assigned a value of type " + JavaClassHelper.getClassNameFullyQualPretty(returnType));
                    }
                }
                else if (JavaClassHelper.isImplementsInterface(returnType, Iterable.class)) {
                    // fine, assumed to return the right type
                }
                else {
                    throw new ExprValidationException("Return type of expression '" + atom.getSplitterExpression().toExpressionString() + "' is '" + returnType.getName() + "', expected an Iterable or array result");
                }

                containedEventEval = new ContainedEventEvalExprNode(evaluator, eventBeanFactory);
                expressionText = validatedExprNode.toExpressionString();
                fragmentEventType = new FragmentEventType(streamEventType, true, false);
            }

            // validate where clause, if any
            streamEventTypes.add(streamEventType);
            streamNames.add(atom.getOptionalAsName());
            streamNameAndNumber.put(atom.getOptionalAsName(), i + 1);
            expressionTexts.add(expressionText);

            if (atom.getOptionalWhereClause() != null)
            {
                EventType[] whereTypes = streamEventTypes.toArray(new EventType[streamEventTypes.size()]);
                String[] whereStreamNames = streamNames.toArray(new String[streamNames.size()]);
                boolean[] isIStreamOnly = new boolean[streamNames.size()];
                Arrays.fill(isIStreamOnly, true);
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(whereTypes, whereStreamNames, isIStreamOnly, engineURI, false);
                ExprValidationContext validationContext = new ExprValidationContext(streamTypeService, methodResolutionService, null, timeProvider, variableService, validateContext, eventAdapterService, statementName, statementId, annotations, null);
                whereClauses[i] = ExprNodeUtility.getValidatedSubtree(atom.getOptionalWhereClause(), validationContext).getExprEvaluator();
            }

            // validate select clause
            if (atom.getOptionalSelectClause() != null)
            {
                EventType[] whereTypes = streamEventTypes.toArray(new EventType[streamEventTypes.size()]);
                String[] whereStreamNames = streamNames.toArray(new String[streamNames.size()]);
                boolean[] isIStreamOnly = new boolean[streamNames.size()];
                Arrays.fill(isIStreamOnly, true);
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(whereTypes, whereStreamNames, isIStreamOnly, engineURI, false);
                ExprValidationContext validationContext = new ExprValidationContext(streamTypeService, methodResolutionService, null, timeProvider, variableService, validateContext, eventAdapterService, statementName, statementId, annotations, null);

                for (SelectClauseElementRaw raw : atom.getOptionalSelectClause().getSelectExprList())
                {
                    if (raw instanceof SelectClauseStreamRawSpec)
                    {
                        SelectClauseStreamRawSpec rawStreamSpec = (SelectClauseStreamRawSpec) raw;
                        if (!streamNames.contains(rawStreamSpec.getStreamName()))
                        {
                            throw new ExprValidationException("Property rename '" + rawStreamSpec.getStreamName() + "' not found in path");
                        }
                        SelectClauseStreamCompiledSpec streamSpec = new SelectClauseStreamCompiledSpec(rawStreamSpec.getStreamName(), rawStreamSpec.getOptionalAsName());
                        int streamNumber = streamNameAndNumber.get(rawStreamSpec.getStreamName());
                        streamSpec.setStreamNumber(streamNumber);
                        cumulativeSelectClause.add(streamSpec);
                    }
                    else if (raw instanceof SelectClauseExprRawSpec)
                    {
                        SelectClauseExprRawSpec exprSpec = (SelectClauseExprRawSpec) raw;
                        ExprNode exprCompiled = ExprNodeUtility.getValidatedSubtree(exprSpec.getSelectExpression(), validationContext);
                        String resultName = exprSpec.getOptionalAsName();
                        if (resultName == null)
                        {
                            resultName = exprCompiled.toExpressionString();
                        }
                        cumulativeSelectClause.add(new SelectClauseExprCompiledSpec(exprCompiled, resultName, exprSpec.getOptionalAsName()));

                        String isMinimal = ExprNodeUtility.isMinimalExpression(exprCompiled);
                        if (isMinimal != null)
                        {
                            throw new ExprValidationException("Expression in a property-selection may not utilize " + isMinimal);
                        }
                    }
                    else if (raw instanceof SelectClauseElementWildcard)
                    {
                        // wildcards are stream selects: we assign a stream name (any) and add a stream wildcard select
                        String streamNameAtom = atom.getOptionalAsName();
                        if (streamNameAtom == null)
                        {
                            streamNameAtom = UuidGenerator.generate();
                        }

                        SelectClauseStreamCompiledSpec streamSpec = new SelectClauseStreamCompiledSpec(streamNameAtom, atom.getOptionalAsName());
                        int streamNumber = i + 1;
                        streamSpec.setStreamNumber(streamNumber);
                        cumulativeSelectClause.add(streamSpec);
                    }
                    else
                    {
                        throw new IllegalStateException("Unknown select clause item:" + raw);
                    }
                }
            }

            currentEventType = fragmentEventType.getFragmentType();
            fragmentEventTypes[i] = fragmentEventType;
            containedEventEvals[i] = containedEventEval;
        }

        if (cumulativeSelectClause.isEmpty())
        {
            if (length == 1)
            {
                return new PropertyEvaluatorSimple(containedEventEvals[0], fragmentEventTypes[0], whereClauses[0], expressionTexts.get(0));
            }
            else
            {
                return new PropertyEvaluatorNested(containedEventEvals, fragmentEventTypes, whereClauses, expressionTexts);
            }
        }
        else
        {
            PropertyEvaluatorAccumulative accumulative = new PropertyEvaluatorAccumulative(containedEventEvals, fragmentEventTypes, whereClauses, expressionTexts);

            EventType[] whereTypes = streamEventTypes.toArray(new EventType[streamEventTypes.size()]);
            String[] whereStreamNames = streamNames.toArray(new String[streamNames.size()]);
            boolean[] isIStreamOnly = new boolean[streamNames.size()];
            Arrays.fill(isIStreamOnly, true);
            StreamTypeService streamTypeService = new StreamTypeServiceImpl(whereTypes, whereStreamNames, isIStreamOnly, engineURI, false);

            SelectExprProcessor selectExpr = SelectExprProcessorFactory.getProcessor(assignedTypeNumberStack, cumulativeSelectClause, false, null, null, streamTypeService, eventAdapterService, null, null, null, methodResolutionService, validateContext, variableService, timeProvider, engineURI, statementId, statementName, annotations, null);
            return new PropertyEvaluatorSelect(selectExpr, accumulative);
        }
    }
}
TOP

Related Classes of com.espertech.esper.epl.property.PropertyEvaluatorFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.