All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.espertech.esper.event.vaevent.VariantPropResolutionStrategyDefault Maven / Gradle / Ivy

/*
 ***************************************************************************************
 *  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.vaevent;

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.util.JavaClassHelper;
import com.espertech.esper.util.SimpleTypeCaster;
import com.espertech.esper.util.SimpleTypeCasterFactory;

import java.util.LinkedHashSet;
import java.util.Set;

/**
 * A property resolution strategy that allows only the preconfigured types, wherein all properties
 * that are common (name and type) to all properties are considered.
 */
public class VariantPropResolutionStrategyDefault implements VariantPropResolutionStrategy {
    private int currentPropertyNumber;
    private VariantPropertyGetterCache propertyGetterCache;

    /**
     * Ctor.
     *
     * @param variantSpec specified the preconfigured types
     */
    public VariantPropResolutionStrategyDefault(VariantSpec variantSpec) {
        propertyGetterCache = new VariantPropertyGetterCache(variantSpec.getEventTypes());
    }

    public VariantPropertyDesc resolveProperty(String propertyName, EventType[] variants) {
        boolean existsInAll = true;
        Class commonType = null;
        boolean mustCoerce = false;
        for (int i = 0; i < variants.length; i++) {
            Class type = JavaClassHelper.getBoxedType(variants[i].getPropertyType(propertyName));
            if (type == null) {
                existsInAll = false;
                continue;
            }

            if (commonType == null) {
                commonType = type;
                continue;
            }

            // compare types
            if (type.equals(commonType)) {
                continue;
            }

            // coercion
            if (JavaClassHelper.isNumeric(type)) {
                if (JavaClassHelper.canCoerce(type, commonType)) {
                    mustCoerce = true;
                    continue;
                }
                if (JavaClassHelper.canCoerce(commonType, type)) {
                    mustCoerce = true;
                    commonType = type;
                }
            } else if (commonType == Object.class) {
                continue;
            } else if (!JavaClassHelper.isJavaBuiltinDataType(type)) {
                // common interface or base class
                Set supersForType = new LinkedHashSet();
                JavaClassHelper.getSuper(type, supersForType);
                supersForType.remove(Object.class);

                if (supersForType.contains(commonType)) {
                    continue;   // type implements or extends common type
                }
                if (JavaClassHelper.isSubclassOrImplementsInterface(commonType, type)) {
                    commonType = type;  // common type implements type
                    continue;
                }

                // find common interface or type both implement
                Set supersForCommonType = new LinkedHashSet();
                JavaClassHelper.getSuper(commonType, supersForCommonType);
                supersForCommonType.remove(Object.class);

                // Take common classes first, ignoring interfaces
                boolean found = false;
                for (Class superClassType : supersForType) {
                    if (!superClassType.isInterface() && (supersForCommonType.contains(superClassType))) {
                        commonType = superClassType;
                        found = true;
                        break;
                    }
                }
                if (found) {
                    continue;
                }
                // Take common interfaces
                for (Class superClassType : supersForType) {
                    if (superClassType.isInterface() && (supersForCommonType.contains(superClassType))) {
                        break;
                    }
                }
            }

            commonType = Object.class;
        }

        if (!existsInAll) {
            return null;
        }

        if (commonType == null) {
            return null;
        }

        // property numbers should start at zero since the serve as array index
        final int assignedPropertyNumber = currentPropertyNumber;
        currentPropertyNumber++;
        propertyGetterCache.addGetters(assignedPropertyNumber, propertyName);

        EventPropertyGetter getter;
        if (mustCoerce) {
            final SimpleTypeCaster caster = SimpleTypeCasterFactory.getCaster(null, commonType);
            getter = new EventPropertyGetter() {
                public Object get(EventBean eventBean) throws PropertyAccessException {
                    VariantEvent variant = (VariantEvent) eventBean;
                    EventPropertyGetter getter = propertyGetterCache.getGetter(assignedPropertyNumber, variant.getUnderlyingEventBean().getEventType());
                    if (getter == null) {
                        return null;
                    }
                    Object value = getter.get(variant.getUnderlyingEventBean());
                    if (value == null) {
                        return value;
                    }
                    return caster.cast(value);
                }

                public boolean isExistsProperty(EventBean eventBean) {
                    VariantEvent variant = (VariantEvent) eventBean;
                    EventPropertyGetter getter = propertyGetterCache.getGetter(assignedPropertyNumber, variant.getUnderlyingEventBean().getEventType());
                    if (getter == null) {
                        return false;
                    }
                    return getter.isExistsProperty(variant.getUnderlyingEventBean());
                }

                public Object getFragment(EventBean eventBean) {
                    return null;
                }
            };
        } else {
            getter = new EventPropertyGetter() {
                public Object get(EventBean eventBean) throws PropertyAccessException {
                    VariantEvent variant = (VariantEvent) eventBean;
                    EventPropertyGetter getter = propertyGetterCache.getGetter(assignedPropertyNumber, variant.getUnderlyingEventBean().getEventType());
                    if (getter == null) {
                        return null;
                    }
                    return getter.get(variant.getUnderlyingEventBean());
                }

                public boolean isExistsProperty(EventBean eventBean) {
                    VariantEvent variant = (VariantEvent) eventBean;
                    EventPropertyGetter getter = propertyGetterCache.getGetter(assignedPropertyNumber, variant.getUnderlyingEventBean().getEventType());
                    if (getter == null) {
                        return false;
                    }
                    return getter.isExistsProperty(variant.getUnderlyingEventBean());
                }

                public Object getFragment(EventBean eventBean) {
                    return null;
                }
            };
        }

        return new VariantPropertyDesc(commonType, getter, true);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy