GME  13
MgaParserSC.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "Parser.h"
00003 #include "MgaParser.h"
00004 #include <xercesc/util/PlatformUtils.hpp>
00005 #include <xercesc/parsers/SAXParser.hpp>
00006 #include <stdio.h>
00007 #include <algorithm>
00008 
00009 #include "../Common/CommonCollection.h"
00010 #include "../Common/CommonMgaTrukk.h"
00011 #include <list>//slist
00012 #include "helper.h"
00013 #include "GUIDcreate.h"
00014 
00015 // --------------------------- CMgaParser - copy closure dumped data parsing
00016 
00017 STDMETHODIMP CMgaParser::ParseClos4(IMgaObject *here, BSTR filename, int options)
00018 {
00019         CHECK_IN(here);
00020 
00021         try
00022         {
00023                 COMTHROW( progress.CoCreateInstance(L"Mga.MgaProgressDlg") );
00024                 COMTHROW( progress->SetTitle(_bstr_t(L"Importing SmartCopied XML data...")) );
00025                 COMTHROW( progress->StartProgressDialog(NULL) );
00026 
00027                 CComObjPtr<IMgaProject> p;
00028                 COMTHROW( here->get_Project(PutOut(p)) );
00029                 ASSERT( p != NULL );
00030                 COMTHROW( p->get_Preferences(&project_prefs_orig) );
00031                 manual_relid_mode = project_prefs_orig & MGAPREF_MANUAL_RELIDS ? true : false;
00032 
00033                 m_GME = get_GME( p);//by zolmol
00034 
00035                 COMTHROW( p->Notify(APPEVENT_XML_IMPORT_SPECIAL_BEGIN));
00036 
00037                 COMTHROW( p->CreateTerritory(NULL, PutOut(territory), NULL) );
00038                 COMTHROW( p->BeginTransaction(territory, TRANSACTION_NON_NESTED) );
00039 
00040                 CComObjPtr<IMgaObject> target;
00041                 COMTHROW(territory->OpenObj(here, PutOut(target)));
00042 
00043                 //by zolmol
00044                 m_maintainGuids = false; // do not preserve guids found in data pasted
00045                 m_mergeAllowed = (options & MERGE) != 0;
00046                 m_target = target;
00047                 m_resolveDerFuncPtr = &CMgaParser::ResolveClosure4Derivation;
00048                 m_clVerStr = _T("4");//end
00049 
00050                 project_prefs = project_prefs_orig | MGAPREF_IGNORECONNCHECKS;
00051                 COMTHROW( p->put_Preferences(project_prefs) );
00052 
00053                 COMTHROW( resolver.CoCreateInstance(L"Mga.MgaResolver") );
00054                 ASSERT( resolver != NULL );
00055 
00056                 project = p;
00057 
00058                 CopyTo(filename, xmlfile);
00059 
00060                 XMLPlatformUtilsTerminate_RAII term;
00061                 try
00062                 {
00063                         XMLPlatformUtils::Initialize();
00064 
00065                         SAXParser parser;
00066                         parser.setValidationScheme(SAXParser::Val_Always);
00067                         parser.setDocumentHandler(this);
00068                         parser.setErrorHandler(this);
00069                         parser.setEntityResolver(this);
00070 
00071                         funcTableState = SC_MGA;
00072                         //elementfuncs = elementfuncs_scmga;
00073 
00074                         // manual first pass
00075 
00076                         pass_count = 1;
00077 
00078                         ranges.clear();
00079                         ranges.push_front(range_type());
00080                         ranges.front().begin = 1;
00081                         ranges.front().end = (counter_type)-1;
00082                         ranges.front().previous.name = _T("start");
00083                         ranges.front().previous.object = target;
00084                         skip_element_level = 0;
00085                         
00086                         parser.parse(xmlfile.c_str());
00087 
00088                         ASSERT( ranges.front().begin == 1 );
00089                         ranges.pop_front();
00090                         elements.clear();
00091 
00092                         max_counter = counter;
00093 
00094                         // the other passes
00095 
00096                         parser.setValidationScheme(SAXParser::Val_Never);
00097 
00098                         while( !ranges.empty() && ranges.front().begin != (counter_type)-1 )
00099                         {
00100                                 // FIXME: better algorithm for infinite loop
00101                                 if( ++pass_count >= 1 )//<!> reduced from 100 to 5
00102                                 {
00103                                         msgSC( CComBSTR(L"Exception during parsing."), MSG_ERROR);
00104                                         HR_THROW(E_TOOMANYPASSES);
00105                                 }
00106 
00107                                 parser.parse(xmlfile.c_str());
00108                         }
00109 
00110                         ASSERT( elements.empty() );
00111                         ranges.clear();
00112 
00113                         if( isNeedFor2ndStep())
00114                         {
00115                                 CComBSTR bstr1(L"Some objects were not found during parsing.");
00116                                 CComBSTR bstr2(L"Invoking 2nd step...");
00117                                 msgSC( bstr1, MSG_ERROR);
00118                                 msgSC( bstr2, MSG_INFO);
00119                                 
00120                                 tryToFindMissedReferreds();
00121                                 tryToFindMissedSetMembers();
00122                         }
00123                 }
00124             catch(const XMLException &e)
00125                 {
00126                         XmlStr desc(e.getMessage());
00127 
00128                         ThrowXmlError(L"%s", desc.c_str());
00129                 }
00130                 COMTHROW( project->put_Preferences(project_prefs_orig) );
00131 
00132                 for(librecords::reverse_iterator i = libstodo.rbegin(); i != libstodo.rend(); ++i) { // copied from ParseProject in order to recognize libraries (zolmol)
00133                         COMTHROW(i->f->put_LibraryName(CComBSTR(i->libname.c_str())));
00134                         COMTHROW(i->f->put_Exempt(VARIANT_FALSE));
00135                 }
00136                 libstodo.clear();
00137 
00138                 COMTHROW( project->CommitTransaction() );
00139                 COMTHROW( project->Notify(APPEVENT_XML_IMPORT_SPECIAL_END));
00140                 project = NULL;
00141                 clear_GME( m_GME);
00142 
00143                 CloseAll();
00144         }
00145         catch(hresult_exception &e)
00146         {
00147                 CloseAll();
00148                 // in case we rethrew the [probably MGA originated] exception 
00149                 // we have set into errorinfo the location info
00150                 if( m_GME)
00151                         COMTHROW(m_GME->ConsoleMessage( errorinfo, MSG_ERROR));
00152                 clear_GME( m_GME);
00153 
00154                 ASSERT( FAILED(e.hr) );
00155                 if( e.hr == E_XMLPARSER )
00156                         SetErrorInfo(errorinfo);
00157                 else
00158                         SetErrorInfo2(e.hr);
00159 
00160                 return e.hr;
00161         }
00162         return S_OK;
00163 }
00164 
00165 CMgaParser::elementfunc CMgaParser::elementfuncs_scmga[] = // special handlers for all elements
00166 {
00167         //elementfunc(_T("project"),  StartProject,      EndNone),
00168         elementfunc(_T("name"),       StartNone,         EndSCName),
00169         //elementfunc(_T("comment"),  StartNone,         EndComment),
00170         //elementfunc(_T("author"),   StartNone,         EndAuthor),
00171         elementfunc(_T("value"),      StartNone,         EndSCValue),
00172         elementfunc(_T("regnode"),    StartSCRegNode,    EndSCRegNode),
00173         elementfunc(_T("attribute"),  StartSCAttribute,  EndNone),
00174         elementfunc(_T("constraint"), StartNone,         EndSCConstraint),
00175         elementfunc(_T("folder"),     StartSCFolder,     EndNone),
00176         elementfunc(_T("model"),      StartSCModel,      EndNone),
00177         elementfunc(_T("atom"),       StartSCAtom,       EndNone),
00178         elementfunc(_T("connection"), StartSCConnection, EndSCConnection),
00179         elementfunc(_T("connpoint"),  StartSCConnPoint,  EndNone),
00180         elementfunc(_T("reference"),  StartSCReference,  EndNone),
00181         elementfunc(_T("set"),        StartSCSet,        EndNone),
00182         elementfunc(_T("clipboard"),  StartBCClipboard,  EndNone),      // common for closures
00183         elementfunc(_T(""), NULL, NULL)
00184 };
00185 
00186 void CMgaParser::ResolveClosure4Derivation(const attributes_type &attributes, deriv_type &deriv)
00187 {
00188         const std::tstring *s = GetByNameX(attributes, _T("derivedfrom"));
00189         if( s == NULL )
00190         {
00191                 s = GetByNameX(attributes, _T("closurelibderivedfrom"));
00192                 if( s != NULL)
00193                 {
00194                         CComObjPtr<IMgaObject> obj;
00195                         findObjOnAbsPath( project, *s, obj, _T("archetype"));
00196                         if( obj)
00197                                 COMTHROW( obj.QueryInterface( deriv.from));
00198                         else
00199                         {
00200                                 CComBSTR bstr(L"Archetype can not be found in library. Basetype lost. ");
00201                                 COMTHROW(bstr.Append(L"Search path used: "));
00202                                 COMTHROW(bstr.Append( makeViewable(*s).c_str()));
00203                                 msgSC( bstr, MSG_ERROR);
00204                         }
00205 
00206                 }
00207                 else //if( s == NULL)
00208                 {
00209                         const std::tstring* g;
00210                         g = GetByNameX( attributes, _T("smartDerivedFromGUID"));
00211                         s = GetByNameX( attributes, _T("closure2derivedfrom"));
00212 
00213                         std::tstring rel_path_changed = s? *s: _T("");
00214                         // since the derfrom is calculated relatively to the fco, 
00215                         // we have to modify the path so that it could be found
00216                         // with a search starting from its container
00217                         if( rel_path_changed.substr(0, 4) == _T("/@.."))
00218                                 rel_path_changed = rel_path_changed.substr(4);
00219                         // else: the object has similar name to its archetype
00220                         // else: the derfrom object cannot be inside the derived object
00221 
00222                         CComObjPtr<IMgaObject> place;
00223                         GetPrevObj(place);
00224 
00225                         if( g != NULL)
00226                         {
00227                                 if( s != NULL) // try a combined search stepping up in the hierarchy then use guid
00228                                         findFCOWithRelPathAndGUID( place, rel_path_changed, *g, deriv.from);
00229 
00230                                 if( !deriv.from) // not found, then search in the whole project with GUID
00231                                 {
00232                                         CComObjPtr<IMgaProject> pr;
00233                                         COMTHROW( place->get_Project( PutOut( pr)));
00234                                         CComObjPtr<IMgaFolder>  rf;
00235                                         COMTHROW( pr->get_RootFolder( PutOut( rf)));
00236                                         findFCOWithGUIDInTree( CComObjPtr<IMgaObject>( rf), *g, deriv.from);
00237                                 }
00238                         }
00239 
00240                         if( !deriv.from && s != NULL)
00241                         {
00242                                 CComObjPtr<IMgaObject> obj;
00243                                 findObjOnRelPath( CComObjPtr<IMgaObject>(place), rel_path_changed, obj, _T("archetype"));
00244 
00245                                 if( obj)
00246                                         COMTHROW( obj.QueryInterface( deriv.from));
00247                                 else // error report
00248                                 {
00249                                         CComBSTR bstr(L"Archetype can not be found. Basetype lost. ");
00250                                         COMTHROW(bstr.Append(L"Search path used: "));
00251                                         COMTHROW(bstr.Append( makeViewable(rel_path_changed).c_str()));
00252                                         msgSC( bstr, MSG_ERROR);
00253                                 }
00254                         }
00255                 }
00256 
00257 
00258                 if ( deriv.from == NULL) // do not throw exception in case of closurelibderivedfrom
00259                 {
00260                         deriv.from.Release();
00261                         return;
00262                 }
00263         }
00264         else
00265         {
00266                 LookupByID(*s, deriv.from);
00267 
00268                 if( deriv.from == NULL )
00269                         throw pass_exception();
00270         }
00271 
00272         s = GetByNameX(attributes, _T("isinstance"));
00273         deriv.isinstance = ( s != NULL && *s == _T("yes") ) ? VARIANT_TRUE : VARIANT_FALSE;
00274 
00275         s = GetByNameX(attributes, _T("isprimary"));
00276         deriv.isprimary = ( s != NULL && *s == _T("no") ) ? false : true;
00277 }
00278 
00279 // ------- Element Handlers
00280 void CMgaParser::StartSCConnection(const attributes_type &attributes)
00281 {
00282         bool skip_inner_elements = false;
00283         CComObjPtr<IMgaFCO> conn;
00284         deriv_type deriv;
00285         //ResolveDerivation(attributes, deriv);
00286         (*this.*m_resolveDerFuncPtr)(attributes, deriv);
00287 
00288         if( GetPrevName() == _T("folder") )
00289         {
00290                 CComObjPtr<IMgaFolder> prev;
00291                 GetPrevObj(prev);
00292 
00293                 preparerelid(attributes);
00294                 if( deriv.from != NULL )
00295                 {
00296                         COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(conn)) );
00297 
00298                         // user info
00299                         CComBSTR msg = makeLink( conn, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
00300                         COMTHROW(msg.Append( L" connection derived from "));
00301                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
00302                         msgSC( msg, MSG_INFO);
00303                 }
00304                 else
00305                 {
00306                         CComObjPtr<IMgaMetaFCO> meta;
00307                         COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, _T("kind")), 
00308                                 OBJTYPE_CONNECTION, PutOut(meta)) );
00309                         ASSERT( meta != NULL );
00310 
00311                         COMTHROW( prev->CreateRootObject(meta, PutOut(conn)) );
00312                 }
00313                 assignrelid(conn);
00314         }
00315         else
00316         {
00317                 ASSERT( GetPrevName() == _T("model") );
00318 
00319                 CComObjPtr<IMgaModel> prev;
00320                 GetPrevObj(prev);
00321 
00322                 CComObjPtr<IMgaMetaRole> role;
00323                 COMTHROW( resolver->get_RoleByStr(prev, 
00324                         PutInBstrAttr(attributes, _T("kind")), OBJTYPE_CONNECTION,
00325                         PutInBstrAttr(attributes, _T("role")), NULL, PutOut(role)) );
00326                 ASSERT( role != NULL );
00327 
00328                 if( deriv.from != NULL )
00329                 {
00330                         CComObjPtr<IMgaConnection> derivedfrom;
00331                         COMTHROW( deriv.from.QueryInterface(derivedfrom) );
00332 
00333                         if( deriv.isprimary )
00334                         {
00335                                 preparerelid(attributes);
00336                                 COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(conn)) );
00337                                 assignrelid(conn);
00338                         }
00339                         else
00340                         {
00341                                 COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(conn)) );
00342                         }
00343 
00344                         // user info
00345                         CComBSTR msg = makeLink( conn, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
00346                         COMTHROW(msg.Append( L" connection derived from "));
00347                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
00348                         msgSC( msg, MSG_INFO);
00349                 }
00350                 else
00351                 {
00352                         // 'attributes' contains the id of the object (in the source project)
00353                         bool found = findObject( prev, attributes, conn, 'C');
00354 
00355                         // create only if not found 
00356                         if( !found)
00357                         {
00358                                 // parse the connection end info
00359                                 CComObjPtr<IMgaFCO> o1, o2;
00360                                 CComObjPtr<IMgaFCOs> chain1, chain2;
00361                                 parseConnection( CComObjPtr<IMgaObject>( prev), attributes, o1, o2, chain1, chain2);
00362                                 if( o1 && o2)
00363                                 {
00364                                         preparerelid(attributes);
00365                                         COMTHROW( prev->CreateSimpleConn( role, o1, o2, chain1, chain2, PutOut(conn)));
00366                                         assignrelid(conn);
00367 
00368                                         // user info
00369                                         CComBSTR msg = makeLink( conn, makeNameViewable( GetByName(attributes, _T("closurename"))));
00370                                         COMTHROW(msg.Append( L" connection created."));
00371                                         msgSC( msg, MSG_INFO);
00372                                 }
00373                                 else
00374                                 {
00375                                         // error, could not find a correct reference chain
00376                                         CComBSTR bstr(L"Connection \"");
00377                                         COMTHROW(bstr.Append( makeNameViewable( GetByName(attributes, _T("closurename"))).c_str()));
00378                                         COMTHROW(bstr.Append(L"\": could not be created."));
00379                                         msgSC( bstr, MSG_ERROR);
00380 
00381                                         bstr.Empty();
00382                                         COMTHROW(bstr.Append(L"   Reference chain involved: "));
00383                                         if( !o1) 
00384                                                 COMTHROW(bstr.Append( makeViewable( GetByName( attributes, _T("smart0RefChain") )).c_str()));
00385                                         else if( !o2) 
00386                                                 COMTHROW(bstr.Append( makeViewable( GetByName( attributes, _T("smart1RefChain") )).c_str()));
00387                                         msgSC( bstr, MSG_ERROR);
00388 
00389                                         bstr.Empty();
00390                                         COMTHROW(bstr.Append(L"   Target path used: "));
00391                                         if( !o1)
00392                                                 COMTHROW(bstr.Append( makeViewable( GetByName( attributes, _T("smart0Target") )).c_str()));
00393                                         else if( !o2) 
00394                                                 COMTHROW(bstr.Append( makeViewable( GetByName( attributes, _T("smart1Target") )).c_str()));
00395                                         msgSC( bstr, MSG_ERROR);
00396 
00397                                         // to safely pass through hard times (parsing internal connpoints, attributes, regnodes...
00398                                         // we create a temporary connection with "handicapped" extrsinfo
00399                                         // which will be deleted by EndSCConnection
00400                                         
00401                                         preparerelid(attributes);
00402                                         COMTHROW( prev->CreateChildObject(role, PutOut(conn)) );
00403                                         assignrelid(conn);
00404                                         
00405                                         GetCurrent().exstrinfo = _T("handicapped");
00406                                 }
00407                         }
00408                         else // will skip contained elements/attribute values/regnode entries/constraints/name element
00409                         {    // will use the object found
00410                                 skip_inner_elements = true;
00411 
00412                                 // user info
00413                                 CComBSTR msg = L"Merging ";
00414                                 COMTHROW(msg.AppendBSTR(makeLink( conn)));
00415                                 COMTHROW(msg.Append( L" connection."));
00416                                 msgSC( msg, MSG_INFO);
00417                         }
00418 
00419                 }
00420         }
00421         ASSERT( conn != NULL );
00422         GetCurrent().object = conn;
00423 
00424         if( GetByName(attributes, _T("isbound")) == _T("yes") 
00425                 || skip_inner_elements) 
00426                 GetCurrent().exstrinfo = _T("skip");
00427 
00428         RegisterLookup(attributes, conn);
00429 }
00430 
00431 bool CMgaParser::findConnectionEnd
00432                 ( CComObjPtr<IMgaObject> pPrev
00433                 , const std::tstring& isbound
00434                 , const std::tstring& role
00435                 , const std::tstring& targetGUID
00436                 , const std::tstring& targetPATH
00437                 , const std::tstring& refchainGUID
00438                 , const std::tstring& refchainPATH
00439                 , CComObjPtr<IMgaFCO>& pFoundObj
00440                 , CComObjPtr<IMgaFCOs>& pFoundRefChain
00441                 )
00442 {
00443         std::vector< std::tstring> guid_closure_ref_vec;
00444         if( !refchainGUID.empty())
00445         {
00446                 int pos = refchainGUID.find_first_not_of(' ', 0);
00447                 ASSERT( pos >= 0 );
00448                 while( pos < (int) refchainGUID.length() )
00449                 {
00450                         int pos2 = refchainGUID.find_first_of(' ', pos);
00451                         if( pos2 < 0 )
00452                                 pos2 = refchainGUID.length();
00453                         ASSERT( pos2 > pos );
00454 
00455                         
00456                         guid_closure_ref_vec.push_back( std::tstring(refchainGUID, pos, pos2-pos));
00457                         pos = pos2+1;
00458                 }
00459         }
00460 
00461         std::vector< std::tstring> name_closure_ref_vec;
00462         if( !refchainPATH.empty())
00463         {
00464                 int pos = refchainPATH.find_first_not_of(' ', 0);
00465                 ASSERT( pos >= 0 );
00466                 while( pos < (int) refchainPATH.length() )
00467                 {
00468                         int pos2 = refchainPATH.find_first_of(' ', pos);
00469                         if( pos2 < 0 )
00470                                 pos2 = refchainPATH.length();
00471                         ASSERT( pos2 > pos );
00472 
00473                         
00474                         name_closure_ref_vec.push_back( std::tstring(refchainPATH, pos, pos2-pos));
00475                         pos = pos2+1;
00476                 }
00477         }
00478 
00479         if( guid_closure_ref_vec.size() < name_closure_ref_vec.size()) 
00480                 guid_closure_ref_vec.clear(); // invalid guid chain string info
00481 
00482         // will try to reconstruct the reference chain (into pFoundRefChain) based on the refs and closure2refs attribute value
00483         COMTHROW( pFoundRefChain.CoCreateInstance(L"Mga.MgaFCOs"));
00484 
00485         CComObjPtr<IMgaModel> container; // this is the container we will look in for the target
00486 
00487         if( !guid_closure_ref_vec.empty())
00488         {
00489                 // based on guid
00490 
00491                 // try to find the first elements in the ref chain inside the container where conn is present
00492                 CComObjPtr<IMgaFCO> next_obj;
00493                 CComObjPtr<IMgaFCO> last_obj; // this will be a model
00494 
00495                 // search based on closurerefs
00496                 findFCOWithGUID( CComObjPtr<IMgaObject>( pPrev), guid_closure_ref_vec[0], next_obj);
00497 
00498                 // we will build up the collection of references
00499                 unsigned int i;
00500                 for( i = 0; next_obj != 0 && i < guid_closure_ref_vec.size(); ++i)
00501                 {
00502                         // we don't have to deal with name_closure_ref_vec[i] except if i == 0
00503                         // just inquire the referred object by next_obj reference
00504 
00505                         objtype_enum type;
00506                         COMTHROW( next_obj->get_ObjType( &type));
00507                         if( type == OBJTYPE_REFERENCE)
00508                         {
00509                                 CComObjPtr<IMgaReference> ref;
00510                                 COMTHROW( next_obj.QueryInterface( ref));
00511                                 if( ref)
00512                                 {
00513                                         CComObjPtr<IMgaFCO> refd;
00514                                         COMTHROW( ref->get_Referred( PutOut( refd)));
00515                                         
00516                                         if( refd)
00517                                         {
00518                                                 // we could check the guid of refd against guid_closure_ref_vec[i]
00519                                                 
00520                                                 // put the latest valid reference at the end of the collection
00521                                                 COMTHROW(pFoundRefChain->Append(next_obj));
00522 
00523                                                 objtype_enum type;
00524                                                 COMTHROW( refd->get_ObjType( &type));
00525                                                 if( type == OBJTYPE_REFERENCE)
00526                                                         next_obj = refd;
00527                                                 else
00528                                                 {
00529                                                         next_obj = 0;
00530                                                         if( type == OBJTYPE_MODEL)
00531                                                                 last_obj = refd;
00532                                                 }
00533                                         }
00534                                 }
00535                         }
00536                 }
00537                 //  i == size should we check this?
00538                 if( i == guid_closure_ref_vec.size() && last_obj) COMTHROW( last_obj.QueryInterface( container));
00539         }
00540         
00541         if( !container && name_closure_ref_vec.size() > 0) // not found based on GUID
00542         {
00543                 // try to find the first elements in the ref chain inside the container where conn is present
00544 
00545                 CComObjPtr<IMgaFCO> next_obj;
00546                 CComObjPtr<IMgaFCO> last_obj; // this will be a model
00547 
00548                 CComObjPtr<IMgaObject> nx_obj;
00549 
00550                 // search based on closurerefs
00551                 findObjOnRelPath( CComObjPtr<IMgaObject>( pPrev), name_closure_ref_vec[0], nx_obj, _T("reference chain"));
00552                 if( nx_obj) COMTHROW( nx_obj.QueryInterface( next_obj));
00553 
00554                 // we will build up the collection of references
00555                 unsigned int i;
00556                 for( i = 0; next_obj != 0 && i < name_closure_ref_vec.size(); ++i)
00557                 {
00558                         // we don't have to deal with name_closure_ref_vec[i] except if i == 0
00559                         // just inquire the referred object by next_obj reference
00560 
00561                         objtype_enum type;
00562                         COMTHROW( next_obj->get_ObjType( &type));
00563                         if( type == OBJTYPE_REFERENCE)
00564                         {
00565                                 CComObjPtr<IMgaReference> ref;
00566                                 COMTHROW( next_obj.QueryInterface( ref));
00567                                 if( ref)
00568                                 {
00569                                         CComObjPtr<IMgaFCO> refd;
00570                                         COMTHROW( ref->get_Referred( PutOut( refd)));
00571                                         
00572                                         if( refd)
00573                                         {
00574                                                 // put the latest valid reference at the end of the collection
00575                                                 COMTHROW(pFoundRefChain->Append(next_obj));
00576 
00577                                                 objtype_enum type;
00578                                                 COMTHROW( refd->get_ObjType( &type));
00579                                                 if( type == OBJTYPE_REFERENCE)
00580                                                         next_obj = refd;
00581                                                 else
00582                                                 {
00583                                                         next_obj = 0;
00584                                                         if( type == OBJTYPE_MODEL)
00585                                                                 last_obj = refd;
00586                                                 }
00587                                         }
00588                                 }
00589                         }
00590                 }
00591 
00592                 // i == size should we check this?
00593                 if( i == name_closure_ref_vec.size() && last_obj) COMTHROW( last_obj.QueryInterface( container));
00594         }
00595 
00596         else // plain connection
00597         {
00598                 CComQIPtr<IMgaModel> m( pPrev);
00599                 container = m; // must be in a model
00600         }
00601 
00602 
00603         if( !container)
00604         {
00605                 //throw pass_exception();
00606                 //pFoundRefChain->removeall();
00607                 return false;
00608         }
00609         else    // container is a valid model
00610         {               // find the target object in it identified by targetGUID/targetPATH
00611                 if( !targetGUID.empty())
00612                 {
00613                         findFCOWithGUID( CComObjPtr<IMgaObject>( pPrev), targetGUID, pFoundObj);
00614                 }
00615                 
00616                 if( !pFoundObj && !targetPATH.empty())
00617                 {
00618                         CComObjPtr<IMgaObject> t_target;
00619                         findObjOnRelPath( CComObjPtr<IMgaObject>( pPrev), targetPATH, t_target, _T("target"));
00620                         if( t_target) COMTHROW( t_target.QueryInterface( pFoundObj));
00621                 }
00622         }
00623 
00624         return (pFoundObj != 0);
00625 }
00626 
00627 bool CMgaParser::parseConnection
00628                         ( CComObjPtr<IMgaObject> pPrev
00629                         , const attributes_type &pAttributes
00630                         , CComObjPtr<IMgaFCO>& pSrcObj
00631                         , CComObjPtr<IMgaFCO>& pDstObj
00632                         , CComObjPtr<IMgaFCOs>& pFoundSrcRefChain
00633                         , CComObjPtr<IMgaFCOs>& pFoundDstRefChain
00634                         )
00635 {
00636         const TCHAR *role_attr []       = { _T("smart0Role")         , _T("smart1Role")         };
00637         const TCHAR *targetGUID_attr [] = { _T("smart0TargetGUID")   , _T("smart1TargetGUID")   };
00638         const TCHAR *target_attr []     = { _T("smart0Target")       , _T("smart1Target")       };
00639         const TCHAR *refchainGUID_attr[]= { _T("smart0RefChainGUID") , _T("smart1RefChainGUID") };
00640         const TCHAR *refchain_attr []   = { _T("smart0RefChain")     , _T("smart1RefChain")     };
00641         const TCHAR *isbound_attr []    = { _T("smart0IsBound")      , _T("smart1IsBound")      };
00642 
00643         CComObjPtr<IMgaFCO> obj[2];
00644         CComObjPtr<IMgaFCOs> coll[2];
00645         for( int i = 0 ; i < 2; ++i)
00646         {
00647                 std::tstring isbound         = GetByName( pAttributes, isbound_attr[i]);
00648                 std::tstring role            = GetByName( pAttributes, role_attr[i]);
00649                 std::tstring targetGUID      = GetByName( pAttributes, targetGUID_attr[i]);
00650                 std::tstring refchainGUID    = GetByName( pAttributes, refchainGUID_attr[i]);
00651                 std::tstring target          = GetByName( pAttributes, target_attr[i]);
00652                 std::tstring refchain        = GetByName( pAttributes, refchain_attr[i]);
00653                 findConnectionEnd( pPrev, isbound, role, targetGUID, target, refchainGUID, refchain, obj[i], coll[i]);
00654         }
00655 
00656         if( obj[0] && obj[1]) 
00657         {
00658                 pSrcObj = obj[0];
00659                 pDstObj = obj[1];
00660                 pFoundSrcRefChain = coll[0];
00661                 pFoundDstRefChain = coll[1];
00662                 return true;
00663         }
00664 
00665         return false;
00666 }
00667 
00668 
00669 void CMgaParser::EndSCConnection()
00670 {
00671         CComObjPtr<IMgaConnection> fresh_conn;
00672 
00673         ASSERT( GetCurrent().object);
00674         COMTHROW( GetCurrent().object.QueryInterface( fresh_conn));
00675         if( !fresh_conn) 
00676         {
00677                 ASSERT(0); // it should be a connection at least
00678                 return;
00679         }
00680 
00681         CComObjPtrVector<IMgaConnPoint> cps;
00682         COMTHROW( fresh_conn->get_ConnPoints( PutOut( cps)));
00683         if( cps.size() < 2 || GetCurrent().exstrinfo == _T("handicapped")) // handicapped connection, error must have occurred
00684         {
00685                 COMTHROW( fresh_conn->DestroyObject());
00686                 return;
00687         }
00688 }
00689 
00690 void CMgaParser::StartSCConnPoint(const attributes_type &attributes)
00691 {
00692 }
00693 
00694 void CMgaParser::StartSCReference(const attributes_type &attributes)
00695 {
00696         CComObjPtr<IMgaObject> obj_prev;
00697         bool skip_inner_elements = false;
00698         bool needs_target = true;
00699         CComObjPtr<IMgaFCO> fco;
00700 
00701         deriv_type deriv;
00702         //ResolveDerivation(attributes, deriv);
00703         (*this.*m_resolveDerFuncPtr)(attributes, deriv);
00704 
00705         CComObjPtr<IMgaFCO> referred;
00706 
00707         if( GetPrevName() == _T("folder") )
00708         {
00709                 CComObjPtr<IMgaFolder> prev;
00710                 GetPrevObj(prev);
00711                 obj_prev = prev;
00712 
00713                 if( deriv.from != NULL )
00714                 {
00715                         preparerelid(attributes);
00716                         COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(fco)) );
00717                         assignrelid(fco);
00718 
00719                         // user info
00720                         CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
00721                         COMTHROW(msg.Append( _T(" reference derived from ")));
00722                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
00723                         msgSC( msg, MSG_INFO);
00724 
00725                 }
00726                 else
00727                 {
00728                         // 'attributes' contains the id of the object (in the source project)
00729                         bool found = findObject( prev, attributes, fco, 'R');
00730 
00731                         // create only if not found 
00732                         if( !found)
00733                         {
00734                                 CComObjPtr<IMgaMetaFCO> meta;
00735                                 COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, _T("kind")), 
00736                                         OBJTYPE_REFERENCE, PutOut(meta)) );
00737                                 ASSERT( meta != NULL );
00738 
00739                                 preparerelid(attributes);
00740                                 COMTHROW( prev->CreateRootObject(meta, PutOut(fco)) );
00741                                 assignrelid(fco);
00742 
00743                                 // user info
00744                                 CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))));
00745                                 COMTHROW(msg.Append( _T(" reference created.")));
00746                                 msgSC( msg, MSG_INFO);
00747                         }
00748                         else // will skip contained elements/attribute values/regnode entries/constraints/name element
00749                         {    // will use the object found
00750                                 skip_inner_elements = true;
00751                                 needs_target = isNullRef( fco);
00752 
00753                                 // user info
00754                                 CComBSTR msg = L"Merging ";
00755                                 COMTHROW(msg.AppendBSTR(makeLink( fco)));
00756                                 if( needs_target)
00757                                         COMTHROW(msg.Append(L" null"));
00758                                 COMTHROW(msg.Append( L" reference."));
00759                                 msgSC( msg, MSG_INFO);
00760                         }
00761                 }
00762         }
00763         else
00764         {
00765                 ASSERT( GetPrevName() == _T("model") );
00766 
00767                 CComObjPtr<IMgaModel> prev;
00768                 GetPrevObj(prev);
00769                 obj_prev = prev;
00770 
00771                 CComObjPtr<IMgaMetaRole> role;
00772                 COMTHROW( resolver->get_RoleByStr(prev, 
00773                         PutInBstrAttr(attributes, _T("kind")), OBJTYPE_REFERENCE,
00774                         PutInBstrAttr(attributes, _T("role")), NULL, PutOut(role)) );
00775                 ASSERT( role != NULL );
00776 
00777                 if( deriv.from != NULL )
00778                 {
00779                         CComObjPtr<IMgaReference> derivedfrom;
00780                         COMTHROW( deriv.from.QueryInterface(derivedfrom) );
00781 
00782                         if( deriv.isprimary )
00783                         {
00784                                 preparerelid(attributes);
00785                                 COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(fco)) );
00786                                 assignrelid(fco);
00787                         }
00788                         else
00789                         {
00790                                 COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(fco)) );
00791                         }
00792                         
00793                         // user info
00794                         CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
00795                         COMTHROW(msg.Append( L" reference derived from "));
00796                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
00797                         msgSC( msg, MSG_INFO);
00798                 }
00799                 else
00800                 {
00801                         // 'attributes' contains the id of the object (in the source project)
00802                         bool found = findObject( prev, attributes, fco, 'R');
00803 
00804                         // create only if not found 
00805                         if( !found)
00806                         {
00807                                 preparerelid(attributes);
00808                                 COMTHROW( prev->CreateChildObject(role, PutOut(fco)) );
00809                                 assignrelid(fco);
00810 
00811                                 // user info
00812                                 CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))));
00813                                 COMTHROW(msg.Append( L" reference created."));
00814                                 msgSC( msg, MSG_INFO);
00815                         }
00816                         else // will skip contained elements/attribute values/regnode entries/constraints/name element
00817                         {    // will use the object found
00818                                 skip_inner_elements = true;
00819                                 needs_target = isNullRef( fco);
00820 
00821                                 // user info
00822                                 CComBSTR msg = "LMerging ";
00823                                 COMTHROW(msg.AppendBSTR(makeLink( fco)));
00824                                 if( needs_target)
00825                                         COMTHROW(msg.Append(L" null"));
00826                                 COMTHROW(msg.Append( L" reference."));
00827                                 msgSC( msg, MSG_INFO);
00828                         }
00829                 }
00830 
00831         }
00832         ASSERT( fco != NULL );
00833         //fco is the reference just created or selected from the already existing ones
00834 
00835         bool bound = GetByName(attributes, _T("isbound")) == _T("yes"); // if bound it does NOT need referees set by hand
00836         if( needs_target && !bound)
00837         {
00838                 const std::tstring *s;
00839                 s = GetByNameX(attributes, _T("closurelibreferred"));
00840                 if( s != NULL)
00841                 {
00842                         CComObjPtr<IMgaObject> obj;
00843                         findObjOnAbsPath( project, *s, obj, _T("referred object"));
00844 
00845                         if( obj)
00846                                 COMTHROW( obj.QueryInterface( referred));
00847                         else // report error
00848                         {
00849                                 CComBSTR bstr("Reference ");
00850                                 COMTHROW(bstr.Append( makeLink( fco, makeNameViewable( GetByName( attributes, _T("closurename"))), true)));
00851                                 COMTHROW(bstr.Append(": target not found in library. "));
00852                                 COMTHROW(bstr.Append("Search path used: "));
00853                                 COMTHROW(bstr.Append( makeViewable( *s).c_str()));
00854                                 msgSC(bstr, MSG_ERROR);
00855                         }
00856                 }
00857                 
00858                 if( s == NULL || !referred)
00859                 {
00860                         // first try to find referred object based on GUID
00861                         std::tstring guid = GetByName(attributes, _T("smartReferredGUID"));
00862                         std::tstring path = GetByName(attributes, _T("closure2referred"));
00863                         
00864                         if( !guid.empty())
00865                         {
00866                                 if( !path.empty())
00867                                 {
00868                                         // use closure2referred info for stepping up in the hierarchy (if needed) and only then use search on GUID
00869                                         findFCOWithRelPathAndGUID( CComObjPtr<IMgaObject>( fco), path, guid, referred);
00870                                 }
00871                                 
00872                                 if( !referred) // not found, then search in the whole project with GUID
00873                                 {
00874                                         CComObjPtr<IMgaProject> pr;
00875                                         COMTHROW( obj_prev->get_Project( PutOut( pr)));
00876                                         CComObjPtr<IMgaFolder>  rf;
00877                                         COMTHROW( pr->get_RootFolder( PutOut( rf)));
00878                                         findFCOWithGUIDInTree( CComObjPtr<IMgaObject>( rf), guid, referred);
00879                                 }
00880                         }
00881                         
00882                         // finally perform a closure2referred based search
00883                         if( !referred && !path.empty())
00884                         {
00885                                 CComObjPtr<IMgaObject> obj;
00886                                 findObjOnRelPath( CComObjPtr<IMgaObject>(fco), path, obj, _T("referred object"));
00887 
00888                                 if ( obj)
00889                                         COMTHROW( obj.QueryInterface( referred));
00890                                 else // report error
00891                                 {
00892                                         CComBSTR bstr("Reference ");
00893                                         COMTHROW(bstr.Append( makeLink( fco, makeNameViewable( GetByName( attributes, _T("closurename"))), true)));
00894                                         COMTHROW(bstr.Append(": target not found. "));
00895                                         COMTHROW(bstr.Append("Search path used: "));
00896                                         COMTHROW(bstr.Append( makeViewable( path).c_str()));
00897                                         msgSC(bstr, MSG_ERROR);
00898 
00899                                         // store data to process in 2nd step
00900                                         m_notFoundReferredObject[ fco ] = path;
00901                                 }
00902                         }
00903                 }
00904 
00905                 //WAS: if( !(GetByName(attributes, "isbound") == "yes") && referred != NULL )
00906                 if( referred != NULL )
00907                 {
00908                         CComObjPtr<IMgaReference> ref;
00909                         COMTHROW( fco.QueryInterface(ref) );
00910 
00911                         COMTHROW( ref->put_Referred(referred) );
00912                 }
00913         }
00914 
00915         GetCurrent().object = fco;
00916         if( skip_inner_elements)
00917                 GetCurrent().exstrinfo = _T("skip");
00918 
00919         RegisterLookup(attributes, fco);
00920 }
00921 
00922 void CMgaParser::StartSCSet(const attributes_type &attributes)
00923 {
00924         CComObjPtr<IMgaObject> obj_prev;
00925         bool skip_inner_elements = false;
00926         bool needs_members = true;
00927         CComObjPtr<IMgaFCO> fco;
00928 
00929         deriv_type deriv;
00930         //ResolveDerivation(attributes, deriv);
00931         (*this.*m_resolveDerFuncPtr)(attributes, deriv);
00932 
00933         if( GetPrevName() == _T("folder") )
00934         {
00935                 CComObjPtr<IMgaFolder> prev;
00936                 GetPrevObj(prev);
00937                 obj_prev = prev;
00938 
00939                 if( deriv.from != NULL )
00940                 {
00941                         preparerelid(attributes);
00942                         COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(fco)) );
00943                         assignrelid(fco);
00944 
00945                         // user info
00946                         CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
00947                         COMTHROW(msg.Append( " set derived from "));
00948                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
00949                         msgSC( msg, MSG_INFO);
00950                 }
00951                 else
00952                 {
00953                         // 'attributes' contains the id of the object (in the source project)
00954                         bool found = findObject( prev, attributes, fco, 'S');
00955 
00956                         // create only if not found 
00957                         if( !found)
00958                         {
00959                                 CComObjPtr<IMgaMetaFCO> meta;
00960                                 COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, _T("kind")), 
00961                                         OBJTYPE_SET, PutOut(meta)) );
00962                                 ASSERT( meta != NULL );
00963 
00964                                 preparerelid(attributes);
00965                                 COMTHROW( prev->CreateRootObject(meta, PutOut(fco)) );
00966                                 assignrelid(fco);
00967 
00968                                 // user info
00969                                 CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))));
00970                                 COMTHROW(msg.Append( " set created."));
00971                                 msgSC( msg, MSG_INFO);
00972                         }
00973                         else // will skip contained connpoints/elements/attribute values/regnode entries/constraints/name element
00974                         {    // will use the object found
00975                                 skip_inner_elements = true;
00976                                 //needs_members = isEmptySet( fco); //try to add to each set new members
00977 
00978                                 // user info
00979                                 CComBSTR msg = "Merging ";
00980                                 COMTHROW(msg.AppendBSTR(makeLink( fco)));
00981                                 //if( needs_members) msg.Append(" empty");
00982                                 COMTHROW(msg.Append( " set."));
00983                                 msgSC( msg, MSG_INFO);
00984                         }
00985                 }
00986         }
00987         else
00988         {
00989                 ASSERT( GetPrevName() == _T("model") );
00990 
00991                 CComObjPtr<IMgaModel> prev;
00992                 GetPrevObj(prev);
00993                 obj_prev = prev;
00994 
00995                 CComObjPtr<IMgaMetaRole> role;
00996                 COMTHROW( resolver->get_RoleByStr(prev, 
00997                         PutInBstrAttr(attributes, _T("kind")), OBJTYPE_SET,
00998                         PutInBstrAttr(attributes, _T("role")), NULL, PutOut(role)) );
00999                 ASSERT( role != NULL );
01000 
01001                 if( deriv.from != NULL )
01002                 {
01003                         CComObjPtr<IMgaSet> derivedfrom;
01004                         COMTHROW( deriv.from.QueryInterface(derivedfrom) );
01005 
01006                         if( deriv.isprimary )
01007                         {
01008                                 preparerelid(attributes);
01009                                 COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(fco)) );
01010                                 assignrelid(fco);
01011                         }
01012                         else
01013                         {
01014                                 preparerelid(attributes);
01015                                 COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(fco)) );
01016                                 assignrelid(fco);
01017                         }
01018 
01019                         // user info
01020                         CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
01021                         COMTHROW(msg.Append( " set derived from "));
01022                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
01023                         msgSC( msg, MSG_INFO);
01024                 }
01025                 else
01026                 {
01027                         // 'attributes' contains the id of the object (in the source project)
01028                         bool found = findObject( prev, attributes, fco, 'S');
01029 
01030                         // create only if not found 
01031                         if( !found)
01032                         {
01033                                 preparerelid(attributes);
01034                                 COMTHROW( prev->CreateChildObject(role, PutOut(fco)) );
01035                                 assignrelid(fco);
01036 
01037                                 // user info
01038                                 CComBSTR msg = makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))));
01039                                 COMTHROW(msg.Append( " set created."));
01040                                 msgSC( msg, MSG_INFO);
01041                         }
01042                         else // will skip contained connpoints/elements/attribute values/regnode entries/constraints/name element
01043                         {    // will use the object found
01044                                 skip_inner_elements = true;
01045                                 //needs_members = isEmptySet( fco); //try to add to each set new members
01046 
01047                                 // user info
01048                                 CComBSTR msg = "Merging ";
01049                                 COMTHROW(msg.AppendBSTR(makeLink( fco)));
01050                                 //if( needs_members) msg.Append(" empty");
01051                                 COMTHROW(msg.Append( " set."));
01052                                 msgSC( msg, MSG_INFO);
01053                         }
01054                 }
01055         }
01056         ASSERT( fco != NULL );
01057 
01058         bool bound = GetByName(attributes, _T("isbound")) == _T("yes"); // if bound it does NOT need members added by hand
01059         if( needs_members && !bound)
01060         {
01061                 std::list< CComObjPtr<IMgaFCO> > members;//slist
01062                 
01063                 // mixed form is used in smartMemberGUIDs
01064                 // i.e. {E200BEEB-34BC-4271-A134-AA5728C18124}\\/@../@module_ref1|kind=module_ref|relpos=0
01065                 std::tstring combineds = GetByName(attributes, _T("smartMemberGUIDs"));
01066                 std::list< std::tstring> combinedV = tokenizer( combineds, ' ', false);
01067 
01068                 // not needed currently, because the combined attr contains a series of <guid\\path>s
01069                 //std::tstring paths = GetByName(attributes, _T("closure2members"));
01070                 //std::list< std::tstring> nameV = tokenizer( paths, ' ', false);
01071 
01072                 std::list< std::tstring>::iterator li = combinedV.begin();
01073                 for( ; li != combinedV.end(); ++li)
01074                 {
01075                         CComObjPtr<IMgaFCO> mem;
01076                         
01077                         std::tstring guid_s, path_s;
01078                         if( (*li).size() >= GLOBAL_ID_LEN && (*li)[0] == '{' && (*li)[GLOBAL_ID_LEN-1] == '}' && (*li)[GLOBAL_ID_LEN] == '\\') // a guid form
01079                         {
01080                                 guid_s = (*li).substr( 0, GLOBAL_ID_LEN);
01081                                 path_s = (*li).substr( GLOBAL_ID_LEN + 1);
01082                         }
01083                         else
01084                         {
01085                                 guid_s = _T("");
01086                                 path_s = *li;
01087                         }
01088 
01089                         // search based on guid first, in the container only
01090                         if( !guid_s.empty()) // guid not empty
01091                         {
01092                                 findFCOWithGUID( obj_prev, guid_s, mem);
01093                         }
01094 
01095                         // either no guid, or not found with guid -> in each case we have to search with path
01096                         if( !mem)
01097                         {
01098                                 CComObjPtr<IMgaObject> obj;
01099                                 findObjOnRelPath( CComObjPtr<IMgaObject>(fco), path_s, obj, _T("set member"));
01100                                 CComObjPtr<IMgaFCO> mem;
01101                                 if( obj) obj.QueryInterface( mem);
01102                         }
01103 
01104                         // if element found, and is not found in the already found members container
01105                         if( mem)
01106                         {
01107                                 if( std::find( members.begin(), members.end(), mem) == members.end())
01108                                         members.push_back( mem);
01109                         }
01110                         else
01111                         {
01112                                 CComBSTR bstr( "Set ");
01113                                 COMTHROW(bstr.Append( makeLink( fco, makeNameViewable( GetByName(attributes, _T("closurename"))), true)));
01114                                 COMTHROW(bstr.Append( ": member not found. "));
01115                                 COMTHROW(bstr.Append( "Search path used: "));
01116                                 COMTHROW(bstr.Append( makeViewable( path_s).c_str()));
01117                                 msgSC(bstr, MSG_ERROR);
01118 
01119                                 // insert data to process in 2nd step
01120                                 m_notFoundSetMembers[ fco ].push_back( path_s);
01121                         }
01122                 }
01123 
01124                 CComObjPtr<IMgaSet> mgaset;
01125                 COMTHROW( fco.QueryInterface(mgaset) );
01126 
01127                 //WAS: if( !(GetByName(attributes, _T("isbound")) == _T("yes")) ) {
01128                 {
01129                         COMTHROW( mgaset->RemoveAll() ); //by ZolMol: if not bound then the members are different, remove the inherited members
01130                         std::list< CComObjPtr<IMgaFCO> >::iterator i = members.begin();//slist
01131                         while( i != members.end() )
01132                         {
01133                                 COMTHROW( mgaset->AddMember(*i) );
01134                                 ++i;
01135                         }
01136                 }
01137         }
01138         GetCurrent().object = fco;
01139         if( skip_inner_elements)
01140                 GetCurrent().exstrinfo = _T("skip");
01141 
01142         RegisterLookup(attributes, fco);
01143 }
01144 
01145 void CMgaParser::StartSCModel(const attributes_type &attributes)
01146 {
01147         bool skip_inner_elements = false;
01148         CComObjPtr<IMgaFCO> model;
01149 
01150         deriv_type deriv;
01151         //ResolveDerivation(attributes, deriv);
01152         (*this.*m_resolveDerFuncPtr)(attributes, deriv);
01153 
01154 
01155         if( GetPrevName() == _T("folder") )
01156         {
01157                 CComObjPtr<IMgaFolder> prev;
01158                 GetPrevObj(prev);
01159 
01160                 preparerelid(attributes);
01161                 if( deriv.from != NULL )
01162                 {
01163                         COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(model)) );
01164 
01165                         // user info
01166                         CComBSTR msg = makeLink( model, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
01167                         COMTHROW(msg.Append( " model derived from "));
01168                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
01169                         msgSC( msg, MSG_INFO);
01170                 }
01171                 else
01172                 {
01173                         // 'attributes' contains the id of the object (in the source project)
01174                         bool found = findObject( prev, attributes, model, 'M');
01175 
01176                         // create only if not found 
01177                         if( !found)
01178                         {
01179                                 CComObjPtr<IMgaMetaFCO> meta;
01180                                 COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, _T("kind")), 
01181                                         OBJTYPE_MODEL, PutOut(meta)) );
01182                                 ASSERT( meta != NULL );
01183 
01184                                 COMTHROW( prev->CreateRootObject(meta, PutOut(model)) );
01185 
01186                                 // user info
01187                                 CComBSTR msg = makeLink( model, makeNameViewable( GetByName(attributes, _T("closurename"))));
01188                                 COMTHROW(msg.Append( " model created."));
01189                                 msgSC( msg, MSG_INFO);
01190                         }
01191                         else // will use the object found
01192                         {    // will skip contained elements/attribute values/regnode entries/constraints/name element
01193                                 skip_inner_elements = true;
01194 
01195                                 // user info
01196                                 CComBSTR msg = "Merging ";
01197                                 COMTHROW(msg.AppendBSTR(makeLink( model)));
01198                                 COMTHROW(msg.Append( " model."));
01199                                 msgSC( msg, MSG_INFO);
01200                         }
01201                 }
01202                 assignrelid(model);
01203         }
01204         else
01205         {
01206                 ASSERT( GetPrevName() == _T("model") );
01207 
01208                 CComObjPtr<IMgaModel> prev;
01209                 GetPrevObj(prev);
01210 
01211                 CComObjPtr<IMgaMetaRole> role;
01212                 COMTHROW( resolver->get_RoleByStr(prev, 
01213                         PutInBstrAttr(attributes, _T("kind")), OBJTYPE_MODEL,
01214                         PutInBstrAttr(attributes, _T("role")), NULL, PutOut(role)) );
01215                 ASSERT( role != NULL );
01216 
01217                 if( deriv.from != NULL )
01218                 {
01219                         CComObjPtr<IMgaModel> derivedfrom;
01220                         COMTHROW( deriv.from.QueryInterface(derivedfrom) );
01221 
01222                         if( deriv.isprimary )
01223                         {
01224                                 preparerelid(attributes);
01225                                 COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(model)) );
01226                                 assignrelid(model);
01227                         }
01228                         else
01229                         {
01230                                 COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(model)) );
01231                         }
01232 
01233                         // user info
01234                         CComBSTR msg = makeLink( model, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
01235                         COMTHROW(msg.Append( " model derived from "));
01236                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
01237                         msgSC( msg, MSG_INFO);
01238                 }
01239                 else
01240                 {
01241                         // 'attributes' contains the id of the object (in the source project)
01242                         bool found = findObject( prev, attributes, model, 'M');
01243 
01244                         // create only if not found 
01245                         if( !found)
01246                         {
01247                                 preparerelid(attributes);
01248                                 COMTHROW( prev->CreateChildObject(role, PutOut(model)) );
01249                                 assignrelid(model);
01250 
01251                                 // user info
01252                                 CComBSTR msg = makeLink( model, makeNameViewable( GetByName(attributes, _T("closurename"))));
01253                                 COMTHROW(msg.Append( " model created."));
01254                                 msgSC( msg, MSG_INFO);
01255                         }
01256                         else // will use the object found
01257                         {
01258                                 skip_inner_elements = true;
01259 
01260                                 // user info
01261                                 CComBSTR msg = "Merging ";
01262                                 COMTHROW(msg.AppendBSTR(makeLink( model)));
01263                                 COMTHROW(msg.Append( " model."));
01264                                 msgSC( msg, MSG_INFO);
01265                         }
01266                 }
01267         }
01268         ASSERT( model != NULL );
01269 
01270         GetCurrent().object = model;
01271         long crid = toLong(GetByName(attributes,_T("childrelidcntr")));
01272         GetCurrent().exnuminfo = crid;
01273         // model may not be IMgaModel if "merging" (FIXME: likely a bug elsewhere) (crash e72e1106-8ab3-42af-b0e7-087fbef92b19)
01274         COMTHROW(CComQIPtr<IMgaModel>(model) ? CComQIPtr<IMgaModel>(model)->put_ChildRelIDCounter(crid) : S_OK);
01275 
01276         if( skip_inner_elements)
01277                 GetCurrent().exstrinfo = _T("skip");
01278 
01279         RegisterLookup(attributes, model);
01280 }
01281 
01282 void CMgaParser::StartSCAtom(const attributes_type &attributes)
01283 {
01284         bool skip_inner_elements = false;
01285         CComObjPtr<IMgaFCO> atom;
01286 
01287         deriv_type deriv;
01288         //ResolveDerivation(attributes, deriv);
01289         (*this.*m_resolveDerFuncPtr)(attributes, deriv);
01290 
01291         if( GetPrevName() == _T("folder") )
01292         {
01293                 CComObjPtr<IMgaFolder> prev;
01294                 GetPrevObj(prev);
01295 
01296                 if( deriv.from != NULL )
01297                 {
01298                         COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(atom)) );
01299 
01300                         // user info
01301                         CComBSTR msg = makeLink( atom, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
01302                         COMTHROW(msg.Append( " atom derived from "));
01303                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
01304                         msgSC( msg, MSG_INFO);
01305                 }
01306                 else
01307                 {
01308                         // 'attributes' contains the id of the object (in the source project)
01309                         bool found = findObject( prev, attributes, atom, 'A');
01310 
01311                         // create only if not found
01312                         if( !found)
01313                         {
01314                                 CComObjPtr<IMgaMetaFCO> meta;
01315                                 COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, _T("kind")),
01316                                         OBJTYPE_ATOM, PutOut(meta)) );
01317                                 ASSERT( meta != NULL );
01318 
01319                                 preparerelid(attributes);
01320                                 COMTHROW( prev->CreateRootObject(meta, PutOut(atom)) );
01321                                 assignrelid(atom);
01322 
01323                                 // user info
01324                                 CComBSTR msg = makeLink( atom, makeNameViewable( GetByName(attributes, _T("closurename"))));
01325                                 COMTHROW(msg.Append( L" atom created."));
01326                                 msgSC( msg, MSG_INFO);
01327                         }
01328                         else // will use the object found
01329                         {
01330                                 skip_inner_elements = true;
01331 
01332                                 // user info
01333                                 CComBSTR msg = L"Merging ";
01334                                 COMTHROW(msg.AppendBSTR(makeLink( atom)));
01335                                 COMTHROW(msg.Append( L" atom."));
01336                                 msgSC( msg, MSG_INFO);
01337                         }
01338                 }
01339         }
01340         else
01341         {
01342                 ASSERT( GetPrevName() == _T("model") );
01343 
01344                 CComObjPtr<IMgaModel> prev;
01345                 GetPrevObj(prev);
01346 
01347                 CComObjPtr<IMgaMetaRole> role;
01348                 COMTHROW( resolver->get_RoleByStr(prev, 
01349                         PutInBstrAttr(attributes, _T("kind")), OBJTYPE_ATOM,
01350                         PutInBstrAttr(attributes, _T("role")), NULL, PutOut(role)) );
01351                 ASSERT( role != NULL );
01352 
01353                 if( deriv.from != NULL )
01354                 {
01355                         CComObjPtr<IMgaAtom> derivedfrom;
01356                         COMTHROW( deriv.from.QueryInterface(derivedfrom) );
01357 
01358                         if( deriv.isprimary )
01359                         {
01360                                 preparerelid(attributes);
01361                                 COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(atom)) );
01362                                 assignrelid(atom);
01363                         }
01364                         else
01365                         {
01366                                 COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(atom)) );
01367                         }
01368 
01369                         // user info
01370                         CComBSTR msg = makeLink( atom, makeNameViewable( GetByName(attributes, _T("closurename"))), true);
01371                         COMTHROW(msg.Append( L" atom derived from "));
01372                         COMTHROW(msg.AppendBSTR( makeLink( deriv.from)));
01373                         msgSC( msg, MSG_INFO);
01374                 }
01375                 else
01376                 {
01377                         // 'attributes' contains the id of the object (in the source project)
01378                         bool found = findObject( prev, attributes, atom, 'A');
01379                         if( !found)
01380                         {
01381                                 // create only if not found 
01382                                 preparerelid(attributes);
01383                                 COMTHROW( prev->CreateChildObject(role, PutOut(atom)) );
01384                                 assignrelid(atom);
01385 
01386                                 // user info
01387                                 CComBSTR msg = makeLink( atom, makeNameViewable( GetByName(attributes, _T("closurename"))));
01388                                 COMTHROW(msg.Append( L" atom created."));
01389                                 msgSC( msg, MSG_INFO);
01390                         }
01391                         else // will skip contained elements
01392                         {
01393                                 skip_inner_elements = true;
01394 
01395                                 // user info
01396                                 CComBSTR msg = L"Merging ";
01397                                 COMTHROW(msg.AppendBSTR(makeLink( atom)));
01398                                 COMTHROW(msg.Append( L" atom."));
01399                                 msgSC( msg, MSG_INFO);
01400                         }
01401                 }
01402         }
01403 
01404         ASSERT( atom != NULL );
01405         GetCurrent().object = atom;
01406 
01407         if( skip_inner_elements)
01408                 GetCurrent().exstrinfo = _T("skip");
01409 
01410         RegisterLookup(attributes, atom);
01411 }
01412 
01413 void CMgaParser::StartSCFolder(const attributes_type &attributes)
01414 {
01415         bool skip_inner_elements = false;
01416         CComObjPtr<IMgaFolder> folder;
01417 
01418         //if( GetPrevName() == _T("project") )
01419         //{
01420         //      COMTHROW( project->get_RootFolder(PutOut(folder)) );
01421         //}
01422         //else
01423         {
01424                 CComObjPtr<IMgaFolder> prev;
01425                 GetPrevObj(prev);
01426 
01427                 CComObjPtr<IMgaMetaFolder> meta;
01428                 _bstr_t fname(PutInBstrAttr(attributes, _T("kind")));
01429 
01430                 VARIANT_BOOL previactmode;
01431                 COMTHROW(resolver->get_IsInteractive(&previactmode));
01432                 COMTHROW(resolver->put_IsInteractive(VARIANT_FALSE));
01433                 HRESULT hr = resolver->get_FolderByStr(prev, fname, PutOut(meta));
01434                 COMTHROW(resolver->put_IsInteractive(previactmode));
01435 
01436                 ASSERT(meta);
01437         
01438 //
01439                 bool found = findFolderIn( prev, attributes, folder);
01440 
01441                 // create only if not found
01442                 if( !found)
01443                 {
01444                         preparerelid(attributes);
01445                         COMTHROW( prev->CreateFolder(meta, PutOut(folder)));
01446                         assignrelid(folder);
01447 
01448                         // user info
01449                         CComBSTR msg = makeLink(CComObjPtr<IMgaObject>(folder), makeNameViewable( GetByName(attributes, _T("closurename"))));
01450                         COMTHROW(msg.Append(L" folder created."));
01451                         msgSC( msg, MSG_INFO);
01452                 }
01453                 else // will use the object found
01454                 {
01455                         skip_inner_elements = true;
01456 
01457                         // user info
01458                         CComBSTR msg = L"Merging ";
01459                         COMTHROW(msg.AppendBSTR(makeLink( CComObjPtr<IMgaObject>(folder))));
01460                         COMTHROW(msg.Append( L" folder."));
01461                         msgSC( msg, MSG_INFO);
01462                 }
01463         }
01464         ASSERT( folder != NULL );
01465         GetCurrent().object = folder;
01466         if( skip_inner_elements)
01467                 GetCurrent().exstrinfo = _T("skip");
01468 
01469         long crid = toLong(GetByName(attributes,_T("childrelidcntr")));
01470         GetCurrent().exnuminfo = crid;
01471         COMTHROW(folder->put_ChildRelIDCounter(crid));
01472 
01473         RegisterLookup(attributes, folder);
01474 }
01475 
01476 void CMgaParser::StartSCRegNode(const attributes_type &attributes)
01477 {
01478         CComObjPtr<IMgaRegNode> regnode;
01479 
01480         _bstr_t name = GetByName(attributes, _T("name")).c_str();
01481 
01482         if( GetPrevName() == _T("regnode") )
01483         {
01484                 CComObjPtr<IMgaRegNode> prev;
01485                 GetPrevObj(prev);
01486 
01487                 COMTHROW( prev->get_SubNodeByName(name, PutOut(regnode)) );
01488         }
01489         else if( GetPrevName() == _T("folder") )
01490         {
01491                 CComObjPtr<IMgaFolder> prev;
01492                 GetPrevObj(prev);
01493 
01494                 COMTHROW( prev->get_RegistryNode(name, PutOut(regnode)) );
01495         }
01496         else if( GetPrevName() == _T("attribute") )
01497         {
01498                 CComObjPtr<IMgaAttribute> prev;
01499                 GetPrevObj(prev);
01500 
01501                 COMTHROW( prev->get_RegistryNode(name, PutOut(regnode)) );
01502         }
01503         else
01504         {
01505                 CComObjPtr<IMgaFCO> prev;
01506                 GetPrevObj(prev);
01507 
01508                 COMTHROW( prev->get_RegistryNode(name, PutOut(regnode)) );
01509         }
01510         ASSERT( regnode != NULL );
01511 
01512         // check its status
01513         long st;
01514         COMTHROW( regnode->get_Status( &st));
01515         
01516         // if MERGE case (skip) and if value is defined HERE, then skip it (don't touch) its value
01517         // but the subnodes may change! even in this case if UNDEF, or they may be created if they not exist
01518         if( GetPrevious().exstrinfo == _T("skip") && st == ATTSTATUS_HERE)
01519         {
01520                 GetCurrent().exstrinfo = _T("skip"); // might have subelements so skip those as well
01521                 GetCurrent().object = regnode;
01522                 return;
01523         }
01524 
01525         if( GetByNameX(attributes, _T("status")) == NULL )
01526                 COMTHROW( regnode->put_Value(NULL) );
01527 
01528         if( GetByName(attributes, _T("isopaque")) == _T("yes") )
01529                 COMTHROW( regnode->put_Opacity(VARIANT_TRUE) );
01530 
01531         GetCurrent().object = regnode;
01532 }
01533 
01534 void CMgaParser::EndSCRegNode()
01535 {
01536         if( GetPrevious().exstrinfo == _T("skip")) // if merge return, deal only with new regnodes
01537                 return;
01538 
01539         CComObjPtr<IMgaRegNode> fresh_regnode;
01540 
01541         ASSERT( GetCurrent().object);
01542         COMTHROW( GetCurrent().object.QueryInterface( fresh_regnode));
01543         if( !fresh_regnode) return;
01544 
01545 
01546         // responsible for shifting the guid related regnodes:
01547         // guid goes to guid/prev node
01548         // new guid to be created int guid node
01549 
01550         CComBSTR nm;
01551         COMTHROW( fresh_regnode->get_Name( &nm));
01552 
01553         if( nm != GLOBAL_ID_STR)
01554                 return;
01555                 
01556         long status;
01557         COMTHROW( fresh_regnode->get_Status( &status));
01558 
01559         if( status != 0) // guid NOT defined here
01560                 return;
01561 
01562         CComBSTR guid;
01563         // guid in the old project
01564         COMTHROW( fresh_regnode->get_Value( &guid));
01565 
01566         // replace the old GUID with a new one
01567         COMTHROW( fresh_regnode->put_Value( GuidCreate::newGuid()));
01568                         
01569         if( guid.Length() != GLOBAL_ID_LEN) // guid invalid, do not store it in prev subnode
01570                 return;
01571 
01572         // store the old GUID in 'prev' subnode
01573         CComPtr<IMgaRegNode> subnd;
01574         COMTHROW( fresh_regnode->get_SubNodeByName( CComBSTR(PREV_ID_STR), &subnd));
01575 
01576         if( subnd) COMTHROW( subnd->put_Value(guid) );
01577 
01578 }
01579 
01580 void CMgaParser::StartSCAttribute(const attributes_type &attributes)
01581 {
01582         CComObjPtr<IMgaAttribute> attr;
01583 
01584         CComObjPtr<IMgaFCO> fco;
01585         GetPrevObj(fco);
01586 
01587         CComObjPtr<IMgaMetaAttribute> metaattr;
01588         HRESULT hr = resolver->get_AttrByStr(fco, PutInBstrAttr(attributes, _T("kind")), PutOut(metaattr));
01589 
01590     if( FAILED(hr) || metaattr == NULL )
01591     {
01592         GetCurrent().object = NULL;
01593         return;
01594     }
01595 
01596         COMTHROW( fco->get_Attribute(metaattr, PutOut(attr)) );
01597 
01598         ASSERT( attr != NULL );
01599         GetCurrent().object = attr;
01600 
01601         long st; // check its status: if value is defined HERE, then skip it (don't touch)
01602         COMTHROW( attr->get_Status( &st));
01603 
01604         // in case parent is merged (skipped) and attr is defined HERE, skip inner contents:
01605         if( GetPrevious().exstrinfo == _T("skip") && st == ATTSTATUS_HERE)
01606         {
01607                 GetCurrent().exstrinfo = _T("skip"); // might have subelements so skip those as well
01608                 return;
01609         }
01610 
01611         if( GetByNameX(attributes, _T("status")) == NULL )
01612         {
01613                 // we set some value, and from the "value" element we set the actual value
01614 
01615                 CComVariant v;
01616                 COMTHROW( attr->get_Value(PutOut(v)) );
01617                 COMTHROW( attr->put_Value(v) );
01618         }
01619 }
01620 
01621 void CMgaParser::EndSCName()
01622 {
01623         if( GetPrevious().exstrinfo == _T("skip")) // has no sub elements
01624                 return;
01625 
01626         //if( GetPrevName() == _T("project") )
01627         //{
01628         //      COMTHROW( project->put_Name(PutInBstr(GetCurrData())) );
01629         //}
01630         //else
01631         if( GetPrevName() == _T("constraint") )
01632         {
01633                 constraint_name = GetCurrData();
01634         }
01635         else if( GetPrevious().object != NULL ) 
01636         {
01637                 CComObjPtr<IMgaObject> prev;
01638                 GetPrevObj(prev);
01639                 COMTHROW( prev->put_Name(PutInBstr(GetCurrData())) );
01640         }
01641 }
01642 
01643 void CMgaParser::EndSCValue()
01644 {
01645         if( GetPrevious().exstrinfo == _T("skip")) // has no sub elements
01646                 return;
01647 
01648         // skip if the object is ignored
01649     if( GetPrevious().object == NULL )
01650         return;
01651 
01652         if( GetPrevName() == _T("constraint") )
01653         {
01654                 constraint_value = GetCurrData();
01655         }
01656         else 
01657                 if( GetPrevName() == _T("regnode") )
01658         {
01659                 CComObjPtr<IMgaRegNode> regnode;
01660                 GetPrevObj(regnode);
01661 
01662                 long status;
01663                 COMTHROW( regnode->get_Status(&status) );
01664 
01665                 // when we create the registry node, 
01666                 // we fill it by an empty string if not inherited or not undefined
01667                 if( status == 0)
01668                         COMTHROW( regnode->put_Value(PutInBstr(GetCurrData())) );
01669         }
01670         else if( GetPrevName() == _T("attribute") ) 
01671         {
01672                 CComObjPtr<IMgaAttribute> attr;
01673                 GetPrevObj(attr);
01674 
01675                 long status;
01676                 COMTHROW( attr->get_Status(&status) );
01677 
01678                 // if inherited, then do not modify the value
01679                 if( status != 0 )
01680                         return;
01681 
01682                 CComObjPtr<IMgaMetaAttribute> metaattr;
01683                 COMTHROW( attr->get_Meta(PutOut(metaattr)) );
01684                 ASSERT( metaattr != NULL );
01685 
01686                 attval_enum attval;
01687                 COMTHROW( metaattr->get_ValueType(&attval) );
01688 
01689                 CComVariant v;
01690 
01691                 switch( attval )
01692                 {
01693                 case ATTVAL_STRING:
01694                 case ATTVAL_ENUM:
01695                 case ATTVAL_DYNAMIC:
01696                         v = GetCurrData().c_str();
01697                         break;
01698 
01699                 case ATTVAL_INTEGER:
01700                         v = GetCurrData().c_str();
01701                         COMTHROW( v.ChangeType(VT_I4) );
01702                         break;
01703 
01704                 case ATTVAL_DOUBLE:
01705                         v = GetCurrData().c_str();
01706                         COMTHROW( v.ChangeType(VT_R8) );
01707                         break;
01708 
01709                 case ATTVAL_BOOLEAN:
01710                         {
01711                                 char c = tolower(*GetCurrData().c_str());
01712                                 CopyTo( (c == 't' || c == '1' || c == 'y') ? VARIANT_TRUE : VARIANT_FALSE, v);
01713                                 break;
01714                         }
01715 
01716                 case ATTVAL_REFERENCE:
01717                         {
01718                                 CComObjPtr<IMgaFCO> object;
01719                                 LookupByID(GetCurrData(), object);
01720 
01721                                 if( object == NULL )
01722                                         throw pass_exception();
01723 
01724                                 CopyTo(object, v);
01725                         }
01726 
01727                 default:
01728                         HR_THROW(E_INVALID_META);
01729 
01730                 };
01731 
01732                 COMTHROW( attr->put_Value(v) );
01733         }
01734 }
01735 
01736 void CMgaParser::EndSCConstraint()
01737 {
01738         if( GetPrevious().exstrinfo == _T("skip"))
01739         {
01740                 GetCurrent().exstrinfo = _T("skip"); // might have subelements, so skip those as well
01741                 return;
01742         }
01743 
01744         CComObjPtr<IMgaConstraint> constraint;
01745 
01746         if( GetPrevName() == _T("folder") )
01747         {
01748                 CComObjPtr<IMgaFolder> folder;
01749                 GetPrevObj(folder);
01750 
01751                 COMTHROW( folder->DefineConstraint(PutInBstr(constraint_name), 0, // FIXME: the mask
01752                         PutInBstr(constraint_value), PutOut(constraint)) );
01753         }
01754         else
01755         {
01756                 CComObjPtr<IMgaFCO> fco;
01757                 GetPrevObj(fco);
01758 
01759                 COMTHROW( fco->DefineConstraint(PutInBstr(constraint_name), 0, // FIXME: the mask
01760                         PutInBstr(constraint_value), PutOut(constraint)) );
01761         }
01762 }
01763 
01764