Package com.espertech.esper.core.context.mgr

Source Code of com.espertech.esper.core.context.mgr.ContextControllerPartitionedUtil

/*
* *************************************************************************************
*  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.core.context.mgr;

import com.espertech.esper.client.EventPropertyGetter;
import com.espertech.esper.client.EventType;
import com.espertech.esper.collection.MultiKeyUntyped;
import com.espertech.esper.epl.expression.ExprValidationException;
import com.espertech.esper.epl.named.NamedWindowProcessor;
import com.espertech.esper.epl.named.NamedWindowService;
import com.espertech.esper.epl.spec.ContextDetailPartitionItem;
import com.espertech.esper.epl.spec.ContextDetailPartitioned;
import com.espertech.esper.epl.spec.StatementSpecCompiled;
import com.espertech.esper.epl.spec.util.StatementSpecCompiledAnalyzerResult;
import com.espertech.esper.event.EventTypeUtility;
import com.espertech.esper.filter.*;
import com.espertech.esper.util.JavaClassHelper;

import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;

public class ContextControllerPartitionedUtil {

    protected static Class[] validateContextDesc(String contextName, ContextDetailPartitioned segmentedSpec) throws ExprValidationException {

        if (segmentedSpec.getItems().isEmpty()) {
            throw new ExprValidationException("Empty list of partition items");
        }

        // verify properties exist
        for (ContextDetailPartitionItem item : segmentedSpec.getItems()) {
            EventType type = item.getFilterSpecCompiled().getFilterForEventType();
            for (String property : item.getPropertyNames()) {
                EventPropertyGetter getter = type.getGetter(property);
                if (getter == null) {
                    throw new ExprValidationException("For context '" + contextName + "' property name '" + property + "' not found on type " + type.getName());
                }
            }
        }

        // verify property number and types compatible
        ContextDetailPartitionItem firstItem = segmentedSpec.getItems().get(0);
        if (segmentedSpec.getItems().size() > 1) {
        // verify the same filter event type is only listed once

            for (int i = 0; i < segmentedSpec.getItems().size(); i++) {
                EventType compareTo = segmentedSpec.getItems().get(i).getFilterSpecCompiled().getFilterForEventType();

                for (int j = 0; j < segmentedSpec.getItems().size(); j++) {
                    if (i == j) {
                        continue;
                    }

                    EventType compareFrom = segmentedSpec.getItems().get(j).getFilterSpecCompiled().getFilterForEventType();
                    if (compareFrom == compareTo) {
                        throw new ExprValidationException("For context '" + contextName + "' the event type '" + compareFrom.getName() + "' is listed twice");
                    }
                    if (EventTypeUtility.isTypeOrSubTypeOf(compareFrom, compareTo) || EventTypeUtility.isTypeOrSubTypeOf(compareTo, compareFrom)) {
                        throw new ExprValidationException("For context '" + contextName + "' the event type '" + compareFrom.getName() + "' is listed twice: Event type '" +
                                compareFrom.getName() + "' is a subtype or supertype of event type '" + compareTo.getName() + "'");
                    }

                }
            }

            // build property type information
            String[] names = new String[firstItem.getPropertyNames().size()];
            Class[] types = new Class[firstItem.getPropertyNames().size()];
            Class[] typesBoxed = new Class[firstItem.getPropertyNames().size()];
            for (int i = 0; i < firstItem.getPropertyNames().size(); i++) {
                String property = firstItem.getPropertyNames().get(i);
                names[i] = property;
                types[i] = firstItem.getFilterSpecCompiled().getFilterForEventType().getPropertyType(property);
                typesBoxed[i] = JavaClassHelper.getBoxedType(types[i]);
            }

            // compare property types and numbers
            for (int item = 1; item < segmentedSpec.getItems().size(); item++) {
                ContextDetailPartitionItem nextItem = segmentedSpec.getItems().get(item);

                // compare number of properties
                if (nextItem.getPropertyNames().size() != types.length) {
                    throw new ExprValidationException("For context '" + contextName + "' expected the same number of property names for each event type, found " +
                            types.length + " properties for event type '" + firstItem.getFilterSpecCompiled().getFilterForEventType().getName() +
                            "' and " + nextItem.getPropertyNames().size() + " properties for event type '" + nextItem.getFilterSpecCompiled().getFilterForEventType().getName() + "'");
                }

                // compare property types
                for (int i = 0; i < nextItem.getPropertyNames().size(); i++) {
                    String property = nextItem.getPropertyNames().get(i);
                    Class type = JavaClassHelper.getBoxedType(nextItem.getFilterSpecCompiled().getFilterForEventType().getPropertyType(property));
                    Class typeBoxed = JavaClassHelper.getBoxedType(type);
                    boolean left = JavaClassHelper.isSubclassOrImplementsInterface(typeBoxed, typesBoxed[i]);
                    boolean right = JavaClassHelper.isSubclassOrImplementsInterface(typesBoxed[i], typeBoxed);
                    if (typeBoxed != typesBoxed[i] && !left && !right) {
                        throw new ExprValidationException("For context '" + contextName + "' for context '" + contextName + "' found mismatch of property types, property '" + names[i] +
                                "' of type '" + JavaClassHelper.getClassNameFullyQualPretty(types[i]) +
                                "' compared to property '" + property +
                                "' of type '" + JavaClassHelper.getClassNameFullyQualPretty(typeBoxed) + "'");
                    }
                }
            }
        }

        Class[] propertyTypes = new Class[firstItem.getPropertyNames().size()];
        for (int i = 0; i < firstItem.getPropertyNames().size(); i++) {
            String property = firstItem.getPropertyNames().get(i);
            propertyTypes[i] = firstItem.getFilterSpecCompiled().getFilterForEventType().getPropertyType(property);
        }
        return propertyTypes;
    }

    protected static void validateStatementForContext(String contextName, ContextControllerStatementBase statement, StatementSpecCompiledAnalyzerResult streamAnalysis, Collection<EventType> itemEventTypes, NamedWindowService namedWindowService)
        throws ExprValidationException
    {
        List<FilterSpecCompiled> filters = streamAnalysis.getFilters();

        boolean isCreateWindow = statement.getStatementSpec().getCreateWindowDesc() != null;

        // if no create-window: at least one of the filters must match one of the filters specified by the context
        if (!isCreateWindow) {
            for (FilterSpecCompiled filter : filters) {
                for (EventType itemEventType : itemEventTypes) {
                    EventType stmtFilterType = filter.getFilterForEventType();
                    if (stmtFilterType == itemEventType) {
                        return;
                    }
                    if (EventTypeUtility.isTypeOrSubTypeOf(stmtFilterType, itemEventType)) {
                        return;
                    }

                    NamedWindowProcessor processor = namedWindowService.getProcessor(stmtFilterType.getName());
                    if (processor != null && processor.getContextName() != null && processor.getContextName().equals(contextName)) {
                        return;
                    }
                }
            }

            if (!filters.isEmpty()) {
                throw new ExprValidationException(getTypeValidationMessage(contextName, filters.get(0).getFilterForEventType().getName()));
            }
            return;
        }

        // validate create-window
        String declaredAsName = statement.getStatementSpec().getCreateWindowDesc().getAsEventTypeName();
        if (declaredAsName != null) {
            for (EventType itemEventType : itemEventTypes) {
                if (itemEventType.getName().equals(declaredAsName)) {
                    return;
                }
            }

            throw new ExprValidationException(getTypeValidationMessage(contextName, declaredAsName));
        }
    }

    // Compare filters in statement with filters in segmented context, addendum filter compilation
    public static void populateAddendumFilters(Object keyValue, List<FilterSpecCompiled> filtersSpecs, ContextDetailPartitioned segmentedSpec, StatementSpecCompiled optionalStatementSpecCompiled, IdentityHashMap<FilterSpecCompiled, List<FilterValueSetParam>> addendums) {

        // determine whether create-named-window
        boolean isCreateWindow = optionalStatementSpecCompiled != null && optionalStatementSpecCompiled.getCreateWindowDesc() != null;
        if (!isCreateWindow) {
            for (FilterSpecCompiled filtersSpec : filtersSpecs) {

                ContextDetailPartitionItem foundPartition = null;
                for (ContextDetailPartitionItem partitionItem : segmentedSpec.getItems()) {
                    boolean typeOrSubtype = EventTypeUtility.isTypeOrSubTypeOf(filtersSpec.getFilterForEventType(), partitionItem.getFilterSpecCompiled().getFilterForEventType());
                    if (typeOrSubtype) {
                        foundPartition = partitionItem;
                    }
                }

                if (foundPartition == null) {
                    continue;
                }

                List<FilterValueSetParam> addendumFilters = new ArrayList<FilterValueSetParam>(foundPartition.getPropertyNames().size());
                if (foundPartition.getPropertyNames().size() == 1) {
                    String propertyName = foundPartition.getPropertyNames().get(0);
                    EventPropertyGetter getter = foundPartition.getFilterSpecCompiled().getFilterForEventType().getGetter(propertyName);
                    Class resultType = foundPartition.getFilterSpecCompiled().getFilterForEventType().getPropertyType(propertyName);
                    FilterSpecLookupable lookupable = new FilterSpecLookupable(propertyName, getter, resultType);
                    FilterValueSetParam filter = new FilterValueSetParamImpl(lookupable, FilterOperator.EQUAL, keyValue);
                    addendumFilters.add(filter);
                }
                else {
                    Object[] keys = ((MultiKeyUntyped) keyValue).getKeys();
                    for (int i = 0; i < foundPartition.getPropertyNames().size(); i++) {
                        String partitionPropertyName = foundPartition.getPropertyNames().get(i);
                        EventPropertyGetter getter = foundPartition.getFilterSpecCompiled().getFilterForEventType().getGetter(partitionPropertyName);
                        Class resultType = foundPartition.getFilterSpecCompiled().getFilterForEventType().getPropertyType(partitionPropertyName);
                        FilterSpecLookupable lookupable = new FilterSpecLookupable(partitionPropertyName, getter, resultType);
                        FilterValueSetParam filter = new FilterValueSetParamImpl(lookupable, FilterOperator.EQUAL, keys[i]);
                        addendumFilters.add(filter);
                    }
                }

                // add those predefined filter parameters, if any
                addendumFilters.addAll(foundPartition.getParametersCompiled());

                // add to existing if any are present
                List<FilterValueSetParam> existing = addendums.get(filtersSpec);
                if (existing != null) {
                    existing.addAll(addendumFilters);
                }
                else {
                    addendums.put(filtersSpec, addendumFilters);
                }
            }
        }
        // handle segmented context for create-window
        else {
            String declaredAsName = optionalStatementSpecCompiled.getCreateWindowDesc().getAsEventTypeName();
            if (declaredAsName != null) {
                for (FilterSpecCompiled filtersSpec : filtersSpecs) {

                    ContextDetailPartitionItem foundPartition = null;
                    for (ContextDetailPartitionItem partitionItem : segmentedSpec.getItems()) {
                        if (partitionItem.getFilterSpecCompiled().getFilterForEventType().getName().equals(declaredAsName)) {
                            foundPartition = partitionItem;
                            break;
                        }
                    }

                    if (foundPartition == null) {
                        continue;
                    }

                    List<FilterValueSetParam> addendumFilters = new ArrayList<FilterValueSetParam>(foundPartition.getPropertyNames().size());
                    int propertyNumber = 0;
                    for (String partitionPropertyName : foundPartition.getPropertyNames()) {
                        EventPropertyGetter getter = foundPartition.getFilterSpecCompiled().getFilterForEventType().getGetter(partitionPropertyName);
                        Class resultType = foundPartition.getFilterSpecCompiled().getFilterForEventType().getPropertyType(partitionPropertyName);
                        FilterSpecLookupable lookupable = new FilterSpecLookupable(partitionPropertyName, getter, resultType);

                        Object propertyValue;
                        if (keyValue instanceof MultiKeyUntyped) {
                            propertyValue = ((MultiKeyUntyped) keyValue).get(propertyNumber);
                        }
                        else {
                            propertyValue = keyValue;
                        }

                        FilterValueSetParam filter = new FilterValueSetParamImpl(lookupable, FilterOperator.EQUAL, propertyValue);
                        addendumFilters.add(filter);
                        propertyNumber++;
                    }

                    // add to existing if any are present
                    List<FilterValueSetParam> existing = addendums.get(filtersSpec);
                    if (existing != null) {
                        existing.addAll(addendumFilters);
                    }
                    else {
                        addendums.put(filtersSpec, addendumFilters);
                    }
                }
            }
        }
    }

    private static String getTypeValidationMessage(String contextName, String typeNameEx) {
        return "Segmented context '" + contextName + "' requires that any of the event types that are listed in the segmented context also appear in any of the filter expressions of the statement, type '" + typeNameEx + "' is not one of the types listed";
    }
}
TOP

Related Classes of com.espertech.esper.core.context.mgr.ContextControllerPartitionedUtil

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.