HelpText.java
/*-
* ========================LICENSE_START=================================
* flyway-core
* ========================================================================
* Copyright (C) 2010 - 2026 Red Gate Software Ltd
* ========================================================================
* Licensed 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.
* =========================LICENSE_END==================================
*/
package org.flywaydb.core.internal.configuration;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
import org.flywaydb.core.extensibility.ConfigurationParameter;
import org.flywaydb.core.internal.util.Pair;
import org.flywaydb.core.internal.util.StringUtils;
@Getter
@Setter
public class HelpText {
private static final String INDENT = " ";
List<String> usage;
List<Pair<String, String>> commands;
List<? extends ConfigurationParameter> parameters;
List<? extends ConfigurationParameter> flags;
List<String> examples;
String description;
String documentationLink;
String additionalInfo;
public String getText() {
final StringBuilder result = new StringBuilder();
addUsageText(result);
addAdditionalInfoText(result);
addDescriptionText(result);
final int padSize = getPadSize();
addCommandsText(result, padSize);
addParametersText(result, padSize);
addFlagsText(result, padSize);
addExamplesText(result);
addDocumentationText(result);
return result.toString();
}
private void addUsageText(final StringBuilder result) {
if (usage != null) {
result.append("Usage:").append(System.lineSeparator());
usage.forEach(line -> result.append(INDENT).append(line).append(System.lineSeparator()));
result.append(System.lineSeparator());
}
}
private void addAdditionalInfoText(final StringBuilder result) {
if (additionalInfo != null) {
result.append(additionalInfo).append(System.lineSeparator()).append(System.lineSeparator());
}
}
private void addDocumentationText(final StringBuilder result) {
if (documentationLink != null) {
result.append("More info at ").append(documentationLink).append(System.lineSeparator());
}
}
private void addExamplesText(final StringBuilder result) {
if (examples != null && !examples.isEmpty()) {
result.append("Example:")
.append(System.lineSeparator())
.append(examples.stream().map(e -> INDENT + e).collect(Collectors.joining(System.lineSeparator())))
.append(System.lineSeparator())
.append(System.lineSeparator());
}
}
private void addDescriptionText(final StringBuilder result) {
if (description != null) {
result.append("Description:").append(System.lineSeparator());
Arrays.stream(description.split(System.lineSeparator()))
.map(String::trim)
.forEach(line -> result.append(INDENT).append(line).append(System.lineSeparator()));
result.append(System.lineSeparator());
}
}
private void addFlagsText(final StringBuilder result, final int padSize) {
if (flags != null) {
result.append("Flags:").append(System.lineSeparator());
for (final ConfigurationParameter p : flags) {
final String flagName = p.name + (p.required ? " [REQUIRED]" : "");
result.append(INDENT)
.append(StringUtils.rightPad(flagName, padSize, ' '))
.append(p.description)
.append(System.lineSeparator());
}
result.append(System.lineSeparator());
}
}
private void addCommandsText(final StringBuilder result, final int padSize) {
if (commands != null) {
result.append("Commands:").append(System.lineSeparator());
for (final Pair<String, String> command : commands) {
final List<String> lines = Arrays.stream(command.getRight().split(System.lineSeparator()))
.map(String::trim)
.toList();
result.append(INDENT)
.append(StringUtils.rightPad(command.getLeft(), padSize, ' '))
.append(lines.get(0))
.append(System.lineSeparator());
for (int i = 1; i < lines.size(); i++) {
result.append(INDENT)
.append(" ".repeat(padSize))
.append(lines.get(i))
.append(System.lineSeparator());
}
}
result.append(System.lineSeparator());
}
}
private void addParametersText(final StringBuilder result, final int padSize) {
if (parameters != null) {
result.append("Configuration parameters: (Format: -key=value)").append(System.lineSeparator());
for (final ConfigurationParameter p : parameters) {
final String parameterName = p.name.startsWith("flyway.")
? p.name.substring("flyway.".length())
: p.name;
final String fullParameter = parameterName + (p.required ? " [REQUIRED]" : "");
if (p.description == null) {
result.append(INDENT).append(fullParameter).append(System.lineSeparator());
continue;
}
result.append(INDENT).append(StringUtils.rightPad(fullParameter, padSize, ' '));
final String descriptionPadding = " ".repeat(INDENT.length() + padSize);
final List<String> descriptionLines = Arrays.stream(p.description.split(System.lineSeparator()))
.toList();
result.append(descriptionLines.get(0)).append(System.lineSeparator());
for (int i = 1; i < descriptionLines.size(); i++) {
result.append(descriptionPadding).append(descriptionLines.get(i)).append(System.lineSeparator());
}
}
result.append(System.lineSeparator());
}
}
private int getPadSize() {
int padSize = 0;
if (parameters != null) {
padSize = parameters.stream()
.filter(p -> p.description != null)
.map(p -> p.name + (p.required ? " [REQUIRED]" : ""))
.mapToInt(String::length)
.max()
.orElse(0) + 2;
}
if (flags != null) {
padSize = Math.max(padSize,
flags.stream()
.filter(p -> p.description != null)
.map(p -> p.name + (p.required ? " [REQUIRED]" : ""))
.mapToInt(String::length)
.max()
.orElse(0) + 2);
}
if (commands != null) {
padSize = Math.max(padSize,
commands.stream().map(Pair::getLeft).mapToInt(String::length).max().orElse(0) + 2);
}
return padSize;
}
}