protected void enableEngineAction(
      String streamName,
      EngineActionType engineActionType,
      Map<String, Object> engineActionParams,
      StreamOperationServiceWithoutMetrics streamOperationService) {

    if (!streamStatusDao.isEngineActionEnabled(streamName, engineActionType)) {

      String engineActionQueryId =
          siddhiManager.addQuery(
              QueryFactory.createQuery()
                  .from(QueryFactory.inputStream(streamName))
                  .insertInto(STREAMING.STATS_NAMES.SINK_STREAM_PREFIX.concat(streamName)));

      BaseEngineAction engineAction = null;

      if (engineActionType == EngineActionType.FIRE_RULES) {

        engineAction =
            new DroolsEngineAction(
                droolsConnectionContainer,
                engineActionParams,
                siddhiManager,
                streamOperationService);
      }

      siddhiManager.addCallback(
          engineActionQueryId,
          callbackService.addEngineCallback(streamName, engineActionType, engineAction));

      streamStatusDao.enableEngineAction(
          streamName, engineActionType, engineActionParams, engineActionQueryId);
    }
  }
  public static void main(String[] args) throws Exception {

    StreamDefinition streamDefinition = new StreamDefinition();
    streamDefinition.setStreamId("TestStream");
    streamDefinition.addAttribute("att1", StreamDefinition.Type.LONG);
    streamDefinition.addAttribute("att2", StreamDefinition.Type.FLOAT);
    streamDefinition.addAttribute("att3", StreamDefinition.Type.STRING);
    streamDefinition.addAttribute("att4", StreamDefinition.Type.INT);

    siddhiManager = new SiddhiManager();
    String attributeStr =
        streamDefinition.getAttributeList().get(0).getName()
            + " "
            + streamDefinition.getAttributeList().get(0).getType().toString().toLowerCase();
    for (int i = 1; i < streamDefinition.getAttributeList().size(); i++) {
      attributeStr +=
          ","
              + streamDefinition.getAttributeList().get(i).getName()
              + " "
              + streamDefinition.getAttributeList().get(i).getType().toString().toLowerCase();
    }

    siddhiManager.defineStream(
        "define stream " + streamDefinition.getStreamId() + " ( " + attributeStr + " )");
    siddhiManager.addQuery(
        "from  TestStream " + "select att1, att2, att3, att4 " + "insert into StockQuote ;");
    siddhiManager.addCallback(
        "StockQuote",
        new org.wso2.siddhi.core.stream.output.StreamCallback() {
          @Override
          public void receive(Event[] events) {
            EventPrinter.print(events);
          }
        });

    ReorderingEventServer eventServer =
        new ReorderingEventServer(
            new EventServerConfig(7612),
            streamDefinition,
            new org.wso2.event.server.StreamCallback() {
              @Override
              public void receive(Object[] event) {
                InputHandler inputHandler = siddhiManager.getInputHandler("TestStream");
                if (inputHandler != null) {
                  try {
                    inputHandler.send(event);
                  } catch (InterruptedException e) {
                    e.printStackTrace();
                  }
                } else {
                  System.out.println("Could not retrieve stream handler");
                  throw new RuntimeException("Could not retrieve stream handler");
                }
              }
            });

    eventServer.start();

    Thread.sleep(10000);
  }
  /** Bolt get saved and reloaded, this to redo the configurations. */
  private void init() {
    siddhiManager = new SiddhiManager(new SiddhiConfiguration());
    log = Logger.getLogger(SiddhiBolt.class);

    if (definitions != null) {
      for (String definition : definitions) {

        if (definition.contains("define stream")) {
          siddhiManager.defineStream(definition);
        } else if (definition.contains("define partition")) {
          siddhiManager.definePartition(definition);
        } else {
          throw new RuntimeException("Invalid definition : " + definition);
        }
      }
    }

    if (queries != null) {

      for (String query : queries) {
        siddhiManager.addQuery(query);
      }
    }

    for (final String streamId : exportedStreamIds) {
      log.info("Adding callback for stream - " + streamId);
      siddhiManager.addCallback(
          streamId,
          new StreamCallback() {
            @Override
            public void receive(Event[] events) {

              for (Event event : events) {
                collector.emit(event.getStreamId(), Arrays.asList(event.getData()));
                if (log.isDebugEnabled()) {
                  log.debug(
                      "Sending Processed event : " + event.getStreamId() + "=>" + event.toString());
                }
              }
            }
          });
    }
  }
  public void enableAction(String streamName, StreamAction action) {

    if (streamStatusDao.getEnabledActions(streamName).size() == 0) {
      String actionQueryId =
          siddhiManager.addQuery(
              QueryFactory.createQuery()
                  .from(QueryFactory.inputStream(streamName))
                  .insertInto(STREAMING.STATS_NAMES.SINK_STREAM_PREFIX.concat(streamName)));

      streamStatusDao.setActionQuery(streamName, actionQueryId);

      String groupId = null;

      if (configurationContext != null && configurationContext.isClusteringEnabled()) {
        groupId = configurationContext.getGroupId();
      }

      siddhiManager.addCallback(
          actionQueryId,
          callbackService.add(streamName, streamStatusDao.getEnabledActions(streamName), groupId));
    }

    streamStatusDao.enableAction(streamName, action);
  }
  @Test
  public void testPatternWithinQuery1() throws InterruptedException {
    log.info("testPatternWithin1 - OUT 1");

    SiddhiManager siddhiManager = new SiddhiManager();

    siddhiManager.defineStream(
        QueryFactory.createStreamDefinition()
            .name("Stream1")
            .attribute("symbol", Attribute.Type.STRING)
            .attribute("price", Attribute.Type.FLOAT)
            .attribute("volume", Attribute.Type.INT));
    siddhiManager.defineStream(
        QueryFactory.createStreamDefinition()
            .name("Stream2")
            .attribute("symbol", Attribute.Type.STRING)
            .attribute("price", Attribute.Type.FLOAT)
            .attribute("volume", Attribute.Type.INT));

    Query query = QueryFactory.createQuery();
    query.from(
        QueryFactory.patternStream(
            Pattern.followedBy(
                Pattern.every(
                    QueryFactory.inputStream("e1", "Stream1")
                        .filter(
                            Condition.compare(
                                Expression.variable("price"),
                                Condition.Operator.GREATER_THAN,
                                Expression.value(20)))),
                QueryFactory.inputStream("e2", "Stream2")
                    .filter(
                        Condition.compare(
                            Expression.variable("price"),
                            Condition.Operator.GREATER_THAN,
                            Expression.variable("e1", "price")))),
            Expression.value(1000)));

    query.insertInto("OutStream");
    query.project(
        QueryFactory.outputProjector()
            .project("symbol1", Expression.variable("e1", "symbol"))
            .project("symbol2", Expression.variable("e2", "symbol")));

    String queryReference = siddhiManager.addQuery(query);
    siddhiManager.addCallback(
        queryReference,
        new QueryCallback() {
          @Override
          public void receive(long timeStamp, Event[] inEvents, Event[] removeEvents) {
            EventPrinter.print(timeStamp, inEvents, removeEvents);
            if (eventCount == 0) {
              Assert.assertArrayEquals(new Object[] {"GOOG", "IBM"}, inEvents[0].getData());
            } else {
              Assert.fail();
            }
            eventCount++;
            eventArrived = true;
          }
        });
    InputHandler stream1 = siddhiManager.getInputHandler("Stream1");
    InputHandler stream2 = siddhiManager.getInputHandler("Stream2");
    stream1.send(new Object[] {"WSO2", 55.6f, 100});
    Thread.sleep(1500);
    stream1.send(new Object[] {"GOOG", 54f, 100});
    Thread.sleep(500);
    stream2.send(new Object[] {"IBM", 55.7f, 100});
    Thread.sleep(500);

    siddhiManager.shutdown();

    Assert.assertEquals("Number of success events", 1, eventCount);
    Assert.assertEquals("Event arrived", true, eventArrived);
  }
  public void addExecutionPlanConfiguration(
      ExecutionPlanConfiguration executionPlanConfiguration, AxisConfiguration axisConfiguration)
      throws ExecutionPlanDependencyValidationException, ExecutionPlanConfigurationException,
          ServiceDependencyValidationException {
    int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
    Map<String, ExecutionPlan> tenantExecutionPlans = tenantSpecificExecutionPlans.get(tenantId);
    if (tenantExecutionPlans == null) {
      tenantExecutionPlans = new ConcurrentHashMap<String, ExecutionPlan>();
      tenantSpecificExecutionPlans.put(tenantId, tenantExecutionPlans);
    } else if (tenantExecutionPlans.get(executionPlanConfiguration.getName()) != null) {
      // if an execution plan with the same name already exists, we are not going to override it
      // with this plan.
      throw new ExecutionPlanConfigurationException(
          "Execution plan with the same name already exists. Please remove it and retry.");
    }

    // This iteration exists only as a check. Actual usage of imported stream configs is further
    // down
    for (StreamConfiguration streamConfiguration :
        executionPlanConfiguration.getImportedStreams()) {
      try {
        StreamDefinition streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(streamConfiguration.getStreamId(), tenantId);
        if (streamDefinition == null) {
          throw new ExecutionPlanDependencyValidationException(
              streamConfiguration.getStreamId(),
              "Imported Stream " + streamConfiguration.getStreamId() + " does not exist");
        }
      } catch (EventStreamConfigurationException e) {
        throw new ExecutionPlanConfigurationException(
            "Error in retrieving stream ID : " + streamConfiguration.getStreamId());
      }
    }

    // This iteration exists only as a check. Actual usage of exported stream configs is further
    // down
    for (StreamConfiguration streamConfiguration :
        executionPlanConfiguration.getExportedStreams()) {
      try {
        StreamDefinition streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(streamConfiguration.getStreamId(), tenantId);
        if (streamDefinition == null) {
          throw new ExecutionPlanDependencyValidationException(
              streamConfiguration.getStreamId(),
              "Exported Stream " + streamConfiguration.getStreamId() + " does not exist");
        }
      } catch (EventStreamConfigurationException e) {
        throw new ExecutionPlanConfigurationException(
            "Error in retrieving stream ID : " + streamConfiguration.getStreamId());
      }
    }

    Map<String, InputHandler> inputHandlerMap =
        new ConcurrentHashMap<String, InputHandler>(
            executionPlanConfiguration.getImportedStreams().size());

    SiddhiConfiguration siddhiConfig =
        getSiddhiConfigurationFor(executionPlanConfiguration, tenantId);
    SiddhiManager siddhiManager =
        getSiddhiManagerFor(executionPlanConfiguration, siddhiConfig, inputHandlerMap);

    for (StreamConfiguration importedStreamConfiguration :
        executionPlanConfiguration.getImportedStreams()) {
      org.wso2.siddhi.query.api.definition.StreamDefinition siddhiStreamDefinition =
          new org.wso2.siddhi.query.api.definition.StreamDefinition();
      siddhiStreamDefinition.name(importedStreamConfiguration.getSiddhiStreamName());
      StreamDefinition streamDefinition = null;
      try {
        streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(importedStreamConfiguration.getStreamId(), tenantId);

        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getMetaData(),
            EventProcessorConstants.META + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getCorrelationData(),
            EventProcessorConstants.CORRELATION + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(siddhiStreamDefinition, streamDefinition.getPayloadData(), "");
        InputHandler inputHandler = siddhiManager.defineStream(siddhiStreamDefinition);
        inputHandlerMap.put(streamDefinition.getStreamId(), inputHandler);
        log.debug("input handler created for " + siddhiStreamDefinition.getStreamId());
      } catch (EventStreamConfigurationException e) {
        // ignored as this will not happen
      }
    }

    for (StreamConfiguration exportedStreamConfiguration :
        executionPlanConfiguration.getExportedStreams()) {
      org.wso2.siddhi.query.api.definition.StreamDefinition siddhiStreamDefinition =
          new org.wso2.siddhi.query.api.definition.StreamDefinition();
      siddhiStreamDefinition.name(exportedStreamConfiguration.getSiddhiStreamName());
      StreamDefinition streamDefinition = null;
      try {
        streamDefinition =
            EventProcessorValueHolder.getEventStreamService()
                .getStreamDefinition(exportedStreamConfiguration.getStreamId(), tenantId);

        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getMetaData(),
            EventProcessorConstants.META + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(
            siddhiStreamDefinition,
            streamDefinition.getCorrelationData(),
            EventProcessorConstants.CORRELATION + EventProcessorConstants.ATTRIBUTE_SEPARATOR);
        populateAttributes(siddhiStreamDefinition, streamDefinition.getPayloadData(), "");
        siddhiManager.defineStream(siddhiStreamDefinition);
        log.debug("stream defined for " + siddhiStreamDefinition.getStreamId());
      } catch (EventStreamConfigurationException e) {
        // ignored as this will not happen
      }
    }

    HAManager haManager = null;
    String isDistributedProcessingEnabledString =
        executionPlanConfiguration
            .getSiddhiConfigurationProperties()
            .get(EventProcessorConstants.SIDDHI_DISTRIBUTED_PROCESSING);
    if (isDistributedProcessingEnabledString != null
        && isDistributedProcessingEnabledString.equalsIgnoreCase("RedundantNode")) {
      haManager =
          new HAManager(
              EventProcessorValueHolder.getHazelcastInstance(),
              executionPlanConfiguration.getName(),
              tenantId,
              siddhiManager,
              inputHandlerMap.size(),
              currentCepMembershipInfo);
    }

    try {
      siddhiManager.addExecutionPlan(executionPlanConfiguration.getQueryExpressions());
    } catch (Exception e) {
      throw new ExecutionPlanConfigurationException(
          "Invalid query specified, " + e.getMessage(), e);
    }

    ExecutionPlan executionPlan =
        new ExecutionPlan(
            executionPlanConfiguration.getName(),
            siddhiManager,
            executionPlanConfiguration,
            haManager);
    tenantExecutionPlans.put(executionPlanConfiguration.getName(), executionPlan);

    // subscribe output to junction
    SindhiStormOutputEventListener stormOutputListener = null;
    if (isRunningOnStorm) {
      stormOutputListener =
          new SindhiStormOutputEventListener(executionPlanConfiguration, tenantId);
    }
    for (StreamConfiguration exportedStreamConfiguration :
        executionPlanConfiguration.getExportedStreams()) {

      SiddhiOutputStreamListener streamCallback;

      if (haManager != null) {
        streamCallback =
            new SiddhiHAOutputStreamListener(
                exportedStreamConfiguration.getSiddhiStreamName(),
                exportedStreamConfiguration.getStreamId(),
                executionPlanConfiguration,
                tenantId);
        haManager.addStreamCallback((SiddhiHAOutputStreamListener) streamCallback);
      } else {
        streamCallback =
            new SiddhiOutputStreamListener(
                exportedStreamConfiguration.getSiddhiStreamName(),
                exportedStreamConfiguration.getStreamId(),
                executionPlanConfiguration,
                tenantId);

        if (isRunningOnStorm) {
          stormOutputListener.registerOutputStreamListener(
              exportedStreamConfiguration.getSiddhiStreamName(), streamCallback);
        }
      }
      siddhiManager.addCallback(exportedStreamConfiguration.getSiddhiStreamName(), streamCallback);
      try {
        EventProcessorValueHolder.getEventStreamService().subscribe(streamCallback, tenantId);
      } catch (EventStreamConfigurationException e) {
        // ignored as this will never happen
      }
      executionPlan.addProducer(streamCallback);
    }

    // subscribe input to junction
    for (StreamConfiguration importedStreamConfiguration :
        executionPlanConfiguration.getImportedStreams()) {
      InputHandler inputHandler = inputHandlerMap.get(importedStreamConfiguration.getStreamId());

      AbstractSiddhiInputEventDispatcher eventDispatcher = null;
      if (haManager != null) {
        eventDispatcher =
            new SiddhiHAInputEventDispatcher(
                importedStreamConfiguration.getStreamId(),
                inputHandler,
                executionPlanConfiguration,
                tenantId,
                haManager.getProcessThreadPoolExecutor(),
                haManager.getThreadBarrier());
        haManager.addInputEventDispatcher(
            importedStreamConfiguration.getStreamId(),
            (SiddhiHAInputEventDispatcher) eventDispatcher);
      } else if (isRunningOnStorm) {
        StreamDefinition streamDefinition = null;
        try {
          streamDefinition =
              EventProcessorValueHolder.getEventStreamService()
                  .getStreamDefinition(importedStreamConfiguration.getStreamId(), tenantId);
        } catch (EventStreamConfigurationException e) {
          // Ignore as this would never happen
        }
        eventDispatcher =
            new SiddhiStormInputEventDispatcher(
                streamDefinition,
                importedStreamConfiguration.getSiddhiStreamName(),
                executionPlanConfiguration,
                tenantId);
      } else {
        eventDispatcher =
            new SiddhiInputEventDispatcher(
                importedStreamConfiguration.getStreamId(),
                inputHandler,
                executionPlanConfiguration,
                tenantId);
      }

      try {
        EventProcessorValueHolder.getEventStreamService().subscribe(eventDispatcher, tenantId);
        executionPlan.addConsumer(eventDispatcher);

      } catch (EventStreamConfigurationException e) {
        // ignored as this will never happen
      }
    }

    if (haManager != null) {
      haManager.init();
    }
  }