void CGenerateFastCppTemplate::codeGenerate()

in src/codegen/tool/GenerateFastCppTemplate.cpp [769:1118]


void CGenerateFastCppTemplate::codeGenerate(const schema::CObservableObjectInfo *pPropertyModelInfo)
{	
    std::wstring typeInfoName = toTypeInfoName(pPropertyModelInfo->getName());

    std::wstring typeInfoNameCodeGen = this->toCodeGenTypeName(typeInfoName.c_str());

    // default base container class
    std::wstring typeInfoBaseNameCodeGen = L"pmod::library::_FastPropertiesContainer<T>";

    //  default base model class
    std::wstring modelClassBaseNameCodeGen = L"pmod::FastModelBase<T, TInterface, TBASE, _ModelContainerType>";
    std::wstring modelBaseDefinition = L"	pmod::library::_ObservableObjectAdapterBaseImpl\n\
    <\n\
    foundation::_ObjectAdapterBase\n\
    <\n\
    pmod::library::_FastBaseHelper<TBASE, TModelPrivateInterface>\n\
    >\n\
    >\n";

    // typedef for base classes that are not inheriting from any class.
    std::wstring typeDefBaseClass = FormatW(L"typedef _Fast{0}<> _Fast{0}Base;\n\n",typeInfoNameCodeGen.data(),nullptr);

    std::wstring baseAdapterType = L"pmod::library::_ObservableObjectAdapterBase<TInterface, piid>";

    std::wstring baseFriendAccess = L"";
    std::wstring custombaseTypeQI = L"";
    std::wstring initializeMethodName = L"_InitializeModel";
    
    std::wostringstream baseMemberDelegates;
    std::wostringstream baseMemberQualifications;
    // check for base type
    if (pPropertyModelInfo->getBaseType())
    {        
        std::wstring typeInfoBaseName = toTypeInfoName(pPropertyModelInfo->getBaseType()->getName());
        baseAdapterType = L"T"+ typeInfoBaseName + L"FastModelAdapter<TInterface, piid>";
        //Attach template params
        typeInfoBaseNameCodeGen = L"_Fast" + this->toCodeGenTypeName(typeInfoBaseName) + L"Container<T>";

        baseFriendAccess = FormatW(_fastModelBaseContainerFriendDecl, this->toCodeGenTypeName(typeInfoBaseName).data(), typeInfoNameCodeGen.data(), nullptr);

        modelClassBaseNameCodeGen = FormatW(_fastModelCustomBaseClass_Template, this->toCodeGenTypeName(typeInfoBaseName).data(), pPropertyModelInfo->getBaseType()->getName().data(), nullptr);        

        // Write Properties and methods for base class delegation
        schema::CObservableObjectInfo* baseType = (schema::CObservableObjectInfo *)(pPropertyModelInfo->getBaseType());

        if(!baseType->getBaseType())
        {
            modelBaseDefinition = L"pmod::library::_DelegateFastModelBase<TBASE, TModelPrivateInterface>";
        }
        else
        {
            std::wstring baseName = this->toCodeGenTypeName(toTypeInfoName(baseType->getName()).c_str());
            modelBaseDefinition = FormatW(L"_Fast{0}<TBASE, TModelPrivateInterface>",baseName.data(),nullptr);
        }

        baseMemberDelegates << "// " <<pPropertyModelInfo->getBaseType()->getName() << "Interface" << std::endl;
        
        // emit base properties for delegating.
        for (schema::_PropertyIteratorType::const_iterator iter = baseType->getProperties().begin();
        iter != baseType->getProperties().end();
        ++iter)
        {
            emitPropertyBaseTypeDelegate(baseMemberDelegates, baseMemberQualifications,(*iter));
        }

        // Iterate Methods for the base class to generate the delegated
        for (schema::_MethodIteratorType::const_iterator iter = baseType->getMethods().begin();
            iter != baseType->getMethods().end();
            ++iter)
        {
            // emit method handler for class template
            emitMethodBaseTypeDelegate(baseMemberDelegates, baseMemberQualifications, *iter);
        }
    }

    // Emit get/set value cases
    std::wostringstream getValueCases;
    std::wostringstream setValueCases;
    std::wostringstream commandInitializations;
    std::wostringstream commandTypedefs;
    std::wostringstream commandVirtualMethods;
    std::wostringstream propertyContainers;
    std::wostringstream ancestorPropertyContainers;
    std::wostringstream osPropertyContainersInitializers;
    std::wostringstream osPublicAccess;
    std::wostringstream osInternalAccess;
    std::wostringstream osPrivateAccess;
    std::wostringstream osPrivateAccessDeclare;
    std::wostringstream osAncestorFriendContainerDeclare;
    std::wostringstream osOngetPropertyInternalCases;
    std::wostringstream osEnsurePropertyActivation;
    std::wostringstream osPropertiesRuntimeClassOptionsInitializers;
    std::wostringstream osContainerReleaseStatements;

    // Iterate Properties
    for (schema::_PropertyIteratorType::const_iterator iter = pPropertyModelInfo->getProperties().begin();
        iter != pPropertyModelInfo->getProperties().end();
        ++iter)
    {
        emitGetSetValuePropertyCases(getValueCases, setValueCases, (*iter));
        bool isAncestor = ((*iter)->getFlags() & PropertyFlagType_IsAncestor) != 0;

        // generate Command Internal support
        if ((*iter)->getModelType() != nullptr &&
            (*iter)->getModelType()->getModelType() == schema::ModelTypeInfoType_Command)
        {
            if ((*iter)->isAutoGenerate())
            {

                CGenerateCppLibrary::emitPropertyCommandHandler(
                    _osFastModelBaseClassTemplates,
                    (*iter),
                    FormatW(L"_WeakRefCommandClass<T,{0}>", pPropertyModelInfo->getName().data(),nullptr).c_str(),
                    L"_Fast");
            }
        }

        // Generation activation for dynamic properties
        emitActivationSupport(osOngetPropertyInternalCases,osEnsurePropertyActivation,(*iter));
        
        // validate if we need to generate the container
        // it will not be generated for parent property or custom container
        if (!(*iter)->isParent() && !(*iter)->isCustomContainer())
        {
            emitPropertyInitializer(osPropertyContainersInitializers, (*iter));
        }
        emitPropertyAccessMethods(osPublicAccess, osInternalAccess, osPrivateAccess, osPrivateAccessDeclare, (*iter));
    
        // we dont not need contaiers for parent properties
        if (!(*iter)->isParent() && !(*iter)->isCustomContainer() && !isAncestor )
        {
            emitPropertyContainer(propertyContainers, (*iter));
            emitContainerReleaseStatement(osContainerReleaseStatements, (*iter));
        }
        
        if (isAncestor)
        {
            ancestorPropertyContainers << "\tfoundation::InspectablePtr " << toAncestorContainerName((*iter)->getName().c_str()) << ";" << std::endl;
        }

        // only generate commands if they are not marked as auto generate
        if ((*iter)->isAutoGenerate())
        {
            if ((*iter)->getModelType() && (*iter)->getModelType()->getModelType() == schema::ModelTypeInfoType_Command)
            {
                emitCommandInitializer(commandInitializations, commandTypedefs, (*iter));
                emitPropertyCommandHandler(commandVirtualMethods, (*iter));
            }
        }
        if ((*iter)->getRuntimeClassOptions() != 0)
        {
            UINT32 runtimeClassOptions = (*iter)->getRuntimeClassOptions();
            std::wstring libraryRuntimeClassOptions;
            if ((runtimeClassOptions & 1) != 0)
            {
                libraryRuntimeClassOptions += FormatW(_propertyRuntimeClassOptions_Template, getCoreNamespace(), L"UseWorkingDispatcherOnGetProperty", nullptr);
            }
            // note: put extra  code here to continue constructing the options 
            if ((runtimeClassOptions & 2) != 0)
            {
                if (libraryRuntimeClassOptions.size())
                {
                    libraryRuntimeClassOptions += L" | ";
                }
                libraryRuntimeClassOptions += FormatW(_propertyRuntimeClassOptions_Template, getCoreNamespace(), L"UseWorkingDispatcherOnSetProperty", nullptr);
            }

            osPropertiesRuntimeClassOptionsInitializers <<
                FormatW(_setPropertyRuntimeClassOptions_Template,
                getNamespace().c_str(),
                typeInfoName.c_str(),
                (*iter)->getName().c_str(),
                FormatW(L"({0}::library::PropertyRuntimeClassOptions)({1})", getCoreNamespace(),libraryRuntimeClassOptions.c_str(),nullptr).c_str(),
                nullptr);
        }
    }

    // Generate Source Property if this is a viewmodel
    if (pPropertyModelInfo->getModelType() == schema::ModelTypeInfoType_ViewModel)
    {
        initializeMethodName = L"_Initialize_viewmodel";
        const schema::CObservableObjectInfo *pSourceType = ((const schema::CPropertyViewModelInfo *)pPropertyModelInfo)->getSourceType();
        // Emit Header
        osPrivateAccessDeclare << "\tvirtual HRESULT GetSource(";
        this->emitModelTypeInfo(osPrivateAccessDeclare, pSourceType);
        osPrivateAccessDeclare << "** ppValue) = 0;" << std::endl;
       
        // Emit Source
        osPublicAccess << "\tHRESULT GetSource(";
        this->emitModelTypeInfo(osPublicAccess, pSourceType);
        osPublicAccess << "** ppValue)" << std::endl;
        osPublicAccess << "\t{" << std::endl;
        osPublicAccess << "\t\treturn this->GetModelProperty(" << getCoreNamespace() << "::Property_Source,ppValue);" << std::endl;
        osPublicAccess << "\t}" << std::endl;        

    }

    // emit property containers
    _osFastModelContainersTemplates << FormatW(_fastModelContainerClass_Template,
        typeInfoNameCodeGen.data(),
        typeInfoBaseNameCodeGen.data(),
        getValueCases.str().length() != 0 ? FormatW(_fastModelGetSetValueSwitchTemplate, getValueCases.str().data(), nullptr).data() : L"",
        setValueCases.str().length() != 0 ? FormatW(_fastModelGetSetValueSwitchTemplate, setValueCases.str().data(), nullptr).data() : L"",
        ancestorPropertyContainers.str().data(),// Ancestor Containers
        nullptr
        );

    //generate initialize method for base class
    std::wstring fastModelInitialization = FormatW(_fastModelInitializeProperties_Template,
                                                    commandInitializations.str().data(),
                                                    osPropertyContainersInitializers.str().c_str(),
                                                    osPropertiesRuntimeClassOptionsInitializers.str().c_str(),
                                                    nullptr);

    std::wostringstream osMethodHandler;
    std::wostringstream osAbstractMethods;

    // Iterate Methods
    for (schema::_MethodIteratorType::const_iterator iter = pPropertyModelInfo->getMethods().begin();
        iter != pPropertyModelInfo->getMethods().end();
        ++iter)
    {
        if ((*iter)->getIsAsync() || _generateMethodInternal)
        {
            emitWrapperMethod(osAbstractMethods, (*iter));
        }
        // emit method handler for class template
        emitMethodHandler(osMethodHandler, osAbstractMethods, *iter, false);
    }

    std::wstring methodInvokeOverride;
    if (pPropertyModelInfo->getMethods().size())
    {
        methodInvokeOverride = FormatW(
            _fastModelMethodInvokeOverride_Template,
            typeInfoName.data(),
            osMethodHandler.str().data(),
            this->getFoundationNamespace(),
            nullptr);
    }
    
    std::wstring strPrivateAccessDeclare = osPrivateAccessDeclare.str();
    std::wstring strCustomInterfaceName = pPropertyModelInfo->getCustomInterfaceName();

    
    _osFastModelPrivateInterfaceDeclares << FormatW(_fastModelPrivateInterfaceDeclare_Template,
        (pPropertyModelInfo->getName() + L"Private").data(),
        strPrivateAccessDeclare.data(),
        pPropertyModelInfo->getName().data(),
        nullptr);		
    
    if (strCustomInterfaceName.size() != 0)
    {
        _osFastModelPrivateInterfaceDeclares << FormatW(_fastModelInterfaceExternDeclare_Template,
            strCustomInterfaceName.data(),
            L"", // Postfix not used
            L"_VOID_MACRO", // No need for exporting this ID
            nullptr);

        std::wstring customIdValue = L"IID_" + strCustomInterfaceName;

        custombaseTypeQI = FormatW(_fastModelBaseClassQI_Template, strCustomInterfaceName.data()
                        ,customIdValue.data(), nullptr);
    }

    // generate the unique iid for the private access interface
    IID iidPrivateModeTypeAccess = createUniqueIId(pPropertyModelInfo);

    std::wostringstream osIIDGuidData;
    formatIIDType(osIIDGuidData, iidPrivateModeTypeAccess);

    _osFastModelPrivateInterfaceIIDs << FormatW(_fastModelPrivateInterfaceIId_Template,
        getNativeNamespace().data(),
        pPropertyModelInfo->getName().data(),
        toIdlIIDType(iidPrivateModeTypeAccess).data(),
        osIIDGuidData.str().data(),
        L"Private",
        nullptr);
    
    bool hasCustomInterfaceName = false;
    bool isCustomPrivateInterface = true;
    if (strCustomInterfaceName.size() != 0)
    {
        hasCustomInterfaceName = true;
        isCustomPrivateInterface = pPropertyModelInfo->isCustomPrivateInterface();

        // generate the unique iid for the custom access interface
        IID iidCustomModeTypeAccess = createUniqueIId(pPropertyModelInfo, L"Custom");
        std::wostringstream osCustomIIDGuidData;
        formatIIDType(osCustomIIDGuidData, iidCustomModeTypeAccess);

        _osFastModelPrivateInterfaceIIDs << FormatW(_fastModelPrivateInterfaceIId_Template,
            getNativeNamespace().data(),
            strCustomInterfaceName.data(),
            toIdlIIDType(iidCustomModeTypeAccess).data(),
            osCustomIIDGuidData.str().data(),
            L"", // Postfix not used
            nullptr);
    }
    emitAncestorContainerFriendDecl(osAncestorFriendContainerDeclare, pPropertyModelInfo);

    std::wstring ensureActivation = L"";
    std::wstring onGetPropetyInternal = L"";
    
    if (osEnsurePropertyActivation.tellp())
    {
        ensureActivation = osEnsurePropertyActivation.str();
        onGetPropetyInternal = FormatW(_fastModelOnPropertyGetInternal_Template, osOngetPropertyInternalCases.str().data(), nullptr);;
    }

    std::wstring privateInterfaceName = pPropertyModelInfo->getName() + L"Private";

    // emit base internal templates
    _osFastModelBaseClassTemplates << FormatW(_fastModelInternalCoreBaseClass_Template,
        typeInfoNameCodeGen.data(),
        modelClassBaseNameCodeGen.data(),
        privateInterfaceName.data(),
        fastModelInitialization.data(),
        commandTypedefs.str().data(),
        pPropertyModelInfo->getBaseType() == nullptr ? 
            FormatW(L" = {0}::library::_FastModelBase<>", getCoreNamespace(), nullptr).c_str():
            L"",
        methodInvokeOverride.data(),
        FormatW(L"{0}\n{1}\nprotected:\n{2}\n",osPublicAccess.str().data(),
                osAbstractMethods.str().data(),
                commandVirtualMethods.str().data(),
                nullptr).data(),
        osPrivateAccess.str().data(),
        osInternalAccess.str().data(),
        propertyContainers.str().data(),
        custombaseTypeQI.data(),
        pPropertyModelInfo->getName().data(),
        FormatW(_fastModelInnerAdpaterName_Template, typeInfoName.data(), nullptr).data(),
        typeInfoNameCodeGen.data(),
        osAncestorFriendContainerDeclare.str().data(),
        onGetPropetyInternal.data(),
        ensureActivation.data(),
        hasCustomInterfaceName && !isCustomPrivateInterface ? (L",\n\tpublic " + strCustomInterfaceName).data() : L"",
        initializeMethodName.data(),
        (L"public " + modelBaseDefinition).data(),
        baseMemberDelegates.tellp() ? baseMemberDelegates.str().data() : L"",
        pPropertyModelInfo->getName().data(),
        pPropertyModelInfo->getBaseType() == nullptr ? L"" : (L":" + modelBaseDefinition + L"(params...)\n").data(),
        pPropertyModelInfo->getBaseType() == nullptr ? L"" : (L":" + modelBaseDefinition + L"(parameter)\n").data(),
        hasCustomInterfaceName && isCustomPrivateInterface ? strCustomInterfaceName.data() : privateInterfaceName.data(),
        osContainerReleaseStatements.str().data(),
        pPropertyModelInfo->getBaseType() == nullptr ? typeDefBaseClass.data() : L"",
        nullptr
        );
}