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

liuyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/master by this push:
     new 3bc7c925d82 [feature][doc] Show language support for pulsar-admin 
functions flags (#16853)
3bc7c925d82 is described below

commit 3bc7c925d82241d594ddefbae4a4f416974528ba
Author: Mercurio <[email protected]>
AuthorDate: Tue Aug 2 17:29:49 2022 +0800

    [feature][doc] Show language support for pulsar-admin functions flags 
(#16853)
---
 .../org/apache/pulsar/admin/cli/CmdFunctions.java  | 126 ++++++++++++---------
 .../pulsar/admin/cli/CmdGenerateDocument.java      |  39 +++++--
 2 files changed, 100 insertions(+), 65 deletions(-)

diff --git 
a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java
 
b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java
index f7da5bf7174..ddb84628eff 100644
--- 
a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java
+++ 
b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdFunctions.java
@@ -185,40 +185,42 @@ public class CmdFunctions extends CmdBase {
      */
     @Getter
     abstract class FunctionDetailsCommand extends BaseCommand {
-        @Parameter(names = "--fqfn", description = "The Fully Qualified 
Function Name (FQFN) for the function")
+        @Parameter(names = "--fqfn", description = "The Fully Qualified 
Function Name (FQFN) for the function"
+                + " #Java, Python")
         protected String fqfn;
-        @Parameter(names = "--tenant", description = "The tenant of a Pulsar 
Function")
+        @Parameter(names = "--tenant", description = "The tenant of a Pulsar 
Function #Java, Python, Go")
         protected String tenant;
-        @Parameter(names = "--namespace", description = "The namespace of a 
Pulsar Function")
+        @Parameter(names = "--namespace", description = "The namespace of a 
Pulsar Function #Java, Python, Go")
         protected String namespace;
-        @Parameter(names = "--name", description = "The name of a Pulsar 
Function")
+        @Parameter(names = "--name", description = "The name of a Pulsar 
Function #Java, Python, Go")
         protected String functionName;
         // for backwards compatibility purposes
         @Parameter(names = "--className", description = "The class name of a 
Pulsar Function", hidden = true)
         protected String deprecatedClassName;
-        @Parameter(names = "--classname", description = "The class name of a 
Pulsar Function")
+        @Parameter(names = "--classname", description = "The class name of a 
Pulsar Function #Java, Python")
         protected String className;
         @Parameter(names = { "-t", "--function-type" }, description = "The 
built-in Pulsar Function type")
         protected String functionType;
         @Parameter(names = "--jar", description = "Path to the JAR file for 
the function "
                 + "(if the function is written in Java). It also supports URL 
path [http/https/file "
                 + "(file protocol assumes that file already exists on worker 
host)/function "
-                + "(package URL from packages management service)] from which 
worker can download the package.",
+                + "(package URL from packages management service)] from which 
worker can download the package. #Java",
                 listConverter = StringConverter.class)
         protected String jarFile;
         @Parameter(names = "--py", description = "Path to the main Python 
file/Python Wheel file for the function "
                 + "(if the function is written in Python). It also supports 
URL path [http/https/file "
                 + "(file protocol assumes that file already exists on worker 
host)/function "
-                + "(package URL from packages management service)] from which 
worker can download the package.",
+                + "(package URL from packages management service)] from which 
worker can download the package. #Python",
                 listConverter = StringConverter.class)
         protected String pyFile;
         @Parameter(names = "--go", description = "Path to the main Go 
executable binary for the function "
                 + "(if the function is written in Go). It also supports URL 
path [http/https/file "
                 + "(file protocol assumes that file already exists on worker 
host)/function "
-                + "(package URL from packages management service)] from which 
worker can download the package.")
+                + "(package URL from packages management service)] from which 
worker can download the package. #Go")
         protected String goFile;
         @Parameter(names = {"-i", "--inputs"}, description = "The input topic 
or "
-                + "topics (multiple topics can be specified as a 
comma-separated list) of a Pulsar Function")
+                + "topics (multiple topics can be specified as a 
comma-separated list) of a Pulsar Function"
+                + " #Java, Python, Go")
         protected String inputs;
         // for backwards compatibility purposes
         @Parameter(names = "--topicsPattern", description = "TopicsPattern to 
consume from list of topics "
@@ -228,23 +230,27 @@ public class CmdFunctions extends CmdBase {
         protected String deprecatedTopicsPattern;
         @Parameter(names = "--topics-pattern", description = "The topic 
pattern to consume from list of topics "
                 + "under a namespace that match the pattern. [--input] and 
[--topic-pattern] are mutually exclusive. "
-                + "Add SerDe class name for a pattern in --custom-serde-inputs 
(supported for java fun only)")
+                + "Add SerDe class name for a pattern in --custom-serde-inputs 
(supported for java fun only)"
+                + " #Java, Python")
         protected String topicsPattern;
 
         @Parameter(names = {"-o", "--output"},
-                description = "The output topic of a Pulsar Function (If none 
is specified, no output is written)")
+                description = "The output topic of a Pulsar Function (If none 
is specified, no output is written)"
+                        + " #Java, Python, Go")
         protected String output;
-        @Parameter(names = "--producer-config", description = "The custom 
producer configuration (as a JSON string)")
+        @Parameter(names = "--producer-config", description = "The custom 
producer configuration (as a JSON string)"
+                + " #Java")
         protected String producerConfig;
         // for backwards compatibility purposes
         @Parameter(names = "--logTopic",
                 description = "The topic to which the logs of a Pulsar 
Function are produced", hidden = true)
         protected String deprecatedLogTopic;
-        @Parameter(names = "--log-topic", description = "The topic to which 
the logs of a Pulsar Function are produced")
+        @Parameter(names = "--log-topic", description = "The topic to which 
the logs of a Pulsar Function are produced"
+                + " #Java, Python, Go")
         protected String logTopic;
 
         @Parameter(names = {"-st", "--schema-type"}, description = "The 
builtin schema type or "
-                + "custom schema class name to be used for messages output by 
the function")
+                + "custom schema class name to be used for messages output by 
the function #Java")
         protected String schemaType = "";
 
         // for backwards compatibility purposes
@@ -252,124 +258,128 @@ public class CmdFunctions extends CmdBase {
                 description = "The map of input topics to SerDe class names 
(as a JSON string)", hidden = true)
         protected String deprecatedCustomSerdeInputString;
         @Parameter(names = "--custom-serde-inputs",
-                description = "The map of input topics to SerDe class names 
(as a JSON string)")
+                description = "The map of input topics to SerDe class names 
(as a JSON string) #Java, Python")
         protected String customSerdeInputString;
         @Parameter(names = "--custom-schema-inputs",
-                description = "The map of input topics to Schema properties 
(as a JSON string)")
+                description = "The map of input topics to Schema properties 
(as a JSON string) #Java, Python")
         protected String customSchemaInputString;
         @Parameter(names = "--custom-schema-outputs",
-                description = "The map of input topics to Schema properties 
(as a JSON string)")
+                description = "The map of input topics to Schema properties 
(as a JSON string) #Java")
         protected String customSchemaOutputString;
         @Parameter(names = "--input-specs",
-                description = "The map of inputs to custom configuration (as a 
JSON string)")
+                description = "The map of inputs to custom configuration (as a 
JSON string) #Java, Python, Go")
         protected String inputSpecs;
         // for backwards compatibility purposes
         @Parameter(names = "--outputSerdeClassName",
                 description = "The SerDe class to be used for messages output 
by the function", hidden = true)
         protected String deprecatedOutputSerdeClassName;
         @Parameter(names = "--output-serde-classname",
-                description = "The SerDe class to be used for messages output 
by the function")
+                description = "The SerDe class to be used for messages output 
by the function #Java, Python")
         protected String outputSerdeClassName;
         // for backwards compatibility purposes
         @Parameter(names = "--functionConfigFile", description = "The path to 
a YAML config file that specifies "
                 + "the configuration of a Pulsar Function", hidden = true)
         protected String deprecatedFnConfigFile;
         @Parameter(names = "--function-config-file",
-                description = "The path to a YAML config file that specifies 
the configuration of a Pulsar Function")
+                description = "The path to a YAML config file that specifies 
the configuration of a Pulsar Function"
+                        + " #Java, Python, Go")
         protected String fnConfigFile;
         // for backwards compatibility purposes
         @Parameter(names = "--processingGuarantees", description = "The 
processing guarantees (aka delivery semantics) "
                 + "applied to the function", hidden = true)
         protected FunctionConfig.ProcessingGuarantees 
deprecatedProcessingGuarantees;
         @Parameter(names = "--processing-guarantees",
-                description = "The processing guarantees (aka delivery 
semantics) applied to the function")
+                description = "The processing guarantees (aka delivery 
semantics) applied to the function"
+                        + " #Java, Python, Go")
         protected FunctionConfig.ProcessingGuarantees processingGuarantees;
         // for backwards compatibility purposes
         @Parameter(names = "--userConfig", description = "User-defined config 
key/values", hidden = true)
         protected String deprecatedUserConfigString;
-        @Parameter(names = "--user-config", description = "User-defined config 
key/values")
+        @Parameter(names = "--user-config", description = "User-defined config 
key/values #Java, Python, Go")
         protected String userConfigString;
         @Parameter(names = "--retainOrdering",
                 description = "Function consumes and processes messages in 
order", hidden = true)
         protected Boolean deprecatedRetainOrdering;
-        @Parameter(names = "--retain-ordering", description = "Function 
consumes and processes messages in order")
+        @Parameter(names = "--retain-ordering", description = "Function 
consumes and processes messages in order #Java")
         protected Boolean retainOrdering;
         @Parameter(names = "--retain-key-ordering",
-                description = "Function consumes and processes messages in key 
order")
+                description = "Function consumes and processes messages in key 
order #Java")
         protected Boolean retainKeyOrdering;
         @Parameter(names = "--batch-builder", description = "BatcherBuilder 
provides two types of "
                 + "batch construction methods, DEFAULT and KEY_BASED. The 
default value is: DEFAULT")
         protected String batchBuilder;
         @Parameter(names = "--forward-source-message-property", description = 
"Forwarding input message's properties "
-                + "to output topic when processing (use false to disable it)", 
arity = 1)
+                + "to output topic when processing (use false to disable it) 
#Java", arity = 1)
         protected Boolean forwardSourceMessageProperty = true;
         @Parameter(names = "--subs-name", description = "Pulsar source 
subscription name if user wants a specific "
-                + "subscription-name for input-topic consumer")
+                + "subscription-name for input-topic consumer #Java, Python, 
Go")
         protected String subsName;
         @Parameter(names = "--subs-position", description = "Pulsar source 
subscription position if user wants to "
-                + "consume messages from the specified location")
+                + "consume messages from the specified location #Java")
         protected SubscriptionInitialPosition subsPosition;
         @Parameter(names = "--parallelism", description = "The parallelism 
factor of a Pulsar Function "
-                + "(i.e. the number of function instances to run)")
+                + "(i.e. the number of function instances to run) #Java")
         protected Integer parallelism;
         @Parameter(names = "--cpu", description = "The cpu in cores that need 
to be allocated "
-                + "per function instance(applicable only to docker runtime)")
+                + "per function instance(applicable only to docker runtime) 
#Java(Process & K8s),Python(K8s),Go(K8s)")
         protected Double cpu;
         @Parameter(names = "--ram", description = "The ram in bytes that need 
to be allocated "
-                + "per function instance(applicable only to process/docker 
runtime)")
+                + "per function instance(applicable only to process/docker 
runtime)"
+                + " #Java(Process & K8s),Python(K8s),Go(K8s)")
         protected Long ram;
         @Parameter(names = "--disk", description = "The disk in bytes that 
need to be allocated "
-                + "per function instance(applicable only to docker runtime)")
+                + "per function instance(applicable only to docker runtime) 
#Java(Process & K8s),Python(K8s),Go(K8s)")
         protected Long disk;
         // for backwards compatibility purposes
         @Parameter(names = "--windowLengthCount", description = "The number of 
messages per window", hidden = true)
         protected Integer deprecatedWindowLengthCount;
-        @Parameter(names = "--window-length-count", description = "The number 
of messages per window")
+        @Parameter(names = "--window-length-count", description = "The number 
of messages per window #Java")
         protected Integer windowLengthCount;
         // for backwards compatibility purposes
         @Parameter(names = "--windowLengthDurationMs",
                 description = "The time duration of the window in 
milliseconds", hidden = true)
         protected Long deprecatedWindowLengthDurationMs;
         @Parameter(names = "--window-length-duration-ms",
-                description = "The time duration of the window in 
milliseconds")
+                description = "The time duration of the window in milliseconds 
#Java")
         protected Long windowLengthDurationMs;
         // for backwards compatibility purposes
         @Parameter(names = "--slidingIntervalCount",
                 description = "The number of messages after which the window 
slides", hidden = true)
         protected Integer deprecatedSlidingIntervalCount;
         @Parameter(names = "--sliding-interval-count",
-                description = "The number of messages after which the window 
slides")
+                description = "The number of messages after which the window 
slides #Java")
         protected Integer slidingIntervalCount;
         // for backwards compatibility purposes
         @Parameter(names = "--slidingIntervalDurationMs",
                 description = "The time duration after which the window 
slides", hidden = true)
         protected Long deprecatedSlidingIntervalDurationMs;
         @Parameter(names = "--sliding-interval-duration-ms",
-                description = "The time duration after which the window 
slides")
+                description = "The time duration after which the window slides 
#Java")
         protected Long slidingIntervalDurationMs;
         // for backwards compatibility purposes
         @Parameter(names = "--autoAck",
                 description = "Whether or not the framework acknowledges 
messages automatically", hidden = true)
         protected Boolean deprecatedAutoAck = null;
         @Parameter(names = "--auto-ack",
-                description = "Whether or not the framework acknowledges 
messages automatically", arity = 1)
+                description = "Whether or not the framework acknowledges 
messages automatically"
+                        + " #Java, Python, Go", arity = 1)
         protected Boolean autoAck;
         // for backwards compatibility purposes
         @Parameter(names = "--timeoutMs", description = "The message timeout 
in milliseconds", hidden = true)
         protected Long deprecatedTimeoutMs;
-        @Parameter(names = "--timeout-ms", description = "The message timeout 
in milliseconds")
+        @Parameter(names = "--timeout-ms", description = "The message timeout 
in milliseconds #Java, Python")
         protected Long timeoutMs;
         @Parameter(names = "--max-message-retries",
-                description = "How many times should we try to process a 
message before giving up")
+                description = "How many times should we try to process a 
message before giving up #Java")
         protected Integer maxMessageRetries;
         @Parameter(names = "--custom-runtime-options", description = "A string 
that encodes options to "
-                + "customize the runtime, see docs for configured runtime for 
details")
+                + "customize the runtime, see docs for configured runtime for 
details #Java")
         protected String customRuntimeOptions;
         @Parameter(names = "--secrets", description = "The map of secretName 
to an object that encapsulates "
-                + "how the secret is fetched by the underlying secrets 
provider")
+                + "how the secret is fetched by the underlying secrets 
provider #Java, Python")
         protected String secretsString;
         @Parameter(names = "--dead-letter-topic",
-                description = "The topic where messages that are not processed 
successfully are sent to")
+                description = "The topic where messages that are not processed 
successfully are sent to #Java")
         protected String deadLetterTopic;
         protected FunctionConfig functionConfig;
         protected String userCodeFile;
@@ -711,61 +721,65 @@ public class CmdFunctions extends CmdBase {
                 + "(the default is Apache BookKeeper)", hidden = true)
         protected String deprecatedStateStorageServiceUrl;
         @Parameter(names = "--state-storage-service-url", description = "The 
URL for the state storage service "
-                + "(the default is Apache BookKeeper)")
+                + "(the default is Apache BookKeeper) #Java, Python")
         protected String stateStorageServiceUrl;
         // for backwards compatibility purposes
         @Parameter(names = "--brokerServiceUrl", description = "The URL for 
Pulsar broker", hidden = true)
         protected String deprecatedBrokerServiceUrl;
-        @Parameter(names = "--broker-service-url", description = "The URL for 
Pulsar broker")
+        @Parameter(names = "--broker-service-url", description = "The URL for 
Pulsar broker #Java, Python, Go")
         protected String brokerServiceUrl;
-        @Parameter(names = "--web-service-url", description = "The URL for 
Pulsar web service")
+        @Parameter(names = "--web-service-url", description = "The URL for 
Pulsar web service #Java, Python")
         protected String webServiceUrl = null;
         // for backwards compatibility purposes
         @Parameter(names = "--clientAuthPlugin", description = "Client 
authentication plugin using "
                 + "which function-process can connect to broker", hidden = 
true)
         protected String deprecatedClientAuthPlugin;
         @Parameter(names = "--client-auth-plugin",
-                description = "Client authentication plugin using which 
function-process can connect to broker")
+                description = "Client authentication plugin using which 
function-process can connect to broker"
+                        + " #Java, Python")
         protected String clientAuthPlugin;
         // for backwards compatibility purposes
         @Parameter(names = "--clientAuthParams", description = "Client 
authentication param", hidden = true)
         protected String deprecatedClientAuthParams;
-        @Parameter(names = "--client-auth-params", description = "Client 
authentication param")
+        @Parameter(names = "--client-auth-params", description = "Client 
authentication param #Java, Python")
         protected String clientAuthParams;
         // for backwards compatibility purposes
         @Parameter(names = "--use_tls", description = "Use tls connection", 
hidden = true)
         protected Boolean deprecatedUseTls = null;
-        @Parameter(names = "--use-tls", description = "Use tls connection")
+        @Parameter(names = "--use-tls", description = "Use tls connection 
#Java, Python")
         protected boolean useTls;
         // for backwards compatibility purposes
         @Parameter(names = "--tls_allow_insecure", description = "Allow 
insecure tls connection", hidden = true)
         protected Boolean deprecatedTlsAllowInsecureConnection = null;
-        @Parameter(names = "--tls-allow-insecure", description = "Allow 
insecure tls connection")
+        @Parameter(names = "--tls-allow-insecure", description = "Allow 
insecure tls connection #Java, Python")
         protected boolean tlsAllowInsecureConnection;
         // for backwards compatibility purposes
         @Parameter(names = "--hostname_verification_enabled",
                 description = "Enable hostname verification", hidden = true)
         protected Boolean deprecatedTlsHostNameVerificationEnabled = null;
-        @Parameter(names = "--hostname-verification-enabled", description = 
"Enable hostname verification")
+        @Parameter(names = "--hostname-verification-enabled", description = 
"Enable hostname verification"
+                + " #Java, Python")
         protected boolean tlsHostNameVerificationEnabled;
         // for backwards compatibility purposes
         @Parameter(names = "--tls_trust_cert_path", description = "tls trust 
cert file path", hidden = true)
         protected String deprecatedTlsTrustCertFilePath;
-        @Parameter(names = "--tls-trust-cert-path", description = "tls trust 
cert file path")
+        @Parameter(names = "--tls-trust-cert-path", description = "tls trust 
cert file path #Java, Python")
         protected String tlsTrustCertFilePath;
         // for backwards compatibility purposes
         @Parameter(names = "--instanceIdOffset", description = "Start the 
instanceIds from this offset", hidden = true)
         protected Integer deprecatedInstanceIdOffset = null;
-        @Parameter(names = "--instance-id-offset", description = "Start the 
instanceIds from this offset")
+        @Parameter(names = "--instance-id-offset", description = "Start the 
instanceIds from this offset #Java, Python")
         protected Integer instanceIdOffset = 0;
-        @Parameter(names = "--runtime", description = "either THREAD or 
PROCESS. Only applies for Java functions")
+        @Parameter(names = "--runtime", description = "either THREAD or 
PROCESS. Only applies for Java functions #Java")
         protected String runtime;
-        @Parameter(names = "--secrets-provider-classname", description = 
"Whats the classname for secrets provider")
+        @Parameter(names = "--secrets-provider-classname", description = 
"Whats the classname for secrets provider"
+                + " #Java, Python")
         protected String secretsProviderClassName;
         @Parameter(names = "--secrets-provider-config",
-                description = "Config that needs to be passed to secrets 
provider")
+                description = "Config that needs to be passed to secrets 
provider #Java, Python")
         protected String secretsProviderConfig;
-        @Parameter(names = "--metrics-port-start", description = "The starting 
port range for metrics server")
+        @Parameter(names = "--metrics-port-start", description = "The starting 
port range for metrics server"
+                + " #Java, Python, Go")
         protected String metricsPortStart;
 
         private void mergeArgs() {
@@ -969,7 +983,7 @@ public class CmdFunctions extends CmdBase {
     @Parameters(commandDescription = "Update a Pulsar Function that has been 
deployed to a Pulsar cluster")
     class UpdateFunction extends FunctionDetailsCommand {
 
-        @Parameter(names = "--update-auth-data", description = "Whether or not 
to update the auth data")
+        @Parameter(names = "--update-auth-data", description = "Whether or not 
to update the auth data #Java, Python")
         protected boolean updateAuthData;
 
         @Override
diff --git 
a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdGenerateDocument.java
 
b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdGenerateDocument.java
index d879f771d4f..70878f8ef53 100644
--- 
a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdGenerateDocument.java
+++ 
b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdGenerateDocument.java
@@ -24,6 +24,7 @@ import com.beust.jcommander.JCommander;
 import com.beust.jcommander.Parameter;
 import com.beust.jcommander.ParameterDescription;
 import com.beust.jcommander.Parameters;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -93,6 +94,11 @@ public class CmdGenerateDocument extends CmdBase {
             }
         }
 
+        private boolean needsLangSupport(String module, String subK) {
+            String[] langSupport = {"localrun", "create", "update"};
+            return module.equals("functions") && 
Arrays.asList(langSupport).contains(subK);
+        }
+
         private void generateDocument(StringBuilder sb, String module, 
JCommander obj) {
             sb.append("------------\n\n");
             sb.append("# ").append(module).append("\n\n");
@@ -112,22 +118,37 @@ public class CmdGenerateDocument extends CmdBase {
                 sb.append("\n\n## <em>").append(subK).append("</em>\n\n");
                 
sb.append(cmdObj.getUsageFormatter().getCommandDescription(subK)).append("\n\n");
                 sb.append("### Usage\n\n");
-                sb.append("------------\n\n\n");
+                sb.append("------------\n\n");
+                sb.append("**Command:**\n\n");
                 sb.append("```bdocs-tab:example_shell\n$ pulsar-admin 
").append(module).append(" ")
                         .append(subK).append(" options").append("\n```\n\n");
                 List<ParameterDescription> options = 
cmdObj.jcommander.getCommands().get(subK).getParameters();
                 if (options.size() > 0) {
-                    sb.append("Options\n\n\n");
-                    sb.append("|Flag|Description|Default|\n");
-                    sb.append("|---|---|---|\n");
+                    sb.append("**Options:**\n\n");
+                    sb.append("|Flag|Description|Default|");
+                    if (needsLangSupport(module, subK)) {
+                        sb.append("Support|\n");
+                        sb.append("|---|---|---|---|\n");
+                    } else {
+                        sb.append("\n|---|---|---|\n");
+                    }
                 }
-                options.stream().filter(ele -> 
!ele.getParameterAnnotation().hidden()).forEach((option) ->
-                        sb.append("| `").append(option.getNames())
-                                .append("` | 
").append(option.getDescription().replace("\n", " "))
-                                
.append("|").append(option.getDefault()).append("|\n")
+                options.stream().filter(
+                        ele -> ele.getParameterAnnotation() == null
+                                || !ele.getParameterAnnotation().hidden()
+                ).forEach((option) -> {
+                            String[] descriptions = 
option.getDescription().replace("\n", " ").split(" #");
+                            sb.append("| `").append(option.getNames())
+                                    .append("` | ").append(descriptions[0])
+                                    
.append("|").append(option.getDefault()).append("|");
+                            if (needsLangSupport(module, subK) && 
descriptions.length > 1) {
+                                sb.append(descriptions[1]);
+                            }
+                            sb.append("|\n");
+                        }
                 );
             });
-            System.out.println(sb.toString());
+            System.out.println(sb);
         }
     }
 }

Reply via email to