feat: Command Line Interface
This commit is contained in:
@@ -34,14 +34,19 @@ dependencies {
|
|||||||
implementation("org.apache.httpcomponents.client5:httpclient5:5.5")
|
implementation("org.apache.httpcomponents.client5:httpclient5:5.5")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
||||||
implementation("org.jsoup:jsoup:1.21.1")
|
implementation("org.jsoup:jsoup:1.21.1")
|
||||||
|
implementation("org.slf4j:slf4j-simple:$slf4jVersion")
|
||||||
|
implementation("info.picocli:picocli:4.7.7")
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:$junitVersion"))
|
testImplementation(platform("org.junit:junit-bom:$junitVersion"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
//noinspection VulnerableLibrariesLocal
|
//noinspection VulnerableLibrariesLocal
|
||||||
testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.1")
|
testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.1")
|
||||||
testImplementation("org.slf4j:slf4j-simple:$slf4jVersion")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass = "ru.di9.ihc.cli.CliApp"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.di9.ihc;
|
package ru.di9.ihc;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||||
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
|
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
|
||||||
@@ -27,6 +28,10 @@ public class IhcClient {
|
|||||||
|
|
||||||
private boolean isAuth = false;
|
private boolean isAuth = false;
|
||||||
|
|
||||||
|
public IhcClient() {
|
||||||
|
this("https://my.ihc.ru");
|
||||||
|
}
|
||||||
|
|
||||||
public IhcClient(String baseUrl) {
|
public IhcClient(String baseUrl) {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
this.httpClient = HttpClientBuilder.create().build();
|
this.httpClient = HttpClientBuilder.create().build();
|
||||||
|
|||||||
56
src/main/java/ru/di9/ihc/cli/AddDomainRecordCommand.java
Normal file
56
src/main/java/ru/di9/ihc/cli/AddDomainRecordCommand.java
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import ru.di9.ihc.Domain;
|
||||||
|
import ru.di9.ihc.IhcClient;
|
||||||
|
import ru.di9.ihc.RecordType;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "add",
|
||||||
|
description = "Добавить запись домена")
|
||||||
|
public class AddDomainRecordCommand implements Callable<Integer> {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-u", "--username"}, description = "Имя пользователя", required = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-p", "--password"}, description = "Пароль пользователя", required = true, arity = "0..1", interactive = true)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@CommandLine.Parameters(index = "0", description = "Имя домена")
|
||||||
|
private String domainName;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--name"}, description = "Имя записи")
|
||||||
|
private String recordName;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--type"}, description = "Тип записи", converter = CliRecordTypeConverter.class, required = true)
|
||||||
|
private RecordType recordType;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--content"}, description = "Контент", required = true)
|
||||||
|
private String recordContent;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--priority"}, description = "Приоритет")
|
||||||
|
private Integer recordPriority;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() throws Exception {
|
||||||
|
IhcClient ihc = new IhcClient();
|
||||||
|
if (!ihc.auth(username, password)) {
|
||||||
|
System.err.println("Неверное имя пользователя или пароль");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Domain domain = ihc.getDomains().stream().filter(d -> d.name().equalsIgnoreCase(domainName)).findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("DOMAIN '%s' NOT EXISTS".formatted(domainName)));
|
||||||
|
|
||||||
|
ihc.addDomainRecord(domain, recordName, recordType, recordContent, recordPriority);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/main/java/ru/di9/ihc/cli/CliApp.java
Normal file
39
src/main/java/ru/di9/ihc/cli/CliApp.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "app",
|
||||||
|
description = "IHC DNS Tools",
|
||||||
|
subcommands = {
|
||||||
|
DomainsListCommand.class,
|
||||||
|
DomainRecordCommand.class
|
||||||
|
},
|
||||||
|
version = "1.0-SNAPSHOT")
|
||||||
|
public class CliApp {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-v", "--version"}, description = "Версия программы", versionHelp = true)
|
||||||
|
private boolean flagVersion;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CliApp cliApp = new CliApp();
|
||||||
|
CommandLine commandLine = new CommandLine(cliApp);
|
||||||
|
commandLine.parseArgs(args);
|
||||||
|
|
||||||
|
if (cliApp.flagHelp) {
|
||||||
|
CommandLine.usage(cliApp, System.out);
|
||||||
|
return;
|
||||||
|
} else if (cliApp.flagVersion) {
|
||||||
|
commandLine.printVersionHelp(System.out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.exit(commandLine.execute(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/ru/di9/ihc/cli/CliRecordTypeConverter.java
Normal file
11
src/main/java/ru/di9/ihc/cli/CliRecordTypeConverter.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import ru.di9.ihc.RecordType;
|
||||||
|
|
||||||
|
public class CliRecordTypeConverter implements CommandLine.ITypeConverter<RecordType> {
|
||||||
|
@Override
|
||||||
|
public RecordType convert(String s) {
|
||||||
|
return RecordType.valueOf(s.toUpperCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/main/java/ru/di9/ihc/cli/DeleteDomainRecordCommand.java
Normal file
50
src/main/java/ru/di9/ihc/cli/DeleteDomainRecordCommand.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import ru.di9.ihc.Domain;
|
||||||
|
import ru.di9.ihc.DomainRecord;
|
||||||
|
import ru.di9.ihc.IhcClient;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "delete",
|
||||||
|
description = "Удалить запись домена")
|
||||||
|
public class DeleteDomainRecordCommand implements Callable<Integer> {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-u", "--username"}, description = "Имя пользователя", required = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-p", "--password"}, description = "Пароль пользователя", required = true, arity = "0..1", interactive = true)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@CommandLine.Parameters(index = "0", description = "Имя домена")
|
||||||
|
private String domainName;
|
||||||
|
|
||||||
|
@CommandLine.Parameters(index = "1", description = "Имя записи")
|
||||||
|
private String recordName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() throws Exception {
|
||||||
|
IhcClient ihc = new IhcClient();
|
||||||
|
if (!ihc.auth(username, password)) {
|
||||||
|
System.err.println("Неверное имя пользователя или пароль");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Domain domain = ihc.getDomains().stream().filter(d -> d.name().equalsIgnoreCase(domainName)).findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("DOMAIN '%s' NOT EXISTS".formatted(domainName)));
|
||||||
|
|
||||||
|
DomainRecord record = ihc.getDomainRecords(domain).stream().filter(r -> r.getName().equals(recordName)).findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("RECORD '%s' FOR DOMAIN '%s' NOT EXISTS".formatted(recordName, domainName)));
|
||||||
|
|
||||||
|
ihc.removeDomainRecord(domain, record.getId());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main/java/ru/di9/ihc/cli/DomainRecordCommand.java
Normal file
21
src/main/java/ru/di9/ihc/cli/DomainRecordCommand.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "domain-record",
|
||||||
|
description = "Работа с записями домена",
|
||||||
|
subcommands = {
|
||||||
|
DomainRecordsListCommand.class,
|
||||||
|
AddDomainRecordCommand.class,
|
||||||
|
EditDomainRecordCommand.class,
|
||||||
|
DeleteDomainRecordCommand.class
|
||||||
|
})
|
||||||
|
public class DomainRecordCommand {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
}
|
||||||
62
src/main/java/ru/di9/ihc/cli/DomainRecordsListCommand.java
Normal file
62
src/main/java/ru/di9/ihc/cli/DomainRecordsListCommand.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import ru.di9.ihc.Domain;
|
||||||
|
import ru.di9.ihc.DomainRecord;
|
||||||
|
import ru.di9.ihc.IhcClient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "list",
|
||||||
|
description = "Список записей доменов")
|
||||||
|
public class DomainRecordsListCommand implements Callable<Integer> {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-u", "--username"}, description = "Имя пользователя", required = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-p", "--password"}, description = "Пароль пользователя", required = true, arity = "0..1", interactive = true)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@CommandLine.Parameters(index = "0", description = "Имя домена")
|
||||||
|
private String domainName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() throws Exception {
|
||||||
|
IhcClient ihc = new IhcClient();
|
||||||
|
if (!ihc.auth(username, password)) {
|
||||||
|
System.err.println("Неверное имя пользователя или пароль");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Domain domain = ihc.getDomains().stream().filter(d -> d.name().equalsIgnoreCase(domainName)).findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("DOMAIN '%s' NOT EXISTS".formatted(domainName)));
|
||||||
|
List<DomainRecord> domainRecords = ihc.getDomainRecords(domain);
|
||||||
|
|
||||||
|
var colId = new TableCol("ID");
|
||||||
|
var colName = new TableCol("Запись");
|
||||||
|
var colType = new TableCol("Тип");
|
||||||
|
var colPriority = new TableCol("Приоритет");
|
||||||
|
var colContent = new TableCol("Контент");
|
||||||
|
var colReadOnly = new TableCol("Только для чтения");
|
||||||
|
|
||||||
|
for (DomainRecord record : domainRecords) {
|
||||||
|
colId.putRow(record.getId());
|
||||||
|
colName.putRow(record.getName());
|
||||||
|
colType.putRow(record.getType().name());
|
||||||
|
colPriority.putRow(record.getPriority());
|
||||||
|
colContent.putRow(record.getContent());
|
||||||
|
colReadOnly.putRow(record.isReadOnly() ? "да" : "нет");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(new Table(colId, colName, colType, colPriority, colContent, colReadOnly).print());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/main/java/ru/di9/ihc/cli/DomainsListCommand.java
Normal file
50
src/main/java/ru/di9/ihc/cli/DomainsListCommand.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import ru.di9.ihc.Domain;
|
||||||
|
import ru.di9.ihc.IhcClient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "domains",
|
||||||
|
description = "Список доменов")
|
||||||
|
public class DomainsListCommand implements Callable<Integer> {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-u", "--username"}, description = "Имя пользователя", required = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-p", "--password"}, description = "Пароль пользователя", required = true, arity = "0..1", interactive = true)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() {
|
||||||
|
IhcClient ihc = new IhcClient();
|
||||||
|
if (!ihc.auth(username, password)) {
|
||||||
|
System.err.println("Неверное имя пользователя или пароль");
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
List<Domain> domains = ihc.getDomains();
|
||||||
|
|
||||||
|
var colId = new TableCol("ID");
|
||||||
|
var colDomain = new TableCol("Домен");
|
||||||
|
var colPunycode = new TableCol("Punycode");
|
||||||
|
|
||||||
|
for (Domain domain : domains) {
|
||||||
|
colId.putRow(domain.id());
|
||||||
|
colDomain.putRow(domain.name());
|
||||||
|
colPunycode.putRow(domain.punycode());
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(new Table(colId, colDomain, colPunycode).print());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/main/java/ru/di9/ihc/cli/EditDomainRecordCommand.java
Normal file
64
src/main/java/ru/di9/ihc/cli/EditDomainRecordCommand.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import ru.di9.ihc.Domain;
|
||||||
|
import ru.di9.ihc.DomainRecord;
|
||||||
|
import ru.di9.ihc.IhcClient;
|
||||||
|
import ru.di9.ihc.RecordType;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@CommandLine.Command(
|
||||||
|
name = "edit",
|
||||||
|
description = "Изменить запись домена")
|
||||||
|
public class EditDomainRecordCommand implements Callable<Integer> {
|
||||||
|
@CommandLine.Option(names = {"-h", "--help"}, description = "Страница помощи", usageHelp = true)
|
||||||
|
private boolean flagHelp;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-u", "--username"}, description = "Имя пользователя", required = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"-p", "--password"}, description = "Пароль пользователя", required = true, arity = "0..1", interactive = true)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@CommandLine.Parameters(index = "0", description = "Имя домена")
|
||||||
|
private String domainName;
|
||||||
|
|
||||||
|
@CommandLine.Parameters(index = "1", description = "Имя записи")
|
||||||
|
private String recordName;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--name"}, description = "Новое имя записи")
|
||||||
|
private String recordNewName;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--content"}, description = "Контент")
|
||||||
|
private String recordContent;
|
||||||
|
|
||||||
|
@CommandLine.Option(names = {"--priority"}, description = "Приоритет")
|
||||||
|
private Integer recordPriority;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() throws Exception {
|
||||||
|
IhcClient ihc = new IhcClient();
|
||||||
|
if (!ihc.auth(username, password)) {
|
||||||
|
System.err.println("Неверное имя пользователя или пароль");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Domain domain = ihc.getDomains().stream().filter(d -> d.name().equalsIgnoreCase(domainName)).findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("DOMAIN '%s' NOT EXISTS".formatted(domainName)));
|
||||||
|
|
||||||
|
DomainRecord record = ihc.getDomainRecords(domain).stream().filter(r -> r.getName().equals(recordName)).findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("RECORD '%s' FOR DOMAIN '%s' NOT EXISTS".formatted(recordName, domainName)));
|
||||||
|
|
||||||
|
if (recordNewName != null) record.setName(recordNewName);
|
||||||
|
if (recordContent != null) record.setContent(recordContent);
|
||||||
|
if (recordPriority != null) record.setPriority(recordPriority);
|
||||||
|
|
||||||
|
ihc.updateDomainRecord(domain, record);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/main/java/ru/di9/ihc/cli/Table.java
Normal file
63
src/main/java/ru/di9/ihc/cli/Table.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Table {
|
||||||
|
private final List<TableCol> cols = new ArrayList<>();
|
||||||
|
|
||||||
|
public Table(TableCol... cols) {
|
||||||
|
this.cols.addAll(Arrays.asList(cols));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String print() {
|
||||||
|
Object[] headers = new Object[cols.size()];
|
||||||
|
String formatRow;
|
||||||
|
String strLine;
|
||||||
|
int maxRows = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
StringBuilder sbFormatRow = new StringBuilder();
|
||||||
|
StringBuilder sbStrLine = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < cols.size(); i++) {
|
||||||
|
TableCol col = cols.get(i);
|
||||||
|
|
||||||
|
headers[i] = col.getHeader();
|
||||||
|
maxRows = Math.max(maxRows, col.getRows().size());
|
||||||
|
|
||||||
|
sbFormatRow.append(" %%-%ds ".formatted(col.getSize()));
|
||||||
|
sbStrLine.append("-".repeat(col.getSize() + 2));
|
||||||
|
|
||||||
|
if (i < cols.size() - 1) {
|
||||||
|
sbFormatRow.append('|');
|
||||||
|
sbStrLine.append('|');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
formatRow = sbFormatRow.toString();
|
||||||
|
strLine = sbStrLine.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
result.append(formatRow.formatted(headers)).append('\n')
|
||||||
|
.append(strLine).append('\n');
|
||||||
|
|
||||||
|
Object[] cells;
|
||||||
|
for (int i = 0; i < maxRows; i++) {
|
||||||
|
cells = new Object[headers.length];
|
||||||
|
for (int j = 0; j < cols.size(); j++) {
|
||||||
|
cells[j] = cols.get(j).getRows().get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(formatRow.formatted(cells));
|
||||||
|
|
||||||
|
if (i < maxRows - 1) {
|
||||||
|
result.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/java/ru/di9/ihc/cli/TableCol.java
Normal file
41
src/main/java/ru/di9/ihc/cli/TableCol.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package ru.di9.ihc.cli;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TableCol {
|
||||||
|
private final List<String> rows = new ArrayList<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final String header;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public TableCol(String header) {
|
||||||
|
this.header = header;
|
||||||
|
this.size = header.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putRow(Integer row) {
|
||||||
|
if (row == null) putRow((String) null);
|
||||||
|
else putRow(String.valueOf(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putRow(String row) {
|
||||||
|
if (row == null) {
|
||||||
|
rows.add("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.add(row);
|
||||||
|
size = Math.max(size, row.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRows() {
|
||||||
|
return Collections.unmodifiableList(rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/main/java/ru/di9/ihc/lombok.config
Normal file
1
src/main/java/ru/di9/ihc/lombok.config
Normal file
@@ -0,0 +1 @@
|
|||||||
|
lombok.log.flagUsage=error
|
||||||
Reference in New Issue
Block a user