[GME-commit] GMESRC/GME/Parser Helper.cpp,NONE,1.1 Helper.h,NONE,1.1 MgaParserBC.cpp,NONE,1.1 MgaParserClosureHelper.cpp,NONE,1.1 MgaParserSC.cpp,NONE,1.1 mgaclosure.dtd,NONE,1.1 MgaDumper.cpp,1.18,1.19 MgaDumper.h,1.11,1.12 MgaParser.cpp,1.24,1.25 MgaParser.h,1.9,1.10 Parser.dsp,1.13,1.14 mga.dtd,1.9,1.10

gme-commit at list.isis.vanderbilt.edu gme-commit at list.isis.vanderbilt.edu
Mon Sep 27 17:33:04 CDT 2004


Update of /var/lib/gme/GMESRC/GME/Parser
In directory braindrain:/tmp/cvs-serv13825

Modified Files:
	MgaDumper.cpp MgaDumper.h MgaParser.cpp MgaParser.h Parser.dsp 
	mga.dtd 
Added Files:
	Helper.cpp Helper.h MgaParserBC.cpp MgaParserClosureHelper.cpp 
	MgaParserSC.cpp mgaclosure.dtd 
Log Message:
Parser rolled back as it was before copyclosure had been introduced.
ParserSC methods introduced to parse smartcopied data.
ParserBC methods introduced to parse (basic) copyclosured data.
Dumper is still combined (closure, smart and regular).

Clipboard data preanalyzed and parser invoked based on attributes of the "clipboard".


CVS User: zolmol

--- NEW FILE: Helper.cpp ---
#include "stdafx.h"
#include "helper.h"

//
// bool include_separator:
//	true : includes the separator in the token
//	false: does not include the separator character in the token
list<string> tokenizer( string m, char separator /*= '/' */, bool include_separator /* = true */)
{
	int offs = include_separator?0:1;
	list<string> r;
	string last;
	while( !m.empty())
	{
		int i = m.find(separator, 1);
		if( i == -1)
		{
			r.push_back( m);
			m = "";
		}
		else if( i != 0)
		{
			r.push_back( m.substr( 0, i));
			m = m.substr( i + offs);
		}
	}

	return r;
}

//
// does not include the separator character in the token
bool findExact( const string& m, const string& to_find)
{
	list< string> tokens = tokenizer( m, ' ', false);
	list< string>::iterator i = tokens.begin();
	list< string>::iterator e = tokens.end();
	while( i != e && (*i).compare( to_find) != 0)
		++i;

	return ( i != e); // false if not found
}

// it calculates nm1's name relatively to nm2
string makeRel( string& nm1, string& nm2)
{
	list<string> r1 = tokenizer( nm1);
	list<string> r2 = tokenizer( nm2);

	list<string>::iterator i1 = r1.begin();
	list<string>::iterator i2 = r2.begin();
	while( i1 != r1.end() && i2 != r2.end() && *i1 == *i2)
	{
		++i1;
		++i2;
	}

	string relpath;
	int count = 0; // how many levels in nm2
	while( i2 != r2.end()) ++i2, ++count, relpath +="/@..";
	while( i1 != r1.end()) relpath +=*i1, ++i1;

	if( relpath == "") // same name nm1 and nm2
	{
		ASSERT( nm1 == nm2);
		//#1 solution: to give back the path as it goes back to the topmost level
		// and then goes down again
		/*for( i2 = r2.begin(); i2 != r2.end(); ++i2) 
			relpath +="/@..";
		relpath += nm1;*/

		//#2 solution: to use a shorter form (only one step up): /@../name
		relpath = "/@.." + *r2.rbegin();
	}
	return relpath;
}

string makeViewable( const string& m)
{
	string res;
	list<string> r1 = tokenizer( m);
	list<string>::iterator i1 = r1.begin();
	while( i1 != r1.end())
	{
		string p = *i1;
		if( p.substr(0, 2) == "/@")
			p = p.substr(2); // "/@"
		int pos = p.find("|kind=");
		if( pos != -1) p = p.substr( 0, pos);

		res += '/' + p;
		++i1;
	}
	
	return res;
}


string makeNameViewable( const string& m)
{
	string res = m;
	if( res.substr(0, 2) == "/@")
		res = res.substr(2);

	ASSERT( res.find( "/@") == -1); //no more than one token

	int pos = res.find("|kind=");
	if( pos != -1)
		res = res.substr( 0, pos);

	return res;
}
--- NEW FILE: Helper.h ---
#ifndef HELPER_H_259823495872394857
#define HELPER_H_259823495872394857

#include <list>
#include <string>

list<string> tokenizer( string m, char separator = '/', bool include_separator = true);

bool findExact( const string& m, const string& to_find);

string makeRel( string& nm, string& nm2);

string makeViewable( const string& m);

string makeNameViewable( const string& m);

#endif // HELPER_H_259823495872394857


--- NEW FILE: MgaParserBC.cpp ---
#include "stdafx.h"
#include "Parser.h"
#include "MgaParser.h"
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <stdio.h>

#include "../Common/CommonCollection.h"
#include "../Common/CommonMgaTrukk.h"
#include <slist>
#include "helper.h"

// --------------------------- CMgaParser - basic copy closure dumped data parsing

STDMETHODIMP CMgaParser::ParseClos1(IMgaObject *here, BSTR filename)
{
	CHECK_IN(here);

	try
	{
		CloseAll();

		COMTHROW( progress.CoCreateInstance(L"Mga.MgaProgressDlg") );
		COMTHROW( progress->SetTitle(PutInBstr("Importing CopyClosured XML data...")) );
		COMTHROW( progress->StartProgressDialog(NULL) );

		CComObjPtr<IMgaProject> p;
		COMTHROW( here->get_Project(PutOut(p)) );
		ASSERT( p != NULL );
		COMTHROW( p->get_Preferences(&project_prefs_orig) );
		manual_relid_mode = project_prefs_orig & MGAPREF_MANUAL_RELIDS ? true : false;

		m_GME = get_GME( p); // by zolmol

		COMTHROW( p->CreateTerritory(NULL, PutOut(territory), NULL) );
		COMTHROW( p->BeginTransaction(territory, TRANSACTION_NON_NESTED) );

		CComObjPtr<IMgaObject> target;
		COMTHROW(territory->OpenObj(here, PutOut(target)));

		//by zolmol
		m_target = target;
		m_resolveDerFuncPtr = CMgaParser::ResolveClosure1Derivation;
		m_clVer = 1;
		m_clVerStr = "1";//end

		project_prefs = project_prefs_orig | MGAPREF_IGNORECONNCHECKS;
		COMTHROW( p->put_Preferences(project_prefs) );

		COMTHROW( resolver.CoCreateInstance(L"Mga.MgaResolver") );
		ASSERT( resolver != NULL );

		project = p;

		CopyTo(filename, xmlfile);

		try
		{
			XMLPlatformUtils::Initialize();

			SAXParser parser;
			parser.setDoValidation(true);
			parser.setDocumentHandler(this);
			parser.setErrorHandler(this);
			parser.setEntityResolver(this);

			elementfuncs = elementfuncs_bcmga;

			// manual first pass

			pass_count = 1;

			ranges.clear();
			ranges.push_front();
			ranges.front().begin = 1;
			ranges.front().end = (counter_type)-1;
			ranges.front().previous.name = "start";
			ranges.front().previous.object = target;
			skip_element_level = 0;
			
			parser.parse(xmlfile.c_str());

			ASSERT( ranges.front().begin == 1 );
			ranges.pop_front();
			elements.clear();

			max_counter = counter;

			// the other passes

			parser.setDoValidation(false);

			while( !ranges.empty() && ranges.front().begin != (counter_type)-1 )
			{
				// FIXME: better algorithm for infinite loop
				if( ++pass_count >= 100 )
					HR_THROW(E_TOOMANYPASSES);

				parser.parse(xmlfile.c_str());
			}

			ASSERT( elements.empty() );
			ranges.clear();
		}
	    catch(const XMLException &e)
		{
			XmlStr desc(e.getMessage());

			ThrowXmlError(desc.c_str());
		}
		COMTHROW( project->put_Preferences(project_prefs_orig) );

		for(librecords::iterator i = libstodo.begin(); i != libstodo.end(); i++) { // copied from ParseProject in order to recognize libraries (zolmol)
			COMTHROW(i->f->put_LibraryName(CComBSTR(i->libname.c_str())));
			COMTHROW(i->f->put_Exempt(VARIANT_FALSE));
		}
		libstodo.clear();

		COMTHROW( project->CommitTransaction() );
		project = NULL;
		clear_GME( m_GME);

		CloseAll();
	}
	catch(hresult_exception &e)
	{
		CloseAll();

		ASSERT( FAILED(e.hr) );
		if( e.hr == E_XMLPARSER )
			SetErrorInfo(errorinfo);
		else
			SetErrorInfo2(e.hr);

		return e.hr;
	}
	return S_OK;
}

CMgaParser::elementfunc CMgaParser::elementfuncs_bcmga[] = 
{
	//elementfunc("project", StartProject, EndNone),
	elementfunc("name", StartNone, EndName),
	elementfunc("comment", StartNone, EndComment),
	elementfunc("author", StartNone, EndAuthor),
	elementfunc("value", StartNone, EndValue),
	elementfunc("regnode", StartRegNode, EndNone),
	elementfunc("attribute", StartAttribute, EndNone),
	elementfunc("constraint", StartNone, EndConstraint),
	elementfunc("folder", StartFolder, EndNone),
	elementfunc("model", StartModel, EndNone),
	elementfunc("atom", StartAtom, EndNone),
	elementfunc("connection", StartConnection, EndNone),
	elementfunc("connpoint", StartBCConnPoint, EndNone),	// diff
	elementfunc("reference", StartBCReference, EndNone),	// diff
	elementfunc("set", StartBCSet, EndNone),				// diff
	elementfunc("clipboard", StartBCClipboard, EndNone),	// diff, common for closure clipboards
	elementfunc("", NULL, NULL)
};

// ------- Element Handlers
void CMgaParser::StartBCClipboard(const attributes_type &attributes)
{
	ASSERT( project != NULL );
	ASSERT( GetPrevName() == "start" );
	ASSERT( GetPrevious().object != NULL );

	const CComObjPtr<IUnknown> &obj = GetPrevious().object;
	GetCurrent().object = obj;

	CComObjPtr<IMgaModel> model;
	CComObjPtr<IMgaFolder> folder;

	if( SUCCEEDED(obj.QueryInterface(model)) )
		GetCurrent().name = "model";
	else if( SUCCEEDED(obj.QueryInterface(folder)) )
		GetCurrent().name = "folder";
	else
		HR_THROW(E_INVALID_FILENAME);

	const string *ver = GetByNameX(attributes, "closureversion");

	ASSERT( ver);
	ASSERT( ver->compare(m_clVerStr) == 0);

	const string *acceptingkinds = GetByNameX(attributes, "acceptingkind");
	if( acceptingkinds != NULL)
	{
		CComBstrObj kind_name;
		if( model)
		{
			CComObjPtr<IMgaMetaFCO> k_meta;
			COMTHROW( model->get_Meta( PutOut( k_meta)));
			COMTHROW( k_meta->get_Name( PutOut(kind_name)) );
		}
		else if( folder)
		{
			CComObjPtr<IMgaMetaFolder> f_meta;
			COMTHROW( folder->get_MetaFolder( PutOut( f_meta)));
			COMTHROW( f_meta->get_Name( PutOut(kind_name)) );
		}
			
		// check if the accepting kind exists among the accepting kinds
		string kind_nm;
		CopyTo( kind_name, kind_nm);

		if( !findExact( *acceptingkinds, kind_nm))
			HR_THROW(E_INVALID_MGA);

	}

}

void CMgaParser::ResolveClosure1Derivation(const attributes_type &attributes, deriv_type &deriv)
{
	const string *s = GetByNameX(attributes, "derivedfrom");
	if( s == NULL )
	{
		s = GetByNameX(attributes, "closurelibderivedfrom");
		if( s == NULL)
		{
			deriv.from.Release();
			return;
		}

		CComObjPtr<IMgaObject> obj;
		COMTHROW( project->get_ObjectByPath( PutInBstr( *s), PutOut( obj)) );
		if ( obj)
			COMTHROW( obj.QueryInterface( deriv.from));
		else // if nonunique is allowed
		{
			COMTHROW( project->get_NthObjectByPath( 0, PutInBstr( *s), PutOut( obj)) );
			if( obj)
				COMTHROW( obj.QueryInterface( deriv.from));

			//<!> warning about non uniqueness
			if( obj && m_GME) 
			{
				CComBSTR bstr, id, nm;
				COMTHROW( obj->get_ID( &id));
				COMTHROW( obj->get_Name( &nm));
				bstr.Append("[Closure Parser] Name ambiguity found. Selected: <A HREF=\"mga:");
				bstr.AppendBSTR( id);
				bstr.Append("\">");
				bstr.AppendBSTR( nm);
				bstr.Append("</A> as basetype. Search path used: ");
				bstr.Append( makeViewable(*s).c_str());

				COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}
		}

		if ( deriv.from == NULL) // do not throw exception in case of closurelibderivedfrom
		{
			deriv.from.Release();
			return;
		}
	}
	else
	{
		LookupByID(*s, deriv.from);

		if( deriv.from == NULL )
			throw pass_exception();
	}

	s = GetByNameX(attributes, "isinstance");
	deriv.isinstance = ( s != NULL && *s == "yes" ) ? VARIANT_TRUE : VARIANT_FALSE;

	s = GetByNameX(attributes, "isprimary");
	deriv.isprimary = ( s != NULL && *s == "no" ) ? false : true;
}


