diff --git a/pom.xml b/pom.xml
index 828a419fc5..9843b35c0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -298,6 +298,11 @@
io.siddhi.distribution.store.api.rest
${io.siddhi.distribution.version}
+
+ io.siddhi.distribution
+ io.siddhi.parser
+ ${io.siddhi.distribution.version}
+
io.siddhi.distribution
io.siddhi.distribution.msf4j.interceptor.common.feature
@@ -317,6 +322,12 @@
${io.siddhi.distribution.version}
zip
+
+ io.siddhi.distribution
+ io.siddhi.parser.service.feature
+ ${io.siddhi.distribution.version}
+ zip
+
io.siddhi.distribution
io.siddhi.distribution.store.api.rest.feature
@@ -1103,8 +1114,8 @@
5.1.0-SNAPSHOT
- 5.1.0
- 5.1.0
+ 5.1.2
+ 5.1.2
[5.0.0, 6.0.0)
6.1.30
[6.1.0, 6.2.0)
@@ -1123,8 +1134,8 @@
1.5.10.wso2v1
- 5.2.8
- 5.2.8
+ 5.2.10
+ 5.2.10
6.0.295
3.0.3
5.2.2
diff --git a/resources/carbon-home/bin/runner.bat b/resources/carbon-home/bin/runner.bat
index 3492444fde..603e81e766 100644
--- a/resources/carbon-home/bin/runner.bat
+++ b/resources/carbon-home/bin/runner.bat
@@ -53,6 +53,9 @@ rem find CARBON_HOME if it does not exist due to either an invalid value passed
rem by the user or the %0 problem on Windows 9x
if not exist "%CARBON_HOME%\bin\version.txt" goto noServerHome
+REM Installing jars
+java -cp ".\*;..\bin\tools\*" -Dwso2.carbon.tool="install-jars" org.wso2.carbon.tools.CarbonToolExecutor "%CURRENT_DIR%"
+
goto startServer
:noServerHome
diff --git a/resources/carbon-home/bin/runner.sh b/resources/carbon-home/bin/runner.sh
index 4aa9201580..2bc2433b9a 100755
--- a/resources/carbon-home/bin/runner.sh
+++ b/resources/carbon-home/bin/runner.sh
@@ -55,6 +55,9 @@ PRGDIR=`dirname "$PRG"`
[ -z "$RUNTIME_HOME" ] && RUNTIME_HOME=`cd "$PRGDIR/../wso2/runner" ; pwd`
+# Installing jars
+java -cp "../bin/tools/*" -Dwso2.carbon.tool="install-jars" org.wso2.carbon.tools.CarbonToolExecutor "$CARBON_HOME"
+
###########################################################################
NAME=start-runner
# Daemon name, where is the actual executable
diff --git a/resources/carbon-home/bin/tooling.bat b/resources/carbon-home/bin/tooling.bat
index 224add96b7..d5d4dccb1d 100644
--- a/resources/carbon-home/bin/tooling.bat
+++ b/resources/carbon-home/bin/tooling.bat
@@ -53,6 +53,9 @@ rem find CARBON_HOME if it does not exist due to either an invalid value passed
rem by the user or the %0 problem on Windows 9x
if not exist "%CARBON_HOME%\bin\version.txt" goto noServerHome
+REM Installing jars
+java -cp ".\*;..\bin\tools\*" -Dwso2.carbon.tool="install-jars" org.wso2.carbon.tools.CarbonToolExecutor "%CURRENT_DIR%"
+
goto startServer
:noServerHome
diff --git a/resources/carbon-home/bin/tooling.sh b/resources/carbon-home/bin/tooling.sh
index f1e0a64652..ae40a2765b 100755
--- a/resources/carbon-home/bin/tooling.sh
+++ b/resources/carbon-home/bin/tooling.sh
@@ -55,6 +55,9 @@ PRGDIR=`dirname "$PRG"`
[ -z "$RUNTIME_HOME" ] && RUNTIME_HOME=`cd "$PRGDIR/../wso2/tooling" ; pwd`
+# Installing jars
+java -cp "../bin/tools/*" -Dwso2.carbon.tool="install-jars" org.wso2.carbon.tools.CarbonToolExecutor "$CARBON_HOME"
+
###########################################################################
NAME=start-tooling
# Daemon name, where is the actual executable
diff --git a/runner/components/io.siddhi.distribution.common/src/main/java/io/siddhi/distribution/common/common/utils/config/FileConfigManager.java b/runner/components/io.siddhi.distribution.common/src/main/java/io/siddhi/distribution/common/common/utils/config/FileConfigManager.java
index 835e656f7d..1bd6434618 100644
--- a/runner/components/io.siddhi.distribution.common/src/main/java/io/siddhi/distribution/common/common/utils/config/FileConfigManager.java
+++ b/runner/components/io.siddhi.distribution.common/src/main/java/io/siddhi/distribution/common/common/utils/config/FileConfigManager.java
@@ -42,26 +42,22 @@ public class FileConfigManager implements ConfigManager {
private static final Logger LOGGER = LoggerFactory.getLogger(FileConfigManager.class);
private ConfigProvider configProvider;
- private List extensions;
- private List references;
- private Map properties;
-
- public FileConfigManager(ConfigProvider configProvider) {
- this.configProvider = configProvider;
- }
+ private List extensions = new ArrayList<>();
+ private List references = new ArrayList<>();
+ private Map properties = new HashMap<>();
public void init() {
if (configProvider != null) {
initialiseExtensions();
initialiseReferences();
initaliseProperties();
- } else {
- extensions = new ArrayList<>();
- references = new ArrayList<>();
- properties = new HashMap<>();
}
}
+ public FileConfigManager(ConfigProvider configProvider) {
+ this.configProvider = configProvider;
+ }
+
private void initaliseProperties() {
// load siddhi properties
try {
@@ -90,7 +86,6 @@ private void initaliseProperties() {
}
} catch (ConfigurationException e) {
LOGGER.error("Could not initiate the siddhi configuration object, " + e.getMessage(), e);
- this.properties = new HashMap<>();
}
}
@@ -111,7 +106,6 @@ private void initialiseReferences() {
}
} catch (Exception e) {
LOGGER.error("Could not initiate the refs configuration object, " + e.getMessage(), e);
- this.references = new ArrayList<>();
}
}
@@ -133,7 +127,6 @@ private void initialiseExtensions() {
}
} catch (Exception e) {
LOGGER.error("Could not initiate the extensions configuration object, " + e.getMessage(), e);
- this.extensions = new ArrayList<>();
}
}
diff --git a/runner/components/io.siddhi.parser/findbugs-exclude.xml b/runner/components/io.siddhi.parser/findbugs-exclude.xml
new file mode 100644
index 0000000000..6e81a77f6e
--- /dev/null
+++ b/runner/components/io.siddhi.parser/findbugs-exclude.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/runner/components/io.siddhi.parser/pom.xml b/runner/components/io.siddhi.parser/pom.xml
new file mode 100644
index 0000000000..0a4b53e095
--- /dev/null
+++ b/runner/components/io.siddhi.parser/pom.xml
@@ -0,0 +1,203 @@
+
+
+
+
+
+ io.siddhi.distribution
+ io.siddhi.distribution.parent
+ 5.1.0-SNAPSHOT
+ ../../../pom.xml
+
+
+ 4.0.0
+ io.siddhi.parser
+ bundle
+
+ Siddhi Parser
+ http://wso2.org
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+ javax.servlet
+ javax.servlet-api
+
+
+ com.fasterxml.jackson.jaxrs
+ jackson-jaxrs-json-provider
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-joda
+
+
+
+
+ io.siddhi
+ siddhi-query-api
+ ${siddhi.version}
+
+
+ io.siddhi
+ siddhi-core
+ ${siddhi.version}
+
+
+ io.siddhi
+ siddhi-query-compiler
+ ${siddhi.version}
+
+
+ io.siddhi
+ siddhi-annotations
+ ${siddhi.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+ org.slf4j
+ slf4j-log4j12
+ ${slf4j.version}
+
+
+ org.wso2.msf4j
+ msf4j-core
+
+
+ io.siddhi.distribution
+ io.siddhi.distribution.common
+
+
+ io.siddhi.distribution
+ io.siddhi.distribution.msf4j.interceptor.common
+
+
+ org.testng
+ testng
+ ${testng.version}
+ test
+
+
+ org.testcontainers
+ testcontainers
+ ${org.testcontainers.version}
+ test
+
+
+ io.nats
+ java-nats-streaming
+ ${io.nats.version}
+ test
+
+
+ io.siddhi.extension.io.http
+ siddhi-io-http
+ test
+
+
+ io.siddhi.extension.io.nats
+ siddhi-io-nats
+ test
+
+
+ io.siddhi.extension.map.json
+ siddhi-map-json
+ test
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 1.9.1
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${project.build.outputDirectory}/io/siddhi/parser/core
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ default-instrument
+
+ instrument
+
+
+
+ default-restore-instrumented-classes
+
+ restore-instrumented-classes
+
+
+
+
+
+ *
+
+
+
+
+
+
+ findbugs-exclude.xml
+
+ io.siddhi.parser.*
+
+
+ org.osgi.framework.*;version="${osgi.framework.import.version.range}",
+ org.wso2.msf4j.*;version="${msf4j.import.version.range}",
+ org.slf4j.*;version="${slf4j.logging.package.import.version.range}",
+ javax.ws.rs.*;version="${javax.ws.rs.version.range}",
+ *;resolution:=optional
+
+
+
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/SiddhiParserDataHolder.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/SiddhiParserDataHolder.java
new file mode 100644
index 0000000000..702e71fa22
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/SiddhiParserDataHolder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.siddhi.parser;
+
+import io.siddhi.core.SiddhiManager;
+import org.wso2.carbon.config.provider.ConfigProvider;
+
+public class SiddhiParserDataHolder {
+ private static ConfigProvider configFileReader;
+ private static SiddhiManager siddhiManager;
+
+ public static SiddhiManager getSiddhiManager() {
+ return siddhiManager;
+ }
+
+ public static void setSiddhiManager(SiddhiManager siddhiManager) {
+ SiddhiParserDataHolder.siddhiManager = siddhiManager;
+ }
+
+ public static ConfigProvider getConfigProvider() {
+ return configFileReader;
+ }
+
+ public static void setConfigProvider(ConfigProvider configProvider) {
+ SiddhiParserDataHolder.configFileReader = configProvider;
+ }
+
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/SiddhiAppCreator.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/SiddhiAppCreator.java
new file mode 100644
index 0000000000..743bf3e1d6
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/SiddhiAppCreator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core;
+
+
+import io.siddhi.parser.core.appcreator.DeployableSiddhiQueryGroup;
+import io.siddhi.parser.core.topology.SiddhiTopology;
+import io.siddhi.parser.service.model.MessagingSystem;
+
+import java.util.List;
+/**
+ * This interface is utilized by which will be implemented by different
+ * distributed deployment implementations. Implementor can either choose to
+ * implement from scratch using this interface or use.
+ */
+public interface SiddhiAppCreator {
+ /**
+ * Create valid concrete Siddhi Apps for each Query Group in the given {@link SiddhiTopology}.
+ *
+ * @param topology Input topology to create Siddhi Apps
+ * @return List of {@link DeployableSiddhiQueryGroup}s. Length of the list should be equal to no. of groups user
+ * has defined. Length of the list should be greater than zero always.
+ */
+ List createApps(SiddhiTopology topology, MessagingSystem messagingSystem);
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/SiddhiTopologyCreator.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/SiddhiTopologyCreator.java
new file mode 100644
index 0000000000..ef9d78e9dc
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/SiddhiTopologyCreator.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core;
+
+import io.siddhi.parser.core.topology.SiddhiTopology;
+
+/**
+ * Topology Creator will consume a Siddhi App and produce a {@link SiddhiTopology} based on distributed annotations.
+ * Implementation of this should not change depending on different distribution methodologies(Ex: default, yarn
+ * based, container based).
+ */
+public interface SiddhiTopologyCreator {
+ /**
+ * consume a Siddhi App and produce a {@link SiddhiTopology} based on distributed annotations.
+ *
+ * @param userDefinedSiddhiApp Siddhi app deployed by the user
+ * @return {@link SiddhiTopology} representing the given siddhi app
+ */
+ SiddhiTopology createTopology(String userDefinedSiddhiApp);
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/AbstractSiddhiAppCreator.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/AbstractSiddhiAppCreator.java
new file mode 100644
index 0000000000..165f7c5ab5
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/AbstractSiddhiAppCreator.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.appcreator;
+
+import io.siddhi.parser.core.SiddhiAppCreator;
+import io.siddhi.parser.core.topology.SiddhiQueryGroup;
+import io.siddhi.parser.core.topology.SiddhiTopology;
+import io.siddhi.parser.service.model.MessagingSystem;
+import org.apache.commons.lang3.text.StrSubstitutor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstract implementation of {@link SiddhiAppCreator}. Developers can use this extension point
+ * to implement custom Siddhi App Creator based on the distribute implementation.
+ */
+public abstract class AbstractSiddhiAppCreator implements SiddhiAppCreator {
+
+ public List createApps(SiddhiTopology topology, MessagingSystem messagingSystem) {
+ List deployableSiddhiQueryGroupList =
+ new ArrayList(topology.getQueryGroupList().size());
+ for (SiddhiQueryGroup queryGroup : topology.getQueryGroupList()) {
+ DeployableSiddhiQueryGroup deployableQueryGroup =
+ new DeployableSiddhiQueryGroup(queryGroup.getName(),
+ queryGroup.isReceiverQueryGroup(), /*queryGroup.isUserGivenSource(),*/
+ queryGroup.getParallelism());
+ deployableQueryGroup.setSiddhiQueries(createApps(topology.getName(), queryGroup, messagingSystem));
+ deployableSiddhiQueryGroupList.add(deployableQueryGroup);
+ }
+ return deployableSiddhiQueryGroupList;
+ }
+
+ /**
+ * This method should return valid concrete Siddhi App/s as Strings. No. of returned Siddhi
+ * Apps should equal the parallelism count for parse group.
+ *
+ * @param queryGroup Input parse group to produce Siddhi Apps.
+ * @return List of valid concrete Siddhi Apps as String.
+ */
+ protected abstract List createApps(String siddhiAppName,
+ SiddhiQueryGroup queryGroup, MessagingSystem messagingSystem);
+
+ protected List getPartitionNumbers(int appParallelism, int availablePartitionCount,
+ int currentAppNum) {
+ List partitionNumbers = new ArrayList();
+ if (availablePartitionCount == appParallelism) {
+ partitionNumbers.add(currentAppNum);
+ return partitionNumbers;
+ } else {
+ //availablePartitionCount < appParallelism scenario cannot occur according to design.
+ // Hence if availablePartitionCount > appParallelism
+ //// TODO: 10/19/17 improve logic
+ int partitionsPerNode = availablePartitionCount / appParallelism;
+ if (currentAppNum + 1 == appParallelism) { //if last app
+ int remainingPartitions = availablePartitionCount - ((appParallelism - 1) *
+ partitionsPerNode);
+ for (int j = 0; j < remainingPartitions; j++) {
+ partitionNumbers.add((currentAppNum * partitionsPerNode) + j);
+ }
+ return partitionNumbers;
+ } else {
+ for (int j = 0; j < partitionsPerNode; j++) {
+ partitionNumbers.add((currentAppNum * partitionsPerNode) + j);
+ }
+ return partitionNumbers;
+ }
+ }
+ }
+
+ protected List generateQueryList(String queryTemplate, String queryGroupName,
+ int parallelism) {
+ List queries = new ArrayList(parallelism);
+ for (int i = 0; i < parallelism; i++) {
+ Map valuesMap = new HashMap(1);
+ String appName = queryGroupName + "-" + (i + 1);
+ valuesMap.put("appName", appName);
+ StrSubstitutor substitutor = new StrSubstitutor(valuesMap);
+ queries.add(new SiddhiQuery(appName, substitutor.replace(queryTemplate),
+ false));
+ }
+ return queries;
+ }
+
+ protected void updateQueryList(List queryList, Map valuesMap) {
+ StrSubstitutor substitutor = new StrSubstitutor(valuesMap);
+ for (SiddhiQuery query : queryList) {
+ String updatedQuery = substitutor.replace(query.getApp());
+ query.setApp(updatedQuery);
+ }
+ }
+
+ protected String getUpdatedQuery(String query, Map valuesMap) {
+ StrSubstitutor substitutor = new StrSubstitutor(valuesMap);
+ return substitutor.replace(query);
+ }
+
+ /**
+ *@param siddhiAppName Name of the userdefined siddhi app
+ * @param streamName Currently processing stream name
+ * @param groupingField Partition key field, if available otherwise null
+ * @return created topic name
+ *
+ * Creates the topic name from above parameters
+ */
+ protected String getTopicName(String siddhiAppName, String streamName, String groupingField) {
+ return siddhiAppName + "_" + streamName + (groupingField == null ? ""
+ : ("_" + groupingField));
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/DeployableSiddhiQueryGroup.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/DeployableSiddhiQueryGroup.java
new file mode 100644
index 0000000000..bc959dc67c
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/DeployableSiddhiQueryGroup.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.appcreator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * POJO Class to hold created Siddhi Apps belonging to a single parse group.
+ */
+public class DeployableSiddhiQueryGroup {
+
+ private String groupName;
+ private List siddhiQueries;
+ private boolean isReceiverQueryGroup;
+ private int parallelism;
+ private boolean isUserGivenSource;
+
+ public DeployableSiddhiQueryGroup(String groupName, boolean receiverQueryGroup, int parallelism) {
+ this.groupName = groupName;
+ siddhiQueries = new ArrayList();
+ isReceiverQueryGroup = receiverQueryGroup;
+ this.parallelism = parallelism;
+ }
+
+ public List getSiddhiQueries() {
+ return siddhiQueries;
+ }
+
+ public void setSiddhiQueries(List siddhiQueries) {
+ this.siddhiQueries = siddhiQueries;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public boolean isReceiverQueryGroup() {
+ return isReceiverQueryGroup;
+ }
+
+ public void setReceiverQueryGroup(boolean receiverQueryGroup) {
+ isReceiverQueryGroup = receiverQueryGroup;
+ }
+
+ public int getParallelism() {
+ return parallelism;
+ }
+
+ public boolean isUserGivenSource() {
+ return isUserGivenSource;
+ }
+
+ public void setUserGivenSource(boolean userGivenSource) {
+ isUserGivenSource = userGivenSource;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DeployableSiddhiQueryGroup that = (DeployableSiddhiQueryGroup) o;
+ if (getGroupName() != null ? !getGroupName().equals(that.getGroupName()) : that.getGroupName() != null) {
+ return false;
+ }
+ return getSiddhiQueries() != null ? getSiddhiQueries().equals(that.getSiddhiQueries())
+ : that.getSiddhiQueries() == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = getGroupName() != null ? getGroupName().hashCode() : 0;
+ result = 31 * result + (getSiddhiQueries() != null ? getSiddhiQueries().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/NatsSiddhiAppCreator.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/NatsSiddhiAppCreator.java
new file mode 100644
index 0000000000..52228111bf
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/NatsSiddhiAppCreator.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.siddhi.parser.core.appcreator;
+
+import io.siddhi.parser.core.topology.InputStreamDataHolder;
+import io.siddhi.parser.core.topology.OutputStreamDataHolder;
+import io.siddhi.parser.core.topology.PublishingStrategyDataHolder;
+import io.siddhi.parser.core.topology.SiddhiQueryGroup;
+import io.siddhi.parser.core.topology.SubscriptionStrategyDataHolder;
+import io.siddhi.parser.core.util.TransportStrategy;
+import io.siddhi.parser.service.model.MessagingSystem;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Creates distributed siddhi application which can be distributed using Nats-streaming.
+ */
+public class NatsSiddhiAppCreator extends AbstractSiddhiAppCreator {
+
+ private static final Logger log = Logger.getLogger(NatsSiddhiAppCreator.class);
+ //App creator constants
+ public static final String APP_NAME = "appName";
+ public static final String TOPIC_LIST = "topicList";
+ public static final String CONSUMER_GROUP_ID = "groupID";
+ public static final String BOOTSTRAP_SERVER_URL = "bootstrapServerURL";
+ public static final String PARTITION_LIST = "partitionList";
+ public static final String PARTITION_KEY = "partitionKey";
+ public static final String DESTINATIONS = "destinations";
+ public static final String PARTITION_NO = "partitionNo";
+ public static final String MAPPING = "text";
+ public static final String PARTITION_TOPIC = "partitionTopic";
+ public static final String DESTINATION_TOPIC = "@destination(destination = '${"
+ + PARTITION_TOPIC + "}')";
+ public static final String CLUSTER_ID = "clusterid";
+ public static final String NATS_SERVER_URL = "natsserverurl";
+ public static final String PARTITIONED_NATS_SINK_TEMPLATE = "@sink(type='nats',"
+ + "cluster.id='${" + CLUSTER_ID + "}',"
+ + "@distribution(strategy='partitioned', partitionKey='${" + PARTITION_KEY + "}',"
+ + "${" + DESTINATIONS + "}), bootstrap.servers="
+ + "'${" + NATS_SERVER_URL + "}',@map(type='" + MAPPING + "'))";
+ public static final String DEFAULT_NATS_SINK_TEMPLATE = "@sink(type='nats',"
+ + "cluster.id='${" + CLUSTER_ID + "}',"
+ + "destination = '${" + TOPIC_LIST + "}', bootstrap.servers="
+ + "'${" + NATS_SERVER_URL + "}',@map(type='" + MAPPING + "'))";
+ public static final String DEFAULT_NATS_SOURCE_TEMPLATE = "@source(type='nats',"
+ + "cluster.id='${" + CLUSTER_ID + "}',"
+ + "destination = '${" + TOPIC_LIST + "}', bootstrap.servers="
+ + "'${" + NATS_SERVER_URL + "}',@map(type='" + MAPPING + "'))";
+ public static final String QUEUE_GROUP_NAME = "queueGroupName";
+ public static final String RR_NATS_SOURCE_TEMPLATE = "@source(type='nats',"
+ + "cluster.id='${" + CLUSTER_ID + "}',"
+ + "queue.group.name='${" + QUEUE_GROUP_NAME + "}',"
+ + "destination = '${" + TOPIC_LIST + "}', bootstrap.servers="
+ + "'${" + NATS_SERVER_URL + "}',@map(type='" + MAPPING + "'))";
+
+ private String clusterId = "";
+ private String natsServerUrl = "";
+
+ @Override
+ protected List createApps(String siddhiAppName, SiddhiQueryGroup queryGroup,
+ MessagingSystem messagingSystem) {
+ String groupName = queryGroup.getName();
+ String queryTemplate = queryGroup.getSiddhiApp();
+ List queryList = generateQueryList(queryTemplate, groupName, queryGroup
+ .getParallelism());
+ if (messagingSystem != null && messagingSystem.getConfig() != null) {
+ natsServerUrl = messagingSystem.getConfig().getBootstrapServerURLs();
+ clusterId = messagingSystem.getConfig().getClusterId();
+ }
+ processInputStreams(siddhiAppName, groupName, queryList, queryGroup.getInputStreams().values());
+ processOutputStreams(siddhiAppName, queryList, queryGroup.getOutputStreams().values());
+ if (log.isDebugEnabled()) {
+ log.debug("Following parse list is created for the Siddhi Query Group " + queryGroup.getName() + " "
+ + "representing Siddhi App " + siddhiAppName + ".");
+ for (SiddhiQuery siddhiQuery : queryList) {
+ log.debug(siddhiQuery.getApp());
+ }
+ }
+ return queryList;
+ }
+
+ /**
+ * @param siddhiAppName Name of the initial user defined siddhi application.
+ * @param queryList Contains the parse of the current execution group replicated
+ * to the parallelism of the group.
+ * @param outputStreams Collection of current execution group's output streams
+ * Assigns the nats sink configurations for output streams.
+ */
+ private void processOutputStreams(String siddhiAppName, List queryList,
+ Collection outputStreams) {
+
+ Map sinkValuesMap = new HashMap();
+ sinkValuesMap.put(CLUSTER_ID, clusterId);
+ sinkValuesMap.put(NATS_SERVER_URL, natsServerUrl);
+
+ for (OutputStreamDataHolder outputStream : outputStreams) {
+ Map sinkList = new HashMap();
+ Map partitionKeys = new HashMap();
+
+ for (PublishingStrategyDataHolder holder : outputStream.getPublishingStrategyList()) {
+ sinkValuesMap.put("topicList", siddhiAppName + "_" +
+ outputStream.getStreamName() + (holder.getGroupingField() == null ? "" : ("_" + holder
+ .getGroupingField())));
+ if (holder.getStrategy() == TransportStrategy.FIELD_GROUPING) {
+ if (partitionKeys.get(holder.getGroupingField()) != null &&
+ partitionKeys.get(holder.getGroupingField()) > holder.getParallelism()) {
+ continue;
+ }
+
+ partitionKeys.put(holder.getGroupingField(), holder.getParallelism());
+ sinkValuesMap.put(PARTITION_KEY, holder.getGroupingField());
+ List destinations = new ArrayList(holder.getParallelism());
+
+ for (int i = 0; i < holder.getParallelism(); i++) {
+ Map destinationMap = new HashMap(holder.getParallelism());
+ destinationMap.put(PARTITION_TOPIC,
+ sinkValuesMap.get(TOPIC_LIST)
+ + "_" + String.valueOf(i));
+ destinations.add(getUpdatedQuery(DESTINATION_TOPIC,
+ destinationMap));
+ }
+
+ sinkValuesMap.put(DESTINATIONS,
+ StringUtils.join(destinations, ","));
+ String sinkString =
+ getUpdatedQuery(PARTITIONED_NATS_SINK_TEMPLATE,
+ sinkValuesMap);
+ sinkList.put(sinkValuesMap.get(TOPIC_LIST),
+ sinkString);
+ } else {
+ //ATM we are handling both strategies in same manner. Later will improve to have multiple
+ // partitions for RR
+ String sinkString = getUpdatedQuery(DEFAULT_NATS_SINK_TEMPLATE,
+ sinkValuesMap);
+ sinkList.put(sinkValuesMap.get(TOPIC_LIST), sinkString);
+ }
+ }
+ Map queryValuesMap = new HashMap(1);
+ queryValuesMap.put(outputStream.getStreamName(), StringUtils.join(sinkList.values(), "\n"));
+ updateQueryList(queryList, queryValuesMap);
+ }
+ }
+
+ /**
+ * @param siddhiAppName Name of the initial user defined siddhi application.
+ * @param queryList Contains the parse of the current execution group replicated
+ * to the parallelism of the group.
+ * @param inputStreams Collection of current execution group's input streams
+ * Assigns the nats source configurations for input streams.
+ */
+ private void processInputStreams(String siddhiAppName, String groupName, List queryList,
+ Collection inputStreams) {
+
+ Map sourceValuesMap = new HashMap();
+ for (InputStreamDataHolder inputStream : inputStreams) {
+ SubscriptionStrategyDataHolder subscriptionStrategy = inputStream.getSubscriptionStrategy();
+ sourceValuesMap.put(CLUSTER_ID, clusterId);
+ sourceValuesMap.put(NATS_SERVER_URL, natsServerUrl);
+
+ if (!inputStream.isUserGiven()) {
+ if (subscriptionStrategy.getStrategy() == TransportStrategy.FIELD_GROUPING) {
+ sourceValuesMap.put(TOPIC_LIST, getTopicName(siddhiAppName,
+ inputStream.getStreamName(), inputStream.getSubscriptionStrategy().getPartitionKey()));
+ for (int i = 0; i < queryList.size(); i++) {
+ List sourceQueries = new ArrayList();
+ List partitionNumbers = getPartitionNumbers(queryList.size(), subscriptionStrategy
+ .getOfferedParallelism(), i);
+ for (int topicCount : partitionNumbers) {
+ String topicName = getTopicName(siddhiAppName, inputStream.getStreamName(),
+ inputStream.getSubscriptionStrategy().getPartitionKey()) + "_"
+ + Integer.toString(topicCount);
+
+ sourceValuesMap.put(TOPIC_LIST, topicName);
+ String sourceQuery = getUpdatedQuery(DEFAULT_NATS_SOURCE_TEMPLATE, sourceValuesMap);
+ sourceQueries.add(sourceQuery);
+ }
+
+ String combinedQueryHeader = StringUtils.join(sourceQueries,
+ System.lineSeparator());
+ Map queryValuesMap = new HashMap(1);
+ queryValuesMap.put(inputStream.getStreamName(), combinedQueryHeader);
+ String updatedQuery = getUpdatedQuery(queryList.get(i).getApp()
+ , queryValuesMap);
+ queryList.get(i).setApp(updatedQuery);
+ }
+
+ } else if (subscriptionStrategy.getStrategy() == TransportStrategy.ROUND_ROBIN) {
+ sourceValuesMap.put(TOPIC_LIST, getTopicName(siddhiAppName,
+ inputStream.getStreamName(), null));
+ sourceValuesMap.put(QUEUE_GROUP_NAME, groupName);
+ String sourceString = getUpdatedQuery(RR_NATS_SOURCE_TEMPLATE, sourceValuesMap);
+ Map queryValuesMap = new HashMap(1);
+ queryValuesMap.put(inputStream.getStreamName(), sourceString);
+ updateQueryList(queryList, queryValuesMap);
+
+ } else if (subscriptionStrategy.getStrategy() == TransportStrategy.ALL) {
+
+ sourceValuesMap.put(TOPIC_LIST, getTopicName(siddhiAppName,
+ inputStream.getStreamName(), null));
+ for (SiddhiQuery aQueryList : queryList) {
+ String sourceString = getUpdatedQuery(DEFAULT_NATS_SOURCE_TEMPLATE, sourceValuesMap);
+ Map queryValuesMap = new HashMap(1);
+ queryValuesMap.put(inputStream.getStreamName(), sourceString);
+ String updatedQuery = getUpdatedQuery(aQueryList.getApp(), queryValuesMap);
+ aQueryList.setApp(updatedQuery);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/SiddhiQuery.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/SiddhiQuery.java
new file mode 100644
index 0000000000..ee6ff403f5
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/appcreator/SiddhiQuery.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.appcreator;
+
+/**
+ * Gives details about siddhi application.
+ */
+public class SiddhiQuery {
+ private String appName;
+ private String app;
+ private boolean isReceiverQuery;
+
+ private SiddhiQuery() {
+ // Avoiding empty initialization
+ }
+
+ public SiddhiQuery(String appName, String app, boolean isReceiverQuery) {
+ this.appName = appName;
+ this.app = app;
+ this.isReceiverQuery = isReceiverQuery;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public SiddhiQuery setAppName(String appName) {
+ this.appName = appName;
+ return this;
+ }
+
+ public String getApp() {
+ return app;
+ }
+
+ public SiddhiQuery setApp(String app) {
+ this.app = app;
+ return this;
+ }
+
+ public boolean isReceiverQuery() {
+ return isReceiverQuery;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ SiddhiQuery that = (SiddhiQuery) o;
+ if (getAppName() != null ? !getAppName().equals(that.getAppName()) : that.getAppName() != null) {
+ return false;
+ }
+ return getApp() != null ? getApp().equals(that.getApp()) : that.getApp() == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = getAppName() != null ? getAppName().hashCode() : 0;
+ result = 31 * result + (getApp() != null ? getApp().hashCode() : 0);
+ return result;
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/InputStreamDataHolder.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/InputStreamDataHolder.java
new file mode 100644
index 0000000000..e74059c8da
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/InputStreamDataHolder.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.topology;
+
+import io.siddhi.parser.core.util.EventHolder;
+import io.siddhi.parser.core.util.SiddhiTopologyCreatorConstants;
+
+/**
+ * Data Holder to hold required details of Input Streams in {@link SiddhiTopology}.
+ */
+public class InputStreamDataHolder {
+ private String streamName;
+ private String streamDefinition;
+ private EventHolder eventHolderType;
+ private boolean isUserGiven;
+ private SubscriptionStrategyDataHolder subscriptionStrategy;
+ private boolean isInnerGroupStream;
+
+ public InputStreamDataHolder(String streamName, String streamDefinition, EventHolder eventHolderType,
+ boolean isUserGiven, SubscriptionStrategyDataHolder subscriptionStrategy) {
+ this.streamName = streamName;
+ this.streamDefinition = streamDefinition;
+ this.eventHolderType = eventHolderType;
+ this.isUserGiven = isUserGiven;
+ this.subscriptionStrategy = subscriptionStrategy;
+ isInnerGroupStream = false;
+ }
+
+ public String getStreamDefinition() {
+ return streamDefinition;
+ }
+
+ public void setStreamDefinition(String streamDefinition) {
+ this.streamDefinition = streamDefinition;
+ }
+
+ public String getStreamName() {
+ return streamName;
+ }
+
+ public SubscriptionStrategyDataHolder getSubscriptionStrategy() {
+ return subscriptionStrategy;
+ }
+
+ public boolean isUserGiven() {
+ return isUserGiven;
+ }
+
+ public void setUserGiven(boolean userGiven) {
+ isUserGiven = userGiven;
+ }
+
+ public EventHolder getEventHolderType() {
+ return eventHolderType;
+ }
+
+ public boolean isInnerGroupStream() {
+ return isInnerGroupStream;
+ }
+
+ public void setInnerGroupStream(boolean innerGroupStream) {
+ isInnerGroupStream = innerGroupStream;
+ }
+
+ public boolean isUserGivenSource() {
+ return streamDefinition.toLowerCase().contains(SiddhiTopologyCreatorConstants.SOURCE_IDENTIFIER);
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/OutputStreamDataHolder.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/OutputStreamDataHolder.java
new file mode 100644
index 0000000000..8a710a5b29
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/OutputStreamDataHolder.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.topology;
+
+import io.siddhi.parser.core.util.EventHolder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Data Holder to hold required details of Output Streams in {@link SiddhiTopology}.
+ */
+public class OutputStreamDataHolder {
+ private String streamName;
+ private String streamDefinition;
+ private EventHolder eventHolderType;
+ private List publishingStrategyList;
+ private boolean isUserGiven;
+ private boolean isInnerGroupStream;
+ private boolean isSinkBridgeAdded;
+
+ public OutputStreamDataHolder(String streamName, String streamDefinition, EventHolder eventHolderType,
+ boolean isUserGiven) {
+ this.streamName = streamName;
+ this.streamDefinition = streamDefinition;
+ this.eventHolderType = eventHolderType;
+ this.isUserGiven = isUserGiven;
+ this.publishingStrategyList = new ArrayList();
+ isInnerGroupStream = false;
+ isSinkBridgeAdded = false;
+ }
+
+ public String getStreamDefinition() {
+ return streamDefinition;
+ }
+
+ public void setStreamDefinition(String streamDefinition) {
+ this.streamDefinition = streamDefinition;
+ }
+
+ public String getStreamName() {
+ return streamName;
+ }
+
+ public List getPublishingStrategyList() {
+ return publishingStrategyList;
+ }
+
+ public boolean isUserGiven() {
+ return isUserGiven;
+ }
+
+ public void addPublishingStrategy(PublishingStrategyDataHolder publishingStrategyDataHolder) {
+ publishingStrategyList.add(publishingStrategyDataHolder);
+ }
+
+ public EventHolder getEventHolderType() {
+ return eventHolderType;
+ }
+
+ public boolean isInnerGroupStream() {
+ return isInnerGroupStream;
+ }
+
+ public void setInnerGroupStream(boolean innerGroupStream) {
+ isInnerGroupStream = innerGroupStream;
+ }
+
+ public boolean isSinkBridgeAdded() {
+ return isSinkBridgeAdded;
+ }
+
+ public void setSinkBridgeAdded(boolean sinkBridgeAdded) {
+ isSinkBridgeAdded = sinkBridgeAdded;
+ }
+}
+
+
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/PublishingStrategyDataHolder.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/PublishingStrategyDataHolder.java
new file mode 100644
index 0000000000..d9fa008a32
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/PublishingStrategyDataHolder.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.topology;
+
+import io.siddhi.parser.core.util.TransportStrategy;
+
+/**
+ * Data Holder to hold required details of Publishing Strategy of an Output Stream. Given Output Stream can have
+ * multiple publishing strategies for each consumer.
+ */
+public class PublishingStrategyDataHolder {
+ private TransportStrategy strategy;
+ private String groupingField = null;
+ private int parallelism;
+
+ public PublishingStrategyDataHolder(TransportStrategy strategy, int parallelism) {
+ this.strategy = strategy;
+ this.parallelism = parallelism;
+ }
+
+ public PublishingStrategyDataHolder(TransportStrategy strategy, String groupingField, int parallelism) {
+ this.strategy = strategy;
+ this.groupingField = groupingField;
+ this.parallelism = parallelism;
+ }
+
+ public TransportStrategy getStrategy() {
+ return strategy;
+ }
+
+ public String getGroupingField() {
+ return groupingField;
+ }
+
+ public int getParallelism() {
+ return parallelism;
+ }
+
+ public void setParallelism(int parallelism) {
+ this.parallelism = parallelism;
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiQueryGroup.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiQueryGroup.java
new file mode 100644
index 0000000000..6943252fcb
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiQueryGroup.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.siddhi.parser.core.topology;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static io.siddhi.parser.core.appcreator.NatsSiddhiAppCreator.APP_NAME;
+
+/**
+ * Data Holder to hold required details of Query Groups in {@link SiddhiTopology}.
+ */
+public class SiddhiQueryGroup {
+ private String name;
+ private int parallelism;
+ private String siddhiApp;
+ private Map inputStreams;
+ private Map outputStreams;
+ private boolean messagingSourceAvailable = false;
+ private List queryList;
+ private boolean isReceiverQueryGroup;
+
+ public SiddhiQueryGroup(String name, int parallelism) {
+ this.name = name;
+ this.parallelism = parallelism;
+ this.queryList = new ArrayList();
+ siddhiApp = " ";
+ inputStreams = new HashMap();
+ outputStreams = new HashMap();
+
+ }
+
+ public List getQueryList() {
+ return queryList;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getParallelism() {
+ return parallelism;
+ }
+
+ public String getSiddhiApp() {
+ //combination of InputStream definitions , OutputStream and queries
+ StringBuilder stringBuilder = new StringBuilder("@App:name(\"${" + APP_NAME + "}\") \n");
+ for (InputStreamDataHolder inputStreamDataHolder : inputStreams.values()) {
+ siddhiApp = inputStreamDataHolder.getStreamDefinition();
+ if (siddhiApp != null) {
+ stringBuilder.append(siddhiApp).append(";\n");
+ }
+ }
+ for (OutputStreamDataHolder outputStreamDataHolder : outputStreams.values()) {
+ siddhiApp = outputStreamDataHolder.getStreamDefinition();
+ if (siddhiApp != null) {
+ stringBuilder.append(siddhiApp).append(";\n");
+ }
+ }
+ for (String aQueryList : queryList) {
+ stringBuilder.append(aQueryList).append(";\n");
+ }
+ siddhiApp = stringBuilder.toString();
+ return stringBuilder.toString();
+ }
+
+ public void addQuery(String query) {
+ queryList.add(query);
+ }
+
+ public void addQueryAtFirst(String query) {
+ queryList.add(0, query);
+ }
+
+ public void addOutputStream(String key, OutputStreamDataHolder outputStreamDataHolder) {
+ if (outputStreamDataHolder != null) {
+ outputStreams.put(key, outputStreamDataHolder);
+ }
+ }
+
+ public void addInputStreams(Map inputStreamDataHolderMap) {
+ if (inputStreamDataHolderMap != null) {
+ this.inputStreams.putAll(inputStreamDataHolderMap);
+ }
+ }
+
+ public Map getInputStreams() {
+ return inputStreams;
+ }
+
+ public Map getOutputStreams() {
+ return outputStreams;
+ }
+
+ public boolean isReceiverQueryGroup() {
+ return isReceiverQueryGroup;
+ }
+
+ public void setReceiverQueryGroup(boolean receiverQueryGroup) {
+ isReceiverQueryGroup = receiverQueryGroup;
+ }
+
+ public void setParallelism(int parallelism) {
+ this.parallelism = parallelism;
+ }
+
+ public boolean isMessagingSourceAvailable() {
+ return messagingSourceAvailable;
+ }
+
+ public void setMessagingSourceAvailable(boolean messagingSourceAvailable) {
+ this.messagingSourceAvailable = messagingSourceAvailable;
+ }
+
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiTopology.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiTopology.java
new file mode 100644
index 0000000000..1a4df3685f
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiTopology.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.topology;
+
+import java.util.List;
+
+/**
+ * Distributed Topology of a user defined distributed Siddhi App. Topology contains all the required details for the
+ * underlying distribution provider to create new Apps.
+ */
+public class SiddhiTopology {
+ private String name;
+ private List queryGroupList;
+ private boolean transportChannelCreationEnabled;
+ private boolean isStatefulApp;
+ private boolean userGiveSourceStateful;
+
+ public SiddhiTopology(String name, List queryGroupList, boolean transportChannelCreationEnabled,
+ boolean isStatefulApp, boolean userGiveSourceStateful) {
+ this.name = name;
+ this.queryGroupList = queryGroupList;
+ this.transportChannelCreationEnabled = transportChannelCreationEnabled;
+ this.isStatefulApp = isStatefulApp;
+ this.userGiveSourceStateful = userGiveSourceStateful;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List getQueryGroupList() {
+ return queryGroupList;
+ }
+
+ public boolean isTransportChannelCreationEnabled() {
+ return transportChannelCreationEnabled;
+ }
+
+ public void setTransportChannelCreationEnabled(boolean transportChannelCreationEnabled) {
+ this.transportChannelCreationEnabled = transportChannelCreationEnabled;
+ }
+
+ public boolean isStatefulApp() {
+ return isStatefulApp;
+ }
+
+ public boolean isUserGiveSourceStateful() {
+ return userGiveSourceStateful;
+ }
+}
diff --git a/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiTopologyCreatorImpl.java b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiTopologyCreatorImpl.java
new file mode 100644
index 0000000000..03c489928c
--- /dev/null
+++ b/runner/components/io.siddhi.parser/src/main/java/io/siddhi/parser/core/topology/SiddhiTopologyCreatorImpl.java
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.siddhi.parser.core.topology;
+
+import io.siddhi.core.SiddhiAppRuntime;
+import io.siddhi.core.partition.PartitionRuntime;
+import io.siddhi.core.query.QueryRuntime;
+import io.siddhi.core.stream.input.source.Source;
+import io.siddhi.core.stream.output.sink.Sink;
+import io.siddhi.core.table.Table;
+import io.siddhi.core.window.Window;
+import io.siddhi.parser.SiddhiParserDataHolder;
+import io.siddhi.parser.core.SiddhiTopologyCreator;
+import io.siddhi.parser.core.util.EventHolder;
+import io.siddhi.parser.core.util.SiddhiTopologyCreatorConstants;
+import io.siddhi.parser.core.util.TransportStrategy;
+import io.siddhi.query.api.SiddhiApp;
+import io.siddhi.query.api.annotation.Annotation;
+import io.siddhi.query.api.annotation.Element;
+import io.siddhi.query.api.definition.AbstractDefinition;
+import io.siddhi.query.api.definition.StreamDefinition;
+import io.siddhi.query.api.exception.SiddhiAppValidationException;
+import io.siddhi.query.api.execution.ExecutionElement;
+import io.siddhi.query.api.execution.partition.Partition;
+import io.siddhi.query.api.execution.partition.PartitionType;
+import io.siddhi.query.api.execution.partition.ValuePartitionType;
+import io.siddhi.query.api.execution.query.Query;
+import io.siddhi.query.api.execution.query.input.stream.InputStream;
+import io.siddhi.query.api.expression.Variable;
+import io.siddhi.query.api.util.AnnotationHelper;
+import io.siddhi.query.api.util.ExceptionUtil;
+import io.siddhi.query.compiler.SiddhiCompiler;
+import org.apache.commons.lang3.text.StrSubstitutor;
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.UUID;
+
+/**
+ * Consumes a Siddhi App and produce a {@link SiddhiTopology} based on distributed annotations.
+ */
+
+public class SiddhiTopologyCreatorImpl implements SiddhiTopologyCreator {
+
+ private static final Logger log = Logger.getLogger(SiddhiTopologyCreatorImpl.class);
+ private static final String DEFAULT_MESSAGING_SYSTEM = "nats";
+ private SiddhiTopologyDataHolder siddhiTopologyDataHolder;
+ private SiddhiApp siddhiApp;
+ private String siddhiAppName;
+ private SiddhiAppRuntime siddhiAppRuntime;
+ private String userDefinedSiddhiApp;
+ private boolean transportChannelCreationEnabled = true;
+ private boolean isUserGiveSourceStateful = false;
+
+ @Override
+ public SiddhiTopology createTopology(String userDefinedSiddhiApp) {
+ this.userDefinedSiddhiApp = userDefinedSiddhiApp;
+ this.siddhiApp = SiddhiCompiler.parse(userDefinedSiddhiApp);
+ this.siddhiAppRuntime = SiddhiParserDataHolder.getSiddhiManager().createSiddhiAppRuntime(userDefinedSiddhiApp);
+ this.siddhiAppName = getSiddhiAppName();
+ this.siddhiTopologyDataHolder = new SiddhiTopologyDataHolder(siddhiAppName, userDefinedSiddhiApp);
+
+ SiddhiQueryGroup siddhiQueryGroup;
+ String execGroupName;
+ String defaultExecGroupName = siddhiAppName + "-" + UUID.randomUUID();
+ //Parallelism is set to default parallelism, since distributed deployment is not supported at the moment
+ int parallelism = SiddhiTopologyCreatorConstants.DEFAULT_PARALLEL;
+
+ for (ExecutionElement executionElement : siddhiApp.getExecutionElementList()) {
+ //groupName is set to default, since all elements go under a single group
+ execGroupName = defaultExecGroupName;
+ siddhiQueryGroup = createSiddhiQueryGroup(execGroupName, parallelism);
+ addExecutionElement(executionElement, siddhiQueryGroup, execGroupName);
+ }
+
+ checkUserGivenSourceDistribution();
+ assignPublishingStrategyOutputStream();
+ cleanInnerGroupStreams(siddhiTopologyDataHolder.getSiddhiQueryGroupMap().values());
+ if (log.isDebugEnabled()) {
+ log.debug("Topology was created with " + siddhiTopologyDataHolder.getSiddhiQueryGroupMap().values().size
+ () + " groups. Following are the partial Siddhi apps.");
+ for (SiddhiQueryGroup debugSiddhiQueryGroup : siddhiTopologyDataHolder.getSiddhiQueryGroupMap().values()) {
+ log.debug(debugSiddhiQueryGroup.getSiddhiApp());
+ }
+ }
+ return new SiddhiTopology(siddhiTopologyDataHolder.getSiddhiAppName(), new ArrayList<>
+ (siddhiTopologyDataHolder.getSiddhiQueryGroupMap().values()),
+ transportChannelCreationEnabled, isStatefulApp(), isUserGiveSourceStateful);
+ }
+
+ private boolean isStatefulApp() {
+ for (List
+
+ io.siddhi.distribution
+ io.siddhi.parser.service.feature
+ zip
+
io.siddhi.distribution
io.siddhi.distribution.common.feature
@@ -229,6 +236,21 @@
io.siddhi.distribution.health.check.core.feature
zip
+
+ org.testcontainers
+ testcontainers
+ test
+
+
+ io.nats
+ java-nats-streaming
+ test
+
+
+ io.nats
+ java-nats-streaming
+ test
+
@@ -570,6 +592,10 @@
io.siddhi.distribution.core.feature
${io.siddhi.distribution.version}
+
+ io.siddhi.parser.service.feature
+ ${io.siddhi.distribution.version}
+
io.siddhi.distribution.common.feature
${io.siddhi.distribution.version}
@@ -744,6 +770,10 @@
io.siddhi.distribution.core.feature.group
${io.siddhi.distribution.version}
+
+ io.siddhi.parser.service.feature.group
+ ${io.siddhi.distribution.version}
+
io.siddhi.distribution.common.feature.group
${io.siddhi.distribution.version}
@@ -871,6 +901,14 @@
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+