You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/02/17 16:59:25 UTC

[1/5] camel git commit: CAMEL-10850: Autogenerate EIP options in documentation files.

Repository: camel
Updated Branches:
  refs/heads/master 451887e9a -> cd11f2d06


CAMEL-10850: Autogenerate EIP options in documentation files.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/cd11f2d0
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/cd11f2d0
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/cd11f2d0

Branch: refs/heads/master
Commit: cd11f2d067013c5b95afbe9d7ddf0ca1283aac25
Parents: 5606ae4
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Feb 17 17:59:19 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Feb 17 17:59:26 2017 +0100

----------------------------------------------------------------------
 .../src/main/docs/eips/aggregate-eip.adoc       | 53 ++++++++++++++------
 .../camel/maven/packaging/UpdateReadmeMojo.java | 16 +++++-
 .../maven/packaging/model/EipOptionModel.java   | 18 +++++++
 3 files changed, 72 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/cd11f2d0/camel-core/src/main/docs/eips/aggregate-eip.adoc
----------------------------------------------------------------------
diff --git a/camel-core/src/main/docs/eips/aggregate-eip.adoc b/camel-core/src/main/docs/eips/aggregate-eip.adoc
index 6cb0e66..795a3e8 100644
--- a/camel-core/src/main/docs/eips/aggregate-eip.adoc
+++ b/camel-core/src/main/docs/eips/aggregate-eip.adoc
@@ -1,4 +1,4 @@
-## Aggregator
+## Aggregate EIP
 
 *This applies for Camel version 2.3 or newer. If you use an older
 version then use this link:aggregator.html[Aggregator] link instead.*
@@ -18,15 +18,43 @@ single correlation key into a single message exchange.
 
 ### Aggregator options
 
-// component options: START
-// component options: END
-
-// endpoint options: START
-// endpoint options: END
-
-[[Aggregator2-AboutAggregationStrategy]]
-About AggregationStrategy
-^^^^^^^^^^^^^^^^^^^^^^^^^
+// eip options: START
+The Aggregate EIP supports 25 options which are listed below:
+
+{% raw %}
+[width="100%",cols="3,1m,6",options="header"]
+|=======================================================================
+| Name | Java Type | Description
+| correlationExpression | NamespaceAwareExpression | *Required* The expression used to calculate the correlation key to use for aggregation. The Exchange which has the same correlation key is aggregated together. If the correlation key could not be evaluated an Exception is thrown. You can disable this by using the ignoreBadCorrelationKeys option.
+| completionPredicate | NamespaceAwareExpression | TODO: document Note: this is experimental and subject to changes in future releases.
+| completionTimeout | NamespaceAwareExpression | Time in millis that an aggregated exchange should be inactive before its complete (timeout). This option can be set as either a fixed value or using an Expression which allows you to evaluate a timeout dynamically - will use Long as result. If both are set Camel will fallback to use the fixed value if the Expression result was null or 0. You cannot use this option together with completionInterval only one of the two can be used.
+| completionSize | NamespaceAwareExpression | Number of messages aggregated before the aggregation is complete. This option can be set as either a fixed value or using an Expression which allows you to evaluate a size dynamically - will use Integer as result. If both are set Camel will fallback to use the fixed value if the Expression result was null or 0.
+| optimisticLockRetryPolicy | OptimisticLockRetryPolicyDefinition | Allows to configure retry settings when using optimistic locking.
+| parallelProcessing | Boolean | When aggregated are completed they are being send out of the aggregator. This option indicates whether or not Camel should use a thread pool with multiple threads for concurrency. If no custom thread pool has been specified then Camel creates a default pool with 10 concurrent threads.
+| optimisticLocking | Boolean | Turns on using optimistic locking which requires the aggregationRepository being used is supporting this by implementing org.apache.camel.spi.OptimisticLockingAggregationRepository.
+| executorServiceRef | String | If using parallelProcessing you can specify a custom thread pool to be used. In fact also if you are not using parallelProcessing this custom thread pool is used to send out aggregated exchanges as well.
+| timeoutCheckerExecutorServiceRef | String | If using either of the completionTimeout completionTimeoutExpression or completionInterval options a background thread is created to check for the completion for every aggregator. Set this option to provide a custom thread pool to be used rather than creating a new thread for every aggregator.
+| aggregationRepositoryRef | String | Sets the custom aggregate repository to use Will by default use org.apache.camel.processor.aggregate.MemoryAggregationRepository
+| strategyRef | String | A reference to lookup the AggregationStrategy in the Registry. Configuring an AggregationStrategy is required and is used to merge the incoming Exchange with the existing already merged exchanges. At first call the oldExchange parameter is null. On subsequent invocations the oldExchange contains the merged exchanges and newExchange is of course the new incoming Exchange.
+| strategyMethodName | String | This option can be used to explicit declare the method name to use when using POJOs as the AggregationStrategy.
+| strategyMethodAllowNull | Boolean | If this option is false then the aggregate method is not used for the very first aggregation. If this option is true then null values is used as the oldExchange (at the very first aggregation) when using POJOs as the AggregationStrategy.
+| completionSize | Integer | Number of messages aggregated before the aggregation is complete. This option can be set as either a fixed value or using an Expression which allows you to evaluate a size dynamically - will use Integer as result. If both are set Camel will fallback to use the fixed value if the Expression result was null or 0.
+| completionInterval | Long | A repeating period in millis by which the aggregator will complete all current aggregated exchanges. Camel has a background task which is triggered every period. You cannot use this option together with completionTimeout only one of them can be used.
+| completionTimeout | Long | Time in millis that an aggregated exchange should be inactive before its complete (timeout). This option can be set as either a fixed value or using an Expression which allows you to evaluate a timeout dynamically - will use Long as result. If both are set Camel will fallback to use the fixed value if the Expression result was null or 0. You cannot use this option together with completionInterval only one of the two can be used.
+| completionFromBatchConsumer | Boolean | Enables the batch completion mode where we aggregate from a org.apache.camel.BatchConsumer and aggregate the total number of exchanges the org.apache.camel.BatchConsumer has reported as total by checking the exchange property link org.apache.camel.ExchangeBATCH_COMPLETE when its complete.
+| groupExchanges | Boolean | Enables grouped exchanges so the aggregator will group all aggregated exchanges into a single combined Exchange holding all the aggregated exchanges in a java.util.List.
+| eagerCheckCompletion | Boolean | Use eager completion checking which means that the completionPredicate will use the incoming Exchange. As opposed to without eager completion checking the completionPredicate will use the aggregated Exchange.
+| ignoreInvalidCorrelationKeys | Boolean | If a correlation key cannot be successfully evaluated it will be ignored by logging a DEBUG and then just ignore the incoming Exchange.
+| closeCorrelationKeyOnCompletion | Integer | Closes a correlation key when its complete. Any late received exchanges which has a correlation key that has been closed it will be defined and a ClosedCorrelationKeyException is thrown.
+| discardOnCompletionTimeout | Boolean | Discards the aggregated message on completion timeout. This means on timeout the aggregated message is dropped and not sent out of the aggregator.
+| forceCompletionOnStop | Boolean | Indicates to complete all current aggregated exchanges when the context is stopped
+| completeAllOnStop | Boolean | Indicates to wait to complete all current and partial (pending) aggregated exchanges when the context is stopped. This also means that we will wait for all pending exchanges which are stored in the aggregation repository to complete so the repository is empty before we can stop. You may want to enable this when using the memory based aggregation repository that is memory based only and do not store data on disk. When this option is enabled then the aggregator is waiting to complete all those exchanges before its stopped when stopping CamelContext or the route using it.
+| aggregateControllerRef | String | To use a org.apache.camel.processor.aggregate.AggregateController to allow external sources to control this aggregator.
+|=======================================================================
+{% endraw %}
+// eip options: END
+
+### About AggregationStrategy
 
 The `AggregationStrategy` is used for aggregating the old (lookup by its
 correlation id) and the new exchanges together into a single exchange.
@@ -633,9 +661,7 @@ Notice that the return type is a List which we want to contain the user
 names. The 1st parameter is the list of names, and then notice the 2nd
 parameter is the incoming `com.foo.User` type.
 
-[[Aggregator2-Seealso]]
-See also
-^^^^^^^^
+### See also
 
 * The link:loan-broker-example.html[Loan Broker Example] which uses an
 aggregator
@@ -647,4 +673,3 @@ post by Torsten Mielke] about using the aggregator correctly.
 link:sql-component.html[SQL Component] for persistence support
 * link:aggregate-example.html[Aggregate Example] for an example
 application
-

http://git-wip-us.apache.org/repos/asf/camel/blob/cd11f2d0/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
index da63df2..fe97744 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
@@ -915,13 +915,27 @@ public class UpdateReadmeMojo extends AbstractMojo {
             EipOptionModel option = new EipOptionModel();
             option.setName(getSafeValue("name", row));
             option.setDisplayName(getSafeValue("displayName", row));
+            option.setType(getSafeValue("type", row));
             option.setJavaType(getSafeValue("javaType", row));
+            option.setRequired(getSafeValue("required", row));
             option.setDeprecated("true".equals(getSafeValue("deprecated", row)));
             option.setDescription(getSafeValue("description", row));
             option.setInput("true".equals(getSafeValue("input", row)));
             option.setOutput("true".equals(getSafeValue("output", row)));
 
-            eip.addEipOptionModel(option);
+            // lets put required in the description
+            if ("true".equals(option.getRequired())) {
+                String desc = "*Required* " + option.getDescription();
+                option.setDescription(desc);
+            }
+
+            // skip option named id/description/expression/outputs
+            if ("id".equals(option.getName()) || "description".equals(option.getName())
+                || "expression".equals(option.getName()) || "outputs".equals(option.getName())) {
+                getLog().debug("Skipping option: " + option.getName());
+            } else {
+                eip.addEipOptionModel(option);
+            }
         }
 
         return eip;

