GME  13
MakeSimpleClosure.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "MakeSimpleClosure.h"
00003 #include "GUIDCreate.h"
00004 #include <algorithm>
00005 
00006 //---------------------------------------------------------------------------
00007 //  C  L  A  S  S   CSimpleSelectClosure
00008 //                  enabler of SmartCopy
00009 //---------------------------------------------------------------------------
00010 #define GLOBAL_ID_STR   "guid"
00011 
00012 bool CSimpleSelectClosure::isValidSelection()
00013 {
00014         // be more permissive than the base class
00015         // allows connections thru refport also
00016         return true;
00017 }
00018 
00019 void CSimpleSelectClosure::manageGuid( CComObjPtr<IMgaObject> object)
00020 {
00021         if( object)
00022         {
00023                 CComObjPtr<IMgaRegNode> regnode;
00024 
00025                 CComObjPtr<IMgaFCO> fco;
00026                 object.QueryInterface( fco);
00027                 if( fco) COMTHROW( fco->get_RegistryNode( CComBSTR( GLOBAL_ID_STR), PutOut( regnode)));
00028                 else
00029                 {
00030                         CComObjPtr<IMgaFolder> folder;
00031                         object.QueryInterface( folder);
00032                         if( folder) COMTHROW( folder->get_RegistryNode( CComBSTR( GLOBAL_ID_STR), PutOut( regnode)));
00033                         else ASSERT(0);
00034                 }
00035 
00036                 // in case object is in Library, do not write anything into registry
00037                 VARIANT_BOOL vbLibrary;
00038                 COMTHROW( object->get_IsLibObject( &vbLibrary ) );
00039 
00040                 if( regnode && !vbLibrary)
00041                 {
00042                         long status;
00043                         COMTHROW( regnode->get_Status(&status) );
00044                         if( status != ATTSTATUS_HERE) //UNDEFINED, METADEF, INVALID, ARCHETYPE1,2,...
00045                                 COMTHROW( regnode->put_Value( GuidCreate::newGuid()));
00046                 }
00047         }
00048 }
00049 
00050 // there is not much magic: process down the hierarchy (folders and models)
00051 void CSimpleSelectClosure::procObj( IMgaObject* obj)
00052 {
00053         ASSERT( obj != NULL );
00055         //if ( m_iIntoLibraries != LIB_CONT && isInLibrary( obj)) // if no intention to step into libraries and the object is in a library then return
00056         //      return;
00057         // library elements are handled the same way as the usual objects, 
00058         // except no guids are stored in their registry
00059 
00060         objtype_enum objtype;
00061         COMTHROW( obj->get_ObjType( &objtype) );
00062 
00063         // now mark the object itself (with a guid), later mark its dependents (ref, mem)
00064         manageGuid( obj);
00065 
00066         switch( objtype)
00067         {
00068         case OBJTYPE_FOLDER:
00069                 {
00070                         if ( m_bFolderContainment)
00071                         {
00072                                 CComObjPtr<IMgaFolder> f;
00073                                 COMTHROW( ::QueryInterface( obj, f) );
00074                                 procFolder( f);
00075                         }
00076                         break;
00077                 }
00078         case OBJTYPE_MODEL:
00079                 {
00080                         if ( m_bContainment)
00081                         {
00082                                 CComObjPtr<IMgaModel> m;
00083                                 COMTHROW( ::QueryInterface( obj, m) );
00084 
00085                                 procModel( m);
00086                         }
00087                         break;
00088                 }
00089 
00090         case OBJTYPE_ATOM: break;
00091         case OBJTYPE_REFERENCE:
00092                 {
00093                         CComObjPtr<IMgaReference> r;
00094                         COMTHROW( ::QueryInterface( obj, r) );
00095 
00096                         // mark its referred object (if any)
00097                         CComObjPtr<IMgaFCO> refd;
00098                         COMTHROW( r->get_Referred( PutOut( refd)));
00099                         manageGuid( CComObjPtr<IMgaObject>( refd));
00100                         break;
00101                 }
00102         case OBJTYPE_CONNECTION:
00103                 {
00104                         CComObjPtr<IMgaConnection> c;
00105                         COMTHROW( ::QueryInterface( obj, c) );
00106                         
00107                         CComObjPtrVector<IMgaConnPoint> cps;
00108                         COMTHROW( c->get_ConnPoints( PutOut( cps)));
00109                         for( unsigned int i = 0; i < cps.size(); ++i)
00110                         {
00111                                 // mark the endpoint
00112                                 CComObjPtr<IMgaFCO> target;
00113                                 COMTHROW( cps[i]->get_Target(PutOut(target)) );
00114                                 manageGuid( CComObjPtr<IMgaObject>( target));
00115 
00116                                 // mark the ref chain
00117                                 CComObjPtrVector<IMgaFCO> refs;
00118                                 COMTHROW( cps[i]->get_References(PutOut(refs)) );
00119                                 for( unsigned int i = 0; i < refs.size(); ++i)
00120                                         manageGuid( CComObjPtr<IMgaObject>( refs[i]));
00121                         }
00122 
00123                         break;
00124                 }
00125         case OBJTYPE_SET:
00126                 {
00127                         CComObjPtr<IMgaSet> s;
00128                         COMTHROW( ::QueryInterface( obj, s) );
00129                         CComObjPtrVector<IMgaFCO> mems;
00130                         COMTHROW( s->get_Members( PutOut( mems)));
00131                         for( unsigned int i = 0; i < mems.size(); ++i)
00132                                 manageGuid( CComObjPtr<IMgaObject>( mems[i]));
00133                         break;
00134                 }
00135         };
00136 }
00137 
00138 void CSimpleSelectClosure::preProcess()
00139 {
00140         send2Console("[Smart Copy] Working...");
00141 }
00142 
00143 void CSimpleSelectClosure::postProcess()
00144 {
00145         //remove specified unneeded kinds 
00146         if( removeExcludedKinds()) 
00147         {   // all objects were removed by the filter
00148                 send2Console( "[Smart Copy] No object in selection.");
00149                 return;
00150         }
00151 
00152         // sort the elements based on: basetypes first, connections last rule
00153         std::sort( m_selFcos.begin(), m_selFcos.end(), ConnsAndDerivsLast());
00154 
00155         selectTop(); // calculate the parentless objects
00156         autoWrap();  // wrapping (resets the Top values)
00157                      // normally if objects selected from the View
00158                      // would not wrap much
00159                      // if initial objects selected from the activebrowser
00160                      // it might have to do something
00161         
00162         checkMeta( m_topFolds, m_topFcos); // calculate the accepting kind
00163 
00164         std::string res_str;
00165         getAccKindsInString( res_str);
00166         if( !res_str.empty()) send2Console( "[Smart Copy] The following kinds may accept the copied data: " + res_str + ".");
00167         else send2Console( "[Smart Copy] Possible accepting kind not found based on the meta.");
00168 }
00169 
00170 bool CSimpleSelectClosure::removeExcludedKinds()
00171 {
00172         // we filter out the excluded kinds even from the initially selected objects
00173         // that is why we don't use the base's kindfilter mechanism (that filters out
00174         // only children of models, folders)
00175         // worth to mention: connections are initially selected by the GUI if both of
00176         // their ends is selected also, thus it may happen that the user would like
00177         // connections excluded, but if they are initially selected by the mechanism
00178         // outlined above then the base's filter would not catch that
00179         CComObjPtrVector<IMgaFCO>::iterator it = m_selFcos.begin();
00180         while( it != m_selFcos.end())
00181         {
00182                 CComQIPtr<IMgaAtom> a = *it;
00183                 CComQIPtr<IMgaConnection> c = *it;
00184                 CComQIPtr<IMgaReference> r = *it;
00185                 CComQIPtr<IMgaSet> s = *it;
00186 
00187                 if( m_bExclAtom && a // if atom and atoms need to be excluded OR
00188                  || m_bExclConn && c // ...
00189                  || m_bExclRef  && r
00190                  || m_bExclSet  && s)
00191                         it = m_selFcos.erase( it); // erase will step forward the iterator
00192                 else
00193                         ++it;
00194         }
00195         
00196         return m_selFcos.size() + m_selFolds.size() == 0; // all objects were removed by the filter
00197 }
00198 
00199 bool ConnsAndDerivsLast::operator()( const CComObjPtr<IMgaFCO>& p1, const CComObjPtr<IMgaFCO>& p2) const
00200 {
00201         // used for sort. 
00202         // 0th rule: derived types will be put after the archetypes
00203         // 1st rule: Connections will be put in the back of the vector
00204         // 2nd rule: if the two elements are both connections or none of them is connection then sort on ID
00205         // returns true if p1 precedes p2
00206 
00207         objtype_enum objtype1, objtype2;
00208         CComObjPtr<IMgaFCO> bas1, bas2;
00209         COMTHROW( p1->get_ArcheType( PutOut(bas1))); // returns 0 for archetypes
00210         COMTHROW( p2->get_ArcheType( PutOut(bas2)));
00211         bool p1_is_der = bas1 != 0;
00212         bool p2_is_der = bas2 != 0;
00213         COMTHROW( p1->get_ObjType( &objtype1));
00214         COMTHROW( p2->get_ObjType( &objtype2));
00215 
00216         // compare on deriv or not?
00217         bool sim = objtype1 == objtype2; 
00218         if( sim && p1_is_der != p2_is_der)
00219                 return p2_is_der;//IF p1 is F, p2 is T ->ret true, IF p1 is T, p2 is F ->ret false
00220 
00221         // sim is F or p1_is_der == p2_is_der
00222 
00223         // compare on conn or not?
00224         bool c1 = objtype1 == OBJTYPE_CONNECTION;
00225         bool c2 = objtype2 == OBJTYPE_CONNECTION;
00226 
00227         if( c1 == c2)
00228         {
00229                 //return true;// the predicate must be a strict weak ordering, so let's compare the IDs
00230                 CComBstrObj bstr1, bstr2;
00231                 COMTHROW( p1->get_ID( PutOut( bstr1)));
00232                 COMTHROW( p2->get_ID( PutOut( bstr2)));
00233                 return bstr1.Compare( bstr2) < 0;
00234         }
00235         else 
00236                 return c2; // IF c2 is T, c1 is F -> ret true, IF c2 is F, c1 is T ->ret false
00237 }