Beispiel #1
0
  /**
   * Ctor.
   *
   * @param typeName is the event type name
   * @param eventType is the event type of the wrapped events
   * @param properties is the additional properties this wrapper adds
   * @param metadata event type metadata
   * @param eventAdapterService is the service for resolving unknown wrapped types
   */
  public WrapperEventType(
      EventTypeMetadata metadata,
      String typeName,
      int eventTypeId,
      EventType eventType,
      Map<String, Object> properties,
      EventAdapterService eventAdapterService) {
    checkForRepeatedPropertyNames(eventType, properties);

    this.metadata = metadata;
    this.underlyingEventType = eventType;
    EventTypeMetadata metadataMapType = EventTypeMetadata.createAnonymous(typeName);
    this.underlyingMapType =
        new MapEventType(
            metadataMapType, typeName, 0, eventAdapterService, properties, null, null, null);
    this.isNoMapProperties = properties.isEmpty();
    this.eventAdapterService = eventAdapterService;
    this.eventTypeId = eventTypeId;
    propertyGetterCache = new HashMap<String, EventPropertyGetter>();

    updatePropertySet();

    if (metadata.getTypeClass() == EventTypeMetadata.TypeClass.NAMED_WINDOW) {
      startTimestampPropertyName = eventType.getStartTimestampPropertyName();
      endTimestampPropertyName = eventType.getEndTimestampPropertyName();
      EventTypeUtility.validateTimestampProperties(
          this, startTimestampPropertyName, endTimestampPropertyName);
    }
  }
Beispiel #2
0
 public Class getPropertyType(String property) {
   if (underlyingEventType.isProperty(property)) {
     return underlyingEventType.getPropertyType(property);
   } else if (underlyingMapType.isProperty(property)) {
     return underlyingMapType.getPropertyType(property);
   } else {
     return null;
   }
 }
Beispiel #3
0
 public FragmentEventType getFragmentType(String property) {
   FragmentEventType fragment = underlyingEventType.getFragmentType(property);
   if (fragment != null) {
     return fragment;
   }
   return underlyingMapType.getFragmentType(property);
 }
Beispiel #4
0
 public EventPropertyGetterIndexed getGetterIndexed(String indexedProperty) {
   final EventPropertyGetterIndexed undIndexed =
       underlyingEventType.getGetterIndexed(indexedProperty);
   if (undIndexed != null) {
     return new EventPropertyGetterIndexed() {
       public Object get(EventBean theEvent, int index) throws PropertyAccessException {
         if (!(theEvent instanceof DecoratingEventBean)) {
           throw new PropertyAccessException("Mismatched property getter to EventBean type");
         }
         DecoratingEventBean wrapperEvent = (DecoratingEventBean) theEvent;
         EventBean wrappedEvent = wrapperEvent.getUnderlyingEvent();
         if (wrappedEvent == null) {
           return null;
         }
         return undIndexed.get(wrappedEvent, index);
       }
     };
   }
   final EventPropertyGetterIndexed decoIndexed =
       underlyingMapType.getGetterIndexed(indexedProperty);
   if (decoIndexed != null) {
     return new EventPropertyGetterIndexed() {
       public Object get(EventBean theEvent, int index) throws PropertyAccessException {
         if (!(theEvent instanceof DecoratingEventBean)) {
           throw new PropertyAccessException("Mismatched property getter to EventBean type");
         }
         DecoratingEventBean wrapperEvent = (DecoratingEventBean) theEvent;
         Map map = wrapperEvent.getDecoratingProperties();
         return decoIndexed.get(
             eventAdapterService.adapterForTypedMap(map, underlyingMapType), index);
       }
     };
   }
   return null;
 }
Beispiel #5
0
 private void updatePropertySet() {
   PropertyDescriptorComposite compositeProperties =
       getCompositeProperties(underlyingEventType, underlyingMapType);
   propertyNames = compositeProperties.getPropertyNames();
   propertyDescriptorMap = compositeProperties.getPropertyDescriptorMap();
   propertyDesc = compositeProperties.getDescriptors();
   numPropertiesUnderlyingType = underlyingEventType.getPropertyDescriptors().length;
 }
  public void testConfiguredViaPropsAndXML() {
    Configuration configuration = SupportConfigFactory.getConfiguration();
    configuration
        .getEngineDefaults()
        .getEventMeta()
        .setDefaultEventRepresentation(Configuration.EventRepresentation.OBJECTARRAY);
    configuration.addEventType(
        "MyOAType",
        "bean,theString,map".split(","),
        new Object[] {SupportBean.class.getName(), "string", "java.util.Map"});

    EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(configuration);
    epService.initialize();
    if (InstrumentationHelper.ENABLED) {
      InstrumentationHelper.startTest(epService, this.getClass(), getName());
    }

    EventType eventType =
        epService.getEPAdministrator().getConfiguration().getEventType("MyOAType");
    assertEquals(Object[].class, eventType.getUnderlyingType());
    assertEquals(String.class, eventType.getPropertyType("theString"));
    assertEquals(Map.class, eventType.getPropertyType("map"));
    assertEquals(SupportBean.class, eventType.getPropertyType("bean"));

    EPStatement stmt =
        epService
            .getEPAdministrator()
            .createEPL("select bean, theString, map('key'), bean.theString from MyOAType");
    SupportUpdateListener listener = new SupportUpdateListener();
    stmt.addListener(listener);
    assertEquals(Object[].class, stmt.getEventType().getUnderlyingType());

    SupportBean bean = new SupportBean("E1", 1);
    epService
        .getEPRuntime()
        .sendEvent(
            new Object[] {bean, "abc", Collections.singletonMap("key", "value")}, "MyOAType");
    EPAssertionUtil.assertProps(
        listener.assertOneGetNew(),
        "bean,theString,map('key'),bean.theString".split(","),
        new Object[] {bean, "abc", "value", "E1"});

    if (InstrumentationHelper.ENABLED) {
      InstrumentationHelper.endTest();
    }
  }
Beispiel #7
0
 private void checkForRepeatedPropertyNames(EventType eventType, Map<String, Object> properties) {
   for (String property : eventType.getPropertyNames()) {
     if (properties.keySet().contains(property)) {
       throw new EPException(
           "Property "
               + property
               + " occurs in both the underlying event and in the additional properties");
     }
   }
 }
Beispiel #8
0
 public Class getUnderlyingType() {
   // If the additional properties are empty, such as when wrapping a native event by means of
   // wildcard-only select
   // then the underlying type is simply the wrapped type.
   if (isNoMapProperties) {
     return underlyingEventType.getUnderlyingType();
   } else {
     return Pair.class;
   }
 }
