ModelGeneratorContext::ModelGeneratorContext(std::string const &sbml,
    unsigned options) :
        ownedDoc(0),
        doc(0),
        symbols(0),
        modelSymbols(0),
        errString(new string()),
        context(0),
        executionEngine(0),
        module(0),
        builder(0),
        functionPassManager(0),
        options(options),
        moietyConverter(0)
{
    try
    {
        ownedDoc = checkedReadSBMLFromString(sbml.c_str());

        if (options & rr::ModelGenerator::CONSERVED_MOIETIES)
        {
            if ((rr::Config::getInt(rr::Config::ROADRUNNER_DISABLE_WARNINGS) &
                    rr::Config::ROADRUNNER_DISABLE_WARNINGS_CONSERVED_MOIETY) == 0)
            {
                Log(Logger::LOG_NOTICE) << "performing conserved moiety conversion";
            }

            // check if already conserved doc
            if (rr::conservation::ConservationExtension::isConservedMoietyDocument(ownedDoc))
            {
                doc = ownedDoc;
            }
            else
            {
                moietyConverter = new rr::conservation::ConservedMoietyConverter();

                if (moietyConverter->setDocument(ownedDoc) != LIBSBML_OPERATION_SUCCESS)
                {
                    throw_llvm_exception("error setting conserved moiety converter document");
                }

                if (moietyConverter->convert() != LIBSBML_OPERATION_SUCCESS)
                {
                    throw_llvm_exception("error converting document to conserved moieties");
                }

                doc = moietyConverter->getDocument();

                SBMLWriter sw;
                char* convertedStr = sw.writeToString(doc);

                Log(Logger::LOG_INFORMATION) << "***************** Conserved Moiety Converted Document ***************";
                Log(Logger::LOG_INFORMATION) << convertedStr;
                Log(Logger::LOG_INFORMATION) << "*********************************************************************";

                free(convertedStr);
            }
        }
        else
        {
            doc = ownedDoc;
        }

        symbols = new LLVMModelDataSymbols(doc->getModel(), options);

        modelSymbols = new LLVMModelSymbols(getModel(), *symbols);


        // initialize LLVM
        // TODO check result
        InitializeNativeTarget();

        context = new LLVMContext();
        // Make the module, which holds all the code.
        module = new Module("LLVM Module", *context);

        builder = new IRBuilder<>(*context);

        // engine take ownership of module
        EngineBuilder engineBuilder(module);

        engineBuilder.setErrorStr(errString);
        executionEngine = engineBuilder.create();

        addGlobalMappings();

        createLibraryFunctions(module);

        ModelDataIRBuilder::createModelDataStructType(module, executionEngine, *symbols);

        initFunctionPassManager();

    }
    catch(const std::exception&)
    {
        // we might have allocated memory in a failed ctor,
        // clean it up here.
        // destructors are not called on *this* class when exception is raised
        // in the ctor.
        cleanup();
        throw;
    }
}
ModelGeneratorContext::ModelGeneratorContext(std::string const &sbml,
    unsigned options) :
        ownedDoc(0),
        doc(0),
        symbols(0),
        modelSymbols(0),
        errString(new string()),
        options(options),
        moietyConverter(0),
        functionPassManager(0)
{
    if (options & rr::ModelGenerator::CONSERVED_MOIETIES)
    {
        Log(Logger::LOG_NOTICE) << "performing conserved moiety conversion";

        moietyConverter = new rr::conservation::ConservedMoietyConverter();
        ownedDoc = checkedReadSBMLFromString(sbml.c_str());

        if (moietyConverter->setDocument(ownedDoc) != LIBSBML_OPERATION_SUCCESS)
        {
            throw_llvm_exception("error setting conserved moiety converter document");
        }

        if (moietyConverter->convert() != LIBSBML_OPERATION_SUCCESS)
        {
            throw_llvm_exception("error converting document to conserved moieties");
        }

        doc = moietyConverter->getDocument();

        SBMLWriter sw;
        char* convertedStr = sw.writeToString(doc);

        Log(Logger::LOG_NOTICE) << "***************** Conserved Moiety Converted Document ***************";
        Log(Logger::LOG_NOTICE) << convertedStr;
        Log(Logger::LOG_NOTICE) << "*********************************************************************";

        delete convertedStr;
    }
    else
    {
        ownedDoc = checkedReadSBMLFromString(sbml.c_str());
        doc = ownedDoc;
    }

    symbols = new LLVMModelDataSymbols(doc->getModel(), options);

    modelSymbols = new LLVMModelSymbols(getModel(), *symbols);


    // initialize LLVM
    // TODO check result
    InitializeNativeTarget();

    context = new LLVMContext();
    // Make the module, which holds all the code.
    module = new Module("LLVM Module", *context);

    builder = new IRBuilder<>(*context);

    // engine take ownership of module
    EngineBuilder engineBuilder(module);

    engineBuilder.setErrorStr(errString);
    executionEngine = engineBuilder.create();

    addGlobalMappings();

    createLibraryFunctions(module);

    ModelDataIRBuilder::createModelDataStructType(module, executionEngine, *symbols);

    initFunctionPassManager();
}