Skip to content

Commit

Permalink
Merge pull request #1011 from zlxs1317169/dubboword
Browse files Browse the repository at this point in the history
Add RpcWordDocBuilder to support generate word of dubbo
  • Loading branch information
shalousun authored Jan 9, 2025
2 parents be3b7ea + 9284398 commit 8dd357d
Show file tree
Hide file tree
Showing 7 changed files with 1,819 additions and 1 deletion.
33 changes: 33 additions & 0 deletions src/main/java/com/ly/doc/builder/IRpcDocBuilderTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@

import com.ly.doc.constants.DocGlobalConstants;
import com.ly.doc.constants.TemplateVariable;
import com.ly.doc.constants.TornaConstants;
import com.ly.doc.factory.BuildTemplateFactory;
import com.ly.doc.model.AbstractRpcApiDoc;
import com.ly.doc.model.ApiConfig;
import com.ly.doc.model.ApiDocDict;
import com.ly.doc.model.ApiErrorCode;
import com.ly.doc.model.rpc.RpcApiAllData;
import com.ly.doc.model.rpc.RpcApiDoc;
import com.ly.doc.template.IDocBuildTemplate;
import com.ly.doc.utils.BeetlTemplateUtil;
import com.ly.doc.utils.DocUtil;
Expand Down Expand Up @@ -121,6 +123,37 @@ default void buildAllInOne(List<T> apiDocList, ApiConfig config, JavaProjectBuil
FileUtil.nioWriteFile(tpl.render(), outPath + DocGlobalConstants.FILE_SEPARATOR + outPutFileName);
}

/**
* Merge all api doc into one document.
* @param apiDocList list data of Api doc
* @param config api config
* @param javaProjectBuilder JavaProjectBuilder
* @param template template
* @param outPutFileName output file
*/
default Template buildAllInOneWord(List<RpcApiDoc> apiDocList, ApiConfig config,
JavaProjectBuilder javaProjectBuilder, String template, String outPutFileName) {
String outPath = config.getOutPath();
String rpcConfig = config.getRpcConsumerConfig();
String rpcConfigConfigContent = null;
if (Objects.nonNull(rpcConfig)) {
rpcConfigConfigContent = FileUtil.getFileContent(rpcConfig);
}
FileUtil.mkdirs(outPath);
Template tpl = BeetlTemplateUtil.getByName(template);
tpl.binding(TemplateVariable.API_DOC_LIST.getVariable(), apiDocList);
tpl.binding(TemplateVariable.DEPENDENCY_LIST.getVariable(), config.getRpcApiDependencies());
tpl.binding(TemplateVariable.RPC_CONSUMER_CONFIG.getVariable(), rpcConfigConfigContent);
// binding common variable
this.bindingCommonVariable(config, javaProjectBuilder, tpl, apiDocList.isEmpty());
this.setDirectoryLanguageVariable(config, tpl);
boolean onlyHasDefaultGroup = apiDocList.stream()
.allMatch(doc -> Objects.equals(TornaConstants.DEFAULT_GROUP_CODE, doc.getGroup()));

tpl.binding(TemplateVariable.API_DOC_LIST_ONLY_HAS_DEFAULT_GROUP.getVariable(), onlyHasDefaultGroup);
return tpl;
}

/**
* Build search js.
* @param apiDocList list data of Api doc
Expand Down
79 changes: 78 additions & 1 deletion src/main/java/com/ly/doc/builder/rpc/RpcDocBuilderTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,21 @@
import com.ly.doc.builder.IRpcDocBuilderTemplate;
import com.ly.doc.constants.DocGlobalConstants;
import com.ly.doc.constants.FrameworkEnum;
import com.ly.doc.model.ApiConfig;
import com.ly.doc.constants.TornaConstants;
import com.ly.doc.model.*;
import com.ly.doc.model.rpc.RpcApiDoc;
import com.ly.doc.utils.DocPathUtil;
import com.ly.doc.utils.DocUtil;
import com.power.common.util.CollectionUtil;
import com.power.common.util.StringUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
* rpc doc builder template.
*
Expand All @@ -49,4 +60,70 @@ public RpcApiDoc createEmptyApiDoc() {
return new RpcApiDoc();
}

/**
* handle group api docs.
* @param apiDocList list of apiDocList
* @param apiConfig ApiConfig apiConfig
* @return List of ApiDoc
* @author wangaiping
*/

