/**************************************************************
 * 
 * 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 "xml_cdim.hxx"

const char ComponentDescriptionImpl::C_sTagDescription[]
										=   "COMPONENTDESCRIPTION";
const char ComponentDescriptionImpl::C_sStatus[]
										=   "Status";
const char * ComponentDescriptionImpl::C_sSubTags[ComponentDescription::tag_MAX]
										= {	"None",
										    "Name",
											"Description",
											"ModuleName",
											"LoaderName",
											"SupportedService",
											"ProjectBuildDependency",
											"RuntimeModuleDependency",
											"ServiceDependency",
											"Language",
											C_sStatus,
											"Type"
										  };

ComponentDescriptionImpl::ComponentDescriptionImpl()
//	:	aTags
{
	const int i_max = tag_MAX;
	aTags.reserve(i_max);

	for (int i = 0; i < i_max; ++i)
	{
		aTags.push_back( new ValueList(E_Tag(i)) );
	}  // end for
}

ComponentDescriptionImpl::~ComponentDescriptionImpl()
{
	for ( std::vector< ValueList* >::iterator aIter = aTags.begin();
		  aIter != aTags.end();
		  ++aIter )
	{
		delete *aIter;
	}
}

inline void
GetStatusValue( ByteString & o_sValue, const ByteString & i_sStatusTag )
{
	// o_sValue is always == "" at the beginning.

	const char * pStatusValue = strchr(i_sStatusTag.GetBuffer(), '"');
	if (pStatusValue == 0)
		return;
	pStatusValue++;
	const char * pStatusValueEnd = strrchr(pStatusValue,'"');
	if (pStatusValueEnd == 0 || pStatusValueEnd - pStatusValue < 1)
		return ;

	ByteString sValue(pStatusValue, pStatusValueEnd - pStatusValue);
	o_sValue = sValue;
}

ComponentDescriptionImpl::ValueList *
ComponentDescriptionImpl::GetBeginTag( ByteString &	 o_sValue,
									   const char *& io_pStartOfTag ) const
{
	o_sValue = "";

	const char * pCurTextEnd = strchr(io_pStartOfTag,'>');
	if ( 0 == pCurTextEnd )
		return 0;

	if ( ComponentDescriptionImpl::CheckEndOfDescription(io_pStartOfTag) )
    	return 0;

	ByteString sTag(io_pStartOfTag + 1, pCurTextEnd - io_pStartOfTag - 1);
	io_pStartOfTag += sTag.Len() + 2;

	// Special case <Status ... >
	if ( strnicmp(C_sStatus, sTag.GetBuffer(), (sizeof C_sStatus) - 1 ) == 0 )
	{
		GetStatusValue(o_sValue,sTag);
		return aTags[tag_Status];
	}

	// Regular seeking for matching data list:
	for ( INT32 i = 0; i < tag_MAX; i++ )
	{
		if ( 0 == stricmp(sTag.GetBuffer(), C_sSubTags[i]) )
			return aTags[i];
	}	// end for

	return 0;
}

const std::vector< ByteString > &
ComponentDescriptionImpl::DataOf( ComponentDescriptionImpl::E_Tag i_eTag ) const
{
	if (0 < i_eTag && i_eTag < tag_MAX)
		return *aTags[i_eTag];
	else
		return ValueList::Null_();
}

ByteString
ComponentDescriptionImpl::DatumOf( ComponentDescriptionImpl::E_Tag i_eTag ) const
{
	if (0 < i_eTag && i_eTag < tag_MAX)
	{
		ValueList & rValues = *aTags[i_eTag];
		if (rValues.size() > 0)
			return rValues[0];
	}
	return "";
}

void
ComponentDescriptionImpl::ParseUntilStartOfDescription( const char * & io_pBufferPosition )
{
	for ( const char * pSearch = strchr(io_pBufferPosition,'<');
		  pSearch != 0;
		  pSearch = strchr(pSearch+1,'<') )
	{
		if ( pSearch != io_pBufferPosition
			 && 0 == strnicmp(pSearch+1,C_sTagDescription, strlen(C_sTagDescription))
			 && *(pSearch + strlen(C_sTagDescription) + 1) == '>' )
		{
			io_pBufferPosition = pSearch + strlen(C_sTagDescription) + 2;
			return;
		}
	}	// end for

	io_pBufferPosition = 0;
}

BOOL
ComponentDescriptionImpl::ValueList::MatchesEndTag( const char * i_pTextPosition ) const
{
	return strnicmp( i_pTextPosition+2, C_sSubTags[eTag], strlen(C_sSubTags[eTag]) ) == 0
		   && strncmp(i_pTextPosition,"</",2) == 0
		   && *(i_pTextPosition + 2 + strlen(C_sSubTags[eTag]) ) == '>';
}

INT32
ComponentDescriptionImpl::ValueList::EndTagLength() const
{
	return strlen(C_sSubTags[eTag]) + 3;
}


const ComponentDescriptionImpl::ValueList &
ComponentDescriptionImpl::ValueList::Null_()
{
	static const ValueList aNull_(ComponentDescription::tag_None);
    return aNull_;
}


