Add goal to mvn plugin to validate if component docs is present when building each component.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/572f9e23 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/572f9e23 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/572f9e23 Branch: refs/heads/master Commit: 572f9e230f6f9317976f0e848f1e87122110e720 Parents: 5e08a9e Author: Claus Ibsen <davscl...@apache.org> Authored: Fri Jun 19 16:12:30 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Jun 19 17:38:08 2015 +0200 ---------------------------------------------------------------------- components/pom.xml | 13 +- .../camel/maven/packaging/ErrorDetail.java | 93 +++++++++++++ .../maven/packaging/PrepareCatalogMojo.java | 7 + .../camel/maven/packaging/StringHelper.java | 15 ++ .../maven/packaging/ValidateComponentMojo.java | 139 +++++++++++++++++++ .../camel/maven/packaging/ValidateHelper.java | 138 ++++++++++++++++++ 6 files changed, 404 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/572f9e23/components/pom.xml ---------------------------------------------------------------------- diff --git a/components/pom.xml b/components/pom.xml index c6fa5ba..057fd60 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -246,13 +246,24 @@ <groupId>org.apache.camel</groupId> <artifactId>camel-package-maven-plugin</artifactId> <version>${project.version}</version> + <configuration> + <validate>true</validate> + </configuration> <executions> <execution> + <id>prepare</id> <goals> <goal>prepare-components</goal> </goals> <phase>generate-resources</phase> - </execution> + </execution> + <execution> + <id>validate</id> + <goals> + <goal>validate-components</goal> + </goals> + <phase>prepare-package</phase> + </execution> </executions> </plugin> </plugins> http://git-wip-us.apache.org/repos/asf/camel/blob/572f9e23/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ErrorDetail.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ErrorDetail.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ErrorDetail.java new file mode 100644 index 0000000..3266a58 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ErrorDetail.java @@ -0,0 +1,93 @@ +/** + * 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.util.ArrayList; +import java.util.List; + +public final class ErrorDetail { + + private String kind; + + private boolean missingLabel; + private boolean missingDescription; + private boolean missingSyntax; + private boolean missingUriPath; + private List<String> missingComponentDocumentation = new ArrayList<>(); + private List<String> missingEndpointDocumentation = new ArrayList<>(); + + public boolean hasErrors() { + return missingLabel || missingDescription || missingDescription || missingUriPath || !missingComponentDocumentation.isEmpty() || !missingEndpointDocumentation.isEmpty(); + } + + public String getKind() { + return kind; + } + + public void setKind(String kind) { + this.kind = kind; + } + + public boolean isMissingUriPath() { + return missingUriPath; + } + + public void setMissingUriPath(boolean missingUriPath) { + this.missingUriPath = missingUriPath; + } + + public boolean isMissingLabel() { + return missingLabel; + } + + public void setMissingLabel(boolean missingLabel) { + this.missingLabel = missingLabel; + } + + public boolean isMissingDescription() { + return missingDescription; + } + + public void setMissingDescription(boolean missingDescription) { + this.missingDescription = missingDescription; + } + + public boolean isMissingSyntax() { + return missingSyntax; + } + + public void setMissingSyntax(boolean missingSyntax) { + this.missingSyntax = missingSyntax; + } + + public void addMissingComponentDoc(String option) { + missingComponentDocumentation.add(option); + } + + public void addMissingEndpointDoc(String option) { + missingEndpointDocumentation.add(option); + } + + public List<String> getMissingComponentDocumentation() { + return missingComponentDocumentation; + } + + public List<String> getMissingEndpointDocumentation() { + return missingEndpointDocumentation; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/572f9e23/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java index f0563bf..8405781 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java @@ -62,6 +62,13 @@ public class PrepareCatalogMojo extends AbstractMojo { protected MavenProject project; /** + * Whether to validate if the components, data formats, and languages are properly documented and have all the needed details. + * + * @parameter default-value="true" + */ + protected Boolean validate; + + /** * The output directory for components catalog * * @parameter default-value="${project.build.directory}/classes/org/apache/camel/catalog/components" http://git-wip-us.apache.org/repos/asf/camel/blob/572f9e23/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/StringHelper.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/StringHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/StringHelper.java index ac6a133..e17f430 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/StringHelper.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/StringHelper.java @@ -16,11 +16,18 @@ */ package org.apache.camel.maven.packaging; +import java.util.Collection; + public final class StringHelper { + private StringHelper() { // Utils Class } + public static boolean isEmpty(String s) { + return s == null || s.trim().isEmpty(); + } + public static String after(String text, String after) { if (!text.contains(after)) { return null; @@ -43,4 +50,12 @@ public final class StringHelper { return before(text, before); } + public static String indentCollection(String indent, Collection<String> list) { + StringBuilder sb = new StringBuilder(); + for (String text : list) { + sb.append(indent).append(text); + } + return sb.toString(); + } + } http://git-wip-us.apache.org/repos/asf/camel/blob/572f9e23/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateComponentMojo.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateComponentMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateComponentMojo.java new file mode 100644 index 0000000..58b3b11 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateComponentMojo.java @@ -0,0 +1,139 @@ +/** + * 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.util.Set; +import java.util.TreeSet; + +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.apache.maven.project.MavenProjectHelper; +import org.sonatype.plexus.build.incremental.BuildContext; + +import static org.apache.camel.maven.packaging.StringHelper.indentCollection; +import static org.apache.camel.maven.packaging.ValidateHelper.asName; +import static org.apache.camel.maven.packaging.ValidateHelper.validate; + +/** + * Validate a Camel component analyzing if the meta-data files for + * <ul> + * <li>components</li> + * <li>dataformats</li> + * <li>languages</li> + * </ul> + * all contains the needed meta-data such as assigned labels, documentation for each option + * + * @goal validate-components + */ +public class ValidateComponentMojo extends AbstractMojo { + + /** + * The maven project. + * + * @parameter property="project" + * @required + * @readonly + */ + protected MavenProject project; + + /** + * Whether to validate if the components, data formats, and languages are properly documented and have all the needed details. + * + * @parameter default-value="false" + */ + protected Boolean validate; + + /** + * The output directory for generated components file + * + * @parameter default-value="${project.build.directory}/classes/" + */ + protected File outDir; + + /** + * Maven ProjectHelper. + * + * @component + * @readonly + */ + private MavenProjectHelper projectHelper; + + /** + * build context to check changed files and mark them for refresh + * (used for m2e compatibility) + * + * @component + * @readonly + */ + private BuildContext buildContext; + + /** + * Execute goal. + * + * @throws org.apache.maven.plugin.MojoExecutionException execution of the main class or one of the + * threads it generated failed. + * @throws org.apache.maven.plugin.MojoFailureException something bad happened... + */ + public void execute() throws MojoExecutionException, MojoFailureException { + + final Set<File> jsonFiles = new TreeSet<>(); + PackageHelper.findJsonFiles(outDir, jsonFiles, new PackageHelper.CamelComponentsModelFilter()); + + boolean failed = false; + if (validate) { + getLog().info("Validating ..."); + + for (File file : jsonFiles) { + final String name = asName(file); + final ErrorDetail detail = new ErrorDetail(); + + validate(file, detail); + + if (detail.hasErrors()) { + failed = true; + getLog().warn("The " + detail.getKind() + ": " + name + " has errors!"); + if (detail.isMissingDescription()) { + getLog().warn("Missing description on " + detail.getKind()); + } + if (detail.isMissingLabel()) { + getLog().warn("Missing label on " + detail.getKind()); + } + if (detail.isMissingSyntax()) { + getLog().warn("Missing syntax on endpoint"); + } + if (detail.isMissingUriPath()) { + getLog().warn("Missing @UriPath on endpoint"); + } + if (!detail.getMissingComponentDocumentation().isEmpty()) { + getLog().warn("Missing component documentation for the following options:" + indentCollection("\n\t", detail.getMissingComponentDocumentation())); + } + if (!detail.getMissingEndpointDocumentation().isEmpty()) { + getLog().warn("Missing endpoint documentation for the following options:" + indentCollection("\n\t", detail.getMissingEndpointDocumentation())); + } + } + } + } + + if (failed) { + throw new MojoFailureException("There are validation errors, see above!"); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/572f9e23/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateHelper.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateHelper.java new file mode 100644 index 0000000..4db0e73 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ValidateHelper.java @@ -0,0 +1,138 @@ +/** + * 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.List; +import java.util.Map; + +import static org.apache.camel.maven.packaging.PackageHelper.loadText; + +/** + * Validation helper for validating components, data formats and languages + */ +public final class ValidateHelper { + + private ValidateHelper() { + } + + /** + * Validates the component json file + * + * @param file the json file + * @param errorDetail details to add errors + */ + public static void validate(File file, ErrorDetail errorDetail) { + String name = asName(file); + + try { + String json = loadText(new FileInputStream(file)); + + boolean isComponent = json.contains("\"kind\": \"component\""); + boolean isDataFormat = json.contains("\"kind\": \"dataformat\""); + boolean isLanguage = json.contains("\"kind\": \"language\""); + + // only check these kind + if (!isComponent && !isDataFormat && !isLanguage) { + return; + } + + if (isComponent) { + errorDetail.setKind("component"); + } else if (isDataFormat) { + errorDetail.setKind("dataformat"); + } else if (isLanguage) { + errorDetail.setKind("language"); + } + + List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema(errorDetail.getKind(), json, false); + boolean label = false; + boolean description = false; + boolean syntax = false; + for (Map<String, String> row : rows) { + String value = row.get("label"); + if (!StringHelper.isEmpty(value)) { + label = true; + } + value = row.get("description"); + if (!StringHelper.isEmpty(value)) { + description = true; + } + value = row.get("syntax"); + if (!StringHelper.isEmpty(value)) { + syntax = true; + } + } + if (!label) { + errorDetail.setMissingLabel(true); + } + if (!description) { + errorDetail.setMissingDescription(true); + } + if (!syntax) { + errorDetail.setMissingDescription(true); + } + + if (isComponent) { + // check all the component properties if they have description + rows = JSonSchemaHelper.parseJsonSchema("componentProperties", json, true); + for (Map<String, String> row : rows) { + String key = row.get("name"); + String doc = row.get("description"); + if (doc == null || doc.isEmpty()) { + errorDetail.addMissingComponentDoc(key); + } + } + } + + // check all the endpoint properties if they have description + rows = JSonSchemaHelper.parseJsonSchema("properties", json, true); + boolean path = false; + for (Map<String, String> row : rows) { + String key = row.get("name"); + String doc = row.get("description"); + if (doc == null || doc.isEmpty()) { + errorDetail.addMissingEndpointDoc(key); + } + String kind = row.get("kind"); + if ("path".equals(kind)) { + path = true; + } + } + if (isComponent && !path) { + // only components can have missing @UriPath + errorDetail.setMissingUriPath(true); + } + } catch (IOException e) { + // ignore + } + } + + /** + * Returns the name of the component, data format or language from the given json file + */ + public static String asName(File file) { + String name = file.getName(); + if (name.endsWith(".json")) { + return name.substring(0, name.length() - 5); + } + return name; + } + +}