package io.airlift.airline.model;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import io.airlift.airline.Accessor;
import io.airlift.airline.OptionType;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.Set;
import static com.google.common.collect.Sets.newHashSet;
public class OptionMetadata
{
private final OptionType optionType;
private final Set<String> options;
private final String title;
private final String description;
private final int arity;
private final boolean required;
private final boolean hidden;
private final Set<String> allowedValues;
private final Set<Accessor> accessors;
public OptionMetadata(OptionType optionType,
Iterable<String> options,
String title,
String description,
int arity,
boolean required,
boolean hidden,
Iterable<String> allowedValues,
Iterable<Field> path)
{
Preconditions.checkNotNull(optionType, "optionType is null");
Preconditions.checkNotNull(options, "options is null");
Preconditions.checkArgument(!Iterables.isEmpty(options), "options is empty");
Preconditions.checkNotNull(title, "title is null");
Preconditions.checkNotNull(path, "path is null");
Preconditions.checkArgument(!Iterables.isEmpty(path), "path is empty");
this.optionType = optionType;
this.options = ImmutableSet.copyOf(options);
this.title = title;
this.description = description;
this.arity = arity;
this.required = required;
this.hidden = hidden;
if (allowedValues != null) {
this.allowedValues = ImmutableSet.copyOf(allowedValues);
}
else {
this.allowedValues = null;
}
this.accessors = ImmutableSet.of(new Accessor(path));
}
public OptionMetadata(Iterable<OptionMetadata> options)
{
Preconditions.checkNotNull(options, "options is null");
Preconditions.checkArgument(!Iterables.isEmpty(options), "options is empty");
OptionMetadata option = options.iterator().next();
this.optionType = option.optionType;
this.options = option.options;
this.title = option.title;
this.description = option.description;
this.arity = option.arity;
this.required = option.required;
this.hidden = option.hidden;
if (option.allowedValues != null) {
this.allowedValues = ImmutableSet.copyOf(option.allowedValues);
}
else {
this.allowedValues = null;
}
Set<Accessor> accessors = newHashSet();
for (OptionMetadata other : options) {
Preconditions.checkArgument(option.equals(other),
"Conflicting options definitions: %s, %s", option, other);
accessors.addAll(other.getAccessors());
}
this.accessors = ImmutableSet.copyOf(accessors);
}
public OptionType getOptionType()
{
return optionType;
}
public Set<String> getOptions()
{
return options;
}
public String getTitle()
{
return title;
}
public String getDescription()
{
return description;
}
public int getArity()
{
return arity;
}
public boolean isRequired()
{
return required;
}
public boolean isHidden()
{
return hidden;
}
public boolean isMultiValued()
{
return accessors.iterator().next().isMultiValued();
}
public Class<?> getJavaType()
{
return accessors.iterator().next().getJavaType();
}
public Set<Accessor> getAccessors()
{
return accessors;
}
public Set<String> getAllowedValues()
{
return allowedValues;
}
@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
OptionMetadata that = (OptionMetadata) o;
if (arity != that.arity) {
return false;
}
if (hidden != that.hidden) {
return false;
}
if (required != that.required) {
return false;
}
if (allowedValues != null ? !allowedValues.equals(that.allowedValues) : that.allowedValues != null) {
return false;
}
if (description != null ? !description.equals(that.description) : that.description != null) {
return false;
}
if (optionType != that.optionType) {
return false;
}
if (!options.equals(that.options)) {
return false;
}
if (!title.equals(that.title)) {
return false;
}
return true;
}
@Override
public int hashCode()
{
int result = optionType.hashCode();
result = 31 * result + options.hashCode();
result = 31 * result + title.hashCode();
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + arity;
result = 31 * result + (required ? 1 : 0);
result = 31 * result + (hidden ? 1 : 0);
result = 31 * result + (allowedValues != null ? allowedValues.hashCode() : 0);
return result;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append("OptionMetadata");
sb.append("{optionType=").append(optionType);
sb.append(", options=").append(options);
sb.append(", title='").append(title).append('\'');
sb.append(", description='").append(description).append('\'');
sb.append(", arity=").append(arity);
sb.append(", required=").append(required);
sb.append(", hidden=").append(hidden);
sb.append(", accessors=").append(accessors);
sb.append('}');
return sb.toString();
}
public static Function<OptionMetadata, Set<String>> optionsGetter()
{
return new Function<OptionMetadata, Set<String>>()
{
public Set<String> apply(OptionMetadata input)
{
return input.getOptions();
}
};
}
public static Predicate<OptionMetadata> isHiddenPredicate()
{
return new Predicate<OptionMetadata>() {
@Override
public boolean apply(@Nullable OptionMetadata input)
{
return !input.isHidden();
}
};
}
}