You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2020/05/22 21:37:51 UTC

[incubator-streampipes] branch dev updated: [STREAMPIPES-140] Add streampipes-maven-plugin

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new aab2f21  [STREAMPIPES-140] Add streampipes-maven-plugin
aab2f21 is described below

commit aab2f2136a89f1833ab3215358284884642875b4
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Fri May 22 23:37:31 2020 +0200

    [STREAMPIPES-140] Add streampipes-maven-plugin
---
 pom.xml                                            |  34 ++++
 streampipes-maven-plugin/pom.xml                   | 195 +++++++++++++++++++++
 .../apache/streampipes/smp/CreateAssetMojo.java    | 108 ++++++++++++
 .../streampipes/smp/ExtractDocumentationMojo.java  | 189 ++++++++++++++++++++
 .../streampipes/smp/constants/PeGridConst.java     |  52 ++++++
 .../apache/streampipes/smp/constants/PeType.java   |  35 ++++
 .../smp/extractor/AssetModelItemExtractor.java     |  90 ++++++++++
 .../smp/extractor/ControllerExtractor.java         |  56 ++++++
 .../smp/extractor/ControllerFileFinder.java        |  65 +++++++
 .../smp/extractor/DockerImageExtractor.java        |  77 ++++++++
 .../streampipes/smp/extractor/FieldReplacer.java   |  59 +++++++
 .../smp/extractor/LocalesExtractor.java            |  60 +++++++
 .../extractor/PipelineElementTypeExtractor.java    |  43 +++++
 .../streampipes/smp/generator/AssetGenerator.java  |  59 +++++++
 .../smp/generator/DataJsonGenerator.java           |  73 ++++++++
 .../smp/generator/ImagePathReplacer.java           |  59 +++++++
 .../smp/generator/MarkdownHeaderGenerator.java     |  51 ++++++
 .../smp/generator/MarkdownTitleRemover.java        |  32 ++++
 .../streampipes/smp/generator/OutputGenerator.java |  36 ++++
 .../generator/PipelineElementGridGenerator.java    | 151 ++++++++++++++++
 .../PipelineElementOverviewGenerator.java          |  52 ++++++
 .../smp/generator/SidebarConfigGenerator.java      |  45 +++++
 .../apache/streampipes/smp/model/AssetModel.java   | 108 ++++++++++++
 .../smp/parser/DocumentationParser.java            |  41 +++++
 .../parser/PipelineElementDescriptionReplacer.java |  38 ++++
 .../smp/parser/PipelineElementNameReplacer.java    |  40 +++++
 .../smp/parser/PlaceholderReplacer.java            |  42 +++++
 .../streampipes/smp/util/DirectoryManager.java     |  32 ++++
 .../streampipes/smp/util/DuplicateRemover.java     |  45 +++++
 .../org/apache/streampipes/smp/util/Utils.java     |  47 +++++
 .../src/main/resources/docker-compose.yml          |  28 +++
 .../src/main/resources/documentation.md            |  48 +++++
 .../src/main/resources/expected.documentation.md   |  48 +++++
 .../src/main/resources/placeholder-icon.png        | Bin 0 -> 3475 bytes
 .../smp/extractor/TestAssetModelExtractor.java     | 107 +++++++++++
 .../smp/extractor/TestDockerImageExtractor.java    |  44 +++++
 .../smp/generator/TestMarkdownTitleRemover.java    | 109 ++++++++++++
 .../TestPipelineElementOverviewGenerator.java      |  43 +++++
 .../smp/parser/TestDocumentationParser.java        |  46 +++++
 39 files changed, 2487 insertions(+)

diff --git a/pom.xml b/pom.xml
index 5473e71..a602ffe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <dependency.locations.enabled>false</dependency.locations.enabled>
+        <maven.version>3.3.9</maven.version>
         <owasp.check.skip>true</owasp.check.skip>
 
         <activemq-client.version>5.15.9</activemq-client.version>
@@ -85,6 +86,8 @@
         <objenesis.version>2.5.1</objenesis.version>
         <okio.version>1.16.0</okio.version>
         <okhttp.version>3.12.2</okhttp.version>
+        <plexus-component-annotations.version>1.6</plexus-component-annotations.version>
+        <plexus-utils.version>3.0.22</plexus-utils.version>
         <rdf4j.version>3.1.0</rdf4j.version>
         <rendersnake.version>1.8</rendersnake.version>
         <retrofit.version>2.5.0</retrofit.version>