List<RpcApiDoc> handleApiGroup(List<RpcApiDoc> apiDocList, ApiConfig apiConfig) {
if (CollectionUtil.isEmpty(apiDocList) || apiConfig == null) {
return apiDocList;
}
List<ApiGroup> groups = apiConfig.getGroups();
List<RpcApiDoc> finalApiDocs = new ArrayList<>();

RpcApiDoc defaultGroup = RpcApiDoc.buildGroupApiDoc(TornaConstants.DEFAULT_GROUP_CODE);
// show default group
AtomicInteger order = new AtomicInteger(1);
finalApiDocs.add(defaultGroup);

if (CollectionUtil.isEmpty(groups)) {
defaultGroup.setOrder(order.getAndIncrement());
defaultGroup.getChildrenApiDocs().addAll(apiDocList);
return finalApiDocs;
}
Map<String, String> hasInsert = new HashMap<>(16);
for (ApiGroup group : groups) {
RpcApiDoc groupApiDoc = RpcApiDoc.buildGroupApiDoc(group.getName());
finalApiDocs.add(groupApiDoc);
for (RpcApiDoc doc : apiDocList) {
if (hasInsert.containsKey(doc.getAlias())) {
continue;
}
if (!DocUtil.isMatch(group.getApis(), doc.getPackageName() + "." + doc.getName())) {
continue;
}
hasInsert.put(doc.getAlias(), null);
groupApiDoc.getChildrenApiDocs().add(doc);
doc.setOrder(groupApiDoc.getChildrenApiDocs().size());
doc.setGroup(group.getName());
if (StringUtil.isEmpty(group.getPaths())) {
continue;
}
List<RpcJavaMethod> methodDocs = doc.getList()
.stream()
.filter(l -> DocPathUtil.matches(l.getMethodDefinition(), group.getPaths(), null))
.collect(Collectors.toList());
doc.setList(methodDocs);
}
}
// Ungrouped join the default group
for (RpcApiDoc doc : apiDocList) {
String key = doc.getAlias();
if (!hasInsert.containsKey(key)) {
defaultGroup.getChildrenApiDocs().add(doc);
doc.setOrder(defaultGroup.getChildrenApiDocs().size());
hasInsert.put(doc.getAlias(), null);
}
}
if (CollectionUtil.isEmpty(defaultGroup.getChildrenApiDocs())) {
finalApiDocs.remove(defaultGroup);
}
finalApiDocs.forEach(group -> group.setOrder(order.getAndIncrement()));
return finalApiDocs;
}

}
148 changes: 148 additions & 0 deletions src/main/java/com/ly/doc/builder/rpc/RpcWordDocBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright (C) 2018-2024 smart-doc
*
* 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 com.ly.doc.builder.rpc;

