protected void injectDomainHandler(
      ClassNode classNode, String implementation, String datasource) {
    classNode.addMethod(
        new MethodNode(
            DOMAIN_HANDLER_METHOD_NAME,
            Modifier.PUBLIC | Modifier.STATIC,
            GRIFFON_DOMAIN_HANDLER_CLASS,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            returns(domainHandlerInstance())));

    classNode.addMethod(
        new MethodNode(
            MAPPING,
            Modifier.PUBLIC | Modifier.STATIC,
            ClassHelper.STRING_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            returns(constx(implementation))));

    classNode.addMethod(
        new MethodNode(
            DATASOURCE,
            Modifier.PUBLIC | Modifier.STATIC,
            ClassHelper.STRING_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            returns(constx(datasource))));
  }
  protected void injectMethodMissing(ClassNode classNode) {
    FieldNode methodMissingInterceptor =
        classNode.addField(
            "this$methodMissingInterceptor",
            Modifier.FINAL | Modifier.STATIC | Modifier.PRIVATE | ACC_SYNTHETIC,
            METHOD_MISSING_INTERCEPTOR_CLASS,
            ctor(
                METHOD_MISSING_INTERCEPTOR_CLASS,
                args(classx(classNode), domainHandlerInstance())));

    classNode.addMethod(
        new MethodNode(
            "$static_methodMissing",
            Modifier.PUBLIC | Modifier.STATIC,
            ClassHelper.OBJECT_TYPE,
            params(
                param(ClassHelper.STRING_TYPE, "methodName"),
                param(ClassHelper.makeWithoutCaching(Object[].class), "arguments")),
            ClassNode.EMPTY_ARRAY,
            returns(
                call(
                    field(methodMissingInterceptor),
                    "handleMethodMissing",
                    args(var("methodName"), var("arguments"))))));
  }
  protected void injectMethod(ClassNode classNode, MethodSignature methodSignature) {
    Parameter[] parameters = makeParameters(methodSignature.getParameterTypes());

    int modifiers = Modifier.PUBLIC;
    if (methodSignature.isStatic()) modifiers |= Modifier.STATIC;
    String returnTypeClassName = methodSignature.getReturnType().getName();
    ClassNode returnType =
        GRIFFON_DOMAIN_CLASSNAME.equals(returnTypeClassName)
            ? classNode
            : ClassHelper.makeWithoutCaching(methodSignature.getReturnType());
    classNode.addMethod(
        new MethodNode(
            methodSignature.getMethodName(),
            modifiers,
            returnType,
            parameters,
            ClassNode.EMPTY_ARRAY,
            makeMethodBody(classNode, methodSignature, parameters)));
  }