void CMgaParser::StartBCConnPoint(const attributes_type &attributes)
{
	ASSERT( GetPrevName() == "connection" );
	CComObjPtr<IMgaConnection> conn;
	GetPrevObj(conn);

	if( GetPrevious().exstrinfo == "skip" || GetByName(attributes, "isbound") == "yes" ) return;

	CComObjPtr<IMgaFCO> target;

	// prefer the closurelibtarget over the target:
	const string *libtg = GetByNameX(attributes, "closurelibtarget");
	if ( libtg != NULL)
	{
		CComObjPtr<IMgaObject> obj;
		COMTHROW( project->get_ObjectByPath( PutInBstr( *libtg), PutOut( obj)) );
		if ( obj)
			COMTHROW( obj.QueryInterface( target));
		else // if nonunique is allowed
		{
			COMTHROW( project->get_NthObjectByPath( 0, PutInBstr( *libtg), PutOut( obj)) );
			if( obj)
				COMTHROW( obj.QueryInterface( target));

			//<!> warning about non uniqueness
			if( obj && m_GME) 
			{
				CComBSTR bstr, id, nm;
				COMTHROW( obj->get_ID( &id));
				COMTHROW( obj->get_Name( &nm));
				bstr.Append("[Closure Parser] Name ambiguity found. Selected: <A HREF=\"mga:");
				bstr.AppendBSTR( id);
				bstr.Append("\">");
				bstr.AppendBSTR( nm);
				bstr.Append("</A> as connection target. Search path used: ");
				bstr.Append( makeViewable(*libtg).c_str());

				COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}
		}
	}

	const string *tg = GetByNameX(attributes, "target");
	if( tg != NULL && libtg == NULL) // valid info in target iff no closurelibtarget token
	{
		LookupByID( *tg, target);
	}

	// throw even if closurelibtarget present but not found the needed object
	if ( target == NULL)
		throw pass_exception();

	CComObjPtr<IMgaFCOs> coll;
	COMTHROW(coll.CoCreateInstance(L"Mga.MgaFCOs"));

	const string *s = GetByNameX(attributes, "refs");
	if( s != NULL )
	{
		int pos = s->find_first_not_of(' ', 0);
		ASSERT( pos >= 0 );
		while( pos < s->length() )
		{
			int pos2 = s->find_first_of(' ', pos);
			if( pos2 < 0 )
				pos2 = s->length();
			ASSERT( pos2 > pos );

			CComObjPtr<IMgaFCO> ref;
			LookupByID(string(*s, pos, pos2-pos), ref);

			if( ref == NULL )
				throw pass_exception();

			COMTHROW(coll->Append(ref));

			pos = pos2+1;
		}
	}

	CComObjPtr<IMgaConnPoint> connpoint;

	COMTHROW( conn->AddConnPoint(PutInBstr(GetByName(attributes, "role")), 0,	// FIXME: multiplicity
		target, coll, PutOut(connpoint)) );
}

void CMgaParser::StartBCReference(const attributes_type &attributes)
{
	CComObjPtr<IMgaFCO> fco;

	deriv_type deriv;
	(*this.*m_resolveDerFuncPtr)(attributes, deriv);

	CComObjPtr<IMgaFCO> referred;

	const string *s = GetByNameX(attributes, "referred");
	if( s != NULL )
	{
		LookupByID(*s, referred);

		if( referred == NULL )
			throw pass_exception();
	}
	else // by ZolMol
	{
		s = GetByNameX(attributes, "closurelibreferred");
		if( s != NULL)
		{
			CComObjPtr<IMgaObject> obj;
			COMTHROW( project->get_ObjectByPath( PutInBstr( *s), PutOut( obj)) );
			if ( obj)
				COMTHROW( obj.QueryInterface( referred));
			else // if nonunique is allowed
			{
				COMTHROW( project->get_NthObjectByPath( 0, PutInBstr( *s), PutOut( obj)) );
				if( obj)
					COMTHROW( obj.QueryInterface( referred));

				//<!> warning about non uniqueness
				if( obj && m_GME) 
				{
					CComBSTR bstr, id, nm;
					COMTHROW( obj->get_ID( &id));
					COMTHROW( obj->get_Name( &nm));
					bstr.Append("[Closure Parser] Name ambiguity found. Selected: <A HREF=\"mga:");
					bstr.AppendBSTR( id);
					bstr.Append("\">");
					bstr.AppendBSTR( nm);
					bstr.Append("</A> as library reference. Search path used: ");
					bstr.Append( makeViewable(*s).c_str());

					COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
				}
			}
		}
	}

	if( GetPrevName() == "folder" )
	{
		CComObjPtr<IMgaFolder> prev;
		GetPrevObj(prev);

		preparerelid(attributes);
		if( deriv.from != NULL )
		{
			COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(fco)) );
		}
		else
		{
			CComObjPtr<IMgaMetaFCO> meta;
			COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, "kind"), 
				OBJTYPE_REFERENCE, PutOut(meta)) );
			ASSERT( meta != NULL );

			COMTHROW( prev->CreateRootObject(meta, PutOut(fco)) );
		}
		assignrelid(fco);
	}
	else
	{
		ASSERT( GetPrevName() == "model" );
		CComObjPtr<IMgaModel> prev;
		GetPrevObj(prev);

		CComObjPtr<IMgaMetaRole> role;
		COMTHROW( resolver->get_RoleByStr(prev, 
			PutInBstrAttr(attributes, "kind"), OBJTYPE_REFERENCE,
			PutInBstrAttr(attributes, "role"), NULL, PutOut(role)) );
		ASSERT( role != NULL );

		if( deriv.from != NULL )
		{
			CComObjPtr<IMgaReference> derivedfrom;
			COMTHROW( deriv.from.QueryInterface(derivedfrom) );

			if( deriv.isprimary )
			{
				preparerelid(attributes);
				COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(fco)) );
				assignrelid(fco);
			}
			else
			{
				COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(fco)) );
			}
		}
		else
		{
			preparerelid(attributes);
			COMTHROW( prev->CreateChildObject(role, PutOut(fco)) );
			assignrelid(fco);
		}
	}
	ASSERT( fco != NULL );

	if( !(GetByName(attributes, "isbound") == "yes") && referred != NULL )
	{
		CComObjPtr<IMgaReference> ref;
		COMTHROW( fco.QueryInterface(ref) );

		COMTHROW( ref->put_Referred(referred) );
	}

	GetCurrent().object = fco;

	RegisterLookup(attributes, fco);
}

void CMgaParser::StartBCSet(const attributes_type &attributes)
{
	CComObjPtr<IMgaFCO> fco;

	deriv_type deriv;
	(*this.*m_resolveDerFuncPtr)(attributes, deriv);

	slist< CComObjPtr<IMgaFCO> > members;

	const string *s = GetByNameX(attributes, "members");
	if( s != NULL )
	{
		int pos = s->find_first_not_of(' ', 0);
		ASSERT( pos >= 0 );
		while( pos < s->length() )
		{
			int pos2 = s->find_first_of(' ', pos);
			if( pos2 < 0 )
				pos2 = s->length();
			ASSERT( pos2 > pos );

			CComObjPtr<IMgaFCO> member;
			LookupByID(string(*s, pos, pos2-pos), member);

			if( member == NULL )
				throw pass_exception();

			members.push_front(member);

			pos = pos2+1;
		}
	}

	if( GetPrevName() == "folder" )
	{
		CComObjPtr<IMgaFolder> prev;
		GetPrevObj(prev);

		preparerelid(attributes);
		if( deriv.from != NULL )
		{
			COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(fco)) );
		}
		else
		{
			CComObjPtr<IMgaMetaFCO> meta;
			COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, "kind"), 
				OBJTYPE_SET, PutOut(meta)) );
			ASSERT( meta != NULL );

			COMTHROW( prev->CreateRootObject(meta, PutOut(fco)) );
		}
		assignrelid(fco);
	}
	else
	{
		ASSERT( GetPrevName() == "model" );
		CComObjPtr<IMgaModel> prev;
		GetPrevObj(prev);

		CComObjPtr<IMgaMetaRole> role;
		COMTHROW( resolver->get_RoleByStr(prev, 
			PutInBstrAttr(attributes, "kind"), OBJTYPE_SET,
			PutInBstrAttr(attributes, "role"), NULL, PutOut(role)) );
		ASSERT( role != NULL );

		if( deriv.from != NULL )
		{
			CComObjPtr<IMgaSet> derivedfrom;
			COMTHROW( deriv.from.QueryInterface(derivedfrom) );

			if( deriv.isprimary )
			{
				preparerelid(attributes);
				COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(fco)) );
				assignrelid(fco);
			}
			else
			{
				preparerelid(attributes);
				COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(fco)) );
				assignrelid(fco);
			}
		}
		else
		{
			preparerelid(attributes);
			COMTHROW( prev->CreateChildObject(role, PutOut(fco)) );
			assignrelid(fco);
		}
	}
	ASSERT( fco != NULL );

	CComObjPtr<IMgaSet> mgaset;
	COMTHROW( fco.QueryInterface(mgaset) );

	if( !(GetByName(attributes, "isbound") == "yes") ) {
		COMTHROW( mgaset->RemoveAll() ); //by ZolMol: if not bound then the members are different, remove the inherited members
		slist< CComObjPtr<IMgaFCO> >::iterator i = members.begin();
		while( i != members.end() )
		{
			COMTHROW( mgaset->AddMember(*i) );
			++i;
		}
	}
	GetCurrent().object = fco;

	RegisterLookup(attributes, fco);
}


--- NEW FILE: MgaParserClosureHelper.cpp ---
#include "stdafx.h"
#include "Parser.h"
#include "MgaParser.h"
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <stdio.h>

#include "../Common/CommonCollection.h"
#include "../Common/CommonMgaTrukk.h"
#include <slist>
#include "helper.h"

void CMgaParser::findObjOnAbsPath( CComObjPtr<IMgaProject> p_project, const string& p_absPath , CComObjPtr<IMgaObject>& p_obj, const string& text)
{
	COMTHROW( p_project->get_ObjectByPath( PutInBstr( p_absPath), PutOut( p_obj)) );
	if( !p_obj) // if nonunique is allowed
	{
		COMTHROW( p_project->get_NthObjectByPath( 0, PutInBstr( p_absPath), PutOut( p_obj)) );

		if( p_obj)
		{
			// name ambiguity exists for sure
			//<!> warning about non uniqueness
			if( m_GME) 
			{
				CComBSTR bstr, id, nm;
				COMTHROW( p_obj->get_ID( &id));
				COMTHROW( p_obj->get_Name( &nm));
				bstr.Append("[Smartcopy Parser] Name ambiguity, selected: <A HREF=\"mga:");
				bstr.AppendBSTR( id);
				bstr.Append("\">");
				if( nm.Length()!= 0)
					bstr.AppendBSTR( nm);
				else
					bstr.Append("emptyname");
				bstr.Append("</A>");
				
				if( !text.empty())
				{
					bstr.Append(" as ");
					bstr.Append( text.c_str());
				}

				bstr.Append(". Search path used: ");
				bstr.Append( makeViewable(p_absPath).c_str());

				COMTHROW( m_GME->ConsoleMessage(bstr, MSG_WARNING));
			}
		}
	}
}

void CMgaParser::findObjOnRelPath( CComObjPtr<IMgaObject> obj_rel_to, const string& relpath , CComObjPtr<IMgaObject>& obj, const string& text)
{
	ASSERT( !relpath.empty());
	ASSERT( obj_rel_to);

	CComObjPtr<IMgaFCO> cur_fco;
	CComObjPtr<IMgaFolder> cur_fld;

	obj_rel_to.QueryInterface( cur_fco);
	obj_rel_to.QueryInterface( cur_fld);

	bool isfco = (cur_fco != NULL);

	string m = relpath;
	
	while( m.substr(0,4) == "/@..")
	{
		CComObjPtr<IMgaModel> mod;
		if( isfco) COMTHROW( cur_fco->get_ParentModel( PutOut( mod)) );

		if ( mod)	// has a valid model parent
		{
			cur_fco = mod;
		}
		else		// must have folder parent
		{
			CComObjPtr<IMgaFolder> fold;

			if( isfco)  COMTHROW( cur_fco->get_ParentFolder( PutOut( fold)) );
			else		COMTHROW( cur_fld->get_ParentFolder( PutOut( fold)) );
			
			if ( fold)
			{
				isfco = false;
				cur_fld = fold;
			}
			// else rootfolder reached: wrong path information
		}
		
		m = m.substr(4);
	}
	
	if( m.empty())
	{
		if (isfco)	obj = cur_fco;
		else 		obj = cur_fld;
	}
	else if( isfco)
		COMTHROW( cur_fco->get_ObjectByPath( PutInBstr( m), PutOut( obj)) );
	else
		COMTHROW( cur_fld->get_ObjectByPath( PutInBstr( m), PutOut( obj)) );

	if( !obj) // not found , name ambiguity may exist, take the 1st
	{
		if( isfco)
			COMTHROW( cur_fco->get_NthObjectByPath( 0, PutInBstr( m), PutOut( obj)) );
		else
			COMTHROW( cur_fld->get_NthObjectByPath( 0, PutInBstr( m), PutOut( obj)) );

		if( obj) // name ambiguity exists for sure
		{
			if( m_GME) 
			{
				CComBSTR bstr, id, nm;
				COMTHROW( obj->get_ID( &id));
				COMTHROW( obj->get_Name( &nm));
				bstr.Append("[Smartcopy Parser] Name ambiguity, selected: <A HREF=\"mga:");
				bstr.AppendBSTR( id);
				bstr.Append("\">");
				if( nm.Length()!= 0)
					bstr.AppendBSTR( nm);
				else
					bstr.Append("emptyname");
				bstr.Append("</A>"); 

				if( !text.empty())
				{
					bstr.Append(" as ");
					bstr.Append( text.c_str());
				}

				bstr.Append(". Search path used: ");
				bstr.Append( makeViewable(relpath).c_str());

				COMTHROW( m_GME->ConsoleMessage(bstr, MSG_WARNING));
			}
		}
	}
}

bool CMgaParser::findPlaceForElem( 
							     const attributes_type &attributes
							   , deriv_type& deriv
							   , CComObjPtr<IMgaObject>& place
							)
{
	const string *nm = GetByNameX(attributes, "closurepath");
	if( nm != NULL)
	{
		if( nm->compare("") == 0)
		{
			place = m_target;
			return true;
		}
		else
		{
			findObjOnRelPath( m_target, *nm, place, "place");
			if( place)
				return true;
			else
				ASSERT(0);
		}
	}
	return false;
}

//<!> check if findObjOnRelPath is given "" string

bool CMgaParser::findPlaceForElem( 
							     const attributes_type &attributes
							   , deriv_type& deriv
							   , CComObjPtr<IMgaFolder>& place_folder
							   , CComObjPtr<IMgaModel>& place_model
							)
{
	
	CComObjPtr<IMgaObject> place;
	if( findPlaceForElem( attributes, deriv, place))
	{
		place.QueryInterface( place_folder);
		place.QueryInterface( place_model);
		return (place_folder || place_model);
	}
	else
	{
		place = m_target;//<!> let's try this
		place.QueryInterface( place_folder);
		place.QueryInterface( place_model);
		return (place_folder || place_model);
	}
	return false;
}

/*static*/ CComPtr<IGMEOLEApp> CMgaParser::get_GME(CComObjPtr<IMgaProject> project)
{
	CComPtr<IGMEOLEApp> gme;
	if ( (project != NULL)) {		
		CComBSTR bstrName("GME.Application");
		CComPtr<IMgaClient> pClient;
		HRESULT hr = project->GetClientByName(bstrName, &pClient);
		if (SUCCEEDED(hr) && pClient) {
			CComPtr<IDispatch> pDispatch;
			hr = pClient->get_OLEServer(&pDispatch);
			if (SUCCEEDED(hr) && pDispatch) {
				hr = pDispatch.QueryInterface(&gme);
				if (FAILED(hr)) {
					gme = NULL;
				}
			}
		}
	}
	return gme;
} 

/*static*/ void CMgaParser::clear_GME( CComPtr<IGMEOLEApp>& p_GME)
{
	p_GME = CComPtr<IGMEOLEApp>();
}

void CMgaParser::popInfo()
{
	if( m_parsed1.empty() || m_parsed2.empty()) return; // empty stack of informations

	CComObjPtr<IMgaObject> obj = m_parsed1[0]; m_parsed1.pop_back();
	CComObjPtr<IMgaObject> fco1 = m_parsed2[0]; m_parsed2.pop_back();
	CComObjPtr<IMgaObject> fco2 = m_parsed3[0]; m_parsed3.pop_back();

	writeInfo( obj, fco1, fco2);
}

void CMgaParser::pushInfo( const CComObjPtr<IMgaFolder>& place_fld, const CComObjPtr<IMgaModel>& place_mdl, const CComObjPtr<IMgaFCO>& fco1, const CComObjPtr<IMgaFCO>& fco2)
{
	CComObjPtr<IMgaObject> obj;
	if( place_fld)
		obj = place_fld;
	else if( place_mdl)
		obj = place_mdl;
	else ASSERT(0);

	//m_parsed.push_back( pair< CComObjPtr<IMgaObject>, CComObjPtr<IMgaObject>( obj, fco1) );
	m_parsed1.push_back( obj);
	m_parsed2.push_back( CComObjPtr<IMgaObject>( fco1));
	m_parsed3.push_back( CComObjPtr<IMgaObject>( fco2));
}

void CMgaParser::writeInfo( const CComObjPtr<IMgaObject>& obj, const CComObjPtr<IMgaObject>& fco1, const CComObjPtr<IMgaObject>& fco2, bool normal_msg)
{
	if( obj && fco1 )
	{
		CComBSTR bstr, id2, nm2, id1, nm1, id0, nm0;
		COMTHROW( obj->get_ID( &id0));
		COMTHROW( obj->get_Name( &nm0));
		COMTHROW( fco1->get_ID( &id1));
		COMTHROW( fco1->get_Name( &nm1));
		if( fco2) COMTHROW( fco2->get_ID( &id2));
		if( fco2) COMTHROW( fco2->get_Name( &nm2));

		bstr.Append("[Smartcopy Parser] <A HREF=\"mga:");
		bstr.AppendBSTR( id1);
		bstr.Append("\">");

		if( nm1.Length() != 0)	bstr.AppendBSTR( nm1);
		else					bstr.Append("emptyname");

		bstr.Append( "</A>");

		if( fco2) 
		{
			bstr.Append( " derived from <A HREF=\"mga:");
			bstr.AppendBSTR( id2);
			bstr.Append("\">");

			if( nm2.Length() != 0)	bstr.AppendBSTR( nm2);
			else					bstr.Append("emptyname");

			bstr.Append("</A>");
		}

		if( !normal_msg)
			bstr.Append(" could not be");
		bstr.Append( " inserted into <A HREF=\"mga:");
		bstr.AppendBSTR( id0);
		bstr.Append( "\">");

		if( nm0.Length() != 0)	bstr.AppendBSTR( nm0);
		else					bstr.Append("emptyname");

		bstr.Append( "</A>.");
		if( m_GME) 
		{
			if( normal_msg) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_INFO));
			else			COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
		}
	}
}
--- NEW FILE: MgaParserSC.cpp ---
#include "stdafx.h"
#include "Parser.h"
#include "MgaParser.h"
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <stdio.h>

#include "../Common/CommonCollection.h"
#include "../Common/CommonMgaTrukk.h"
#include <slist>
#include "helper.h"

// --------------------------- CMgaParser - copy closure dumped data parsing

STDMETHODIMP CMgaParser::ParseClos4(IMgaObject *here, BSTR filename)
{
	CHECK_IN(here);

	try
	{
		CloseAll();

		COMTHROW( progress.CoCreateInstance(L"Mga.MgaProgressDlg") );
		COMTHROW( progress->SetTitle(PutInBstr("Importing SmartCopied XML data...")) );
		COMTHROW( progress->StartProgressDialog(NULL) );

		CComObjPtr<IMgaProject> p;
		COMTHROW( here->get_Project(PutOut(p)) );
		ASSERT( p != NULL );
		COMTHROW( p->get_Preferences(&project_prefs_orig) );
		manual_relid_mode = project_prefs_orig & MGAPREF_MANUAL_RELIDS ? true : false;

		m_GME = get_GME( p);//by zolmol

		COMTHROW( p->CreateTerritory(NULL, PutOut(territory), NULL) );
		COMTHROW( p->BeginTransaction(territory, TRANSACTION_NON_NESTED) );

		CComObjPtr<IMgaObject> target;
		COMTHROW(territory->OpenObj(here, PutOut(target)));

		//by zolmol
		m_target = target;
		m_resolveDerFuncPtr = CMgaParser::ResolveClosure4Derivation;
		m_clVer = 4;
		m_clVerStr = "4";//end

		project_prefs = project_prefs_orig | MGAPREF_IGNORECONNCHECKS;
		COMTHROW( p->put_Preferences(project_prefs) );

		COMTHROW( resolver.CoCreateInstance(L"Mga.MgaResolver") );
		ASSERT( resolver != NULL );

		project = p;

		CopyTo(filename, xmlfile);

		try
		{
			XMLPlatformUtils::Initialize();

			SAXParser parser;
			parser.setDoValidation(true);
			parser.setDocumentHandler(this);
			parser.setErrorHandler(this);
			parser.setEntityResolver(this);

			elementfuncs = elementfuncs_scmga;

			// manual first pass

			pass_count = 1;

			ranges.clear();
			ranges.push_front();
			ranges.front().begin = 1;
			ranges.front().end = (counter_type)-1;
			ranges.front().previous.name = "start";
			ranges.front().previous.object = target;
			skip_element_level = 0;
			
			parser.parse(xmlfile.c_str());

			ASSERT( ranges.front().begin == 1 );
			ranges.pop_front();
			elements.clear();

			max_counter = counter;

			// the other passes

			parser.setDoValidation(false);

			while( !ranges.empty() && ranges.front().begin != (counter_type)-1 )
			{
				// FIXME: better algorithm for infinite loop
				if( ++pass_count >= 1 )//<!> reduced from 100 to 5
					HR_THROW(E_TOOMANYPASSES);

				parser.parse(xmlfile.c_str());
			}

			ASSERT( elements.empty() );
			ranges.clear();
		}
	    catch(const XMLException &e)
		{
			XmlStr desc(e.getMessage());

			ThrowXmlError(desc.c_str());
		}
		COMTHROW( project->put_Preferences(project_prefs_orig) );

		for(librecords::iterator i = libstodo.begin(); i != libstodo.end(); i++) { // copied from ParseProject in order to recognize libraries (zolmol)
			COMTHROW(i->f->put_LibraryName(CComBSTR(i->libname.c_str())));
			COMTHROW(i->f->put_Exempt(VARIANT_FALSE));
		}
		libstodo.clear();

		COMTHROW( project->CommitTransaction() );
		project = NULL;
		clear_GME( m_GME);

		CloseAll();
	}
	catch(hresult_exception &e)
	{
		CloseAll();

		ASSERT( FAILED(e.hr) );
		if( e.hr == E_XMLPARSER )
			SetErrorInfo(errorinfo);
		else
			SetErrorInfo2(e.hr);

		return e.hr;
	}
	return S_OK;
}

CMgaParser::elementfunc CMgaParser::elementfuncs_scmga[] = 
{
	//elementfunc("project", StartProject, EndNone),
	elementfunc("name", StartNone, EndName),
	elementfunc("comment", StartNone, EndComment),
	elementfunc("author", StartNone, EndAuthor),
	elementfunc("value", StartNone, EndValue),
	elementfunc("regnode", StartRegNode, EndNone),
	elementfunc("attribute", StartAttribute, EndNone),
	elementfunc("constraint", StartNone, EndConstraint),
	elementfunc("folder", StartFolder, EndNone),
	elementfunc("model", StartModel, EndNone),
	elementfunc("atom", StartAtom, EndNone),
	elementfunc("connection", StartSCConnection, EndSCConnection),	//
	elementfunc("connpoint", StartSCConnPoint, EndNone),	//
	elementfunc("reference", StartSCReference, EndSCReference),	//
	elementfunc("set", StartSCSet, EndSCSet),				//
	elementfunc("clipboard", StartBCClipboard, EndNone),	// common for closures
	elementfunc("", NULL, NULL)
};

void CMgaParser::ResolveClosure4Derivation(const attributes_type &attributes, deriv_type &deriv)
{
	const string *s = GetByNameX(attributes, "derivedfrom");
	if( s == NULL )
	{
		s = GetByNameX(attributes, "closurelibderivedfrom");
		if( s != NULL)
		{
			CComObjPtr<IMgaObject> obj;
			findObjOnAbsPath( project, *s, obj, "archetype");
			if( obj)
				COMTHROW( obj.QueryInterface( deriv.from));
			else if( m_GME)
			{
				CComBSTR bstr("[Smartcopy Parser] Archetype can not be found in library. Basetype lost. ");
				bstr.Append("Search path used: ");
				bstr.Append( makeViewable(*s).c_str());
				COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}

		}
		else //if( s == NULL)
		{
			s = GetByNameX( attributes, "closure2derivedfrom");
			if( s != NULL)
			{
				CComObjPtr<IMgaFolder> place_f;
				CComObjPtr<IMgaModel> place_m;
				//<!>
				// it searches for the objects place (one more time this search will occur later) 
				bool place_found = findPlaceForElem( attributes, deriv, place_f, place_m);
				
				string rel_path_changed = *s;
				// since the derfrom is calculated relatively to the fco, 
				// we have to modify the path so that it could be found
				// with a search starting from place_m _f
				if( rel_path_changed.substr(0, 4) == "/@..")
					rel_path_changed = rel_path_changed.substr(4);
				else if( rel_path_changed == "")
				{
					//<!>
					// the object has similar name to its archetype
					ASSERT(0);
					deriv.from.Release();
					return;
				}
				else // the derfrom object cannot be inside the derived object
				{
					ASSERT(0);
					deriv.from.Release();
					return;
				}

				CComObjPtr<IMgaObject> obj;
				if( place_f)
					findObjOnRelPath( CComObjPtr<IMgaObject>(place_f), rel_path_changed, obj, "archetype");
				else if(place_m)
					findObjOnRelPath( CComObjPtr<IMgaObject>(place_m), rel_path_changed, obj, "archetype");

				if( obj)
					COMTHROW( obj.QueryInterface( deriv.from));
				else if( m_GME) // error report
				{
					CComBSTR bstr("[Smartcopy Parser] Archetype can not be found. Basetype lost. ");
					bstr.Append("Search path used: ");
					bstr.Append( makeViewable(rel_path_changed).c_str());
					COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
				}
			}
			else
			{
				deriv.from.Release();
				return;
			}
		}


		if ( deriv.from == NULL) // do not throw exception in case of closurelibderivedfrom
		{
			deriv.from.Release();
			return;
		}
	}
	else
	{
		LookupByID(*s, deriv.from);

		if( deriv.from == NULL )
			throw pass_exception();
	}

	s = GetByNameX(attributes, "isinstance");
	deriv.isinstance = ( s != NULL && *s == "yes" ) ? VARIANT_TRUE : VARIANT_FALSE;

	s = GetByNameX(attributes, "isprimary");
	deriv.isprimary = ( s != NULL && *s == "no" ) ? false : true;
}

