All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.squareup.protoparser.EnumElement Maven / Gradle / Ivy

// Copyright 2013 Square, Inc.
package com.squareup.protoparser;

import com.google.auto.value.AutoValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import static com.squareup.protoparser.Utils.appendDocumentation;
import static com.squareup.protoparser.Utils.appendIndented;
import static com.squareup.protoparser.Utils.checkNotNull;
import static com.squareup.protoparser.Utils.immutableCopyOf;

/** An enumerated type declaration. */
@AutoValue
public abstract class EnumElement implements TypeElement {
  private static void validateTagUniqueness(String qualifiedName,
      List constants) {
    checkNotNull(qualifiedName, "qualifiedName");

    Set tags = new LinkedHashSet<>();
    for (EnumConstantElement constant : constants) {
      int tag = constant.tag();
      if (!tags.add(tag)) {
        throw new IllegalStateException("Duplicate tag " + tag + " in " + qualifiedName);
      }
    }
  }

  private static boolean parseAllowAlias(List options) {
    OptionElement option = OptionElement.findByName(options, "allow_alias");
    return option != null && "true".equals(option.value());
  }

  /**
   * Though not mentioned in the spec, enum names use C++ scoping rules, meaning that enum constants
   * are siblings of their declaring element, not children of it.
   */
  static void validateValueUniquenessInScope(String qualifiedName,
      List nestedElements) {
    Set names = new LinkedHashSet<>();
    for (TypeElement nestedElement : nestedElements) {
      if (nestedElement instanceof EnumElement) {
        EnumElement enumElement = (EnumElement) nestedElement;
        for (EnumConstantElement constant : enumElement.constants()) {
          String name = constant.name();
          if (!names.add(name)) {
            throw new IllegalStateException(
                "Duplicate enum constant " + name + " in scope " + qualifiedName);
          }
        }
      }
    }
  }

  public static Builder builder() {
    return new Builder();
  }

  EnumElement() {
  }

  @Override public abstract String name();
  @Override public abstract String qualifiedName();
  @Override public abstract String documentation();
  public abstract List constants();
  @Override public abstract List options();

  @Override public final List nestedElements() {
    return Collections.emptyList(); // Enums do not allow nested type declarations.
  }

  @Override public final String toSchema() {
    StringBuilder builder = new StringBuilder();
    appendDocumentation(builder, documentation());
    builder.append("enum ")
        .append(name())
        .append(" {");
    if (!options().isEmpty()) {
      builder.append('\n');
      for (OptionElement option : options()) {
        appendIndented(builder, option.toSchemaDeclaration());
      }
    }
    if (!constants().isEmpty()) {
      builder.append('\n');
      for (EnumConstantElement constant : constants()) {
        appendIndented(builder, constant.toSchema());
      }
    }
    return builder.append("}\n").toString();
  }

  public static final class Builder {
    private String name;
    private String qualifiedName;
    private String documentation = "";
    private final List constants = new ArrayList<>();
    private final List options = new ArrayList<>();

    private Builder() {
    }

    public Builder name(String name) {
      this.name = checkNotNull(name, "name");
      if (qualifiedName == null) {
        qualifiedName = name;
      }
      return this;
    }

    public Builder qualifiedName(String qualifiedName) {
      this.qualifiedName = checkNotNull(qualifiedName, "qualifiedName");
      return this;
    }

    public Builder documentation(String documentation) {
      this.documentation = checkNotNull(documentation, "documentation");
      return this;
    }

    public Builder addConstant(EnumConstantElement constant) {
      constants.add(checkNotNull(constant, "constant"));
      return this;
    }

    public Builder addConstants(Collection constants) {
      for (EnumConstantElement constant : checkNotNull(constants, "constants")) {
        addConstant(constant);
      }
      return this;
    }

    public Builder addOption(OptionElement option) {
      options.add(checkNotNull(option, "option"));
      return this;
    }

    public Builder addOptions(Collection options) {
      for (OptionElement option : checkNotNull(options, "options")) {
        addOption(option);
      }
      return this;
    }

    public EnumElement build() {
      checkNotNull(name, "name");
      checkNotNull(qualifiedName, "qualifiedName");

      if (!parseAllowAlias(options)) {
        validateTagUniqueness(qualifiedName, constants);
      }
      return new AutoValue_EnumElement(name, qualifiedName, documentation,
          immutableCopyOf(constants), immutableCopyOf(options));
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy