text:
package com.google.api.codegen.transformer;

import com.google.api.codegen.ReleaseLevel;
import com.google.api.codegen.config.AnyResourceNameConfig;
import com.google.api.codegen.config.FieldConfig;
import com.google.api.codegen.config.FieldModel;
import com.google.api.codegen.config.GrpcStreamingConfig;
import com.google.api.codegen.config.InterfaceConfig;
import com.google.api.codegen.config.InterfaceModel;
import com.google.api.codegen.config.MethodConfig;
import com.google.api.codegen.config.MethodContext;
import com.google.api.codegen.config.MethodModel;
import com.google.api.codegen.config.OneofConfig;
import com.google.api.codegen.config.PageStreamingConfig;
import com.google.api.codegen.config.ResourceNameConfig;
import com.google.api.codegen.config.ResourceNameType;
import com.google.api.codegen.config.SampleConfig;
import com.google.api.codegen.config.SingleResourceNameConfig;
import com.google.api.codegen.config.TransportProtocol;
import com.google.api.codegen.config.TypeModel;
import com.google.api.codegen.config.VisibilityConfig;
import com.google.api.codegen.discovery.Document;
import com.google.api.codegen.discovery.Schema;
import com.google.api.codegen.util.CommentReformatter;
import com.google.api.codegen.util.CommonRenderingUtil;
import com.google.api.codegen.util.Name;
import com.google.api.codegen.util.NameFormatter;
import com.google.api.codegen.util.NameFormatterDelegator;
import com.google.api.codegen.util.NamePath;
import com.google.api.codegen.util.StringUtil;
import com.google.api.codegen.util.SymbolTable;
import com.google.api.codegen.util.TypeNameConverter;
import com.google.api.codegen.viewmodel.CallingForm;
import com.google.api.codegen.viewmodel.ServiceMethodType;
import com.google.api.tools.framework.model.EnumType;
import com.google.api.tools.framework.model.Interface;
import com.google.api.tools.framework.model.MessageType;
import com.google.api.tools.framework.model.TypeRef;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * A SurfaceNamer provides language-specific names for specific components of a view for a surface.
 *
 *
Naming is composed of two steps:
 *
 *
1. Composing a Name instance with the name pieces 2. Formatting the Name for the particular
 * type of identifier needed.
 *
 *
This class delegates step 2 to the provided name formatter, which generally would be a
 * language-specific namer.
 */
public class SurfaceNamer extends NameFormatterDelegator {
  private final TypeFormatter typeFormatter;
  private final TypeNameConverter typeNameConverter;
  private final CommentReformatter commentReformatter;
  private final String rootPackageName;
  private final String packageName;
  private final NameFormatter nameFormatter;

  /** Represents a kind of test. */
  public enum TestKind {
    UNIT,
    SYSTEM
  }

  public enum Cardinality implements Comparable<Cardinality> {
    IS_REPEATED(true),
    NOT_REPEATED(false);

    Cardinality(boolean value) {
      this.value = value;
    }

    public static Cardinality ofRepeated(boolean value) {
      return value ? IS_REPEATED : NOT_REPEATED;
    }

    private final boolean value;
  }

  public enum MapType implements Comparable<MapType> {
    IS_MAP(true),
    NOT_MAP(false);

    MapType(boolean value) {
      this.value = value;
    }

    public static MapType ofMap(boolean value) {
      return value ? IS_MAP : NOT_MAP;
    }

    private final boolean value;
  }

  public SurfaceNamer(
      NameFormatter languageNamer,
      ModelTypeFormatter typeFormatter,
      TypeNameConverter typeNameConverter,
      CommentReformatter commentReformatter,
      String rootPackageName,
      String packageName) {
    super(languageNamer);
    this.typeFormatter = typeFormatter;
    this.typeNameConverter = typeNameConverter;
    this.commentReformatter = commentReformatter;
    this.rootPackageName = rootPackageName;
    this.packageName = packageName;
    this.nameFormatter = languageNamer;
  }

  // Create a SurfaceNamer based on Discovery Documents.
  public SurfaceNamer(
      NameFormatter languageNamer,
      SchemaTypeFormatter typeFormatter,
      TypeNameConverter typeNameConverter,
      CommentReformatter commentReformatter,
      String rootPackageName,
      String packageName) {
    super(languageNamer);
    this.typeNameConverter = typeNameConverter;
    this.commentReformatter = commentReformatter;
    this.packageName = packageName;
    this.rootPackageName = rootPackageName;
    this.typeFormatter = typeFormatter;
    this.nameFormatter = languageNamer;
  }

  public SurfaceNamer cloneWithPackageName(String packageName) {
    throw new UnsupportedOperationException("clone needs to be overridden");
  }

  public SurfaceNamer cloneWithPackageNameForDiscovery(String packageName) {
    throw new UnsupportedOperationException("clone needs to be overridden");
  }

  public ModelTypeFormatter getModelTypeFormatter() {
    return (ModelTypeFormatter) typeFormatter;
  }

  public TypeFormatter getTypeFormatter() {
    return typeFormatter;
  }

  public TypeNameConverter getTypeNameConverter() {
    return typeNameConverter;
  }

  public NameFormatter getNameFormatter() {
    return nameFormatter;
  }

  public CommentReformatter getCommentReformatter() {
    return commentReformatter;
  }

  public String getPackageName() {
    return packageName;
  }

  public String getRootPackageName() {
    return rootPackageName;
  }

  public String getStubPackageName() {
    return rootPackageName + ".stub";
  }

  public String getNotImplementedString(String feature) {
    return "$ NOT IMPLEMENTED: " + feature + " $";
  }

  /////////////////////////////////////// Service names ///////////////////////////////////////////

  /**
   * Returns the service name with common suffixes removed.
   *
   *
For example: "LoggingServiceV2" becomes Name("Logging")
   */
  public Name getReducedServiceName(String interfaceSimpleName) {
    String name = interfaceSimpleName.replaceAll("V[0-9]+$", "");
    name = name.replaceAll("Service$", "");
    return Name.upperCamel(name);
  }

