summaryrefslogtreecommitdiff
path: root/svx/source/smarttags/SmartTagMgr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/smarttags/SmartTagMgr.cxx')
-rw-r--r--svx/source/smarttags/SmartTagMgr.cxx552
1 files changed, 552 insertions, 0 deletions
diff --git a/svx/source/smarttags/SmartTagMgr.cxx b/svx/source/smarttags/SmartTagMgr.cxx
new file mode 100644
index 000000000000..0070646b3330
--- /dev/null
+++ b/svx/source/smarttags/SmartTagMgr.cxx
@@ -0,0 +1,552 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// SMARTTAGS
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/SmartTagMgr.hxx>
+
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/smarttags/XSmartTagRecognizer.hpp>
+#include <com/sun/star/smarttags/XSmartTagAction.hpp>
+#include <com/sun/star/deployment/ExtensionManager.hpp>
+#include <com/sun/star/text/XTextMarkup.hpp>
+#include <com/sun/star/smarttags/SmartTagRecognizerMode.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/util/XChangesNotifier.hpp>
+#include <comphelper/processfactory.hxx>
+#include <rtl/ustring.hxx>
+#include <tools/string.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+
+#define C2U(cChar) rtl::OUString::createFromAscii(cChar)
+
+
+SmartTagMgr::SmartTagMgr( const rtl::OUString& rApplicationName )
+ : maApplicationName( rApplicationName ),
+ maRecognizerList(),
+ maActionList(),
+ maDisabledSmartTagTypes(),
+ maSmartTagMap(),
+ mxMSF( ::comphelper::getProcessServiceFactory() ),
+ mbLabelTextWithSmartTags(true)
+{
+}
+
+SmartTagMgr::~SmartTagMgr()
+{
+}
+
+void SmartTagMgr::Init( const rtl::OUString& rConfigurationGroupName )
+{
+ // get component context to pass to components:
+ if ( mxMSF.is() )
+ {
+ Reference< beans::XPropertySet > xPropSet = Reference< beans::XPropertySet>( mxMSF, UNO_QUERY);
+ const Any aAny = xPropSet->getPropertyValue( C2U("DefaultContext"));
+ aAny >>= mxContext;
+
+ if ( mxContext.is() )
+ {
+ PrepareConfiguration( rConfigurationGroupName );
+ ReadConfiguration( true, true );
+ RegisterListener();
+ LoadLibraries();
+ }
+ }
+}
+void SmartTagMgr::CreateBreakIterator() const
+{
+ if ( !mxBreakIter.is() && mxMSF.is() && mxContext.is() )
+ {
+ // get the break iterator
+ mxBreakIter.set(mxMSF->createInstance( C2U( "com.sun.star.i18n.BreakIterator" ) ), UNO_QUERY);
+ }
+}
+
+/** Dispatches the recognize call to all installed smart tag recognizers
+*/
+void SmartTagMgr::Recognize( const rtl::OUString& rText,
+ const Reference< text::XTextMarkup > xMarkup,
+ const Reference< frame::XController > xController,
+ const lang::Locale& rLocale,
+ sal_uInt32 nStart, sal_uInt32 nLen ) const
+{
+ for ( sal_uInt32 i = 0; i < maRecognizerList.size(); i++ )
+ {
+ Reference < smarttags::XSmartTagRecognizer > xRecognizer = maRecognizerList[i];
+
+ // if all smart tag types supported by this recognizer have been
+ // disabled, we do not have to call the recognizer:
+ bool bCallRecognizer = false;
+ const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
+ for ( sal_uInt32 j = 0; j < nSmartTagCount && !bCallRecognizer; ++j )
+ {
+ const rtl::OUString aSmartTagName = xRecognizer->getSmartTagName(j);
+ if ( IsSmartTagTypeEnabled( aSmartTagName ) )
+ bCallRecognizer = true;
+ }
+
+ if ( bCallRecognizer )
+ {
+ CreateBreakIterator();
+ maRecognizerList[i]->recognize( rText, nStart, nLen,
+ smarttags::SmartTagRecognizerMode_PARAGRAPH,
+ rLocale, xMarkup, maApplicationName, xController,
+ mxBreakIter );
+ }
+ }
+}
+
+typedef std::multimap < rtl::OUString, ActionReference >::const_iterator SmartTagMapIter;
+
+void SmartTagMgr::GetActionSequences( Sequence < rtl::OUString >& rSmartTagTypes,
+ Sequence < Sequence< Reference< smarttags::XSmartTagAction > > >& rActionComponentsSequence,
+ Sequence < Sequence< sal_Int32 > >& rActionIndicesSequence ) const
+{
+ rActionComponentsSequence.realloc( rSmartTagTypes.getLength() );
+ rActionIndicesSequence.realloc( rSmartTagTypes.getLength() );
+
+ for ( USHORT j = 0; j < rSmartTagTypes.getLength(); ++j )
+ {
+ const rtl::OUString& rSmartTagType = rSmartTagTypes[j];
+
+ const sal_Int32 nNumberOfActionRefs = maSmartTagMap.count( rSmartTagType );
+
+ Sequence< Reference< smarttags::XSmartTagAction > > aActions( nNumberOfActionRefs );
+ Sequence< sal_Int32 > aIndices( nNumberOfActionRefs );
+
+ USHORT i = 0;
+ SmartTagMapIter aActionsIter;
+ SmartTagMapIter aEnd = maSmartTagMap.upper_bound( rSmartTagType );
+
+ for ( aActionsIter = maSmartTagMap.lower_bound( rSmartTagType ); aActionsIter != aEnd; ++aActionsIter )
+ {
+ aActions[ i ] = (*aActionsIter).second.mxSmartTagAction;
+ aIndices[ i++ ] = (*aActionsIter).second.mnSmartTagIndex;
+ }
+
+ rActionComponentsSequence[ j ] = aActions;
+ rActionIndicesSequence[ j ] = aIndices;
+ }
+}
+
+/** Returns the caption for a smart tag type.
+*/
+rtl::OUString SmartTagMgr::GetSmartTagCaption( const rtl::OUString& rSmartTagType, const com::sun::star::lang::Locale& rLocale ) const
+{
+ rtl::OUString aRet;
+
+ SmartTagMapIter aLower = maSmartTagMap.lower_bound( rSmartTagType );
+
+ if ( aLower != maSmartTagMap.end() )
+ {
+ const ActionReference& rActionRef = (*aLower).second;
+ Reference< smarttags::XSmartTagAction > xAction = rActionRef.mxSmartTagAction;
+
+ if ( xAction.is() )
+ {
+ const sal_Int32 nSmartTagIndex = rActionRef.mnSmartTagIndex;
+ aRet = xAction->getSmartTagCaption( nSmartTagIndex, rLocale );
+ }
+ }
+
+ return aRet;
+}
+
+
+/** Returns true if the given smart tag type is enabled.
+*/
+bool SmartTagMgr::IsSmartTagTypeEnabled( const rtl::OUString& rSmartTagType ) const
+{
+ return maDisabledSmartTagTypes.end() == maDisabledSmartTagTypes.find( rSmartTagType );
+}
+
+/** Writes currently disabled smart tag types to configuration.
+*/
+void SmartTagMgr::WriteConfiguration( const bool* pIsLabelTextWithSmartTags,
+ const std::vector< rtl::OUString >* pDisabledTypes ) const
+{
+ if ( mxConfigurationSettings.is() )
+ {
+ bool bCommit = false;
+
+ if ( pIsLabelTextWithSmartTags )
+ {
+ const Any aEnabled = makeAny( *pIsLabelTextWithSmartTags );
+
+ try
+ {
+ mxConfigurationSettings->setPropertyValue( C2U("RecognizeSmartTags"), aEnabled );
+ bCommit = true;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+
+ if ( pDisabledTypes )
+ {
+ const sal_Int32 nNumberOfDisabledSmartTagTypes = pDisabledTypes->size();
+ Sequence< rtl::OUString > aTypes( nNumberOfDisabledSmartTagTypes );
+
+ std::vector< rtl::OUString >::const_iterator aIter;
+ sal_Int32 nCount = 0;
+ for ( aIter = pDisabledTypes->begin(); aIter != pDisabledTypes->end(); ++aIter )
+ aTypes[ nCount++ ] = *aIter;
+
+ const Any aNewTypes = makeAny( aTypes );
+
+ try
+ {
+ mxConfigurationSettings->setPropertyValue( C2U("ExcludedSmartTagTypes"), aNewTypes );
+ bCommit = true;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+
+ if ( bCommit )
+ {
+ try
+ {
+ Reference< util::XChangesBatch >( mxConfigurationSettings, UNO_QUERY_THROW )->commitChanges();
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+ }
+}
+
+// ::com::sun::star::util::XModifyListener
+void SmartTagMgr::modified( const lang::EventObject& ) throw( RuntimeException )
+{
+ vos::OGuard aGuard(Application::GetSolarMutex());
+
+ maRecognizerList.clear();
+ maActionList.clear();
+ maSmartTagMap.clear();
+
+ LoadLibraries();
+}
+
+// ::com::sun::star::lang::XEventListener
+void SmartTagMgr::disposing( const lang::EventObject& rEvent ) throw( RuntimeException )
+{
+ vos::OGuard aGuard(Application::GetSolarMutex());
+
+ uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY );
+ uno::Reference< util::XModifyBroadcaster > xMB(xModel, uno::UNO_QUERY);
+ uno::Reference< util::XChangesNotifier > xCN(xModel, uno::UNO_QUERY);
+
+ try
+ {
+ if( xMB.is() )
+ {
+ uno::Reference< util::XModifyListener > xListener( this );
+ xMB->removeModifyListener( xListener );
+ }
+ else if ( xCN.is() )
+ {
+ uno::Reference< util::XChangesListener > xListener( this );
+ xCN->removeChangesListener( xListener );
+ }
+ }
+ catch(Exception& )
+ {
+ }
+}
+
+// ::com::sun::star::util::XChangesListener
+void SmartTagMgr::changesOccurred( const util::ChangesEvent& rEvent ) throw( RuntimeException)
+{
+ vos::OGuard aGuard(Application::GetSolarMutex());
+
+ const util::ElementChange* pElementChanges = rEvent.Changes.getConstArray();
+ const sal_Int32 nNumberOfChanges = rEvent.Changes.getLength();
+ bool bExcludedTypes = false;
+ bool bRecognize = false;
+
+ for( sal_Int32 i = 0; i < nNumberOfChanges; ++i)
+ {
+ rtl::OUString sTemp;
+ pElementChanges[i].Accessor >>= sTemp;
+
+ if ( sTemp == C2U( "ExcludedSmartTagTypes" ) )
+ bExcludedTypes = true;
+ else if ( sTemp == C2U( "RecognizeSmartTags" ) )
+ bRecognize = true;
+ }
+
+ ReadConfiguration( bExcludedTypes, bRecognize );
+}
+
+//------------- PRIVATE -----------------------------------------------
+
+/**
+*/
+void SmartTagMgr::LoadLibraries()
+{
+ Reference< container::XContentEnumerationAccess > rContent( mxMSF , UNO_QUERY );
+ if ( !rContent.is() )
+ return;
+
+ // load recognizers: No recognizers -> nothing to do.
+ Reference < container::XEnumeration > rEnum = rContent->createContentEnumeration( C2U("com.sun.star.smarttags.SmartTagRecognizer"));
+ if ( !rEnum.is() || !rEnum->hasMoreElements() )
+ return;
+
+ // iterate over all implementations of the smart tag recognizer service:
+ while( rEnum->hasMoreElements())
+ {
+ const Any a = rEnum->nextElement();
+ Reference< lang::XSingleComponentFactory > xSCF;
+ Reference< lang::XServiceInfo > xsInfo;
+
+ if (a >>= xsInfo)
+ xSCF = Reference< lang::XSingleComponentFactory >(xsInfo, UNO_QUERY);
+ else
+ continue;
+
+ Reference< smarttags::XSmartTagRecognizer > xLib ( xSCF->
+ createInstanceWithContext(mxContext), UNO_QUERY );
+
+ if (!xLib.is())
+ continue;
+
+ xLib->initialize( Sequence< Any >() );
+ maRecognizerList.push_back(xLib);
+ }
+
+ // load actions: No actions -> nothing to do.
+ rEnum = rContent->createContentEnumeration( C2U("com.sun.star.smarttags.SmartTagAction"));
+ if ( !rEnum.is() )
+ return;
+
+ // iterate over all implementations of the smart tag action service:
+ while( rEnum->hasMoreElements())
+ {
+ const Any a = rEnum->nextElement();
+ Reference< lang::XServiceInfo > xsInfo;
+ Reference< lang::XSingleComponentFactory > xSCF;
+
+ if (a >>= xsInfo)
+ xSCF = Reference< lang::XSingleComponentFactory >(xsInfo, UNO_QUERY);
+ else
+ continue;
+
+ Reference< smarttags::XSmartTagAction > xLib ( xSCF->
+ createInstanceWithContext(mxContext), UNO_QUERY );
+
+ if (!xLib.is())
+ continue;
+
+ xLib->initialize( Sequence< Any >() );
+ maActionList.push_back(xLib);
+ }
+
+ AssociateActionsWithRecognizers();
+
+}
+
+/**
+*/
+void SmartTagMgr::PrepareConfiguration( const rtl::OUString& rConfigurationGroupName )
+{
+ Any aAny = makeAny( C2U( "/org.openoffice.Office.Common/SmartTags/" ) + rConfigurationGroupName );
+ beans::PropertyValue aPathArgument;
+ aPathArgument.Name = C2U( "nodepath" );
+ aPathArgument.Value = aAny;
+ Sequence< Any > aArguments( 1 );
+ aArguments[ 0 ] <<= aPathArgument;
+ Reference< lang::XMultiServiceFactory > xConfProv( mxMSF->createInstance(C2U ("com.sun.star.configuration.ConfigurationProvider")), UNO_QUERY );
+
+ if ( !xConfProv.is() )
+ return;
+
+ // try to get read-write access to configuration:
+ Reference< XInterface > xConfigurationAccess;
+ try
+ {
+ xConfigurationAccess = xConfProv->createInstanceWithArguments(
+ C2U("com.sun.star.configuration.ConfigurationUpdateAccess" ), aArguments );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ // fallback: try read-only access to configuration:
+ if ( !xConfigurationAccess.is() )
+ {
+ try
+ {
+ xConfigurationAccess = xConfProv->createInstanceWithArguments(
+ C2U("com.sun.star.configuration.ConfigurationAccess" ), aArguments );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+
+ if ( xConfigurationAccess.is() )
+ {
+ mxConfigurationSettings = Reference< beans::XPropertySet >( xConfigurationAccess, UNO_QUERY );
+ }
+}
+
+
+void SmartTagMgr::ReadConfiguration( bool bExcludedTypes, bool bRecognize )
+{
+ if ( mxConfigurationSettings.is() )
+ {
+ if ( bExcludedTypes )
+ {
+ maDisabledSmartTagTypes.clear();
+
+ Any aAny = mxConfigurationSettings->getPropertyValue( C2U("ExcludedSmartTagTypes") );
+ Sequence< rtl::OUString > aValues;
+ aAny >>= aValues;
+
+ const sal_Int32 nValues = aValues.getLength();
+
+ for ( sal_Int32 nI = 0; nI < nValues; ++nI )
+ maDisabledSmartTagTypes.insert( aValues[nI] );
+ }
+
+ if ( bRecognize )
+ {
+ Any aAny = mxConfigurationSettings->getPropertyValue( C2U("RecognizeSmartTags") );
+ sal_Bool bValue = sal_True;
+ aAny >>= bValue;
+
+ mbLabelTextWithSmartTags = bValue;
+ }
+ }
+}
+
+/**
+*/
+void SmartTagMgr::RegisterListener()
+{
+ // register as listener at package manager
+ try
+ {
+ Reference<deployment::XExtensionManager> xExtensionManager(
+ deployment::ExtensionManager::get( mxContext ) );
+ Reference< util::XModifyBroadcaster > xMB ( xExtensionManager, UNO_QUERY_THROW );
+
+ Reference< util::XModifyListener > xListener( this );
+ xMB->addModifyListener( xListener );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ // register as listener at configuration
+ try
+ {
+ Reference<util::XChangesNotifier> xCN( mxConfigurationSettings, UNO_QUERY_THROW );
+ Reference< util::XChangesListener > xListener( this );
+ xCN->addChangesListener( xListener );
+ }
+ catch ( uno::Exception& )
+ {
+ }
+}
+
+typedef std::pair < const rtl::OUString, ActionReference > SmartTagMapElement;
+
+/** Sets up a map that maps smart tag type names to actions references.
+*/
+void SmartTagMgr::AssociateActionsWithRecognizers()
+{
+ const sal_uInt32 nActionLibCount = maActionList.size();
+ const sal_uInt32 nRecognizerCount = maRecognizerList.size();
+
+ for ( sal_uInt32 i = 0; i < nRecognizerCount; ++i )
+ {
+ Reference < smarttags::XSmartTagRecognizer > xRecognizer = maRecognizerList[i];
+ const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
+ for ( sal_uInt32 j = 0; j < nSmartTagCount; ++j )
+ {
+ const rtl::OUString aSmartTagName = xRecognizer->getSmartTagName(j);
+
+ // check if smart tag type has already been processed:
+ if ( maSmartTagMap.find( aSmartTagName ) != maSmartTagMap.end() )
+ continue;
+
+ bool bFound = false;
+ for ( sal_uInt32 k = 0; k < nActionLibCount; ++k )
+ {
+ Reference< smarttags::XSmartTagAction > xActionLib = maActionList[k];
+ const sal_uInt32 nSmartTagCountInActionLib = xActionLib->getSmartTagCount();
+ for ( sal_uInt32 l = 0; l < nSmartTagCountInActionLib; ++l )
+ {
+ const rtl::OUString aSmartTagNameInActionLib = xActionLib->getSmartTagName(l);
+ if ( aSmartTagName.equals( aSmartTagNameInActionLib ) )
+ {
+ // found actions and recognizer for same smarttag
+ ActionReference aActionRef( xActionLib, l );
+
+ // add recognizer/action pair to map
+ maSmartTagMap.insert( SmartTagMapElement( aSmartTagName, aActionRef ));
+
+ bFound = true;
+ }
+ }
+ }
+
+ if ( !bFound )
+ {
+ // insert 'empty' action reference if there is no action associated with
+ // the current smart tag type:
+ Reference< smarttags::XSmartTagAction > xActionLib;
+ ActionReference aActionRef( xActionLib, 0 );
+
+ // add recognizer/action pair to map
+ maSmartTagMap.insert( SmartTagMapElement( aSmartTagName, aActionRef ));
+ }
+ }
+ }
+}
+