// ------- Element Handlers
void CMgaParser::StartSCConnection(const attributes_type &attributes)
{
	bool place_found = false;
	CComObjPtr<IMgaFolder> place_f;
	CComObjPtr<IMgaModel> place_m;

	CComObjPtr<IMgaFCO> conn;
	deriv_type deriv;
	//ResolveDerivation(attributes, deriv);
	(*this.*m_resolveDerFuncPtr)(attributes, deriv);

	if( !(place_found = findPlaceForElem( attributes, deriv, place_f, place_m)))
		throw pass_exception();//<!>

	if( place_f)
	{
		CComObjPtr<IMgaFolder> prev;
		prev = place_f;

		preparerelid(attributes);
		if( deriv.from != NULL )
		{
			COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(conn)) );
		}
		else
		{
			CComObjPtr<IMgaMetaFCO> meta;
			COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, "kind"), 
				OBJTYPE_CONNECTION, PutOut(meta)) );
			ASSERT( meta != NULL );

			COMTHROW( prev->CreateRootObject(meta, PutOut(conn)) );
		}
		assignrelid(conn);
	}
	else
	{
		ASSERT( place_m);
		CComObjPtr<IMgaModel> prev;
		prev = place_m;

		CComObjPtr<IMgaMetaRole> role;
		COMTHROW( resolver->get_RoleByStr(prev, 
			PutInBstrAttr(attributes, "kind"), OBJTYPE_CONNECTION,
			PutInBstrAttr(attributes, "role"), NULL, PutOut(role)) );
		ASSERT( role != NULL );

		if( deriv.from != NULL )
		{
			CComObjPtr<IMgaConnection> derivedfrom;
			COMTHROW( deriv.from.QueryInterface(derivedfrom) );

			if( deriv.isprimary )
			{
				preparerelid(attributes);
				COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(conn)) );
				assignrelid(conn);
			}
			else
			{
				COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(conn)) );
			}
		}
		else
		{
			preparerelid(attributes);
			COMTHROW( prev->CreateChildObject(role, PutOut(conn)) );
			assignrelid(conn);
		}
	}
	ASSERT( conn != NULL );
	GetCurrent().object = conn;

	if( GetByName(attributes, "isbound") == "yes" ) GetCurrent().exstrinfo = "skip";

	RegisterLookup(attributes, conn);
}

void CMgaParser::StartSCConnPoint(const attributes_type &attributes)
{
	ASSERT( GetPrevName() == "connection" );
	CComObjPtr<IMgaConnection> conn;
	GetPrevObj(conn);
	
	CComBstrObj ccname; // does not have "closurename" attribute, that is why we use the connection's name property
	COMTHROW( conn->get_Name( PutOut( ccname)));
	string viewable_name; 
	CopyTo( ccname, viewable_name);

	if( GetPrevious().exstrinfo == "skip" || GetByName(attributes, "isbound") == "yes" ) return;

	CComObjPtr<IMgaFCO> target;

	const string *closlibtg = GetByNameX(attributes, "closurelibtarget");
	if ( closlibtg != NULL)
	{
		CComObjPtr<IMgaObject> obj;
		findObjOnAbsPath( project, *closlibtg, obj, "connection target");
		if ( obj)
			COMTHROW( obj.QueryInterface( target));
		else // error report
		{
			CComBSTR bstr("[Smartcopy Parser] Connection \"");
			bstr.Append( viewable_name.c_str());
			bstr.Append("\": target not found in library. ");
			bstr.Append("Search path used: ");
			bstr.Append( makeViewable( *closlibtg).c_str());
			if( m_GME) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
		}
	}

	if( closlibtg == NULL || !target)
	{
		const string *clos2tg = GetByNameX(attributes, "closure2target");
		if( clos2tg != NULL)
		{
			CComObjPtr<IMgaObject> obj;
			findObjOnRelPath( CComObjPtr<IMgaObject>(conn), *clos2tg, obj, "connection target");
			if ( obj)
				COMTHROW( obj.QueryInterface( target));
			else // error report
			{
				CComBSTR bstr("[Smartcopy Parser] Connection \"");
				bstr.Append( viewable_name.c_str());
				bstr.Append("\": target not found. ");
				bstr.Append("Search path used: ");
				bstr.Append( makeViewable( *clos2tg).c_str());
				if( m_GME) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}
		}
	}

	// throw even if closurelibtarget present but not found the needed object
	if ( target == NULL)
		throw pass_exception();

	CComObjPtr<IMgaFCOs> coll;
	COMTHROW(coll.CoCreateInstance(L"Mga.MgaFCOs"));

	const string *s = GetByNameX(attributes, "closure2refs");
	if( s != NULL )
	{
		int pos = s->find_first_not_of(' ', 0);
		ASSERT( pos >= 0 );
		while( pos < s->length() )
		{
			int pos2 = s->find_first_of(' ', pos);
			if( pos2 < 0 )
				pos2 = s->length();
			ASSERT( pos2 > pos );

			CComObjPtr<IMgaFCO> ref;
			//LookupByID(string(*s, pos, pos2-pos), ref);
			CComObjPtr<IMgaObject> obj;
			string ref_str(*s, pos, pos2-pos);
			findObjOnRelPath( CComObjPtr<IMgaObject>(conn), ref_str, obj, "reference chain");
			if ( obj)
				COMTHROW( obj.QueryInterface( ref));
			else // error report
			{
				CComBSTR bstr("[Smartcopy Parser] Reference not found involved in Connection \"");
				bstr.Append( viewable_name.c_str());
				bstr.Append("\". ");
				bstr.Append("Search path used: ");
				bstr.Append( makeViewable( ref_str).c_str());
				if( m_GME) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}

			if( ref == NULL )
				throw pass_exception();

			COMTHROW(coll->Append(ref));

			pos = pos2+1;
		}
	}

	CComObjPtr<IMgaConnPoint> connpoint;

	COMTHROW( conn->AddConnPoint(PutInBstr(GetByName(attributes, "role")), 0,	// FIXME: multiplicity
		target, coll, PutOut(connpoint)) );
}

void CMgaParser::StartSCReference(const attributes_type &attributes)
{
	bool place_found = false;
	CComObjPtr<IMgaFolder> place_f;
	CComObjPtr<IMgaModel> place_m;

	CComObjPtr<IMgaFCO> fco;

	deriv_type deriv;
	//ResolveDerivation(attributes, deriv);
	(*this.*m_resolveDerFuncPtr)(attributes, deriv);

	CComObjPtr<IMgaFCO> referred;

	const string *s;

	if( !(place_found = findPlaceForElem( attributes, deriv, place_f, place_m)))
		throw pass_exception();//<!>

	if( place_f)
	{
		CComObjPtr<IMgaFolder> prev;
		prev = place_f;

		preparerelid(attributes);
		if( deriv.from != NULL )
		{
			COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(fco)) );
		}
		else
		{
			CComObjPtr<IMgaMetaFCO> meta;
			COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, "kind"), 
				OBJTYPE_REFERENCE, PutOut(meta)) );
			ASSERT( meta != NULL );

			COMTHROW( prev->CreateRootObject(meta, PutOut(fco)) );
		}
		assignrelid(fco);
	}
	else
	{
		ASSERT( place_m);
		CComObjPtr<IMgaModel> prev;
		prev = place_m;

		CComObjPtr<IMgaMetaRole> role;
		COMTHROW( resolver->get_RoleByStr(prev, 
			PutInBstrAttr(attributes, "kind"), OBJTYPE_REFERENCE,
			PutInBstrAttr(attributes, "role"), NULL, PutOut(role)) );
		ASSERT( role != NULL );

		if( deriv.from != NULL )
		{
			CComObjPtr<IMgaReference> derivedfrom;
			COMTHROW( deriv.from.QueryInterface(derivedfrom) );

			if( deriv.isprimary )
			{
				preparerelid(attributes);
				COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(fco)) );
				assignrelid(fco);
			}
			else
			{
				COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(fco)) );
			}
		}
		else
		{
			preparerelid(attributes);
			COMTHROW( prev->CreateChildObject(role, PutOut(fco)) );
			assignrelid(fco);
		}
	}
	ASSERT( fco != NULL );
	//fco is the reference just created

	s = GetByNameX(attributes, "closurelibreferred");
	if( s != NULL)
	{
		CComObjPtr<IMgaObject> obj;
		findObjOnAbsPath( project, *s, obj, "referred object");

		if( obj)
			COMTHROW( obj.QueryInterface( referred));
		else // report error
		{
			CComBSTR bstr("[Smartcopy Parser] Reference \"");
			bstr.Append( makeNameViewable( GetByName( attributes, "closurename")).c_str());
			bstr.Append("\": target not found in library. ");
			bstr.Append("Search path used: ");
			bstr.Append( makeViewable( *s).c_str());
			if( m_GME) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
		}
	}
	
	if( s == NULL || !referred)
	{
		s = GetByNameX(attributes, "closure2referred");
		if( s != NULL && s->compare("") != 0)
		{
			CComObjPtr<IMgaObject> obj;
			findObjOnRelPath( CComObjPtr<IMgaObject>(fco), *s, obj, "referred object");

			if ( obj)
				COMTHROW( obj.QueryInterface( referred));
			else // report error
			{
				CComBSTR bstr("[Smartcopy Parser] Reference \"");
				bstr.Append( makeNameViewable( GetByName( attributes, "closurename")).c_str());
				bstr.Append("\": target not found. ");
				bstr.Append("Search path used: ");
				bstr.Append( makeViewable( *s).c_str());
				if( m_GME) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}
		}
	}

	if( !(GetByName(attributes, "isbound") == "yes") && referred != NULL )
	{
		CComObjPtr<IMgaReference> ref;
		COMTHROW( fco.QueryInterface(ref) );

		COMTHROW( ref->put_Referred(referred) );
	}

	GetCurrent().object = fco;

	RegisterLookup(attributes, fco);
	pushInfo( place_f, place_m, fco, deriv.from);
}

void CMgaParser::StartSCSet(const attributes_type &attributes)
{
	bool place_found;
	CComObjPtr<IMgaFolder> place_f;
	CComObjPtr<IMgaModel> place_m;
	CComObjPtr<IMgaFCO> fco;

	deriv_type deriv;
	//ResolveDerivation(attributes, deriv);
	(*this.*m_resolveDerFuncPtr)(attributes, deriv);

	if( !( place_found = findPlaceForElem( attributes, deriv, place_f, place_m)))
		throw pass_exception();//<!>

	if( place_f)
	{
		CComObjPtr<IMgaFolder> prev;
		prev = place_f;

		preparerelid(attributes);
		if( deriv.from != NULL )
		{
			COMTHROW( prev->DeriveRootObject(deriv.from, deriv.isinstance, PutOut(fco)) );
		}
		else
		{
			CComObjPtr<IMgaMetaFCO> meta;
			COMTHROW( resolver->get_KindByStr(prev, PutInBstrAttr(attributes, "kind"), 
				OBJTYPE_SET, PutOut(meta)) );
			ASSERT( meta != NULL );

			COMTHROW( prev->CreateRootObject(meta, PutOut(fco)) );
		}
		assignrelid(fco);
	}
	else
	{
		ASSERT( place_m);
		CComObjPtr<IMgaModel> prev;
		prev = place_m;

		CComObjPtr<IMgaMetaRole> role;
		COMTHROW( resolver->get_RoleByStr(prev, 
			PutInBstrAttr(attributes, "kind"), OBJTYPE_SET,
			PutInBstrAttr(attributes, "role"), NULL, PutOut(role)) );
		ASSERT( role != NULL );

		if( deriv.from != NULL )
		{
			CComObjPtr<IMgaSet> derivedfrom;
			COMTHROW( deriv.from.QueryInterface(derivedfrom) );

			if( deriv.isprimary )
			{
				preparerelid(attributes);
				COMTHROW( prev->DeriveChildObject(derivedfrom, role, deriv.isinstance, PutOut(fco)) );
				assignrelid(fco);
			}
			else
			{
				preparerelid(attributes);
				COMTHROW( prev->get_ChildDerivedFrom(derivedfrom, PutOut(fco)) );
				assignrelid(fco);
			}
		}
		else
		{
			preparerelid(attributes);
			COMTHROW( prev->CreateChildObject(role, PutOut(fco)) );
			assignrelid(fco);
		}
	}
	ASSERT( fco != NULL );
	slist< CComObjPtr<IMgaFCO> > members;

	const string *s = GetByNameX(attributes, "closure2members");
	if( s != NULL)
	{
		int pos = s->find_first_not_of(' ', 0);
		ASSERT( pos >= 0 );
		while( pos < s->length() )
		{
			int pos2 = s->find_first_of(' ', pos);
			if( pos2 < 0 )
				pos2 = s->length();
			ASSERT( pos2 > pos );

			string member_str(*s, pos, pos2-pos);
			CComObjPtr<IMgaObject> obj;
			findObjOnRelPath( CComObjPtr<IMgaObject>(fco), member_str, obj, "set member");

			if ( obj)
			{
				CComObjPtr<IMgaFCO> member;
				COMTHROW( obj.QueryInterface( member));
				members.push_front(member);
			}
			else // error report
			{
				CComBSTR bstr("[Smartcopy Parser] Set \"");
				bstr.Append( makeNameViewable( GetByName( attributes, "closurename")).c_str());
				bstr.Append("\": member not found. ");
				bstr.Append("Search path used: ");
				bstr.Append( makeViewable( member_str).c_str());
				if( m_GME) COMTHROW( m_GME->ConsoleMessage(bstr, MSG_ERROR));
			}

			pos = pos2+1;
		}
	}

	CComObjPtr<IMgaSet> mgaset;
	COMTHROW( fco.QueryInterface(mgaset) );

	if( !(GetByName(attributes, "isbound") == "yes") ) {
		COMTHROW( mgaset->RemoveAll() ); //by ZolMol: if not bound then the members are different, remove the inherited members
		slist< CComObjPtr<IMgaFCO> >::iterator i = members.begin();
		while( i != members.end() )
		{
			COMTHROW( mgaset->AddMember(*i) );
			++i;
		}
	}
	GetCurrent().object = fco;

	RegisterLookup(attributes, fco);
	pushInfo( place_f, place_m, fco, deriv.from);
}



void CMgaParser::EndSCReference()
{
	popInfo();
}

void CMgaParser::EndSCSet()
{
	popInfo();
}

void CMgaParser::EndSCConnection()
{
	ASSERT( GetCurrent().object);
	if( !GetCurrent().object) return;

	CComObjPtr<IMgaSimpleConnection> cur_conn;

	COMTHROW( GetCurrent().object.QueryInterface( cur_conn));

	if( !cur_conn) return;

	CComObjPtr<IMgaModel> parent_m;
	CComObjPtr<IMgaFolder> parent_f;

	COMTHROW( cur_conn->get_ParentModel( PutOut( parent_m)));
	COMTHROW( cur_conn->get_ParentFolder( PutOut( parent_f)));

	CComObjPtr<IMgaObject> parent_obj;
	if( parent_f)
		parent_obj = parent_f;
	else if( parent_m)
		parent_obj = parent_m;

	if( !parent_obj) return;

	CComObjPtr<IMgaFCO> s,d;
	COMTHROW( cur_conn->get_Src( PutOut( s)));
	COMTHROW( cur_conn->get_Dst( PutOut( d)));

	// 3rd param: ignore its basetype, anyway it is a connection
	// 4th param: error msg to be displayed if (s && d) is false
	writeInfo( parent_obj, CComObjPtr<IMgaObject>( cur_conn), CComObjPtr<IMgaObject>(), s && d );
}

--- NEW FILE: mgaclosure.dtd ---
<?xml version="1.0" encoding="UTF-8"?>

<!ENTITY lt     "&#38;#60;">
<!ENTITY gt     "&#62;">
<!ENTITY amp    "&#38;#38;">
<!ENTITY apos   "&#39;"> 
<!ENTITY quot   "&#34;">

<!ELEMENT project (name, comment?, author?, folder)>
<!ATTLIST project
	version		CDATA		#IMPLIED
	guid		CDATA		#IMPLIED
	cdate		CDATA		#IMPLIED
	mdate		CDATA		#IMPLIED
	metaversion	CDATA		#IMPLIED
	metaguid	CDATA		#IMPLIED
	metaname	CDATA		#REQUIRED
>

<!ELEMENT name (#PCDATA)>
<!ELEMENT comment (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT value (#PCDATA)>

<!ELEMENT constraint (name, value)>

<!ELEMENT regnode (value, regnode*)>
<!ATTLIST regnode
	name		CDATA		#REQUIRED
	status		(inherited|meta) #IMPLIED
	isopaque	(yes|no)	"no"
>

<!ELEMENT folder (name, (regnode|constraint|folder|model|atom|reference|set|connection)*)>
<!ATTLIST folder
	id			ID			#IMPLIED
	kind		NMTOKEN		#REQUIRED
	relid		CDATA		#IMPLIED
	childrelidcntr	CDATA	#IMPLIED
	libref		CDATA		#IMPLIED
	closurename	CDATA		#IMPLIED		
	closurepath	CDATA		#IMPLIED		
	merge	(yes|no)	"no"	
>

<!ELEMENT model (name, (regnode|constraint|attribute|model|atom|reference|set|connection)*)>
<!ATTLIST model
	id			ID			#IMPLIED
	kind		NMTOKEN		#REQUIRED
	role		NMTOKEN		#IMPLIED
	derivedfrom	CDATA		#IMPLIED
	closurelibderivedfrom	CDATA		#IMPLIED
	closure2derivedfrom	CDATA		#IMPLIED
	isinstance	(yes|no)	"no"
	isprimary	(yes|no)	"yes"
	relid		CDATA		#IMPLIED
	childrelidcntr	CDATA		#IMPLIED
	closurename	CDATA		#IMPLIED	
	closurepath	CDATA		#IMPLIED		
	merge	(yes|no)	"no"	
>

<!ELEMENT atom (name, (regnode|constraint|attribute)*)>
<!ATTLIST atom
	id			ID			#IMPLIED
	kind		NMTOKEN		#REQUIRED
	role		NMTOKEN		#IMPLIED
	derivedfrom	CDATA		#IMPLIED
	closurelibderivedfrom	CDATA		#IMPLIED
	closure2derivedfrom	CDATA		#IMPLIED
	isinstance	(yes|no)	"no"
	isprimary	(yes|no)	"yes"
	relid		CDATA		#IMPLIED
	closurename	CDATA		#IMPLIED	
	closurepath	CDATA		#IMPLIED		
	merge	(yes|no)	"no"	
>

<!ELEMENT reference (name, (regnode|constraint|attribute)*)>
<!ATTLIST reference
	id			ID			#IMPLIED
	kind		NMTOKEN		#REQUIRED
	role		NMTOKEN		#IMPLIED
	derivedfrom	CDATA		#IMPLIED
	closurelibderivedfrom	CDATA		#IMPLIED
	closure2derivedfrom	CDATA		#IMPLIED
	isinstance	(yes|no)	"no"
	isprimary	(yes|no)	"yes"
	referred	CDATA		#IMPLIED
	closurelibreferred	CDATA		#IMPLIED
	closure2referred	CDATA		#IMPLIED
	isbound		(yes|no)	"no"
	relid		CDATA		#IMPLIED
	closurename	CDATA		#IMPLIED	
	closurepath	CDATA		#IMPLIED		
	merge	(yes|no)	"no"	
>

<!ELEMENT set (name, (regnode|constraint|attribute)*)>
<!ATTLIST set
	id			ID			#IMPLIED
	kind		NMTOKEN		#REQUIRED
	role		NMTOKEN		#IMPLIED
	derivedfrom	CDATA		#IMPLIED
	closurelibderivedfrom	CDATA		#IMPLIED
	closure2derivedfrom	CDATA		#IMPLIED
	closure2members	CDATA		#IMPLIED
	isinstance	(yes|no)	"no"
	isprimary	(yes|no)	"yes"
	members		CDATA		#IMPLIED
	isbound		(yes|no)	"no"
	relid		CDATA		#IMPLIED
	closurename	CDATA		#IMPLIED	
	closurepath	CDATA		#IMPLIED		
	merge	(yes|no)	"no"	
>

<!ELEMENT connection (name?, (regnode|constraint|connpoint|attribute)*)>
<!ATTLIST connection
	id			ID			#IMPLIED
	kind		NMTOKEN		#REQUIRED
	role		NMTOKEN		#IMPLIED
	derivedfrom	CDATA		#IMPLIED
	closurelibderivedfrom	CDATA		#IMPLIED
	closure2derivedfrom	CDATA		#IMPLIED
	isinstance	(yes|no)	"no"
	isprimary	(yes|no)	"yes"
	isbound		(yes|no)	"no"
	relid		CDATA		#IMPLIED
	closurename	CDATA		#IMPLIED	
	closurepath	CDATA		#IMPLIED		
	merge	(yes|no)	"no"	
>

<!ELEMENT connpoint EMPTY>
<!ATTLIST connpoint
	role		NMTOKEN		#REQUIRED
	closurelibtarget	CDATA		#IMPLIED
	closure2target	CDATA		#IMPLIED
	target		CDATA		#IMPLIED
	refs		CDATA		#IMPLIED
	closure2refs		CDATA		#IMPLIED
	isbound		(yes|no)	"no"
>

<!ELEMENT attribute (value, regnode*)>
<!ATTLIST attribute
	kind		NMTOKEN		#REQUIRED
	status		(inherited|meta) #IMPLIED
>

Index: MgaDumper.cpp
===================================================================
RCS file: /var/lib/gme/GMESRC/GME/Parser/MgaDumper.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** MgaDumper.cpp	19 Jul 2004 07:01:00 -0000	1.18
--- MgaDumper.cpp	27 Sep 2004 21:33:01 -0000	1.19
***************
*** 138,144 ****
  {
  	CHECK_IN(p);
  	m_dumpLibraryStubs = false; // make sure closure logic does not involve in it
  
- 
  	COMTRY
  	{
--- 138,146 ----
  {
  	CHECK_IN(p);
+ 	m_closureDump = false;
+ 	m_strictDump = false;
+ 	m_dumpRelids = true;
  	m_dumpLibraryStubs = false; // make sure closure logic does not involve in it
  
  	COMTRY
  	{
***************
*** 156,164 ****
  STDMETHODIMP CMgaDumper::DumpFCOs(IMgaFCOs *p, IMgaFolders *f, BSTR xmlfile)
  {
  	m_strictDump = false; // this method uses the permissive dump
  	// meaning that if a model/folder is in the closure then all children
  	// and grandchildren are dumped as well
  
! 	dumpversion = 2; // no relids dumped
  	m_dumpLibraryStubs = false; // make sure closure logic does not involve in it
  
--- 158,167 ----
  STDMETHODIMP CMgaDumper::DumpFCOs(IMgaFCOs *p, IMgaFolders *f, BSTR xmlfile)
  {
+ 	m_closureDump = false;
  	m_strictDump = false; // this method uses the permissive dump
  	// meaning that if a model/folder is in the closure then all children
  	// and grandchildren are dumped as well
  
! 	m_dumpRelids = false; //dumpversion = 2; // no relids dumped
  	m_dumpLibraryStubs = false; // make sure closure logic does not involve in it
  
***************
*** 186,189 ****
--- 189,193 ----
  		ofs << "<!DOCTYPE clipboard SYSTEM \"mga.dtd\" [\n";
  		ofs << "\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection)*>\n";
+ 		ofs << "\t<!ATTLIST clipboard acceptingkind CDATA	#IMPLIED>\n";
  		ofs << "]>\n\n";
  
***************
*** 489,494 ****
  
  	Attr("id", folder, IMgaFolder::get_ID);
  	if(dumpversion >= 1) {
! 		if ( dumpversion != 2)
  		{
  			LAttr("relid", folder, IMgaFolder::get_RelID);
--- 493,528 ----
  
  	Attr("id", folder, IMgaFolder::get_ID);
+ 
+ 	if( m_closureDump && m_v2)
+ 	{
+ 		// "closurename"
+ 		CComBSTR path;
+ 		COMTHROW( folder->get_AbsPath( &path));
+ 		string rel_path, abs_path;
+ 		CopyTo( path, abs_path);
+ 		rel_path = abs_path;
+ 
+ 		if( rel_path.substr(0, m_curTopPath.length()) == m_curTopPath)
+ 			rel_path = rel_path.substr( m_curTopPath.length());
+ 		else
+ 			ASSERT(0);
+ 
+ 		Attr( "closurename", rel_path);
+ 
+ 		// "closurepath"
+ 		string place2path = abs_path.substr( m_currParAbsPath.length());
+ 		int pp = place2path.length() - 1; 
+ 		while( pp >= 0 && place2path[pp] != '/') --pp;
+ 		
+ 		if( pp == -1 || pp == 0)
+ 			place2path = "";
+ 		else
+ 			place2path = place2path.substr(0, pp);
+ 
+ 		Attr( "closurepath", place2path);
+ 	}
+ 
  	if(dumpversion >= 1) {
! 		if( m_dumpRelids)
  		{
  			LAttr("relid", folder, IMgaFolder::get_RelID);
***************
*** 501,505 ****
  	}
  
- 
  	CComObjPtr<IMgaMetaFolder> metafolder;
  	COMTHROW( folder->get_MetaFolder(PutOut(metafolder)) );
--- 535,538 ----
***************
*** 511,514 ****
--- 544,548 ----
  
  	DumpConstraints(folder);
+ 
  	Dump(folder, IMgaFolder::get_ChildFolders);
  
***************
*** 658,661 ****
--- 692,725 ----
  			Attr("role", role, IMgaMetaRole::get_Name);
  
+ 		if( m_closureDump && m_v2)
+ 		{
+ 			// "closurename"
+ 			CComBSTR path;
+ 			COMTHROW( fco->get_AbsPath( &path));
+ 			string rel_path, abs_path;
+ 			CopyTo( path, abs_path);
+ 			rel_path = abs_path;
+ 
+ 			if( rel_path.substr(0, m_curTopPath.length()) == m_curTopPath)
+ 				rel_path = rel_path.substr( m_curTopPath.length());
+ 			else
+ 				ASSERT(0);
+ 
+ 			Attr( "closurename", rel_path);//put the attr out only for non initial objects
+ 
+ 			// "closurepath"
+ 			if( m_currParAbsPath.length() > 0)
+ 			{
+ 				string place2path = abs_path.substr( m_currParAbsPath.length());
+ 				int pp = place2path.length() - 1; 
+ 				while( pp >= 0 && place2path[pp] != '/') --pp;
+ 				if( pp == -1 || pp == 0)
+ 					place2path = "";
+ 				else
+ 					place2path = place2path.substr(0, pp);
+ 				Attr( "closurepath", place2path);
+ 			}
+ 		}
+ 
  		VARIANT_BOOL prim = VARIANT_TRUE;
  		bool lost_basetype = false;
***************
*** 675,702 ****
  				Attr("isprimary", prim != VARIANT_FALSE ? "yes" : "no");
  			}
! 			// logic added by ZolMol
! 			else if ( m_dumpLibraryStubs && !isInLibrary( fco) && isInLibrary( derivedfrom)) { //derived from a type defined in a library
! 				CComBSTR name;
! 				COMTHROW( derivedfrom->get_AbsPath( &name));
! 				string nm;
! 				CopyTo( name, nm);
! 				
! 				Attr("closurelibderivedfrom", nm);
  
! 				VARIANT_BOOL b;
  
! 				COMTHROW( fco->get_IsInstance(&b) );
! 				Attr("isinstance", b != VARIANT_FALSE ? "yes" : "no");
  
! 				COMTHROW( fco->get_IsPrimaryDerived(&prim) );
! 				Attr("isprimary", prim != VARIANT_FALSE ? "yes" : "no");
! 			}
! 			else {
! 				lost_basetype = true;
  			}
  		}
! 		if(prim && (dumpversion >= 1) && (!lost_basetype)) 
! 			if ( dumpversion != 2)
! 				LAttr("relid", fco, IMgaFCO::get_RelID);
  	}
  
--- 739,790 ----
  				Attr("isprimary", prim != VARIANT_FALSE ? "yes" : "no");
  			}
! 			else {
! 				lost_basetype = true;
! 			}
  
! 			if( m_closureDump && !CheckInClosure(derivedfrom))//!CIN() introduced fresly //<!>
! 			{
! 				if ( m_dumpLibraryStubs && !CheckInClosure(derivedfrom) && !isInLibrary( fco) && isInLibrary( derivedfrom)) { //derived from a type defined in a library
! 					CComBSTR name;
! 					COMTHROW( derivedfrom->get_AbsPath( &name));
! 					string nm;
! 					CopyTo( name, nm);
! 					
! 					Attr("closurelibderivedfrom", nm);
  
! 					VARIANT_BOOL b;
  
! 					COMTHROW( fco->get_IsInstance(&b) );
! 					Attr("isinstance", b != VARIANT_FALSE ? "yes" : "no");
! 
! 					COMTHROW( fco->get_IsPrimaryDerived(&prim) );
! 					Attr("isprimary", prim != VARIANT_FALSE ? "yes" : "no");
! 				}
! 				else if( m_v2)
! 				{
! 					CComBSTR name;
! 
! 					COMTHROW( derivedfrom->get_AbsPath( &name));
! 					string nm;
! 					CopyTo( name, nm);
! 					
! 					COMTHROW( fco->get_AbsPath( &name));
! 					string nm2;
! 					CopyTo( name, nm2);
! 
! 					Attr("closure2derivedfrom", makeRel( nm, nm2));
! 
! 					VARIANT_BOOL b;
! 
! 					COMTHROW( fco->get_IsInstance(&b) );
! 					Attr("isinstance", b != VARIANT_FALSE ? "yes" : "no");
! 
! 					COMTHROW( fco->get_IsPrimaryDerived(&prim) );
! 					Attr("isprimary", prim != VARIANT_FALSE ? "yes" : "no");
! 				}
  			}
  		}
! 		if(prim && (dumpversion >= 1) && (!lost_basetype) && m_dumpRelids)
! 			LAttr("relid", fco, IMgaFCO::get_RelID);
  	}
  
***************
*** 738,747 ****
  
  	DumpFCO(model, true, false, false);	
! 	if(dumpversion >= 1 && dumpversion != 2) LAttr("childrelidcntr", model, IMgaModel::get_ChildRelIDCounter);
  	DumpFCO(model, false, true, true);	
  
  	Dump(model, IMgaModel::get_ChildFCOs);
  
- 
  	EndElem();
  }
--- 826,834 ----
  
  	DumpFCO(model, true, false, false);	
! 	if(dumpversion >= 1 && m_dumpRelids) LAttr("childrelidcntr", model, IMgaModel::get_ChildRelIDCounter);
  	DumpFCO(model, false, true, true);	
  
  	Dump(model, IMgaModel::get_ChildFCOs);
  
  	EndElem();
  }
***************
*** 909,921 ****
  		if( CheckInClosure( fco)) // regular dump or the fco is really in the closure
  			Attr("referred", fco, IMgaFCO::get_ID);
! 		// logic added by ZolMol
! 		else if ( m_dumpLibraryStubs && !isInLibrary( reference) && isInLibrary( fco)) //reference pointing out to a library
  		{
! 			CComBSTR name;
! 			COMTHROW( fco->get_AbsPath( &name));
! 			string nm;
! 			CopyTo( name, nm);
! 			
! 			Attr("closurelibreferred", nm);
  		}
  	}
--- 996,1027 ----
  		if( CheckInClosure( fco)) // regular dump or the fco is really in the closure
  			Attr("referred", fco, IMgaFCO::get_ID);
! 		
! 		if( m_closureDump)
  		{
! 			if ( m_dumpLibraryStubs && !CheckInClosure( fco) && !isInLibrary( reference) && isInLibrary( fco)) //reference pointing out to a library
! 			{
! 				CComBSTR name;
! 				COMTHROW( fco->get_AbsPath( &name));
! 				string nm;
! 				CopyTo( name, nm);
! 				
! 				Attr("closurelibreferred", nm);
! 			}
! 
! 			// dump the relativepath of the referred object if v2
! 			else if( m_v2) // "else" introd freshly, not to dump to paths, the parser will check first for closurelibreferred
! 			{
! 				CComBSTR name;
! 				COMTHROW( fco->get_AbsPath( &name));
! 				string nm;
! 				CopyTo( name, nm);
! 
! 				COMTHROW( reference->get_AbsPath( &name));
! 				string nm2;
! 				CopyTo( name, nm2);
! 
! 				
! 				Attr("closure2referred", makeRel( nm, nm2));
! 			}
  		}
  	}
***************
*** 986,989 ****
--- 1092,1103 ----
  		CComObjPtrVector<IMgaFCO> members;
  		COMTHROW( set->get_Members(PutOut(members)) );
+ 		
+ 		if( m_closureDump)
+ 		{
+ 			CComBSTR name;
+ 			COMTHROW( set->get_AbsPath( &name));
+ 			CopyTo( name, m_currAbsPath);
+ 		}
+ 
  		DumpIDRefs("members", members);
  	}
***************
*** 1022,1041 ****
  	}
  
