public LifecycleCallbackMethodReference(
      SourceMethod method,
      MapperReference mapperReference,
      List<ParameterBinding> parameterBindings,
      Type methodReturnType,
      Type methodResultType,
      Set<String> existingVariableNames) {
    super(method, mapperReference, parameterBindings);
    this.declaringType = method.getDeclaringMapper();
    this.methodReturnType = methodReturnType;
    this.methodResultType = methodResultType;

    if (hasReturnType()) {
      this.targetVariableName = Strings.getSaveVariableName("target", existingVariableNames);
      existingVariableNames.add(this.targetVariableName);
    } else {
      this.targetVariableName = null;
    }
  }
  private Decorator getDecorator(
      TypeElement element, List<SourceMethod> methods, String implName, String implPackage) {
    DecoratedWithPrism decoratorPrism = DecoratedWithPrism.getInstanceOn(element);

    if (decoratorPrism == null) {
      return null;
    }

    TypeElement decoratorElement = (TypeElement) typeUtils.asElement(decoratorPrism.value());

    if (!typeUtils.isAssignable(decoratorElement.asType(), element.asType())) {
      messager.printMessage(element, decoratorPrism.mirror, Message.DECORATOR_NO_SUBTYPE);
    }

    List<MappingMethod> mappingMethods = new ArrayList<MappingMethod>(methods.size());

    for (SourceMethod mappingMethod : methods) {
      boolean implementationRequired = true;
      for (ExecutableElement method :
          ElementFilter.methodsIn(decoratorElement.getEnclosedElements())) {
        if (elementUtils.overrides(method, mappingMethod.getExecutable(), decoratorElement)) {
          implementationRequired = false;
          break;
        }
      }
      Type declaringMapper = mappingMethod.getDeclaringMapper();
      if (implementationRequired && !(mappingMethod.isDefault() || mappingMethod.isStatic())) {
        if ((declaringMapper == null) || declaringMapper.equals(typeFactory.getType(element))) {
          mappingMethods.add(new DelegatingMethod(mappingMethod));
        }
      }
    }

    boolean hasDelegateConstructor = false;
    boolean hasDefaultConstructor = false;
    for (ExecutableElement constructor :
        ElementFilter.constructorsIn(decoratorElement.getEnclosedElements())) {
      if (constructor.getParameters().isEmpty()) {
        hasDefaultConstructor = true;
      } else if (constructor.getParameters().size() == 1) {
        if (typeUtils.isAssignable(element.asType(), first(constructor.getParameters()).asType())) {
          hasDelegateConstructor = true;
        }
      }
    }

    if (!hasDelegateConstructor && !hasDefaultConstructor) {
      messager.printMessage(element, decoratorPrism.mirror, Message.DECORATOR_CONSTRUCTOR);
    }

    Decorator decorator =
        new Decorator.Builder()
            .elementUtils(elementUtils)
            .typeFactory(typeFactory)
            .mapperElement(element)
            .decoratorPrism(decoratorPrism)
            .methods(mappingMethods)
            .hasDelegateConstructor(hasDelegateConstructor)
            .options(options)
            .versionInformation(versionInformation)
            .implName(implName)
            .implPackage(implPackage)
            .extraImports(getExtraImports(element))
            .build();

    return decorator;
  }