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

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

There is a newer version: 9.1.7.Final
Show newest version
// Copyright 2013 Square, Inc.
package com.squareup.protoparser;

import com.google.auto.value.AutoValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static com.squareup.protoparser.Utils.appendIndented;
import static com.squareup.protoparser.Utils.checkNotNull;
import static java.util.Collections.unmodifiableMap;

@AutoValue
public abstract class OptionElement {
  public enum Kind {
    STRING,
    BOOLEAN,
    NUMBER,
    ENUM,
    MAP,
    LIST,
    OPTION
  }

  @SuppressWarnings("unchecked")
  public static Map optionsAsMap(List options) {
    Map map = new LinkedHashMap<>();
    for (OptionElement option : options) {
      String name = option.name();
      Object value = option.value();

      if (value instanceof String || value instanceof List) {
        map.put(name, value);
      } else if (value instanceof OptionElement) {
        Map newMap = optionsAsMap(Collections.singletonList((OptionElement) value));

        Object oldValue = map.get(name);
        if (oldValue instanceof Map) {
          Map oldMap = (Map) oldValue;
          // Existing nested maps are immutable. Make a mutable copy, update, and replace.
          oldMap = new LinkedHashMap<>(oldMap);
          oldMap.putAll(newMap);
          map.put(name, oldMap);
        } else {
          map.put(name, newMap);
        }
      } else if (value instanceof Map) {
        Object oldValue = map.get(name);
        if (oldValue instanceof Map) {
          ((Map) oldValue).putAll((Map) value);
        } else {
          map.put(name, value);
        }
      } else {
        throw new AssertionError("Option value must be String, Option, List, or Map");
      }
    }
    return unmodifiableMap(map);
  }

  /** Return the option with the specified name from the supplied list or null. */
  public static OptionElement findByName(List options, String name) {
    checkNotNull(options, "options");
    checkNotNull(name, "name");

    OptionElement found = null;
    for (OptionElement option : options) {
      if (option.name().equals(name)) {
        if (found != null) {
          throw new IllegalStateException("Multiple options match name: " + name);
        }
        found = option;
      }
    }
    return found;
  }

  public static OptionElement create(String name, Kind kind, Object value) {
    return create(name, kind, value, false);
  }

  public static OptionElement create(String name, Kind kind, Object value,
      boolean isParenthesized) {
    checkNotNull(name, "name");
    checkNotNull(value, "value");

    return new AutoValue_OptionElement(name, kind, value, isParenthesized);
  }

  OptionElement() {
  }

  public abstract String name();
  public abstract Kind kind();
  public abstract Object value();
  public abstract boolean isParenthesized();

  public final String toSchema() {
    Object value = value();
    switch (kind()) {
      case STRING:
        return formatName() + " = \"" + value + '"';
      case BOOLEAN:
      case NUMBER:
      case ENUM:
        return formatName() + " = " + value;
      case OPTION: {
        StringBuilder builder = new StringBuilder();
        OptionElement optionValue = (OptionElement) value;
        // Treat nested options as non-parenthesized always, prevents double parentheses.
        optionValue =
            OptionElement.create(optionValue.name(), optionValue.kind(), optionValue.value());
        builder.append(formatName()).append('.').append(optionValue.toSchema());
        return builder.toString();
      }
      case MAP: {
        StringBuilder builder = new StringBuilder();
        builder.append(formatName()).append(" = {\n");
        //noinspection unchecked
        Map valueMap = (Map) value;
        formatOptionMap(builder, valueMap);
        builder.append('}');
        return builder.toString();
      }
      case LIST: {
        StringBuilder builder = new StringBuilder();
        builder.append(formatName()).append(" = [\n");
        //noinspection unchecked
        List optionList = (List) value;
        formatOptionList(builder, optionList);
        builder.append(']');
        return builder.toString();
      }
      default:
        throw new AssertionError();
    }
  }

  public final String toSchemaDeclaration() {
    return "option " + toSchema() + ";\n";
  }

  static void formatOptionList(StringBuilder builder, List optionList) {
    for (int i = 0, count = optionList.size(); i < count; i++) {
      String endl = (i < count - 1) ? "," : "";
      appendIndented(builder, optionList.get(i).toSchema() + endl);
    }
  }

  static void formatOptionMap(StringBuilder builder, Map valueMap) {
    List> entries = new ArrayList<>(valueMap.entrySet());
    for (int i = 0, count = entries.size(); i < count; i++) {
      Map.Entry entry = entries.get(i);
      String endl = (i < count - 1) ? "," : "";
      appendIndented(builder,
          entry.getKey() + ": " + formatOptionMapValue(entry.getValue()) + endl);
    }
  }

  static String formatOptionMapValue(Object value) {
    checkNotNull(value, "value == null");
    if (value instanceof String) {
      return "\"" + value + '"';
    }
    if (value instanceof Map) {
      StringBuilder builder = new StringBuilder().append("{\n");
      //noinspection unchecked
      Map map = (Map) value;
      formatOptionMap(builder, map);
      return builder.append('}').toString();
    }
    if (value instanceof List) {
      StringBuilder builder = new StringBuilder().append("[\n");
      List list = (List) value;
      for (int i = 0, count = list.size(); i < count; i++) {
        String endl = (i < count - 1) ? "," : "";
        appendIndented(builder, formatOptionMapValue(list.get(i)) + endl);
      }
      return builder.append("]").toString();
    }
    return value.toString();
  }

  private String formatName() {
    if (isParenthesized()) {
      return '(' + name() + ')';
    } else {
      return name();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy