// XMLToJava.cpp: implementation of the XMLToJava class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XMLToJava.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
extern void AddToLog( CString str );
XMLToJava::XMLToJava()
{
	m_TabNumber = 0;
}

XMLToJava::~XMLToJava()
{

}

void XMLToJava::Do(CString dir ,CString fn)
{
	CFile file;
	if( file.Open( fn , CFile::modeRead ) )
	{
		CString str;
		CString path;
		StringList items;
		CString code;
		CString className;
		//解出所有的单词
		do{
			ReadALine( file , str );
			DecodeALine( items , str );
		}while(str.GetLength() );
		file.Close();
		//开始生成代码
		path = dir;
		while( items.GetUpperBound() >= 0 )
		{
			CString *pStr;
			pStr = items.GetAt( 0 );
			if( *pStr == "<NAMESPACE>" || *pStr == "<CLASS>" || *pStr == "<THREAD>" || *pStr =="<SYNCH>")
			{
				items.RemoveAt( 0 );
				if( *pStr == "<NAMESPACE>" )
				{//遇到名字空间，需要创建目录
					CString str;
					path += "\\";
					DecodeItem( items , str );
					path += str;
					CreateDirectory( LPCTSTR( path ) , NULL );
				}
				else
				{//遇到类
					CString txt;
					DecodeItem( items , txt );
					m_TabNumber = 0;
					code = "public class ";
					code += txt;
					if( *pStr == "<THREAD>" )
					{
						code += " extends Thread";
					}
					code += "\r\n";
					code += "{\r\n";
					className = txt;
					m_TabNumber++;
				}
				delete pStr;
			}
			else if( *pStr == "<ATTRIBUTE>" )
			{
				code += Tabs();
				code += DecodeAttribute( items );//pStr已经被delete了
				code += "\r\n";
			}
			else if( *pStr == "<OPERATION>")
			{
				code += DecodeOperation( items );
			}
			else
			{
				if( *pStr == "</NAMESPACE>" )
				{
					path = path.Left( path.ReverseFind('\\') );
				}
				else if( *pStr == "</CLASS>" || *pStr == "</THREAD>" || *pStr == "</SYNCH>" )
				{
					CFile javaFile;
					CString javaFileName;

					m_TabNumber --;
					code += Tabs();

					code += "};\r\n";

					javaFileName = path;
					javaFileName += "\\";
					javaFileName += className;
					javaFileName += ".java";

					if( javaFile.Open( javaFileName , CFile::modeCreate | CFile::modeWrite ) )
					{
						javaFile.Write( code , code.GetLength() );
						javaFile.Close();
					}
				}
				else
				{
					
				}
				items.RemoveAt( 0 );
				delete pStr;
			}
		}
	}
}

BOOL XMLToJava::ReadALine(CFile &file, CString &str)
{
	char c;
	str = "";
	while( file.Read( &c , 1 ) )
	{
		if( c == '\r' )
		{
			file.Read( &c , 1 );
			str.TrimLeft();
			return TRUE;
		}
		else
		{
			str += c;
		}
	}
	return TRUE;
}

CString XMLToJava::DecodeAttribute(StringList &list)
{//list中包含ATTRIBUTE标签
	CString rlt;
	CString *pStr;

	CString visibility;
	CString name;
	CString type;
	CString iniValue;

	CPtrStack<CString*>waitStack;
	
	while( list.GetUpperBound() >= 0 )
	{
		pStr = list.GetAt( 0 );
		list.RemoveAt( 0 );
		if( *pStr == "<ATTRIBUTE>")
		{
			delete pStr;
			continue;
		}
		else if( *pStr == "</ATTRIBUTE>" )
		{
			delete pStr;
			break;
		}
		if( *pStr == "<NAME>" )
		{
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			name = *pStr;
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			delete pStr;
		}
		else if( *pStr == "<VISIBILITY>" )
		{
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			visibility = *pStr;
			visibility.MakeLower();
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			delete pStr;
		}
		else if( *pStr == "<TYPE>" )
		{
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			type = MapType(*pStr);
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			delete pStr;
		}
		else if( *pStr == "<INIVALUE>" )
		{
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			iniValue = *pStr;
			delete pStr;
			pStr = list.GetAt( 0 );
			list.RemoveAt( 0 );
			delete pStr;
		}
	}
	if( visibility.GetLength() == 0 )rlt = "public";
	else rlt = visibility;
	rlt += " ";
	rlt += type;
	rlt += " ";
	rlt += name;
	if( iniValue.GetLength() )
	{
		rlt += " = ";
		rlt += iniValue;
	}
	rlt += " ; ";
	return rlt;
}



CString XMLToJava::DecodeItem(StringList &list ,CString &content)
{
	CString rlt;
	CString *pStr;
	pStr = list.GetAt( 0 );
	rlt = *pStr;
	pStr = list.GetAt( 1 );
	content = *pStr;
	for(  int i = 0 ; i < 3 ; i ++ )
	{
		pStr = list.GetAt( 0 );
		delete pStr;
		list.RemoveAt( 0 );
	}
	return rlt;
}

