content: /*
   * Copyright (C) 2016 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   */
  package androidx.test.espresso.remote;
  
  import static androidx.test.espresso.remote.ProtoUtils.capitalizeFirstChar;
  
  import com.google.protobuf.Any;
  import com.google.protobuf.ByteString;
  import com.google.protobuf.MessageLite;
  import java.util.List;
  import java.util.Locale;
  
  /** Reflection helper to invoke methods on a proto message. */
  final class ProtoReflector {
  
    private static final String PROTO_MSG_GET_ALL_LIST_METHOD_NAME_TPL = "get%sList";
    private static final String PROTO_MSG_GET_VALUE_METHOD_NAME_TPL = "get%s";
  
    private final Class<?> protoType;
    private final MessageLite proto;
  
    /**
     * Creates a new {@link BuilderReflector}.
     *
     * @param protoType the proto message type
     * @param proto instance of a proto message. The runtime class of this instance must match the
     *     {@link #protoType}.
     */
    public ProtoReflector(Class<?> protoType, MessageLite proto) {
      this.protoType = protoType;
      this.proto = proto;
    }
  
    /**
     * Invokes and returns the {@link Any} list of a proto instances {@value
     * PROTO_MSG_GET_ALL_LIST_METHOD_NAME_TPL} method.
     *
     * @param methodSuffix the method suffix to substitute "get<suffix>List" to create the full method
     *     name. For instance, if the proto method is called {@code getSomeSuffixList()} the method
     *     prefix needs to be "SomeSuffix".
     * @return a list of {@link Any} objects
     */
    @SuppressWarnings("unchecked")
    public List<Any> getAnyList(String methodSuffix) {
      return invokeMethod(proto, PROTO_MSG_GET_ALL_LIST_METHOD_NAME_TPL, methodSuffix, List.class);
    }
  
    /**
     * Invokes and returns the {@link Any} value of a proto instances {@value
     * PROTO_MSG_GET_VALUE_METHOD_NAME_TPL} method.
     *
     * @param methodSuffix the method suffix to append "get" to create the full method name. For
     *     instance, if the proto method is called {@code getSomeSuffix()} the method prefix needs to
     *     be "SomeSuffix".
     * @return the {@link Any} object
     */
    public Any getAnyValue(String methodSuffix) {
      return invokeMethod(proto, PROTO_MSG_GET_VALUE_METHOD_NAME_TPL, methodSuffix, Any.class);
    }
  
    /**
     * Invokes and returns the {@link ByteString} value of a proto instances {@value
     * PROTO_MSG_GET_VALUE_METHOD_NAME_TPL} method.
     *
     * @param methodSuffix the method suffix to append "get" to create the full method name. For
     *     instance, if the proto method is called {@code getSomeSuffix()} the method prefix weeds to
     *     be "SomeSuffix".
     * @return the {@link ByteString} object
     */
    public ByteString getByteStringValue(String methodSuffix) {
      return invokeMethod(proto, PROTO_MSG_GET_VALUE_METHOD_NAME_TPL, methodSuffix, ByteString.class);
    }
  
    private <T> T invokeMethod(
        MessageLite messageLite, String methodNameTpl, String methodSuffix, Class<T> clazz) {
      return clazz.cast(
          new MethodInvocation(
                  protoType,
                  messageLite,
                  String.format(Locale.ROOT, methodNameTpl, capitalizeFirstChar(methodSuffix)))
              .invokeDeclaredMethod());
    }
  }
  