// Active Directory Display Specifier Upgrade Tool // // Copyright (c) 2001 Microsoft Corporation // // class Repairer // // keeps a list of the localeIds to be extracted from the dcpromo.csv file, // and a list of operations to be represented in an LDIF file. // // 7 Mar 2001 sburns #include "headers.hxx" #include "Repairer.hpp" // // // make sure that the ldif operations are executed in advance of the csv // // // operations. this is so the object creates will not conflict with object // // // deletes Repairer::Repairer( const String& dcpromoCsvFilePath_) : dcpromoCsvFilePath(dcpromoCsvFilePath_) { LOG_CTOR(Repairer); ASSERT(!dcpromoCsvFilePath.empty()); } bool Repairer::IsLocaleInObjectsToCreateTable(int localeId) const { LOG_FUNCTION2( Repairer::IsLocaleInObjectsToCreateTable, String::format(L"%1!d!", localeId)); ASSERT(localeId); bool result = false; for ( LocaleIdObjectNamePairList::iterator i = objectsToCreate.begin(); i != objectsToCreate.end(); ++i) { if (i->first == localeId) { result = true; break; } } LOG_BOOL(result); return result; } void Repairer::AddCreateContainerWorkItem(int localeId) { LOG_FUNCTION2( Repairer::AddCreateContainerWorkItem, String::format(L"%1!d!", localeId)); ASSERT(localeId); do { LocaleIdList::iterator i = std::find( containersToCreate.begin(), containersToCreate.end(), localeId); if (i != containersToCreate.end()) { // The locale should not already be in the list, since each locale // container is evaluated only once. LOG(L"locale already in list"); ASSERT(false); break; } if (IsLocaleInObjectsToCreateTable(localeId)) { // We don't expect any entries for this locale to be present in the // objects-to-create list, because the containers are evaluated first. LOG(L"objects for locale already in object list"); ASSERT(false); // CODEWORK: we should handle this situation anyway, just for // robustness' sake. To deal with it, all entires in the objects- // to-create list for this locale id should be removed. break; } containersToCreate.push_back(localeId); } while (0); } void Repairer::AddCreateObjectWorkItem( int localeId, const String& displaySpecifierObjectName) { LOG_FUNCTION2( Repairer::AddCreateObjectWorkItem, String::format( L"%1!d! %2", localeId, displaySpecifierObjectName.c_str())); ASSERT(localeId); ASSERT(!displaySpecifierObjectName.empty()); do { LocaleIdList::iterator i = std::find( containersToCreate.begin(), containersToCreate.end(), localeId); if (i != containersToCreate.end()) { // The locale is already in the containers-to-create list, which // we don't expect, since if the container does not exist, we should // not be evaluating which objects should be created in that container. ASSERT(false); // do nothing, as the object will be created as part of the container // creation. break; } LocaleIdObjectNamePair p(localeId, displaySpecifierObjectName); LocaleIdObjectNamePairList::iterator j = std::find( objectsToCreate.begin(), objectsToCreate.end(), p); if (j != objectsToCreate.end()) { // The object is already in the list. We don't expect this, since // each object should be evaluated only once per locale. ASSERT(false); // do nothing, if the object is already present, then fine. break; } objectsToCreate.push_back(p); } while (0); } void Repairer::AddDeleteObjectWorkItem( int localeId, const String& displaySpecifierObjectName) { //CODEWORK: //lucios: Inserted to remove link error localeId++; String x=displaySpecifierObjectName; } HRESULT Repairer::BuildRepairFiles() { LOG_FUNCTION(Repairer::BuildRepairFiles); HRESULT hr = S_OK; // CODEWORK // csv file: // // create a (temp) file // copy out the first line of the dcpromo.csv file (the column labels) // for each localeid in the list // copy out all of the lines in the dcpromo.csv file for that locale // for each entry // copy out that line from the dcpromo.csv file // // ldif file: LOG_HRESULT(hr); return hr; } HRESULT Repairer::ApplyRepairs() { LOG_FUNCTION(Repairer::ApplyRepairs); HRESULT hr = S_OK; // CODEWORK: needs finishing LOG_HRESULT(hr); return hr; } // could have gone with a architecture like: // // repairer.workQueue.Add(new CreateContainerWorkItem(localeId)); // // but while that certainly seems more OO, more "extensible" because new work // item types could be derived. Upon further thought, it seems like a worse // solution to me, since there are them lots of trivial classes involved, and // the coordination of those classes becomes a real nuisance. Once all the // work items are collected, who's responsible for translating them into the // csv/ldif files? It would have to be an additional manager class. The // extensibility turns out to be an illusion, since adding a new work item // type requires modifying the manager class. So the added complexity buys // nothing. // // The other design choice was whether to make the Repairer a "static class" // -- my name for a class that is really a namespace, which instead of members // uses static data that is hidden in a single translation unit as though it // were private class data. This is a technique that makes the private data // truly secret, as there is no mention of the data in the header declaration // for the class at all. It also is a nice way to implement the Singleton // pattern: there are no instances, and therefore no need to worry about // constructors, destructors, assignment, stack or heap allocation, no // "GetInstance" methods, and no lifetime issues. // // The technique gives a slightly nicer syntax as: // // Repairer::AddCreateContainerWorkItem(localeId) // // as opposed to // // Repairer::GetInstance()->AddCreateContainerWorkItem(localeId); // // I decided to go with a real, fully-contained object implementation, instead // of a singleton, thinking that maybe someday multiple instances could be // repairing multiple forests at once. Not likely, but why not?