import com.ly.doc.constants.DocGlobalConstants;
import com.ly.doc.helper.JavaProjectBuilderHelper;
import com.ly.doc.model.ApiConfig;
import com.ly.doc.model.rpc.RpcApiDoc;
import com.thoughtworks.qdox.JavaProjectBuilder;
import org.beetl.core.Template;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
* Dubbo Word doc builder
*
* @author <a href="[email protected]">wangaiping</a>
* @since 3.0.10
*/
public class RpcWordDocBuilder {

/**
* template docx
*/
private static final String TEMPLATE_DOCX = "template/dubbo/template.docx";

/**
* build docx file name
*/
private static final String INDEX_DOC = "rpc-index.docx";

/**
* build error code docx file name
*/
private static final String BUILD_ERROR_DOCX = "error.docx";

/**
* build directory data docx file name
*/
private static final String BUILD_DICT_DOCX = "dict.docx";

/**
* private constructor
*/
private RpcWordDocBuilder() {
throw new IllegalStateException("Utility class");
}

/**
* build dubbo api
* @param config config
* @throws Exception exception
*/
public static void buildApiDoc(ApiConfig config) throws Exception {
JavaProjectBuilder javaProjectBuilder = JavaProjectBuilderHelper.create();
buildApiDoc(config, javaProjectBuilder);
}

/**
* build dubbo api
* @param config config
* @param javaProjectBuilder javaProjectBuilder
* @throws Exception exception
*/
public static void buildApiDoc(ApiConfig config, JavaProjectBuilder javaProjectBuilder) throws Exception {
RpcDocBuilderTemplate rpcDocBuilderTemplate = new RpcDocBuilderTemplate();
List<RpcApiDoc> apiDocList = rpcDocBuilderTemplate.getApiDoc(false, true, false, config, javaProjectBuilder);

if (config.isAllInOne()) {
String docName = rpcDocBuilderTemplate.allInOneDocName(config, INDEX_DOC,
DocGlobalConstants.WORD_DOC_EXTENSION);
apiDocList = rpcDocBuilderTemplate.handleApiGroup(apiDocList, config);
Template tpl = rpcDocBuilderTemplate.buildAllInOneWord(apiDocList, config, javaProjectBuilder,
DocGlobalConstants.RPC_ALL_IN_ONE_WORD_TPL, docName);

String outPath = config.getOutPath();
copyAndReplaceDocx(tpl.render(), outPath + DocGlobalConstants.FILE_SEPARATOR + docName);
}

}

/**
* replace docx content
* @param content doc content
* @param docxOutputPath docx output path
* @throws Exception exception
* @since 1.0.0
*/
public static void copyAndReplaceDocx(String content, String docxOutputPath) throws Exception {
InputStream resourceAsStream = RpcWordDocBuilder.class.getClassLoader().getResourceAsStream(TEMPLATE_DOCX);
Objects.requireNonNull(resourceAsStream, "dubbo word template docx is not found");

ZipInputStream zipInputStream = new ZipInputStream(resourceAsStream);
ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(Paths.get(docxOutputPath)));
// Traverse the files in the compressed package
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null) {
String entryName = entry.getName();
// copy fix the bug: invalid entry compressed size
zipOutputStream.putNextEntry(new ZipEntry(entryName));
if ("word/document.xml".equals(entryName)) {
byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
zipOutputStream.write(bytes, 0, bytes.length);
}
else {
// copy
byte[] buffer = new byte[1024];
int len;
while ((len = zipInputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
}

zipOutputStream.closeEntry();
zipInputStream.closeEntry();
}

zipInputStream.close();
zipOutputStream.close();
}

}
10 changes: 10 additions & 0 deletions src/main/java/com/ly/doc/constants/DocGlobalConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,11 @@ public interface DocGlobalConstants {
*/
String RPC_ALL_IN_ONE_ADOC_TPL = "dubbo/DubboAllInOne.adoc";

/**
* rpc all in one word template.
*/
String RPC_ALL_IN_ONE_WORD_TPL = "dubbo/DubboAllInOneWordTemplate.xml";

/**
* rpc all in one html template.
*/
Expand Down Expand Up @@ -609,6 +614,11 @@ public interface DocGlobalConstants {
*/
String ASCIIDOC_EXTENSION = ".adoc";

/**
* asciidoc extension.
*/
String WORD_DOC_EXTENSION = ".docx";

/**
* default map key desc.
*/
Expand Down
Loading

0 comments on commit 8dd357d

Please sign in to comment.