! 	// m_dumpLibraryStubs is true, so the connection to a library element will be dumped with "closurelibtarget" attribute and a dummy! "target" attribute
! 	if ( m_dumpLibraryStubs && !isInLibrary( conn) && isInLibrary( target))
  	{
  		CComBSTR name;
! 		COMTHROW( target->get_AbsPath( &name));
! 		string nm;
! 		CopyTo( name, nm);
! 		
! 		Attr("closurelibtarget", nm);
! 		Attr("target", conn, IMgaFCO::get_ID); // this is required, dump a dummy!! value, since the ID is checked and if not found inside the <clipboard/> section the parser will complain about it
  	}
! 	else
! 		Attr("target", target, IMgaFCO::get_ID);
  
  	CComObjPtrVector<IMgaFCO> refs;
  	COMTHROW( connpoint->get_References(PutOut(refs)) );
  	DumpIDRefs("refs", refs);
  
--- 1136,1172 ----
  	}
  
! 	Attr("target", target, IMgaFCO::get_ID);
! 
! 	if( m_closureDump)
  	{
  		CComBSTR name;
! 		COMTHROW( conn->get_AbsPath( &name));
! 		CopyTo( name, m_currAbsPath);
! 
! 		// m_dumpLibraryStubs is true, so the connection to a library element will be dumped with "closurelibtarget" attribute and a dummy! "target" attribute
! 		if ( m_dumpLibraryStubs && !isInLibrary( conn) && isInLibrary( target))
! 		{
! 			CComBSTR name;
! 			COMTHROW( target->get_AbsPath( &name));
! 			string nm;
! 			CopyTo( name, nm);
! 			
! 			Attr("closurelibtarget", nm);
! 		}
! 		else if( m_v2) // closure v2
! 		{
! 			CComBSTR name;
! 			COMTHROW( target->get_AbsPath( &name));
! 			string nm;
! 			CopyTo( name, nm);
! 
! 			Attr("closure2target", makeRel( nm, m_currAbsPath));
! 		} 
  	}
! 
  
  	CComObjPtrVector<IMgaFCO> refs;
  	COMTHROW( connpoint->get_References(PutOut(refs)) );
+ 	// m_currAbsPath is set above, at the "closure2target" dump
  	DumpIDRefs("refs", refs);
  
