UIOption.java
/*
* 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.rat.ui;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.cli.Option;
import org.apache.commons.lang3.StringUtils;
import org.apache.rat.OptionCollection;
import org.apache.rat.utils.CasedString;
import static java.lang.String.format;
/**
* Abstract class that provides the framework for UI-specific RAT options.
* In this context UI option means an option expressed in the specific UI.
* @param <T> the concrete implementation of AbstractOption.
*/
public abstract class UIOption<T extends UIOption<T>> {
/** The pattern to match CLI options in text */
protected static final Pattern PATTERN = Pattern.compile("-?-([A-Za-z0-9]+-?)+"); // NOSONAR
/** The actual UI-specific name for the option */
protected final Option option;
/** The name for the option */
protected final CasedString name;
/** The argument type for this option */
protected final OptionCollection.ArgumentType argumentType;
/** The AbstractOptionCollection associated with this AbstractOption */
protected final UIOptionCollection<T> optionCollection;
/**
* Constructor.
*
* @param option The CLI option
* @param name the UI-specific name for the option
*/
protected <C extends UIOptionCollection<T>> UIOption(final C optionCollection, final Option option, final CasedString name) {
this.optionCollection = optionCollection;
this.option = option;
this.name = name;
OptionCollection.ArgumentType argType;
if (option.hasArg()) {
if (option.getArgName() == null) {
argType = OptionCollection.ArgumentType.ARG;
} else {
// extract the name of the argument type.
try {
argType = OptionCollection.ArgumentType.valueOf(option.getArgName().toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
argType = OptionCollection.ArgumentType.ARG;
}
}
} else {
argType = OptionCollection.ArgumentType.NONE;
}
this.argumentType = argType;
}
/**
* Gets the AbstractOptionCollection that this option is a member of.
* @return the AbstractOptionCollection that this option is a member of.
*/
public final <X extends UIOptionCollection<T>> X getOptionCollection() {
return (X) optionCollection;
}
/**
* Gets the option this abstract option is wrapping.
* @return the original Option.
*/
public final Option getOption() {
return option;
}
/**
* Return default value.
* @return default value or {@code null} if no argument given.
*/
public final String getDefaultValue() {
return optionCollection.defaultValue(option);
}
/**
* Provide means to wrap the given option depending on the UI-specific option implementation.
* @param option The CLI option
* @return the cleaned up option name.
*/
protected abstract String cleanupName(Option option);
/**
* Gets an example of how to use this option in the native UI.
* @return An example of how to use this option in the native UI.
*/
public abstract String getExample();
/**
* Replaces CLI pattern options with implementation specific pattern options.
* @param str the string to clean.
* @return the string with CLI names replaced with implementation specific names.
*/
public String cleanup(final String str) {
String workingStr = str;
if (StringUtils.isNotBlank(workingStr)) {
Map<String, String> maps = new HashMap<>();
Matcher matcher = PATTERN.matcher(workingStr);
while (matcher.find()) {
String key = matcher.group();
String optKey = (1 == key.indexOf('-', 1)) ? key.substring(2) : key.substring(1);
Optional<Option> maybeResult = getOptionCollection().getOptions().getOptions().stream()
.filter(o -> optKey.equals(o.getOpt()) || optKey.equals(o.getLongOpt())).findFirst();
maybeResult.ifPresent(value -> maps.put(key, cleanupName(value)));
}
for (Map.Entry<String, String> entry : maps.entrySet()) {
workingStr = workingStr.replaceAll(Pattern.quote(format("%s", entry.getKey())), entry.getValue());
}
}
return workingStr;
}
/**
* Gets the implementation specific name for the native UI.
* @return The implementation specific name for the native UI.
*/
public final String getName() {
return name.toString();
}
/**
* Gets the CasedString version of the name for the native UI.
* @return the CasedString version of the name for the native UI.
*/
public final CasedString getCasedName() {
return name;
}
/**
* return a string showing long and short options if they are available. Will return
* a string.
* @return A string showing long and short options if they are available. Never {@code null}.
*/
public abstract String getText();
/**
* Gets the description in implementation specific format.
*
* @return the description or an empty string.
*/
public final String getDescription() {
return cleanup(option.getDescription());
}
/**
* Gets the simple class name for the data type for this option.
* Normally "String".
* @return the simple class name for the type.
*/
public final Class<?> getType() {
return option.hasArg() ? ((Class<?>) option.getType()) : boolean.class;
}
/**
* Gets the argument name if there is one.
* @return the Argument name
*/
public final String getArgName() {
return argumentType.getDisplayName();
}
/**
* Gets the argument type if there is one.
* @return the Argument name
*/
public final OptionCollection.ArgumentType getArgType() {
return argumentType;
}
/**
* Determines if the option is deprecated.
* @return {@code true} if the option is deprecated
*/
public final boolean isDeprecated() {
return option.isDeprecated();
}
/**
* Determines if the option is required.
* @return {@code true} if the option is required.
*/
public final boolean isRequired() {
return option.isRequired();
}
/**
* Determine if the enclosed option expects an argument.
* @return {@code true} if the enclosed option expects at least one argument.
*/
public final boolean hasArg() {
return option.hasArg();
}
/**
* Returns {@code true} if the option has multiple arguments.
* @return {@code true} if the option has multiple arguments.
*/
public final boolean hasArgs() {
return option.hasArgs();
}
/**
* The key value for the option.
* @return the key value for the CLI argument map.
*/
public final String keyValue() {
return StringUtils.defaultIfEmpty(option.getLongOpt(), option.getOpt());
}
/**
* Gets the deprecated string if the option is deprecated, or an empty string otherwise.
* @return the deprecated string if the option is deprecated, or an empty string otherwise.
*/
public final String getDeprecated() {
return option.isDeprecated() ? cleanup(StringUtils.defaultIfEmpty(option.getDeprecated().toString(), StringUtils.EMPTY)) : StringUtils.EMPTY;
}
}