  /** Returns the service name exported by the package */
  public String getPackageServiceName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getPackageServiceName");
  }

  /** Human-friendly name of this API interface */
  public String getServicePhraseName(InterfaceConfig interfaceConfig) {
    return Name.upperCamel(interfaceConfig.getInterfaceModel().getSimpleName()).toPhrase();
  }

  /////////////////////////////////////// Constructors /////////////////////////////////////////////

  /**
   * The name of the constructor for the interfaceConfig.getInterfaceModel() client. The client is
   * VKit generated, not GRPC.
   */
  public String getApiWrapperClassConstructorName(InterfaceConfig interfaceConfig) {
    return publicClassName(
        Name.upperCamel(interfaceConfig.getInterfaceModel().getSimpleName(), "Client"));
  }

  /** Constructor name for the type with the given nickname. */
  public String getTypeConstructor(String typeNickname) {
    return typeNickname;
  }

  //////////////////////////////////// Package & module names /////////////////////////////////////

  /** The local (unqualified) name of the package */
  public String getLocalPackageName() {
    return getNotImplementedString("SurfaceNamer.getLocalPackageName");
  }

  /**
   * The name of a variable that holds an instance of the module that contains the implementation of
   * a particular proto interface.
   */
  public String getApiWrapperModuleName() {
    return getNotImplementedString("SurfaceNamer.getApiWrapperModuleName");
  }

  /**
   * The version of a variable that holds an instance of the module that contains the implementation
   * of a particular proto interface. So far it is used by just NodeJS.
   */
  public String getApiWrapperModuleVersion() {
    return getNotImplementedString("SurfaceNamer.getApiWrapperModuleVersion");
  }

  /** The qualified namespace of an API interface. */
  public String getNamespace(InterfaceModel apiInterface) {
    NamePath namePath =
        typeNameConverter.getNamePath(getModelTypeFormatter().getFullNameFor(apiInterface));
    return qualifiedName(namePath.withoutHead());
  }

  public String getGapicImplNamespace() {
    return getNotImplementedString("SurfaceNamer.getGapicImplNamespace");
  }

  /** The qualified namespace of an API. */
  public String getTopLevelNamespace() {
    return getNotImplementedString("SurfaceNamer.getTopLevelNamespace");
  }

  /** The versioned namespace of an api. Example: google.cloud.vision_v1 */
  public String getVersionedDirectoryNamespace() {
    return getNotImplementedString("SurfaceNamer.getVersionedDirectoryNamespace");
  }

  /** The modules of the package. */
  public ImmutableList<String> getApiModules() {
    return ImmutableList.<String>of();
  }

  /** The top level modules of the package. */
  public List<String> getTopLevelApiModules() {
    return ImmutableList.of();
  }

  /** The name of the gapic package. */
  public String getGapicPackageName(String configPackageName) {
    return "gapic-" + configPackageName;
  }

  /** The name of the module for the service of an API. */
  public String getModuleServiceName() {
    return getNotImplementedString("SurfaceNamer.getModuleServiceName");
  }

  /////////////////////////////////// Proto methods /////////////////////////////////////////////

  /** The function name to set the given field. */
  public String getFieldSetFunctionName(FeatureConfig featureConfig, FieldConfig fieldConfig) {
    FieldModel field = fieldConfig.getField();
    if (featureConfig.useResourceNameProtoAccessor(fieldConfig)) {
      return getResourceNameFieldSetFunctionName(fieldConfig.getMessageFieldConfig());
    } else {
      return getFieldSetFunctionName(field);
    }
  }

  /** The function name to set the given field. */
  public String getFieldSetFunctionName(FieldModel field) {
    return getFieldSetFunctionName(
        field.getNameAsParameterName(),
        MapType.ofMap(field.isMap()),
        Cardinality.ofRepeated(field.isRepeated()));
  }

  /** The function name to set a field having the given type and name. */
  public String getFieldSetFunctionName(TypeModel type, Name identifier) {
    return getFieldSetFunctionName(
        identifier, MapType.ofMap(type.isMap()), Cardinality.ofRepeated(type.isRepeated()));
  }
  /** The function name to get a field having the given name. */
  public String getFieldSetFunctionName(Name identifier, MapType mapType, Cardinality cardinality) {
    if (mapType == MapType.IS_MAP) {
      return publicMethodName(Name.from("put", "all").join(identifier));
    } else if (cardinality == Cardinality.IS_REPEATED) {
      return publicMethodName(Name.from("add", "all").join(identifier));
    } else {
      return publicMethodName(Name.from("set").join(identifier));
    }
  }

  /** The function name to add an element to a map or repeated field. */
  public String getFieldAddFunctionName(FieldModel field) {
    if (field.isMap()) {
      return publicMethodName(Name.from("put").join(field.getNameAsParameterName()));
    } else if (field.isRepeated()) {
      return publicMethodName(Name.from("add").join(field.getNameAsParameterName()));
    } else {
      return publicMethodName(Name.from("set").join(field.getNameAsParameterName()));
    }
  }

  /** The function name to add an element to a map or repeated field. */
  public String getFieldAddFunctionName(TypeModel type, Name identifier) {
    return getNotImplementedString("SurfaceNamer.getFieldAddFunctionName");
  }

  /** The function name to set a field that is a resource name class. */
  public String getResourceNameFieldSetFunctionName(FieldConfig fieldConfig) {
    FieldModel type = fieldConfig.getField();
    Name identifier = fieldConfig.getField().getNameAsParameterName();
    Name resourceName = getResourceTypeNameObject(fieldConfig.getResourceNameConfig());
    if (type.isMap()) {
      return getNotImplementedString("SurfaceNamer.getResourceNameFieldSetFunctionName:map-type");
    } else if (type.isRepeated()) {
      return publicMethodName(
          Name.from("add", "all").join(identifier).join("with").join(resourceName).join("list"));
    } else {
      return publicMethodName(Name.from("set").join(identifier).join("with").join(resourceName));
    }
  }

  public String getFullNameForElementType(FieldModel type) {
    return getTypeFormatter().getFullNameForElementType(type);
  }

  /** The function name to get the given field. */
  public String getFieldGetFunctionName(FeatureConfig featureConfig, FieldConfig fieldConfig) {
    FieldModel field = fieldConfig.getField();
    if (featureConfig.useResourceNameProtoAccessor(fieldConfig)) {
      return getResourceNameFieldGetFunctionName(fieldConfig.getMessageFieldConfig());
    } else {
      return getFieldGetFunctionName(field);
    }
  }

  /** The function name to get the given field. */
  public String getFieldGetFunctionName(FieldModel field) {
    return getFieldGetFunctionName(field, field.getNameAsParameterName());
  }

  /** The function name to get a field having the given name. */
  public String getFieldGetFunctionName(Name identifier, MapType mapType, Cardinality cardinality) {
    if (mapType != MapType.IS_MAP && cardinality == Cardinality.IS_REPEATED) {
      return publicMethodName(Name.from("get").join(identifier).join("list"));
    } else if (mapType == MapType.IS_MAP) {
      return publicMethodName(Name.from("get").join(identifier).join("map"));
    } else {
      return publicMethodName(Name.from("get").join(identifier));
    }
  }

  public String getFieldHasFunctionName(FieldModel field) {
    return getFieldHasFunctionName(
        field.getNameAsParameterName(),
        MapType.ofMap(field.isMap()),
        Cardinality.ofRepeated(field.isRepeated()));
  }

  public String getFieldHasFunctionName(Name identifier, MapType mapType, Cardinality cardinality) {
    if (mapType == MapType.IS_MAP && cardinality == Cardinality.IS_REPEATED) {
      throw new IllegalArgumentException("Maps and repeated fields don't have has*() methods");
    } else {
      return publicMethodName(Name.from("has").join(identifier));
    }
  }

  /** The function name to get a field having the given type and name. */
  public String getFieldGetFunctionName(TypeModel type, Name identifier) {
    return getFieldGetFunctionName(
        identifier, MapType.ofMap(type.isMap()), Cardinality.ofRepeated(type.isRepeated()));
  }

  /** The function name to get a field having the given type and name. */
  public String getFieldGetFunctionName(FieldModel type, Name identifier) {
    return getFieldGetFunctionName(
        identifier, MapType.ofMap(type.isMap()), Cardinality.ofRepeated(type.isRepeated()));
  }

  /** The function name to get a field that is a resource name class. */
  public String getResourceNameFieldGetFunctionName(FieldConfig fieldConfig) {
    FieldModel type = fieldConfig.getField();
    Name identifier = fieldConfig.getField().getNameAsParameterName();
    Name resourceName = getResourceTypeNameObject(fieldConfig.getResourceNameConfig());
    if (type.isMap()) {
      return getNotImplementedString("SurfaceNamer.getResourceNameFieldGetFunctionName:map-type");
    } else if (type.isRepeated()) {
      return publicMethodName(
          Name.from("get").join(identifier).join("list_as").join(resourceName).join("list"));
    } else {
      return publicMethodName(Name.from("get").join(identifier).join("as").join(resourceName));
    }
  }

  /**
   * The function name to get the count of elements in the given field.
   *
   * @throws IllegalArgumentException if the field is not a repeated field.
   */
  public String getFieldCountGetFunctionName(FieldModel field) {
    if (field.isRepeated()) {
      return publicMethodName(Name.from("get").join(field.getNameAsParameterName()).join("count"));
    } else {
      throw new IllegalArgumentException(
          "Non-repeated field " + field.getSimpleName() + " has no count function.");
    }
  }

  /**
   * The function name to get an element by index from the given field.
   *
   * @throws IllegalArgumentException if the field is not a repeated field.
   */
  public String getByIndexGetFunctionName(FieldModel field) {
    if (field.isRepeated()) {
      return publicMethodName(Name.from("get", field.getSimpleName()));
    } else {
      throw new IllegalArgumentException(
          "Non-repeated field " + field.getSimpleName() + " has no get-by-index function.");
    }
  }

  ///////////////////////////////// Function & Callable names /////////////////////////////////////

  /** The function name to retrieve default client option */
  public String getDefaultApiSettingsFunctionName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getDefaultClientOptionFunctionName");
  }

  /** The method name to create a rerouted gRPC client. Used in C# */
  public String getReroutedGrpcMethodName(MethodConfig methodConfig) {
    return getNotImplementedString("SurfaceNamer.getReroutedGrpcMethodName");
  }

  /** The type name of a rerouted gRPC type. Used in C# */
  public String getReroutedGrpcTypeName(ImportTypeTable typeTable, MethodConfig methodConfig) {
    return getNotImplementedString("SurfaceNamer.getReroutedGrpcTypeName");
  }

  /** The name of the surface method which can call the given API method. */
  public String getApiMethodName(MethodModel method, VisibilityConfig visibility) {
    return getApiMethodName(method.asName(), visibility);
  }

  /** The name of the async surface method which can call the given API method. */
  public String getAsyncApiMethodName(MethodModel method, VisibilityConfig visibility) {
    return getApiMethodName(method.asName().join("async"), visibility);
  }

  protected String getApiMethodName(Name name, VisibilityConfig visibility) {
    switch (visibility) {
      case PUBLIC:
        return publicMethodName(name);
      case PACKAGE:
      case PRIVATE:
        return privateMethodName(name);
      default:
        throw new IllegalArgumentException("cannot name method with visibility: " + visibility);
    }
  }

  /** The name of the paged resource variable name used in generated test cases. */
  public String getPagedResourceName() {
    return localVarName(Name.from("resources"));
  }

  /**
   * The name of the iterate method of the PagedListResponse type for a field, returning the
   * resource type iterate method if available
   */
  public String getPagedResponseIterateMethod(
      FeatureConfig featureConfig, FieldConfig fieldConfig) {
    if (featureConfig.useResourceNameFormatOption(fieldConfig)) {
      Name resourceName = getResourceTypeNameObject(fieldConfig.getResourceNameConfig());
      return publicMethodName(Name.from("iterate_all_as").join(resourceName));
    } else {
      return getPagedResponseIterateMethod();
    }
  }

  /** The name of the iterate method of the PagedListResponse type for a field */
  public String getPagedResponseIterateMethod() {
    return publicMethodName(Name.from("iterate_all_elements"));
  }

  /**
   * The name of the get values method of the Page type for a field, returning the resource type get
   * values method if available
   */
  public String getPageGetValuesMethod(FeatureConfig featureConfig, FieldConfig fieldConfig) {
    if (featureConfig.useResourceNameFormatOption(fieldConfig)) {
      Name resourceName = getResourceTypeNameObject(fieldConfig.getResourceNameConfig());
      return publicMethodName(Name.from("get_values_as").join(resourceName));
    } else {
      return getPageGetValuesMethod();
    }
  }

  /** The name of the get values method of the Page type for a field */
  public String getPageGetValuesMethod() {
    return publicMethodName(Name.from("get_values"));
  }

  public String getResourceTypeParseMethodName(
      ImportTypeTable typeTable, FieldConfig resourceFieldConfig) {
    return getNotImplementedString("SurfaceNamer.getResourceTypeParseMethodName");
  }

  public String getResourceTypeParseListMethodName(
      ImportTypeTable typeTable, FieldConfig resourceFieldConfig) {
    return getNotImplementedString("SurfaceNamer.getResourceTypeParseListMethodName");
  }

  public String getResourceTypeFormatListMethodName(
      ImportTypeTable typeTable, FieldConfig resourceFieldConfig) {
    return getNotImplementedString("SurfaceNamer.getResourceTypeFormatListMethodName");
  }

  /** The name of the create method for the resource one-of for the given field config */
  public String getResourceOneofCreateMethod(ImportTypeTable typeTable, FieldConfig fieldConfig) {
    return getAndSaveResourceTypeName(typeTable, fieldConfig.getMessageFieldConfig())
        + "."
        + publicMethodName(Name.from("from"));
  }

  /** The name of the create method for the resource one-of for the given field config */
  public String getResourceTypeParentParseMethod(
      MethodContext context, FieldConfig resourceFieldConfig) {
    return getNotImplementedString("SurfaceNamer.getResourceTypeParentParseMethod");
  }

  public String getResourceNameFormatMethodName() {
    return "toString";
  }

  /** The method name of the retry filter for the given key */
  public String retryFilterMethodName(String key) {
    return privateMethodName(Name.from(key).join("retry").join("filter"));
  }

  /** The method name of the retry backoff for the given key */
  public String retryBackoffMethodName(String key) {
    return privateMethodName(Name.from("get").join(key).join("retry").join("backoff"));
  }

  /** The method name of the timeout backoff for the given key */
  public String timeoutBackoffMethodName(String key) {
    return privateMethodName(Name.from("get").join(key).join("timeout").join("backoff"));
  }

  /** The name of the GRPC streaming surface method which can call the given API method. */
  public String getGrpcStreamingApiMethodName(MethodModel method, VisibilityConfig visibility) {
    return getApiMethodName(method, visibility);
  }

  /** The name of the callable for the paged callable variant of the given method. */
  public String getPagedCallableName(MethodModel method) {
    return privateFieldName(method.asName().join(Name.from("paged", "callable")));
  }

  /** The name of the paged callable variant of the given method. */
  public String getPagedCallableMethodName(MethodModel method) {
    return publicMethodName(method.asName().join(Name.from("paged", "callable")));
  }

  /** The name of the plain callable variant of the given method. */
  public String getCallableMethodName(MethodModel method) {
    return publicMethodName(method.asName().join("callable"));
  }

  /** The name of the plain callable variant of the given method. */
  public String getCallableAsyncMethodName(MethodModel method) {
    return publicMethodName(method.asName().join(Name.from("callable", "async")));
  }

  /** The name of the operation callable variant of the given method. */
  public String getOperationCallableMethodName(MethodModel method) {
    return publicMethodName(method.asName().join(Name.from("operation", "callable")));
  }

  /** The name of the plain callable for the given method. */
  public String getCallableName(MethodModel method) {
    return privateFieldName(method.asName().join("callable"));
  }

  /** The name of the operation callable for the given method. */
  public String getOperationCallableName(MethodModel method) {
    return privateFieldName(method.asName().join(Name.from("operation", "callable")));
  }

  public String getMethodDescriptorName(MethodModel method) {
    return privateFieldName(Name.anyCamel(method.getSimpleName(), "MethodDescriptor"));
  }

  public String getTransportSettingsVar(MethodModel method) {
    return localVarName(Name.anyCamel(method.getSimpleName(), "TransportSettings"));
  }

  /** The name of the settings member name for the given method. */
  public String getSettingsMemberName(MethodModel method) {
    return publicMethodName(method.asName().join("settings"));
  }

  /** The name of the settings member name for the given method. */
  public String getOperationSettingsMemberName(MethodModel method) {
    return getSettingsMemberName(method);
  }

  /** The getter function name for the settings for the given method. */
  public String getSettingsFunctionName(MethodModel method) {
    return getSettingsMemberName(method);
  }

  /** The getter function name for the settings for the given method. */
  public String getOperationSettingsFunctionName(MethodModel method) {
    return getOperationSettingsMemberName(method);
  }

  /** The name of a method to apply modifications to this method request. */
  public String getModifyMethodName(MethodContext method) {
    return getNotImplementedString("SurfaceNamer.getModifyMethodName");
  }

  /** The function name to retrieve default call option */
  public String getDefaultCallSettingsFunctionName(InterfaceConfig interfaceConfig) {
    return publicMethodName(
        Name.upperCamel(interfaceConfig.getInterfaceModel().getSimpleName(), "Settings"));
  }

  /** The name of the IAM resource getter function. */
  public String getIamResourceGetterFunctionName(FieldModel field) {
    return getNotImplementedString("SurfaceNamer.getIamResourceGetterFunctionName");
  }

  /** The name of the function that will create a stub. */
  public String getCreateStubFunctionName(InterfaceModel apiInterface) {
    return privateMethodName(
        Name.upperCamel("Create", apiInterface.getSimpleName(), "Stub", "Function"));
  }

  /** Function used to register the GRPC server. */
  public String getServerRegisterFunctionName(InterfaceModel apiInterface) {
    return getNotImplementedString("SurfaceNamer.getServerRegisterFunctionName");
  }

  /** The name of the LRO surface method which can call the given API method. */
  public String getLroApiMethodName(MethodModel method, VisibilityConfig visibility) {
    return getAsyncApiMethodName(method, visibility);
  }

  public String getByteLengthFunctionName(FieldModel field) {
    return getNotImplementedString("SurfaceNamer.getByteLengthFunctionName");
  }

  /////////////////////////////////////// Variable names //////////////////////////////////////////

  /**
   * The name of a variable to hold a value for the given proto message field (such as a flattened
   * parameter).
   */
  public String getVariableName(FieldModel field) {
    return localVarName(field.getNameAsParameterName());
  }

  /**
   * The name of a variable that holds an instance of the class that implements a particular proto
   * interface.
   */
  public String getApiWrapperVariableName(InterfaceConfig interfaceConfig) {
    return localVarName(Name.anyCamel(getInterfaceName(interfaceConfig), "Client"));
  }

  /**
   * The name of a variable that holds the settings class for a particular proto interface; not used
   * in most languages.
   */
  public String getApiSettingsVariableName(InterfaceConfig interfaceConfig) {
    return localVarName(Name.anyCamel(getInterfaceName(interfaceConfig), "Settings"));
  }

  /**
   * The name of the builder class for the settings class for a particular proto interface; not used
   * in most languages.
   */
  public String getApiSettingsBuilderVarName(InterfaceConfig interfaceConfig) {
    return localVarName(Name.anyCamel(getInterfaceName(interfaceConfig), "SettingsBuilder"));
  }

  /** The variable name for the given identifier that is formatted. */
  public String getFormattedVariableName(Name identifier) {
    return localVarName(Name.from("formatted").join(identifier));
  }

  /** The variable name of the rerouted gRPC client. Used in C# */
  public String getReroutedGrpcClientVarName(MethodConfig methodConfig) {
    return getNotImplementedString("SurfaceNamer.getGrpcClientName");
  }

  /** The name of the variable that will hold the stub for an API interface. */
  public String getStubName(InterfaceModel apiInterface) {
    return privateFieldName(Name.upperCamel(apiInterface.getSimpleName(), "Stub"));
  }

  /** The name of the array which will hold the methods for a given stub. */
  public String getStubMethodsArrayName(InterfaceModel apiInterface) {
    return privateMethodName(Name.upperCamel(apiInterface.getSimpleName(), "Stub", "Methods"));
  }

  /** The parameter name for the given lower-case field name. */
  public String getParamName(String var) {
    return localVarName(Name.from(var));
  }

  public String getPropertyName(String var) {
    return publicMethodName(Name.from(var));
  }

  /** The name of a retry definition */
  public String getRetryDefinitionName(String retryDefinitionKey) {
    return privateMethodName(Name.from(retryDefinitionKey));
  }

  /** The name of the field. */
  public String getFieldName(FieldModel field) {
    return publicFieldName(field.getNameAsParameterName());
  }

  /** The page streaming descriptor name for the given method. */
  public String getPageStreamingDescriptorName(MethodModel method) {
    return privateFieldName(method.asName().join(Name.from("page", "streaming", "descriptor")));
  }

  /** The variable name of the gRPC request object. */
  public String getRequestVariableName(MethodModel method) {
    return getNotImplementedString("SurfaceNamer.getRequestVariableName");
  }

  /////////////////////////////////////// Type names /////////////////////////////////////////////

  protected String getInterfaceName(InterfaceConfig interfaceConfig) {
    return interfaceConfig.getName();
  }

  /** The name of the class that operates on a particular resource type. */
  public String getApiWrapperClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.anyCamel(getInterfaceName(interfaceConfig), "Client"));
  }

  /** The name of the class that operates on a particular Discovery Document resource type. */
  public String getApiWrapperClassName(Document document) {
    return publicClassName(Name.anyCamel(document.name(), "Client"));
  }

  public String getGrpcTransportClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.anyCamel(getInterfaceName(interfaceConfig), "GrpcTransport"));
  }

  /** The name of the implementation class that implements a particular proto interface. */
  public String getApiWrapperClassImplName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getApiWrapperClassImplName");
  }

  /**
   * The name of the class that holds a sample for an API method, constructed from {@code parts}.
   */
  public String getApiSampleClassName(String... parts) {
    return publicClassName(Name.anyLower(parts));
  }

  /**
   * The name of the file holding the sample class for a single API method and variant. The name is
   * constucted from pieces in the language-idiomatic case, followed by appropriate suffix.
   */
  public String getApiSampleFileName(String... pieces) {
    return getNotImplementedString("SurfaceNamer.getApiSampleFileName");
  }

  /** The name of the class that implements snippets for a particular proto interface. */
  public String getApiSnippetsClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(
        Name.upperCamel(interfaceConfig.getInterfaceModel().getSimpleName(), "ApiSnippets"));
  }

  /**
   * The name of the settings class for a particular proto interface; not used in most languages.
   */
  public String getApiSettingsClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.anyCamel(getInterfaceName(interfaceConfig), "Settings"));
  }

  /**
   * The name of the stub interface for a particular proto interface; not used in most languages.
   */
  public String getApiStubInterfaceName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.upperCamel(interfaceConfig.getRawName(), "Stub"));
  }

  /**
   * The name of the stub interface for a particular proto interface; not used in most languages.
   */
  public String getApiStubSettingsClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.upperCamel(interfaceConfig.getRawName(), "Stub", "Settings"));
  }

  /**
   * The name of the callable factory for a particular stub interface; not used in most languages.
   */
  public String getCallableFactoryClassName(
      InterfaceConfig interfaceConfig, TransportProtocol transportProtocol) {
    return publicClassName(
        getTransportProtocolName(transportProtocol)
            .join(Name.upperCamel(interfaceConfig.getRawName(), "Callable", "Factory")));
  }

  /** The name of the RPC stub for a particular proto interface; not used in most languages. */
  public String getApiRpcStubClassName(
      InterfaceModel interfaceModel, TransportProtocol transportProtocol) {
    return publicClassName(
        getTransportProtocolName(transportProtocol)
            .join(Name.anyCamel(interfaceModel.getSimpleName(), "Stub")));
  }

  /**
   * The type name of the Grpc service class This needs to match what Grpc generates for the
   * particular language.
   */
  public String getGrpcServiceClassName(InterfaceModel apiInterface) {
    NamePath namePath =
        typeNameConverter.getNamePath(getTypeFormatter().getFullNameFor(apiInterface));
    String grpcContainerName =
        publicClassName(Name.upperCamelKeepUpperAcronyms(namePath.getHead(), "Grpc"));
    String serviceClassName =
        publicClassName(Name.upperCamelKeepUpperAcronyms(apiInterface.getSimpleName(), "ImplBase"));
    return qualifiedName(namePath.withHead(grpcContainerName).append(serviceClassName));
  }

  /**
   * The fully qualified class name of an API interface.
   *
   *
TODO: Support the general pattern of package + class name in NameFormatter.
   */
  public String getFullyQualifiedApiWrapperClassName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getFullyQualifiedApiWrapperClassName");
  }

  public String getTopLevelAliasedApiClassName(
      InterfaceConfig interfaceConfig, boolean packageHasMultipleServices) {
    return getNotImplementedString("SurfaceNamer.getTopLevelAliasedApiClassName");
  }

  public String getVersionAliasedApiClassName(
      InterfaceConfig interfaceConfig, boolean packageHasMultipleServices) {
    return getNotImplementedString("SurfaceNamer.getVersionAliasedApiClassName");
  }

  protected Name getResourceTypeNameObject(ResourceNameConfig resourceNameConfig) {
    Name entityName = resourceNameConfig.getEntityName();
    ResourceNameType resourceNameType = resourceNameConfig.getResourceNameType();
    switch (resourceNameType) {
      case ANY:
        return getAnyResourceTypeName();
      case FIXED:
        return entityName.join("name_fixed");
      case ONEOF:
        // Remove suffix "_oneof". This allows the collection oneof config to "share" an entity name
        // with a collection config.
        entityName = Name.from(StringUtil.removeSuffix(entityName.toLowerUnderscore(), "_oneof"));
        return entityName.join("name_oneof");
      case SINGLE:
        return entityName.join("name");
      case NONE:
      default:
        throw new UnsupportedOperationException("unexpected entity name type");
    }
  }

  protected Name getAnyResourceTypeName() {
    return Name.from(AnyResourceNameConfig.ENTITY_NAME);
  }

  public String getResourceTypeName(ResourceNameConfig resourceNameConfig) {
    String commonResourceName = resourceNameConfig.getCommonResourceName();
    return commonResourceName != null
        ? commonResourceName
        : publicClassName(getResourceTypeNameObject(resourceNameConfig));
  }

  /**
   * The type name of the Grpc server class. This needs to match what Grpc generates for the
   * particular language.
   */
  public String getGrpcServerTypeName(InterfaceModel apiInterface) {
    return getNotImplementedString("SurfaceNamer.getGrpcServerTypeName");
  }

  /** The imported name of the default client config. */
  public String getClientConfigName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getClientConfigName");
  }

  /**
   * The type name of the Grpc client class. This needs to match what Grpc generates for the
   * particular language.
   */
  public String getGrpcClientTypeName(InterfaceModel apiInterface) {
    return getNotImplementedString("SurfaceNamer.getGrpcClientTypeName");
  }

  /**
   * Gets the type name of the Grpc client class, saves it to the type table provided, and returns
   * the nickname.
   */
  public String getAndSaveNicknameForGrpcClientTypeName(
      ImportTypeTable typeTable, InterfaceModel apiInterface) {
    return typeTable.getAndSaveNicknameFor(getGrpcClientTypeName(apiInterface));
  }

  /**
   * The type name of the Grpc container class. This needs to match what Grpc generates for the
   * particular language.
   */
  public String getGrpcContainerTypeName(InterfaceModel apiInterface) {
    NamePath namePath =
        typeNameConverter.getNamePath(getTypeFormatter().getFullNameFor(apiInterface));
    String publicClassName =
        publicClassName(Name.upperCamelKeepUpperAcronyms(namePath.getHead(), "Grpc"));
    return qualifiedName(namePath.withHead(publicClassName));
  }

  /** The type name for the method param */
  public String getParamTypeName(ImportTypeTable typeTable, TypeModel type) {
    return getNotImplementedString("SurfaceNamer.getParamTypeName");
  }

  /** The type name for the message property */
  public String getMessagePropertyTypeName(ImportTypeTable typeTable, FieldModel type) {
    return getParamTypeName(typeTable, type.getType());
  }

  /** The type name for an optional array argument; not used in most languages. */
  public String getOptionalArrayTypeName() {
    return getNotImplementedString("SurfaceNamer.getOptionalArrayTypeName");
  }

  /** The return type name in a dynamic language for the given method. */
  public String getDynamicLangReturnTypeName(MethodContext methodContext) {
    return getNotImplementedString("SurfaceNamer.getDynamicReturnTypeName");
  }

  /** The return type name in a static language for the given method. */
  public String getStaticLangReturnTypeName(MethodContext methodContext) {
    return getNotImplementedString("SurfaceNamer.getStaticLangReturnTypeName");
  }

  /** The return type name in a static language that is used by the caller */
  public String getStaticLangCallerReturnTypeName(MethodContext methodContext) {
    return getStaticLangReturnTypeName(methodContext);
  }

  /** The async return type name in a static language for the given method. */
  public String getStaticLangAsyncReturnTypeName(MethodContext methodContext) {
    return getNotImplementedString("SurfaceNamer.getStaticLangAsyncReturnTypeName");
  }

  /**
   * Computes the nickname of the operation response type name for the given method, saves it in the
   * given type table, and returns it.
   */
  public String getAndSaveOperationResponseTypeName(
      MethodContext methodContext, ImportTypeTable typeTable) {
    return getNotImplementedString("SurfaceNamer.getAndSaveOperationResponseTypeName");
  }

  /** The async return type name in a static language that is used by the caller */
  public String getStaticLangCallerAsyncReturnTypeName(MethodContext methodContext) {
    return getStaticLangAsyncReturnTypeName(methodContext);
  }

  /** The name used in Grpc for the given API method. This needs to match what Grpc generates. */
  public String getGrpcMethodName(MethodModel method) {
    // This might seem silly, but it makes clear what we're dealing with (upper camel).
    // This is language-independent because of gRPC conventions.
    return Name.anyCamelKeepUpperAcronyms(method.getSimpleName()).toUpperCamel();
  }

  /**
   * The name used in Grpc for the given API async method. This needs to match what Grpc generates.
   */
  public String getAsyncGrpcMethodName(MethodModel method) {
    return getNotImplementedString("SurfaceNamer.getAsyncGrpcMethodName");
  }

  /** The GRPC streaming server type name for a given method. */
  public String getStreamingServerName(MethodModel method) {
    return getNotImplementedString("SurfaceNamer.getStreamingServerName");
  }

  /** The type name of call options */
  public String getCallSettingsTypeName(InterfaceConfig interfaceConfig) {
    return publicClassName(
        Name.upperCamel(interfaceConfig.getInterfaceModel().getSimpleName(), "Settings"));
  }

  /** The name of the return type of the given grpc streaming method. */
  public String getGrpcStreamingApiReturnTypeName(
      MethodContext methodContext, ImportTypeTable typeTable) {
    return publicClassName(
        Name.upperCamel(methodContext.getMethodModel().getOutputTypeSimpleName()));
  }

  /**
   * The generic-aware response type name for the given type. For example, in Java, this will be the
   * type used for Future<...>.
   */
  public String getGenericAwareResponseTypeName(MethodContext methodContext) {
    return getNotImplementedString("SurfaceNamer.getGenericAwareResponseType");
  }

  /**
   * Computes the nickname of the paged response type name for the given method and resources field,
   * saves it in the given type table, and returns it.
   */
  public String getAndSavePagedResponseTypeName(
      MethodContext methodContext, FieldConfig resourcesFieldConfig) {
    return getNotImplementedString("SurfaceNamer.getAndSavePagedResponseTypeName");
  }

  /** The inner type name of the paged response type for the given method and resources field. */
  public String getPagedResponseTypeInnerName(
      MethodModel method, ImportTypeTable typeTable, FieldModel resourcesField) {
    return getNotImplementedString("SurfaceNamer.getAndSavePagedResponseTypeInnerName");
  }

  /** The inner type name of the page type for the given method and resources field. */
  public String getPageTypeInnerName(
      MethodModel method, ImportTypeTable typeTable, FieldModel resourceField) {
    return getNotImplementedString("SurfaceNamer.getPageTypeInnerName");
  }

  /**
   * The inner type name of the fixed size collection type for the given method and resources field.
   */
  public String getFixedSizeCollectionTypeInnerName(
      MethodModel method, ImportTypeTable typeTable, FieldModel resourceField) {
    return getNotImplementedString("SurfaceNamer.getPageTypeInnerName");
  }

  /**
   * Computes the nickname of the async response type name for the given resource type, saves it in
   * the given type table, and returns it.
   */
  public String getAndSaveAsyncPagedResponseTypeName(
      MethodContext methodContext, FieldConfig resourcesFieldConfig) {
    return getNotImplementedString("SurfaceNamer.getAndSavePagedAsyncResponseTypeName");
  }

  /**
   * Computes the nickname of the response type name for the given resource type, as used by the
   * caller, saves it in the given type table, and returns it.
   */
  public String getAndSaveCallerPagedResponseTypeName(
      MethodContext methodContext, FieldConfig resourcesFieldConfig) {
    return getAndSavePagedResponseTypeName(methodContext, resourcesFieldConfig);
  }

  /**
   * Computes the nickname of the response type name for the given resource type, as used by the
   * caller, saves it in the given type table, and returns it.
   */
  public String getAndSaveCallerAsyncPagedResponseTypeName(
      MethodContext method, FieldConfig resourcesFieldConfig) {
    return getAndSaveAsyncPagedResponseTypeName(method, resourcesFieldConfig);
  }

  /** The class name of the generated resource type from the entity name. */
  public String getAndSaveResourceTypeName(ImportTypeTable typeTable, FieldConfig fieldConfig) {
    String commonResourceName = fieldConfig.getResourceNameConfig().getCommonResourceName();
    String resourceClassName =
        commonResourceName != null
            ? commonResourceName
            : publicClassName(getResourceTypeNameObject(fieldConfig.getResourceNameConfig()));
    return typeTable.getAndSaveNicknameForTypedResourceName(fieldConfig, resourceClassName);
  }

  /** The class name of the generated resource type from the entity name. */
  public String getAndSaveElementResourceTypeName(
      ImportTypeTable typeTable, FieldConfig fieldConfig) {
    ResourceNameConfig resourceNameConfig = fieldConfig.getResourceNameConfig();
    if (resourceNameConfig.getCommonResourceName() != null) {
      String resourceClassName = resourceNameConfig.getCommonResourceName();
      return typeTable.getAndSaveNicknameFor(resourceClassName);
    }
    String resourceClassName = publicClassName(getResourceTypeNameObject(resourceNameConfig));
    return typeTable.getAndSaveNicknameForResourceNameElementType(fieldConfig, resourceClassName);
  }

  /** The fully qualified type name for the stub of an API interface. */
  public String getFullyQualifiedStubType(InterfaceModel apiInterface) {
    return getNotImplementedString("SurfaceNamer.getFullyQualifiedStubType");
  }

  /** The fully qualified type name for the RPC stub of an API interface. */
  public String getFullyQualifiedRpcStubType(
      InterfaceModel interfaceModel, TransportProtocol transportProtocol) {
    return getNotImplementedString("SurfaceNamer.getFullyQualifiedStubType");
  }

  /** The type name of the API callable class for this service method type. */
  public String getApiCallableTypeName(ServiceMethodType serviceMethodType) {
    return getNotImplementedString("SurfaceNamer.getApiCallableTypeName");
  }

  /** Return the type name used to discriminate oneof variants. */
  public String getOneofVariantTypeName(OneofConfig oneof) {
    return getNotImplementedString("SurfaceNamer.getOneofVariantTypeName");
  }

  /**
   * The formatted name of a type used in long running operations, i.e. the operation payload and
   * metadata,
   */
  public String getLongRunningOperationTypeName(ImportTypeTable typeTable, TypeModel type) {
    return getNotImplementedString("SurfaceNamer.getLongRunningOperationTypeName");
  }

  /** The type name for the gPRC request. */
  public String getAndSaveTypeName(ImportTypeTable typeTable, TypeModel type) {
    return getNotImplementedString("SurfaceNamer.getAndSaveTypeName");
  }

  public String getMessageTypeName(ImportTypeTable typeTable, MessageType message) {
    return ((ModelTypeTable) typeTable).getNicknameFor(TypeRef.of(message));
  }

  public String getEnumTypeName(ImportTypeTable typeTable, EnumType enumType) {
    return ((ModelTypeTable) typeTable).getNicknameFor(TypeRef.of(enumType));
  }

  public String getStreamTypeName(GrpcStreamingConfig.GrpcStreamingType type) {
    return getNotImplementedString("SurfaceNamer.getStreamTypeName");
  }

  public String getMockCredentialsClassName(Interface anInterface) {
    return getNotImplementedString("SurfaceNamer.getMockCredentialsClassName");
  }

  public String getFullyQualifiedCredentialsClassName() {
    return getNotImplementedString("SurfaceNamer.getFullyQualifiedCredentialsClassName");
  }

  /////////////////////////////////////// Resource names //////////////////////////////////////////

  public String getResourceParameterName(ResourceNameConfig resourceNameConfig) {
    return localVarName(getResourceTypeNameObject(resourceNameConfig));
  }

  public String getResourcePropertyName(ResourceNameConfig resourceNameConfig) {
    return publicMethodName(getResourceTypeNameObject(resourceNameConfig));
  }

  public String getResourceEnumName(ResourceNameConfig resourceNameConfig) {
    return getResourceTypeNameObject(resourceNameConfig).toUpperUnderscore().toUpperCase();
  }

  /** The parameter name of the IAM resource. */
  public String getIamResourceParamName(FieldModel field) {
    return localVarName(Name.upperCamel(field.getParentSimpleName()));
  }

  public String formatSpec() {
    return "%s";
  }

  /////////////////////////////////////// Path Template ////////////////////////////////////////

  /**
   * The name of a path template constant for the given collection, to be held in an API wrapper
   * class.
   */
  public String getPathTemplateName(
      InterfaceConfig interfaceConfig, SingleResourceNameConfig resourceNameConfig) {
    return inittedConstantName(resourceNameConfig.getEntityName().join("path").join("template"));
  }

  /** The name of a getter function to get a particular path template for the given collection. */
  public String getPathTemplateNameGetter(
      InterfaceConfig interfaceConfig, SingleResourceNameConfig resourceNameConfig) {
    return publicMethodName(
        Name.from("get").join(resourceNameConfig.getEntityName()).join("name").join("template"));
  }

  /** The name of the path template resource, in human format. */
  public String getPathTemplateResourcePhraseName(SingleResourceNameConfig resourceNameConfig) {
    return resourceNameConfig.getEntityName().toPhrase();
  }

  /** The function name to format the entity for the given collection. */
  public String getFormatFunctionName(
      InterfaceConfig interfaceConfig, SingleResourceNameConfig resourceNameConfig) {
    return staticFunctionName(
        Name.from("format").join(resourceNameConfig.getEntityName()).join("name"));
  }

  /**
   * The function name to parse a variable from the string representing the entity for the given
   * collection.
   */
  public String getParseFunctionName(String var, SingleResourceNameConfig resourceNameConfig) {
    return staticFunctionName(
        Name.from("parse", var, "from").join(resourceNameConfig.getEntityName()).join("name"));
  }

  /** The entity name for the given collection. */
  public String getEntityName(SingleResourceNameConfig resourceNameConfig) {
    return localVarName(resourceNameConfig.getEntityName());
  }

  /** The parameter name for the entity for the given collection config. */
  public String getEntityNameParamName(SingleResourceNameConfig resourceNameConfig) {
    return localVarName(resourceNameConfig.getEntityName().join("name"));
  }

  /////////////////////////////////////// Page Streaming ////////////////////////////////////////

  /** The formatted field name of a page streaming request token. */
  public String getRequestTokenFieldName(PageStreamingConfig pageStreaming) {
    return keyName(Name.from(pageStreaming.getRequestTokenField().getSimpleName()));
  }

  /** The formatted field name of a page streaming response token. */
  public String getResponseTokenFieldName(PageStreamingConfig pageStreaming) {
    return keyName(Name.from(pageStreaming.getResponseTokenField().getSimpleName()));
  }

  /** The formatted name of a page streaming resources field. */
  public String getResourcesFieldName(PageStreamingConfig pageStreaming) {
    return keyName(Name.from(pageStreaming.getResourcesFieldName()));
  }

  ///////////////////////////////////// Constant & Keyword ////////////////////////////////////////

  /** The name of the constant to hold the batching descriptor for the given method. */
  public String getBatchingDescriptorConstName(MethodModel method) {
    return inittedConstantName(Name.anyCamel(method.getSimpleName()).join("bundling_desc"));
  }

  /** The key to use in a dictionary for the given method. */
  public String getMethodKey(MethodModel method) {
    return keyName(method.asName());
  }

  /** The key to use in a dictionary for the given field. */
  public String getFieldKey(FieldModel field) {
    return keyName(field.getNameAsParameterName());
  }

  /** The path to the client config for the given interface. */
  public String getClientConfigPath(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getClientConfigPath");
  }

  /** The path to a config with a specified name. */
  public String getConfigPath(InterfaceConfig interfaceConfig, String name) {
    return getNotImplementedString("SurfaceNamer.getConfigPath");
  }

  /** The keyword controlling the visiblity, eg "public", "protected". */
  public String getVisiblityKeyword(VisibilityConfig visibility) {
    switch (visibility) {
      case PUBLIC:
        return "public";
      case PACKAGE:
        return "/* package-private */";
      case PRIVATE:
        return "private";
      default:
        throw new IllegalArgumentException("invalid visibility: " + visibility);
    }
  }

  /** The private access modifier for the current language. */
  public String getPrivateAccessModifier() {
    return "private";
  }

  /** The name of an RPC status code */
  public String getStatusCodeName(String code) {
    return privateMethodName(Name.upperUnderscore(code));
  }

  /** The name of the constant to hold the page streaming descriptor for the given method. */
  public String getPageStreamingDescriptorConstName(MethodModel method) {
    return inittedConstantName(Name.anyCamel(method.getSimpleName()).join("page_str_desc"));
  }

  /** The name of the constant to hold the page streaming factory for the given method. */
  public String getPagedListResponseFactoryConstName(MethodModel method) {
    return inittedConstantName(Name.anyCamel(method.getSimpleName()).join("page_str_fact"));
  }

  /** The string used to identify the method in the gRPC stub. Not all languages will use this. */
  public String getGrpcStubCallString(InterfaceModel apiInterface, MethodModel method) {
    return getNotImplementedString("SurfaceNamer.getGrpcStubCallString");
  }

  ///////////////////////////////////////// Imports ///////////////////////////////////////////////

  /** Returns true if the request object param type for the given field should be imported. */
  public boolean shouldImportRequestObjectParamType(FieldModel field) {
    return true;
  }

  /**
   * Returns true if the request object param element type for the given field should be imported.
   */
  public boolean shouldImportRequestObjectParamElementType(FieldModel field) {
    return true;
  }

  public String getServiceFileImportName(String filename) {
    return getNotImplementedString("SurfaceNamer.getServiceFileImportName");
  }

  public String getProtoFileImportName(String filename) {
    return getNotImplementedString("SurfaceNamer.getProtoFileImportName");
  }

  public String getGrpcTransportImportName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getGrpcTransportImportName");
  }

  public String getVersionIndexFileImportName() {
    return getNotImplementedString("SurfaceNamer.getVersionIndexFileImportName");
  }

  public String getTopLevelIndexFileImportName() {
    return getNotImplementedString("SurfaceNamer.getTopLevelIndexFileImportName");
  }

  public String getCredentialsClassImportName() {
    return getNotImplementedString("SurfaceNamer.getCredentialsClassImportName");
  }
  /////////////////////////////////// Docs & Annotations //////////////////////////////////////////

  /** The documentation name of a parameter for the given lower-case field name. */
  public String getParamDocName(String var) {
    return localVarName(Name.from(var));
  }

  /** Returns the language specific format of parameter documentation. */
  public String getParamDocText(String paramName, String paramTypeName, String text) {
    return getNotImplementedString("SurfaceNamer.getParamDocText");
  }

  /** Converts the given text to doc lines in the format of the current language. */
  public List<String> getDocLines(String text) {
    return CommonRenderingUtil.getDocLines(commentReformatter.reformat(text));
  }

  /**
   * Wrap the text when it is too long. By default wrap at 100 characters. If reformat is true, text
   * is also reformatted in the format of the current language.
   */
  public List<String> getWrappedDocLines(String text, boolean reformat) {
    return getWrappedDocLines(text, reformat, 100);
  }

  protected List<String> getWrappedDocLines(String text, boolean reformat, int maxWidth) {
    if (reformat) {
      return CommonRenderingUtil.getDocLines(getCommentReformatter().reformat(text), maxWidth);
    }
    return CommonRenderingUtil.getDocLines(text, maxWidth);
  }

  /** Converts the given text to doc lines in the format of the current language. */
  public List<String> getDocLines(Schema schema) {
    StringBuffer description = new StringBuffer(schema.description());
    if (schema.additionalProperties() != null
        && !Strings.isNullOrEmpty(schema.additionalProperties().reference())
        && !Strings.isNullOrEmpty(schema.additionalProperties().description())) {
      description
          .append("\nThe key for the map is: ")
          .append(schema.additionalProperties().description());
    }
    return CommonRenderingUtil.getDocLines(commentReformatter.reformat(description.toString()));
  }

  /** Provides the doc lines for the given field in the current language. */
  public List<String> getDocLines(FieldModel field) {
    return getDocLines(field.getScopedDocumentation());
  }

  /** Provides the doc lines for the given method element in the current language. */
  public List<String> getDocLines(MethodModel method, MethodConfig methodConfig) {
    return getDocLines(method.getScopedDescription());
  }

  /** The doc lines that declare what exception(s) are thrown for an API method. */
  public List<String> getThrowsDocLines(MethodConfig methodConfig) {
    return new ArrayList<>();
  }

  /** The doc lines that describe the return value for an API method. */
  public List<String> getReturnDocLines(
      TransformationContext context, MethodContext methodContext, Synchronicity synchronicity) {
    return Collections.singletonList(getNotImplementedString("SurfaceNamer.getReturnDocLines"));
  }

  public String getReleaseAnnotation(ReleaseLevel releaseLevel) {
    return getNotImplementedString("SurfaceNamer.getReleaseAnnotation");
  }

  /** The name of a type with with qualifying articles and descriptions. */
  public String getTypeNameDoc(ImportTypeTable typeTable, TypeModel type) {
    return getNotImplementedString("SurfaceNamer.getTypeNameDoc");
  }

  //////////////////////////////////////// File names ////////////////////////////////////////////

  /** The file name for an API interface. */
  public String getServiceFileName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getServiceFileName");
  }

  public String getSourceFilePath(String path, String publicClassName) {
    return getNotImplementedString("SurfaceNamer.getSourceFilePath");
  }

  /** The language-specific file name for a proto file. */
  public String getProtoFileName(String fileSimpleName) {
    return getNotImplementedString("SurfaceNamer.getProtoFileName");
  }

  /** The list of proto files for the given service. Currently, only for Node.js. */
  public String getProtoListFileName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getProtoListFileName");
  }

  ////////////////////////////////////////// Test /////////////////////////////////////////////

  public String getTestPackageName() {
    return getNotImplementedString("SurfaceNamer.getTestPackageName");
  }

  public String getTestPackageName(TestKind testKind) {
    return getNotImplementedString("SurfaceNamer.getTestPackageName");
  }

  /** The test case name for the given method. */
  public String getTestCaseName(SymbolTable symbolTable, MethodModel method) {
    Name testCaseName = symbolTable.getNewSymbol(method.asName().join("test"));
    return publicMethodName(testCaseName);
  }

  public String getAsyncTestCaseName(SymbolTable symbolTable, MethodModel method) {
    return getNotImplementedString("SurfaceNamer.getAsyncTestCaseName");
  }

  /** The exception test case name for the given method. */
  public String getExceptionTestCaseName(SymbolTable symbolTable, MethodModel method) {
    Name testCaseName =
        symbolTable.getNewSymbol(method.asName().join(Name.from("exception", "test")));
    return publicMethodName(testCaseName);
  }

  /** The unit test class name for the given API interface. */
  public String getUnitTestClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.anyCamel(getInterfaceName(interfaceConfig), "Client", "Test"));
  }

  /** The smoke test class name for the given API interface. */
  public String getSmokeTestClassName(InterfaceConfig interfaceConfig) {
    return publicClassName(Name.upperCamel(getInterfaceName(interfaceConfig), "Smoke", "Test"));
  }

  /** The class name of the mock gRPC service for the given API interface. */
  public String getMockServiceClassName(InterfaceModel apiInterface) {
    return publicClassName(Name.upperCamelKeepUpperAcronyms("Mock", apiInterface.getSimpleName()));
  }

  /** The class name of a variable to hold the mock gRPC service for the given API interface. */
  public String getMockServiceVarName(InterfaceModel apiInterface) {
    return localVarName(Name.upperCamelKeepUpperAcronyms("Mock", apiInterface.getSimpleName()));
  }

  /** The class name of the mock gRPC service implementation for the given API interface. */
  public String getMockGrpcServiceImplName(InterfaceModel apiInterface) {
    return publicClassName(
        Name.upperCamelKeepUpperAcronyms("Mock", apiInterface.getSimpleName(), "Impl"));
  }

  /** Inject random value generator code to the given string. */
  public String injectRandomStringGeneratorCode(String randomString) {
    return getNotImplementedString("SurfaceNamer.injectRandomStringGeneratorCode");
  }

  ////////////////////////////////////////// Examples ////////////////////////////////////////////

  /** The name of the example package */
  public String getExamplePackageName() {
    return getNotImplementedString("SurfaceNamer.getExamplePackageName");
  }

  /** The local (unqualified) name of the example package */
  public String getLocalExamplePackageName() {
    return getNotImplementedString("SurfaceNamer.getLocalExamplePackageName");
  }

  /**
   * The name of example of the constructor for the service client. The client is VKit generated,
   * not GRPC.
   */
  public String getApiWrapperClassConstructorExampleName(InterfaceConfig interfaceConfig) {
    return getApiWrapperClassConstructorName(interfaceConfig);
  }

  /** The name of the example for the paged callable variant. */
  public String getPagedCallableMethodExampleName(MethodModel method) {
    return getPagedCallableMethodName(method);
  }

  /** The name of the example for the plain callable variant. */
  public String getCallableMethodExampleName(MethodModel method) {
    return getCallableMethodName(method);
  }

  /** The name of the example for the operation callable variant of the given method. */
  public String getOperationCallableMethodExampleName(MethodModel method) {
    return getOperationCallableMethodName(method);
  }

  /** The name of the example for the method. */
  public String getApiMethodExampleName(InterfaceConfig interfaceConfig, MethodModel method) {
    return getApiMethodName(
        Name.anyCamel(interfaceConfig.getInterfaceModel().getSimpleName()),
        VisibilityConfig.PUBLIC);
  }

  /** The name of the example for the async variant of the given method. */
  public String getAsyncApiMethodExampleName(MethodModel method) {
    return getAsyncApiMethodName(method, VisibilityConfig.PUBLIC);
  }

  /**
   * The name of the example of the GRPC streaming surface method which can call the given API
   * method.
   */
  public String getGrpcStreamingApiMethodExampleName(
      InterfaceConfig interfaceConfig, MethodModel method) {
    return getGrpcStreamingApiMethodName(method, VisibilityConfig.PUBLIC);
  }

  /** The example name of the IAM resource getter function. */
  public String getIamResourceGetterFunctionExampleName(
      InterfaceConfig interfaceConfig, FieldModel field) {
    return getIamResourceGetterFunctionName(field);
  }

  /** The file name for the example of an API interface. */
  public String getExampleFileName(InterfaceConfig interfaceConfig) {
    return getNotImplementedString("SurfaceNamer.getExampleFileName");
  }

  /**
   * Translate C-printf-spec and a list of args into those expected by the language's format
   * utilities.
   *
   *
For languages that prefer interpolating the arguments in the format string, the returned
   * list will only have one element, the interpolated format string.
   *
   *
For languages that prefer using placeholders in the format string, the returned list will be
   * a format string followed by all the arguments to replace the placeholders.
   */
  public ImmutableList<String> getInterpolatedFormatAndArgs(String spec, List<String> args) {
    StringBuilder sb = new StringBuilder();
    int p = 0;
    while (true) {
      int pos = spec.indexOf('%', p);
      if (pos == -1) {
        sb.append(spec, p, spec.length());
        return ImmutableList.<String>builder()
            .add(
                sb.toString()
                    .replace("\\", "\\\\")
                    .replace("\"", "\\\"")
                    .replace("\t", "\\t")
                    .replace("\n", "\\n"))
            .addAll(args)
            .build();
      } else {
        sb.append(spec, p, pos);
      }
      if (spec.startsWith("%s", pos)) {
        sb.append("%s");
        p = pos + 2;
      } else if (spec.startsWith("%%", pos)) {
        sb.append("%%");
        p = pos + 2;
      } else {
        throw new IllegalArgumentException(String.format("bad format verb: %s", spec));
      }
    }
  }

  /** Returns the formatted expression to nicely print a field of a variable. */
  public String getFormattedPrintArgName(
      ImportTypeTable typeTable, TypeModel type, String variable, List<String> accessors) {
    if (accessors.isEmpty()) {
      return variable;
    }
    return variable + String.join("", accessors);
  }

  /**
   * Returns the expression to access an element of a collection by index.
   *
   *
Note that the returned value includes the language-specific syntax for accessing an element
   * of a collection. For example, the returned value will be `.get(i)` in Java, and `[i]` in PHP.
   */
  public String getIndexAccessorName(int index) {
    return getNotImplementedString("SurfaceNamer.getIndexAccessorName");
  }

  /**
   * Returns the expression to access a field of a protobuf object.
   *
   *
Note that the returned value includes not only the field name, but also the
   * language-specific syntax for accessing a protobuf object field. For example, the returned value
   * will be `.getField()` in Java, and `->getField()` in PHP.
   */
  public String getFieldAccessorName(FieldModel field) {
    return getNotImplementedString("SurfaceNamer.getFieldAccessorName");
  }

  /**
   * Returns the expression to get the value of a map entry by its key.
   *
   *
Note that the returned value includes the language-specific syntax for accessing a map entry
   * by key. For example, the returned value will be `.get("key")` in Java, and `["key"]` in Python.
   */
  public String getMapKeyAccessorName(TypeModel keyType, String key) {
    return getNotImplementedString("SurfaceNamer.getMapKeyAccessorName");
  }

  public String getSampleResponseVarName(MethodContext context, CallingForm form) {
    MethodConfig config = context.getMethodConfig();
    if (config.getPageStreaming() != null) {
      return "responseItem";
    }
    if (config.getGrpcStreaming() != null) {
      GrpcStreamingConfig.GrpcStreamingType type = config.getGrpcStreaming().getType();
      if (type == GrpcStreamingConfig.GrpcStreamingType.ServerStreaming
          || type == GrpcStreamingConfig.GrpcStreamingType.BidiStreaming) {
        return "responseItem";
      }
    }
    return "response";
  }

  public Set<String> getSampleUsedVarNames(MethodContext context, CallingForm form) {
    // TODO: Change this to an empty set once the PHP, Java, and Python implementations of this
    // method are in place to define these identifiers. These values are here for now so we don't
    // break those languages in the interim.
    return ImmutableSet.of("response", "responseItem");
  }

  public String getSampleFunctionName(MethodModel method) {
    return getApiMethodName(Name.from("sample").join(method.asName()), VisibilityConfig.PRIVATE);
  }

  // TODO(hzyi): this method doesn't fit very well in SurfaceNamer. So far we don't have a
  // better place for this logic but consider moving this out when we implement default
  // calling forms.
  public List<CallingForm> getCallingForms(MethodContext context) {
    return Collections.singletonList(CallingForm.Generic);
  }

  public List<CallingForm> getMatchingCallingForms(MethodContext context, String callingPattern) {
    if (callingPattern.isEmpty() || SampleConfig.DEFAULT_CALLING_PATTERN.equals(callingPattern)) {
      return Collections.singletonList(getDefaultCallingForm(context));
    }
    return getCallingForms(context)
        .stream()
        .filter(c -> c.toLowerUnderscore().matches(callingPattern))
        .collect(ImmutableList.toImmutableList());
  }

  public CallingForm getDefaultCallingForm(MethodContext context) {
    return CallingForm.Generic;
  }

  public boolean usesAsyncAwaitPattern(CallingForm form) {
    return false;
  }

  /////////////////////////////////// Transport Protocol /////////////////////////////////////////

  public Name getTransportProtocolName(TransportProtocol protocol) {
    switch (protocol) {
      case HTTP:
        return Name.from("http", "json");
      case GRPC:
      default:
        return Name.from("grpc");
    }
  }

  public String getInstantiatingChannelProvider(TransportProtocol protocol) {
    return publicClassName(
        Name.from("instantiating")
            .join(getTransportProtocolName(protocol).join("channel").join("provider")));
  }

  public String getTransportProvider(TransportProtocol protocol) {
    Name protocolName = getTransportProtocolName(protocol);
    return publicClassName(protocolName.join("transport").join("provider"));
  }

  public String getDefaultTransportProviderBuilder(TransportProtocol protocol) {
    Name protocolName = getTransportProtocolName(protocol);
    return privateMethodName(
        Name.from("default").join(protocolName).join("transport").join("provider").join("builder"));
  }

  public String getDefaultChannelProviderBuilder(TransportProtocol protocol) {
    Name protocolName = getTransportProtocolName(protocol);
    return privateMethodName(
        Name.from("default").join(protocolName).join("channel").join("provider").join("builder"));
  }

  public String getTransporNameGetMethod(TransportProtocol protocol) {
    Name protocolName = getTransportProtocolName(protocol);
    return privateMethodName(Name.from("get").join(protocolName).join("transport").join("name"));
  }

  public String getTransportClassName(TransportProtocol protocol) {
    Name protocolName = getTransportProtocolName(protocol);
    return publicClassName(protocolName.join(Name.anyCamel("TransportChannel")));
  }

  ////////////////////////////////////////// Utility /////////////////////////////////////////////

  /** Indicates whether the specified method supports retry settings. */
  public boolean methodHasRetrySettings(MethodConfig methodConfig) {
    return true;
  }

  /** Indicates whether the specified method supports timeout settings. */
  public boolean methodHasTimeoutSettings(MethodConfig methodConfig) {
    return true;
  }

  /** Make the given type name able to accept nulls, if it is a primitive type */
  public String makePrimitiveTypeNullable(String typeName, FieldModel type) {
    return typeName;
  }

  /** Is this type a primitive, according to target language. */
  public boolean isPrimitive(TypeModel type) {
    return type.isPrimitive();
  }

  /** Is this type a primitive, according to target language. */
  public boolean isPrimitive(FieldModel type) {
    return type.isPrimitive();
  }

  /** The default value for an optional field, null if no default value required. */
  public String getOptionalFieldDefaultValue(FieldConfig fieldConfig, MethodContext context) {
    return getNotImplementedString("SurfaceNamer.getOptionalFieldDefaultValue");
  }

  public String getToStringMethod() {
    return getNotImplementedString("SurfaceNamer.getToStringMethod");
  }
}


