Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.edwmigration.dumper.application.dumper.ZonedParser.DayOffset;
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsInput;
import com.google.edwmigration.dumper.application.dumper.connector.Connector;
import com.google.edwmigration.dumper.application.dumper.connector.ConnectorProperty;
import com.google.edwmigration.dumper.application.dumper.connector.ConnectorPropertyWithDefault;
Expand All @@ -43,17 +41,11 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
Expand All @@ -63,7 +55,6 @@
import joptsimple.OptionSpec;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;

/** @author shevek */
public class ConnectorArguments extends DefaultArguments {
Expand Down Expand Up @@ -311,7 +302,6 @@ public class ConnectorArguments extends DefaultArguments {
private final OptionSpec<Void> optionOutputContinue =
parser.accepts("continue", "Continues writing a previous output file.");

// TODO: Make this be an ISO instant.
@Deprecated
private final OptionSpec<String> optionQueryLogEarliestTimestamp =
parser
Expand Down Expand Up @@ -606,123 +596,31 @@ public ConnectorArguments(@Nonnull String... args) throws IOException {
super(args);
}

private static class InputDescriptor implements Comparable<InputDescriptor> {

public enum Category {
Arg,
Env,
Other
}

private final RespectsInput annotation;

public InputDescriptor(RespectsInput annotation) {
this.annotation = annotation;
}

@Nonnull
public Category getCategory() {
if (!Strings.isNullOrEmpty(annotation.arg())) {
return Category.Arg;
}
if (!Strings.isNullOrEmpty(annotation.env())) {
return Category.Env;
}
return Category.Other;
}

@Nonnull
public String getKey() {
switch (getCategory()) {
case Arg:
return "--" + annotation.arg();
case Env:
return annotation.env();
default:
return String.valueOf(annotation.hashCode());
}
}

@Override
public int compareTo(InputDescriptor o) {
return ComparisonChain.start()
.compare(getCategory(), o.getCategory())
.compare(annotation.order(), o.annotation.order())
.result();
}

@Override
public String toString() {
StringBuilder buf = new StringBuilder();
String key = getKey();
buf.append(key).append(StringUtils.repeat(' ', 12 - key.length()));
if (getCategory() == Category.Env) {
buf.append(" (environment variable)");
}
String defaultValue = annotation.defaultValue();
if (!Strings.isNullOrEmpty(defaultValue)) {
buf.append(" (default: ").append(defaultValue).append(")");
}
buf.append(" ").append(annotation.description());
String required = annotation.required();
if (!Strings.isNullOrEmpty(required)) {
buf.append(" (Required ").append(required).append(".)");
}
return buf.toString();
}
}

@Nonnull
private static Collection<InputDescriptor> getAcceptsInputs(@Nonnull Connector connector) {
Map<String, InputDescriptor> tmp = new HashMap<>();
Class<?> connectorType = connector.getClass();
while (connectorType != null) {
Set<RespectsInput> respectsInputs =
AnnotationUtils.getDeclaredRepeatableAnnotations(connectorType, RespectsInput.class);
for (RespectsInput respectsInput : respectsInputs) {
InputDescriptor descriptor = new InputDescriptor(respectsInput);
tmp.putIfAbsent(descriptor.getKey(), descriptor);
}
connectorType = connectorType.getSuperclass();
}

List<InputDescriptor> out = new ArrayList<>(tmp.values());
Collections.sort(out);
return out;
}

@Override
protected void printHelpOn(PrintStream out, OptionSet o) throws IOException {
protected void printHelpOn(@Nonnull PrintStream out, OptionSet o) throws IOException {
out.append(HELP_INFO);
super.printHelpOn(out, o);

ConnectorRepository repository = ConnectorRepository.getInstance();
// if --connector <valid-connection> provided, print only that
if (o.has(connectorNameOption)) {
String helpOnConnector = o.valueOf(connectorNameOption);
Connector connector = ConnectorRepository.getInstance().getByName(helpOnConnector);
Connector connector = repository.getByName(helpOnConnector);
if (connector != null) {
out.append("\nSelected connector:\n");
printConnectorHelp(out, connector);
return;
}
}
out.append("\nAvailable connectors:\n");
for (Connector connector : ConnectorRepository.getInstance().getAllConnectors()) {
for (Connector connector : repository.getAllConnectors()) {
printConnectorHelp(out, connector);
}
}

private void printConnectorHelp(@Nonnull Appendable out, @Nonnull Connector connector)
private static void printConnectorHelp(@Nonnull Appendable out, @Nonnull Connector connector)
throws IOException {
out.append("* " + connector.getName());
String description = connector.getDescription();
if (!description.isEmpty()) {
out.append(" - " + description);
}
out.append("\n");
for (InputDescriptor descriptor : getAcceptsInputs(connector)) {
out.append(String.format("%8s%s\n", "", descriptor));
}
connector.printHelp(out);
ConnectorProperties.printHelp(out, connector);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright 2022-2025 Google LLC
* Copyright 2013-2021 CompilerWorks
*
* 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.
*/
package com.google.edwmigration.dumper.application.dumper;

import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.joining;

import com.google.edwmigration.dumper.application.dumper.annotations.RespectsInput;
import java.util.ArrayList;
import java.util.Comparator;
import javax.annotation.Nonnull;

public final class InputDescriptor {
private enum Category {
ARGUMENT(1) {
@Override
String getKey(@Nonnull RespectsInput annotation) {
return "--" + annotation.arg();
}
},
ENVIRONMENT(2) {
@Override
String getKey(@Nonnull RespectsInput annotation) {
return annotation.env();
}
},
OTHER(3) {
@Override
String getKey(@Nonnull RespectsInput annotation) {
return String.valueOf(annotation.hashCode());
}
};

final int order;

abstract String getKey(@Nonnull RespectsInput annotation);

Category(int order) {
this.order = order;
}
}

private final RespectsInput annotation;

public InputDescriptor(RespectsInput annotation) {
this.annotation = annotation;
}

@Nonnull
private Category getCategory() {
if (!isNullOrEmpty(annotation.arg())) {
return Category.ARGUMENT;
}
if (!isNullOrEmpty(annotation.env())) {
return Category.ENVIRONMENT;
}
return Category.OTHER;
}

public static Comparator<InputDescriptor> comparator() {
return comparing(InputDescriptor::categoryOrder)
.thenComparing(InputDescriptor::annotationOrder);
}

@Override
public String toString() {
ArrayList<String> buf = new ArrayList<>();
buf.add(String.format("%-12s", getKey()));
if (getCategory() == Category.ENVIRONMENT) {
buf.add("(environment variable)");
}
buf.add(defaultHint(annotation.defaultValue()));
buf.add(annotation.description());
buf.add(requiredHint(annotation.required()));

return buf.stream().filter(el -> !el.isEmpty()).collect(joining(" "));
}

public String getKey() {
return getCategory().getKey(annotation);
}

private String defaultHint(String value) {
if (isNullOrEmpty(value)) {
return "";
} else {
return String.format("(default: %s)", value);
}
}

private String requiredHint(String value) {
if (isNullOrEmpty(value)) {
return "";
} else {
return String.format("(Required %s.)", value);
}
}

private int annotationOrder() {
return annotation.order();
}

private int categoryOrder() {
return getCategory().order;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,23 @@

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.springframework.core.annotation.AnnotationUtils.getDeclaredRepeatableAnnotations;

import autovalue.shaded.com.google.common.collect.ImmutableList;
import com.google.edwmigration.dumper.application.dumper.ConnectorArguments;
import com.google.edwmigration.dumper.application.dumper.InputDescriptor;
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsInput;
import com.google.edwmigration.dumper.application.dumper.handle.Handle;
import com.google.edwmigration.dumper.application.dumper.task.Task;
import java.io.IOException;
import java.time.Clock;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;

/** @author shevek */
Expand Down Expand Up @@ -77,4 +87,39 @@ void addTasksTo(@Nonnull List<? super Task<?>> out, @Nonnull ConnectorArguments

@Nonnull
Iterable<ConnectorProperty> getPropertyConstants();

default void printHelp(@Nonnull Appendable out) throws IOException {
out.append("* " + getName());
String description = getDescription();
if (!description.isEmpty()) {
out.append(" - " + description);
}
out.append("\n");
for (InputDescriptor descriptor : getAcceptsInputs(this)) {
out.append(String.format("%8s%s\n", "", descriptor));
}
}

@Nonnull
static Collection<InputDescriptor> getAcceptsInputs(@Nonnull Connector connector) {

ArrayList<Class<?>> classes = new ArrayList<>();
for (Class<?> type = connector.getClass(); type != null; type = type.getSuperclass()) {
classes.add(type);
}

Map<String, InputDescriptor> map = new HashMap<>();
for (Class<?> type : classes) {
Set<RespectsInput> respectsInputs =
getDeclaredRepeatableAnnotations(type, RespectsInput.class);
for (RespectsInput item : respectsInputs) {
InputDescriptor descriptor = new InputDescriptor(item);
map.putIfAbsent(descriptor.getKey(), descriptor);
}
}

return map.values().stream()
.sorted(InputDescriptor.comparator())
.collect(ImmutableList.toImmutableList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsInput;
import com.google.edwmigration.dumper.application.dumper.annotations.RespectsInputs;
import com.google.edwmigration.dumper.application.dumper.connector.AbstractJdbcConnector;
import com.google.edwmigration.dumper.application.dumper.connector.Connector;
import com.google.edwmigration.dumper.application.dumper.handle.Handle;
import com.google.edwmigration.dumper.application.dumper.handle.JdbcHandle;
import com.google.edwmigration.dumper.application.dumper.task.AbstractJdbcTask;
Expand Down Expand Up @@ -252,4 +253,10 @@ String sanitizeDatabaseName(@Nonnull String databaseName) throws MetadataDumperU
}
return trimmedName;
}

static String describeAsDelegate(Connector connector, String baseName) {
String summary = String.format("* %s - %s\n", connector.getName(), connector.getDescription());
String details = String.format("%8s[same options as '%s']\n", "", baseName);
return summary + details;
}
}
Loading
Loading