@@ -358,6 +361,26 @@
                 <version>${kafka.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.maven</groupId>
+                <artifactId>maven-plugin-api</artifactId>
+                <version>${maven.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.maven</groupId>
+                <artifactId>maven-core</artifactId>
+                <version>${maven.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.maven</groupId>
+                <artifactId>maven-artifact</artifactId>
+                <version>${maven.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.maven</groupId>
+                <artifactId>maven-compat</artifactId>
+                <version>${maven.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.apache.activemq</groupId>
                 <artifactId>activemq-client</artifactId>
                 <version>${activemq-client.version}</version>
@@ -408,6 +431,16 @@
                 <version>${spark.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.codehaus.plexus</groupId>
+                <artifactId>plexus-component-annotations</artifactId>
+                <version>${plexus-component-annotations.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.plexus</groupId>
+                <artifactId>plexus-utils</artifactId>
+                <version>${plexus-utils.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-server</artifactId>
                 <version>${jetty.version}</version>
@@ -833,6 +866,7 @@
         <module>streampipes-connect-container-worker</module>
         <module>streampipes-container-base</module>
         <module>streampipes-messaging-mqtt</module>
+        <module>streampipes-maven-plugin</module>
     </modules>
 
     <profiles>
diff --git a/streampipes-maven-plugin/pom.xml b/streampipes-maven-plugin/pom.xml
new file mode 100644
index 0000000..7321c69
--- /dev/null
+++ b/streampipes-maven-plugin/pom.xml
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>streampipes-parent</artifactId>
+        <groupId>org.apache.streampipes</groupId>
+        <version>0.67.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>streampipes-maven-plugin</artifactId>
+    <packaging>maven-plugin</packaging>
+
+    <name>Apache StreamPipes Maven Plugin</name>
+
+    <prerequisites>
+        <maven>${maven.version}</maven>
+    </prerequisites>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <version.roaster>2.20.8.Final</version.roaster>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-artifact</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-compat</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <version>3.6.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-testing</groupId>
+            <artifactId>maven-plugin-testing-harness</artifactId>
+            <version>3.3.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.shared</groupId>
+            <artifactId>file-management</artifactId>
+            <version>3.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-interactivity-api</artifactId>
+            <version>1.0-alpha-6</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-component-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.forge.roaster</groupId>
+            <artifactId>roaster-api</artifactId>
+            <version>${version.roaster}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.forge.roaster</groupId>
+            <artifactId>roaster-jdt</artifactId>
+            <version>${version.roaster}</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.j2html</groupId>
+            <artifactId>j2html</artifactId>
+            <version>1.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+            <version>1.24</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-clean-plugin</artifactId>
+                    <version>3.1.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>3.0.2</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.8.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-plugin-plugin</artifactId>
+                    <version>3.6.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.22.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>3.0.2</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>2.5.2</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-deploy-plugin</artifactId>
+                    <version>2.8.2</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-invoker-plugin</artifactId>
+                    <version>3.1.0</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <version>3.6.0</version>
+                <configuration>
+                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>mojo-descriptor</id>
+                        <goals>
+                            <goal>descriptor</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>help-goal</id>
+                        <goals>
+                            <goal>helpmojo</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/CreateAssetMojo.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/CreateAssetMojo.java
new file mode 100644
index 0000000..e8af443
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/CreateAssetMojo.java
@@ -0,0 +1,108 @@
+/*
+ * 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.streampipes.smp;
+
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.streampipes.smp.extractor.ControllerFileFinder;
+import org.apache.streampipes.smp.generator.AssetGenerator;
+import org.apache.streampipes.smp.model.AssetModel;
+import org.apache.streampipes.smp.util.DuplicateRemover;
+import org.codehaus.plexus.components.interactivity.Prompter;
+import org.codehaus.plexus.components.interactivity.PrompterException;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Goal which creates an asset directory.
+ */
+@Mojo(name = "create-assets", defaultPhase = LifecyclePhase.NONE)
+public class CreateAssetMojo
+        extends AbstractMojo {
+
+  @Parameter(defaultValue = "${session}")
+  private MavenSession session;
+
+  @Parameter(defaultValue = "${project}", readonly = true)
+  private MavenProject project;
+
+  @Component
+  private Prompter prompter;
+
+  private static final String APP_ID_PROPERTY = "appId";
+  private static final String GENERATE_ALL_PROPERTY = "all";
+
+  public void execute() throws MojoExecutionException {
+
+    String appId = this.session.getExecutionProperties().getProperty(APP_ID_PROPERTY);
+    String addAll = this.session.getExecutionProperties().getProperty(GENERATE_ALL_PROPERTY);
+    File baseDir = this.project.getBasedir();
+
+    if (appId != null) {
+      getLog().info("Generating asset directory for element " + appId);
+      AssetModel assetModel = new AssetModel(appId, "Pipeline Element Name", "Pipeline Element " +
+              "Description");
+      new AssetGenerator(baseDir.getAbsolutePath(), assetModel);
+    }
+
+    if (addAll != null) {
+      List<String> sourceRoots = this.project.getCompileSourceRoots();
+      getLog().info("Generating asset directories for source root " + sourceRoots.get(0));
+
+      getLog().info("Finding controllers...");
+      List<AssetModel> allAssetModels =  new ControllerFileFinder(getLog(), baseDir.getAbsolutePath(),
+              sourceRoots.get(0),
+              "**/*Controller.java").makeAssetModels();
+
+      getLog().info("Checking for already existing asset directories...");
+
+      List<AssetModel> filteredModels =
+              new DuplicateRemover(baseDir.getAbsolutePath(), allAssetModels).removeAlreadyExisting();
+
+      try {
+        String proceed = prompter.prompt(makeProceedText(filteredModels));
+        if (proceed.equals("Y")) {
+          filteredModels.forEach(am -> new AssetGenerator(baseDir.getAbsolutePath(), am)
+           .genreateAssetDirectoryAndContents());
+        }
+      } catch (PrompterException e) {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private String makeProceedText(List<AssetModel> assetModels) {
+    StringBuilder builder = new StringBuilder();
+    builder.append("The following asset directories will be created: ");
+
+    assetModels.forEach(f -> builder.append(f.toString()));
+
+    builder.append("Proceed? [Y][N]");
+    return builder.toString();
+  }
+
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/ExtractDocumentationMojo.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/ExtractDocumentationMojo.java
new file mode 100644
index 0000000..e18eda2
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/ExtractDocumentationMojo.java
@@ -0,0 +1,189 @@
+/*
+ * 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.streampipes.smp;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.streampipes.smp.extractor.ControllerFileFinder;
+import org.apache.streampipes.smp.extractor.DockerImageExtractor;
+import org.apache.streampipes.smp.generator.*;
+import org.apache.streampipes.smp.model.AssetModel;
+import org.apache.streampipes.smp.util.DirectoryManager;
+import org.apache.streampipes.smp.util.Utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * goal which extracts pipeline element documentations for the StreamPipes website + documentation
+ */
+
+@Mojo(name = "extract-docs", defaultPhase = LifecyclePhase.NONE, aggregator = true)
+public class ExtractDocumentationMojo extends AbstractMojo {
+
+  private static final String DOCS_ROOT_FOLDER = "docs";
+  private static final String DOCS_FOLDER = "docs-documentation";
+  private static final String DOCS_WEBSITE_FOLDER = "docs-website";
+  private static final String IMG_FOLDER = "img";
+  private static final String SP_IGNORE_FILENAME = ".spignore";
+
+  @Parameter(defaultValue = "${session}")
+  private MavenSession session;
+
+  @Parameter(defaultValue = "${project}", readonly = true)
+  private MavenProject project;
+
+  @Override
+  public void execute() throws MojoExecutionException, MojoFailureException {
+    String targetDir = this.session.getExecutionRootDirectory() + File.separator + "target";
+    String spIgnoreFile =
+            this.session.getExecutionRootDirectory() + File.separator + SP_IGNORE_FILENAME;
+    Path docsBasePath = Paths.get(targetDir, DOCS_ROOT_FOLDER);
+
+    List<MavenProject> projects = session.getProjects();
+    List<AssetModel> documentedPipelineElements = new ArrayList<>();
+    List<String> pipelineElementsToExclude = new ArrayList<>();
+
+    if (Files.exists(Paths.get(spIgnoreFile))) {
+      try {
+        pipelineElementsToExclude = Files.readAllLines(Paths.get(spIgnoreFile));
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+    }
+
+    for (MavenProject currentModule : projects) {
+      File baseDir = currentModule.getBasedir();
+      List<String> sourceRoots = currentModule.getCompileSourceRoots();
+      //String targetDir = this.project.getModel().getBuild().getDirectory();
+
+      String dockerImageName =
+              new DockerImageExtractor(baseDir.getAbsolutePath()).extractImageName();
+
+      List<AssetModel> allAssetModels = new ArrayList<>(new ControllerFileFinder(getLog(),
+              baseDir.getAbsolutePath(), sourceRoots.get(0),
+              "**/*Controller.java").makeAssetModels());
+
+      allAssetModels.forEach(am -> {
+        am.setBaseDir(baseDir.getAbsolutePath());
+        am.setModuleName(currentModule.getName());
+        am.setContainerName(dockerImageName);
+      });
+
+      List<String> finalPipelineElementsToExclude = pipelineElementsToExclude;
+      documentedPipelineElements.addAll(
+              allAssetModels
+                      .stream()
+                      .filter(am -> finalPipelineElementsToExclude.stream().noneMatch(pe -> pe.equals(am.getAppId())))
+                      .filter(am -> new File(Utils.makePath(baseDir.getAbsolutePath(),
+                              am.getAppId())).exists())
+                      .collect(Collectors.toList()));
+
+    }
+    try {
+      Collections.sort(documentedPipelineElements);
+      documentedPipelineElements.forEach(am -> System.out.println(am.getAppId() + ", " + am.getPipelineElementName() + ", " + am.getPipelineElementDescription()));
+
+      for (AssetModel assetModel : documentedPipelineElements) {
+        Path docsPath = Paths.get(targetDir, DOCS_ROOT_FOLDER, DOCS_FOLDER,
+                assetModel.getAppId());
+        Path docsWebsitePath = Paths.get(targetDir, DOCS_ROOT_FOLDER, DOCS_WEBSITE_FOLDER,
+                assetModel.getAppId());
+        Path imgPath = Paths.get(targetDir, DOCS_ROOT_FOLDER, IMG_FOLDER,
+                assetModel.getAppId());
+        DirectoryManager.createIfNotExists(docsPath);
+        DirectoryManager.createIfNotExists(imgPath);
+
+        Boolean iconExists = Files.exists(Utils.makeResourcePath(assetModel.getBaseDir(),
+                assetModel.getAppId()).resolve("icon.png"));
+
+        if (iconExists) {
+          Files.copy(Utils.makeResourcePath(assetModel.getBaseDir(),
+                  assetModel.getAppId()).resolve("icon.png")
+                  , imgPath.resolve("icon.png"));
+        } else {
+          ClassLoader classLoader = this.getClass().getClassLoader();
+          InputStream inputStream = classLoader.getResourceAsStream("placeholder-icon.png");
+          Files.copy(inputStream, imgPath.resolve("icon.png"));
+        }
+
+        String originalDocumentationFileContents =
+                FileUtils.readFileToString(Utils.makeResourcePath(assetModel.getBaseDir(),
+                        assetModel.getAppId()).resolve("documentation.md").toFile());
+
+        // modify docs for documentation page
+        String documentationFileContents =
+                new MarkdownTitleRemover(originalDocumentationFileContents).removeTitle();
+
+        documentationFileContents =
+                new MarkdownHeaderGenerator(assetModel, documentationFileContents).createHeaders();
+
+        documentationFileContents = new ImagePathReplacer(documentationFileContents,
+                assetModel.getAppId()).replaceContentForDocs();
+
+        FileUtils.writeStringToFile(docsPath.resolve("documentation.md").toFile(),
+                documentationFileContents);
+
+        // modify docs for website
+        String websiteFileContents = new ImagePathReplacer(originalDocumentationFileContents,
+                assetModel.getAppId()).replaceContentForWebsite();
+
+        FileUtils.writeStringToFile(docsWebsitePath.resolve("documentation.md").toFile(),
+                websiteFileContents);
+      }
+
+      Boolean existsOverviewFile = Files.exists(docsBasePath.resolve("pipeline-elements.md"));
+      if (!existsOverviewFile) {
+        AssetModel assetModel = new AssetModel("pipeline-elements", "Overview", "");
+        String header = new MarkdownHeaderGenerator(assetModel, "").createHeaders();
+        FileUtils.writeStringToFile(docsBasePath.resolve("pipeline-elements.md").toFile(), header);
+      }
+
+      String pipelineElementOverviewContent = new PipelineElementOverviewGenerator(documentedPipelineElements).generate();
+      FileUtils.writeStringToFile(docsBasePath.resolve("pipeline-elements.md").toFile(),
+              pipelineElementOverviewContent, true);
+
+
+      FileUtils.writeStringToFile(docsBasePath.resolve("sidebars.json").toFile(),
+              new SidebarConfigGenerator(documentedPipelineElements).generate());
+
+      FileUtils.writeStringToFile(docsBasePath.resolve("_data.json").toFile(),
+              new DataJsonGenerator(documentedPipelineElements).generate());
+
+
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/constants/PeGridConst.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/constants/PeGridConst.java
new file mode 100644
index 0000000..7918561
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/constants/PeGridConst.java
@@ -0,0 +1,52 @@
+/*
+ * 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.streampipes.smp.constants;
+
+public class PeGridConst {
+
+  public static final String PE_GRID_CONTAINER = "pe-grid-container";
+  public static final String PE_CONTAINER_ITEM = "pe-container-item";
+
+  public static final String PE_CONTAINER_ITEM_PROCESSOR = "pe-container-item-processor";
+  public static final String PE_CONTAINER_ITEM_SINK = "pe-container-item-sink";
+
+  public static final String PE_CONTAINER_ITEM_HEADER = "pe-container-item-header";
+
+  public static final String PE_CONTAINER_ITEM_ICON = "pe-container-item-icon";
+  public static final String PE_ITEM_ICON_PROCESSOR = "pe-icon-processor";
+  public static final String PE_ITEM_ICON_SINK = "pe-icon-sink";
+  public static final String PE_ICON = "pe-icon";
+
+  public static final String PE_CONTAINER_ITEM_HEADER_PE = "pe-container-item-header-pe";
+
+  public static final String PE_CONTAINER_ITEM_LABEL = "pe-container-item-label";
+  public static final String PE_CONTAINER_ITEM_LABEL_PROCESSOR = "pe-container-item-label" +
+          "-processor";
+  public static final String PE_CONTAINER_ITEM_LABEL_SINK = "pe-container-item-label-sink";
+  public static final String PE_CONTAINER_ITEM_LABEL_NAME = "pe-container-item-label-name";
+
+  public static final String PE_CONTAINER_ITEM_BODY = "pe-container-item-body";
+  public static final String PE_CONTAINER_ITEM_FOOTER = "pe-container-item-footer";
+
+  public static final String FAS = "fas";
+  public static final String FA_FILE = "fa-file";
+  public static final String FAB = "fab";
+  public static final String FA_DOCKER = "fa-docker";
+  public static final String FA_GITHUB = "fa-github";
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/constants/PeType.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/constants/PeType.java
new file mode 100644
index 0000000..855c178
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/constants/PeType.java
@@ -0,0 +1,35 @@
+/*
+ * 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.streampipes.smp.constants;
+
+public enum PeType {
+  ADAPTER("Adapter"),
+  PROCESSOR("Data Processor"),
+  SINK("Data Sink");
+
+  private String friendly;
+
+  PeType(String friendly) {
+    this.friendly = friendly;
+  }
+
+  public String getFriendly() {
+    return friendly;
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/AssetModelItemExtractor.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/AssetModelItemExtractor.java
new file mode 100644
index 0000000..60d0c10
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/AssetModelItemExtractor.java
@@ -0,0 +1,90 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.streampipes.smp.constants.PeType;
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class AssetModelItemExtractor {
+
+  private static final String REGEX = "(DataSinkBuilder|ProcessingElementBuilder)\\.create\\" +
+          "((\".*?\"),.*?(\".*?\"),.*?(\".*?\")\\)";
+
+  private static final String ONLY_APP_ID_REGEX = "(DataSinkBuilder|ProcessingElementBuilder)\\" +
+          ".create\\" +
+          "((\".*?\")\\)";
+
+  private static final Pattern pattern = Pattern.compile(REGEX);
+  private static final Pattern onlyAppIdPattern = Pattern.compile(ONLY_APP_ID_REGEX);
+
+  private String declareModelContent;
+
+  public AssetModelItemExtractor(String declareModelContent) {
+    this.declareModelContent = declareModelContent
+            .replaceAll("\n", "");
+
+  }
+
+
+  public AssetModel extractAssetItem() throws IllegalArgumentException {
+    AssetModel assetModel = new AssetModel();
+    Matcher matcher = pattern.matcher(this.declareModelContent);
+    Boolean matches = false;
+
+//    while (matcher.find()) {
+//      matches = true;
+//      PeType peType = new PipelineElementTypeExtractor(matcher.group(1)).extractType();
+//      String appId = removeQuotes(matcher.group(2));
+//      String pipelineElementName = removeQuotes(matcher.group(3));
+//      String pipelineElementDescription = removeQuotes(matcher.group(4));
+//
+//      assetModel.setPeType(peType);
+//      assetModel.setAppId(appId);
+//      assetModel.setPipelineElementName(pipelineElementName);
+//      assetModel.setPipelineElementDescription(pipelineElementDescription);
+//
+//    }
+
+    if (matches) {
+      return assetModel;
+    } else {
+      Matcher appIdMatcher = onlyAppIdPattern.matcher(this.declareModelContent);
+      while (appIdMatcher.find()) {
+        matches = true;
+        PeType peType = new PipelineElementTypeExtractor(appIdMatcher.group(1)).extractType();
+        assetModel.setAppId(removeQuotes(appIdMatcher.group(2)));
+        assetModel.setPeType(peType);
+      }
+      if (!matches) {
+        throw new IllegalArgumentException("Could not extract appId");
+      } else {
+        return assetModel;
+      }
+    }
+  }
+
+  private String removeQuotes(String text) {
+    return text
+            .replaceAll("\" \\+ \"", "")
+            .replaceAll("\"", "");
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/ControllerExtractor.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/ControllerExtractor.java
new file mode 100644
index 0000000..a7700f3
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/ControllerExtractor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.streampipes.smp.model.AssetModel;
+import org.jboss.forge.roaster.Roaster;
+import org.jboss.forge.roaster.model.source.JavaClassSource;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class ControllerExtractor {
+
+  private String filename;
+  private String baseDir;
+  private static String DECLARE_MODEL_METHOD = "declareModel";
+
+  public ControllerExtractor(String baseDir, String filename) {
+    this.filename = filename;
+    this.baseDir = baseDir;
+  }
+
+  public AssetModel extractControllerDetails() throws Exception {
+    String fileContents = new String(Files.readAllBytes(Paths.get(filename)));
+    JavaClassSource clazz = Roaster.parse(JavaClassSource.class, fileContents);
+    if (clazz.hasMethodSignature(DECLARE_MODEL_METHOD)) {
+      String declareMethodContent = (clazz.getMethod(DECLARE_MODEL_METHOD).getBody());
+      declareMethodContent =
+              new FieldReplacer(clazz, declareMethodContent).replaceDeclareModelContent();
+      AssetModel assetModel = new AssetModelItemExtractor(declareMethodContent).extractAssetItem();
+      if (assetModel.getPipelineElementName() == null) {
+        assetModel = new LocalesExtractor(baseDir, assetModel).extract();
+      }
+      return assetModel;
+
+    } else {
+      throw new Exception("Not a valid controller class or could not read id elements");
+    }
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/ControllerFileFinder.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/ControllerFileFinder.java
new file mode 100644
index 0000000..274436e
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/ControllerFileFinder.java
@@ -0,0 +1,65 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.shared.model.fileset.FileSet;
+import org.apache.maven.shared.model.fileset.util.FileSetManager;
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ControllerFileFinder {
+
+  private String sourceRoot;
+  private String filterPattern;
+  private Log log;
+  private String baseDir;
+
+  public ControllerFileFinder(Log log, String baseDir, String sourceRoot, String filterPattern) {
+    this.sourceRoot = sourceRoot;
+    this.filterPattern = filterPattern;
+    this.log = log;
+    this.baseDir = baseDir;
+  }
+
+  public String[] findFiles() {
+    FileSet fileSet = new FileSet();
+    fileSet.setDirectory(sourceRoot);
+    fileSet.addInclude(filterPattern);
+    FileSetManager fileSetManager = new FileSetManager();
+
+    return fileSetManager.getIncludedFiles(fileSet);
+  }
+
+  public List<AssetModel> makeAssetModels() {
+    List<AssetModel> allAssetModels = new ArrayList<>();
+    for (String file : findFiles()) {
+      try {
+        allAssetModels.add(new ControllerExtractor(baseDir, sourceRoot + File.separator + file).extractControllerDetails());
+      } catch (Exception e) {
+        log.error(e.getMessage());
+        log.info("Could not parse file " + file + ", skipping...");
+      }
+    }
+    return allAssetModels;
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/DockerImageExtractor.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/DockerImageExtractor.java
new file mode 100644
index 0000000..3a9d357
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/DockerImageExtractor.java
@@ -0,0 +1,77 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class DockerImageExtractor {
+
+  private static final String Deployment = "deployment";
+  private static final String DockerCompose = "docker-compose.yml";
+  private static final String Image = "image";
+  private static final String Services = "services";
+  private static final String Colon = ":";
+  private static final String ImagePrefix = "${SP_PE_DOCKER_REGISTRY}/streampipes" +
+          "/streampipes" +
+          "-pipeline-elements/";
+
+  private String baseDir;
+
+  public DockerImageExtractor(String baseDir) {
+    this.baseDir = baseDir;
+  }
+
+  public String extractImageName() {
+    Path dockerComposePath = Paths.get(baseDir, Deployment, DockerCompose);
+
+    Yaml yaml = new Yaml();
+    try {
+      Map<String, Object> fileContents =
+              yaml.load(new String(Files.readAllBytes(dockerComposePath)));
+
+      return extractNameFromYaml(fileContents);
+
+    } catch (IOException e) {
+      e.printStackTrace();
+      return "";
+    }
+  }
+
+  public String extractNameFromYaml(Map<String, Object> fileContents) {
+    Map<String, Object> services = (Map<String, Object>) fileContents.get(Services);
+    AtomicReference<String> imageName = new AtomicReference<>("");
+    if (services.size() > 0) {
+      services.forEach((key, value) -> imageName.set(parseValue(((Map<String,
+              Object>) value).get(Image).toString())));
+    }
+
+    return imageName.get();
+  }
+
+  private String parseValue(String imageName) {
+    return imageName.replace(ImagePrefix, "").split(Colon)[0];
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/FieldReplacer.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/FieldReplacer.java
new file mode 100644
index 0000000..081e514
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/FieldReplacer.java
@@ -0,0 +1,59 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.jboss.forge.roaster.model.source.JavaClassSource;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class FieldReplacer {
+
+  private String declareModelContent;
+  private JavaClassSource source;
+
+  private static final String CHECK_FIELD_REGEX = "(DataSinkBuilder|ProcessingElementBuilder)\\" +
+          ".create\\" +
+          "((.*?),(.*?)\\)";
+  private static final Pattern checkFieldPattern = Pattern.compile(CHECK_FIELD_REGEX);
+
+
+  public FieldReplacer(JavaClassSource source, String declareModelContent) {
+    this.source = source;
+    this.declareModelContent = declareModelContent;
+  }
+
+  public String replaceDeclareModelContent() {
+    Matcher matcher = checkFieldPattern.matcher(this.declareModelContent);
+    while(matcher.find()) {
+      String match = matcher.group(2);
+      if (!match.startsWith("\"")) {
+        declareModelContent = declareModelContent.replaceFirst(match,
+                getFieldValue(match));
+      }
+    }
+    return declareModelContent;
+  }
+
+  private String getFieldValue(String fieldName) {
+    return "\""
+            + source.getField(fieldName).getStringInitializer()
+            + "\"";
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/LocalesExtractor.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/LocalesExtractor.java
new file mode 100644
index 0000000..3c46a27
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/LocalesExtractor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.streampipes.smp.model.AssetModel;
+import org.apache.streampipes.smp.util.Utils;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Properties;
+
+public class LocalesExtractor {
+
+  private AssetModel assetModel;
+  private String baseDir;
+
+  private static final String TITLE = ".title";
+  private static final String DESCRIPTION = ".description";
+
+  public LocalesExtractor(String baseDir, AssetModel assetModel) {
+    this.baseDir = baseDir;
+    this.assetModel = assetModel;
+  }
+
+  public AssetModel extract() throws IOException {
+    String localesPath = Utils.makeLocalesPath(baseDir, assetModel.getAppId());
+    Properties props = loadProperties(localesPath);
+
+    assetModel.setPipelineElementName(extractKey(props, assetModel, TITLE));
+    assetModel.setPipelineElementDescription(extractKey(props, assetModel, DESCRIPTION));
+
+    return assetModel;
+  }
+
+  private String extractKey(Properties props, AssetModel assetModel, String appendix) {
+    return props.getProperty(assetModel.getAppId() + appendix);
+  }
+
+  private Properties loadProperties(String localesPath) throws IOException {
+    Properties props = new Properties();
+    props.load(new FileReader(localesPath));
+    return props;
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/PipelineElementTypeExtractor.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/PipelineElementTypeExtractor.java
new file mode 100644
index 0000000..462a72f
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/extractor/PipelineElementTypeExtractor.java
@@ -0,0 +1,43 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.streampipes.smp.constants.PeType;
+
+public class PipelineElementTypeExtractor {
+
+  private static final String ProcessorString = "ProcessingElementBuilder";
+  private static final String SinkString = "DataSinkBuilder";
+
+  private String typeString;
+
+  public PipelineElementTypeExtractor(String typeString) {
+    this.typeString = typeString;
+  }
+
+  public PeType extractType() throws IllegalArgumentException {
+    if (typeString.equals(ProcessorString)) {
+      return PeType.PROCESSOR;
+    } else if (typeString.equals(SinkString)) {
+      return PeType.SINK;
+    } else {
+      throw new IllegalArgumentException("Unknown pipeline element type " +typeString);
+    }
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/AssetGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/AssetGenerator.java
new file mode 100644
index 0000000..664f640
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/AssetGenerator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.streampipes.smp.model.AssetModel;
+import org.apache.streampipes.smp.parser.DocumentationParser;
+import org.apache.streampipes.smp.util.Utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class AssetGenerator {
+
+  private AssetModel assetModel;
+  private String baseDir;
+
+  private static final String DOCUMENTATION_FILE = "documentation.md";
+
+  public AssetGenerator(String baseDir, AssetModel assetModel) {
+    this.assetModel = assetModel;
+    this.baseDir = baseDir;
+  }
+
+  public void genreateAssetDirectoryAndContents() {
+    ClassLoader classLoader = this.getClass().getClassLoader();
+    String resourcePath = Utils.makePath(baseDir, assetModel.getAppId());
+
+    Boolean dir = new File(resourcePath).mkdirs();
+    InputStream inputStream = classLoader.getResourceAsStream(DOCUMENTATION_FILE);
+    try {
+      String content =
+              new DocumentationParser(assetModel)
+                      .parseAndStoreDocumentation(IOUtils.toString(inputStream));
+      FileUtils.writeStringToFile(new File(resourcePath + File.separator + DOCUMENTATION_FILE),
+              content);
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/DataJsonGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/DataJsonGenerator.java
new file mode 100644
index 0000000..5b0059e
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/DataJsonGenerator.java
@@ -0,0 +1,73 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.util.List;
+
+public class DataJsonGenerator extends OutputGenerator {
+
+  public DataJsonGenerator(List<AssetModel> assetModels) {
+    super(assetModels);
+  }
+
+  @Override
+  public String generate() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.add("pipelineElements", makePipelineElementList());
+
+    return jsonObject.toString();
+  }
+
+  private JsonArray makePipelineElementList() {
+    JsonArray elementList = new JsonArray();
+
+    assetModels.forEach(am -> {
+      elementList.add(makePipelineElementEntry(am));
+    });
+
+    return elementList;
+  }
+
+  private JsonObject makePipelineElementEntry(AssetModel am) {
+    JsonObject entry = new JsonObject();
+    entry.addProperty("appId", am.getAppId());
+    entry.addProperty("type", am.getPeType().getFriendly());
+    entry.addProperty("name", am.getPipelineElementName());
+    entry.addProperty("description", am.getPipelineElementDescription());
+    entry.addProperty("dockerHubLink", makeDockerHubLink(am.getModuleName()));
+    entry.addProperty("githubLink", makeGithubLink(am.getModuleName()));
+
+    return entry;
+  }
+
+  private String makeDockerHubLink(String moduleName) {
+    String dockerHubRepoName = moduleName.replace("streampipes-", "");
+    return "https://hub.docker.com/r/apachestreampipes/" +dockerHubRepoName;
+  }
+
+  private String makeGithubLink(String moduleName) {
+    return "https://github.com/apache/incubator-streampipes-extensions/tree/dev/" + moduleName;
+  }
+
+
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/ImagePathReplacer.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/ImagePathReplacer.java
new file mode 100644
index 0000000..cda528f
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/ImagePathReplacer.java
@@ -0,0 +1,59 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ImagePathReplacer {
+
+  private static final String IMAGE_REGEX = "(<img.*src=\")(.*)(\")";
+  private static final Pattern pattern = Pattern.compile(IMAGE_REGEX);
+
+  private static final String DOCS_PREFIX = "/docs/img/pipeline-elements/";
+  private static final String WEBSITE_PREFIX = "/img/pipeline-elements/";
+
+  private String originalContent;
+  private String appId;
+
+  public ImagePathReplacer(String originalContent, String appId) {
+    this.originalContent = originalContent;
+    this.appId = appId;
+  }
+
+  public String replaceContentForDocs() {
+    return replaceContent(DOCS_PREFIX);
+  }
+
+  public String replaceContentForWebsite() {
+    return replaceContent(WEBSITE_PREFIX);
+  }
+
+  public String replaceContent(String prefix) {
+    String newContent;
+    Matcher matcher = pattern.matcher(originalContent);
+    newContent = matcher.replaceAll("$1" + getUrl(prefix) + "$2$3");
+
+    return newContent;
+  }
+
+  private String getUrl(String prefix) {
+    return prefix + appId + "/";
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/MarkdownHeaderGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/MarkdownHeaderGenerator.java
new file mode 100644
index 0000000..c810620
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/MarkdownHeaderGenerator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import org.apache.streampipes.smp.model.AssetModel;
+
+public class MarkdownHeaderGenerator {
+
+  private AssetModel assetModel;
+  private String markdown;
+
+  public MarkdownHeaderGenerator(AssetModel assetModel, String markdown) {
+    this.assetModel = assetModel;
+    this.markdown = markdown;
+  }
+
+  public String createHeaders() {
+    StringBuilder builder = new StringBuilder();
+    builder
+            .append("---\n")
+            .append("id: ")
+            .append(assetModel.getAppId())
+            .append("\n")
+            .append("title: ")
+            .append(assetModel.getPipelineElementName())
+            .append("\n")
+            .append("sidebar_label: ")
+            .append(assetModel.getPipelineElementName())
+            .append("\n")
+            .append("---\n\n")
+            .append(markdown);
+
+    return builder.toString();
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/MarkdownTitleRemover.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/MarkdownTitleRemover.java
new file mode 100644
index 0000000..67dc71d
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/MarkdownTitleRemover.java
@@ -0,0 +1,32 @@
+/*
+ * 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.streampipes.smp.generator;
+
+public class MarkdownTitleRemover {
+
+  private String markdown;
+
+  public MarkdownTitleRemover(String markdown) {
+    this.markdown = markdown;
+  }
+
+  public String removeTitle() {
+    return markdown.replaceFirst("(?m)^\\#\\#.*", "");
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/OutputGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/OutputGenerator.java
new file mode 100644
index 0000000..75186a3
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/OutputGenerator.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.streampipes.smp.generator;
+
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.util.List;
+
+public abstract class OutputGenerator {
+
+  protected List<AssetModel> assetModels;
+
+  public OutputGenerator(List<AssetModel> assetModels) {
+    this.assetModels = assetModels;
+  }
+
+  public abstract String generate();
+
+
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/PipelineElementGridGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/PipelineElementGridGenerator.java
new file mode 100644
index 0000000..796cecc
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/PipelineElementGridGenerator.java
@@ -0,0 +1,151 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import j2html.tags.DomContent;
+import org.apache.streampipes.smp.constants.PeGridConst;
+import org.apache.streampipes.smp.constants.PeType;
+import org.apache.streampipes.smp.model.AssetModel;
+
+import static j2html.TagCreator.*;
+
+public class PipelineElementGridGenerator {
+
+  private static final String IMG_PATH_PREFIX = "/docs/img/pipeline-elements/";
+  private static final String IMG_PATH_APPENDIX = "/icon.png";
+
+  private static final String DOCUMENTATION = "Documentation";
+  private static final String GITHUB = "Code on Github";
+  private static final String DOCKER_HUB = "Docker Container";
+
+  private static final String STREAMPIPES_GITHUB_URL = "https://www.github" +
+          ".com/apache/incubator-streampipes-extensions/tree/dev/";
+
+  private static final String DOCKER_HUB_URL = "https://hub.docker.com/r/streampipes/";
+
+  private AssetModel assetModel;
+
+  public PipelineElementGridGenerator(AssetModel assetModel) {
+    this.assetModel = assetModel;
+  }
+
+  public DomContent makeGrid() {
+    return makeContainerItem();
+  }
+
+  private DomContent makeContainerItem() {
+    return div(makeContainerItemHeader(),
+            makeContainerItemBody(),
+            makeContainerItemFooter()).withClasses(PeGridConst.PE_CONTAINER_ITEM,
+            getContainerItemType());
+  }
+
+  private DomContent makeContainerItemFooter() {
+    return div(makeFile(), makeDocker(), makeGithub()).withClass(PeGridConst.PE_CONTAINER_ITEM_FOOTER);
+  }
+
+  private DomContent makeGithub() {
+    return div(makeGithubIcon(), makeBlank(), makeGithubLink());
+  }
+
+  private DomContent makeGithubLink() {
+    return a(GITHUB).withHref(STREAMPIPES_GITHUB_URL + assetModel.getModuleName());
+  }
+
+  private DomContent makeGithubIcon() {
+    return i().withClasses(PeGridConst.FAB, PeGridConst.FA_GITHUB);
+  }
+
+  private DomContent makeDocker() {
+    return div(makeDockerIcon(), makeBlank(), makeDockerLink());
+  }
+
+  private DomContent makeDockerLink() {
+    return a(DOCKER_HUB).withHref(DOCKER_HUB_URL + assetModel.getModuleName().replace("streampipes-", ""));
+  }
+
+  private DomContent makeDockerIcon() {
+    return i().withClasses(PeGridConst.FAB, PeGridConst.FA_DOCKER);
+  }
+
+  private DomContent makeFile() {
+    return div(makeFileIcon(), makeBlank(), makeDocumentationLink());
+  }
+
+  private DomContent makeDocumentationLink() {
+    return a(DOCUMENTATION).withHref("/docs/docs/" + assetModel.getAppId() + "/" +assetModel.getAppId());
+  }
+
+  private DomContent makeBlank() {
+    return text("  ");
+  }
+
+  private DomContent makeFileIcon() {
+    return i().withClasses(PeGridConst.FAS, PeGridConst.FA_FILE);
+  }
+
+  private DomContent makeContainerItemBody() {
+    return div(assetModel.getPipelineElementDescription()).withClass(PeGridConst.PE_CONTAINER_ITEM_BODY);
+  }
+
+  private DomContent makeContainerItemHeader() {
+    return div(makeContainerItemIconWrapper(),
+            makeContainerItemHeaderPe()).withClass(PeGridConst.PE_CONTAINER_ITEM_HEADER);
+  }
+
+  private DomContent makeContainerItemHeaderPe() {
+    return div(makeContainerItemLabel(), makeContainerItemLabelName()).withClass(PeGridConst.PE_CONTAINER_ITEM_HEADER_PE);
+  }
+
+  private DomContent makeContainerItemLabelName() {
+    return div(assetModel.getPipelineElementName()).withClass(PeGridConst.PE_CONTAINER_ITEM_LABEL_NAME);
+  }
+
+  private DomContent makeContainerItemLabel() {
+    return div(makeLabelText()).withClasses(PeGridConst.PE_CONTAINER_ITEM_LABEL, makeLabelType());
+  }
+
+  private String makeLabelText() {
+    return assetModel.getPeType().equals(PeType.PROCESSOR) ? "Data Processor" : "Data Sink";
+  }
+
+  private String makeLabelType() {
+    return assetModel.getPeType().equals(PeType.PROCESSOR) ? PeGridConst.PE_CONTAINER_ITEM_LABEL_PROCESSOR :
+            PeGridConst.PE_CONTAINER_ITEM_LABEL_SINK;
+  }
+
+  private DomContent makeContainerItemIconWrapper() {
+    return div(makeIconImg()).withClasses(PeGridConst.PE_CONTAINER_ITEM_ICON, makeIconType());
+  }
+
+  private DomContent makeIconImg() {
+    return img().withClass(PeGridConst.PE_ICON).withSrc(IMG_PATH_PREFIX + assetModel.getAppId() + IMG_PATH_APPENDIX);
+  }
+
+  private String makeIconType() {
+    return assetModel.getPeType().equals(PeType.PROCESSOR) ? PeGridConst.PE_ITEM_ICON_PROCESSOR :
+            PeGridConst.PE_ITEM_ICON_SINK;
+  }
+
+  private String getContainerItemType() {
+    return assetModel.getPeType().equals(PeType.PROCESSOR) ? PeGridConst.PE_CONTAINER_ITEM_PROCESSOR :
+            PeGridConst.PE_CONTAINER_ITEM_SINK;
+  }
+
+}
\ No newline at end of file
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/PipelineElementOverviewGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/PipelineElementOverviewGenerator.java
new file mode 100644
index 0000000..af5f0c6
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/PipelineElementOverviewGenerator.java
@@ -0,0 +1,52 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import j2html.tags.ContainerTag;
+import j2html.tags.DomContent;
+import org.apache.streampipes.smp.constants.PeGridConst;
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.util.List;
+
+import static j2html.TagCreator.div;
+
+public class PipelineElementOverviewGenerator extends OutputGenerator {
+
+  public PipelineElementOverviewGenerator(List<AssetModel> assetModels) {
+    super(assetModels);
+  }
+
+  public String generate() {
+
+    ContainerTag gridContent = div().withClass(PeGridConst.PE_GRID_CONTAINER);
+    for(AssetModel am : assetModels) {
+      gridContent.with(makeGrid(am));
+    }
+    String markdownContent = gridContent.render();
+    return markdownContent;
+    //return new MarkdownHeaderGenerator(assetModel, markdownContent).createHeaders();
+  }
+
+  private DomContent makeGrid(AssetModel assetModel) {
+    return new PipelineElementGridGenerator(assetModel).makeGrid();
+  }
+
+
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/SidebarConfigGenerator.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/SidebarConfigGenerator.java
new file mode 100644
index 0000000..b8081e4
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/generator/SidebarConfigGenerator.java
@@ -0,0 +1,45 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.util.List;
+
+public class SidebarConfigGenerator extends OutputGenerator {
+
+
+  public SidebarConfigGenerator(List<AssetModel> assetModels) {
+    super(assetModels);
+  }
+
+  public String generate() {
+    JsonArray pipelineElements = new JsonArray();
+    assetModels.forEach(pe -> pipelineElements.add(pe.getAppId() + "/" + pe.getAppId()));
+
+    JsonObject pipelineElementObject = new JsonObject();
+    pipelineElementObject.add("Pipeline Elements", pipelineElements);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.add("pipeline-elements", pipelineElementObject);
+
+    return jsonObject.toString();
+  }
+}
\ No newline at end of file
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/model/AssetModel.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/model/AssetModel.java
new file mode 100644
index 0000000..5446da3
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/model/AssetModel.java
@@ -0,0 +1,108 @@
+/*
+ * 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.streampipes.smp.model;
+
+import org.apache.streampipes.smp.constants.PeType;
+
+public class AssetModel implements Comparable<AssetModel> {
+
+  private String appId;
+  private String pipelineElementName;
+  private String pipelineElementDescription;
+  private PeType peType = PeType.PROCESSOR;
+  private String moduleName = "";
+  private String containerName = "";
+  private String baseDir;
+
+  public AssetModel() {
+
+  }
+
+  public AssetModel(String appId, String pipelineElementName, String pipelineElementDescription) {
+    this.appId = appId;
+    this.pipelineElementName = pipelineElementName;
+    this.pipelineElementDescription = pipelineElementDescription;
+  }
+
+  public String getAppId() {
+    return appId;
+  }
+
+  public void setAppId(String appId) {
+    this.appId = appId;
+  }
+
+  public String getPipelineElementName() {
+    return pipelineElementName;
+  }
+
+  public void setPipelineElementName(String pipelineElementName) {
+    this.pipelineElementName = pipelineElementName;
+  }
+
+  public String getPipelineElementDescription() {
+    return pipelineElementDescription;
+  }
+
+  public void setPipelineElementDescription(String pipelineElementDescription) {
+    this.pipelineElementDescription = pipelineElementDescription;
+  }
+
+  public PeType getPeType() {
+    return peType;
+  }
+
+  public void setPeType(PeType peType) {
+    this.peType = peType;
+  }
+
+  public String getModuleName() {
+    return moduleName;
+  }
+
+  public String getContainerName() {
+    return containerName;
+  }
+
+  public void setModuleName(String moduleName) {
+    this.moduleName = moduleName;
+  }
+
+  public void setContainerName(String containerName) {
+    this.containerName = containerName;
+  }
+
+  public String getBaseDir() {
+    return baseDir;
+  }
+
+  public void setBaseDir(String baseDir) {
+    this.baseDir = baseDir;
+  }
+
+  @Override
+  public String toString() {
+    return pipelineElementName + " (" + peType.toString() + ", " + appId + "): " +
+            pipelineElementDescription + "\n";
+  }
+
+  public int compareTo(AssetModel other) {
+    return pipelineElementName.compareTo(other.getPipelineElementName());
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/DocumentationParser.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/DocumentationParser.java
new file mode 100644
index 0000000..bb2773d
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/DocumentationParser.java
@@ -0,0 +1,41 @@
+/*
+ * 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.streampipes.smp.parser;
+
+import org.apache.streampipes.smp.model.AssetModel;
+
+public class DocumentationParser {
+
+  private AssetModel assetModel;
+
+  public DocumentationParser(AssetModel assetModel) {
+    this.assetModel = assetModel;
+  }
+
+  public String parseAndStoreDocumentation(String markdown) {
+
+    markdown = new PipelineElementNameReplacer(assetModel.getPipelineElementName(),
+            markdown).replace();
+    markdown = new PipelineElementDescriptionReplacer(assetModel.getPipelineElementDescription(),
+            markdown).replace();
+
+    return markdown;
+
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PipelineElementDescriptionReplacer.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PipelineElementDescriptionReplacer.java
new file mode 100644
index 0000000..b2e4dff
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PipelineElementDescriptionReplacer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.streampipes.smp.parser;
+
+import java.util.regex.Pattern;
+
+public class PipelineElementDescriptionReplacer extends PlaceholderReplacer {
+
+  private static final String PLACEHOLDER = "pipelineElementDescription";
+  private static final String REGEX = "(\\$\\{" +PLACEHOLDER + ")(.*)(})";
+  private static final Pattern pattern = Pattern.compile(REGEX);
+
+  public PipelineElementDescriptionReplacer(String newContent, String markdown) {
+    super(newContent, markdown);
+  }
+
+
+  @Override
+  protected Pattern getPattern() {
+    return pattern;
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PipelineElementNameReplacer.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PipelineElementNameReplacer.java
new file mode 100644
index 0000000..cd04963
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PipelineElementNameReplacer.java
@@ -0,0 +1,40 @@
+/*
+ * 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.streampipes.smp.parser;
+
+import java.util.regex.Pattern;
+
+public class PipelineElementNameReplacer extends PlaceholderReplacer {
+
+  private static final String PLACEHOLDER = "pipelineElementName";
+  private static final String REGEX = "(\\$\\{" +PLACEHOLDER + ")(.*)(})";
+  private static final Pattern pattern = Pattern.compile(REGEX);
+
+  public PipelineElementNameReplacer(String pipelineElementName, String markdown) {
+    super(pipelineElementName, markdown);
+  }
+
+
+  @Override
+  protected Pattern getPattern() {
+    return pattern;
+  }
+
+
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PlaceholderReplacer.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PlaceholderReplacer.java
new file mode 100644
index 0000000..53e7423
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/parser/PlaceholderReplacer.java
@@ -0,0 +1,42 @@
+/*
+ * 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.streampipes.smp.parser;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public abstract class PlaceholderReplacer {
+
+  private String newContent;
+  private String markdown;
+
+  public PlaceholderReplacer(String newContent, String markdown) {
+    this.newContent = newContent;
+    this.markdown = markdown;
+  }
+
+  public String replace() {
+    Matcher matcher = getPattern().matcher(markdown);
+    markdown = matcher.replaceAll(newContent);
+
+    return markdown;
+  }
+
+  protected abstract Pattern getPattern();
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/DirectoryManager.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/DirectoryManager.java
new file mode 100644
index 0000000..dae482f
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/DirectoryManager.java
@@ -0,0 +1,32 @@
+/*
+ * 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.streampipes.smp.util;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class DirectoryManager {
+
+  public static void createIfNotExists(Path directory) throws IOException {
+    if (!Files.exists(directory)) {
+      Files.createDirectories(directory);
+    }
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/DuplicateRemover.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/DuplicateRemover.java
new file mode 100644
index 0000000..f157a2c
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/DuplicateRemover.java
@@ -0,0 +1,45 @@
+/*
+ * 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.streampipes.smp.util;
+
+import org.apache.streampipes.smp.model.AssetModel;
+
+import java.io.File;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class DuplicateRemover {
+
+  private List<AssetModel> assetModels;
+  private String sourceDir;
+
+  public DuplicateRemover(String sourceDir, List<AssetModel> assetModels) {
+    this.assetModels = assetModels;
+    this.sourceDir = sourceDir;
+  }
+
+  public List<AssetModel> removeAlreadyExisting() {
+
+    return assetModels
+            .stream()
+            .filter(am -> !(new File(Utils.makePath(sourceDir, am.getAppId() + File.separator +
+                    "documentation.md")).exists()))
+            .collect(Collectors.toList());
+  }
+}
diff --git a/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/Utils.java b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/Utils.java
new file mode 100644
index 0000000..94f8b3b
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/java/org/apache/streampipes/smp/util/Utils.java
@@ -0,0 +1,47 @@
+/*
+ * 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.streampipes.smp.util;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class Utils {
+
+  public static String makePath(String sourceRoot, String appId) {
+    return sourceRoot
+            + File.separator
+            + "src"
+            + File.separator
+            + "main"
+            + File.separator
+            + "resources"
+            + File.separator
+            + appId;
+  }
+
+  public static Path makeResourcePath(String sourcePath, String appId) {
+    return Paths.get(sourcePath, "src", "main", "resources", appId);
+  }
+
+  public static String makeLocalesPath(String sourceRoot, String appId) {
+    return makePath(sourceRoot, appId) + File.separator + "strings.en";
+  }
+
+}
diff --git a/streampipes-maven-plugin/src/main/resources/docker-compose.yml b/streampipes-maven-plugin/src/main/resources/docker-compose.yml
new file mode 100644
index 0000000..6fa9154
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/resources/docker-compose.yml
@@ -0,0 +1,28 @@
+# 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.
+
+version: "2"
+services:
+  processors-text-mining-flink:
+    image: ${SP_DOCKER_REGISTRY}/streampipes/streampipes-pipeline-elements/processors-text-mining-flink:${SP_PE_VERSION}
+    depends_on:
+      - "consul"
+#    ports:
+#      - "8098:8090"
+    environment:
+      - SP_ICON_HOST=${SP_ICON_HOST}
+    networks:
+      spnet:
+
diff --git a/streampipes-maven-plugin/src/main/resources/documentation.md b/streampipes-maven-plugin/src/main/resources/documentation.md
new file mode 100644
index 0000000..a0b07ca
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/resources/documentation.md
@@ -0,0 +1,48 @@
+<!--
+  ~ 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.
+  ~
+  -->
+
+## ${pipelineElementName}
+
+<p align="center"> 
+    <img src="icon.png" width="150px;"/>
+</p>
+
+***
+
+## Description
+
+${pipelineElementDescription}
+Add a detailed description here
+
+***
+
+## Required input
+
+
+***
+
+## Configuration
+
+Describe the configuration parameters here
+
+### 1st parameter
+
+
+### 2nd parameter
+
+## Output
\ No newline at end of file
diff --git a/streampipes-maven-plugin/src/main/resources/expected.documentation.md b/streampipes-maven-plugin/src/main/resources/expected.documentation.md
new file mode 100644
index 0000000..4f9efea
--- /dev/null
+++ b/streampipes-maven-plugin/src/main/resources/expected.documentation.md
@@ -0,0 +1,48 @@
+<!--
+  ~ 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.
+  ~
+  -->
+
+## Numerical Filter
+
+<p align="center"> 
+    <img src="icon.png" width="150px;"/>
+</p>
+
+***
+
+## Description
+
+Numerical Filter Description
+Add a detailed description here
+
+***
+
+## Required input
+
+
+***
+
+## Configuration
+
+Describe the configuration parameters here
+
+### 1st parameter
+
+
+### 2nd parameter
+
+## Output
\ No newline at end of file
diff --git a/streampipes-maven-plugin/src/main/resources/placeholder-icon.png b/streampipes-maven-plugin/src/main/resources/placeholder-icon.png
new file mode 100644
index 0000000..dcd55fc
Binary files /dev/null and b/streampipes-maven-plugin/src/main/resources/placeholder-icon.png differ
diff --git a/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/extractor/TestAssetModelExtractor.java b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/extractor/TestAssetModelExtractor.java
new file mode 100644
index 0000000..87dd9b2
--- /dev/null
+++ b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/extractor/TestAssetModelExtractor.java
@@ -0,0 +1,107 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.streampipes.smp.constants.PeType;
+import org.apache.streampipes.smp.model.AssetModel;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class TestAssetModelExtractor {
+
+  private String declareModelContent = "return ProcessingElementBuilder.create(\"org.apache.streampipes.processors.filters.jvm.numericalfilter\", \"Numerical Filter\", \"Numerical Filter Description\")\n" +
+          "            .category(DataProcessorType.FILTER)\n" +
+          "            .providesAssets(Assets.DOCUMENTATION, Assets.ICON)\n" +
+          "            .requiredStream(StreamRequirementsBuilder\n" +
+          "                    .create()\n" +
+          "                    .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),\n" +
+          "                            Labels.from(NUMBER_MAPPING, \"Field\", \"Specifies the field name where \"\n" +
+          "                                    + \"the filter operation should be applied on.\"),\n" +
+          "                            PropertyScope.NONE).build())\n" +
+          "            .outputStrategy(OutputStrategies.keep())\n" +
+          "            .requiredSingleValueSelection(Labels.from(OPERATION, \"Filter Operation\", \"Specifies the filter \" +\n" +
+          "                    \"operation that should be applied on the field\"), Options.from(\"<\", \"<=\", \">\", \">=\", \"==\", \"!=\"))\n" +
+          "            .requiredFloatParameter(Labels.from(VALUE, \"Threshold value\", \"Specifies a threshold value.\"), \"number\")\n" +
+          "            .supportedProtocols(SupportedProtocols.kafka(), SupportedProtocols.jms())\n" +
+          "            .supportedFormats(SupportedFormats.jsonFormat())\n" +
+          "            .build();";
+
+  private String declareModelContent2 = "return ProcessingElementBuilder.create(\"org.apache.streampipes.processors.filters.jvm.processor.mergestartandend\",\n" +
+          "            \"MergeStartAndEnd\", \"Merges two event streams if there is a start and an end\")\n" +
+          "            .category(DataProcessorType.TRANSFORM)\n" +
+          "            .iconUrl(FiltersJvmConfig.getIconUrl(\"projection\"))\n" +
+          "            .requiredStream(StreamRequirementsBuilder\n" +
+          "                    .create()\n" +
+          "                    .requiredProperty(EpRequirements.anyProperty())\n" +
+          "                    .build())\n" +
+          "            .requiredStream(StreamRequirementsBuilder\n" +
+          "                    .create()\n" +
+          "                    .requiredProperty(EpRequirements.anyProperty())\n" +
+          "                .build())\n" +
+          "            .outputStrategy(OutputStrategies.custom(true))\n" +
+          "            .supportedFormats(SupportedFormats.jsonFormat())\n" +
+          "            .supportedProtocols(SupportedProtocols.jms(), SupportedProtocols.kafka())\n" +
+          "            .build();";
+
+  private String getDeclareModelContent3 = "return DataSinkBuilder.create(\"org.apache.streampipes.sinks.brokers.jvm.jms\")\n" +
+          "            .withLocales(Locales.EN)\n" +
+          "            .withAssets(Assets.DOCUMENTATION, Assets.ICON)\n" +
+          "            .requiredStream(StreamRequirementsBuilder\n" +
+          "                    .create()\n" +
+          "                    .requiredProperty(EpRequirements.anyProperty())\n" +
+          "                    .build())\n" +
+          "            .requiredTextParameter(Labels.withId(TOPIC_KEY), false, false)\n" +
+          "            .requiredOntologyConcept(Labels.withId(JMS_BROKER_SETTINGS_KEY),\n" +
+          "                    OntologyProperties.mandatory(JMS_HOST_URI),\n" +
+          "                    OntologyProperties.mandatory(JMS_PORT_URI))\n" +
+          "            .supportedFormats(SupportedFormats.jsonFormat())\n" +
+          "            .supportedProtocols(SupportedProtocols.kafka(), SupportedProtocols.jms())\n" +
+          "            .build();";
+
+  private String getGetDeclareModelContent4 = "return ProcessingElementBuilder.create(\"org.apache.streampipes.processors.filters.jvm.numericalfilter\")\n" +
+          "            .category(DataProcessorType.FILTER)\n" +
+          "            .withAssets(Assets.DOCUMENTATION, Assets.ICON)\n" +
+          "            .withLocales(Locales.EN)\n" +
+          "            .requiredStream(StreamRequirementsBuilder\n" +
+          "                    .create()\n" +
+          "                    .requiredPropertyWithUnaryMapping(EpRequirements.numberReq(),\n" +
+          "                            Labels.withId(NUMBER_MAPPING),\n" +
+          "                            PropertyScope.NONE).build())\n" +
+          "            .outputStrategy(OutputStrategies.keep())\n" +
+          "            .requiredSingleValueSelection(Labels.withId(OPERATION), Options.from(\"<\", \"<=\", \">\",\n" +
+          "                    \">=\", \"==\", \"!=\"))\n" +
+          "            .requiredFloatParameter(Labels.withId(VALUE), NUMBER_MAPPING)\n" +
+          "            .supportedProtocols(SupportedProtocols.kafka(), SupportedProtocols.jms())\n" +
+          "            .supportedFormats(SupportedFormats.jsonFormat())\n" +
+          "            .build();";
+  
+
+  @Test
+  public void testAssetExtraction4() {
+    AssetModel model = new AssetModelItemExtractor(getGetDeclareModelContent4).extractAssetItem();
+
+    assertEquals("org.apache.streampipes.processors.filters.jvm.numericalfilter", model.getAppId());
+    assertEquals(PeType.PROCESSOR, model.getPeType());
+    assertNull(model.getPipelineElementName());
+    assertNull(model.getPipelineElementDescription());
+
+  }
+}
diff --git a/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/extractor/TestDockerImageExtractor.java b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/extractor/TestDockerImageExtractor.java
new file mode 100644
index 0000000..c5370be
--- /dev/null
+++ b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/extractor/TestDockerImageExtractor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.streampipes.smp.extractor;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestDockerImageExtractor {
+
+  @Test
+  @Ignore
+  public void testDockerImageExtrator() throws IOException {
+    ClassLoader classLoader = this.getClass().getClassLoader();
+    String yamlContent = IOUtils.toString(classLoader.getResourceAsStream("docker-compose.yml"));
+    Yaml yaml = new Yaml();
+    String imageName = new DockerImageExtractor(null).extractNameFromYaml(yaml.load(yamlContent));
+    System.out.println(imageName);
+
+    assertEquals("processors-text-mining-flink", imageName);
+
+  }
+}
diff --git a/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/generator/TestMarkdownTitleRemover.java b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/generator/TestMarkdownTitleRemover.java
new file mode 100644
index 0000000..d1a2f96
--- /dev/null
+++ b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/generator/TestMarkdownTitleRemover.java
@@ -0,0 +1,109 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestMarkdownTitleRemover {
+
+  private String content = "---\n" +
+          "id: org.apache.streampipes.processor.imageclassification.image-rectifier\n" +
+          "title: Image Rectifier\n" +
+          "sidebar_label: Image Rectifier\n" +
+          "---\n" +
+          "\n" +
+          "## Image Rectifier\n" +
+          "\n" +
+          "<p align=\"center\"> \n" +
+          "    <img src=\"/img/pipeline-elements/org.apache.streampipes.processor.imageclassification.image-rectifier/icon.png\" width=\"150px;\"/>\n" +
+          "</p>\n" +
+          "\n" +
+          "***\n" +
+          "\n" +
+          "## Description\n" +
+          "\n" +
+          "Image Rectification: Rectifies  + an image\n" +
+          "Add a detailed description here\n" +
+          "\n" +
+          "***\n" +
+          "\n" +
+          "## Required input\n" +
+          "\n" +
+          "\n" +
+          "***\n" +
+          "\n" +
+          "## Configuration\n" +
+          "\n" +
+          "Describe the configuration parameters here\n" +
+          "\n" +
+          "### 1st parameter\n" +
+          "\n" +
+          "\n" +
+          "### 2nd parameter\n" +
+          "\n" +
+          "## Output";
+
+  private String expected = "---\n" +
+          "id: org.apache.streampipes.processor.imageclassification.image-rectifier\n" +
+          "title: Image Rectifier\n" +
+          "sidebar_label: Image Rectifier\n" +
+          "---\n" +
+          "\n" +
+          "\n" +
+          "\n" +
+          "<p align=\"center\"> \n" +
+          "    <img src=\"/img/pipeline-elements/org.apache.streampipes.processor.imageclassification.image-rectifier/icon.png\" width=\"150px;\"/>\n" +
+          "</p>\n" +
+          "\n" +
+          "***\n" +
+          "\n" +
+          "## Description\n" +
+          "\n" +
+          "Image Rectification: Rectifies  + an image\n" +
+          "Add a detailed description here\n" +
+          "\n" +
+          "***\n" +
+          "\n" +
+          "## Required input\n" +
+          "\n" +
+          "\n" +
+          "***\n" +
+          "\n" +
+          "## Configuration\n" +
+          "\n" +
+          "Describe the configuration parameters here\n" +
+          "\n" +
+          "### 1st parameter\n" +
+          "\n" +
+          "\n" +
+          "### 2nd parameter\n" +
+          "\n" +
+          "## Output";
+
+  @Test
+  public void testTitleRemover() {
+
+    String removed = new MarkdownTitleRemover(content).removeTitle();
+
+    assertEquals(expected, removed);
+
+  }
+}
diff --git a/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/generator/TestPipelineElementOverviewGenerator.java b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/generator/TestPipelineElementOverviewGenerator.java
new file mode 100644
index 0000000..cb77c85
--- /dev/null
+++ b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/generator/TestPipelineElementOverviewGenerator.java
@@ -0,0 +1,43 @@
+/*
+ * 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.streampipes.smp.generator;
+
+import org.apache.streampipes.smp.constants.PeType;
+import org.apache.streampipes.smp.model.AssetModel;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertTrue;
+
+public class TestPipelineElementOverviewGenerator {
+
+  private AssetModel am = new AssetModel("a", "B", "C");
+
+  @Test
+  public void testHtmlGenerator() {
+    am.setPeType(PeType.PROCESSOR);
+    String html =
+            new PipelineElementOverviewGenerator(Arrays.asList(am)).generate();
+
+    System.out.println(html);
+
+    assertTrue(true);
+  }
+}
diff --git a/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/parser/TestDocumentationParser.java b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/parser/TestDocumentationParser.java
new file mode 100644
index 0000000..24dbbfc
--- /dev/null
+++ b/streampipes-maven-plugin/src/test/java/org/apache/streampipes/smp/parser/TestDocumentationParser.java
@@ -0,0 +1,46 @@
+/*
+ * 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.streampipes.smp.parser;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.streampipes.smp.model.AssetModel;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestDocumentationParser {
+
+
+  @Test
+  public void testPipelineElementNameReplacement() throws IOException {
+    ClassLoader classLoader = this.getClass().getClassLoader();
+    AssetModel assetModel = new AssetModel("abc", "Numerical Filter", "Numerical Filter " +
+            "Description");
+
+    String originalContent = IOUtils.toString(classLoader.getResourceAsStream("documentation.md"));
+    String expectedContent = IOUtils.toString(classLoader.getResourceAsStream("expected.documentation.md"));
+    String content =
+            new DocumentationParser(assetModel)
+                    .parseAndStoreDocumentation(originalContent);
+
+    assertEquals(expectedContent, content);
+  }
+}