public CharSequence apply(ImportManager importManager) {
    JvmOperation cacheMethod =
        (JvmOperation)
            logicalContainerProvider.getLogicalContainer(createExtensionInfo.getCreateExpression());
    StringBuilderBasedAppendable appendable = new StringBuilderBasedAppendable(importManager);
    JvmDeclaredType containerType = cacheMethod.getDeclaringType();
    JvmTypeReference listType = typeReferences.getTypeForName(ArrayList.class, containerType);
    JvmTypeReference collectonLiterals =
        typeReferences.getTypeForName(CollectionLiterals.class, containerType);
    String cacheVarName = cacheField.getSimpleName();
    String cacheKeyVarName = appendable.declareVariable("CacheKey", "_cacheKey");
    appendable.append("final ");
    typeReferenceSerializer.serialize(listType, containerType, appendable);
    appendable.append(cacheKeyVarName).append(" = ");
    typeReferenceSerializer.serialize(collectonLiterals, containerType, appendable);
    appendable.append(".newArrayList(");
    EList<JvmFormalParameter> list = cacheMethod.getParameters();
    for (Iterator<JvmFormalParameter> iterator = list.iterator(); iterator.hasNext(); ) {
      JvmFormalParameter jvmFormalParameter = iterator.next();
      appendable.append(getVarName(jvmFormalParameter));
      if (iterator.hasNext()) {
        appendable.append(", ");
      }
    }
    appendable.append(");");
    // declare result variable
    JvmTypeReference returnType = typeProvider.getType(createExtensionInfo.getCreateExpression());
    appendable.append("\nfinal ");
    typeReferenceSerializer.serialize(returnType, containerType, appendable);
    String resultVarName = "_result";
    appendable.append(" ").append(resultVarName).append(";");
    // open synchronize block
    appendable.append("\nsynchronized (").append(cacheVarName).append(") {");
    appendable.increaseIndentation();
    // if the cache contains the key return the previously created object.
    appendable
        .append("\nif (")
        .append(cacheVarName)
        .append(".containsKey(")
        .append(cacheKeyVarName)
        .append(")) {");
    appendable.increaseIndentation();
    appendable
        .append("\nreturn ")
        .append(cacheVarName)
        .append(".get(")
        .append(cacheKeyVarName)
        .append(");");
    appendable.decreaseIndentation().append("\n}");
    // execute the creation
    compiler.toJavaStatement(createExtensionInfo.getCreateExpression(), appendable, true);
    appendable.append("\n");
    appendable.append(resultVarName).append(" = ");
    compiler.toJavaExpression(createExtensionInfo.getCreateExpression(), appendable);
    appendable.append(";");

    // store the newly created object in the cache
    appendable
        .append("\n")
        .append(cacheVarName)
        .append(".put(")
        .append(cacheKeyVarName)
        .append(", ")
        .append(resultVarName)
        .append(");");

    // close synchronize block
    appendable.decreaseIndentation();
    appendable.append("\n}");
    appendable
        .append("\n")
        .append(initializerMethod.getSimpleName())
        .append("(")
        .append(resultVarName);
    for (JvmFormalParameter parameter : cacheMethod.getParameters()) {
      appendable.append(", ").append(parameter.getName());
    }
    appendable.append(");");
    // return the result
    appendable.append("\nreturn ");
    appendable.append(resultVarName).append(";");
    return appendable.toString();
  }
  protected void transform(XtendFunction source, JvmGenericType container) {
    JvmOperation operation = typesFactory.createJvmOperation();
    container.getMembers().add(operation);
    associator.associatePrimary(source, operation);
    String sourceName = source.getName();
    JvmVisibility visibility = source.getVisibility();
    if (source.isDispatch()) {
      if (!source.eIsSet(Xtend2Package.Literals.XTEND_FUNCTION__VISIBILITY))
        visibility = JvmVisibility.PROTECTED;
      sourceName = "_" + sourceName;
    }
    operation.setSimpleName(sourceName);
    operation.setVisibility(visibility);
    operation.setStatic(source.isStatic());
    for (XtendParameter parameter : source.getParameters()) {
      JvmFormalParameter jvmParam = typesFactory.createJvmFormalParameter();
      jvmParam.setName(parameter.getName());
      jvmParam.setParameterType(cloneWithProxies(parameter.getParameterType()));
      operation.getParameters().add(jvmParam);
      associator.associate(parameter, jvmParam);
      jvmTypesBuilder.translateAnnotationsTo(parameter.getAnnotations(), jvmParam);
    }
    JvmTypeReference returnType = null;
    if (source.getReturnType() != null) {
      returnType = cloneWithProxies(source.getReturnType());
    } else {
      returnType = getTypeProxy(operation);
    }
    operation.setReturnType(returnType);
    copyAndFixTypeParameters(source.getTypeParameters(), operation);
    for (JvmTypeReference exception : source.getExceptions()) {
      operation.getExceptions().add(cloneWithProxies(exception));
    }
    jvmTypesBuilder.translateAnnotationsTo(source.getAnnotationInfo().getAnnotations(), operation);
    CreateExtensionInfo createExtensionInfo = source.getCreateExtensionInfo();
    if (createExtensionInfo != null) {
      JvmTypeReference arrayList =
          typeReferences.getTypeForName(ArrayList.class, container, typeReferences.wildCard());
      JvmTypeReference hashMap =
          typeReferences.getTypeForName(
              HashMap.class, container, arrayList, cloneWithProxies(returnType));

      JvmField cacheVar =
          jvmTypesBuilder.toField(
              source, CREATE_CHACHE_VARIABLE_PREFIX + source.getName(), hashMap);
      cacheVar.setFinal(true);
      jvmTypesBuilder.setInitializer(cacheVar, compileStrategies.forCacheVariable(container));
      container.getMembers().add(cacheVar);

      JvmOperation initializer = typesFactory.createJvmOperation();
      container.getMembers().add(initializer);
      initializer.setSimpleName(CREATE_INITIALIZER_PREFIX + source.getName());
      initializer.setVisibility(JvmVisibility.PRIVATE);
      initializer.setReturnType(typeReferences.getTypeForName(Void.TYPE, source));
      for (JvmTypeReference exception : source.getExceptions()) {
        initializer.getExceptions().add(cloneWithProxies(exception));
      }

      jvmTypesBuilder.setBody(
          operation, compileStrategies.forCacheMethod(createExtensionInfo, cacheVar, initializer));

      // the first parameter is the created object
      JvmFormalParameter jvmParam = typesFactory.createJvmFormalParameter();
      jvmParam.setName(createExtensionInfo.getName());
      jvmParam.setParameterType(getTypeProxy(createExtensionInfo.getCreateExpression()));
      initializer.getParameters().add(jvmParam);
      associator.associate(createExtensionInfo, jvmParam);

      // add all others
      for (XtendParameter parameter : source.getParameters()) {
        jvmParam = typesFactory.createJvmFormalParameter();
        jvmParam.setName(parameter.getName());
        jvmParam.setParameterType(cloneWithProxies(parameter.getParameterType()));
        initializer.getParameters().add(jvmParam);
        associator.associate(parameter, jvmParam);
      }
      associator.associate(source, initializer);
      associator.associateLogicalContainer(createExtensionInfo.getCreateExpression(), operation);
      associator.associateLogicalContainer(source.getExpression(), initializer);
    } else {
      associator.associateLogicalContainer(source.getExpression(), operation);
    }
    jvmTypesBuilder.setDocumentation(operation, jvmTypesBuilder.getDocumentation(source));
  }