text: /**************************************************************
   * 
   * 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.
   * 
   *************************************************************/
  
  
  
  // MARKER(update_precomp.py): autogen include statement, do not remove
  #include "precompiled_xmloff.hxx"
  #include "EventOASISTContext.hxx"
  #include "EventMap.hxx"
  #include "MutableAttrList.hxx"
  #include "xmloff/xmlnmspe.hxx"
  #include "ActionMapTypesOASIS.hxx"
  #include "AttrTransformerAction.hxx"
  #include "TransformerActions.hxx"
  #ifndef _XMLOFF_TRANSFORMERBASE_HXX
  #include "TransformerBase.hxx"
  #endif
  
  #ifndef OASIS_FILTER_OOO_1X
  // Used to parse Scripting Framework URLs
  #include <com/sun/star/uri/XUriReferenceFactory.hpp>
  #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
  #include <comphelper/processfactory.hxx>
  #endif
  
  #include <hash_map>
  
  using ::rtl::OUString;
  
  using namespace ::com::sun::star::uno;
  using namespace ::com::sun::star::xml::sax;
  using namespace ::xmloff::token;
  
  class XMLTransformerOASISEventMap_Impl:
  	public ::std::hash_map< NameKey_Impl, ::rtl::OUString, 
  						    NameHash_Impl, NameHash_Impl >
  {
  public:
  	XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit );
  	~XMLTransformerOASISEventMap_Impl();
  };
  
  XMLTransformerOASISEventMap_Impl::XMLTransformerOASISEventMap_Impl( XMLTransformerEventMapEntry *pInit )
  {
  	if( pInit )
  	{
  		XMLTransformerOASISEventMap_Impl::key_type aKey;
  		XMLTransformerOASISEventMap_Impl::mapped_type aData;
  		while( pInit->m_pOASISName )
  		{
  			aKey.m_nPrefix = pInit->m_nOASISPrefix;
  			aKey.m_aLocalName = OUString::createFromAscii(pInit->m_pOASISName);
  
  			OSL_ENSURE( find( aKey ) == end(), "duplicate event map entry" );
  
  			aData = OUString::createFromAscii(pInit->m_pOOoName);
  
  			XMLTransformerOASISEventMap_Impl::value_type aVal( aKey, aData );
  
  			insert( aVal );
  			++pInit;
  		}
  	}
  }
  
  XMLTransformerOASISEventMap_Impl::~XMLTransformerOASISEventMap_Impl()
  {
  }
  
  // -----------------------------------------------------------------------------
  
  TYPEINIT1( XMLEventOASISTransformerContext, XMLRenameElemTransformerContext);
  
  XMLEventOASISTransformerContext::XMLEventOASISTransformerContext( 
  		XMLTransformerBase& rImp, 
  		const OUString& rQName ) :
  	XMLRenameElemTransformerContext( rImp, rQName, 
  		 rImp.GetNamespaceMap().GetKeyByAttrName( rQName ), XML_EVENT )
  {
  }
  
  XMLEventOASISTransformerContext::~XMLEventOASISTransformerContext()
  {
  }
  
  XMLTransformerOASISEventMap_Impl 
  	*XMLEventOASISTransformerContext::CreateEventMap()
  {
  	return new XMLTransformerOASISEventMap_Impl( aTransformerEventMap );
  }
  
  XMLTransformerOASISEventMap_Impl 
  	*XMLEventOASISTransformerContext::CreateFormEventMap()
  {
  	return new XMLTransformerOASISEventMap_Impl( aFormTransformerEventMap );
  }
  
  void XMLEventOASISTransformerContext::FlushEventMap(
  		XMLTransformerOASISEventMap_Impl *p )
  {
  	delete p;
  }
  
  OUString XMLEventOASISTransformerContext::GetEventName( 
  		sal_uInt16 nPrefix,
  		const OUString& rName,
  	   	XMLTransformerOASISEventMap_Impl& rMap,
  	   	XMLTransformerOASISEventMap_Impl *pMap2)
  {
  	XMLTransformerOASISEventMap_Impl::key_type aKey( nPrefix, rName );
  	if( pMap2 )
  	{
  		XMLTransformerOASISEventMap_Impl::const_iterator aIter = 
  			pMap2->find( aKey );
  		if( !(aIter == pMap2->end()) )
  			return (*aIter).second;
  	}
  
  	XMLTransformerOASISEventMap_Impl::const_iterator aIter = rMap.find( aKey );
  	if( aIter == rMap.end() )
  		return rName;
  	else
  		return (*aIter).second;
  }
  
  bool ParseURLAsString(
  	const OUString& rAttrValue,
  	OUString* pName, OUString* pLocation )
  {
  	OUString SCHEME( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:" ) );
  
  	sal_Int32 params = rAttrValue.indexOf( '?' );
  	if ( rAttrValue.indexOf( SCHEME ) != 0 || params < 0 )
  	{
  		return sal_False;
  	}
  
  	sal_Int32 start = SCHEME.getLength();
  	*pName = rAttrValue.copy( start, params - start ); 
  
  	OUString aToken;
  	OUString aLanguage; 
  	params++;
  	do
  	{
  		aToken = rAttrValue.getToken( 0, '&', params );
  		sal_Int32 dummy = 0;
  
  		if ( aToken.match( GetXMLToken( XML_LANGUAGE ) ) )
  		{
  			aLanguage = aToken.getToken( 1, '=', dummy );
  		}
  		else if ( aToken.match( GetXMLToken( XML_LOCATION ) ) )
  		{
  			OUString tmp = aToken.getToken( 1, '=', dummy );
  			if ( tmp.equalsIgnoreAsciiCase( GetXMLToken( XML_DOCUMENT ) ) )
  			{
  				*pLocation = GetXMLToken( XML_DOCUMENT );
  			}
  			else
  			{
  				*pLocation = GetXMLToken( XML_APPLICATION );
  			}
  		}
  	} while ( params >= 0 );
  
  	if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) )
  	{
  		return sal_True;
  	}
  	return sal_False;
  }
  
  bool ParseURL(
  	const OUString& rAttrValue,
  	OUString* pName, OUString* pLocation )
  {
  #ifdef OASIS_FILTER_OOO_1X
  	return ParseURLAsString( rAttrValue, pName, pLocation ); 
  #else
  	Reference< com::sun::star::lang::XMultiServiceFactory >
  		xSMgr = ::comphelper::getProcessServiceFactory();
  
  	Reference< com::sun::star::uri::XUriReferenceFactory >
  		xFactory( xSMgr->createInstance( OUString::createFromAscii(
  			"com.sun.star.uri.UriReferenceFactory" ) ), UNO_QUERY );
  
  	if ( xFactory.is() )
  	{
  		Reference< com::sun::star::uri::XVndSunStarScriptUrl > xUrl (
  			xFactory->parse( rAttrValue ), UNO_QUERY );
  
  		if ( xUrl.is() )
  		{
  			OUString aLanguageKey = GetXMLToken( XML_LANGUAGE );
  			if ( xUrl.is() && xUrl->hasParameter( aLanguageKey ) )
  			{
  				OUString aLanguage = xUrl->getParameter( aLanguageKey );
  
  				if ( aLanguage.equalsIgnoreAsciiCaseAscii( "basic" ) )
  				{
  					*pName = xUrl->getName();
  
  					OUString tmp =
  						xUrl->getParameter( GetXMLToken( XML_LOCATION ) );
  
  					OUString doc = GetXMLToken( XML_DOCUMENT );
  
  					if ( tmp.equalsIgnoreAsciiCase( doc ) )
  					{
  						*pLocation = doc;
  					}
  					else
  					{
  						*pLocation = GetXMLToken( XML_APPLICATION );
  					}
  					return sal_True;
  				}
  			}
  		}
  		return sal_False;
  	}
  	else
  	{
  		return ParseURLAsString( rAttrValue, pName, pLocation ); 
  	}
  #endif
  }
  
  void XMLEventOASISTransformerContext::StartElement( 
  	const Reference< XAttributeList >& rAttrList )
  {
  	OSL_TRACE("XMLEventOASISTransformerContext::StartElement");
  
  	XMLTransformerActions *pActions =
  		GetTransformer().GetUserDefinedActions( OASIS_EVENT_ACTIONS );
  	OSL_ENSURE( pActions, "go no actions" );
  	
  	Reference< XAttributeList > xAttrList( rAttrList );
  	XMLMutableAttributeList *pMutableAttrList = 0;
  	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
  	for( sal_Int16 i=0; i < nAttrCount; i++ )
  	{
  		const OUString& rAttrName = xAttrList->getNameByIndex( i );
  		OUString aLocalName;
  		sal_uInt16 nPrefix =
  			GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName, 
  																 &aLocalName );
  		XMLTransformerActions::key_type aKey( nPrefix, aLocalName );
  		XMLTransformerActions::const_iterator aIter =
  			pActions->find( aKey );
  		if( !(aIter == pActions->end() ) )
  		{
  			if( !pMutableAttrList )
  			{
  				pMutableAttrList = 
  						new XMLMutableAttributeList( xAttrList );
  				xAttrList = pMutableAttrList;
  			}
  			const OUString& rAttrValue = xAttrList->getValueByIndex( i );
  			switch( (*aIter).second.m_nActionType )
  			{
  			case XML_ATACTION_HREF:
  				{
  					OUString aAttrValue( rAttrValue );
  					OUString aName, aLocation;
  
  					bool bNeedsTransform =
  						ParseURL( rAttrValue, &aName, &aLocation );
  
  					if ( bNeedsTransform )
  					{
  						pMutableAttrList->RemoveAttributeByIndex( i );
  
  						OUString aAttrQName(
  							GetTransformer().GetNamespaceMap().GetQNameByKey(
  								XML_NAMESPACE_SCRIPT, 
  							::xmloff::token::GetXMLToken( XML_MACRO_NAME ) ) );
  
  						pMutableAttrList->AddAttribute( aAttrQName, aName );
  
  						sal_Int16 idx = pMutableAttrList->GetIndexByName(
  							GetTransformer().GetNamespaceMap().GetQNameByKey(
  								XML_NAMESPACE_SCRIPT,
  							GetXMLToken( XML_LANGUAGE ) ) );
  
  						pMutableAttrList->SetValueByIndex( idx,
  							OUString::createFromAscii("StarBasic") );
  
  						OUString aLocQName(
  							GetTransformer().GetNamespaceMap().GetQNameByKey(
  								XML_NAMESPACE_SCRIPT,
  								GetXMLToken( XML_LOCATION ) ) );
  
  						pMutableAttrList->AddAttribute( aLocQName, aLocation );
  					}
  				}
  				break;
  			case XML_ATACTION_EVENT_NAME:
  				{
  					// Check if the event belongs to a form or control by
  					// cehcking the 2nd ancestor element, f.i.:
  					// <form:button><form:event-listeners><form:event-listener>
  					const XMLTransformerContext *pObjContext =
  						GetTransformer().GetAncestorContext( 1 );
  					sal_Bool bForm = pObjContext && 
  
  						pObjContext->HasNamespace(XML_NAMESPACE_FORM );
  					pMutableAttrList->SetValueByIndex( i, 
  								   GetTransformer().GetEventName( rAttrValue,
  									  							  bForm ) );
  				}
  				break;
  			case XML_ATACTION_REMOVE_NAMESPACE_PREFIX:
  				{
  					OUString aAttrValue( rAttrValue );
  					sal_uInt16 nValPrefix =
  						static_cast<sal_uInt16>((*aIter).second.m_nParam1);
  					if( GetTransformer().RemoveNamespacePrefix( 
  								aAttrValue, nValPrefix ) )
  						pMutableAttrList->SetValueByIndex( i, aAttrValue );
  				}
  				break;
  			case XML_ATACTION_MACRO_NAME:
              {
                  OUString aName, aLocation;
                  bool bNeedsTransform =
                  ParseURL( rAttrValue, &aName, &aLocation );
                  
                  if ( bNeedsTransform )
                  {
                      pMutableAttrList->SetValueByIndex( i, aName );
                      
                      sal_Int16 idx = pMutableAttrList->GetIndexByName(
                      GetTransformer().GetNamespaceMap().GetQNameByKey(
                      XML_NAMESPACE_SCRIPT,
                      GetXMLToken( XML_LANGUAGE ) ) );
                      
                      pMutableAttrList->SetValueByIndex( idx,
                      OUString::createFromAscii("StarBasic") );
                      
                      OUString aLocQName(
                      GetTransformer().GetNamespaceMap().GetQNameByKey(
                      XML_NAMESPACE_SCRIPT,
                      GetXMLToken( XML_LOCATION ) ) );
                      
                      pMutableAttrList->AddAttribute( aLocQName, aLocation );
                  }
                  else
                  {
                      const OUString& rApp = GetXMLToken( XML_APPLICATION ); 
                      const OUString& rDoc = GetXMLToken( XML_DOCUMENT ); 
                      OUString aAttrValue;
                      if( rAttrValue.getLength() > rApp.getLength()+1 &&
                          rAttrValue.copy(0,rApp.getLength()).
                              equalsIgnoreAsciiCase( rApp ) &&
                          ':' == rAttrValue[rApp.getLength()] )
                      {
                          aLocation = rApp;
                          aAttrValue = rAttrValue.copy( rApp.getLength()+1 );
                      }
                      else if( rAttrValue.getLength() > rDoc.getLength()+1 &&
                               rAttrValue.copy(0,rDoc.getLength()).
                                  equalsIgnoreAsciiCase( rDoc ) &&
                               ':' == rAttrValue[rDoc.getLength()] )
                      {
                          aLocation= rDoc;
                          aAttrValue = rAttrValue.copy( rDoc.getLength()+1 );
                      }
                      if( aAttrValue.getLength() )
                          pMutableAttrList->SetValueByIndex( i, 
                      aAttrValue );
                      if( aLocation.getLength() )
                      {	
                          OUString aAttrQName( GetTransformer().GetNamespaceMap().
                          GetQNameByKey( XML_NAMESPACE_SCRIPT, 
                          ::xmloff::token::GetXMLToken( XML_LOCATION ) ) );
                          pMutableAttrList->AddAttribute( aAttrQName, aLocation );
                          // draw bug
                          aAttrQName = GetTransformer().GetNamespaceMap().
                          GetQNameByKey( XML_NAMESPACE_SCRIPT, 
                          ::xmloff::token::GetXMLToken( XML_LIBRARY ) );
                          pMutableAttrList->AddAttribute( aAttrQName, aLocation );
                      }
                  }
              }
              break;
  			case XML_ATACTION_COPY:
  				break;
  			default:
  				OSL_ENSURE( sal_False, "unknown action" );
  				break;
  			}
  		}
  	}
  
  	XMLRenameElemTransformerContext::StartElement( xAttrList );
  }
  