/**************************************************************
 *
 * 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_;
}