http://git-wip-us.apache.org/repos/asf/camel/blob/cd11f2d0/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
index db3ed3d..76adc84 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
@@ -21,7 +21,9 @@ public class EipOptionModel {
     private String name;
     private String displayName;
     private String title;
+    private String required;
     private String javaType;
+    private String type;
     private String label;
     private String description;
     private boolean deprecated;
@@ -60,6 +62,22 @@ public class EipOptionModel {
         this.javaType = javaType;
     }
 
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getRequired() {
+        return required;
+    }
+
+    public void setRequired(String required) {
+        this.required = required;
+    }
+
     public String getLabel() {
         return label;
     }


[3/5] camel git commit: CAMEL-10850: Autogenerate EIP options in documentation files.

Posted by da...@apache.org.
CAMEL-10850: Autogenerate EIP options in documentation files.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/5606ae43
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/5606ae43
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/5606ae43

Branch: refs/heads/master
Commit: 5606ae430478ccdaf8ca83afe8b7c857bfac01bc
Parents: 68d371f
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Feb 17 17:45:54 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Feb 17 17:59:26 2017 +0100

----------------------------------------------------------------------
 .../camel/maven/packaging/PrepareExampleMojo.java    |  7 ++++---
 .../camel/maven/packaging/UpdateReadmeMojo.java      | 14 +++++++++++---
 .../camel/maven/packaging/model/EipOptionModel.java  | 15 +++++++++++++++
 .../src/main/resources/eip-options.mvel              |  9 +++++++++
 4 files changed, 39 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/5606ae43/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
index 41e0d94..9423d56 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
@@ -19,6 +19,7 @@ package org.apache.camel.maven.packaging;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -79,13 +80,13 @@ public class PrepareExampleMojo extends AbstractMojo {
     protected void executeExamplesReadme() throws MojoExecutionException, MojoFailureException {
         Set<File> examples = new TreeSet<>();
 
-        File dir = new File(".");
-
         // only run in examples directory where the main readme.adoc file is located
-        if (!dir.getName().equals("examples")) {
+        String currentDir = Paths.get(".").normalize().toAbsolutePath().toString();
+        if (!currentDir.endsWith("examples")) {
             return;
         }
 
+        File dir = new File(".");
         File[] files = dir.listFiles();
         if (files != null) {
             examples.addAll(Arrays.asList(files));

http://git-wip-us.apache.org/repos/asf/camel/blob/5606ae43/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
index a7fd59a..da63df2 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
@@ -19,6 +19,7 @@ package org.apache.camel.maven.packaging;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -272,14 +273,15 @@ public class UpdateReadmeMojo extends AbstractMojo {
 
     private void executeEips() throws MojoExecutionException, MojoFailureException {
         // only run if in camel-core
-        File coreDir = new File(".");
-        if (!coreDir.getName().equals("camel-core")) {
+        String currentDir = Paths.get(".").normalize().toAbsolutePath().toString();
+        if (!currentDir.endsWith("camel-core")) {
             return;
         }
 
         final Set<File> jsonFiles = new TreeSet<File>();
 
         // find all json files in camel-core
+        File coreDir = new File(".");
         if (coreDir.isDirectory()) {
             File target = new File(coreDir, "target/classes/org/apache/camel/model");
             PackageHelper.findJsonFiles(target, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
@@ -297,7 +299,13 @@ public class UpdateReadmeMojo extends AbstractMojo {
                     model.setTitle(title);
 
                     String eipName = model.getName();
-                    File file = new File(docDir, eipName + "-eip.adoc");
+
+                    // we only want actual EIPs from the models
+                    if (!model.getLabel().startsWith("eip")) {
+                        continue;
+                    }
+
+                    File file = new File(eipDocDir, eipName + "-eip.adoc");
 
                     boolean exists = file.exists();
                     boolean updated;

http://git-wip-us.apache.org/repos/asf/camel/blob/5606ae43/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
index c1cae8e..db3ed3d 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/model/EipOptionModel.java
@@ -108,5 +108,20 @@ public class EipOptionModel {
         return output ? "true" : "false";
     }
 
+    public String getShortJavaType() {
+        if (javaType.startsWith("java.util.Map")) {
+            return "Map";
+        } else if (javaType.startsWith("java.util.Set")) {
+            return "Set";
+        } else if (javaType.startsWith("java.util.List")) {
+            return "List";
+        }
+        int pos = javaType.lastIndexOf(".");
+        if (pos != -1) {
+            return javaType.substring(pos + 1);
+        } else {
+            return javaType;
+        }
+    }
 }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/5606ae43/tooling/maven/camel-package-maven-plugin/src/main/resources/eip-options.mvel
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/resources/eip-options.mvel b/tooling/maven/camel-package-maven-plugin/src/main/resources/eip-options.mvel
new file mode 100644
index 0000000..9932ebc
--- /dev/null
+++ b/tooling/maven/camel-package-maven-plugin/src/main/resources/eip-options.mvel
@@ -0,0 +1,9 @@
+The @{title} EIP supports @{eipOptions.size()} options which are listed below:
+
+{% raw %}
+[width="100%",cols="3,1m,6",options="header"]
+|=======================================================================
+| Name | Java Type | Description
+@foreach{row : eipOptions}| @{row.name} | @{row.shortJavaType} | @{row.description}
+@end{}|=======================================================================
+{% endraw %}


[5/5] camel git commit: CAMEL-10850: Autogenerate EIP options in documentation files.

Posted by da...@apache.org.
CAMEL-10850: Autogenerate EIP options in documentation files.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/56a58647
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/56a58647
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/56a58647

Branch: refs/heads/master
Commit: 56a58647e18fa518e6628f1fc318442403224ce2
Parents: 451887e
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Feb 17 14:04:21 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Feb 17 17:59:26 2017 +0100

----------------------------------------------------------------------
 .../maven/packaging/PrepareExampleMojo.java     |    2 +-
 .../maven/packaging/PrepareReadmeMojo.java      |   10 +-
 .../maven/packaging/ReadmeComponentMojo.java    |  908 ---------------
 .../camel/maven/packaging/UpdateReadmeMojo.java | 1059 ++++++++++++++++++
 4 files changed, 1065 insertions(+), 914 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/56a58647/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
index ca56721..41e0d94 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareExampleMojo.java
@@ -162,7 +162,7 @@ public class PrepareExampleMojo extends AbstractMojo {
 
     private String templateExamples(List<ExampleModel> models) throws MojoExecutionException {
         try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("readme-examples.mvel"));
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("readme-examples.mvel"));
             Map<String, Object> map = new HashMap<>();
             map.put("examples", models);
             String out = (String) TemplateRuntime.eval(template, map);

http://git-wip-us.apache.org/repos/asf/camel/blob/56a58647/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareReadmeMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareReadmeMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareReadmeMojo.java
index d96a5ca..e42fc10 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareReadmeMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareReadmeMojo.java
@@ -429,7 +429,7 @@ public class PrepareReadmeMojo extends AbstractMojo {
 
     private String templateEips(List<EipModel> models) throws MojoExecutionException {
         try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("readme-eips.mvel"));
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("readme-eips.mvel"));
             Map<String, Object> map = new HashMap<>();
             map.put("eips", models);
             String out = (String) TemplateRuntime.eval(template, map);
@@ -441,7 +441,7 @@ public class PrepareReadmeMojo extends AbstractMojo {
 
     private String templateComponents(List<ComponentModel> models) throws MojoExecutionException {
         try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("readme-components.mvel"));
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("readme-components.mvel"));
             Map<String, Object> map = new HashMap<>();
             map.put("components", models);
             String out = (String) TemplateRuntime.eval(template, map);
@@ -453,7 +453,7 @@ public class PrepareReadmeMojo extends AbstractMojo {
 
     private String templateOthers(List<OtherModel> models) throws MojoExecutionException {
         try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("readme-others.mvel"));
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("readme-others.mvel"));
             Map<String, Object> map = new HashMap<>();
             map.put("others", models);
             String out = (String) TemplateRuntime.eval(template, map);
@@ -465,7 +465,7 @@ public class PrepareReadmeMojo extends AbstractMojo {
 
     private String templateDataFormats(List<DataFormatModel> models) throws MojoExecutionException {
         try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("readme-dataformats.mvel"));
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("readme-dataformats.mvel"));
             Map<String, Object> map = new HashMap<>();
             map.put("dataformats", models);
             String out = (String) TemplateRuntime.eval(template, map);
@@ -477,7 +477,7 @@ public class PrepareReadmeMojo extends AbstractMojo {
 
     private String templateLanguages(List<LanguageModel> models) throws MojoExecutionException {
         try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("readme-languages.mvel"));
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("readme-languages.mvel"));
             Map<String, Object> map = new HashMap<>();
             map.put("languages", models);
             String out = (String) TemplateRuntime.eval(template, map);

http://git-wip-us.apache.org/repos/asf/camel/blob/56a58647/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ReadmeComponentMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ReadmeComponentMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ReadmeComponentMojo.java
deleted file mode 100644
index f781e73..0000000
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ReadmeComponentMojo.java
+++ /dev/null
@@ -1,908 +0,0 @@
-/**
- * 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.camel.maven.packaging;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
-import org.apache.camel.maven.packaging.model.ComponentModel;
-import org.apache.camel.maven.packaging.model.ComponentOptionModel;
-import org.apache.camel.maven.packaging.model.DataFormatModel;
-import org.apache.camel.maven.packaging.model.DataFormatOptionModel;
-import org.apache.camel.maven.packaging.model.EndpointOptionModel;
-import org.apache.camel.maven.packaging.model.LanguageModel;
-import org.apache.camel.maven.packaging.model.LanguageOptionModel;
-import org.apache.maven.model.Resource;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.project.MavenProject;
-import org.mvel2.templates.TemplateRuntime;
-import org.sonatype.plexus.build.incremental.BuildContext;
-
-import static org.apache.camel.maven.packaging.JSonSchemaHelper.getSafeValue;
-import static org.apache.camel.maven.packaging.PackageHelper.loadText;
-import static org.apache.camel.maven.packaging.PackageHelper.writeText;
-import static org.apache.camel.maven.packaging.StringHelper.isEmpty;
-
-/**
- * Generate or updates the component/dataformat/language readme.md and .adoc files in the project root directory.
- *
- * @goal update-readme
- */
-public class ReadmeComponentMojo extends AbstractMojo {
-
-    /**
-     * The maven project.
-     *
-     * @parameter property="project"
-     * @required
-     * @readonly
-     */
-    protected MavenProject project;
-
-    /**
-     * The project build directory
-     *
-     * @parameter default-value="${project.build.directory}"
-     */
-    protected File buildDir;
-
-    /**
-     * The documentation directory
-     *
-     * @parameter default-value="${basedir}/src/main/docs"
-     */
-    protected File docDir;
-
-    /**
-     * Whether to fail the build fast if any Warnings was detected.
-     *
-     * @parameter
-     */
-    protected Boolean failFast;
-
-    /**
-     * build context to check changed files and mark them for refresh (used for
-     * m2e compatibility)
-     *
-     * @component
-     * @readonly
-     */
-    private BuildContext buildContext;
-
-    @Override
-    public void execute() throws MojoExecutionException, MojoFailureException {
-        executeComponent();
-        executeDataFormat();
-        executeLanguage();
-    }
-
-    private void executeComponent() throws MojoExecutionException, MojoFailureException {
-        // find the component names
-        List<String> componentNames = findComponentNames();
-
-        final Set<File> jsonFiles = new TreeSet<File>();
-        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
-
-        // only if there is components we should update the documentation files
-        if (!componentNames.isEmpty()) {
-            getLog().debug("Found " + componentNames.size() + " components");
-            for (String componentName : componentNames) {
-                String json = loadComponentJson(jsonFiles, componentName);
-                if (json != null) {
-                    // special for some components
-                    componentName = asComponentName(componentName);
-
-                    File file = new File(docDir, componentName + "-component.adoc");
-
-                    ComponentModel model = generateComponentModel(componentName, json);
-                    String title = asComponentTitle(model.getScheme(), model.getTitle());
-                    model.setTitle(title);
-
-                    // we only want the first scheme as the alternatives do not have their own readme file
-                    if (!isEmpty(model.getAlternativeSchemes())) {
-                        String first = model.getAlternativeSchemes().split(",")[0];
-                        if (!model.getScheme().equals(first)) {
-                            continue;
-                        }
-                    }
-
-                    boolean exists = file.exists();
-                    boolean updated;
-
-                    updated = updateTitles(file, model.getTitle() + " Component");
-                    updated |= updateAvailableFrom(file, model.getFirstVersion());
-
-                    if (model.getComponentOptions() != null) {
-                        String options = templateComponentOptions(model);
-                        updated |= updateComponentOptions(file, options);
-                    }
-                    if (model.getEndpointOptions() != null) {
-                        String options = templateEndpointOptions(model);
-                        updated |= updateEndpointOptions(file, options);
-                    }
-
-                    if (updated) {
-                        getLog().info("Updated doc file: " + file);
-                    } else if (exists) {
-                        getLog().debug("No changes to doc file: " + file);
-                    } else {
-                        getLog().warn("No component doc file: " + file);
-                        if (isFailFast()) {
-                            throw new MojoExecutionException("Failed build due failFast=true");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private void executeDataFormat() throws MojoExecutionException, MojoFailureException {
-        // find the dataformat names
-        List<String> dataFormatNames = findDataFormatNames();
-
-        final Set<File> jsonFiles = new TreeSet<File>();
-        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
-
-        // only if there is dataformat we should update the documentation files
-        if (!dataFormatNames.isEmpty()) {
-            getLog().debug("Found " + dataFormatNames.size() + " dataformats");
-            for (String dataFormatName : dataFormatNames) {
-                String json = loadDataFormatJson(jsonFiles, dataFormatName);
-                if (json != null) {
-                    // special for some data formats
-                    dataFormatName = asDataFormatName(dataFormatName);
-
-                    File file = new File(docDir, dataFormatName + "-dataformat.adoc");
-
-                    DataFormatModel model = generateDataFormatModel(dataFormatName, json);
-                    String title = asDataFormatTitle(model.getName(), model.getTitle());
-                    model.setTitle(title);
-
-                    boolean exists = file.exists();
-                    boolean updated;
-
-                    updated = updateTitles(file, model.getTitle() + " DataFormat");
-                    updated |= updateAvailableFrom(file, model.getFirstVersion());
-
-                    if (model.getDataFormatOptions() != null) {
-                        String options = templateDataFormatOptions(model);
-                        updated |= updateDataFormatOptions(file, options);
-                    }
-
-                    if (updated) {
-                        getLog().info("Updated doc file: " + file);
-                    } else if (exists) {
-                        getLog().debug("No changes to doc file: " + file);
-                    } else {
-                        getLog().warn("No dataformat doc file: " + file);
-                        if (isFailFast()) {
-                            throw new MojoExecutionException("Failed build due failFast=true");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static String asComponentName(String name) {
-        // special for some components which share the same readme file
-        if (name.equals("imap") || name.equals("imaps") || name.equals("pop3") || name.equals("pop3s") || name.equals("smtp") || name.equals("smtps")) {
-            return "mail";
-        } else {
-            return name;
-        }
-    }
-
-    private void executeLanguage() throws MojoExecutionException, MojoFailureException {
-        // find the language names
-        List<String> languageNames = findLanguageNames();
-
-        final Set<File> jsonFiles = new TreeSet<File>();
-        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
-
-        // only if there is language we should update the documentation files
-        if (!languageNames.isEmpty()) {
-            getLog().debug("Found " + languageNames.size() + " languages");
-            for (String languageName : languageNames) {
-                String json = loadLanguageJson(jsonFiles, languageName);
-                if (json != null) {
-                    File file = new File(docDir, languageName + "-language.adoc");
-
-                    LanguageModel model = generateLanguageModel(languageName, json);
-
-                    boolean exists = file.exists();
-                    boolean updated;
-
-                    updated = updateTitles(file, model.getTitle() + " Language");
-                    updated |= updateAvailableFrom(file, model.getFirstVersion());
-
-                    if (model.getLanguageOptions() != null) {
-                        String options = templateLanguageOptions(model);
-                        updated |= updateLanguageOptions(file, options);
-                    }
-
-                    if (updated) {
-                        getLog().info("Updated doc file: " + file);
-                    } else if (exists) {
-                        getLog().debug("No changes to doc file: " + file);
-                    } else {
-                        getLog().warn("No language doc file: " + file);
-                        if (isFailFast()) {
-                            throw new MojoExecutionException("Failed build due failFast=true");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static String asComponentTitle(String name, String title) {
-        // special for some components which share the same readme file
-        if (name.equals("imap") || name.equals("imaps") || name.equals("pop3") || name.equals("pop3s") || name.equals("smtp") || name.equals("smtps")) {
-            return "Mail";
-        } else {
-            return title;
-        }
-    }
-
-    private static String asDataFormatName(String name) {
-        // special for some dataformats which share the same readme file
-        if (name.startsWith("bindy")) {
-            return "bindy";
-        } else {
-            return name;
-        }
-    }
-
-    private static String asDataFormatTitle(String name, String title) {
-        // special for some dataformats which share the same readme file
-        if (name.startsWith("bindy")) {
-            return "Bindy";
-        } else {
-            return title;
-        }
-    }
-
-    private boolean updateTitles(File file, String title) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        boolean updated = false;
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            List<String> newLines = new ArrayList<>();
-
-            String[] lines = text.split("\n");
-            for (int i = 0; i < lines.length; i++) {
-                String line = lines[i];
-
-                if (i == 0) {
-                    // first line is the title to make the text less noisy we use level 2
-                    String newLine = "## " + title;
-                    newLines.add(newLine);
-                    updated = !line.equals(newLine);
-                    continue;
-                }
-
-                // use single line headers with # as level instead of the cumbersome adoc weird style
-                if (line.startsWith("^^^") || line.startsWith("~~~") || line.startsWith("+++")) {
-                    String level = line.startsWith("+++") ? "####" : "###";
-
-                    // transform legacy heading into new style
-                    int idx = newLines.size() - 1;
-                    String prev = newLines.get(idx);
-
-                    newLines.set(idx, level + " " + prev);
-
-                    // okay if 2nd-prev line is a [[title]] we need to remove that too
-                    // so we have nice clean sub titles
-                    idx = newLines.size() - 2;
-                    if (idx >= 0) {
-                        prev = newLines.get(idx);
-                        if (prev.startsWith("[[")) {
-                            // remove
-                            newLines.remove(idx);
-                        }
-                    }
-
-                    updated = true;
-                } else {
-                    // okay normal text so just add it
-                    newLines.add(line);
-                }
-            }
-
-
-            if (updated) {
-                // build the new updated text
-                String newText = newLines.stream().collect(Collectors.joining("\n"));
-                writeText(file, newText);
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-
-        return updated;
-    }
-
-    private boolean updateAvailableFrom(File file, String firstVersion) throws MojoExecutionException {
-        if (firstVersion == null || !file.exists()) {
-            return false;
-        }
-
-        // cut last digit so its not 2.18.0 but 2.18
-        String[] parts = firstVersion.split("\\.");
-        if (parts.length == 3 && parts[2].equals("0")) {
-            firstVersion = parts[0] + "." + parts[1];
-        }
-
-        boolean updated = false;
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String[] lines = text.split("\n");
-
-            List<String> newLines = new ArrayList<>();
-
-            // copy over to all new lines
-            newLines.addAll(Arrays.asList(lines));
-
-            // check the first four lines
-            boolean title = lines[0].startsWith("##");
-            boolean empty = lines[1].trim().isEmpty();
-            boolean availableFrom = lines[2].trim().contains("Available as of") || lines[2].trim().contains("Available in");
-            boolean empty2 = lines[3].trim().isEmpty();
-
-            if (title && empty && availableFrom) {
-                String newLine = "*Available as of Camel version " + firstVersion + "*";
-                if (!newLine.equals(lines[2])) {
-                    newLines.set(2, newLine);
-                    updated = true;
-                }
-                if (!empty2) {
-                    newLines.add(3, "");
-                    updated = true;
-                }
-            } else if (!availableFrom) {
-                String newLine = "*Available as of Camel version " + firstVersion + "*";
-                newLines.add(2, newLine);
-                newLines.add(3, "");
-                updated = true;
-            }
-
-            if (updated) {
-                // build the new updated text
-                String newText = newLines.stream().collect(Collectors.joining("\n"));
-                writeText(file, newText);
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-
-        return updated;
-    }
-
-    private boolean updateComponentOptions(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// component options: START", "// component options: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// component options: START");
-                    String after = StringHelper.after(text, "// component options: END");
-                    text = before + "// component options: START\n" + changed + "\n// component options: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// component options: START");
-                getLog().warn("\t// component options: END");
-                if (isFailFast()) {
-                    throw new MojoExecutionException("Failed build due failFast=true");
-                }
-                return false;
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-    }
-
-    private boolean updateEndpointOptions(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// endpoint options: START", "// endpoint options: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// endpoint options: START");
-                    String after = StringHelper.after(text, "// endpoint options: END");
-                    text = before + "// endpoint options: START\n" + changed + "\n// endpoint options: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// endpoint options: START");
-                getLog().warn("\t// endpoint options: END");
-                if (isFailFast()) {
-                    throw new MojoExecutionException("Failed build due failFast=true");
-                }
-                return false;
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-    }
-
-    private boolean updateDataFormatOptions(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// dataformat options: START", "// dataformat options: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// dataformat options: START");
-                    String after = StringHelper.after(text, "// dataformat options: END");
-                    text = before + "// dataformat options: START\n" + changed + "\n// dataformat options: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// dataformat options: START");
-                getLog().warn("\t// dataformat options: END");
-                if (isFailFast()) {
-                    throw new MojoExecutionException("Failed build due failFast=true");
-                }
-                return false;
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-    }
-
-    private boolean updateLanguageOptions(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// language options: START", "// language options: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// language options: START");
-                    String after = StringHelper.after(text, "// language options: END");
-                    text = before + "// language options: START\n" + changed + "\n// language options: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// language options: START");
-                getLog().warn("\t// language options: END");
-                if (isFailFast()) {
-                    throw new MojoExecutionException("Failed build due failFast=true");
-                }
-                return false;
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-    }
-
-    private String loadComponentJson(Set<File> jsonFiles, String componentName) {
-        try {
-            for (File file : jsonFiles) {
-                if (file.getName().equals(componentName + ".json")) {
-                    String json = loadText(new FileInputStream(file));
-                    boolean isComponent = json.contains("\"kind\": \"component\"");
-                    if (isComponent) {
-                        return json;
-                    }
-                }
-            }
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-    private String loadDataFormatJson(Set<File> jsonFiles, String dataFormatName) {
-        try {
-            for (File file : jsonFiles) {
-                if (file.getName().equals(dataFormatName + ".json")) {
-                    String json = loadText(new FileInputStream(file));
-                    boolean isDataFormat = json.contains("\"kind\": \"dataformat\"");
-                    if (isDataFormat) {
-                        return json;
-                    }
-                }
-            }
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-    private String loadLanguageJson(Set<File> jsonFiles, String languageName) {
-        try {
-            for (File file : jsonFiles) {
-                if (file.getName().equals(languageName + ".json")) {
-                    String json = loadText(new FileInputStream(file));
-                    boolean isLanguage = json.contains("\"kind\": \"language\"");
-                    if (isLanguage) {
-                        return json;
-                    }
-                }
-            }
-        } catch (IOException e) {
-            // ignore
-        }
-        return null;
-    }
-
-    private ComponentModel generateComponentModel(String componentName, String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
-
-        ComponentModel component = new ComponentModel(true);
-        component.setScheme(JSonSchemaHelper.getSafeValue("scheme", rows));
-        component.setSyntax(JSonSchemaHelper.getSafeValue("syntax", rows));
-        component.setAlternativeSyntax(JSonSchemaHelper.getSafeValue("alternativeSyntax", rows));
-        component.setAlternativeSchemes(JSonSchemaHelper.getSafeValue("alternativeSchemes", rows));
-        component.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        component.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        component.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
-        component.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        component.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
-        component.setConsumerOnly(JSonSchemaHelper.getSafeValue("consumerOnly", rows));
-        component.setProducerOnly(JSonSchemaHelper.getSafeValue("producerOnly", rows));
-        component.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        component.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
-        component.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
-        component.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
-
-        rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
-        for (Map<String, String> row : rows) {
-            ComponentOptionModel option = new ComponentOptionModel();
-            option.setName(getSafeValue("name", row));
-            option.setDisplayName(getSafeValue("displayName", row));
-            option.setKind(getSafeValue("kind", row));
-            option.setGroup(getSafeValue("group", row));
-            option.setRequired(getSafeValue("required", row));
-            option.setType(getSafeValue("type", row));
-            option.setJavaType(getSafeValue("javaType", row));
-            option.setEnums(getSafeValue("enum", row));
-            option.setDeprecated(getSafeValue("deprecated", row));
-            option.setSecret(getSafeValue("secret", row));
-            option.setDefaultValue(getSafeValue("defaultValue", row));
-            option.setDescription(getSafeValue("description", row));
-            // lets put required in the description
-            if ("true".equals(option.getRequired())) {
-                String desc = "*Required* " + option.getDescription();
-                option.setDescription(desc);
-            }
-            component.addComponentOption(option);
-        }
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-        for (Map<String, String> row : rows) {
-            EndpointOptionModel option = new EndpointOptionModel();
-            option.setName(getSafeValue("name", row));
-            option.setDisplayName(getSafeValue("displayName", row));
-            option.setKind(getSafeValue("kind", row));
-            option.setGroup(getSafeValue("group", row));
-            option.setRequired(getSafeValue("required", row));
-            option.setType(getSafeValue("type", row));
-            option.setJavaType(getSafeValue("javaType", row));
-            option.setEnums(getSafeValue("enum", row));
-            option.setPrefix(getSafeValue("prefix", row));
-            option.setMultiValue(getSafeValue("multiValue", row));
-            option.setDeprecated(getSafeValue("deprecated", row));
-            option.setSecret(getSafeValue("secret", row));
-            option.setDefaultValue(getSafeValue("defaultValue", row));
-            option.setDescription(getSafeValue("description", row));
-            // lets put required in the description
-            if ("true".equals(option.getRequired())) {
-                String desc = "*Required* " + option.getDescription();
-                option.setDescription(desc);
-            }
-            component.addEndpointOption(option);
-        }
-
-        return component;
-    }
-
-    private DataFormatModel generateDataFormatModel(String dataFormatName, String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("dataformat", json, false);
-
-        DataFormatModel dataFormat = new DataFormatModel();
-        dataFormat.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        dataFormat.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
-        dataFormat.setName(JSonSchemaHelper.getSafeValue("name", rows));
-        dataFormat.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        dataFormat.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
-        dataFormat.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        dataFormat.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
-        dataFormat.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        dataFormat.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
-        dataFormat.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
-        dataFormat.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-        for (Map<String, String> row : rows) {
-            DataFormatOptionModel option = new DataFormatOptionModel();
-            option.setName(getSafeValue("name", row));
-            option.setDisplayName(getSafeValue("displayName", row));
-            option.setKind(getSafeValue("kind", row));
-            option.setType(getSafeValue("type", row));
-            option.setJavaType(getSafeValue("javaType", row));
-            option.setDeprecated(getSafeValue("deprecated", row));
-            option.setEnumValues(getSafeValue("enum", row));
-            option.setDefaultValue(getSafeValue("defaultValue", row));
-            option.setDescription(getSafeValue("description", row));
-
-            // special for bindy as we reuse one readme file
-            if (dataFormatName.startsWith("bindy") && option.getName().equals("type")) {
-                option.setDefaultValue("");
-                String doc = option.getDescription() + " The default value is either Csv or KeyValue depending on chosen dataformat.";
-                option.setDescription(doc);
-            }
-
-            // skip option named id
-            if ("id".equals(option.getName())) {
-                getLog().debug("Skipping option: " + option.getName());
-            } else {
-                dataFormat.addDataFormatOption(option);
-            }
-        }
-
-        return dataFormat;
-    }
-
-    private LanguageModel generateLanguageModel(String languageName, String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
-
-        LanguageModel language = new LanguageModel();
-        language.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        language.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
-        language.setName(JSonSchemaHelper.getSafeValue("name", rows));
-        language.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        language.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
-        language.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        language.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
-        language.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        language.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
-        language.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
-        language.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
-        for (Map<String, String> row : rows) {
-            LanguageOptionModel option = new LanguageOptionModel();
-            option.setName(getSafeValue("name", row));
-            option.setDisplayName(getSafeValue("displayName", row));
-            option.setKind(getSafeValue("kind", row));
-            option.setType(getSafeValue("type", row));
-            option.setJavaType(getSafeValue("javaType", row));
-            option.setDeprecated(getSafeValue("deprecated", row));
-            option.setEnumValues(getSafeValue("enum", row));
-            option.setDefaultValue(getSafeValue("defaultValue", row));
-            option.setDescription(getSafeValue("description", row));
-
-            // skip option named id/expression
-            if ("id".equals(option.getName()) || "expression".equals(option.getName())) {
-                getLog().debug("Skipping option: " + option.getName());
-            } else {
-                language.addLanguageOption(option);
-            }
-        }
-
-        return language;
-    }
-
-    private String templateComponentHeader(ComponentModel model) throws MojoExecutionException {
-        try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("component-header.mvel"));
-            String out = (String) TemplateRuntime.eval(template, model);
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private String templateComponentOptions(ComponentModel model) throws MojoExecutionException {
-        try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("component-options.mvel"));
-            String out = (String) TemplateRuntime.eval(template, model);
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private String templateEndpointOptions(ComponentModel model) throws MojoExecutionException {
-        try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("endpoint-options.mvel"));
-            String out = (String) TemplateRuntime.eval(template, model);
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private String templateDataFormatOptions(DataFormatModel model) throws MojoExecutionException {
-        try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("dataformat-options.mvel"));
-            String out = (String) TemplateRuntime.eval(template, model);
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private String templateLanguageOptions(LanguageModel model) throws MojoExecutionException {
-        try {
-            String template = loadText(ReadmeComponentMojo.class.getClassLoader().getResourceAsStream("language-options.mvel"));
-            String out = (String) TemplateRuntime.eval(template, model);
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private List<String> findComponentNames() {
-        List<String> componentNames = new ArrayList<String>();
-        for (Resource r : project.getBuild().getResources()) {
-            File f = new File(r.getDirectory());
-            if (!f.exists()) {
-                f = new File(project.getBasedir(), r.getDirectory());
-            }
-            f = new File(f, "META-INF/services/org/apache/camel/component");
-
-            if (f.exists() && f.isDirectory()) {
-                File[] files = f.listFiles();
-                if (files != null) {
-                    for (File file : files) {
-                        // skip directories as there may be a sub .resolver directory
-                        if (file.isDirectory()) {
-                            continue;
-                        }
-                        String name = file.getName();
-                        if (name.charAt(0) != '.') {
-                            componentNames.add(name);
-                        }
-                    }
-                }
-            }
-        }
-        return componentNames;
-    }
-
-    private List<String> findDataFormatNames() {
-        List<String> dataFormatNames = new ArrayList<String>();
-        for (Resource r : project.getBuild().getResources()) {
-            File f = new File(r.getDirectory());
-            if (!f.exists()) {
-                f = new File(project.getBasedir(), r.getDirectory());
-            }
-            f = new File(f, "META-INF/services/org/apache/camel/dataformat");
-
-            if (f.exists() && f.isDirectory()) {
-                File[] files = f.listFiles();
-                if (files != null) {
-                    for (File file : files) {
-                        // skip directories as there may be a sub .resolver directory
-                        if (file.isDirectory()) {
-                            continue;
-                        }
-                        String name = file.getName();
-                        if (name.charAt(0) != '.') {
-                            dataFormatNames.add(name);
-                        }
-                    }
-                }
-            }
-        }
-        return dataFormatNames;
-    }
-
-    private List<String> findLanguageNames() {
-        List<String> languageNames = new ArrayList<String>();
-        for (Resource r : project.getBuild().getResources()) {
-            File f = new File(r.getDirectory());
-            if (!f.exists()) {
-                f = new File(project.getBasedir(), r.getDirectory());
-            }
-            f = new File(f, "META-INF/services/org/apache/camel/language");
-
-            if (f.exists() && f.isDirectory()) {
-                File[] files = f.listFiles();
-                if (files != null) {
-                    for (File file : files) {
-                        // skip directories as there may be a sub .resolver directory
-                        if (file.isDirectory()) {
-                            continue;
-                        }
-                        String name = file.getName();
-                        if (name.charAt(0) != '.') {
-                            languageNames.add(name);
-                        }
-                    }
-                }
-            }
-        }
-        return languageNames;
-    }
-
-    private boolean isFailFast() {
-        return failFast != null && failFast;
-    }
-
-}


[2/5] camel git commit: CAMEL-10850: Autogenerate EIP options in documentation files.

Posted by da...@apache.org.
CAMEL-10850: Autogenerate EIP options in documentation files.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/68d371f0
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/68d371f0
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/68d371f0

Branch: refs/heads/master
Commit: 68d371f0bb2d803c59779834bde7177f941e22e2
Parents: 56a5864
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Feb 17 14:24:07 2017 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Feb 17 17:59:26 2017 +0100

----------------------------------------------------------------------
 .../camel/maven/packaging/UpdateReadmeMojo.java | 180 ++++++++++---------
 1 file changed, 95 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/68d371f0/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
index 59282ab..a7fd59a 100644
--- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
@@ -44,7 +44,7 @@ import org.apache.maven.project.MavenProject;
 import org.mvel2.templates.TemplateRuntime;
 import org.sonatype.plexus.build.incremental.BuildContext;
 
-import static org.apache.camel.maven.packaging.JSonSchemaHelper.getSafeValue;
+import static org.apache.camel.maven.packaging.JSonSchemaHelper.*;
 import static org.apache.camel.maven.packaging.PackageHelper.loadText;
 import static org.apache.camel.maven.packaging.PackageHelper.writeText;
 import static org.apache.camel.maven.packaging.StringHelper.isEmpty;
@@ -271,28 +271,34 @@ public class UpdateReadmeMojo extends AbstractMojo {
     }
 
     private void executeEips() throws MojoExecutionException, MojoFailureException {
-        // find the eips names
-        List<String> eipNames = findEipNames();
+        // only run if in camel-core
+        File coreDir = new File(".");
+        if (!coreDir.getName().equals("camel-core")) {
+            return;
+        }
 
-        // TODO: how to find model json files
         final Set<File> jsonFiles = new TreeSet<File>();
-        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
+
+        // find all json files in camel-core
+        if (coreDir.isDirectory()) {
+            File target = new File(coreDir, "target/classes/org/apache/camel/model");
+            PackageHelper.findJsonFiles(target, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
+        }
 
         // only if there is dataformat we should update the documentation files
-        if (!eipNames.isEmpty()) {
-            getLog().debug("Found " + eipNames.size() + " eips");
-            for (String eipName : eipNames) {
-                String json = loadEipJson(jsonFiles, eipName);
+        if (!jsonFiles.isEmpty()) {
+            getLog().debug("Found " + jsonFiles.size() + " eips");
+            for (File jsonFile : jsonFiles) {
+                String json = loadEipJson(jsonFile);
                 if (json != null) {
-                    // special for some data formats
-                    eipName = asEipName(eipName);
-
-                    File file = new File(docDir, eipName + "-eip.adoc");
 
                     EipModel model = generateEipModel(json);
                     String title = asEipTitle(model.getName(), model.getTitle());
                     model.setTitle(title);
 
+                    String eipName = model.getName();
+                    File file = new File(docDir, eipName + "-eip.adoc");
+
                     boolean exists = file.exists();
                     boolean updated;
 
@@ -308,7 +314,7 @@ public class UpdateReadmeMojo extends AbstractMojo {
                     } else if (exists) {
                         getLog().debug("No changes to doc file: " + file);
                     } else {
-                        getLog().warn("No dataformat doc file: " + file);
+                        getLog().warn("No eip doc file: " + file);
                         if (isFailFast()) {
                             throw new MojoExecutionException("Failed build due failFast=true");
                         }
@@ -712,16 +718,12 @@ public class UpdateReadmeMojo extends AbstractMojo {
         return null;
     }
 
-    private String loadEipJson(Set<File> jsonFiles, String eipName) {
+    private String loadEipJson(File file) {
         try {
-            for (File file : jsonFiles) {
-                if (file.getName().equals(eipName + ".json")) {
-                    String json = loadText(new FileInputStream(file));
-                    boolean isEip = json.contains("\"kind\": \"model\"");
-                    if (isEip) {
-                        return json;
-                    }
-                }
+            String json = loadText(new FileInputStream(file));
+            boolean isEip = json.contains("\"kind\": \"model\"");
+            if (isEip) {
+                return json;
             }
         } catch (IOException e) {
             // ignore
@@ -730,26 +732,26 @@ public class UpdateReadmeMojo extends AbstractMojo {
     }
 
     private ComponentModel generateComponentModel(String componentName, String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+        List<Map<String, String>> rows = parseJsonSchema("component", json, false);
 
         ComponentModel component = new ComponentModel(true);
-        component.setScheme(JSonSchemaHelper.getSafeValue("scheme", rows));
-        component.setSyntax(JSonSchemaHelper.getSafeValue("syntax", rows));
-        component.setAlternativeSyntax(JSonSchemaHelper.getSafeValue("alternativeSyntax", rows));
-        component.setAlternativeSchemes(JSonSchemaHelper.getSafeValue("alternativeSchemes", rows));
-        component.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        component.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        component.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
-        component.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        component.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
-        component.setConsumerOnly(JSonSchemaHelper.getSafeValue("consumerOnly", rows));
-        component.setProducerOnly(JSonSchemaHelper.getSafeValue("producerOnly", rows));
-        component.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        component.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
-        component.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
-        component.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
-
-        rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
+        component.setScheme(getSafeValue("scheme", rows));
+        component.setSyntax(getSafeValue("syntax", rows));
+        component.setAlternativeSyntax(getSafeValue("alternativeSyntax", rows));
+        component.setAlternativeSchemes(getSafeValue("alternativeSchemes", rows));
+        component.setTitle(getSafeValue("title", rows));
+        component.setDescription(getSafeValue("description", rows));
+        component.setFirstVersion(getSafeValue("firstVersion", rows));
+        component.setLabel(getSafeValue("label", rows));
+        component.setDeprecated(getSafeValue("deprecated", rows));
+        component.setConsumerOnly(getSafeValue("consumerOnly", rows));
+        component.setProducerOnly(getSafeValue("producerOnly", rows));
+        component.setJavaType(getSafeValue("javaType", rows));
+        component.setGroupId(getSafeValue("groupId", rows));
+        component.setArtifactId(getSafeValue("artifactId", rows));
+        component.setVersion(getSafeValue("version", rows));
+
+        rows = parseJsonSchema("componentProperties", json, true);
         for (Map<String, String> row : rows) {
             ComponentOptionModel option = new ComponentOptionModel();
             option.setName(getSafeValue("name", row));
@@ -772,7 +774,7 @@ public class UpdateReadmeMojo extends AbstractMojo {
             component.addComponentOption(option);
         }
 
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        rows = parseJsonSchema("properties", json, true);
         for (Map<String, String> row : rows) {
             EndpointOptionModel option = new EndpointOptionModel();
             option.setName(getSafeValue("name", row));
@@ -801,22 +803,22 @@ public class UpdateReadmeMojo extends AbstractMojo {
     }
 
     private DataFormatModel generateDataFormatModel(String dataFormatName, String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("dataformat", json, false);
+        List<Map<String, String>> rows = parseJsonSchema("dataformat", json, false);
 
         DataFormatModel dataFormat = new DataFormatModel();
-        dataFormat.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        dataFormat.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
-        dataFormat.setName(JSonSchemaHelper.getSafeValue("name", rows));
-        dataFormat.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        dataFormat.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
-        dataFormat.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        dataFormat.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
-        dataFormat.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        dataFormat.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
-        dataFormat.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
-        dataFormat.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        dataFormat.setTitle(getSafeValue("title", rows));
+        dataFormat.setModelName(getSafeValue("modelName", rows));
+        dataFormat.setName(getSafeValue("name", rows));
+        dataFormat.setDescription(getSafeValue("description", rows));
+        dataFormat.setFirstVersion(getSafeValue("firstVersion", rows));
+        dataFormat.setLabel(getSafeValue("label", rows));
+        dataFormat.setDeprecated(getSafeValue("deprecated", rows));
+        dataFormat.setJavaType(getSafeValue("javaType", rows));
+        dataFormat.setGroupId(getSafeValue("groupId", rows));
+        dataFormat.setArtifactId(getSafeValue("artifactId", rows));
+        dataFormat.setVersion(getSafeValue("version", rows));
+
+        rows = parseJsonSchema("properties", json, true);
         for (Map<String, String> row : rows) {
             DataFormatOptionModel option = new DataFormatOptionModel();
             option.setName(getSafeValue("name", row));
@@ -848,22 +850,22 @@ public class UpdateReadmeMojo extends AbstractMojo {
     }
 
     private LanguageModel generateLanguageModel(String languageName, String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
+        List<Map<String, String>> rows = parseJsonSchema("language", json, false);
 
         LanguageModel language = new LanguageModel();
-        language.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        language.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
-        language.setName(JSonSchemaHelper.getSafeValue("name", rows));
-        language.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        language.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
-        language.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        language.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
-        language.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        language.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
-        language.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
-        language.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
-
-        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        language.setTitle(getSafeValue("title", rows));
+        language.setModelName(getSafeValue("modelName", rows));
+        language.setName(getSafeValue("name", rows));
+        language.setDescription(getSafeValue("description", rows));
+        language.setFirstVersion(getSafeValue("firstVersion", rows));
+        language.setLabel(getSafeValue("label", rows));
+        language.setDeprecated(getSafeValue("deprecated", rows));
+        language.setJavaType(getSafeValue("javaType", rows));
+        language.setGroupId(getSafeValue("groupId", rows));
+        language.setArtifactId(getSafeValue("artifactId", rows));
+        language.setVersion(getSafeValue("version", rows));
+
+        rows = parseJsonSchema("properties", json, true);
         for (Map<String, String> row : rows) {
             LanguageOptionModel option = new LanguageOptionModel();
             option.setName(getSafeValue("name", row));
@@ -888,17 +890,31 @@ public class UpdateReadmeMojo extends AbstractMojo {
     }
 
     private EipModel generateEipModel(String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("model", json, false);
+        List<Map<String, String>> rows = parseJsonSchema("model", json, false);
 
         EipModel eip = new EipModel();
-        eip.setName(JSonSchemaHelper.getSafeValue("name", rows));
-        eip.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
-        eip.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
-        eip.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
-        eip.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
-        eip.setDeprecated("true".equals(JSonSchemaHelper.getSafeValue("deprecated", rows)));
-        eip.setInput("true".equals(JSonSchemaHelper.getSafeValue("input", rows)));
-        eip.setOutput("true".equals(JSonSchemaHelper.getSafeValue("output", rows)));
+        eip.setName(getSafeValue("name", rows));
+        eip.setTitle(getSafeValue("title", rows));
+        eip.setDescription(getSafeValue("description", rows));
+        eip.setJavaType(getSafeValue("javaType", rows));
+        eip.setLabel(getSafeValue("label", rows));
+        eip.setDeprecated("true".equals(getSafeValue("deprecated", rows)));
+        eip.setInput("true".equals(getSafeValue("input", rows)));
+        eip.setOutput("true".equals(getSafeValue("output", rows)));
+
+        rows = parseJsonSchema("properties", json, true);
+        for (Map<String, String> row : rows) {
+            EipOptionModel option = new EipOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setDeprecated("true".equals(getSafeValue("deprecated", row)));
+            option.setDescription(getSafeValue("description", row));
+            option.setInput("true".equals(getSafeValue("input", row)));
+            option.setOutput("true".equals(getSafeValue("output", row)));
+
+            eip.addEipOptionModel(option);
+        }
 
         return eip;
     }
@@ -1046,12 +1062,6 @@ public class UpdateReadmeMojo extends AbstractMojo {
         return languageNames;
     }
 
-    private List<String> findEipNames() {
-        List<String> eipNames = new ArrayList<String>();
-        // TODO: find by scanning model (prepare catalog does something)
-        return eipNames;
-    }
-
     private boolean isFailFast() {
         return failFast != null && failFast;
     }


[4/5] camel git commit: CAMEL-10850: Autogenerate EIP options in documentation files.

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/camel/blob/56a58647/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
new file mode 100644
index 0000000..59282ab
--- /dev/null
+++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/UpdateReadmeMojo.java
@@ -0,0 +1,1059 @@
+/**
+ * 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.camel.maven.packaging;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import org.apache.camel.maven.packaging.model.ComponentModel;
+import org.apache.camel.maven.packaging.model.ComponentOptionModel;
+import org.apache.camel.maven.packaging.model.DataFormatModel;
+import org.apache.camel.maven.packaging.model.DataFormatOptionModel;
+import org.apache.camel.maven.packaging.model.EipModel;
+import org.apache.camel.maven.packaging.model.EipOptionModel;
+import org.apache.camel.maven.packaging.model.EndpointOptionModel;
+import org.apache.camel.maven.packaging.model.LanguageModel;
+import org.apache.camel.maven.packaging.model.LanguageOptionModel;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.mvel2.templates.TemplateRuntime;
+import org.sonatype.plexus.build.incremental.BuildContext;
+
+import static org.apache.camel.maven.packaging.JSonSchemaHelper.getSafeValue;
+import static org.apache.camel.maven.packaging.PackageHelper.loadText;
+import static org.apache.camel.maven.packaging.PackageHelper.writeText;
+import static org.apache.camel.maven.packaging.StringHelper.isEmpty;
+
+/**
+ * Generate or updates the component/dataformat/language/eip readme.md and .adoc files in the project root directory.
+ *
+ * @goal update-readme
+ */
+public class UpdateReadmeMojo extends AbstractMojo {
+
+    /**
+     * The maven project.
+     *
+     * @parameter property="project"
+     * @required
+     * @readonly
+     */
+    protected MavenProject project;
+
+    /**
+     * The project build directory
+     *
+     * @parameter default-value="${project.build.directory}"
+     */
+    protected File buildDir;
+
+    /**
+     * The documentation directory
+     *
+     * @parameter default-value="${basedir}/src/main/docs"
+     */
+    protected File docDir;
+
+    /**
+     * The documentation directory
+     *
+     * @parameter default-value="${basedir}/src/main/docs/eips"
+     */
+    protected File eipDocDir;
+
+    /**
+     * Whether to fail the build fast if any Warnings was detected.
+     *
+     * @parameter
+     */
+    protected Boolean failFast;
+
+    /**
+     * build context to check changed files and mark them for refresh (used for
+     * m2e compatibility)
+     *
+     * @component
+     * @readonly
+     */
+    private BuildContext buildContext;
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        executeComponent();
+        executeDataFormat();
+        executeLanguage();
+        executeEips();
+    }
+
+    private void executeComponent() throws MojoExecutionException, MojoFailureException {
+        // find the component names
+        List<String> componentNames = findComponentNames();
+
+        final Set<File> jsonFiles = new TreeSet<File>();
+        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
+
+        // only if there is components we should update the documentation files
+        if (!componentNames.isEmpty()) {
+            getLog().debug("Found " + componentNames.size() + " components");
+            for (String componentName : componentNames) {
+                String json = loadComponentJson(jsonFiles, componentName);
+                if (json != null) {
+                    // special for some components
+                    componentName = asComponentName(componentName);
+
+                    File file = new File(docDir, componentName + "-component.adoc");
+
+                    ComponentModel model = generateComponentModel(componentName, json);
+                    String title = asComponentTitle(model.getScheme(), model.getTitle());
+                    model.setTitle(title);
+
+                    // we only want the first scheme as the alternatives do not have their own readme file
+                    if (!isEmpty(model.getAlternativeSchemes())) {
+                        String first = model.getAlternativeSchemes().split(",")[0];
+                        if (!model.getScheme().equals(first)) {
+                            continue;
+                        }
+                    }
+
+                    boolean exists = file.exists();
+                    boolean updated;
+
+                    updated = updateTitles(file, model.getTitle() + " Component");
+                    updated |= updateAvailableFrom(file, model.getFirstVersion());
+
+                    if (model.getComponentOptions() != null) {
+                        String options = templateComponentOptions(model);
+                        updated |= updateComponentOptions(file, options);
+                    }
+                    if (model.getEndpointOptions() != null) {
+                        String options = templateEndpointOptions(model);
+                        updated |= updateEndpointOptions(file, options);
+                    }
+
+                    if (updated) {
+                        getLog().info("Updated doc file: " + file);
+                    } else if (exists) {
+                        getLog().debug("No changes to doc file: " + file);
+                    } else {
+                        getLog().warn("No component doc file: " + file);
+                        if (isFailFast()) {
+                            throw new MojoExecutionException("Failed build due failFast=true");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void executeDataFormat() throws MojoExecutionException, MojoFailureException {
+        // find the dataformat names
+        List<String> dataFormatNames = findDataFormatNames();
+
+        final Set<File> jsonFiles = new TreeSet<File>();
+        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
+
+        // only if there is dataformat we should update the documentation files
+        if (!dataFormatNames.isEmpty()) {
+            getLog().debug("Found " + dataFormatNames.size() + " dataformats");
+            for (String dataFormatName : dataFormatNames) {
+                String json = loadDataFormatJson(jsonFiles, dataFormatName);
+                if (json != null) {
+                    // special for some data formats
+                    dataFormatName = asDataFormatName(dataFormatName);
+
+                    File file = new File(docDir, dataFormatName + "-dataformat.adoc");
+
+                    DataFormatModel model = generateDataFormatModel(dataFormatName, json);
+                    String title = asDataFormatTitle(model.getName(), model.getTitle());
+                    model.setTitle(title);
+
+                    boolean exists = file.exists();
+                    boolean updated;
+
+                    updated = updateTitles(file, model.getTitle() + " DataFormat");
+                    updated |= updateAvailableFrom(file, model.getFirstVersion());
+
+                    if (model.getDataFormatOptions() != null) {
+                        String options = templateDataFormatOptions(model);
+                        updated |= updateDataFormatOptions(file, options);
+                    }
+
+                    if (updated) {
+                        getLog().info("Updated doc file: " + file);
+                    } else if (exists) {
+                        getLog().debug("No changes to doc file: " + file);
+                    } else {
+                        getLog().warn("No dataformat doc file: " + file);
+                        if (isFailFast()) {
+                            throw new MojoExecutionException("Failed build due failFast=true");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static String asComponentName(String name) {
+        // special for some components which share the same readme file
+        if (name.equals("imap") || name.equals("imaps") || name.equals("pop3") || name.equals("pop3s") || name.equals("smtp") || name.equals("smtps")) {
+            return "mail";
+        } else {
+            return name;
+        }
+    }
+
+    private void executeLanguage() throws MojoExecutionException, MojoFailureException {
+        // find the language names
+        List<String> languageNames = findLanguageNames();
+
+        final Set<File> jsonFiles = new TreeSet<File>();
+        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
+
+        // only if there is language we should update the documentation files
+        if (!languageNames.isEmpty()) {
+            getLog().debug("Found " + languageNames.size() + " languages");
+            for (String languageName : languageNames) {
+                String json = loadLanguageJson(jsonFiles, languageName);
+                if (json != null) {
+                    File file = new File(docDir, languageName + "-language.adoc");
+
+                    LanguageModel model = generateLanguageModel(languageName, json);
+
+                    boolean exists = file.exists();
+                    boolean updated;
+
+                    updated = updateTitles(file, model.getTitle() + " Language");
+                    updated |= updateAvailableFrom(file, model.getFirstVersion());
+
+                    if (model.getLanguageOptions() != null) {
+                        String options = templateLanguageOptions(model);
+                        updated |= updateLanguageOptions(file, options);
+                    }
+
+                    if (updated) {
+                        getLog().info("Updated doc file: " + file);
+                    } else if (exists) {
+                        getLog().debug("No changes to doc file: " + file);
+                    } else {
+                        getLog().warn("No language doc file: " + file);
+                        if (isFailFast()) {
+                            throw new MojoExecutionException("Failed build due failFast=true");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void executeEips() throws MojoExecutionException, MojoFailureException {
+        // find the eips names
+        List<String> eipNames = findEipNames();
+
+        // TODO: how to find model json files
+        final Set<File> jsonFiles = new TreeSet<File>();
+        PackageHelper.findJsonFiles(buildDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter());
+
+        // only if there is dataformat we should update the documentation files
+        if (!eipNames.isEmpty()) {
+            getLog().debug("Found " + eipNames.size() + " eips");
+            for (String eipName : eipNames) {
+                String json = loadEipJson(jsonFiles, eipName);
+                if (json != null) {
+                    // special for some data formats
+                    eipName = asEipName(eipName);
+
+                    File file = new File(docDir, eipName + "-eip.adoc");
+
+                    EipModel model = generateEipModel(json);
+                    String title = asEipTitle(model.getName(), model.getTitle());
+                    model.setTitle(title);
+
+                    boolean exists = file.exists();
+                    boolean updated;
+
+                    updated = updateTitles(file, model.getTitle() + " EIP");
+
+                    if (model.getEipOptions() != null) {
+                        String options = templateEipOptions(model);
+                        updated |= updateEipOptions(file, options);
+                    }
+
+                    if (updated) {
+                        getLog().info("Updated doc file: " + file);
+                    } else if (exists) {
+                        getLog().debug("No changes to doc file: " + file);
+                    } else {
+                        getLog().warn("No dataformat doc file: " + file);
+                        if (isFailFast()) {
+                            throw new MojoExecutionException("Failed build due failFast=true");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static String asComponentTitle(String name, String title) {
+        // special for some components which share the same readme file
+        if (name.equals("imap") || name.equals("imaps") || name.equals("pop3") || name.equals("pop3s") || name.equals("smtp") || name.equals("smtps")) {
+            return "Mail";
+        } else {
+            return title;
+        }
+    }
+
+    private static String asDataFormatName(String name) {
+        // special for some dataformats which share the same readme file
+        if (name.startsWith("bindy")) {
+            return "bindy";
+        } else {
+            return name;
+        }
+    }
+
+    private static String asEipName(String name) {
+        return name;
+    }
+
+    private static String asDataFormatTitle(String name, String title) {
+        // special for some dataformats which share the same readme file
+        if (name.startsWith("bindy")) {
+            return "Bindy";
+        } else {
+            return title;
+        }
+    }
+
+    private static String asEipTitle(String name, String title) {
+        return title;
+    }
+
+    private boolean updateTitles(File file, String title) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        boolean updated = false;
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            List<String> newLines = new ArrayList<>();
+
+            String[] lines = text.split("\n");
+            for (int i = 0; i < lines.length; i++) {
+                String line = lines[i];
+
+                if (i == 0) {
+                    // first line is the title to make the text less noisy we use level 2
+                    String newLine = "## " + title;
+                    newLines.add(newLine);
+                    updated = !line.equals(newLine);
+                    continue;
+                }
+
+                // use single line headers with # as level instead of the cumbersome adoc weird style
+                if (line.startsWith("^^^") || line.startsWith("~~~") || line.startsWith("+++")) {
+                    String level = line.startsWith("+++") ? "####" : "###";
+
+                    // transform legacy heading into new style
+                    int idx = newLines.size() - 1;
+                    String prev = newLines.get(idx);
+
+                    newLines.set(idx, level + " " + prev);
+
+                    // okay if 2nd-prev line is a [[title]] we need to remove that too
+                    // so we have nice clean sub titles
+                    idx = newLines.size() - 2;
+                    if (idx >= 0) {
+                        prev = newLines.get(idx);
+                        if (prev.startsWith("[[")) {
+                            // remove
+                            newLines.remove(idx);
+                        }
+                    }
+
+                    updated = true;
+                } else {
+                    // okay normal text so just add it
+                    newLines.add(line);
+                }
+            }
+
+
+            if (updated) {
+                // build the new updated text
+                String newText = newLines.stream().collect(Collectors.joining("\n"));
+                writeText(file, newText);
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+
+        return updated;
+    }
+
+    private boolean updateAvailableFrom(File file, String firstVersion) throws MojoExecutionException {
+        if (firstVersion == null || !file.exists()) {
+            return false;
+        }
+
+        // cut last digit so its not 2.18.0 but 2.18
+        String[] parts = firstVersion.split("\\.");
+        if (parts.length == 3 && parts[2].equals("0")) {
+            firstVersion = parts[0] + "." + parts[1];
+        }
+
+        boolean updated = false;
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            String[] lines = text.split("\n");
+
+            List<String> newLines = new ArrayList<>();
+
+            // copy over to all new lines
+            newLines.addAll(Arrays.asList(lines));
+
+            // check the first four lines
+            boolean title = lines[0].startsWith("##");
+            boolean empty = lines[1].trim().isEmpty();
+            boolean availableFrom = lines[2].trim().contains("Available as of") || lines[2].trim().contains("Available in");
+            boolean empty2 = lines[3].trim().isEmpty();
+
+            if (title && empty && availableFrom) {
+                String newLine = "*Available as of Camel version " + firstVersion + "*";
+                if (!newLine.equals(lines[2])) {
+                    newLines.set(2, newLine);
+                    updated = true;
+                }
+                if (!empty2) {
+                    newLines.add(3, "");
+                    updated = true;
+                }
+            } else if (!availableFrom) {
+                String newLine = "*Available as of Camel version " + firstVersion + "*";
+                newLines.add(2, newLine);
+                newLines.add(3, "");
+                updated = true;
+            }
+
+            if (updated) {
+                // build the new updated text
+                String newText = newLines.stream().collect(Collectors.joining("\n"));
+                writeText(file, newText);
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+
+        return updated;
+    }
+
+    private boolean updateComponentOptions(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            String existing = StringHelper.between(text, "// component options: START", "// component options: END");
+            if (existing != null) {
+                // remove leading line breaks etc
+                existing = existing.trim();
+                changed = changed.trim();
+                if (existing.equals(changed)) {
+                    return false;
+                } else {
+                    String before = StringHelper.before(text, "// component options: START");
+                    String after = StringHelper.after(text, "// component options: END");
+                    text = before + "// component options: START\n" + changed + "\n// component options: END" + after;
+                    writeText(file, text);
+                    return true;
+                }
+            } else {
+                getLog().warn("Cannot find markers in file " + file);
+                getLog().warn("Add the following markers");
+                getLog().warn("\t// component options: START");
+                getLog().warn("\t// component options: END");
+                if (isFailFast()) {
+                    throw new MojoExecutionException("Failed build due failFast=true");
+                }
+                return false;
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+    }
+
+    private boolean updateEndpointOptions(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            String existing = StringHelper.between(text, "// endpoint options: START", "// endpoint options: END");
+            if (existing != null) {
+                // remove leading line breaks etc
+                existing = existing.trim();
+                changed = changed.trim();
+                if (existing.equals(changed)) {
+                    return false;
+                } else {
+                    String before = StringHelper.before(text, "// endpoint options: START");
+                    String after = StringHelper.after(text, "// endpoint options: END");
+                    text = before + "// endpoint options: START\n" + changed + "\n// endpoint options: END" + after;
+                    writeText(file, text);
+                    return true;
+                }
+            } else {
+                getLog().warn("Cannot find markers in file " + file);
+                getLog().warn("Add the following markers");
+                getLog().warn("\t// endpoint options: START");
+                getLog().warn("\t// endpoint options: END");
+                if (isFailFast()) {
+                    throw new MojoExecutionException("Failed build due failFast=true");
+                }
+                return false;
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+    }
+
+    private boolean updateDataFormatOptions(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            String existing = StringHelper.between(text, "// dataformat options: START", "// dataformat options: END");
+            if (existing != null) {
+                // remove leading line breaks etc
+                existing = existing.trim();
+                changed = changed.trim();
+                if (existing.equals(changed)) {
+                    return false;
+                } else {
+                    String before = StringHelper.before(text, "// dataformat options: START");
+                    String after = StringHelper.after(text, "// dataformat options: END");
+                    text = before + "// dataformat options: START\n" + changed + "\n// dataformat options: END" + after;
+                    writeText(file, text);
+                    return true;
+                }
+            } else {
+                getLog().warn("Cannot find markers in file " + file);
+                getLog().warn("Add the following markers");
+                getLog().warn("\t// dataformat options: START");
+                getLog().warn("\t// dataformat options: END");
+                if (isFailFast()) {
+                    throw new MojoExecutionException("Failed build due failFast=true");
+                }
+                return false;
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+    }
+
+    private boolean updateLanguageOptions(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            String existing = StringHelper.between(text, "// language options: START", "// language options: END");
+            if (existing != null) {
+                // remove leading line breaks etc
+                existing = existing.trim();
+                changed = changed.trim();
+                if (existing.equals(changed)) {
+                    return false;
+                } else {
+                    String before = StringHelper.before(text, "// language options: START");
+                    String after = StringHelper.after(text, "// language options: END");
+                    text = before + "// language options: START\n" + changed + "\n// language options: END" + after;
+                    writeText(file, text);
+                    return true;
+                }
+            } else {
+                getLog().warn("Cannot find markers in file " + file);
+                getLog().warn("Add the following markers");
+                getLog().warn("\t// language options: START");
+                getLog().warn("\t// language options: END");
+                if (isFailFast()) {
+                    throw new MojoExecutionException("Failed build due failFast=true");
+                }
+                return false;
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+    }
+
+    private boolean updateEipOptions(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            String existing = StringHelper.between(text, "// eip options: START", "// eip options: END");
+            if (existing != null) {
+                // remove leading line breaks etc
+                existing = existing.trim();
+                changed = changed.trim();
+                if (existing.equals(changed)) {
+                    return false;
+                } else {
+                    String before = StringHelper.before(text, "// eip options: START");
+                    String after = StringHelper.after(text, "// eip options: END");
+                    text = before + "// eip options: START\n" + changed + "\n// eip options: END" + after;
+                    writeText(file, text);
+                    return true;
+                }
+            } else {
+                getLog().warn("Cannot find markers in file " + file);
+                getLog().warn("Add the following markers");
+                getLog().warn("\t// eip options: START");
+                getLog().warn("\t// eip options: END");
+                if (isFailFast()) {
+                    throw new MojoExecutionException("Failed build due failFast=true");
+                }
+                return false;
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+    }
+
+    private String loadComponentJson(Set<File> jsonFiles, String componentName) {
+        try {
+            for (File file : jsonFiles) {
+                if (file.getName().equals(componentName + ".json")) {
+                    String json = loadText(new FileInputStream(file));
+                    boolean isComponent = json.contains("\"kind\": \"component\"");
+                    if (isComponent) {
+                        return json;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    private String loadDataFormatJson(Set<File> jsonFiles, String dataFormatName) {
+        try {
+            for (File file : jsonFiles) {
+                if (file.getName().equals(dataFormatName + ".json")) {
+                    String json = loadText(new FileInputStream(file));
+                    boolean isDataFormat = json.contains("\"kind\": \"dataformat\"");
+                    if (isDataFormat) {
+                        return json;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    private String loadLanguageJson(Set<File> jsonFiles, String languageName) {
+        try {
+            for (File file : jsonFiles) {
+                if (file.getName().equals(languageName + ".json")) {
+                    String json = loadText(new FileInputStream(file));
+                    boolean isLanguage = json.contains("\"kind\": \"language\"");
+                    if (isLanguage) {
+                        return json;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    private String loadEipJson(Set<File> jsonFiles, String eipName) {
+        try {
+            for (File file : jsonFiles) {
+                if (file.getName().equals(eipName + ".json")) {
+                    String json = loadText(new FileInputStream(file));
+                    boolean isEip = json.contains("\"kind\": \"model\"");
+                    if (isEip) {
+                        return json;
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // ignore
+        }
+        return null;
+    }
+
+    private ComponentModel generateComponentModel(String componentName, String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+
+        ComponentModel component = new ComponentModel(true);
+        component.setScheme(JSonSchemaHelper.getSafeValue("scheme", rows));
+        component.setSyntax(JSonSchemaHelper.getSafeValue("syntax", rows));
+        component.setAlternativeSyntax(JSonSchemaHelper.getSafeValue("alternativeSyntax", rows));
+        component.setAlternativeSchemes(JSonSchemaHelper.getSafeValue("alternativeSchemes", rows));
+        component.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        component.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        component.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        component.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        component.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        component.setConsumerOnly(JSonSchemaHelper.getSafeValue("consumerOnly", rows));
+        component.setProducerOnly(JSonSchemaHelper.getSafeValue("producerOnly", rows));
+        component.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        component.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        component.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        component.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
+
+        rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true);
+        for (Map<String, String> row : rows) {
+            ComponentOptionModel option = new ComponentOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setKind(getSafeValue("kind", row));
+            option.setGroup(getSafeValue("group", row));
+            option.setRequired(getSafeValue("required", row));
+            option.setType(getSafeValue("type", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setEnums(getSafeValue("enum", row));
+            option.setDeprecated(getSafeValue("deprecated", row));
+            option.setSecret(getSafeValue("secret", row));
+            option.setDefaultValue(getSafeValue("defaultValue", row));
+            option.setDescription(getSafeValue("description", row));
+            // lets put required in the description
+            if ("true".equals(option.getRequired())) {
+                String desc = "*Required* " + option.getDescription();
+                option.setDescription(desc);
+            }
+            component.addComponentOption(option);
+        }
+
+        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        for (Map<String, String> row : rows) {
+            EndpointOptionModel option = new EndpointOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setKind(getSafeValue("kind", row));
+            option.setGroup(getSafeValue("group", row));
+            option.setRequired(getSafeValue("required", row));
+            option.setType(getSafeValue("type", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setEnums(getSafeValue("enum", row));
+            option.setPrefix(getSafeValue("prefix", row));
+            option.setMultiValue(getSafeValue("multiValue", row));
+            option.setDeprecated(getSafeValue("deprecated", row));
+            option.setSecret(getSafeValue("secret", row));
+            option.setDefaultValue(getSafeValue("defaultValue", row));
+            option.setDescription(getSafeValue("description", row));
+            // lets put required in the description
+            if ("true".equals(option.getRequired())) {
+                String desc = "*Required* " + option.getDescription();
+                option.setDescription(desc);
+            }
+            component.addEndpointOption(option);
+        }
+
+        return component;
+    }
+
+    private DataFormatModel generateDataFormatModel(String dataFormatName, String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("dataformat", json, false);
+
+        DataFormatModel dataFormat = new DataFormatModel();
+        dataFormat.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        dataFormat.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
+        dataFormat.setName(JSonSchemaHelper.getSafeValue("name", rows));
+        dataFormat.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        dataFormat.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        dataFormat.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        dataFormat.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        dataFormat.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        dataFormat.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        dataFormat.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        dataFormat.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
+
+        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        for (Map<String, String> row : rows) {
+            DataFormatOptionModel option = new DataFormatOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setKind(getSafeValue("kind", row));
+            option.setType(getSafeValue("type", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setDeprecated(getSafeValue("deprecated", row));
+            option.setEnumValues(getSafeValue("enum", row));
+            option.setDefaultValue(getSafeValue("defaultValue", row));
+            option.setDescription(getSafeValue("description", row));
+
+            // special for bindy as we reuse one readme file
+            if (dataFormatName.startsWith("bindy") && option.getName().equals("type")) {
+                option.setDefaultValue("");
+                String doc = option.getDescription() + " The default value is either Csv or KeyValue depending on chosen dataformat.";
+                option.setDescription(doc);
+            }
+
+            // skip option named id
+            if ("id".equals(option.getName())) {
+                getLog().debug("Skipping option: " + option.getName());
+            } else {
+                dataFormat.addDataFormatOption(option);
+            }
+        }
+
+        return dataFormat;
+    }
+
+    private LanguageModel generateLanguageModel(String languageName, String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
+
+        LanguageModel language = new LanguageModel();
+        language.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        language.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
+        language.setName(JSonSchemaHelper.getSafeValue("name", rows));
+        language.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        language.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        language.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        language.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        language.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        language.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        language.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        language.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
+
+        rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+        for (Map<String, String> row : rows) {
+            LanguageOptionModel option = new LanguageOptionModel();
+            option.setName(getSafeValue("name", row));
+            option.setDisplayName(getSafeValue("displayName", row));
+            option.setKind(getSafeValue("kind", row));
+            option.setType(getSafeValue("type", row));
+            option.setJavaType(getSafeValue("javaType", row));
+            option.setDeprecated(getSafeValue("deprecated", row));
+            option.setEnumValues(getSafeValue("enum", row));
+            option.setDefaultValue(getSafeValue("defaultValue", row));
+            option.setDescription(getSafeValue("description", row));
+
+            // skip option named id/expression
+            if ("id".equals(option.getName()) || "expression".equals(option.getName())) {
+                getLog().debug("Skipping option: " + option.getName());
+            } else {
+                language.addLanguageOption(option);
+            }
+        }
+
+        return language;
+    }
+
+    private EipModel generateEipModel(String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("model", json, false);
+
+        EipModel eip = new EipModel();
+        eip.setName(JSonSchemaHelper.getSafeValue("name", rows));
+        eip.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        eip.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        eip.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        eip.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        eip.setDeprecated("true".equals(JSonSchemaHelper.getSafeValue("deprecated", rows)));
+        eip.setInput("true".equals(JSonSchemaHelper.getSafeValue("input", rows)));
+        eip.setOutput("true".equals(JSonSchemaHelper.getSafeValue("output", rows)));
+
+        return eip;
+    }
+
+    private String templateComponentHeader(ComponentModel model) throws MojoExecutionException {
+        try {
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("component-header.mvel"));
+            String out = (String) TemplateRuntime.eval(template, model);
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private String templateComponentOptions(ComponentModel model) throws MojoExecutionException {
+        try {
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("component-options.mvel"));
+            String out = (String) TemplateRuntime.eval(template, model);
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private String templateEndpointOptions(ComponentModel model) throws MojoExecutionException {
+        try {
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("endpoint-options.mvel"));
+            String out = (String) TemplateRuntime.eval(template, model);
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private String templateDataFormatOptions(DataFormatModel model) throws MojoExecutionException {
+        try {
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("dataformat-options.mvel"));
+            String out = (String) TemplateRuntime.eval(template, model);
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private String templateLanguageOptions(LanguageModel model) throws MojoExecutionException {
+        try {
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("language-options.mvel"));
+            String out = (String) TemplateRuntime.eval(template, model);
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private String templateEipOptions(EipModel model) throws MojoExecutionException {
+        try {
+            String template = loadText(UpdateReadmeMojo.class.getClassLoader().getResourceAsStream("eip-options.mvel"));
+            String out = (String) TemplateRuntime.eval(template, model);
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private List<String> findComponentNames() {
+        List<String> componentNames = new ArrayList<String>();
+        for (Resource r : project.getBuild().getResources()) {
+            File f = new File(r.getDirectory());
+            if (!f.exists()) {
+                f = new File(project.getBasedir(), r.getDirectory());
+            }
+            f = new File(f, "META-INF/services/org/apache/camel/component");
+
+            if (f.exists() && f.isDirectory()) {
+                File[] files = f.listFiles();
+                if (files != null) {
+                    for (File file : files) {
+                        // skip directories as there may be a sub .resolver directory
+                        if (file.isDirectory()) {
+                            continue;
+                        }
+                        String name = file.getName();
+                        if (name.charAt(0) != '.') {
+                            componentNames.add(name);
+                        }
+                    }
+                }
+            }
+        }
+        return componentNames;
+    }
+
+    private List<String> findDataFormatNames() {
+        List<String> dataFormatNames = new ArrayList<String>();
+        for (Resource r : project.getBuild().getResources()) {
+            File f = new File(r.getDirectory());
+            if (!f.exists()) {
+                f = new File(project.getBasedir(), r.getDirectory());
+            }
+            f = new File(f, "META-INF/services/org/apache/camel/dataformat");
+
+            if (f.exists() && f.isDirectory()) {
+                File[] files = f.listFiles();
+                if (files != null) {
+                    for (File file : files) {
+                        // skip directories as there may be a sub .resolver directory
+                        if (file.isDirectory()) {
+                            continue;
+                        }
+                        String name = file.getName();
+                        if (name.charAt(0) != '.') {
+                            dataFormatNames.add(name);
+                        }
+                    }
+                }
+            }
+        }
+        return dataFormatNames;
+    }
+    private List<String> findLanguageNames() {
+        List<String> languageNames = new ArrayList<String>();
+        for (Resource r : project.getBuild().getResources()) {
+            File f = new File(r.getDirectory());
+            if (!f.exists()) {
+                f = new File(project.getBasedir(), r.getDirectory());
+            }
+            f = new File(f, "META-INF/services/org/apache/camel/language");
+
+            if (f.exists() && f.isDirectory()) {
+                File[] files = f.listFiles();
+                if (files != null) {
+                    for (File file : files) {
+                        // skip directories as there may be a sub .resolver directory
+                        if (file.isDirectory()) {
+                            continue;
+                        }
+                        String name = file.getName();
+                        if (name.charAt(0) != '.') {
+                            languageNames.add(name);
+                        }
+                    }
+                }
+            }
+        }
+        return languageNames;
+    }
+
+    private List<String> findEipNames() {
+        List<String> eipNames = new ArrayList<String>();
+        // TODO: find by scanning model (prepare catalog does something)
+        return eipNames;
+    }
+
+    private boolean isFailFast() {
+        return failFast != null && failFast;
+    }
+
+}