You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2019/06/21 07:09:22 UTC

[servicecomb-toolkit] 06/49: Add feature of contract generating document

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

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-toolkit.git

commit c8658ec773a72e96f84138279253cd70a7d6949d
Author: MabinGo <bi...@huawei.com>
AuthorDate: Mon May 20 20:20:24 2019 +0800

    Add feature of contract generating document
    
    Signed-off-by: MabinGo <bi...@huawei.com>
---
 doc-generator/pom.xml                              | 118 +++++++++++++++++++++
 .../docgen/ContractsAsciidocGenerator.java         |  87 +++++++++++++++
 .../docgen/ContractsSwaggerUIGenerator.java        | 109 +++++++++++++++++++
 .../apache/servicecomb/docgen/DocGenerator.java    |  27 +++++
 .../servicecomb/docgen/DocGeneratorManager.java    |  48 +++++++++
 .../org.apache.servicecomb.docgen.DocGenerator     |  19 ++++
 .../src/main/resources/webroot/swagger-ui.html     |  32 ++++++
 pom.xml                                            |   1 +
 swagger-ui.html                                    |  32 ++++++
 9 files changed, 473 insertions(+)

diff --git a/doc-generator/pom.xml b/doc-generator/pom.xml
new file mode 100755
index 0000000..bf5ba09
--- /dev/null
+++ b/doc-generator/pom.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>toolkit</artifactId>
+    <groupId>org.apache.servicecomb</groupId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>doc-generator</artifactId>
+
+  <repositories>
+    <repository>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>jcenter-releases</id>
+      <name>jcenter</name>
+      <url>http://jcenter.bintray.com</url>
+    </repository>
+  </repositories>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.asciidoctor</groupId>
+      <artifactId>asciidoctorj</artifactId>
+      <version>1.6.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.asciidoctor</groupId>
+      <artifactId>asciidoctorj-pdf</artifactId>
+      <version>1.5.0-alpha.15</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.jruby</groupId>
+          <artifactId>jruby-complete</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.jruby</groupId>
+      <artifactId>jruby-complete</artifactId>
+      <version>9.2.6.0</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>swagger-generator-core</artifactId>
+      <version>1.2.0</version>
+    </dependency>
+
+    <dependency>
+      <groupId>io.github.swagger2markup</groupId>
+      <artifactId>swagger2markup</artifactId>
+      <version>1.3.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.4</version>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jgit</groupId>
+      <artifactId>org.eclipse.jgit</artifactId>
+      <version>5.3.0.201903130848-r</version>
+    </dependency>
+
+    <!--<dependency>-->
+    <!--<groupId>org.apache.servicecomb</groupId>-->
+    <!--<artifactId>toolkit-common</artifactId>-->
+    <!--<version>${project.version}</version>-->
+    <!--</dependency>-->
+
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsAsciidocGenerator.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsAsciidocGenerator.java
new file mode 100755
index 0000000..1e28116
--- /dev/null
+++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsAsciidocGenerator.java
@@ -0,0 +1,87 @@
+/*
+ * 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.servicecomb.docgen;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+
+import org.asciidoctor.Asciidoctor;
+import org.asciidoctor.Attributes;
+import org.asciidoctor.AttributesBuilder;
+import org.asciidoctor.OptionsBuilder;
+import org.asciidoctor.SafeMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Ordering;
+
+import io.github.swagger2markup.Swagger2MarkupConverter;
+import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
+import io.swagger.models.Swagger;
+import io.swagger.models.parameters.Parameter;
+
+
+public class ContractsAsciidocGenerator implements DocGenerator {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(ContractsAsciidocGenerator.class);
+
+  private final static String DOC_FORMAT = "asciidoc";
+
+  @Override
+  public boolean canProcess(String type) {
+    return type != null && DOC_FORMAT.equals(type.toLowerCase());
+  }
+
+  @Override
+  public String generate(Swagger contractContent, String outputPath) {
+
+    Asciidoctor asciidoctor = Asciidoctor.Factory.create();
+    Swagger2MarkupConverter.Builder markupBuilder = Swagger2MarkupConverter.from(contractContent);
+    Swagger2MarkupConfigBuilder swagger2MarkupConfigBuilder = new Swagger2MarkupConfigBuilder()
+        .withParameterOrdering(Ordering
+            .explicit("path", "query", "header", "cookie", "formData", "body")
+            .onResultOf(Parameter::getIn));
+    String markup = markupBuilder.withConfig(swagger2MarkupConfigBuilder.build()).build().toString();
+
+    final Map<String, Object> optionsMap = OptionsBuilder.options()
+        .docType("book")
+        .backend("html5")
+        .headerFooter(true)
+        .safe(SafeMode.UNSAFE)
+        .attributes(AttributesBuilder.attributes()
+            .attribute("toclevels", 3)
+            .attribute(Attributes.TOC_2, true)
+            .attribute(Attributes.TOC_POSITION, "left")
+            .attribute(Attributes.LINK_CSS, true)
+            .attribute(Attributes.SECTION_NUMBERS, true)
+            .attribute(Attributes.SECT_NUM_LEVELS, 4))
+        .asMap();
+    String asciidocResult = asciidoctor.convert(markup, optionsMap);
+    try {
+      Files.write(Paths.get(outputPath), asciidocResult.getBytes());
+    } catch (IOException e) {
+      LOGGER.error(e.getMessage());
+    }
+
+    return asciidocResult;
+  }
+}
diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsSwaggerUIGenerator.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsSwaggerUIGenerator.java
new file mode 100755
index 0000000..2f154b5
--- /dev/null
+++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/ContractsSwaggerUIGenerator.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.docgen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import io.swagger.models.Swagger;
+import io.swagger.util.Json;
+
+public class ContractsSwaggerUIGenerator implements DocGenerator {
+
+  private static Pattern variablePattern = Pattern.compile("(?<=\\{\\{)[a-zA-Z0-9_-]*(?=\\}\\})");
+
+  private final static String DOC_FORMAT = "html";
+
+  @Override
+
+  public boolean canProcess(String type) {
+    return DOC_FORMAT.equals(type);
+  }
+
+  @Override
+  public String generate(Swagger contractContent, String outputPath) {
+
+    String swaggerUiHtml = null;
+    try {
+      String swaggerJson = Json.mapper().writeValueAsString(contractContent);
+      swaggerUiHtml = renderHtml(getSwaggerUiHtml(), Collections.singletonMap("spec", swaggerJson));
+
+      outputPath = correctPath(outputPath);
+      Path outputFile = Paths.get(outputPath);
+
+      if (!Files.exists(outputFile)) {
+        if (outputFile.getParent() != null) {
+          Files.createDirectories(outputFile.getParent());
+        }
+        Files.createFile(outputFile);
+      }
+
+      Files.write(outputFile, swaggerUiHtml.getBytes());
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+
+    return swaggerUiHtml;
+  }
+
+  private String correctPath(String filepath) {
+
+    if (!filepath.endsWith("." + DOC_FORMAT)) {
+      return filepath + DOC_FORMAT;
+    }
+
+    return filepath;
+  }
+
+  private String renderHtml(String html, Map<String, String> args) {
+
+    Matcher variableMatcher = variablePattern.matcher(html);
+    while (variableMatcher.find()) {
+      String variableStr = variableMatcher.group();
+      String variableValue = args.get(variableStr);
+
+      html = html.replace("{{" + variableStr + "}}", variableValue);
+    }
+
+    return html;
+  }
+
+  private String getSwaggerUiHtml() throws IOException {
+    int len;
+
+    ByteArrayOutputStream bout = new ByteArrayOutputStream();
+    InputStream in = this.getClass().getClassLoader().getResourceAsStream("webroot/swagger-ui.html");
+
+    byte[] buf = new byte[1024];
+    while ((len = in.read(buf)) != -1) {
+      bout.write(buf, 0, len);
+    }
+    bout.close();
+    in.close();
+
+    return new String(bout.toByteArray());
+  }
+}
diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGenerator.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGenerator.java
new file mode 100755
index 0000000..6381e5e
--- /dev/null
+++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGenerator.java
@@ -0,0 +1,27 @@
+/*
+ * 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.servicecomb.docgen;
+
+import io.swagger.models.Swagger;
+
+public interface DocGenerator {
+
+  boolean canProcess(String type);
+
+  String generate(Swagger source, String outputPath);
+}
diff --git a/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGeneratorManager.java b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGeneratorManager.java
new file mode 100755
index 0000000..17566b8
--- /dev/null
+++ b/doc-generator/src/main/java/org/apache/servicecomb/docgen/DocGeneratorManager.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.docgen;
+
+import java.util.ServiceLoader;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import io.swagger.models.Swagger;
+
+public class DocGeneratorManager {
+
+  private final static CopyOnWriteArrayList<DocGenerator> registeredGenerators = new CopyOnWriteArrayList<>();
+
+  static {
+    loadInitialDocGenerators();
+  }
+
+  private static void loadInitialDocGenerators() {
+
+    ServiceLoader.load(DocGenerator.class).forEach(registeredGenerators::add);
+  }
+
+  public static String generate(Swagger source, String outputPath, String outputType) {
+
+    for (DocGenerator docGenerator : registeredGenerators) {
+      if (docGenerator.canProcess(outputType)) {
+        return docGenerator.generate(source, outputPath);
+      }
+    }
+
+    return null;
+  }
+}
diff --git a/doc-generator/src/main/resources/META-INF/services/org.apache.servicecomb.docgen.DocGenerator b/doc-generator/src/main/resources/META-INF/services/org.apache.servicecomb.docgen.DocGenerator
new file mode 100755
index 0000000..aa6fb85
--- /dev/null
+++ b/doc-generator/src/main/resources/META-INF/services/org.apache.servicecomb.docgen.DocGenerator
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.docgen.ContractsAsciidocGenerator
+org.apache.servicecomb.docgen.ContractsSwaggerUIGenerator
\ No newline at end of file
diff --git a/doc-generator/src/main/resources/webroot/swagger-ui.html b/doc-generator/src/main/resources/webroot/swagger-ui.html
new file mode 100755
index 0000000..6718b91
--- /dev/null
+++ b/doc-generator/src/main/resources/webroot/swagger-ui.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+
+    <meta charset="UTF-8">
+    <title>Title</title>
+
+    <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui.css">
+    <script src="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui-standalone-preset.js"></script>
+    <script src="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui-bundle.js"></script>
+</head>
+<body>
+
+<div id="swagger-ui"></div>
+
+</body>
+
+
+<script>
+    const ui = SwaggerUIBundle({
+        spec: JSON.parse('{{spec}}'),
+        dom_id: '#swagger-ui',
+        deepLinking: true,
+        presets: [
+            SwaggerUIBundle.presets.apis,
+            SwaggerUIStandalonePreset
+        ],
+        layout: "StandaloneLayout"
+    })
+</script>
+
+</html>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ca48b94..d97307d 100755
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
   <modules>
     <module>code-generator</module>
     <module>toolkit-cli</module>
+    <module>doc-generator</module>
   </modules>
 
 </project>
diff --git a/swagger-ui.html b/swagger-ui.html
new file mode 100755
index 0000000..282a229
--- /dev/null
+++ b/swagger-ui.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+
+    <meta charset="UTF-8">
+    <title>Title</title>
+
+    <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui.css">
+    <script src="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui-standalone-preset.js"></script>
+    <script src="https://unpkg.com/swagger-ui-dist@3.22.1/swagger-ui-bundle.js"></script>
+</head>
+<body>
+
+<div id="swagger-ui"></div>
+
+</body>
+
+
+<script>
+    const ui = SwaggerUIBundle({
+        spec: JSON.parse('{"swagger":"2.0","info":{"description":"ThisisasampleserverPetstoreserver.YoucanfindoutmoreaboutSwaggerat[http://swagger.io](http://swagger.io)oron[irc.freenode.net,#swagger](http://swagger.io/irc/).Forthissample,youcanusetheapikey`special-key`totesttheauthorizationfilters.","version":"1.0.0","title":"SwaggerPetstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache2.0","url":"http://www.apache.org/li [...]
+        dom_id: '#swagger-ui',
+        deepLinking: true,
+        presets: [
+            SwaggerUIBundle.presets.apis,
+            SwaggerUIStandalonePreset
+        ],
+        layout: "StandaloneLayout"
+    })
+</script>
+
+</html>
\ No newline at end of file