void XMLToJava::DecodeNext(StringList &list, CString &id, CString &condiction ,CString &expression)
{
	CString *pStr;

	expression = "";
	while(list.GetUpperBound() >= 0)
	{
		pStr = list.GetAt( 0 );
		if( *pStr == "<NEXT>" )
		{
			delete pStr;
			list.RemoveAt( 0 );
			continue;
		}
		else if( *pStr == "</NEXT>" )
		{
			delete pStr;
			list.RemoveAt( 0 );
			break;
		}
		else if( *pStr == "<ID>" )
		{
			DecodeItem( list , id );
		}
		else if( *pStr == "<CONDICTION>" )
		{
			DecodeItem( list ,condiction );
		}
		else if( *pStr == "<EXPRESSION>" )
		{
			DecodeItem( list , expression );
		}
	}
}

void XMLToJava::DecodeALine(StringList &list, CString str)
{
	if( str.GetLength() )
	{
		if( str.GetAt( 0 ) == '<' )
		{
			if( str.GetAt( 1 ) == '/' )
			{
				list.Add( new CString( str ) );
			}
			else
			{
				for( int i = 0 ; i < str.GetLength() ; i ++ )
				{
					if( str.GetAt( i ) == '>' ) break;
				}
				if( i != str.GetLength() - 1 )
				{
					CString tag1,tag2,con;
					tag1 = str.Left( i + 1 );
					tag2 = str.Right( i + 2 );
					con = str.Mid( i + 1 , str.GetLength() - i - i - 3 );
					list.Add( new CString( tag1 ) );
					list.Add( new CString( con ) );
					list.Add( new CString( tag2 ) );
				}
				else
				{
					list.Add( new CString( str ) );
				}
			}
		}
		else
		{//is content
			list.Add( new CString( str ) );
		}
	}
}

CString XMLToJava::DecodeOperation(StringList &list)
{
	CString opeName,opeReturn,opeParam,opeVisi,opeBody;
	CString *pStr;
	CString code;
	while( list.GetUpperBound() >= 0 )
	{
		pStr = list.GetAt( 0 );
		if( *pStr == "<OPERATION>" )
		{
			list.RemoveAt( 0 );
			delete pStr;
			continue;
		}
		else if( *pStr == "<NAME>" )
		{//操作名字
			DecodeItem( list , opeName );
		}
		else if( *pStr =="<RETURNTYPE>" )
		{//RETURN TYPE
			DecodeItem( list , opeReturn );
			opeReturn = MapType( opeReturn );
		}
		else if( *pStr == "<VISIBILITY>" )
		{//visibility
			DecodeItem( list , opeVisi );
		}
		else if( *pStr == "<PARAMETER>" )
		{
			if( opeParam.GetLength() )
			{
				opeParam += " , ";
				opeParam += DecodeParameter( list );
			}
			else
			{
				opeParam = DecodeParameter( list );
			}
		}
		else if( *pStr == "<TRANSTABLE>" )
		{
			opeBody = DecodeTranstable( list );
		}
		else if( *pStr == "<EXPRESSION>" )
		{
			CString t;
			m_TabNumber ++;
			DecodeItem( list , t );
			opeBody += Tabs();
			opeBody += t;
			opeBody += "\r\n";
			m_TabNumber --;
		}
		else if( *pStr == "</OPERATION>" )
		{
			list.RemoveAt( 0 );
			delete pStr;
			opeVisi.MakeLower();
			code += Tabs();
			if( opeVisi.GetLength() )
			{
				opeVisi.MakeLower();
				code += opeVisi;
				code += " ";
			}
			else
			{
				code += "public ";
			}
			if( opeReturn.GetLength() )
				code += opeReturn;
			else
				code += "void";
			code += " ";
			code += opeName;
			code += "(";
			code += opeParam;
			code += ")\r\n";
			code += Tabs();
			code += "{\r\n";
			code += opeBody;
			code += Tabs();
			code += "};\r\n";
			break;
		}
	}
	return code;
}

CString XMLToJava::DecodeParameter(StringList &list)
{
	CString *pStr;
	CString name,type,ini;
	CString code;
	while( list.GetUpperBound() >= 0)
	{
		pStr = list.GetAt( 0 );
		
		if( *pStr == "<PARAMETER>" )
		{
			list.RemoveAt( 0 );
			delete pStr;
		}
		else if( *pStr == "</PARAMETER>")
		{
			delete pStr;
			list.RemoveAt( 0 );
			break;
		}
		else if( *pStr == "<NAME>" )
		{
			DecodeItem( list , name );
		}
		else if( *pStr == "<TYPE>" )
		{
			DecodeItem( list , type );
			type = MapType( type );
		}
		else if( *pStr == "<DEFAULTVALUE>" )
		{
			DecodeItem( list , ini );
		}
	}
	code = type;
	code += " ";
	code += name;
	if( ini.GetLength() )
	{
		code += "=";
		code += ini;
	}
	return code;
}

