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());
  }
  public void testObjectArrayTypeUpdate() {
    Configuration configuration = SupportConfigFactory.getConfiguration();
    configuration
        .getEngineDefaults()
        .getEventMeta()
        .setDefaultEventRepresentation(Configuration.EventRepresentation.OBJECTARRAY);

    String[] names = {"base1", "base2"};
    Object[] types = {String.class, makeMap(new Object[][] {{"n1", int.class}})};
    configuration.addEventType("MyOAEvent", names, types);

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

    EPStatement statementOne =
        epService
            .getEPAdministrator()
            .createEPL(
                "select base1 as v1, base2.n1 as v2, base3? as v3, base2.n2? as v4 from MyOAEvent");
    assertEquals(Object[].class, statementOne.getEventType().getUnderlyingType());
    EPStatement statementOneSelectAll =
        epService.getEPAdministrator().createEPL("select * from MyOAEvent");
    assertEquals(
        "[base1, base2]", Arrays.toString(statementOneSelectAll.getEventType().getPropertyNames()));
    SupportUpdateListener listenerOne = new SupportUpdateListener();
    statementOne.addListener(listenerOne);
    String[] fields = "v1,v2,v3,v4".split(",");

    epService
        .getEPRuntime()
        .sendEvent(new Object[] {"abc", makeMap(new Object[][] {{"n1", 10}}), ""}, "MyOAEvent");
    EPAssertionUtil.assertProps(
        listenerOne.assertOneGetNewAndReset(), fields, new Object[] {"abc", 10, null, null});

    // update type
    String[] namesNew = {"base3", "base2"};
    Object[] typesNew = new Object[] {Long.class, makeMap(new Object[][] {{"n2", String.class}})};
    epService
        .getEPAdministrator()
        .getConfiguration()
        .updateObjectArrayEventType("MyOAEvent", namesNew, typesNew);

    EPStatement statementTwo =
        epService
            .getEPAdministrator()
            .createEPL(
                "select base1 as v1, base2.n1 as v2, base3 as v3, base2.n2 as v4 from MyOAEvent");
    EPStatement statementTwoSelectAll =
        epService.getEPAdministrator().createEPL("select * from MyOAEvent");
    SupportUpdateListener listenerTwo = new SupportUpdateListener();
    statementTwo.addListener(listenerTwo);

    epService
        .getEPRuntime()
        .sendEvent(
            new Object[] {"def", makeMap(new Object[][] {{"n1", 9}, {"n2", "xyz"}}), 20L},
            "MyOAEvent");
    EPAssertionUtil.assertProps(
        listenerOne.assertOneGetNewAndReset(), fields, new Object[] {"def", 9, 20L, "xyz"});
    EPAssertionUtil.assertProps(
        listenerTwo.assertOneGetNewAndReset(), fields, new Object[] {"def", 9, 20L, "xyz"});

    // assert event type
    assertEquals(
        "[base1, base2, base3]",
        Arrays.toString(statementOneSelectAll.getEventType().getPropertyNames()));
    assertEquals(
        "[base1, base2, base3]",
        Arrays.toString(statementTwoSelectAll.getEventType().getPropertyNames()));

    EPAssertionUtil.assertEqualsAnyOrder(
        new Object[] {
          new EventPropertyDescriptor("base3", Long.class, null, false, false, false, false, false),
          new EventPropertyDescriptor("base2", Map.class, null, false, false, false, true, false),
          new EventPropertyDescriptor(
              "base1", String.class, null, false, false, false, false, false),
        },
        statementTwoSelectAll.getEventType().getPropertyDescriptors());

    try {
      epService
          .getEPAdministrator()
          .getConfiguration()
          .updateObjectArrayEventType("dummy", new String[0], new Object[0]);
      fail();
    } catch (ConfigurationException ex) {
      assertEquals(
          "Error updating Object-array event type: Event type named 'dummy' has not been declared",
          ex.getMessage());
    }

    epService
        .getEPAdministrator()
        .getConfiguration()
        .addEventType("SupportBean", SupportBean.class);
    try {
      epService
          .getEPAdministrator()
          .getConfiguration()
          .updateObjectArrayEventType("SupportBean", new String[0], new Object[0]);
      fail();
    } catch (ConfigurationException ex) {
      assertEquals(
          "Error updating Object-array event type: Event type by name 'SupportBean' is not an Object-array event type",
          ex.getMessage());
    }

    if (InstrumentationHelper.ENABLED) {
      InstrumentationHelper.endTest();
    }
  }
  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());
    }
  }