You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by do...@apache.org on 2022/04/15 12:02:46 UTC

[incubator-inlong] 02/02: [INLONG-3731][Manager] Abstract state and optimization printUtil (#3739)

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

dockerzhang pushed a commit to branch release-1.1.0
in repository https://gitbox.apache.org/repos/asf/incubator-inlong.git

commit f81ec7e75822a40fa284ee26e7737d1459f0242f
Author: haifxu <xh...@gmail.com>
AuthorDate: Fri Apr 15 19:58:33 2022 +0800

    [INLONG-3731][Manager] Abstract state and optimization printUtil (#3739)
---
 .../inlong/manager/client/cli/CommandDescribe.java |   9 +-
 .../inlong/manager/client/cli/CommandList.java     |  22 ++--
 .../inlong/manager/client/cli/CommandUtil.java     | 100 -----------------
 .../manager/client/cli/enums/InlongGroupState.java |  76 +++++++++++++
 .../cli/{CommandUtil.java => util/PrintUtil.java}  | 120 ++++++---------------
 5 files changed, 131 insertions(+), 196 deletions(-)

diff --git a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandDescribe.java b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandDescribe.java
index d2698979c..268d8fb48 100644
--- a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandDescribe.java
+++ b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandDescribe.java
@@ -21,6 +21,7 @@ import com.beust.jcommander.Parameter;
 import com.beust.jcommander.Parameters;
 import com.github.pagehelper.PageInfo;
 import org.apache.inlong.manager.client.api.inner.InnerInlongManagerClient;
+import org.apache.inlong.manager.client.cli.util.PrintUtil;
 import org.apache.inlong.manager.common.pojo.group.InlongGroupListResponse;
 import org.apache.inlong.manager.common.pojo.sink.SinkListResponse;
 import org.apache.inlong.manager.common.pojo.source.SourceListResponse;
@@ -56,7 +57,7 @@ public class CommandDescribe extends CommandBase {
             try {
                 InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
                 List<FullStreamResponse> fullStreamResponseList = managerClient.listStreamInfo(groupId);
-                fullStreamResponseList.forEach(response -> printJson(response.getStreamInfo()));
+                fullStreamResponseList.forEach(response -> PrintUtil.printJson(response.getStreamInfo()));
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
@@ -83,7 +84,7 @@ public class CommandDescribe extends CommandBase {
             try {
                 InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
                 PageInfo<InlongGroupListResponse> groupPageInfo = managerClient.listGroups(group, status, 1, pageSize);
-                groupPageInfo.getList().forEach(this::printJson);
+                groupPageInfo.getList().forEach(PrintUtil::printJson);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
@@ -107,7 +108,7 @@ public class CommandDescribe extends CommandBase {
             InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
             try {
                 List<SinkListResponse> sinkListResponses = managerClient.listSinks(group, stream);
-                sinkListResponses.forEach(this::printJson);
+                sinkListResponses.forEach(PrintUtil::printJson);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
@@ -134,7 +135,7 @@ public class CommandDescribe extends CommandBase {
             try {
                 InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
                 List<SourceListResponse> sourceListResponses = managerClient.listSources(group, stream, type);
-                sourceListResponses.forEach(this::printJson);
+                sourceListResponses.forEach(PrintUtil::printJson);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
diff --git a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandList.java b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandList.java
index 45e08fbe4..4244408fc 100644
--- a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandList.java
+++ b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandList.java
@@ -21,10 +21,12 @@ import com.beust.jcommander.Parameter;
 import com.beust.jcommander.Parameters;
 import com.github.pagehelper.PageInfo;
 import org.apache.inlong.manager.client.api.inner.InnerInlongManagerClient;
+import org.apache.inlong.manager.client.cli.enums.InlongGroupState;
 import org.apache.inlong.manager.client.cli.pojo.GroupInfo;
 import org.apache.inlong.manager.client.cli.pojo.SinkInfo;
 import org.apache.inlong.manager.client.cli.pojo.SourceInfo;
 import org.apache.inlong.manager.client.cli.pojo.StreamInfo;
+import org.apache.inlong.manager.client.cli.util.PrintUtil;
 import org.apache.inlong.manager.common.pojo.group.InlongGroupListResponse;
 import org.apache.inlong.manager.common.pojo.sink.SinkListResponse;
 import org.apache.inlong.manager.common.pojo.source.SourceListResponse;
@@ -66,7 +68,7 @@ public class CommandList extends CommandBase {
                 fullStreamResponseList.forEach(fullStreamResponse -> {
                     inlongStreamInfoList.add(fullStreamResponse.getStreamInfo());
                 });
-                print(inlongStreamInfoList, StreamInfo.class);
+                PrintUtil.print(inlongStreamInfoList, StreamInfo.class);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
@@ -80,7 +82,7 @@ public class CommandList extends CommandBase {
         private java.util.List<String> params;
 
         @Parameter(names = {"-s", "--status"})
-        private int status;
+        private String status;
 
         @Parameter(names = {"-g", "--group"}, description = "inlong group id")
         private String group;
@@ -90,10 +92,16 @@ public class CommandList extends CommandBase {
 
         @Override
         void run() {
-            InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
             try {
-                PageInfo<InlongGroupListResponse> groupPageInfo = managerClient.listGroups(group, status, 1, pageSize);
-                print(groupPageInfo.getList(), GroupInfo.class);
+                List<Integer> stateList = InlongGroupState.parseStatus(status);
+                InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
+                List<InlongGroupListResponse> groupList = new ArrayList<>();
+                for (int state : stateList) {
+                    PageInfo<InlongGroupListResponse> groupPageInfo = managerClient.listGroups(group, state, 1,
+                            pageSize);
+                    groupList.addAll(groupPageInfo.getList());
+                }
+                PrintUtil.print(groupList, GroupInfo.class);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
@@ -117,7 +125,7 @@ public class CommandList extends CommandBase {
             InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
             try {
                 List<SinkListResponse> sinkListResponses = managerClient.listSinks(group, stream);
-                print(sinkListResponses, SinkInfo.class);
+                PrintUtil.print(sinkListResponses, SinkInfo.class);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
@@ -144,7 +152,7 @@ public class CommandList extends CommandBase {
             InnerInlongManagerClient managerClient = new InnerInlongManagerClient(connect().getConfiguration());
             try {
                 List<SourceListResponse> sourceListResponses = managerClient.listSources(group, stream, type);
-                print(sourceListResponses, SourceInfo.class);
+                PrintUtil.print(sourceListResponses, SourceInfo.class);
             } catch (Exception e) {
                 System.out.println(e.getMessage());
             }
diff --git a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java
index e39edc801..ab53c8067 100644
--- a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java
+++ b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java
@@ -18,15 +18,10 @@
 package org.apache.inlong.manager.client.cli;
 
 import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.inlong.manager.client.api.ClientConfiguration;
 import org.apache.inlong.manager.client.api.auth.DefaultAuthentication;
 import org.apache.inlong.manager.client.api.impl.InlongClientImpl;
 import org.apache.inlong.manager.client.cli.util.GsonUtil;
-import org.springframework.beans.BeanUtils;
 
 import java.io.BufferedInputStream;
 import java.io.File;
@@ -36,11 +31,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.lang.reflect.Field;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
 import java.util.Properties;
 
 abstract class CommandUtil {
@@ -65,22 +55,6 @@ abstract class CommandUtil {
         return new InlongClientImpl(serviceUrl, configuration);
     }
 
-    <T, K> void print(List<T> item, Class<K> clazz) {
-        if (item.isEmpty()) {
-            return;
-        }
-        List<K> list = copyObject(item, clazz);
-        int[] maxColumnWidth = getColumnWidth(list);
-        printTable(list, maxColumnWidth);
-    }
-
-    <T> void printJson(T item) {
-        Gson gson = new GsonBuilder().setPrettyPrinting().create();
-        JsonParser jsonParser = new JsonParser();
-        JsonObject jsonObject = jsonParser.parse(gson.toJson(item)).getAsJsonObject();
-        System.out.println(gson.toJson(jsonObject));
-    }
-
     String readFile(File file) {
         if (!file.exists()) {
             System.out.println("File does not exist.");
@@ -110,78 +84,4 @@ abstract class CommandUtil {
     }
 
     abstract void run() throws Exception;
-
-    private <K> void printTable(List<K> list, int[] columnWidth) {
-        Field[] fields = list.get(0).getClass().getDeclaredFields();
-        System.out.print("|");
-        for (int i = 0; i < fields.length; i++) {
-            System.out.printf("%s|", StringUtils.center(fields[i].getName(), columnWidth[i]));
-        }
-        System.out.println();
-        for (int i = 0; i < fields.length; i++) {
-            System.out.printf("%s", StringUtils.leftPad("—", columnWidth[i] + 1, "—"));
-        }
-        System.out.println();
-        list.forEach(k -> {
-            for (int j = 0; j < fields.length; j++) {
-                fields[j].setAccessible(true);
-                try {
-                    System.out.print("|");
-                    if (fields[j].get(k) != null) {
-                        if (fields[j].getType().equals(Date.class)) {
-                            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                            String dataFormat = sf.format(fields[j].get(k));
-                            System.out.printf("%s", StringUtils.center(dataFormat, columnWidth[j]));
-                        } else {
-                            System.out.printf("%s", StringUtils.center(fields[j].get(k).toString(), columnWidth[j]));
-                        }
-                    } else {
-                        System.out.printf("%s", StringUtils.center("NULL", columnWidth[j]));
-                    }
-                } catch (IllegalAccessException e) {
-                    e.printStackTrace();
-                }
-            }
-            System.out.println("|");
-        });
-    }
-
-    private <T, K> List<K> copyObject(List<T> item, Class<K> clazz) {
-        List<K> newList = new ArrayList<>();
-        item.forEach(t -> {
-            try {
-                K k = clazz.newInstance();
-                BeanUtils.copyProperties(t, k);
-                newList.add(k);
-            } catch (InstantiationException | IllegalAccessException e) {
-                e.printStackTrace();
-            }
-        });
-        return newList;
-    }
-
-    private <K> int[] getColumnWidth(List<K> list) {
-        Field[] fields = list.get(0).getClass().getDeclaredFields();
-        int[] maxWidth = new int[fields.length];
-        for (int i = 0; i < fields.length; i++) {
-            maxWidth[i] = Math.max(fields[i].getName().length(), maxWidth[i]);
-        }
-        list.forEach(k -> {
-            try {
-                for (int j = 0; j < fields.length; j++) {
-                    fields[j].setAccessible(true);
-                    if (fields[j].get(k) != null) {
-                        int length = fields[j].get(k).toString().length();
-                        maxWidth[j] = Math.max(length, maxWidth[j]);
-                    }
-                }
-            } catch (IllegalAccessException e) {
-                e.printStackTrace();
-            }
-        });
-        for (int i = 0; i < maxWidth.length; i++) {
-            maxWidth[i] += 4;
-        }
-        return maxWidth;
-    }
 }
diff --git a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/enums/InlongGroupState.java b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/enums/InlongGroupState.java
new file mode 100644
index 000000000..63bc8dd04
--- /dev/null
+++ b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/enums/InlongGroupState.java
@@ -0,0 +1,76 @@
+/*
+ * 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.inlong.manager.client.cli.enums;
+
+import org.apache.inlong.manager.common.enums.GroupState;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public enum InlongGroupState {
+    CREATE, REJECTED, INITIALIZING, OPERATING, STARTED, FAILED, STOPPED, FINISHED, DELETED;
+
+    public static List<Integer> parseStatus(String state) {
+
+        InlongGroupState groupState;
+        try {
+            groupState = InlongGroupState.valueOf(state);
+        } catch (IllegalArgumentException e) {
+            throw new IllegalArgumentException(String.format("Unsupported status %s for group", state));
+        }
+
+        List<Integer> stateList = new ArrayList<>();
+        switch (groupState) {
+            case CREATE:
+                stateList.add(GroupState.DRAFT.getCode());
+                stateList.add(GroupState.TO_BE_SUBMIT.getCode());
+                return stateList;
+            case OPERATING:
+                stateList.add(GroupState.DELETING.getCode());
+                stateList.add(GroupState.SUSPENDING.getCode());
+                stateList.add(GroupState.RESTARTING.getCode());
+                return stateList;
+            case REJECTED:
+                stateList.add(GroupState.APPROVE_REJECTED.getCode());
+                return stateList;
+            case INITIALIZING:
+                stateList.add(GroupState.TO_BE_APPROVAL.getCode());
+                stateList.add(GroupState.APPROVE_PASSED.getCode());
+                stateList.add(GroupState.CONFIG_ING.getCode());
+                return stateList;
+            case FAILED:
+                stateList.add(GroupState.CONFIG_FAILED.getCode());
+                return stateList;
+            case STARTED:
+                stateList.add(GroupState.RESTARTED.getCode());
+                stateList.add(GroupState.CONFIG_SUCCESSFUL.getCode());
+                return stateList;
+            case STOPPED:
+                stateList.add(GroupState.SUSPENDED.getCode());
+                return stateList;
+            case FINISHED:
+                stateList.add(GroupState.FINISH.getCode());
+                return stateList;
+            case DELETED:
+                stateList.add(GroupState.DELETED.getCode());
+                return stateList;
+            default:
+                throw new IllegalArgumentException(String.format("Unsupported status %s for group", state));
+        }
+    }
+}
diff --git a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/util/PrintUtil.java
similarity index 52%
copy from inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java
copy to inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/util/PrintUtil.java
index e39edc801..06774e452 100644
--- a/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/CommandUtil.java
+++ b/inlong-manager/manager-client-tools/src/main/java/org/apache/inlong/manager/client/cli/util/PrintUtil.java
@@ -15,57 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.inlong.manager.client.cli;
+package org.apache.inlong.manager.client.cli.util;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.inlong.manager.client.api.ClientConfiguration;
-import org.apache.inlong.manager.client.api.auth.DefaultAuthentication;
-import org.apache.inlong.manager.client.api.impl.InlongClientImpl;
-import org.apache.inlong.manager.client.cli.util.GsonUtil;
 import org.springframework.beans.BeanUtils;
 
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
 import java.lang.reflect.Field;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.Properties;
 
-abstract class CommandUtil {
+public class PrintUtil {
 
-    public InlongClientImpl connect() {
-        Properties properties = new Properties();
-        String path = System.getProperty("user.dir") + "/conf/application.properties";
+    private static final String joint = "+";
+    private static final String horizontal = "—";
+    private static final String vertical = "|";
 
-        try {
-            InputStream inputStream = new BufferedInputStream(new FileInputStream(path));
-            properties.load(inputStream);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        String serviceUrl = properties.getProperty("server.host") + ":" + properties.getProperty("server.port");
-        String user = properties.getProperty("default.admin.user");
-        String password = properties.getProperty("default.admin.password");
-
-        ClientConfiguration configuration = new ClientConfiguration();
-        configuration.setAuthentication(new DefaultAuthentication(user, password));
-
-        return new InlongClientImpl(serviceUrl, configuration);
-    }
-
-    <T, K> void print(List<T> item, Class<K> clazz) {
+    public static <T, K> void print(List<T> item, Class<K> clazz) {
         if (item.isEmpty()) {
             return;
         }
@@ -74,79 +45,50 @@ abstract class CommandUtil {
         printTable(list, maxColumnWidth);
     }
 
-    <T> void printJson(T item) {
+    public static <T> void printJson(T item) {
         Gson gson = new GsonBuilder().setPrettyPrinting().create();
         JsonParser jsonParser = new JsonParser();
         JsonObject jsonObject = jsonParser.parse(gson.toJson(item)).getAsJsonObject();
         System.out.println(gson.toJson(jsonObject));
     }
 
-    String readFile(File file) {
-        if (!file.exists()) {
-            System.out.println("File does not exist.");
-        } else {
-            try {
-                FileReader fileReader = new FileReader(file);
-                Reader reader = new InputStreamReader(new FileInputStream(file));
-                int ch;
-                StringBuffer stringBuffer = new StringBuffer();
-                while ((ch = reader.read()) != -1) {
-                    stringBuffer.append((char) ch);
-                }
-                fileReader.close();
-                reader.close();
-
-                return stringBuffer.toString();
-            } catch (Exception e) {
-                System.out.println(e.getMessage());
-            }
-        }
-        return null;
-    }
-
-    CreateGroupConf jsonToObject(String string) {
-        Gson gson = GsonUtil.gsonBuilder();
-        return gson.fromJson(string, CreateGroupConf.class);
-    }
-
-    abstract void run() throws Exception;
-
-    private <K> void printTable(List<K> list, int[] columnWidth) {
+    private static <K> void printTable(List<K> list, int[] columnWidth) {
         Field[] fields = list.get(0).getClass().getDeclaredFields();
-        System.out.print("|");
-        for (int i = 0; i < fields.length; i++) {
-            System.out.printf("%s|", StringUtils.center(fields[i].getName(), columnWidth[i]));
-        }
-        System.out.println();
+
+        String format = "%s" + vertical;
+        printLine(columnWidth, fields.length);
+        System.out.print(vertical);
         for (int i = 0; i < fields.length; i++) {
-            System.out.printf("%s", StringUtils.leftPad("—", columnWidth[i] + 1, "—"));
+            System.out.printf(format, StringUtils.center(fields[i].getName(), columnWidth[i]));
         }
         System.out.println();
+        printLine(columnWidth, fields.length);
         list.forEach(k -> {
-            for (int j = 0; j < fields.length; j++) {
-                fields[j].setAccessible(true);
+            for (int i = 0; i < fields.length; i++) {
+                fields[i].setAccessible(true);
                 try {
-                    System.out.print("|");
-                    if (fields[j].get(k) != null) {
-                        if (fields[j].getType().equals(Date.class)) {
+                    System.out.print(vertical);
+                    if (fields[i].get(k) != null) {
+                        if (fields[i].getType().equals(Date.class)) {
                             SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                            String dataFormat = sf.format(fields[j].get(k));
-                            System.out.printf("%s", StringUtils.center(dataFormat, columnWidth[j]));
+                            String dataFormat = sf.format(fields[i].get(k));
+                            System.out.printf("%s", StringUtils.center(dataFormat, columnWidth[i]));
                         } else {
-                            System.out.printf("%s", StringUtils.center(fields[j].get(k).toString(), columnWidth[j]));
+                            System.out.printf("%s", StringUtils.center(fields[i].get(k).toString(), columnWidth[i]));
                         }
                     } else {
-                        System.out.printf("%s", StringUtils.center("NULL", columnWidth[j]));
+                        System.out.printf("%s", StringUtils.center("NULL", columnWidth[i]));
                     }
                 } catch (IllegalAccessException e) {
                     e.printStackTrace();
                 }
             }
-            System.out.println("|");
+            System.out.println(vertical);
         });
+        printLine(columnWidth, fields.length);
     }
 
-    private <T, K> List<K> copyObject(List<T> item, Class<K> clazz) {
+    private static <T, K> List<K> copyObject(List<T> item, Class<K> clazz) {
         List<K> newList = new ArrayList<>();
         item.forEach(t -> {
             try {
@@ -160,7 +102,7 @@ abstract class CommandUtil {
         return newList;
     }
 
-    private <K> int[] getColumnWidth(List<K> list) {
+    private static <K> int[] getColumnWidth(List<K> list) {
         Field[] fields = list.get(0).getClass().getDeclaredFields();
         int[] maxWidth = new int[fields.length];
         for (int i = 0; i < fields.length; i++) {
@@ -184,4 +126,12 @@ abstract class CommandUtil {
         }
         return maxWidth;
     }
+
+    private static void printLine(int[] columnWidth, int fieldNum) {
+        System.out.print(joint);
+        for (int i = 0; i < fieldNum; i++) {
+            System.out.printf("%s", StringUtils.leftPad(joint, columnWidth[i] + 1, horizontal));
+        }
+        System.out.println();
+    }
 }