CString XMLToJava::DecodeTranstable(StringList &list)
{
	CString *pStr;
	CString iniID;
	CObjTempl<CString>finID;
	CString code;
	CString branch;
	m_TabNumber ++;
	while( list.GetUpperBound() >= 0 )
	{
		pStr = list.GetAt( 0 );
		if( *pStr == "<TRANSTABLE>" )
		{
			delete pStr;
			list.RemoveAt( 0 );
			continue;
		}
		else if( *pStr == "</TRANSTABLE>" )
		{
			delete pStr;
			list.RemoveAt( 0 ) ;
			break;
		}
		else if( *pStr == "<INITID>" )
		{
			DecodeItem( list , iniID );
		}
		else if( *pStr == "<FINIID>" )
		{
			CString t;
			DecodeItem( list ,t);
			finID.Add( t );
		}
		else if( *pStr == "<ACTIVITY>" )
		{
			branch += DecodeActivity( list ,finID);
		}
	}
	code += Tabs();
	code += "int iCurID = ";
	code += iniID;
	code += ";\r\n";
	code += Tabs();
	code += "boolean quit = false;\r\n";
	code += Tabs();
	code += "while( !quit )\r\n";//while(iniID != finID )
	code += Tabs();
	code += "{\r\n";//while后边的{
	m_TabNumber ++;
	code += Tabs();
	code += "switch( iCurID )\r\n";//switch( iniID )
	code += Tabs();
	code += "{\r\n";//switch后边的{

	code += branch;//所有的case

	code += Tabs();
	code += "};\r\n";//switch的}
	m_TabNumber --;
	code += Tabs();
	code += " };\r\n";//while的}
	m_TabNumber --;
	return code;
}

CString XMLToJava::DecodeActivity(StringList &list , CObjTempl<CString>& finiID)
{
	CString *pStr;
	CString id;
	CString expression;
	CString nextcode;
	CString code;
	m_TabNumber ++;
	while( list.GetUpperBound() >= 0 )
	{
		pStr = list.GetAt( 0 );
		if( *pStr == "<ACTIVITY>" )
		{
			delete pStr;
			list.RemoveAt( 0 );
			continue;
		}
		else if( *pStr == "</ACTIVITY>" )
		{
			delete pStr;
			list.RemoveAt( 0 );
			break;
		}
		else if( *pStr == "<ID>" )
		{
			DecodeItem( list , id );
		}
		else if( *pStr == "<EXPRESSION>")
		{
			DecodeItem( list , expression );
		}
		else if( *pStr == "<NEXT>" )
		{
			CString nextid ,con ,ec;
			DecodeNext( list , nextid ,con ,ec);
			m_TabNumber ++;
			if( nextcode.GetLength() )
			{
				CString cur;
				cur = "else if( ";
				cur += con;
				cur += " ) {\r\n";
				cur += Tabs();
				cur += "iCurID = ";
				cur += nextid;
				cur += ";";
				cur += "\r\n";
				nextcode += Tabs();
				if( ec.GetLength() )
				{
					cur += ec;
					cur +="\r\n";
					cur += Tabs();
				}
				cur += "}\r\n";
				cur += Tabs();
				nextcode += cur;
			}
			else
			{
				CString cur;
				cur = "if( ";
				cur += con;
				cur += " ) {\r\n";
				cur += Tabs();
				cur += "iCurID = ";
				cur += nextid;
				cur += ";";
				cur += "\r\n";
				nextcode += Tabs();
				if( ec.GetLength() )
				{
					cur += ec;
					cur +="\r\n";
					cur += Tabs();
				}
				cur += "}\r\n";
				cur += Tabs();
				nextcode += cur;
			}
			m_TabNumber --;
		}
	}
	code += Tabs();
	code += "case ";
	code += id;
	code += ":\r\n";
	m_TabNumber ++;

	BOOL isFini = FALSE;
	for( int i = 0 ; i < finiID.GetSize() ; i ++)
	{
		CString t = finiID.GetAt( i );
		if( t == id )
		{
			isFini = TRUE;
			break;
		}
	}
	if( isFini )
	{
		code += Tabs();
		code += "quit = true;\r\n";
	}
	if( expression.GetLength() )
	{
		code += Tabs();
		code += expression;
		code += "\r\n";
	}
	code += nextcode;
	code += Tabs();
	code += "break;\r\n";
	m_TabNumber --;
	m_TabNumber --;
	return code;
}

CString XMLToJava::Tabs()
{
	CString str;
	for( int i = 0 ; i < m_TabNumber ; i ++ )
	{
		str += "\t";
	}
	return str;
}

CString XMLToJava::MapType(CString tpo)
{
	CString tp;
	tp = tpo;
	tp.MakeLower();
	if( tp == "integer" )return "int";
	else if( tp == "string" ) return "String";
	else if( tp == "boolean" ) return "boolean";
	else if( tp == "real" ) return "float";
	else return tpo;
}
