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") }
void CRecipientListRouterInstance::initialize( const IBean::Cargs& ctorArgs, const IBean::Cprops& properties, const SmartPtrIDocument& configSection) { CAF_CM_FUNCNAME("initialize"); CAF_CM_ENTER { CAF_CM_PRECOND_ISNOTINITIALIZED(_isInitialized); CAF_CM_VALIDATE_INTERFACE(configSection); _id = configSection->findRequiredAttribute("id"); std::string val = configSection->findOptionalAttribute("timeout"); if (val.length()) { _timeout = CStringConv::fromString<int32>(val); } val = configSection->findOptionalAttribute("ignore-send-failures"); _ignoreSendFailures = (val == "true"); Csetstr channelIds; const IDocument::SmartPtrCChildCollection childCollection = configSection->getAllChildren(); for(TSmartConstMultimapIterator<IDocument::CChildCollection> childIter(*childCollection); childIter; childIter++) { const std::string sectionName = childIter.getKey(); if (sectionName == "recipient") { const SmartPtrIDocument document = *childIter; const std::string channelId = document->findRequiredAttribute("channel"); const std::string selectorExpression = document->findOptionalAttribute("selector-expression"); if (!channelIds.insert(channelId).second) { CAF_CM_EXCEPTIONEX_VA2( DuplicateElementException, 0, "Duplicate channelId '%s' in " "recipient-list-router definition '%s'", channelId.c_str(), _id.c_str()); } if (selectorExpression.length()) { _selectorDefinitions.insert( Cmapstrstr::value_type(channelId, selectorExpression)); } else { _staticChannelIds.push_back(channelId); } } } if (!_staticChannelIds.size() && !_selectorDefinitions.size()) { CAF_CM_EXCEPTIONEX_VA1( NoSuchElementException, 0, "No recipients were listed in the definition of " "recipient-list-router '%s'", _id.c_str()); } _isInitialized = true; } CAF_CM_EXIT; }