Finish service dispatcher generation.
diff --git a/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/DispatcherContext.java b/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/DispatcherContext.java
new file mode 100644
index 0000000..06c597f
--- /dev/null
+++ b/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/DispatcherContext.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.skywalking.oal.tool.output;
+
+import java.util.LinkedList;
+import java.util.List;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oal.tool.parser.AnalysisResult;
+
+@Getter(AccessLevel.PUBLIC)
+@Setter(AccessLevel.PUBLIC)
+public class DispatcherContext {
+    private List<AnalysisResult> serviceIndicators = new LinkedList<>();
+    private List<AnalysisResult> serviceInstanceIndicators = new LinkedList<>();
+    private List<AnalysisResult> endpointIndicators = new LinkedList<>();
+
+
+}
diff --git a/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/FileGenerator.java b/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/FileGenerator.java
index a8dbc1e..7d0fdc6 100644
--- a/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/FileGenerator.java
+++ b/oal-parser/src/main/java/org/apache/skywalking/oal/tool/output/FileGenerator.java
@@ -19,22 +19,19 @@
 package org.apache.skywalking.oal.tool.output;
 
 import freemarker.template.Configuration;
-import freemarker.template.Template;
 import freemarker.template.TemplateException;
 import freemarker.template.Version;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.io.Writer;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import org.apache.skywalking.oal.tool.parser.AnalysisResult;
 
 public class FileGenerator {
     private List<AnalysisResult> results;
     private String outputPath;
     private Configuration configuration;
+    private DispatcherContext dispatcherContext;
 
     public FileGenerator(List<AnalysisResult> results, String outputPath) {
         this.results = results;
@@ -42,6 +39,7 @@
         configuration = new Configuration(new Version("2.3.28"));
         configuration.setEncoding(Locale.ENGLISH, "UTF-8");
         configuration.setClassLoaderForTemplateLoading(FileGenerator.class.getClassLoader(), "/code-templates");
+        this.toDispatchers();
     }
 
     public void generate() {
@@ -63,4 +61,28 @@
     void generateIndicatorImplementor(AnalysisResult result, Writer output) throws IOException, TemplateException {
         configuration.getTemplate("IndicatorImplementor.ftl").process(result, output);
     }
+
+    void generateServiceDispatcher(Writer output) throws IOException, TemplateException {
+        configuration.getTemplate("ServiceDispatcherTemplate.ftl").process(dispatcherContext, output);
+    }
+
+    private void toDispatchers() {
+        dispatcherContext = new DispatcherContext();
+        for (AnalysisResult result : results) {
+            String sourceName = result.getSourceName();
+            switch (sourceName) {
+                case "Service":
+                    dispatcherContext.getServiceIndicators().add(result);
+                    break;
+                case "Endpoint":
+                    dispatcherContext.getServiceInstanceIndicators().add(result);
+                    break;
+                case "ServiceInstance":
+                    dispatcherContext.getEndpointIndicators().add(result);
+                    break;
+                default:
+
+            }
+        }
+    }
 }
diff --git a/oal-parser/src/main/resources/code-templates/ServiceDispatcherTemplate.ftl b/oal-parser/src/main/resources/code-templates/ServiceDispatcherTemplate.ftl
new file mode 100644
index 0000000..66be8b6
--- /dev/null
+++ b/oal-parser/src/main/resources/code-templates/ServiceDispatcherTemplate.ftl
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.skywalking.oap.server.core.analysis.generated;
+
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
+import org.apache.skywalking.oap.server.core.analysis.worker.define.WorkerMapper;
+import org.apache.skywalking.oap.server.core.source.Endpoint;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+
+/**
+ * This class is auto generated. Please don't change this class manually.
+ *
+ * @author Observability Analysis Language code generator
+ */
+public class ServiceDispatcher implements SourceDispatcher<Service> {
+
+    private final ModuleManager moduleManager;
+<#list serviceIndicators as indicator>
+    private ${indicator.metricName}AggregateWorker ${indicator.metricName};
+</#list>
+
+    public ServiceDispatcher(ModuleManager moduleManager) {
+        this.moduleManager = moduleManager;
+    }
+
+    @Override public void dispatch(Service source) {
+<#list serviceIndicators as indicator>
+        do${indicator.metricName}(source);
+</#list>
+    }
+
+<#list serviceIndicators as indicator>
+    private void do${indicator.metricName}(Service source) {
+        if (avgAggregator == null) {
+            WorkerMapper workerMapper = moduleManager.find(CoreModule.NAME).getService(WorkerMapper.class);
+            avgAggregator = (${indicator.metricName}AggregateWorker)workerMapper.findInstanceByClass(${indicator.metricName}AggregateWorker.class);
+        }
+
+        ${indicator.metricName}Indicator indicator = new ${indicator.metricName}Indicator();
+
+        indicator.setTimeBucket(source.getTimeBucket());
+    <#list indicator.fieldsFromSource as field>
+        indicator.${field.fieldSetter}(source.${field.fieldGetter}())
+    </#list>
+        indicator.${indicator.entryMethod.methodName}(
+            <#list indicator.entryMethod.argsExpressions as arg>${arg}<#if arg_has_next>, </#if></#list>);
+        avgAggregator.in(indicator);
+    }
+</#list>
+}
diff --git a/oal-parser/src/test/java/org/apache/skywalking/oal/tool/output/FileGeneratorTest.java b/oal-parser/src/test/java/org/apache/skywalking/oal/tool/output/FileGeneratorTest.java
index 3761f7a..9cd522b 100644
--- a/oal-parser/src/test/java/org/apache/skywalking/oal/tool/output/FileGeneratorTest.java
+++ b/oal-parser/src/test/java/org/apache/skywalking/oal/tool/output/FileGeneratorTest.java
@@ -26,6 +26,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import org.apache.skywalking.oal.tool.parser.AnalysisResult;
+import org.apache.skywalking.oal.tool.parser.EntryMethod;
 import org.apache.skywalking.oal.tool.parser.SourceColumnsFactory;
 import org.apache.skywalking.oap.server.core.remote.selector.Selector;
 import org.junit.Assert;
@@ -42,6 +43,12 @@
         result.setRemoteSelector(Selector.HashCode);
         result.setNeedMerge(true);
         result.setIndicatorClassName("AvgIndicator");
+        EntryMethod method = new EntryMethod();
+        method.setMethodName("combine");
+        method.setArgsExpressions(new LinkedList<>());
+        method.getArgsExpressions().add("source.getLatency()");
+        method.getArgsExpressions().add("1");
+        result.setEntryMethod(method);
         result.addPersistentField("summation", "summation", long.class);
         result.addPersistentField("count", "count", int.class);
         result.addPersistentField("value", "value", long.class);
@@ -112,6 +119,21 @@
         //fileGenerator.generateIndicatorImplementor(result, new OutputStreamWriter(System.out));
     }
 
+    @Test
+    public void testServiceDispatcher() throws IOException, TemplateException {
+        AnalysisResult result = buildResult();
+
+        List<AnalysisResult> results = new LinkedList<>();
+        results.add(result);
+
+        FileGenerator fileGenerator = new FileGenerator(results, ".");
+        StringWriter writer = new StringWriter();
+        fileGenerator.generateServiceDispatcher(writer);
+        Assert.assertEquals(readExpectedFile("ServiceDispatcherExpected.java"), writer.toString());
+
+        //fileGenerator.generateServiceDispatcher(new OutputStreamWriter(System.out));
+    }
+
     private String readExpectedFile(String filename) throws IOException {
         BufferedReader reader = new BufferedReader(new InputStreamReader(FileGenerator.class.getResourceAsStream("/expectedFiles/" + filename)));
 
diff --git a/oal-parser/src/test/resources/expectedFiles/ServiceDispatcherExpected.java b/oal-parser/src/test/resources/expectedFiles/ServiceDispatcherExpected.java
new file mode 100644
index 0000000..199d40a
--- /dev/null
+++ b/oal-parser/src/test/resources/expectedFiles/ServiceDispatcherExpected.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.skywalking.oap.server.core.analysis.generated;
+
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
+import org.apache.skywalking.oap.server.core.analysis.worker.define.WorkerMapper;
+import org.apache.skywalking.oap.server.core.source.Endpoint;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+
+/**
+ * This class is auto generated. Please don't change this class manually.
+ *
+ * @author Observability Analysis Language code generator
+ */
+public class ServiceDispatcher implements SourceDispatcher<Service> {
+
+    private final ModuleManager moduleManager;
+    private ServiceAvgAggregateWorker ServiceAvg;
+
+    public ServiceDispatcher(ModuleManager moduleManager) {
+        this.moduleManager = moduleManager;
+    }
+
+    @Override public void dispatch(Service source) {
+        doServiceAvg(source);
+    }
+
+    private void doServiceAvg(Service source) {
+        if (avgAggregator == null) {
+            WorkerMapper workerMapper = moduleManager.find(CoreModule.NAME).getService(WorkerMapper.class);
+            avgAggregator = (ServiceAvgAggregateWorker)workerMapper.findInstanceByClass(ServiceAvgAggregateWorker.class);
+        }
+
+        ServiceAvgIndicator indicator = new ServiceAvgIndicator();
+
+        indicator.setTimeBucket(source.getTimeBucket());
+        indicator.setId(source.getId())
+        indicator.setServiceId(source.getServiceId())
+        indicator.setServiceInstanceId(source.getServiceInstanceId())
+        indicator.combine(
+            source.getLatency(), 1);
+        avgAggregator.in(indicator);
+    }
+}
\ No newline at end of file