text:
Khalid Doudin
NMR Specialist and Lead Undergraduate Projects Officer, Chemical Eng & Applied Chemistry
Contract Research Fellow, Chemical Eng & Applied Chemistry
Aston Institute of Materials Research (AIMR)
Dr Doudin is an organic chemist who joined the school of Chemical Engineering and Applied Chemistry at Aston University in May 2004. He started with us as a research fellow for few years then as Nuclear Magnetic Resonance (NMR) and Characterisation Specialist and Undergraduate Projects Officer.
His research involves analysis and characterisation of organic materials, using a variety of spectroscopic and thermal methodologies, very often with the aid of different chromatographic techniques. Most of his research has been focused on the performance of natural additives (such as, Vitamin E, Rosemary extracts, Caffeic acid derivatives …) in stabilising polymers and bio-oils.
A number of collaborations both within Aston and externally started. Being an NMR specialist with extensive knowledge of other characterisation techniques working with different groups has allowed Dr Doudin to add an extra dimension to the school research.
PhD: 2001, University of Bergen
MSc: 1997, University of Bergen
BSc, 1995, Birzeit University
2013 - Present: Nuclear Magnetic Resonance (NMR) and Characterisation Specialist and Lead Undergraduate Projects Officer
2014 - Present: Magnetic Resonance Safety Officer
2004 - 2013: Research Fellow, Aston University.
2002 - 2004: Research Fellow, The University of Greenwich
Nuclear Magnetic Resonance (CH2101)
Final Year MEng Research Projects (CE4011)
Chemistry Literature Review Projects (CH3117)
Research Projects/Collaborations
A project on the oxidation and stability of vegetable oils on kitchen metal surfaces, my work was mainly focused on characterisation and understating retarding the polymerisation of unsaturated hydrocarbon moieties of the oils and the influence of stabilisers (antioxidants) on limiting the influence on metals surfaces on the oil polymerisation / toughening process.
K. Doudin, S. Al-Malaika, H. Dole, T. Stirling, M. Sharples, Effect of contact surfaces on the thermal and photooxidation of dehydrated castor oil, Polymer Degradation and Stability 96(4) (2011) 438-454.
In another project I have worked on in the use of natural antioxidants extracted from rosemary (polyphenols) in oils and polyolefins industries, in collaboration with Boots, Croda, Lubrizol and others. The targeted antioxidants were chemically modified to suite the different industries, characterised and their effectiveness was tested in the different systems.
K. Doudin, S. Al-Malaika, H.H. Sheena, V. Tverezovskiy, P. Fowler, New genre of antioxidants from renewable natural resources: Synthesis and characterisation of rosemary plant-derived antioxidants and their performance in polyolefins, Polymer Degradation and Stability 130 (2016) 126-134.
I have worked on a project on the stabilisation of medical implants (Tibias) made of Polyethylene (UHMWPE) by Vitamin E. What is happening to the Vitamin E during the making process of medical implants was the focus of the projects. The formed products were extracted, separated, characterised, quantified and identified.
K. Doudin, S. Al-Malaika, Vitamin E-stabilised UHMWPE for orthopaedic implants: Quantitative determination of vitamin E and characterisation of its transformation products, Polymer Degradation and Stability 125 (2016) 59-75.
One project involves the NMR characterisation of reactive (graftable) functional groups on polyethylene and ethylene propylene rubber.
K. Doudin, A. Ahmad, S. Al-Malaika, Reactive processing of polymers: Structural characterisation of products by H-1 and C-13 NMR spectroscopy for glycidyl methacrylate grafting onto EPR in the absence and presence of a reactive co-monomer, Polymer Degradation and Stability 94(10) (2009) 1599-1614.
A collaborative project on new approach to prepare phase change microcapsules using carbon-based particles via Pickering emulsions for energy storage applications
W. Gondora, K. Doudin, D.J. Nowakowski, B. Xiao, Y.L. Ding, T. Bridgwater, Q.C. Yuan, Encapsulation of phase change materials using rice-husk-char, Applied Energy 182 (2016) 274-281.
With Prof. K W Törnroos, University of Bergen, Norway, worked on completing unfinished work for my PhD study.
K. Doudin, K.W. Törnroos, Selenium carboxylic acids betaine; 3,3′,3″- selenotris(propanoic acid) betaine, Journal of Molecular Structure 1137 (2017) 506- 511.
K. Doudin, K.W. Törnroos, 2,2′,2″-Thiotris(acetic acid) betaine, and 2,2′,2″- selenotris(acetic acid) betaine, Journal of Molecular Structure 1134 (2017) 611-616.
On a project with School of Pharmacy, University of Wolverhampton worked on the effect of polymers on the release drug from tablets, drug-polymers chemical interactions were studied using spectroscopic and differential scanning calorimetry analysis.
E. Al-Ani, C. Martin, S. T. Britland, K. Doudin, D. J. Hill, The effect of the source and the concentration of polymers on the release of chlorhexidine from muco adhesive buccal tablets, Saudi Pharmaceutical Journal (2019)
With Dr Abul Hossain, MECHANICAL ENGINEERING & DESIGN worked spectroscopic characterisations of Biodiesel samples.
A. Hossain K. Masera, P. Davies, K. Doudin, Experimental investigation of 2-Butoxyethanol as biodiesel additive, Journal of the Energy Institute, Submitted (May 2019)
Email: K.Doudin@aston.ac.uk
Room number: MB123
Fingerprint Dive into the research topics where Khalid Doudin is active. These topic labels come from the works of this person. Together they form a unique fingerprint.
Carboxylic Acids Chemical Compounds
Betaine Chemical Compounds
Nuclear magnetic resonance Chemical Compounds
Acetic Acid Chemical Compounds
Atoms Chemical Compounds
Hydrogen bonds Chemical Compounds
Dimers Chemical Compounds
Antioxidants Chemical Compounds
The Effect of the Source and the Concentration of polymers on the Release of Chlorhexidine from Mucoadhesive Buccal Tablets
Al-ani, E., Martin, C., Britland, S. T., Doudin, K. & Hill, D. J., 1 Sep 2019, In : Saudi Pharmaceutical Journal. 27, 6, p. 756-766 11 p.
2,2′,2″-Thiotris(acetic acid) betaine, S(CH 2 COOH) 2 (CH 2 COO), and 2,2′,2″-selenotris(acetic acid) betaine, Se(CH 2 COOH) 2 (CH 2 COO)
Doudin, K. & Törnroos, K., 15 Apr 2017, In : Journal of Molecular Structure. 1134, p. 611–616 6 p.
Selenium carboxylic acids betaine; 3,3′,3″-selenotris(propanoic acid) betaine, Se(CH 2 CH 2 COOH) 2 (CH 2 CH 2 COO)
Doudin, K. & Törnroos, K., 5 Jun 2017, In : Journal of Molecular Structure. 1137, p. 506–511 6 p.
Carboxylic Acids
Encapsulation of phase change materials using rice-husk-char
Gondora, W., Doudin, K., Nowakoski, D. J., Xiao, B., Ding, Y., Bridgwater, T. & Yuan, Q., 15 Nov 2016, In : Applied Energy. 182, p. 274-281 8 p.
Phase change materials
New genre of antioxidants from renewable natural resources: synthesis and characterisation of rosemary plant-derived antioxidants and their performance in polyolefins
Doudin, K., Al-Malaika, S., Sheena, H. H., Tverezovskiy, V. & Fowler, P., Aug 2016, In : Polymer Degradation and Stability. 130, p. 126-134 9 p.
1 Participation in conference
30th Polymer Degradation Discussion Group Conference
Khalid Doudin (Participant)
Contact Khalid Doudin

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: Hi can someone help explain why my code isn't working?

