/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

#include <precomp.h>
#include <s2_luidl/pe_file2.hxx>


// NOT FULLY DECLARED SERVICES
#include <ary/idl/i_gate.hxx>
#include <ary/idl/i_module.hxx>
#include <ary/idl/ip_ce.hxx>
#include <ary/doc/d_oldidldocu.hxx>
#include <s2_luidl/distrib.hxx>
#include <s2_luidl/pe_servi.hxx>
#include <s2_luidl/pe_iface.hxx>
#include <s2_luidl/pe_singl.hxx>
#include <s2_luidl/pe_struc.hxx>
#include <s2_luidl/pe_excp.hxx>
#include <s2_luidl/pe_const.hxx>
#include <s2_luidl/pe_enum2.hxx>
#include <s2_luidl/pe_tydf2.hxx>
#include <s2_luidl/tk_keyw.hxx>
#include <s2_luidl/tk_ident.hxx>
#include <s2_luidl/tk_punct.hxx>




namespace csi
{
namespace uidl
{


PE_File::PE_File( TokenDistributor & i_rTokenAdmin,
				  const ParserInfo & i_parseInfo )
	:	pTokenAdmin(&i_rTokenAdmin),
    	pPE_Service(new PE_Service),
    	pPE_Singleton(new PE_Singleton),
		pPE_Interface(new PE_Interface),
		pPE_Struct(new PE_Struct),
		pPE_Exception(new PE_Exception),
		pPE_Constant(new PE_Constant),
		pPE_Enum(new PE_Enum),
		pPE_Typedef(new PE_Typedef),
		pCurNamespace(0),
		pParseInfo(&i_parseInfo),
		eState(e_none),
		nBracketCount_inDefMode(0)
{
}

void
PE_File::EstablishContacts( UnoIDL_PE *					io_pParentPE,
							ary::Repository &		io_rRepository,
							TokenProcessing_Result & 	o_rResult )
{
	UnoIDL_PE::EstablishContacts(io_pParentPE,io_rRepository,o_rResult);
	pPE_Service->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Singleton->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Interface->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Struct->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Exception->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Constant->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Enum->EstablishContacts(this,io_rRepository,o_rResult);
	pPE_Typedef->EstablishContacts(this,io_rRepository,o_rResult);

	pCurNamespace = &Gate().Ces().GlobalNamespace();
}

PE_File::~PE_File()
{
}

void
PE_File::ProcessToken( const Token & i_rToken )
{
	i_rToken.Trigger(*this);
}

void
PE_File::Process_Identifier( const TokIdentifier & i_rToken )
{
	switch (eState)
	{
		case wait_for_module:
		{
				csv_assert(pCurNamespace != 0);

				ary::idl::Module & rCe = Gate().Ces().CheckIn_Module(pCurNamespace->CeId(), i_rToken.Text());
				pCurNamespace = &rCe;

                // Get docu out of normal:
                SetDocu(pTokenAdmin->ReleaseLastParsedDocu());
        		PassDocuAt(rCe);

				csv_assert(pCurNamespace != 0);

				SetResult(done, stay);
				eState = wait_for_module_bracket;
		}		break;
		case on_default:
				SetResult(done, stay);
				break;
		default:
			csv_assert(false);
	}
}

void
PE_File::Process_Punctuation( const TokPunctuation & i_rToken )
{
	switch (eState)
	{
		case e_std:
				if (i_rToken.Id() == TokPunctuation::CurledBracketClose)
				{
					csv_assert(pCurNamespace != 0);

					pCurNamespace = &Gate().Ces().Find_Module(pCurNamespace->Owner());

					SetResult(done, stay);
					eState = wait_for_module_semicolon;
				}
				else
				{
					csv_assert(false);
				}
				break;
		case wait_for_module_bracket:
				if (i_rToken.Id() == TokPunctuation::CurledBracketOpen)
				{
					SetResult(done, stay);
					eState = e_std;
				}
				else
				{
					csv_assert(false);
				}
				break;
		case wait_for_module_semicolon:
				if (i_rToken.Id() == TokPunctuation::Semicolon)
				{
					SetResult(done, stay);
					eState = e_std;
				}
				else
				{
					csv_assert(false);
				}
				break;
		case on_default:
				if (i_rToken.Id() == TokPunctuation::CurledBracketClose)
				{
					nBracketCount_inDefMode--;
				}
				else if (i_rToken.Id() == TokPunctuation::CurledBracketOpen)
				{
					nBracketCount_inDefMode++;
				}
				else if (i_rToken.Id() == TokPunctuation::Semicolon)
				{
					if (nBracketCount_inDefMode <= 0)
					{
						eState = e_std;
					}
				}
				SetResult(done, stay);
				break;
		default:
			csv_assert(false);
	}
}

void
PE_File::Process_MetaType( const TokMetaType &	i_rToken )
{
	switch (i_rToken.Id())
	{
		case TokMetaType::mt_service:
				eState = in_sub_pe;
				SetResult( not_done, push_sure, pPE_Service.Ptr());
				break;
		case TokMetaType::mt_singleton:
				eState = in_sub_pe;
				SetResult( not_done, push_sure, pPE_Singleton.Ptr());
				break;
		case TokMetaType::mt_uik:
				Cerr() << "Syntax error: [uik ....] is obsolete now." << Endl();
				SetResult( not_done, pop_failure);
				break;
		case TokMetaType::mt_interface:
				eState = in_sub_pe;
				SetResult( not_done, push_sure, pPE_Interface.Ptr());
				break;
		case TokMetaType::mt_module:
				eState = wait_for_module;
				SetResult( done, stay );
				break;
		case TokMetaType::mt_struct:
				eState = in_sub_pe;
				SetResult( done, push_sure, pPE_Struct.Ptr());
				break;
		case TokMetaType::mt_exception:
				eState = in_sub_pe;
				SetResult( done, push_sure, pPE_Exception.Ptr());
				break;
		case TokMetaType::mt_constants:
				eState = in_sub_pe;
				SetResult( done, push_sure, pPE_Constant.Ptr());
				break;
		case TokMetaType::mt_enum:
				eState = in_sub_pe;
				SetResult( done, push_sure, pPE_Enum.Ptr());
				break;
		case TokMetaType::mt_typedef:
				eState = in_sub_pe;
				SetResult( done, push_sure, pPE_Typedef.Ptr());
				break;

		default:
				Process_Default();
	} 	// end switch
}

void
PE_File::Process_Stereotype( const TokStereotype & i_rToken )
{
    if (i_rToken.Id() == TokStereotype::ste_published)
    {
        pTokenAdmin->Set_PublishedOn();

        SetResult(done, stay);
    }
    else
    {
        Process_Default();
    }
}

void
PE_File::Process_Default()
{
	if (eState != on_default)
	{
		eState = on_default;
		nBracketCount_inDefMode = 0;
	}
	SetResult(done, stay);
}

const ary::idl::Module &
PE_File::CurNamespace() const
{
	csv_assert(pCurNamespace);
	return *pCurNamespace;
}

const ParserInfo &
PE_File::ParseInfo() const
{
	csv_assert(pParseInfo);
	return *pParseInfo;
}

void
PE_File::InitData()
{
	eState = e_std;
}

void
PE_File::TransferData()
{
	eState = e_none;
}

void
PE_File::ReceiveData()
{
	eState = e_std;
}


UnoIDL_PE &
PE_File::MyPE()
{
 	return *this;
}

}   // namespace uidl
}   // namespace csi