Beispiel #9
0
  private static PropertyDescriptorComposite getCompositeProperties(
      EventType underlyingEventType, MapEventType underlyingMapType) {
    List<String> propertyNames = new ArrayList<String>();
    propertyNames.addAll(Arrays.asList(underlyingEventType.getPropertyNames()));
    propertyNames.addAll(Arrays.asList(underlyingMapType.getPropertyNames()));
    String[] propertyNamesArr = propertyNames.toArray(new String[propertyNames.size()]);

    List<EventPropertyDescriptor> propertyDesc = new ArrayList<EventPropertyDescriptor>();
    HashMap<String, EventPropertyDescriptor> propertyDescriptorMap =
        new HashMap<String, EventPropertyDescriptor>();
    for (EventPropertyDescriptor eventProperty : underlyingEventType.getPropertyDescriptors()) {
      propertyDesc.add(eventProperty);
      propertyDescriptorMap.put(eventProperty.getPropertyName(), eventProperty);
    }
    for (EventPropertyDescriptor mapProperty : underlyingMapType.getPropertyDescriptors()) {
      propertyDesc.add(mapProperty);
      propertyDescriptorMap.put(mapProperty.getPropertyName(), mapProperty);
    }
    EventPropertyDescriptor[] propertyDescArr =
        propertyDesc.toArray(new EventPropertyDescriptor[propertyDesc.size()]);
    return new PropertyDescriptorComposite(
        propertyDescriptorMap, propertyNamesArr, propertyDescArr);
  }
  public SelectExprProcessor getEvaluator() throws ExprValidationException {

    // Get the named and un-named stream selectors (i.e. select s0.* from S0 as s0), if any
    List<SelectClauseStreamCompiledSpec> namedStreams =
        new ArrayList<SelectClauseStreamCompiledSpec>();
    List<SelectExprStreamDesc> unnamedStreams = new ArrayList<SelectExprStreamDesc>();
    for (SelectExprStreamDesc spec : selectedStreams) {
      if (spec.getStreamSelected() != null && spec.getStreamSelected().getOptionalName() == null) {
        unnamedStreams.add(spec);
      } else if (spec.getExpressionSelectedAsStream()
          != null) { // handle special "transpose(...)" function
        unnamedStreams.add(spec);
      } else {
        namedStreams.add(spec.getStreamSelected());
        if (spec.getStreamSelected().isProperty()) {
          throw new ExprValidationException(
              "The property wildcard syntax must be used without column name");
        }
      }
    }

    // Error if there are more then one un-named streams (i.e. select s0.*, s1.* from S0 as s0, S1
    // as s1)
    // Thus there is only 1 unnamed stream selector maximum.
    if (unnamedStreams.size() > 1) {
      throw new ExprValidationException(
          "A column name must be supplied for all but one stream if multiple streams are selected via the stream.* notation");
    }

    if (selectedStreams.isEmpty() && selectionList.isEmpty() && !isUsingWildcard) {
      throw new IllegalArgumentException("Empty selection list not supported");
    }

    for (SelectClauseExprCompiledSpec entry : selectionList) {
      if (entry.getAssignedName() == null) {
        throw new IllegalArgumentException(
            "Expected name for each expression has not been supplied");
      }
    }

    // Verify insert into clause
    if (insertIntoDesc != null) {
      verifyInsertInto(insertIntoDesc, selectionList);
    }

    // Build a subordinate wildcard processor for joins
    SelectExprProcessor joinWildcardProcessor = null;
    if (typeService.getStreamNames().length > 1 && isUsingWildcard) {
      joinWildcardProcessor =
          SelectExprJoinWildcardProcessorFactory.create(
              assignedTypeNumberStack,
              statementId,
              typeService.getStreamNames(),
              typeService.getEventTypes(),
              eventAdapterService,
              null,
              selectExprEventTypeRegistry,
              methodResolutionService,
              annotations,
              configuration);
    }

    // Resolve underlying event type in the case of wildcard select
    EventType eventType = null;
    boolean singleStreamWrapper = false;
    if (isUsingWildcard) {
      if (joinWildcardProcessor != null) {
        eventType = joinWildcardProcessor.getResultEventType();
      } else {
        eventType = typeService.getEventTypes()[0];
        if (eventType instanceof WrapperEventType) {
          singleStreamWrapper = true;
        }
      }
    }

    // Get expression nodes
    ExprEvaluator[] exprEvaluators = new ExprEvaluator[selectionList.size()];
    ExprNode[] exprNodes = new ExprNode[selectionList.size()];
    Object[] expressionReturnTypes = new Object[selectionList.size()];
    for (int i = 0; i < selectionList.size(); i++) {
      ExprNode expr = selectionList.get(i).getSelectExpression();
      exprNodes[i] = expr;
      exprEvaluators[i] = expr.getExprEvaluator();
      Map<String, Object> eventTypeExpr = exprEvaluators[i].getEventType();
      if (eventTypeExpr == null) {
        expressionReturnTypes[i] = exprEvaluators[i].getType();
      } else {
        final ExprEvaluator innerExprEvaluator = expr.getExprEvaluator();
        final EventType mapType =
            eventAdapterService.createAnonymousMapType(
                statementId
                    + "_innereval_"
                    + CollectionUtil.toString(assignedTypeNumberStack, "_")
                    + "_"
                    + i,
                eventTypeExpr);
        ExprEvaluator evaluatorFragment =
            new ExprEvaluator() {
              public Object evaluate(
                  EventBean[] eventsPerStream,
                  boolean isNewData,
                  ExprEvaluatorContext exprEvaluatorContext) {
                Map<String, Object> values =
                    (Map<String, Object>)
                        innerExprEvaluator.evaluate(
                            eventsPerStream, isNewData, exprEvaluatorContext);
                if (values == null) {
                  values = Collections.emptyMap();
                }
                return eventAdapterService.adapterForTypedMap(values, mapType);
              }

              public Class getType() {
                return Map.class;
              }

              public Map<String, Object> getEventType() {
                return null;
              }
            };

        expressionReturnTypes[i] = mapType;
        exprEvaluators[i] = evaluatorFragment;
      }
    }

    // Get column names
    String[] columnNames;
    String[] columnNamesAsProvided;
    if ((insertIntoDesc != null) && (!insertIntoDesc.getColumnNames().isEmpty())) {
      columnNames =
          insertIntoDesc
              .getColumnNames()
              .toArray(new String[insertIntoDesc.getColumnNames().size()]);
      columnNamesAsProvided = columnNames;
    } else if (!selectedStreams.isEmpty()) { // handle stream selection column names
      int numStreamColumnsJoin = 0;
      if (isUsingWildcard && typeService.getEventTypes().length > 1) {
        numStreamColumnsJoin = typeService.getEventTypes().length;
      }
      columnNames = new String[selectionList.size() + namedStreams.size() + numStreamColumnsJoin];
      columnNamesAsProvided = new String[columnNames.length];
      int count = 0;
      for (SelectClauseExprCompiledSpec aSelectionList : selectionList) {
        columnNames[count] = aSelectionList.getAssignedName();
        columnNamesAsProvided[count] = aSelectionList.getProvidedName();
        count++;
      }
      for (SelectClauseStreamCompiledSpec aSelectionList : namedStreams) {
        columnNames[count] = aSelectionList.getOptionalName();
        columnNamesAsProvided[count] = aSelectionList.getOptionalName();
        count++;
      }
      // for wildcard joins, add the streams themselves
      if (isUsingWildcard && typeService.getEventTypes().length > 1) {
        for (String streamName : typeService.getStreamNames()) {
          columnNames[count] = streamName;
          columnNamesAsProvided[count] = streamName;
          count++;
        }
      }
    } else // handle regular column names
    {
      columnNames = new String[selectionList.size()];
      columnNamesAsProvided = new String[selectionList.size()];
      for (int i = 0; i < selectionList.size(); i++) {
        columnNames[i] = selectionList.get(i).getAssignedName();
        columnNamesAsProvided[i] = selectionList.get(i).getProvidedName();
      }
    }

    // Find if there is any fragments selected
    EventType targetType = null;
    if (insertIntoDesc != null) {
      targetType = eventAdapterService.getExistsTypeByName(insertIntoDesc.getEventTypeName());
    }

    // Find if there is any fragment event types:
    // This is a special case for fragments: select a, b from pattern [a=A -> b=B]
    // We'd like to maintain 'A' and 'B' EventType in the Map type, and 'a' and 'b' EventBeans in
    // the event bean
    for (int i = 0; i < selectionList.size(); i++) {
      if (!(exprNodes[i] instanceof ExprIdentNode)) {
        continue;
      }

      ExprIdentNode identNode = (ExprIdentNode) exprNodes[i];
      String propertyName = identNode.getResolvedPropertyName();
      final int streamNum = identNode.getStreamId();

      EventType eventTypeStream = typeService.getEventTypes()[streamNum];
      if (eventTypeStream instanceof NativeEventType) {
        continue; // we do not transpose the native type for performance reasons
      }

      FragmentEventType fragmentType = eventTypeStream.getFragmentType(propertyName);
      if ((fragmentType == null) || (fragmentType.isNative())) {
        continue; // we also ignore native Java classes as fragments for performance reasons
      }

      // may need to unwrap the fragment if the target type has this underlying type
      FragmentEventType targetFragment = null;
      if (targetType != null) {
        targetFragment = targetType.getFragmentType(columnNames[i]);
      }
      if ((targetType != null)
          && (fragmentType.getFragmentType().getUnderlyingType() == expressionReturnTypes[i])
          && ((targetFragment == null) || (targetFragment != null && targetFragment.isNative()))) {
        ExprEvaluator evaluatorFragment;

        // A match was found, we replace the expression
        final EventPropertyGetter getter = eventTypeStream.getGetter(propertyName);
        final Class returnType = eventTypeStream.getPropertyType(propertyName);
        evaluatorFragment =
            new ExprEvaluator() {
              public Object evaluate(
                  EventBean[] eventsPerStream,
                  boolean isNewData,
                  ExprEvaluatorContext exprEvaluatorContext) {
                EventBean streamEvent = eventsPerStream[streamNum];
                if (streamEvent == null) {
                  return null;
                }
                return getter.get(streamEvent);
              }

              public Class getType() {
                return returnType;
              }

              @Override
              public Map<String, Object> getEventType() {
                return null;
              }
            };
        exprEvaluators[i] = evaluatorFragment;
      }
      // same for arrays: may need to unwrap the fragment if the target type has this underlying
      // type
      else if ((targetType != null)
          && expressionReturnTypes[i] instanceof Class
          && (fragmentType.getFragmentType().getUnderlyingType()
              == ((Class) expressionReturnTypes[i]).getComponentType())
          && ((targetFragment == null) || (targetFragment != null && targetFragment.isNative()))) {
        ExprEvaluator evaluatorFragment;
        final EventPropertyGetter getter = eventTypeStream.getGetter(propertyName);
        final Class returnType =
            JavaClassHelper.getArrayType(eventTypeStream.getPropertyType(propertyName));
        evaluatorFragment =
            new ExprEvaluator() {
              public Object evaluate(
                  EventBean[] eventsPerStream,
                  boolean isNewData,
                  ExprEvaluatorContext exprEvaluatorContext) {
                EventBean streamEvent = eventsPerStream[streamNum];
                if (streamEvent == null) {
                  return null;
                }
                return getter.get(streamEvent);
              }

              public Class getType() {
                return returnType;
              }

              @Override
              public Map<String, Object> getEventType() {
                return null;
              }
            };
        exprEvaluators[i] = evaluatorFragment;
      } else {
        ExprEvaluator evaluatorFragment;
        final EventPropertyGetter getter = eventTypeStream.getGetter(propertyName);
        final Class returnType =
            eventTypeStream.getFragmentType(propertyName).getFragmentType().getUnderlyingType();

        // A match was found, we replace the expression
        evaluatorFragment =
            new ExprEvaluator() {

              public Object evaluate(
                  EventBean[] eventsPerStream,
                  boolean isNewData,
                  ExprEvaluatorContext exprEvaluatorContext) {
                EventBean streamEvent = eventsPerStream[streamNum];
                if (streamEvent == null) {
                  return null;
                }
                return getter.getFragment(streamEvent);
              }

              public Class getType() {
                return returnType;
              }

              public Map<String, Object> getEventType() {
                return null;
              }
            };

        exprEvaluators[i] = evaluatorFragment;
        if (!fragmentType.isIndexed()) {
          expressionReturnTypes[i] = fragmentType.getFragmentType();
        } else {
          expressionReturnTypes[i] = new EventType[] {fragmentType.getFragmentType()};
        }
      }
    }

    // Find if there is any stream expression (ExprStreamNode) :
    // This is a special case for stream selection: select a, b from A as a, B as b
    // We'd like to maintain 'A' and 'B' EventType in the Map type, and 'a' and 'b' EventBeans in
    // the event bean
    for (int i = 0; i < selectionList.size(); i++) {
      if (!(exprEvaluators[i] instanceof ExprStreamUnderlyingNode)) {
        continue;
      }

      ExprStreamUnderlyingNode undNode = (ExprStreamUnderlyingNode) exprEvaluators[i];
      final int streamNum = undNode.getStreamId();
      final Class returnType = undNode.getExprEvaluator().getType();
      EventType eventTypeStream = typeService.getEventTypes()[streamNum];

      // A match was found, we replace the expression
      ExprEvaluator evaluator =
          new ExprEvaluator() {

            public Object evaluate(
                EventBean[] eventsPerStream,
                boolean isNewData,
                ExprEvaluatorContext exprEvaluatorContext) {
              return eventsPerStream[streamNum];
            }

            public Class getType() {
              return returnType;
            }

            public Map<String, Object> getEventType() {
              return null;
            }
          };

      exprEvaluators[i] = evaluator;
      expressionReturnTypes[i] = eventTypeStream;
    }

    // Build event type that reflects all selected properties
    Map<String, Object> selPropertyTypes = new LinkedHashMap<String, Object>();
    int count = 0;
    for (int i = 0; i < exprEvaluators.length; i++) {
      Object expressionReturnType = expressionReturnTypes[count];
      selPropertyTypes.put(columnNames[count], expressionReturnType);
      count++;
    }
    if (!selectedStreams.isEmpty()) {
      for (SelectClauseStreamCompiledSpec element : namedStreams) {
        EventType eventTypeStream = typeService.getEventTypes()[element.getStreamNumber()];
        selPropertyTypes.put(columnNames[count], eventTypeStream);
        count++;
      }
      if (isUsingWildcard && typeService.getEventTypes().length > 1) {
        for (int i = 0; i < typeService.getEventTypes().length; i++) {
          EventType eventTypeStream = typeService.getEventTypes()[i];
          selPropertyTypes.put(columnNames[count], eventTypeStream);
          count++;
        }
      }
    }

    // Handle stream selection
    EventType underlyingEventType = null;
    int underlyingStreamNumber = 0;
    boolean underlyingIsFragmentEvent = false;
    EventPropertyGetter underlyingPropertyEventGetter = null;
    ExprEvaluator underlyingExprEvaluator = null;
    boolean useMapOutput =
        EventRepresentationUtil.isMap(
            annotations, configuration, CreateSchemaDesc.AssignedType.NONE);

    if (!selectedStreams.isEmpty()) {
      // Resolve underlying event type in the case of wildcard or non-named stream select.
      // Determine if the we are considering a tagged event or a stream name.
      if ((isUsingWildcard) || (!unnamedStreams.isEmpty())) {
        if (!unnamedStreams.isEmpty()) {
          if (unnamedStreams.get(0).getStreamSelected() != null) {
            SelectClauseStreamCompiledSpec streamSpec = unnamedStreams.get(0).getStreamSelected();

            // the tag.* syntax for :  select tag.* from pattern [tag = A]
            underlyingStreamNumber = streamSpec.getStreamNumber();
            if (streamSpec.isFragmentEvent()) {
              EventType compositeMap = typeService.getEventTypes()[underlyingStreamNumber];
              FragmentEventType fragment = compositeMap.getFragmentType(streamSpec.getStreamName());
              underlyingEventType = fragment.getFragmentType();
              underlyingIsFragmentEvent = true;
            }
            // the property.* syntax for :  select property.* from A
            else if (streamSpec.isProperty()) {
              String propertyName = streamSpec.getStreamName();
              Class propertyType = streamSpec.getPropertyType();
              int streamNumber = streamSpec.getStreamNumber();

              if (JavaClassHelper.isJavaBuiltinDataType(streamSpec.getPropertyType())) {
                throw new ExprValidationException(
                    "The property wildcard syntax cannot be used on built-in types as returned by property '"
                        + propertyName
                        + "'");
              }

              // create or get an underlying type for that Class
              underlyingEventType =
                  eventAdapterService.addBeanType(
                      propertyType.getName(), propertyType, false, false, false);
              selectExprEventTypeRegistry.add(underlyingEventType);
              underlyingPropertyEventGetter =
                  typeService.getEventTypes()[streamNumber].getGetter(propertyName);
              if (underlyingPropertyEventGetter == null) {
                throw new ExprValidationException(
                    "Unexpected error resolving property getter for property " + propertyName);
              }
            }
            // the stream.* syntax for:  select a.* from A as a
            else {
              underlyingEventType = typeService.getEventTypes()[underlyingStreamNumber];
            }
          }
          // handle case where the unnamed stream is a "transpose" function
          else {
            ExprNode expression =
                unnamedStreams.get(0).getExpressionSelectedAsStream().getSelectExpression();
            Class returnType = expression.getExprEvaluator().getType();
            underlyingEventType =
                eventAdapterService.addBeanType(
                    returnType.getName(), returnType, false, false, false);
            selectExprEventTypeRegistry.add(underlyingEventType);
            underlyingExprEvaluator = expression.getExprEvaluator();
          }
        } else {
          // no un-named stream selectors, but a wildcard was specified
          if (typeService.getEventTypes().length == 1) {
            // not a join, we are using the selected event
            underlyingEventType = typeService.getEventTypes()[0];
            if (underlyingEventType instanceof WrapperEventType) {
              singleStreamWrapper = true;
            }
          } else {
            // For joins, all results are placed in a map with properties for each stream
            underlyingEventType = null;
          }
        }
      }
    }

    SelectExprContext selectExprContext =
        new SelectExprContext(exprEvaluators, columnNames, eventAdapterService);

    if (insertIntoDesc == null) {
      if (!selectedStreams.isEmpty()) {
        EventType resultEventType;
        if (underlyingEventType != null) {
          resultEventType =
              eventAdapterService.createAnonymousWrapperType(
                  statementId + "_wrapout_" + CollectionUtil.toString(assignedTypeNumberStack, "_"),
                  underlyingEventType,
                  selPropertyTypes);
          return new EvalSelectStreamWUnderlying(
              selectExprContext,
              resultEventType,
              namedStreams,
              isUsingWildcard,
              unnamedStreams,
              singleStreamWrapper,
              underlyingIsFragmentEvent,
              underlyingStreamNumber,
              underlyingPropertyEventGetter,
              underlyingExprEvaluator);
        } else {
          resultEventType =
              eventAdapterService.createAnonymousMapType(
                  statementId + "_mapout_" + CollectionUtil.toString(assignedTypeNumberStack, "_"),
                  selPropertyTypes);
          return new EvalSelectStreamNoUnderlyingMap(
              selectExprContext, resultEventType, namedStreams, isUsingWildcard);
        }
      }

      if (isUsingWildcard) {
        EventType resultEventType =
            eventAdapterService.createAnonymousWrapperType(
                statementId
                    + "_wrapoutwild_"
                    + CollectionUtil.toString(assignedTypeNumberStack, "_"),
                eventType,
                selPropertyTypes);
        if (singleStreamWrapper) {
          return new EvalSelectWildcardSSWrapper(selectExprContext, resultEventType);
        }
        if (joinWildcardProcessor == null) {
          return new EvalSelectWildcard(selectExprContext, resultEventType);
        }
        return new EvalSelectWildcardJoin(
            selectExprContext, resultEventType, joinWildcardProcessor);
      }

      EventType resultEventType;
      if (!useMapOutput) {
        resultEventType =
            eventAdapterService.createAnonymousObjectArrayType(
                statementId + "_result_" + CollectionUtil.toString(assignedTypeNumberStack, "_"),
                selPropertyTypes);
      } else {
        resultEventType =
            eventAdapterService.createAnonymousMapType(
                statementId + "_result_" + CollectionUtil.toString(assignedTypeNumberStack, "_"),
                selPropertyTypes);
      }
      if (selectExprContext.getExpressionNodes().length == 0) {
        return new EvalSelectNoWildcardEmptyProps(selectExprContext, resultEventType);
      } else {
        if (!useMapOutput) {
          return new EvalSelectNoWildcardObjectArray(selectExprContext, resultEventType);
        }
        return new EvalSelectNoWildcardMap(selectExprContext, resultEventType);
      }
    }

    EventType vaeInnerEventType = null;
    boolean singleColumnWrapOrBeanCoercion =
        false; // Additional single-column coercion for non-wrapped type done by
    // SelectExprInsertEventBeanFactory
    boolean isRevisionEvent = false;

    try {
      if (!selectedStreams.isEmpty()) {
        EventType resultEventType;
        if (underlyingEventType
            != null) // a single stream was selected via "stream.*" and there is no column name
        {
          // recast as a Map-type
          if (underlyingEventType instanceof MapEventType && targetType instanceof MapEventType) {
            return new EvalSelectStreamWUnderlyingRecastMap(
                selectExprContext,
                selectedStreams.get(0).getStreamSelected().getStreamNumber(),
                targetType);
          }

          // recast as a Object-array-type
          if (underlyingEventType instanceof ObjectArrayEventType
              && targetType instanceof ObjectArrayEventType) {
            return new EvalSelectStreamWUnderlyingRecastObjectArray(
                selectExprContext,
                selectedStreams.get(0).getStreamSelected().getStreamNumber(),
                targetType);
          }

          // recast as a Bean-type
          if (underlyingEventType instanceof BeanEventType && targetType instanceof BeanEventType) {
            SelectClauseExprCompiledSpec expressionAsStream =
                selectedStreams.get(0).getExpressionSelectedAsStream();
            if (expressionAsStream != null) {
              return new EvalSelectStreamWUnderlyingRecastBean(
                  selectExprContext,
                  expressionAsStream,
                  underlyingEventType,
                  targetType,
                  exprEvaluators.length);
            } else {
              return new EvalInsertBeanRecast(
                  targetType,
                  eventAdapterService,
                  selectedStreams.get(0).getStreamSelected().getStreamNumber(),
                  typeService.getEventTypes());
            }
          }

          // wrap if no recast possible
          resultEventType =
              eventAdapterService.addWrapperType(
                  insertIntoDesc.getEventTypeName(),
                  underlyingEventType,
                  selPropertyTypes,
                  false,
                  true);
          return new EvalSelectStreamWUnderlying(
              selectExprContext,
              resultEventType,
              namedStreams,
              isUsingWildcard,
              unnamedStreams,
              singleStreamWrapper,
              underlyingIsFragmentEvent,
              underlyingStreamNumber,
              underlyingPropertyEventGetter,
              underlyingExprEvaluator);
        } else // there are one or more streams selected with column name such as "stream.* as
        // columnOne"
        {
          EventType existingType =
              eventAdapterService.getExistsTypeByName(insertIntoDesc.getEventTypeName());
          if (existingType instanceof BeanEventType) {
            String name = selectedStreams.get(0).getStreamSelected().getStreamName();
            String alias = selectedStreams.get(0).getStreamSelected().getOptionalName();
            String syntaxUsed = name + ".*" + (alias != null ? " as " + alias : "");
            String syntaxInstead = name + (alias != null ? " as " + alias : "");
            throw new ExprValidationException(
                "The '"
                    + syntaxUsed
                    + "' syntax is not allowed when inserting into an existing bean event type, use the '"
                    + syntaxInstead
                    + "' syntax instead");
          }
          if (existingType == null || existingType instanceof MapEventType) {
            resultEventType =
                eventAdapterService.addNestableMapType(
                    insertIntoDesc.getEventTypeName(),
                    selPropertyTypes,
                    null,
                    false,
                    false,
                    false,
                    false,
                    true);
            Set<String> propertiesToUnwrap =
                getEventBeanToObjectProps(selPropertyTypes, resultEventType);
            if (propertiesToUnwrap.isEmpty()) {
              return new EvalSelectStreamNoUnderlyingMap(
                  selectExprContext, resultEventType, namedStreams, isUsingWildcard);
            } else {
              return new EvalSelectStreamNoUndWEventBeanToObj(
                  selectExprContext,
                  resultEventType,
                  namedStreams,
                  isUsingWildcard,
                  propertiesToUnwrap);
            }
          } else {
            Set<String> propertiesToUnwrap =
                getEventBeanToObjectProps(selPropertyTypes, existingType);
            if (propertiesToUnwrap.isEmpty()) {
              return new EvalSelectStreamNoUnderlyingObjectArray(
                  selectExprContext, existingType, namedStreams, isUsingWildcard);
            } else {
              return new EvalSelectStreamNoUndWEventBeanToObjObjArray(
                  selectExprContext,
                  existingType,
                  namedStreams,
                  isUsingWildcard,
                  propertiesToUnwrap);
            }
          }
        }
      }

      ValueAddEventProcessor vaeProcessor =
          valueAddEventService.getValueAddProcessor(insertIntoDesc.getEventTypeName());
      EventType resultEventType;
      if (isUsingWildcard) {
        if (vaeProcessor != null) {
          resultEventType = vaeProcessor.getValueAddEventType();
          isRevisionEvent = true;
          vaeProcessor.validateEventType(eventType);
        } else {
          EventType existingType =
              eventAdapterService.getExistsTypeByName(insertIntoDesc.getEventTypeName());

          SelectExprProcessor existingTypeProcessor = null;
          if (existingType != null) {
            // we may get away with re-casting an existing bean-event-type event to another
            // bean-event-type
            if ((existingType instanceof BeanEventType)
                && (typeService.getEventTypes()[0] instanceof BeanEventType)
                && (selPropertyTypes.isEmpty())) {
              return new EvalInsertBeanRecast(
                  existingType, eventAdapterService, 0, typeService.getEventTypes());
            }
            if ((existingType instanceof WrapperEventType)
                && (typeService.getEventTypes()[0] instanceof BeanEventType)
                && (exprEvaluators.length == 0)) {

              WrapperEventType wrapperType = (WrapperEventType) existingType;
              if (wrapperType.getUnderlyingEventType() instanceof BeanEventType) {
                return new EvalInsertBeanWrapRecast(
                    wrapperType, eventAdapterService, 0, typeService.getEventTypes());
              }
            }

            existingTypeProcessor =
                SelectExprInsertEventBeanFactory.getInsertUnderlyingNonJoin(
                    eventAdapterService,
                    existingType,
                    isUsingWildcard,
                    typeService,
                    exprEvaluators,
                    columnNames,
                    expressionReturnTypes,
                    methodResolutionService.getEngineImportService(),
                    insertIntoDesc,
                    columnNamesAsProvided);
          }

          if (existingTypeProcessor != null) {
            return existingTypeProcessor;
          } else if (existingType != null
              && selPropertyTypes.isEmpty()
              && existingType instanceof MapEventType) {
            resultEventType = existingType;
            return new EvalInsertCoercionMap(resultEventType, eventAdapterService);
          } else if (existingType != null
              && selPropertyTypes.isEmpty()
              && existingType instanceof ObjectArrayEventType) {
            resultEventType = existingType;
            return new EvalInsertCoercionObjectArray(resultEventType, eventAdapterService);
          } else if (selPropertyTypes.isEmpty() && eventType instanceof BeanEventType) {
            BeanEventType beanEventType = (BeanEventType) eventType;
            resultEventType =
                eventAdapterService.addBeanTypeByName(
                    insertIntoDesc.getEventTypeName(), beanEventType.getUnderlyingType(), false);
          } else {
            resultEventType =
                eventAdapterService.addWrapperType(
                    insertIntoDesc.getEventTypeName(), eventType, selPropertyTypes, false, true);
          }
        }

        if (singleStreamWrapper) {
          if (!isRevisionEvent) {
            return new EvalInsertWildcardSSWrapper(selectExprContext, resultEventType);
          } else {
            return new EvalInsertWildcardSSWrapperRevision(
                selectExprContext, resultEventType, vaeProcessor);
          }
        }
        if (joinWildcardProcessor == null) {
          if (!isRevisionEvent) {
            if (resultEventType instanceof WrapperEventType) {
              return new EvalInsertWildcardWrapper(selectExprContext, resultEventType);
            } else {
              return new EvalInsertWildcardBean(selectExprContext, resultEventType);
            }
          } else {
            if (exprEvaluators.length == 0) {
              return new EvalInsertWildcardRevision(
                  selectExprContext, resultEventType, vaeProcessor);
            } else {
              EventType wrappingEventType =
                  eventAdapterService.addWrapperType(
                      insertIntoDesc.getEventTypeName() + "_wrapped",
                      eventType,
                      selPropertyTypes,
                      false,
                      true);
              return new EvalInsertWildcardRevisionWrapper(
                  selectExprContext, resultEventType, vaeProcessor, wrappingEventType);
            }
          }
        } else {
          if (!isRevisionEvent) {
            return new EvalInsertWildcardJoin(
                selectExprContext, resultEventType, joinWildcardProcessor);
          } else {
            return new EvalInsertWildcardJoinRevision(
                selectExprContext, resultEventType, joinWildcardProcessor, vaeProcessor);
          }
        }
      }

      // not using wildcard
      resultEventType = null;
      if ((columnNames.length == 1) && (insertIntoDesc.getColumnNames().size() == 0)) {
        EventType existingType =
            eventAdapterService.getExistsTypeByName(insertIntoDesc.getEventTypeName());
        if (existingType != null) {
          // check if the existing type and new type are compatible
          Object columnOneType = expressionReturnTypes[0];
          if (existingType instanceof WrapperEventType) {
            WrapperEventType wrapperType = (WrapperEventType) existingType;
            // Map and Object both supported
            if (wrapperType.getUnderlyingEventType().getUnderlyingType() == columnOneType) {
              singleColumnWrapOrBeanCoercion = true;
              resultEventType = existingType;
            }
          }
          if ((existingType instanceof BeanEventType) && (columnOneType instanceof Class)) {
            BeanEventType beanType = (BeanEventType) existingType;
            // Map and Object both supported
            if (JavaClassHelper.isSubclassOrImplementsInterface(
                (Class) columnOneType, beanType.getUnderlyingType())) {
              singleColumnWrapOrBeanCoercion = true;
              resultEventType = existingType;
            }
          }
        }
      }
      if (singleColumnWrapOrBeanCoercion) {
        if (!isRevisionEvent) {
          if (resultEventType instanceof WrapperEventType) {
            WrapperEventType wrapper = (WrapperEventType) resultEventType;
            if (wrapper.getUnderlyingEventType() instanceof MapEventType) {
              return new EvalInsertNoWildcardSingleColCoercionMapWrap(
                  selectExprContext, resultEventType);
            } else if (wrapper.getUnderlyingEventType() instanceof ObjectArrayEventType) {
              return new EvalInsertNoWildcardSingleColCoercionObjectArrayWrap(
                  selectExprContext, resultEventType);
            } else if (wrapper.getUnderlyingEventType() instanceof VariantEventType) {
              VariantEventType variantEventType =
                  (VariantEventType) wrapper.getUnderlyingEventType();
              vaeProcessor = valueAddEventService.getValueAddProcessor(variantEventType.getName());
              return new EvalInsertNoWildcardSingleColCoercionBeanWrapVariant(
                  selectExprContext, resultEventType, vaeProcessor);
            } else {
              return new EvalInsertNoWildcardSingleColCoercionBeanWrap(
                  selectExprContext, resultEventType);
            }
          } else {
            if (resultEventType instanceof BeanEventType) {
              return new EvalInsertNoWildcardSingleColCoercionBean(
                  selectExprContext, resultEventType);
            }
          }
        } else {
          if (resultEventType instanceof MapEventType) {
            return new EvalInsertNoWildcardSingleColCoercionRevisionMap(
                selectExprContext, resultEventType, vaeProcessor, vaeInnerEventType);
          } else if (resultEventType instanceof ObjectArrayEventType) {
            return new EvalInsertNoWildcardSingleColCoercionRevisionObjectArray(
                selectExprContext, resultEventType, vaeProcessor, vaeInnerEventType);
          } else if (resultEventType instanceof BeanEventType) {
            return new EvalInsertNoWildcardSingleColCoercionRevisionBean(
                selectExprContext, resultEventType, vaeProcessor, vaeInnerEventType);
          } else {
            return new EvalInsertNoWildcardSingleColCoercionRevisionBeanWrap(
                selectExprContext, resultEventType, vaeProcessor, vaeInnerEventType);
          }
        }
      }
      if (resultEventType == null) {
        if (vaeProcessor != null) {
          // Use an anonymous type if the target is not a variant stream
          if (valueAddEventService.getValueAddProcessor(insertIntoDesc.getEventTypeName())
              == null) {
            resultEventType =
                eventAdapterService.createAnonymousMapType(
                    statementId + "_vae_" + CollectionUtil.toString(assignedTypeNumberStack, "_"),
                    selPropertyTypes);
          } else {
            String statementName = "stmt_" + statementId + "_insert";
            resultEventType =
                eventAdapterService.addNestableMapType(
                    statementName, selPropertyTypes, null, false, false, false, false, true);
          }
        } else {
          EventType existingType =
              eventAdapterService.getExistsTypeByName(insertIntoDesc.getEventTypeName());

          if (existingType == null) {
            // The type may however be an auto-import or fully-qualified class name
            Class clazz = null;
            try {
              clazz = this.methodResolutionService.resolveClass(insertIntoDesc.getEventTypeName());
            } catch (EngineImportException e) {
              log.debug(
                  "Target stream name '"
                      + insertIntoDesc.getEventTypeName()
                      + "' is not resolved as a class name");
            }
            if (clazz != null) {
              existingType =
                  eventAdapterService.addBeanType(clazz.getName(), clazz, false, false, false);
            }
          }

          SelectExprProcessor selectExprInsertEventBean = null;
          if (existingType != null) {
            selectExprInsertEventBean =
                SelectExprInsertEventBeanFactory.getInsertUnderlyingNonJoin(
                    eventAdapterService,
                    existingType,
                    isUsingWildcard,
                    typeService,
                    exprEvaluators,
                    columnNames,
                    expressionReturnTypes,
                    methodResolutionService.getEngineImportService(),
                    insertIntoDesc,
                    columnNamesAsProvided);
          }
          if (selectExprInsertEventBean != null) {
            return selectExprInsertEventBean;
          } else {
            boolean useMap =
                EventRepresentationUtil.isMap(
                    annotations, configuration, CreateSchemaDesc.AssignedType.NONE);
            if (useMap) {
              resultEventType =
                  eventAdapterService.addNestableMapType(
                      insertIntoDesc.getEventTypeName(),
                      selPropertyTypes,
                      null,
                      false,
                      false,
                      false,
                      false,
                      true);
            } else {
              resultEventType =
                  eventAdapterService.addNestableObjectArrayType(
                      insertIntoDesc.getEventTypeName(),
                      selPropertyTypes,
                      null,
                      false,
                      false,
                      false,
                      false,
                      true);
            }
          }
        }
      }
      if (vaeProcessor != null) {
        vaeProcessor.validateEventType(resultEventType);
        vaeInnerEventType = resultEventType;
        resultEventType = vaeProcessor.getValueAddEventType();
        isRevisionEvent = true;
      }

      if (!isRevisionEvent) {
        if (resultEventType instanceof MapEventType) {
          return new EvalInsertNoWildcardMap(selectExprContext, resultEventType);
        } else {
          return new EvalInsertNoWildcardObjectArray(selectExprContext, resultEventType);
        }
      } else {
        return new EvalInsertNoWildcardRevision(
            selectExprContext, resultEventType, vaeProcessor, vaeInnerEventType);
      }
    } catch (EventAdapterException ex) {
      log.debug("Exception provided by event adapter: " + ex.getMessage(), ex);
      throw new ExprValidationException(ex.getMessage(), ex);
    }
  }
