// REI_Automation_CPP_no_MFC.cpp : Defines the entry point for the console application. // /////////////////////////////////////////////////////////////////////// // This source code shows how to use the REI with automation in C++ // without using the MFCs. // // The development/testing environment used to create this code was: // - Windows 2000 // - Visual C++ IDE 6.0 // - Rational Rose 2000e version 7.0.9420.17 // The final testing was done on release: //- Rational Rose 2002 Release 2 /////////////////////////////////////////////////////////////////////// // The main part of this code is composed of four examples: // Example #1: Creating an association and accessing Roles // Example #2: Export control; accessing RichType objects // Example #3: Consulting existing collections // Example #4: Creating collections for local use #include // The no_namespace attribute is used here to simplify this very simple example. // This way there is no need to specify the namespace to acess a class: // do IRose...Ptr instead of namspace::IRose...Ptr // See help on "namespace" or "using" or "#import" for more infos. #import "c:\\Program Files\\Rational\\Rose\\rationalrose.tlb" no_namespace int main(int argc, char* argv[]) { // Initialize the COM library. CoInitialize(NULL); CLSID RoseID; HRESULT hr; // Get the CLSID from the registry base // (HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Rose.Application\CLSID) hr = CLSIDFromProgID(L"Rose.Application", &RoseID); if(FAILED(hr)) { CoUninitialize(); return -1; } LPUNKNOWN lpUnk; // Create a new Rose instance //hr = CoCreateInstance(RoseID, NULL, CLSCTX_SERVER, IID_IUnknown, (LPVOID FAR*)&lpUnk); // OR // Get an active Rose instance launched prior to this hr = GetActiveObject(RoseID, NULL, (LPUNKNOWN *)&lpUnk); if(FAILED(hr)) { CoUninitialize(); return -2; } // Ask for an interface pointer LPDISPATCH lpDispatch; hr = lpUnk->QueryInterface(IID_IDispatch, (LPVOID FAR*)&lpDispatch); // Now that we have the interface pointer, we don't need the LPUNKNOWN pointer anymore. // Because this is a "basic" pointer (and not an IDispatch object) we have to // release the interface. lpUnk->Release(); if(FAILED(hr)) { CoUninitialize(); return -3; } // Begin a new block (curly braces) to allocate a new space in the system stack // so that the objects are guaranted to be destructed at the end of this block. // This is important because the smart pointers destructors calls Release() and // this has to be done before CoUninitialize(); { // Create an IRoseApplicationPtr from the interface pointer // Note: You cannot instanciate "IRose..." classes since they all are abstracts // The "IRose...Ptr" classes are smart pointers to "IRose..." classes. // They handle resource reference counting, via function calls // to the IUnknown member functions: QueryInterface, AddRef, and Release. // Info: See help on _com_ptr_t or _COM_SMARTPTR_TYPEDEF or IUnknown IRoseApplicationPtr roseApp(lpDispatch); // When a new Rose instance is created it is not visible by default //roseApp->PutVisible(true); // Note that the character strings have to be handled with the _bstr_t class. // See the _bstr_t help for the available methods. IRoseModelPtr theModel = roseApp->NewModel(); // OR //IRoseModelPtr theModel = roseApp->GetCurrentModel(); IRoseCategoryPtr rootCategory = theModel->GetRootCategory(); // Example #1: Creating an association and accessing Roles printf("Example #1: Creating an association and accessing Roles\n"); // According to the design of the REI, the role cannot exist without an // association. (An association is a composition of two roles and an // association class). So instanciating a Role without a class is a non-sense // in the scope of a Rose model. IRoseClassPtr clientClass = rootCategory->AddClass("clientClass"); IRoseClassPtr supplierClass = rootCategory->AddClass("supplierClass"); IRoseAssociationPtr ex1Assoc = clientClass->AddAssociation("supplierRole", "supplierClass"); ex1Assoc->PutName("ex1Assoc"); IRoseRolePtr ex1AssocRole1 = ex1Assoc->Role1; IRoseRolePtr ex1AssocRole2 = ex1Assoc->Role2; printf("Created Role1 Class name: %s\n", (char *)ex1AssocRole1->GetClass()->GetName()); printf("Created Role2 Class name: %s\n", (char *)ex1AssocRole2->GetClass()->GetName()); printf("End Example #1.\n\n"); // End Example #1. // Example #2: Export control; accessing RichType objects printf("Example #2: Export control; accessing RichType objects\n"); // The RichType class is part of a composition for the following classes: // Attribute, InheritRelation, // Operation, Class, Role, // ClassDependency, HasRelationship. // Each of these classes has an attribute (composition) inheriting from RichType: // AttributeExportControl, InheritRelationshipExportControl, // OperationExportControl, ClassExportControl, RoleExportControl, // UsesRelationExportControl, HasRelationshipExportControl. // Using automation, we don't have these last classes. // They all are corresponding to the IRoseRichTypePtr class. IRoseClassPtr ex2Class = rootCategory->AddClass("ex2Class"); IRoseRichTypePtr exportControl = ex2Class->GetExportControl(); IRoseRichTypeValuesCollectionPtr values = exportControl->GetTypes(); printf("Possible values for the RichType in ex2Class\n"); for(int i=1; i<=values->GetCount(); i++) { printf("Value %d = %s\n", i, (char *)values->GetAt(i)); } printf("Current export control name = %s\n", (char *)exportControl->GetName()); printf("Put value ProtectedAccess\n"); exportControl->PutName("ProtectedAccess"); // or PutName(values->GetAt(yourChoice)) printf("Current export control name = %s\n", (char *)exportControl->GetName()); printf("End Example #2.\n\n"); // End Example #2. // Example #3: Consulting existing collections printf("Example #3: Consulting existing collections\n"); IRoseClassPtr ex3Class1 = rootCategory->AddClass("ex3Class1"); IRoseClassPtr ex3Class2 = rootCategory->AddClass("ex3Class2"); IRoseClassPtr ex3Class3 = rootCategory->AddClass("ex3Class3"); IRoseClassPtr ex3Class4 = rootCategory->AddClass("ex3Class4"); // The first argument is the name the supplier's role // The second argument is the name of the supplier class IRoseAssociationPtr ex3Assoc12 = ex3Class1->AddAssociation("", "ex3Class2"); IRoseAssociationPtr ex3Assoc34 = ex3Class3->AddAssociation("", "ex3Class4"); ex3Assoc12->PutName("ex3Assoc12"); ex3Assoc34->PutName("ex3Assoc34"); IRoseAssociationCollectionPtr rootAssociations = rootCategory->GetAssociations(); // Use the (char *) operator to get a pointer on the actual internal buffer // of the returned _bstr_t object printf("Associations in %s:\n", (char *)rootCategory->GetName()); for(i=1; i<=rootAssociations->GetCount(); i++) { IRoseAssociationPtr anAssociation = rootAssociations->GetAt(i); printf("Association: \"%s\" \tClass A: \"%s\" \tClass B: \"%s\"\n", (char *)anAssociation->GetName(), // association name (char *)anAssociation->GetRole1()->GetClass()->GetName(), // class A name (char *)anAssociation->GetRole2()->GetClass()->GetName()); // class B name } printf("End Example #3.\n\n"); // End Example #3. // Example #4: Creating collections for local use printf("Example #4: Creating collections for local use\n"); // The instanciable classes are only those figuring in the registry. // (HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Rose.*) IRoseRoleCollectionPtr rootRoles(L"Rose.RoleCollection"); for(i=1; i<=rootAssociations->GetCount(); i++) { IRoseAssociationPtr anAssociation = rootAssociations->GetAt(i); rootRoles->Add(anAssociation->GetRole1()); rootRoles->Add(anAssociation->GetRole2()); } printf("Number of associations: %d\nNumber of roles: %d\n", rootAssociations->GetCount(), rootRoles->GetCount()); printf("List of all Role class names in the Logical View:\n"); for(i=1; i<=rootRoles->GetCount(); i++) { IRoseRolePtr aRole = rootRoles->GetAt(i); printf("%s\n", (char *)aRole->GetClass()->GetName()); } printf("End Example #4.\n\n"); // End Example #4. // Ends the Rose application //roseApp->PutVisible(false); // Exit will not work without that //roseApp->Exit(); } // Force the destructors in the previous block to be executed // i.e. releases all used interfaces. // We still have to Release lpDispatch // That's the point where rose.exe dies if we called Exit lpDispatch->Release(); // Uninitialize the COM library. CoUninitialize(); return 0; }