***************
*** 1047,1051 ****
  	if( !fcos.empty() )
  	{
! 		string idrefs;
  
  		CComObjPtrVector<IMgaFCO>::iterator i = fcos.begin();
--- 1178,1182 ----
  	if( !fcos.empty() )
  	{
! 		string idrefs, clos_idrefs;
  
  		CComObjPtrVector<IMgaFCO>::iterator i = fcos.begin();
***************
*** 1053,1056 ****
--- 1184,1200 ----
  		while( i != e )
  		{
+ 			if( m_closureDump)
+ 			{
+ 				CComBSTR name;
+ 				COMTHROW( (*i)->get_AbsPath( &name));
+ 				string nm;
+ 				CopyTo( name, nm);
+ 
+ 				if( !clos_idrefs.empty() )
+ 					clos_idrefs += ' ';
+ 
+ 				clos_idrefs += makeRel( nm, m_currAbsPath);
+ 			}
+ 
  			if (!CheckInClosure(*i)) {
  				++i; // inserted by ZolMol
***************
*** 1073,1076 ****
--- 1217,1226 ----
  		if ( !idrefs.empty())
  			Attr(name, idrefs);
+ 
+ 		if( m_closureDump && m_v2 && !clos_idrefs.empty()) // closure v2
+ 		{
+ 			string clos_name("closure2"); clos_name += name;
+ 			Attr( clos_name.c_str(), clos_idrefs);
+ 		}
  	}
  }
***************
*** 1375,1382 ****
  STDMETHODIMP CMgaDumper::DumpClos( IMgaFCOs *p_sel_fcos, IMgaFolders *p_sel_folds,  BSTR xmlfile, int dump_options)
  {
  	m_strictDump = true; // strict dump meaning that all dumped objects must be strictly in the closure
! 	dumpversion = 2; // no relids dumped
! 	m_dumpLibraryStubs = (dump_options & 0x1) == 0x1; // dump library stubs ( absolute path used as libreferred or libderivedfrom attribute)
  
  	COMTRY
  	{
--- 1525,1536 ----
  STDMETHODIMP CMgaDumper::DumpClos( IMgaFCOs *p_sel_fcos, IMgaFolders *p_sel_folds,  BSTR xmlfile, int dump_options)
  {
+ 	m_closureDump = true;
  	m_strictDump = true; // strict dump meaning that all dumped objects must be strictly in the closure
! 	
! 	m_dumpRelids = false; // dumpversion = 2; // no relids dumped
  
+ 	m_dumpLibraryStubs =	(dump_options & 0x1) == 0x1; // dump library stubs ( absolute path used as libreferred or libderivedfrom attribute)
+ 	m_v2 =					(dump_options & 0x2) == 0x2;
+ 	
  	COMTRY
  	{
***************
*** 1404,1412 ****
  		if ( false) // clipboard format
  		{
! 			ofs << "<!DOCTYPE clipboard SYSTEM \"mga.dtd\" [\n";
! 			ofs << "\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection)*>\n";
  			ofs << "]>\n\n";
  
  			StartElem("clipboard");
  			Dump( project); 
  			EndElem();
--- 1558,1571 ----
  		if ( false) // clipboard format
  		{
! 			ofs << "<!DOCTYPE clipboard SYSTEM \"mgaclosure.dtd\" [\n";
! 			ofs << "\t<!ELEMENT clipboard (project|folder|model|atom|reference|set|connection)*>\n";//<!> project introd
! 			ofs << "\t<!ATTLIST clipboard\n";
! 			ofs << "\t\tclosureversion CDATA #IMPLIED\n";
! 			ofs << "\t\tacceptingkind CDATA #IMPLIED\n";
! 			ofs << "\t>\n";
  			ofs << "]>\n\n";
  
  			StartElem("clipboard");
+ 			Attr("closureversion", "1");
  			Dump( project); 
  			EndElem();
***************
*** 1414,1418 ****
  		else
  		{
! 			ofs << "<!DOCTYPE project SYSTEM \"mga.dtd\">\n\n";
  
  			Dump( project); 
--- 1573,1577 ----
  		else
  		{
! 			ofs << "<!DOCTYPE project SYSTEM \"mgaclosure.dtd\">\n\n";//<!> mga.dtd ?
  
  			Dump( project); 
***************
*** 1428,1436 ****
  STDMETHODIMP CMgaDumper::DumpClosR(
  			IMgaFCOs *p_sel_fcos, IMgaFolders *p_sel_folds, BSTR xmlfile, 
! 			IMgaFCOs *p_top_fcos, IMgaFolders *p_top_folds, int dump_options)
  {
  	m_strictDump = true; // strict dump meaning that all dumped objects must be strictly in the closure
! 	dumpversion = 2; // no relids dumped
! 	m_dumpLibraryStubs = (dump_options & 0x1) == 0x1; // dump library stubs ( absolute path used as closurelibreferred, closurelibderivedfrom, closurelibtarget attribute)
  
  	COMTRY
--- 1587,1606 ----
  STDMETHODIMP CMgaDumper::DumpClosR(
  			IMgaFCOs *p_sel_fcos, IMgaFolders *p_sel_folds, BSTR xmlfile, 
! 			IMgaFCOs *p_top_fcos, IMgaFolders *p_top_folds, int dump_options, BSTR abspath, BSTR acceptingkinds)
  {
+ 	m_closureDump = true;
  	m_strictDump = true; // strict dump meaning that all dumped objects must be strictly in the closure
! 	m_dumpRelids = false; //dumpversion = 2; // no relids dumped
! 
! 	m_dumpLibraryStubs	= (dump_options & 0x1) == 0x1; // dump library stubs ( absolute path used as closurelibreferred, closurelibderivedfrom, closurelibtarget attribute)
! 	m_v2				= (dump_options & 0x2) == 0x2; // dump the closure2members, closure2refs like attributes
! 
! 	string version_string;
! 	if( dump_options & 0x4)
! 		version_string = "4";
! 	else
! 		version_string = "1";
! 	
! 	CopyTo( abspath, m_currParAbsPath);
  
  	COMTRY
***************
*** 1451,1455 ****
  			return S_OK;
  
- 
  		CComObjPtrVector<IMgaFCO>	parentless_fcos; // parentless fcos from the selected set
  		CComObjPtrVector<IMgaFolder> parentless_folders; // parentless folders from the selected set
--- 1621,1624 ----
***************
*** 1475,1489 ****
  		putInTerritory( parentless_folders);
  
! 		ofs << "<!DOCTYPE clipboard SYSTEM \"mga.dtd\" [\n";
  		ofs << "\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection)*>\n";
  		ofs << "]>\n\n";
  
  		StartElem("clipboard");
  
  		for( CComObjPtrVector<IMgaFolder>::iterator j = parentless_folders.begin(); j != parentless_folders.end(); ++j )
! 			Dump( *j); 
  
  		for( CComObjPtrVector<IMgaFCO>::iterator i = parentless_fcos.begin() ; i != parentless_fcos.end(); ++i )
  			Dump( *i); 
  		
  		EndElem();
--- 1644,1697 ----
  		putInTerritory( parentless_folders);
  
! 		ofs << "<!DOCTYPE clipboard SYSTEM \"mgaclosure.dtd\" [\n";
  		ofs << "\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection)*>\n";
+ 		ofs << "\t<!ATTLIST clipboard\n";
+ 		ofs << "\t\tclosureversion CDATA #IMPLIED\n";
+ 		ofs << "\t\tacceptingkind CDATA #IMPLIED\n";
+ 		ofs << "\t>\n";
  		ofs << "]>\n\n";
  
  		StartElem("clipboard");
+ 		Attr("closureversion", version_string);
+ 		Attr("acceptingkind", CComBstrObj( acceptingkinds));
  
  		for( CComObjPtrVector<IMgaFolder>::iterator j = parentless_folders.begin(); j != parentless_folders.end(); ++j )
! 		{
! 			CComBSTR path;
! 
! 			CComObjPtr<IMgaFolder> parent;
! 			COMTHROW( (*j)->get_ParentFolder( PutOut( parent)));
! 			if ( parent) // it has a folder parent
! 				COMTHROW( parent->get_AbsPath( &path));
! 			// else: a parentless_folder is the rootfolder, so the path = "";
! 			
! 			CopyTo( path, m_curTopPath);// m_curTopPath will be used to dump the relative path in "closurename" attr
! 
! 			Dump( *j);
! 		}
  
  		for( CComObjPtrVector<IMgaFCO>::iterator i = parentless_fcos.begin() ; i != parentless_fcos.end(); ++i )
+ 		{
+ 			CComBSTR path;
+ 
+ 			CComObjPtr<IMgaModel> parent;
+ 			COMTHROW( (*i)->get_ParentModel( PutOut( parent)));
+ 			if ( parent) // it has a model parent
+ 				COMTHROW( parent->get_AbsPath( &path));
+ 			else // it may be contained by a folder
+ 			{
+ 				CComObjPtr<IMgaFolder> parent;
+ 				COMTHROW( (*i)->get_ParentFolder( PutOut( parent)));
+ 				if ( parent) // it has a folder parent
+ 					COMTHROW( parent->get_AbsPath( &path));
+ 				else // what the heck! (a parentless fco cannot be the rootfolder)
+ 					ASSERT(0);
+ 			}
+ 
+ 
+ 			CopyTo( path, m_curTopPath);// m_curTopPath will be used to dump the relative path in "closurename" attr
+ 
  			Dump( *i); 
+ 		}
  		
  		EndElem();
***************
*** 1496,1497 ****
--- 1704,1706 ----
  	m_selFolders.clear();
  }
+ 

Index: MgaDumper.h
===================================================================
RCS file: /var/lib/gme/GMESRC/GME/Parser/MgaDumper.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** MgaDumper.h	6 Jul 2004 16:10:05 -0000	1.11
--- MgaDumper.h	27 Sep 2004 21:33:01 -0000	1.12
***************
*** 7,10 ****
--- 7,11 ----
  #include "CommonVersionInfo.h"
  #include "Transcoder.h"
+ #include "helper.h"
  
  class GmeEqual
***************
*** 40,44 ****
  {
  public:
! 	CMgaDumper() : dumpversion( 1), m_strictDump( true), m_dumpLibraryStubs(false) { }
  
  DECLARE_REGISTRY_RESOURCEID(IDR_MGADUMPER)
--- 41,51 ----
  {
  public:
! 	CMgaDumper()
! 		: dumpversion( 1)
! 		, m_closureDump( false)
! 		, m_strictDump( true)
! 		, m_dumpRelids( true)
! 		, m_dumpLibraryStubs(false) 
! 	{ }
  
  DECLARE_REGISTRY_RESOURCEID(IDR_MGADUMPER)
***************
*** 61,65 ****
  	STDMETHOD(DumpFCOs)(IMgaFCOs *p, IMgaFolders *f, BSTR xmlfile);
  	STDMETHOD(DumpClos)( IMgaFCOs *sel_fco, IMgaFolders *sel_fold, BSTR xmlfile, int lib_stub);
! 	STDMETHOD(DumpClosR)( IMgaFCOs *sel_fco, IMgaFolders *sel_fold, BSTR xmlfile, IMgaFCOs *root_fco, IMgaFolders *root_fold, int lib_stub);
  	STDMETHOD(put_FormatVersion)(long p) { dumpversion = p; return S_OK; }
  
--- 68,72 ----
  	STDMETHOD(DumpFCOs)(IMgaFCOs *p, IMgaFolders *f, BSTR xmlfile);
  	STDMETHOD(DumpClos)( IMgaFCOs *sel_fco, IMgaFolders *sel_fold, BSTR xmlfile, int lib_stub);
! 	STDMETHOD(DumpClosR)( IMgaFCOs *sel_fco, IMgaFolders *sel_fold, BSTR xmlfile, IMgaFCOs *top_fco, IMgaFolders *top_fold, int options, BSTR abspath, BSTR acceptingkinds);
  	STDMETHOD(put_FormatVersion)(long p) { dumpversion = p; return S_OK; }
  
***************
*** 215,220 ****
--- 222,230 ----
  	int dumpversion;// >=1 means new xme format, ==2 means do not dump relids
  
+ 	bool m_closureDump;
+ 	bool m_dumpRelids;
  	bool m_strictDump; // if true then containers dump their children only if the child is present in the closure collection
  	bool m_dumpLibraryStubs; // if true the libreferred attribute is dumped
+ 
  	inline bool isInLibrary( IMgaObject * obj)
  	{
***************
*** 233,236 ****
--- 243,252 ----
  	void putInTerritory( CComObjPtrVector<IMgaFCO>&);
  	void putInTerritory( CComObjPtrVector<IMgaFolder>&);
+ 
+ 	string m_curTopPath; // used for the 'closurename' calc
+ 	string m_currAbsPath;
+ 	string m_currParAbsPath; // used for 'closurepath' calc
+ 	bool m_v2;
+ 
  };
  

Index: MgaParser.cpp
===================================================================
RCS file: /var/lib/gme/GMESRC/GME/Parser/MgaParser.cpp,v
retrieving revision 1.24
retrieving revision 1.25
diff -C2 -d -r1.24 -r1.25
*** MgaParser.cpp	23 Jul 2004 13:19:18 -0000	1.24
--- MgaParser.cpp	27 Sep 2004 21:33:01 -0000	1.25
***************
*** 47,50 ****
--- 47,51 ----
  		CopyTo(filename, xmlfile);
  
+ 		m_resolveDerFuncPtr = CMgaParser::ResolveDerivation; // zolmol
  		try
  		{
***************
*** 95,99 ****
  			ranges.clear();
  		}
! 	    catch(const XMLException &e)
  		{
  			XmlStr desc(e.getMessage());
--- 96,100 ----
  			ranges.clear();
  		}
! 		catch(const XMLException &e)
  		{
  			XmlStr desc(e.getMessage());
***************
*** 161,164 ****
--- 162,166 ----
  		CopyTo(filename, xmlfile);
  
+ 		m_resolveDerFuncPtr = CMgaParser::ResolveDerivation; // zolmol
  		try
  		{
***************
*** 564,567 ****
--- 566,570 ----
  	ASSERT( GetPrevName() == "start" );
  	ASSERT( GetPrevious().object != NULL );
+ 	if( !GetPrevious().object) HR_THROW(E_XMLPARSER);//by ZolMol
  
  	const CComObjPtr<IUnknown> &obj = GetPrevious().object;
***************
*** 808,836 ****
  	if( s == NULL )
  	{
! 		s = GetByNameX(attributes, "closurelibderivedfrom");
! 		if( s == NULL)
! 		{
! 			deriv.from.Release();
! 			return;
! 		}
! 
! 		CComObjPtr<IMgaObject> obj;
! 		COMTHROW( project->get_ObjectByPath( PutInBstr( *s), PutOut( obj)) );
! 		if ( obj)
! 			COMTHROW( obj.QueryInterface( deriv.from));
! 
! 		if ( deriv.from == NULL) // do not throw exception in case of closurelibderivedfrom
! 		{
! 			deriv.from.Release();
! 			return;
! 		}
  	}
- 	else
- 	{
- 		LookupByID(*s, deriv.from);
  
! 		if( deriv.from == NULL )
! 			throw pass_exception();
! 	}
  
  	s = GetByNameX(attributes, "isinstance");
--- 811,821 ----
  	if( s == NULL )
  	{
! 		deriv.from.Release();
! 		return;
  	}
  
! 	LookupByID(*s, deriv.from);
! 	if( deriv.from == NULL )
! 		throw pass_exception();
  
  	s = GetByNameX(attributes, "isinstance");
***************
*** 846,850 ****
  
  	deriv_type deriv;
! 	ResolveDerivation(attributes, deriv);
  
  	if( GetPrevName() == "folder" )
--- 831,837 ----
  
  	deriv_type deriv;
! 	//ResolveDerivation(attributes, deriv);
! 	(*this.*m_resolveDerFuncPtr)(attributes, deriv);
! 
  
  	if( GetPrevName() == "folder" )
***************
*** 920,924 ****
  
  	deriv_type deriv;
! 	ResolveDerivation(attributes, deriv);
  
  	if( GetPrevName() == "folder" )
--- 907,913 ----
  
  	deriv_type deriv;
! 	//ResolveDerivation(attributes, deriv);
! 	(*this.*m_resolveDerFuncPtr)(attributes, deriv);
! 
  
  	if( GetPrevName() == "folder" )
***************
*** 1068,1072 ****
  
  	deriv_type deriv;
! 	ResolveDerivation(attributes, deriv);
  
  	if( GetPrevName() == "folder" )
--- 1057,1062 ----
  
  	deriv_type deriv;
! 	//ResolveDerivation(attributes, deriv);
! 	(*this.*m_resolveDerFuncPtr)(attributes, deriv);
  
  	if( GetPrevName() == "folder" )
***************
*** 1143,1167 ****
  
  	CComObjPtr<IMgaFCO> target;
! 
! 	//LookupByID(GetByName(attributes, "target"), target);
! 	const string *libtg = GetByNameX(attributes, "closurelibtarget");
! 	if ( libtg != NULL)
! 	{
! 		CComObjPtr<IMgaObject> obj;
! 		COMTHROW( project->get_ObjectByPath( PutInBstr( *libtg), PutOut( obj)) );
! 		if ( obj)
! 			COMTHROW( obj.QueryInterface( target));
! 	}
! 
! 	const string *tg = GetByNameX(attributes, "target");
! 	if( tg != NULL && libtg == NULL) // valid info in target iff no closurelibtarget token
! 	{
! 		LookupByID( *tg, target);
! 	}
! 
! 	// throw even if closurelibtarget present but not found the needed object
! 	if ( target == NULL)
  		throw pass_exception();
  
  	CComObjPtr<IMgaFCOs> coll;
  	COMTHROW(coll.CoCreateInstance(L"Mga.MgaFCOs"));
--- 1133,1141 ----
  
  	CComObjPtr<IMgaFCO> target;
! 	LookupByID(GetByName(attributes, "target"), target);
! 	if( target == NULL )
  		throw pass_exception();
  
+ 
  	CComObjPtr<IMgaFCOs> coll;
  	COMTHROW(coll.CoCreateInstance(L"Mga.MgaFCOs"));
***************
*** 1224,1228 ****
  
  	deriv_type deriv;
! 	ResolveDerivation(attributes, deriv);
  
  	CComObjPtr<IMgaFCO> referred;
--- 1198,1203 ----
  
  	deriv_type deriv;
! 	//ResolveDerivation(attributes, deriv);
! 	(*this.*m_resolveDerFuncPtr)(attributes, deriv);
  
  	CComObjPtr<IMgaFCO> referred;
***************
*** 1236,1250 ****
  			throw pass_exception();
  	}
- 	else // by ZolMol
- 	{
- 		s = GetByNameX(attributes, "closurelibreferred");
- 		if( s != NULL)
- 		{
- 			CComObjPtr<IMgaObject> obj;
- 			COMTHROW( project->get_ObjectByPath( PutInBstr( *s), PutOut( obj)) );
- 			if ( obj)
- 				COMTHROW( obj.QueryInterface( referred));
- 		}
- 	}
  
  	if( GetPrevName() == "folder" )
--- 1211,1214 ----
***************
*** 1324,1328 ****
  
  	deriv_type deriv;
! 	ResolveDerivation(attributes, deriv);
  
  	slist< CComObjPtr<IMgaFCO> > members;
--- 1288,1293 ----
  
  	deriv_type deriv;
! 	//ResolveDerivation(attributes, deriv);
! 	(*this.*m_resolveDerFuncPtr)(attributes, deriv);
  
  	slist< CComObjPtr<IMgaFCO> > members;
***************
*** 1502,1503 ****
--- 1467,1618 ----
  }
  
+ CMgaParser::elementfunc CMgaParser::elementfuncs_clipmgainfo[] = 
+ {
+ 	elementfunc("clipboard", StartClipboardInfo, EndNone),
+ 	elementfunc("", NULL, NULL)
+ };
+ 
+ void CMgaParser::StartClipboardInfo(const attributes_type &attributes)
+ {
+ 	bool closure_version_found = false;
+ 	*closversion = 0;
+ 	*closacckind = 0;
+ 	attributes_iterator i = attributes.begin();
+ 	attributes_iterator e = attributes.end();
+ 	while( i != e )
+ 	{
+ 		if( i->first == "closureversion" )
+ 		{
+ 			closure_version_found = true;
+ 			CComBstrObj bstr;
+ 			CopyTo(i->second, bstr); // if the value is "" then the bstr will be null, so bool introduced to correctly check the presence of "closureversion" token
+ 
+ 			*closversion = bstr.Detach();
+ 		}
+ 		else if( i->first == "acceptingkind" )
+ 		{
+ 			CComBstrObj bstr;
+ 			CopyTo(i->second, bstr);
+ 
+ 			*closacckind = bstr.Detach();
+ 		}
+ 		++i;
+ 	}
+ 	if( !closure_version_found && *closversion == 0) // not found such token
+ 	{
+ 		CComBSTR bstr("0");
+ 		*closversion = bstr.Detach();
+ 	}
+ }
+ 
+ STDMETHODIMP CMgaParser::GetClipXMLInfo(BSTR filename, IMgaObject *target, VARIANT_BOOL *is_acceptable, BSTR* p_acckind, BSTR* p_version) 
+ {
+ 	try
+ 	{
+ 		CloseAll();
+ 		COMTHROW( progress.CoCreateInstance(L"Mga.MgaProgressDlg") );
+ 		COMTHROW( progress->SetTitle(PutInBstr("Analyzing clipboard data...")) );
+ 		COMTHROW( progress->StartProgressDialog(NULL) );
+ 
+ 
+ 		CopyTo(filename, xmlfile);
+ 
+ 		try
+ 		{
+ 			XMLPlatformUtils::Initialize();
+ 
+ 			SAXParser parser;
+ 			parser.setDoValidation(false);
+ 			parser.setDocumentHandler(this);
+ 			parser.setErrorHandler(this);
+ 			parser.setEntityResolver(this);
+ 
+ 			elementfuncs = elementfuncs_clipmgainfo;
+ 
+ 			pass_count = 1;
+ 
+ 			ranges.clear();
+ 			ranges.push_front();
+ 			ranges.front().begin = 1;
+ 			ranges.front().end = (counter_type)-1;
+ 			skip_element_level = 0;
+ 
+ 			closversion = p_version; // the result stored in these returning parameters p_...
+ 			closacckind = p_acckind;
+ 
+ 			parser.parse(xmlfile.c_str());
+ 
+ 		}
+ 	    catch(const XMLException &e)
+ 		{
+ 			XmlStr desc(e.getMessage());
+ 
+ 			ThrowXmlError(desc.c_str());
+ 		}
+ 
+ 		CloseAll();
+ 	}
+ 	catch(hresult_exception &e)
+ 	{
+ 		CloseAll();
+ 
+ 		ASSERT( FAILED(e.hr) );
+ 		if( e.hr == E_XMLPARSER )
+ 			SetErrorInfo(errorinfo);
+ 		else
+ 			SetErrorInfo2(e.hr);
+ 
+ 		return e.hr;
+ 	}
+ 
+ #if(0)
+ 	/*
+ 	//- orroekprofkpeok
+ 	CComObjPtr<IMgaObject> target_obj = target;
+ 	CComObjPtr<IMgaProject> p;
+ 	COMTHROW( target_obj->get_Project(PutOut(p)) );
+ 	ASSERT( p != NULL );
+ 	COMTHROW( p->CreateTerritory(NULL, PutOut(territory), NULL) );
+ 	COMTHROW( p->BeginTransaction(territory, TRANSACTION_NON_NESTED) );
+ 
+ 	CComObjPtr<IMgaObject> target_in_terr;
+ 	COMTHROW(territory->OpenObj(target_obj, PutOut(target_in_terr)));
+ 
+ 	CComObjPtr<IMgaModel> model;
+ 	CComObjPtr<IMgaFolder> folder;
+ 
+ 	target_in_terr.QueryInterface(model);
+ 	target_in_terr.QueryInterface(folder);
+ 
+ 
+ 	CComBstrObj kind_name;
+ 	if( model)
+ 	{
+ 		CComObjPtr<IMgaMetaFCO> k_meta;
+ 		COMTHROW( model->get_Meta( PutOut( k_meta)));
+ 		COMTHROW( k_meta->get_Name( PutOut(kind_name)) );
+ 	}
+ 	else if( folder)
+ 	{
+ 		CComObjPtr<IMgaMetaFolder> f_meta;
+ 		COMTHROW( folder->get_MetaFolder( PutOut( f_meta)));
+ 		COMTHROW( f_meta->get_Name( PutOut(kind_name)) );
+ 	}
+ 	COMTHROW( p->CommitTransaction() );
+ 	project = NULL;
+ 		
+ 	// check if the accepting kind exists among the accepting kinds
+ 	string kind_nm, acc_kinds;
+ 	CopyTo( kind_name, kind_nm);
+ 
+ 	CComBstrObj acckinds = *closacckind;
+ 	CopyTo( acckinds, acc_kinds);
+ 
+ 	*is_acceptable = VARIANT_FALSE;
+ 	if( findExact( acc_kinds, kind_nm))
+ 		*is_acceptable = VARIANT_TRUE;
+ */
+ //-
+ #endif
+ 	return S_OK;
+ }

Index: MgaParser.h
===================================================================
RCS file: /var/lib/gme/GMESRC/GME/Parser/MgaParser.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** MgaParser.h	19 Jul 2004 08:42:19 -0000	1.9
--- MgaParser.h	27 Sep 2004 21:33:01 -0000	1.10
***************
*** 11,15 ****
  #include <hash_map>
  #include <list>
! 
  // --------------------------- CMgaParser
  
--- 11,15 ----
  #include <hash_map>
  #include <list>
! #include <vector>
  // --------------------------- CMgaParser
  
***************
*** 23,27 ****
  {
  public:
! 	CMgaParser() { }
  
  DECLARE_REGISTRY_RESOURCEID(IDR_MGAPARSER)
--- 23,30 ----
  {
  public:
! 	CMgaParser() 
! 	{ 
! 		m_resolveDerFuncPtr = CMgaParser::ResolveDerivation;
! 	}
  
  DECLARE_REGISTRY_RESOURCEID(IDR_MGAPARSER)
***************
*** 39,45 ****
--- 42,53 ----
  public:
  	STDMETHOD(GetXMLInfo)(BSTR filename, BSTR *paradigm, BSTR* parversion, VARIANT *parguid, BSTR* basename, BSTR* version);
+ 	STDMETHOD(GetClipXMLInfo)(BSTR filename, IMgaObject *target, VARIANT_BOOL *isacceptable, BSTR* p_acckind, BSTR* p_version);
  	STDMETHOD(ParseFCOs)(IMgaObject *p, BSTR filename);
+ 	STDMETHOD(ParseClos1)(IMgaObject *p, BSTR filename); // basic
+ 	STDMETHOD(ParseClos4)(IMgaObject *p, BSTR filename); // smart
  	STDMETHOD(ParseProject)(IMgaProject *p, BSTR filename);
  
+ 	string GetClipXMLInfo2();
+ 
  	void CloseAll();
  
***************
*** 85,88 ****
--- 93,99 ----
  	static elementfunc elementfuncs_mga[];
  	static elementfunc elementfuncs_mgainfo[];
+ 	static elementfunc elementfuncs_bcmga[];
+ 	static elementfunc elementfuncs_scmga[];
+ 	static elementfunc elementfuncs_clipmgainfo[];
  
  	CComObjPtr<IMgaProject> project;
***************
*** 91,94 ****
--- 102,109 ----
  	CComObjPtr<IMgaProgressDlg> progress;
  
+ 	CComObjPtr<IMgaObject> m_target;
+ 
+ 	BSTR *closversion;
+ 	BSTR *closacckind;
  	BSTR *infoparname;
  	BSTR *infoparversion;
***************
*** 128,133 ****
--- 143,167 ----
  	};
  
+ 	typedef void (CMgaParser::*ResolverFuncType) (const attributes_type &, deriv_type &);
+ 	ResolverFuncType m_resolveDerFuncPtr;
+ 
  	void ResolveDerivation(const attributes_type &attributes, deriv_type &deriv);
+ 	void ResolveClosure1Derivation(const attributes_type &attributes, deriv_type &deriv);
+ 	void ResolveClosure4Derivation(const attributes_type &attributes, deriv_type &deriv);
  
+ 	bool findPlaceForElem( const attributes_type &attributes, deriv_type& deriv, CComObjPtr<IMgaObject>& place);
+ 	bool findPlaceForElem( const attributes_type &attributes, deriv_type& deriv, CComObjPtr<IMgaFolder>& place_fld, CComObjPtr<IMgaModel>& place_mdl);
+ 
+ 	void findObjOnRelPath( CComObjPtr<IMgaObject> obj_rel_to, const string& relpath , CComObjPtr<IMgaObject>& obj, const string& text = "");
+ 	void findObjOnAbsPath( CComObjPtr<IMgaProject> project, const string& abspath , CComObjPtr<IMgaObject>& obj, const string& text = "");
+ 	void pushInfo( const CComObjPtr<IMgaFolder>& place_fld, const CComObjPtr<IMgaModel>& place_mdl, const CComObjPtr<IMgaFCO>& fco1, const CComObjPtr<IMgaFCO>& fco2/* = CComObjPtr<IMgaFCO>()*/);
+ 	void popInfo();
+ 	void writeInfo( const CComObjPtr<IMgaObject>& place, const CComObjPtr<IMgaObject>& fco1, const CComObjPtr<IMgaObject>& fco2, bool normal_msg = true);
+ 	vector< CComObjPtr<IMgaObject> > m_parsed1;
+ 	vector< CComObjPtr<IMgaObject> > m_parsed2;
+ 	vector< CComObjPtr<IMgaObject> > m_parsed3; // the archetype
+ 
+ 	int  m_clVer;
+ 	string m_clVerStr;
  
  	bool manual_relid_mode;
***************
*** 158,161 ****
--- 192,218 ----
  	void StartProjectInfo(const attributes_type &attributes);
  	void EndNameInfo();
+ 
+ 	void StartBCConnPoint(const attributes_type &attributes);
+ 	void StartBCReference(const attributes_type &attributes);
+ 	void StartBCSet(const attributes_type &attributes);
+ 	void StartBCClipboard(const attributes_type &attributes);
+ 
+ 	void StartSCConnection(const attributes_type &attributes);
+ 	void StartSCConnPoint(const attributes_type &attributes);
+ 	void StartSCReference(const attributes_type &attributes);
+ 	void StartSCSet(const attributes_type &attributes);
+ 
+ 	void EndSCReference();
+ 	void EndSCSet();
+ 	void EndSCConnection();
+ 
+ 
+ 	void StartClipboardInfo(const attributes_type &attributes);
+ 
+ 	protected:
+ 		static CComPtr<IGMEOLEApp>	get_GME(CComObjPtr<IMgaProject> project);
+ 		static void					clear_GME( CComPtr<IGMEOLEApp>& p_GME);
+ 		CComPtr<IGMEOLEApp> m_GME;
+ 
  };
  

Index: Parser.dsp
===================================================================
RCS file: /var/lib/gme/GMESRC/GME/Parser/Parser.dsp,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** Parser.dsp	22 Jul 2004 14:26:50 -0000	1.13
--- Parser.dsp	27 Sep 2004 21:33:01 -0000	1.14
***************
*** 130,133 ****
--- 130,137 ----
  # Begin Source File
  
+ SOURCE=.\Helper.cpp
+ # End Source File
+ # Begin Source File
+ 
  SOURCE=.\MetaParser.cpp
  # End Source File
***************
*** 142,145 ****
--- 146,161 ----
  # Begin Source File
  
+ SOURCE=.\MgaParserBC.cpp
+ # End Source File
+ # Begin Source File
+ 
+ SOURCE=.\MgaParserClosureHelper.cpp
+ # End Source File
+ # Begin Source File
+ 
+ SOURCE=.\MgaParserSC.cpp
+ # End Source File
+ # Begin Source File
+ 
  SOURCE=.\MgaXslt.cpp
  # End Source File
***************
*** 184,187 ****
--- 200,207 ----
  
  SOURCE=.\GenParser.h
+ # End Source File
+ # Begin Source File
+ 
+ SOURCE=.\Helper.h
  # End Source File
  # Begin Source File

Index: mga.dtd
===================================================================
RCS file: /var/lib/gme/GMESRC/GME/Parser/mga.dtd,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** mga.dtd	19 Jul 2004 07:01:00 -0000	1.9
--- mga.dtd	27 Sep 2004 21:33:01 -0000	1.10
***************
*** 47,51 ****
  	role		NMTOKEN		#IMPLIED
  	derivedfrom	IDREF		#IMPLIED
- 	closurelibderivedfrom	CDATA		#IMPLIED
  	isinstance	(yes|no)	"no"
  	isprimary	(yes|no)	"yes"
--- 47,50 ----
***************
*** 60,64 ****
  	role		NMTOKEN		#IMPLIED
  	derivedfrom	IDREF		#IMPLIED
- 	closurelibderivedfrom	CDATA		#IMPLIED
  	isinstance	(yes|no)	"no"
  	isprimary	(yes|no)	"yes"
--- 59,62 ----
***************
*** 72,80 ****
  	role		NMTOKEN		#IMPLIED
  	derivedfrom	IDREF		#IMPLIED
- 	closurelibderivedfrom	CDATA		#IMPLIED
  	isinstance	(yes|no)	"no"
  	isprimary	(yes|no)	"yes"
  	referred	IDREF		#IMPLIED
- 	closurelibreferred	CDATA		#IMPLIED
  	isbound		(yes|no)	"no"
  	relid		CDATA		#IMPLIED
--- 70,76 ----
***************
*** 87,91 ****
  	role		NMTOKEN		#IMPLIED
  	derivedfrom	IDREF		#IMPLIED
- 	closurelibderivedfrom	CDATA		#IMPLIED
  	isinstance	(yes|no)	"no"
  	isprimary	(yes|no)	"yes"
--- 83,86 ----
***************
*** 101,105 ****
  	role		NMTOKEN		#IMPLIED
  	derivedfrom	IDREF		#IMPLIED
- 	closurelibderivedfrom	CDATA		#IMPLIED
  	isinstance	(yes|no)	"no"
  	isprimary	(yes|no)	"yes"
--- 96,99 ----
***************
*** 111,115 ****
  <!ATTLIST connpoint
  	role		NMTOKEN		#REQUIRED
- 	closurelibtarget	CDATA		#IMPLIED
  	target		IDREF		#REQUIRED
  	refs		IDREFS		#IMPLIED
--- 105,108 ----



More information about the GME-commit mailing list