Beispiel #11
0
 private void checkInitProperties() {
   if (numPropertiesUnderlyingType != underlyingEventType.getPropertyDescriptors().length) {
     updatePropertySet();
   }
 }
Beispiel #12
0
 public boolean isProperty(String property) {
   return underlyingEventType.isProperty(property) || underlyingMapType.isProperty(property);
 }
Beispiel #13
0
  public EventPropertyGetter getGetter(final String property) {
    EventPropertyGetter cachedGetter = propertyGetterCache.get(property);
    if (cachedGetter != null) {
      return cachedGetter;
    }

    if (underlyingMapType.isProperty(property) && (property.indexOf('?') == -1)) {
      final EventPropertyGetter mapGetter = underlyingMapType.getGetter(property);
      EventPropertyGetter getter =
          new EventPropertyGetter() {
            public Object get(EventBean theEvent) {
              if (!(theEvent instanceof DecoratingEventBean)) {
                throw new PropertyAccessException("Mismatched property getter to EventBean type");
              }
              DecoratingEventBean wrapperEvent = (DecoratingEventBean) theEvent;
              Map map = wrapperEvent.getDecoratingProperties();
              return mapGetter.get(eventAdapterService.adapterForTypedMap(map, underlyingMapType));
            }

            public boolean isExistsProperty(EventBean eventBean) {
              return true; // Property exists as the property is not dynamic (unchecked)
            }

            public Object getFragment(EventBean theEvent) {
              if (!(theEvent instanceof DecoratingEventBean)) {
                throw new PropertyAccessException("Mismatched property getter to EventBean type");
              }
              DecoratingEventBean wrapperEvent = (DecoratingEventBean) theEvent;
              Map map = wrapperEvent.getDecoratingProperties();
              return mapGetter.getFragment(
                  eventAdapterService.adapterForTypedMap(map, underlyingMapType));
            }
          };
      propertyGetterCache.put(property, getter);
      return getter;
    } else if (underlyingEventType.isProperty(property)) {
      EventPropertyGetter getter =
          new EventPropertyGetter() {
            public Object get(EventBean theEvent) {
              if (!(theEvent instanceof DecoratingEventBean)) {
                throw new PropertyAccessException("Mismatched property getter to EventBean type");
              }
              DecoratingEventBean wrapperEvent = (DecoratingEventBean) theEvent;
              EventBean wrappedEvent = wrapperEvent.getUnderlyingEvent();
              if (wrappedEvent == null) {
                return null;
              }

              EventPropertyGetter underlyingGetter = underlyingEventType.getGetter(property);
              return underlyingGetter.get(wrappedEvent);
            }

            public boolean isExistsProperty(EventBean eventBean) {
              return true; // Property exists as the property is not dynamic (unchecked)
            }

            public Object getFragment(EventBean theEvent) {
              if (!(theEvent instanceof DecoratingEventBean)) {
                throw new PropertyAccessException("Mismatched property getter to EventBean type");
              }
              DecoratingEventBean wrapperEvent = (DecoratingEventBean) theEvent;
              EventBean wrappedEvent = wrapperEvent.getUnderlyingEvent();
              if (wrappedEvent == null) {
                return null;
              }

              EventPropertyGetter underlyingGetter = underlyingEventType.getGetter(property);
              return underlyingGetter.getFragment(wrappedEvent);
            }
          };
      propertyGetterCache.put(property, getter);
      return getter;
    } else {
      return null;
    }
  }
  public void testNestedPojo() {
    Pair<String[], Object[]> pair = getTestDefTwo();
    EPServiceProvider epService =
        getEngineInitialized("NestedObjectArr", pair.getFirst(), pair.getSecond());

    String statementText =
        "select "
            + "simple, object, nodefmap, map, "
            + "object.id as a1, nodefmap.key1? as a2, nodefmap.key2? as a3, nodefmap.key3?.key4 as a4, "
            + "map.objectOne as b1, map.simpleOne as b2, map.nodefmapOne.key2? as b3, map.mapOne.simpleTwo? as b4, "
            + "map.objectOne.indexed[1] as c1, map.objectOne.nested.nestedValue as c2,"
            + "map.mapOne.simpleTwo as d1, map.mapOne.objectTwo as d2, map.mapOne.nodefmapTwo as d3, "
            + "map.mapOne.mapTwo as e1, map.mapOne.mapTwo.simpleThree as e2, map.mapOne.mapTwo.objectThree as e3, "
            + "map.mapOne.objectTwo.array[1].mapped('1ma').value as f1, map.mapOne.mapTwo.objectThree.id as f2"
            + " from NestedObjectArr";
    EPStatement statement = epService.getEPAdministrator().createEPL(statementText);
    SupportUpdateListener listener = new SupportUpdateListener();
    statement.addListener(listener);

    Object[] testdata = getTestDataTwo();
    epService.getEPRuntime().sendEvent(testdata, "NestedObjectArr");

    // test all properties exist
    EventBean received = listener.assertOneGetNewAndReset();
    EPAssertionUtil.assertProps(
        received,
        "simple,object,nodefmap,map".split(","),
        new Object[] {"abc", new SupportBean_A("A1"), testdata[2], testdata[3]});
    EPAssertionUtil.assertProps(
        received, "a1,a2,a3,a4".split(","), new Object[] {"A1", "val1", null, null});
    EPAssertionUtil.assertProps(
        received,
        "b1,b2,b3,b4".split(","),
        new Object[] {getNestedKey(testdata, 3, "objectOne"), 10, "val2", 300});
    EPAssertionUtil.assertProps(received, "c1,c2".split(","), new Object[] {2, "nestedValue"});
    EPAssertionUtil.assertProps(
        received,
        "d1,d2,d3".split(","),
        new Object[] {
          300,
          getNestedKey(testdata, 3, "mapOne", "objectTwo"),
          getNestedKey(testdata, 3, "mapOne", "nodefmapTwo")
        });
    EPAssertionUtil.assertProps(
        received,
        "e1,e2,e3".split(","),
        new Object[] {
          getNestedKey(testdata, 3, "mapOne", "mapTwo"), 4000L, new SupportBean_B("B1")
        });
    EPAssertionUtil.assertProps(received, "f1,f2".split(","), new Object[] {"1ma0", "B1"});

    // assert type info
    EPStatement stmt = epService.getEPAdministrator().createEPL(("select * from NestedObjectArr"));
    EventType eventType = stmt.getEventType();

    String[] propertiesReceived = eventType.getPropertyNames();
    String[] propertiesExpected = new String[] {"simple", "object", "nodefmap", "map"};
    EPAssertionUtil.assertEqualsAnyOrder(propertiesReceived, propertiesExpected);
    assertEquals(String.class, eventType.getPropertyType("simple"));
    assertEquals(Map.class, eventType.getPropertyType("map"));
    assertEquals(Map.class, eventType.getPropertyType("nodefmap"));
    assertEquals(SupportBean_A.class, eventType.getPropertyType("object"));

    assertNull(eventType.getPropertyType("map.mapOne.simpleOne"));

    // nested POJO with generic return type
    listener.reset();
    epService
        .getEPAdministrator()
        .getConfiguration()
        .addEventType("MyNested", new String[] {"bean"}, new Object[] {MyNested.class});
    EPStatement stmtTwo =
        epService
            .getEPAdministrator()
            .createEPL("select * from MyNested(bean.insides.anyOf(i=>id = 'A'))");
    stmtTwo.addListener(listener);

    epService
        .getEPRuntime()
        .sendEvent(
            new Object[] {new MyNested(Arrays.asList(new MyInside[] {new MyInside("A")}))},
            "MyNested");
    assertTrue(listener.isInvoked());
  }
  private void runObjectArrInheritanceAssertion(EPServiceProvider epService) {
    SupportUpdateListener listeners[] = new SupportUpdateListener[5];
    String[] statements = {
      "select base as vbase, sub1? as v1, sub2? as v2, suba? as va, subb? as vb from RootEvent", // 0
      "select base as vbase, sub1 as v1, sub2? as v2, suba? as va, subb? as vb from Sub1Event", // 1
      "select base as vbase, sub1? as v1, sub2 as v2, suba? as va, subb? as vb from Sub2Event", // 2
      "select base as vbase, sub1 as v1, sub2? as v2, suba as va, subb? as vb from SubAEvent", // 3
      "select base as vbase, sub1? as v1, sub2? as v2, suba? as va, subb as vb from SubBEvent" // 4
    };
    for (int i = 0; i < statements.length; i++) {
      EPStatement statement = epService.getEPAdministrator().createEPL(statements[i]);
      listeners[i] = new SupportUpdateListener();
      statement.addListener(listeners[i]);
    }
    String[] fields = "vbase,v1,v2,va,vb".split(",");

    EventType type = epService.getEPAdministrator().getConfiguration().getEventType("SubAEvent");
    assertEquals("base", type.getPropertyDescriptors()[0].getPropertyName());
    assertEquals("sub1", type.getPropertyDescriptors()[1].getPropertyName());
    assertEquals("suba", type.getPropertyDescriptors()[2].getPropertyName());
    assertEquals(3, type.getPropertyDescriptors().length);

    type = epService.getEPAdministrator().getConfiguration().getEventType("SubBEvent");
    assertEquals("[base, sub1, suba, subb]", Arrays.toString(type.getPropertyNames()));
    assertEquals(4, type.getPropertyDescriptors().length);

    type = epService.getEPAdministrator().getConfiguration().getEventType("Sub1Event");
    assertEquals("[base, sub1]", Arrays.toString(type.getPropertyNames()));
    assertEquals(2, type.getPropertyDescriptors().length);

    type = epService.getEPAdministrator().getConfiguration().getEventType("Sub2Event");
    assertEquals("[base, sub2]", Arrays.toString(type.getPropertyNames()));
    assertEquals(2, type.getPropertyDescriptors().length);

    epService
        .getEPRuntime()
        .sendEvent(new Object[] {"a", "b", "x"}, "SubAEvent"); // base, sub1, suba
    EPAssertionUtil.assertProps(
        listeners[0].assertOneGetNewAndReset(), fields, new Object[] {"a", "b", null, "x", null});
    assertFalse(listeners[2].isInvoked() || listeners[4].isInvoked());
    EPAssertionUtil.assertProps(
        listeners[1].assertOneGetNewAndReset(), fields, new Object[] {"a", "b", null, "x", null});
    EPAssertionUtil.assertProps(
        listeners[3].assertOneGetNewAndReset(), fields, new Object[] {"a", "b", null, "x", null});

    epService.getEPRuntime().sendEvent(new Object[] {"f1", "f2", "f4"}, "SubAEvent");
    EPAssertionUtil.assertProps(
        listeners[0].assertOneGetNewAndReset(),
        fields,
        new Object[] {"f1", "f2", null, "f4", null});
    assertFalse(listeners[2].isInvoked() || listeners[4].isInvoked());
    EPAssertionUtil.assertProps(
        listeners[1].assertOneGetNewAndReset(),
        fields,
        new Object[] {"f1", "f2", null, "f4", null});
    EPAssertionUtil.assertProps(
        listeners[3].assertOneGetNewAndReset(),
        fields,
        new Object[] {"f1", "f2", null, "f4", null});

    epService.getEPRuntime().sendEvent(new Object[] {"XBASE", "X1", "X2", "XY"}, "SubBEvent");
    Object[] values = new Object[] {"XBASE", "X1", null, "X2", "XY"};
    EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fields, values);
    assertFalse(listeners[2].isInvoked());
    EPAssertionUtil.assertProps(listeners[1].assertOneGetNewAndReset(), fields, values);
    EPAssertionUtil.assertProps(listeners[3].assertOneGetNewAndReset(), fields, values);
    EPAssertionUtil.assertProps(listeners[4].assertOneGetNewAndReset(), fields, values);

    epService.getEPRuntime().sendEvent(new Object[] {"YBASE", "Y1"}, "Sub1Event");
    values = new Object[] {"YBASE", "Y1", null, null, null};
    EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fields, values);
    assertFalse(listeners[2].isInvoked() || listeners[3].isInvoked() || listeners[4].isInvoked());
    EPAssertionUtil.assertProps(listeners[1].assertOneGetNewAndReset(), fields, values);

    epService.getEPRuntime().sendEvent(new Object[] {"YBASE", "Y2"}, "Sub2Event");
    values = new Object[] {"YBASE", null, "Y2", null, null};
    EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fields, values);
    assertFalse(listeners[1].isInvoked() || listeners[3].isInvoked() || listeners[4].isInvoked());
    EPAssertionUtil.assertProps(listeners[2].assertOneGetNewAndReset(), fields, values);

    epService.getEPRuntime().sendEvent(new Object[] {"ZBASE"}, "RootEvent");
    values = new Object[] {"ZBASE", null, null, null, null};
    EPAssertionUtil.assertProps(listeners[0].assertOneGetNewAndReset(), fields, values);
    assertFalse(
        listeners[1].isInvoked()
            || listeners[2].isInvoked()
            || listeners[3].isInvoked()
            || listeners[4].isInvoked());

    // try property not available
    try {
      epService.getEPAdministrator().createEPL("select suba from Sub1Event");
      fail();
    } catch (EPStatementException ex) {
      assertEquals(
          "Error starting statement: Failed to validate select-clause expression 'suba': Property named 'suba' is not valid in any stream (did you mean 'sub1'?) [select suba from Sub1Event]",
          ex.getMessage());
    }

    // try supertype not exists
    try {
      epService
          .getEPAdministrator()
          .getConfiguration()
          .addEventType("Sub1Event", makeMap(""), new String[] {"doodle"});
      fail();
    } catch (ConfigurationException ex) {
      assertEquals("Supertype by name 'doodle' could not be found", ex.getMessage());
    }
  }