void CApplicationContext::createBeanGraph( CBeanCollection& beanCollection, CBeanGraph& beanGraph, CBeanGraph::ClistVertexEdges& beanTopologySort) const { CAF_CM_FUNCNAME("createBeanGraph"); // Iterate the bean collection and create the beans. They will not be initialized. // Two name sets will be built: bean names and contstructor-arg ref names. // These two sets will be compared to ensure that all referenced beans exist. Csetstr beanNames; Csetstr beanCtorRefNames; for (TSmartMapIterator<CBeanCollection> beanIter(beanCollection); beanIter; beanIter++) { // Create the bean and add it to the collection CAF_CM_LOG_DEBUG_VA2( "Creating bean [id=%s][class=%s]", beanIter.getKey().c_str(), beanIter->_class.c_str()); beanIter->_bean.CreateInstance(beanIter->_class.c_str()); // Add the bean id to the beanNames set if (!beanNames.insert(beanIter->_id).second) { CAF_CM_LOG_DEBUG_VA1( "Internal logic error: duplicate bean detected. " "[id=%s]", beanIter->_id.c_str()); } // Add ref constructor args to the ctor ref name set for (TConstMapIterator<CBeanCtorArgCollection> beanCtorArg(beanIter->_ctorArgs); beanCtorArg; beanCtorArg++) { if (CBeanCtorArg::REFERENCE == beanCtorArg->_type) { beanCtorRefNames.insert(beanCtorArg->_value); } } } // Make sure that all beans referenced as ctor args exist Csetstr beanNameDiff; std::set_difference( beanCtorRefNames.begin(), beanCtorRefNames.end(), beanNames.begin(), beanNames.end(), std::inserter(beanNameDiff, beanNameDiff.end())); if (beanNameDiff.size()) { for (TConstIterator<Csetstr> missingName(beanNameDiff); missingName; missingName++) { CAF_CM_LOG_ERROR_VA1( "No bean definition exists for constructor-arg referenced bean '%s'", missingName->c_str()); } CAF_CM_EXCEPTIONEX_VA0( NoSuchElementException, 0, "One or more bean constructor-args references beans that are not defined."); } // Create a graph node for each bean for (TSmartConstMapIterator<CBeanCollection> beanIter(beanCollection); beanIter; beanIter++) { beanGraph.addVertex(*beanIter); } // Okay. Now connect the vertices according the constructor-arg references. // The resulting graph will give us the initialization/tear-down order. for (TSmartConstMapIterator<CBeanCollection> beanIter(beanCollection); beanIter; beanIter++) { for (TConstMapIterator<CBeanCtorArgCollection> ctorArg(beanIter->_ctorArgs); ctorArg; ctorArg++) { if (CBeanCtorArg::REFERENCE == ctorArg->_type) { CBeanCollection::const_iterator ctorBean = beanCollection.find(ctorArg->_value); if (beanCollection.end() == ctorBean) { CAF_CM_EXCEPTIONEX_VA1( NoSuchElementException, 0, "Internal error: constructor-arg referenced bean '%s' is missing", ctorArg->_value.c_str()); } beanGraph.addEdge(ctorBean->second, *beanIter); } } } // And finally - compute the bean topology sort order beanTopologySort = beanGraph.topologySort(); // Debugging - you will thank me for this later CAF_CM_LOG_DEBUG_VA0("BEGIN: Bean initialization order") for (TSmartConstIterator<CBeanGraph::ClistVertexEdges> beanNode(beanTopologySort); beanNode; beanNode++) { CAF_CM_LOG_DEBUG_VA1("bean id=%s", beanNode->_id.c_str()); } CAF_CM_LOG_DEBUG_VA0("END: Bean initialization order") }