function Books(title, author, pages, info) {
  this.title = title
  this.author = author
  this.pages = pages
  this.info = function() {
    return this.title + 'by' + this.author + ',' + this.pages + 'pages' + ',' + 'have read!'
  }
}

var books = new Books('Behold a Pale Horse', 'Bill Cooper', 505)

books.info()

A: I was also able to run it with no problems here. I would suggest a few edits, just to make the code and printed text more readable:

    function Books(title, author, pages, info) {
      this.title = title;
      this.author = author;
      this.pages = pages;
      this.info = () => {
        return this.title + ' by ' + this.author + ', ' + this.pages + ' pages' + ',' + ' have read!';
      }
    }

    var books = new Books('Behold a Pale Horse', 'Bill Cooper', 505);

    console.log(books.info());

A: it is working, probably you meant it does not print anything?
try
console.log(books.info())

A: Try:
console.log(books.info())

A: Your code is absolutely correct.
The reason why it isn't printing the output on the console is that you haven't used console.log(books.info())
If you use Chrome's console you wouldn't even need to use console.log()

redpajama_set_name: RedPajamaStackExchange


text:
Discussion of some "trap signatures" observed by admittance spectroscopy in CdTe thin-film solar cells
Li, J. V., Johnston, S. W., Li, X., Albin, D. S., Gessert, T. A. & Levi, D. H., 2010 九月 15, 於: Journal of Applied Physics. 108, 6, 064501.
Discussion on Approaches for Reusing Unused Military Base in Dapeng Bay Scenic Area, Taiwan
Lin, H-W. & Fu Chao-Ching, 2009
Discussion on electrical characteristics of i-In0.13Ga0.87N p-i-n photovoltaics by using a single/multi-antireflection layer
Cheng Lee, H., Kuin Su, Y., Chuang, W. K., Ching Lin, J., Chin Huang, K., Cheng Cheng, Y. & Jen Chang, K., 2010 七月 1, 於: Solar Energy Materials and Solar Cells. 94, 7, p. 1259-1262 4 p.
Discussion on How the Choice of Action Figure's Facial Expression Affects Consumers' Perception
Chen, H-J. & Liou, C-F., 2020 十一月, 2020 IEEE International Conference on Applied System Innovation (IEEE ICASI 2020) & Innovation, Communication and Engineering (IEEE ICICE 2020). Taitung, Taiwan
Discussion on slow light in magnetized plasma by electromagnetically induced transparency
Kawamori, E., 2010, 37th EPS Conference on Plasma Physics 2010, EPS 2010. 卷 3. p. 1564-1567 4 p.
Discussion on sustainable land use allocation toward the sustainable city–A practice on Linco New Town
Chang, H-S. & Chiu, S. L., 2013, 於: Procedia Environmental Sciences. 17, p. 408-417
Discussion on the Effect of Bedding on Sleep Postures
Lin, Y. T., Chen, C. H. & Wu, F. G., 2020, Human Systems Engineering and Design II - Proceedings of the 2nd International Conference on Human Systems Engineering and Design: Future Trends and Applications, IHSED 2019. Ahram, T., Karwowski, W., Pickl, S. & Taiar, R. (編輯). Springer Verlag, p. 724-729 6 p. (Advances in Intelligent Systems and Computing; 卷 1026).
Discussion on the error of wave forecast by Markov chain theory
Lee, B. C., Wu, L. C. & Doong, D. J., 2007 十二月 3, Proceedings of The Seventeenth 2007 International Offshore and Polar Engineering Conference, ISOPE 2007. p. 1965-1969 5 p. (Proceedings of the International Offshore and Polar Engineering Conference).
Discussion on the impact factor of agricultural land in Taiwan–Case study of Yunlin, Chiayi, and Tainan
Chen, X. R. & Chang, H-S., 2013, 於: Procedia Environmental Sciences. 17, p. 28-36
Discussion on the important key factor of storm transposition method under long duration Typhoon
Liu, C. C., Yang, T. C., Lin, Y. C. & Yu, P. S., 2012 三月 1, 於: Taiwan Water Conservancy. 60, 1, p. 1-14 14 p.
Discussion on the mining pollutionand geologic backgroundin Yinyang seaat the northeast cornerof Taiwan
Wang, S. C., Chen, S. F., Shen, Y. H. & Chen, C. Y., 2013, Environmental Protection and Resources Exploitation. p. 81-87 7 p. (Advanced Materials Research; 卷 807-809).
Discussions on simulation models for gyrokinetic MHD: A kinetic-fluid model and a gyrokinetic PIC model (P4.150)
Nishimura, Y. & Cheng, C. Z., 2010 十二月 1, 37th EPS Conference on Plasma Physics 2010, EPS 2010. p. 1310-1313 4 p. (37th EPS Conference on Plasma Physics 2010, EPS 2010; 卷 2).
Discuss the epithelial to mesenchymal transition by the view of mechanics
Huang, H. K. & Yeh, M. L., 2015 一月 1, 1st Global Conference on Biomedical Engineering and 9th Asian-Pacific Conference on Medical and Biological Engineering. Su, F-C., Yeh, M-L. & Wang, S-H. (編輯). Springer Verlag, p. 69-71 3 p. (IFMBE Proceedings; 卷 47).
Disease activity affects all domains of quality of life in patients with rheumatoid arthritis and is modified by disease duration
Chiu, Y. M., Lai, M. S., Lin, H. Y., Lang, H. C., Lee, L. J. H. & Wang, J. D., 2014, 於: Clinical and Experimental Rheumatology. 32, 6, p. 898-903 6 p.
Disease and economic burden for rare diseases in Taiwan: A longitudinal study using Taiwan's National Health Insurance Research Database
Hsu, J. C., Wu, H. C., Feng, W. C., Chou, C. H., Lai, E. C. C. & Lu, C. Y., 2018 九月, 於: PloS one. 13, 9, e0204206.
Disease animal models of TDP-43 proteinopathy and their pre-clinical applications
Liu, Y. C., Chiang, P. M. & Tsai, K. J., 2013 十月 9, 於: International journal of molecular sciences. 14, 10, p. 20079-20111 33 p.
Disease burden of invasive listeriosis and molecular characterization of clinicalisolates in Taiwan, 2000-2013
Huang, Y. T., Ko, W. C., Chan, Y. J., Lu, J. J., Tsai, H. Y., Liao, C. H., Sheng, W. H., Teng, L. J. & Hsueh, P. R., 2015 十一月 10, 於: PloS one. 10, 11, e0141241.
Disease-related disability burden: a comparison of seven chronic conditions in middle-aged and older adults
Chou, C. Y., Chiu, C. J., Chang, C. M., Wu, C. H., Lu, F. H., Wu, J. S. & Yang, Y. C., 2021 十二月, 於: BMC geriatrics. 21, 1, 201.
Disease risk prediction by mining personalized health trend patterns: A case study on diabetes
Lan, G. C., Lee, C. H., Lee, Y. Y., Tseng, V. S., Chin, C. Y., Day, M. L., Wang, S. C., Chang, C. N., Cheng, S. Y. & Wu, J. S., 2012 十二月 1, Proceedings - 2012 Conference on Technologies and Applications of Artificial Intelligence, TAAI 2012. p. 27-32 6 p. 6395001. (Proceedings - 2012 Conference on Technologies and Applications of Artificial Intelligence, TAAI 2012).
Diseases caused by enterovirus 71 infection
Lee, T. C., Guo, H. R., Su, H. J. J., Yang, Y. C., Chang, H. L. & Chen, K. T., 2009 十月, 於: Pediatric Infectious Disease Journal. 28, 10, p. 904-910 7 p.
Disease severity at the first hospitalization as a predictor for mechanical ventilation dependency in elderly patients with chronic obstructive pulmonary disease
Liao, K. M., Lin, W. C., Lin, T. C., Li, C. Y. & Yang, Y. H. K., 2014 十一月 28, 於: Tohoku Journal of Experimental Medicine. 234, 4, p. 263-269 7 p.
Disease tolerance to infection: the immune defense strategy of mitoribosome targeting
Wu, L. S. H. & Wang, J. Y., 2021 七月, 於: Cellular and Molecular Immunology. 18, 7, p. 1626-1627 2 p.
研究成果: Comment/debate › 同行評審
Disentanglement of two harmonic oscillators in relativistic motion
Lin, S. Y., Chou, C. H. & Hu, B. L., 2008 十二月 2, 於: Physical Review D - Particles, Fields, Gravitation and Cosmology. 78, 12, 125025.
Disfluency correction of spontaneous speech using conditional random fields with variable length features
Yeh, J. F., Wu, W. Y. & Wu, C. H., 2006, p. 173-187. 15 p.
Disfluency correction of spontaneous speech using conditional random fields with variable-length features
Yeh, J. F., Wu, C. H. & Wu, W. Y., 2007, International Speech Communication Association - 8th Annual Conference of the International Speech Communication Association, Interspeech 2007. p. 549-552 4 p. (Proceedings of the Annual Conference of the International Speech Communication Association, INTERSPEECH; 卷 1).
Dishevelled 1-Regulated Superpotent Cancer Stem Cells Mediate Wnt Heterogeneity and Tumor Progression in Hepatocellular Carcinoma
Liao, W. Y., Hsu, C. C., Chan, T. S., Yen, C. J., Chen, W. Y., Pan, H. W. & Tsai, K. K., 2020 三月 10, 於: Stem Cell Reports. 14, 3, p. 462-477 16 p.
Disilanylketenes and -bisketenes
Sung, K-S. & Tidwell, T. T., 1997 一月 7, 於: Organometallics. 16, 1, p. 78-85 8 p.
Disinfection efficiency of hospital infectious disease wards with chlorine dioxide and hypochlorous acid
Lu, M. C., Chen, P. L., Huang, D. J., Liang, C. K., Hsu, C. S. & Liu, W. T., 2021 三月, 於: Aerobiologia. 37, 1, p. 29-38 10 p.
Disintegrin variants and pharmaceutical uses thereof
Chuang, W-J., 2011 二月 10, 專利號 2477727
研究成果: Patent
Chuang, W-J., 2009 七月 29, 專利號 153383
Chuang, W-J., 2009 十月 13, 專利號 291711
Chuang, W-J., 2012 三月 30, 專利號 577998
Chuang, W-J., 1800, 專利號 I392738
Chuang, W-J., 2009 十二月 2, 專利號 EP 2124548
Chuang, W-J., 2008 八月 7, 專利號 7943728
Chuang, W-J., 2013 三月 28, 專利號 HK1136160
Chuang, W-J., 2009 七月 23, 專利號 60/871,854
Chuang, W-J., 1800, 專利號 8183201
Disk-type piezoelectric transformer of a Na 0.5K 0.5NbO 3-CuNb 2O 6 lead-free ceramic for driving T5 fluorescent lamp
Yang, M. R., Chu, S. Y., Chan, I. H. & Yang, S. L., 2012 五月 5, 於: Journal of Alloys and Compounds. 522, p. 3-8 6 p.
Disk-type piezoelectric transformer of the CuF2-doped potassium sodium niobate lead-free ceramics for driving LED bar
Weng, C. M., Chu, S-Y., Tsai, C. C. & Hong, C. S., 2015 一月 1, 22nd International Display Workshops, IDW 2015. International Display Workshops, p. 792-793 2 p. (Proceedings of the International Display Workshops; 卷 2).
Dislocation After Total Hip Arthroplasty Among Patients With Developmental Dysplasia of the Hip
Wang, L., Trousdale, R. T., Ai, S., An, K. N., Dai, K. & Morrey, B. F., 2012 五月, 於: Journal of Arthroplasty. 27, 5, p. 764-769 6 p.
Dislocation inside, outside, or on the interface of an anisotropic elliptical inclusion
Yen, W. J., Hwu, C. & Liang, Y. K., 1995 六月, 於: Journal of Applied Mechanics, Transactions ASME. 62, 2, p. 306-311 6 p.
Dislocation reduction in nitride-based Schottky diodes by using multiple MgxNy/GaN nucleation layers
Lee, K. H., Chang, P. C., Chang, S-J., Su, Y. K., Wang, Y. C., Yu, C. L. & Kuo, C. H., 2010 三月 1, 於: Thin Solid Films. 518, 10, p. 2839-2842 4 p.
Dislocation reduction through nucleation and growth selectivity of metal-organic chemical vapor deposition GaN
Zhang, W., Liu, P., Jackson, B., Sun, T., Huang, S. J., Hsu, H. C., Su, Y. K., Chang, S. J., Li, L., Li, D., Wang, L., Hu, X. & Xie, Y. H., 2013 四月 14, 於: Journal of Applied Physics. 113, 14, 144908.
Disorder and flux pinning in superconducting pnictide single crystals
Van Der Beek, C. J., Rizza, G., Konczykowski, M., Fertey, P., Monnet, I., Okazaki, R., Kato, T., Hashimoto, K., Shimozawa, M., Shishido, H., Yamashita, M., Ishikado, M., Kito, H., Iyo, A., Eisaki, H., Shamoto, S., Shibauchi, T. & Matsuda, Y., 2010 十二月, 於: Physica C: Superconductivity and its applications. 470, SUPPL.1, p. S385-S386
Disorder effects in electronic structure of substituted transition metal compounds
Sarma, D. D., Chainani, A., Krishnakumar, S. R., Vescovo, E., Carbone, C., Eberhardt, W., Rader, O., Jung, C., Gudat, W., Srikanth, H. & Raychaudhuri, A. K., 1998, 於: Physical review letters. 80, 18, p. 4004-4007 4 p.
Disorder-induced bulk superconductivity in ZrTe3 single crystals via growth control
Zhu, X., Lv, B., Wei, F., Xue, Y., Lorenz, B., Deng, L., Sun, Y. & Chu, C. W., 2013 一月 10, 於: Physical Review B - Condensed Matter and Materials Physics. 87, 2, 024508.
Disorder-induced short-range ferromagnetism and cluster spin-glass state in sol-gel derived La0.7 Ca0.3 Mn1-x Cdx O3 (0≤x≤0.2)
Karmakar, S., Taran, S., Chaudhuri, B. K., Sakata, H., Sun, C. P., Huang, C. L. & Yang, H. D., 2006, 於: Physical Review B - Condensed Matter and Materials Physics. 74, 10, 104407.
Disorder-induced variability of transport properties of sub-5 nm-wide graphene nanoribbons
Poljak, M., Wang, M., Song, E. B., Suligoj, T. & Wang, K. L., 2013, 於: Solid-State Electronics. 84, p. 103-111 9 p.


