/**
   * @return the static utility entityManager() method used by other methods to obtain entity
   *     manager and available as a utility for user code (never returns nulls)
   */
  public MethodMetadata getEntityManagerMethod() {
    if (parent != null) {
      // The parent is required to guarantee this is available
      return parent.getEntityManagerMethod();
    }

    // Method definition to find or build
    final JavaSymbolName methodName = new JavaSymbolName(ENTITY_MANAGER_METHOD_NAME);
    final JavaType[] parameterTypes = {};
    final JavaType returnType = ENTITY_MANAGER;

    // Locate user-defined method
    final MethodMetadata userMethod = getGovernorMethod(methodName, parameterTypes);
    if (userMethod != null) {
      Assert.isTrue(
          userMethod.getReturnType().equals(returnType),
          "Method '"
              + methodName
              + "' on '"
              + destination
              + "' must return '"
              + returnType.getNameIncludingTypeParameters()
              + "'");
      return userMethod;
    }

    // Create method
    final InvocableMemberBodyBuilder bodyBuilder = new InvocableMemberBodyBuilder();

    if (Modifier.isAbstract(governorTypeDetails.getModifier())) {
      // Create an anonymous inner class that extends the abstract class (no-arg constructor is
      // available as this is a JPA entity)
      bodyBuilder.appendFormalLine(
          ENTITY_MANAGER.getNameIncludingTypeParameters(
                  false, builder.getImportRegistrationResolver())
              + " em = new "
              + destination.getSimpleTypeName()
              + "() {");
      // Handle any abstract methods in this class
      bodyBuilder.indent();
      for (final MethodMetadata method : governorTypeDetails.getMethods()) {
        if (Modifier.isAbstract(method.getModifier())) {
          final StringBuilder params = new StringBuilder();
          int i = -1;
          final List<AnnotatedJavaType> types = method.getParameterTypes();
          for (final JavaSymbolName name : method.getParameterNames()) {
            i++;
            if (i > 0) {
              params.append(", ");
            }
            final AnnotatedJavaType type = types.get(i);
            params.append(type.toString()).append(" ").append(name);
          }
          final int newModifier = method.getModifier() - Modifier.ABSTRACT;
          bodyBuilder.appendFormalLine(
              Modifier.toString(newModifier)
                  + " "
                  + method.getReturnType().getNameIncludingTypeParameters()
                  + " "
                  + method.getMethodName().getSymbolName()
                  + "("
                  + params.toString()
                  + ") {");
          bodyBuilder.indent();
          bodyBuilder.appendFormalLine("throw new UnsupportedOperationException();");
          bodyBuilder.indentRemove();
          bodyBuilder.appendFormalLine("}");
        }
      }
      bodyBuilder.indentRemove();
      bodyBuilder.appendFormalLine(
          "}." + getEntityManagerField().getFieldName().getSymbolName() + ";");
    } else {
      // Instantiate using the no-argument constructor (we know this is available as the entity must
      // comply with the JPA no-arg constructor requirement)
      bodyBuilder.appendFormalLine(
          ENTITY_MANAGER.getNameIncludingTypeParameters(
                  false, builder.getImportRegistrationResolver())
              + " em = new "
              + destination.getSimpleTypeName()
              + "()."
              + getEntityManagerField().getFieldName().getSymbolName()
              + ";");
    }

    bodyBuilder.appendFormalLine(
        "if (em == null) throw new IllegalStateException(\"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)\");");
    bodyBuilder.appendFormalLine("return em;");
    final int modifier = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;

    final MethodMetadataBuilder methodBuilder =
        new MethodMetadataBuilder(
            getId(),
            modifier,
            methodName,
            returnType,
            AnnotatedJavaType.convertFromJavaTypes(parameterTypes),
            new ArrayList<JavaSymbolName>(),
            bodyBuilder);
    return methodBuilder.build();
  }
 private boolean isMethodOfInterest(MethodMetadata method) {
   return method.getMethodName().getSymbolName().startsWith("set")
       && method.getModifier() == Modifier.PUBLIC;
 }