Trigger warning: disordered eating, Jamie Oliver, fatphobia.
In the spring of 2005, Jamie Oliver began his war on British school dinners, and children across the country were forced to try and eat a bit healthier, whether they wanted to or not.
I was 12 at the time, and yeah – I probably did need a bit of help with healthy eating. I'd stopped eating meat less than a year previously, and replaced the meat largely with carbs and cheese. Which is tasty, but not great for growing children. My school had already stopped letting us fill our Pot Noodles in the canteens before Jamie got involved, but he went one step further. He took our chips.
I'll forever be bitter about this. I know chips aren't the healthiest of foods and I know that they shouldn't have been my midday sustenance for the best part of two years. But the main problem with Jamie's war on school dinners isn't that he took away turkey twizzlers and my beloved fried potato products. The problem is that Jamie's brand new school dinners just didn't replace the old ones well enough.
Right as I was about to become a teenager, The Naked Chef made his move to help fight the obesity epidemic, and pulled my staple food out from under me for all but one day per week. And what appeared in its place? Not much. The breaded and fried meat products went to grilled ones, but all I was left with was poorly drained soggy pasta in disgusting sauce.
This meant that, at the ripe old age of twelve, for four days each week, I would skip lunch. I left my free school meal entitlement unfulfilled and took my 40 minute lunch break anywhere other than the dining hall.
In the ten years that followed, I went from a reasonably unhealthily eating but thin and somewhat athletic pre-teen to an early 20s disabled and chronically ill fat person. But the one constant across those years and the other half a decade since, is that I've had an unhealthy relationship with food. When I feel as though my depression is getting on top of me, I just stop eating.
I'm not sure I've ever been motivated by the urge to be thin — I was thin up until I started university. I'm a body positive fat person now. But Jamie's War on School Dinners taught me that it's just easier to not eat – and that is incredibly problematic.
Not eating can be as bad for your health as eating too much, or the wrong thing. I've certainly found that my disordered eating has had more effect on my health (mentally) than being fat has (physically or mentally!).
When I see the latest thing that Jamie wants to ban in the name of healthy eating, I'm thrown back to being 12-years-old and being told that chips are only for Fridays. I'm left standing on a Monday morning, holding up the queue while I try and decide between a disgusting but marginally 'healthier' meal, or nothing at all.
And for me, that choice existed. Lately, Oliver has gone after 2 for 1 deals on takeaway pizzas, which if you're a working class family with little money, might be the only way you can feed the whole family if you don't have the time or ability to slave over the cooker. I'm imagining 12-year-old girls in Generation Z who are faced with a similar situation to me, but whereas I had one poor option, they've got nothing. And if I stopped eating when there was an alternative, what are they going to do?
I'm also from a working class family who had little money growing up – I already said that we claimed free school meals. But in the mid 2000s, Jamie Oliver hadn't managed to sink his claws into as much high carb, high fat, high sugar food as he has now. I realise now, as an adult, that it's because my parents made sacrifices, but I didn't go without an evening meal. Even as a vegetarian, when we went shopping my mum would pick me up the various options that only I would eat so I could be fed. I was very fortunate. And yet, I still have a problem with food. Now it's not just school dinners, he seems to be going after everything that the working class rely on in the name of the 'War on Obesity'.
And, yes, I guess, there is likely to be less obesity. But if that's at the cost of kids literally not eating, developing disordered eating patterns and suffering mentally – is it worth it? Hell no.
F*ck off Jamie. It's too late for me, I've had 15 years of your bullsh*t. Stop trading one food problem for another and calling it progress.