1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski #ifdef SYSTEM_COINMP
24*b1cdbd2cSJim Jagielski #include <coin/CoinMP.h>
25*b1cdbd2cSJim Jagielski #else
26*b1cdbd2cSJim Jagielski #include <coinmp/CoinMP.h>
27*b1cdbd2cSJim Jagielski #endif
28*b1cdbd2cSJim Jagielski
29*b1cdbd2cSJim Jagielski #include "solver.hxx"
30*b1cdbd2cSJim Jagielski #include "solver.hrc"
31*b1cdbd2cSJim Jagielski
32*b1cdbd2cSJim Jagielski #include <com/sun/star/beans/XPropertySet.hpp>
33*b1cdbd2cSJim Jagielski #include <com/sun/star/container/XIndexAccess.hpp>
34*b1cdbd2cSJim Jagielski #include <com/sun/star/frame/XModel.hpp>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36*b1cdbd2cSJim Jagielski #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
37*b1cdbd2cSJim Jagielski #include <com/sun/star/sheet/XSpreadsheet.hpp>
38*b1cdbd2cSJim Jagielski #include <com/sun/star/table/CellAddress.hpp>
39*b1cdbd2cSJim Jagielski #include <com/sun/star/table/CellRangeAddress.hpp>
40*b1cdbd2cSJim Jagielski #include <com/sun/star/text/XTextRange.hpp>
41*b1cdbd2cSJim Jagielski
42*b1cdbd2cSJim Jagielski #include <rtl/math.hxx>
43*b1cdbd2cSJim Jagielski #include <rtl/ustrbuf.hxx>
44*b1cdbd2cSJim Jagielski #include <cppuhelper/factory.hxx>
45*b1cdbd2cSJim Jagielski #include <vector>
46*b1cdbd2cSJim Jagielski #include <hash_map>
47*b1cdbd2cSJim Jagielski
48*b1cdbd2cSJim Jagielski #include <tools/resmgr.hxx>
49*b1cdbd2cSJim Jagielski
50*b1cdbd2cSJim Jagielski using namespace com::sun::star;
51*b1cdbd2cSJim Jagielski
52*b1cdbd2cSJim Jagielski using ::rtl::OUString;
53*b1cdbd2cSJim Jagielski
54*b1cdbd2cSJim Jagielski #define C2U(constAsciiStr) (::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( constAsciiStr ) ))
55*b1cdbd2cSJim Jagielski
56*b1cdbd2cSJim Jagielski #define STR_NONNEGATIVE "NonNegative"
57*b1cdbd2cSJim Jagielski #define STR_INTEGER "Integer"
58*b1cdbd2cSJim Jagielski #define STR_TIMEOUT "Timeout"
59*b1cdbd2cSJim Jagielski #define STR_EPSILONLEVEL "EpsilonLevel"
60*b1cdbd2cSJim Jagielski #define STR_LIMITBBDEPTH "LimitBBDepth"
61*b1cdbd2cSJim Jagielski
62*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
63*b1cdbd2cSJim Jagielski // Resources from tools are used for translated strings
64*b1cdbd2cSJim Jagielski
65*b1cdbd2cSJim Jagielski static ResMgr* pSolverResMgr = NULL;
66*b1cdbd2cSJim Jagielski
lcl_GetResourceString(sal_uInt32 nId)67*b1cdbd2cSJim Jagielski OUString lcl_GetResourceString( sal_uInt32 nId )
68*b1cdbd2cSJim Jagielski {
69*b1cdbd2cSJim Jagielski if (!pSolverResMgr)
70*b1cdbd2cSJim Jagielski pSolverResMgr = CREATEVERSIONRESMGR( solver );
71*b1cdbd2cSJim Jagielski
72*b1cdbd2cSJim Jagielski return String( ResId( nId, *pSolverResMgr ) );
73*b1cdbd2cSJim Jagielski }
74*b1cdbd2cSJim Jagielski
75*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
76*b1cdbd2cSJim Jagielski
77*b1cdbd2cSJim Jagielski namespace
78*b1cdbd2cSJim Jagielski {
79*b1cdbd2cSJim Jagielski enum
80*b1cdbd2cSJim Jagielski {
81*b1cdbd2cSJim Jagielski PROP_NONNEGATIVE,
82*b1cdbd2cSJim Jagielski PROP_INTEGER,
83*b1cdbd2cSJim Jagielski PROP_TIMEOUT,
84*b1cdbd2cSJim Jagielski PROP_EPSILONLEVEL,
85*b1cdbd2cSJim Jagielski PROP_LIMITBBDEPTH
86*b1cdbd2cSJim Jagielski };
87*b1cdbd2cSJim Jagielski }
88*b1cdbd2cSJim Jagielski
89*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
90*b1cdbd2cSJim Jagielski
91*b1cdbd2cSJim Jagielski // hash map for the coefficients of a dependent cell (objective or constraint)
92*b1cdbd2cSJim Jagielski // The size of each vector is the number of columns (variable cells) plus one, first entry is initial value.
93*b1cdbd2cSJim Jagielski
94*b1cdbd2cSJim Jagielski struct ScSolverCellHash
95*b1cdbd2cSJim Jagielski {
operator ()ScSolverCellHash96*b1cdbd2cSJim Jagielski size_t operator()( const table::CellAddress& rAddress ) const
97*b1cdbd2cSJim Jagielski {
98*b1cdbd2cSJim Jagielski return ( rAddress.Sheet << 24 ) | ( rAddress.Column << 16 ) | rAddress.Row;
99*b1cdbd2cSJim Jagielski }
100*b1cdbd2cSJim Jagielski };
101*b1cdbd2cSJim Jagielski
AddressEqual(const table::CellAddress & rAddr1,const table::CellAddress & rAddr2)102*b1cdbd2cSJim Jagielski inline bool AddressEqual( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 )
103*b1cdbd2cSJim Jagielski {
104*b1cdbd2cSJim Jagielski return rAddr1.Sheet == rAddr2.Sheet && rAddr1.Column == rAddr2.Column && rAddr1.Row == rAddr2.Row;
105*b1cdbd2cSJim Jagielski }
106*b1cdbd2cSJim Jagielski
107*b1cdbd2cSJim Jagielski struct ScSolverCellEqual
108*b1cdbd2cSJim Jagielski {
operator ()ScSolverCellEqual109*b1cdbd2cSJim Jagielski bool operator()( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 ) const
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski return AddressEqual( rAddr1, rAddr2 );
112*b1cdbd2cSJim Jagielski }
113*b1cdbd2cSJim Jagielski };
114*b1cdbd2cSJim Jagielski
115*b1cdbd2cSJim Jagielski typedef std::hash_map< table::CellAddress, std::vector<double>, ScSolverCellHash, ScSolverCellEqual > ScSolverCellHashMap;
116*b1cdbd2cSJim Jagielski
117*b1cdbd2cSJim Jagielski // -----------------------------------------------------------------------
118*b1cdbd2cSJim Jagielski
lcl_GetCell(const uno::Reference<sheet::XSpreadsheetDocument> & xDoc,const table::CellAddress & rPos)119*b1cdbd2cSJim Jagielski uno::Reference<table::XCell> lcl_GetCell( const uno::Reference<sheet::XSpreadsheetDocument>& xDoc,
120*b1cdbd2cSJim Jagielski const table::CellAddress& rPos )
121*b1cdbd2cSJim Jagielski {
122*b1cdbd2cSJim Jagielski uno::Reference<container::XIndexAccess> xSheets( xDoc->getSheets(), uno::UNO_QUERY );
123*b1cdbd2cSJim Jagielski uno::Reference<sheet::XSpreadsheet> xSheet( xSheets->getByIndex( rPos.Sheet ), uno::UNO_QUERY );
124*b1cdbd2cSJim Jagielski return xSheet->getCellByPosition( rPos.Column, rPos.Row );
125*b1cdbd2cSJim Jagielski }
126*b1cdbd2cSJim Jagielski
lcl_SetValue(const uno::Reference<sheet::XSpreadsheetDocument> & xDoc,const table::CellAddress & rPos,double fValue)127*b1cdbd2cSJim Jagielski void lcl_SetValue( const uno::Reference<sheet::XSpreadsheetDocument>& xDoc,
128*b1cdbd2cSJim Jagielski const table::CellAddress& rPos, double fValue )
129*b1cdbd2cSJim Jagielski {
130*b1cdbd2cSJim Jagielski lcl_GetCell( xDoc, rPos )->setValue( fValue );
131*b1cdbd2cSJim Jagielski }
132*b1cdbd2cSJim Jagielski
lcl_GetValue(const uno::Reference<sheet::XSpreadsheetDocument> & xDoc,const table::CellAddress & rPos)133*b1cdbd2cSJim Jagielski double lcl_GetValue( const uno::Reference<sheet::XSpreadsheetDocument>& xDoc,
134*b1cdbd2cSJim Jagielski const table::CellAddress& rPos )
135*b1cdbd2cSJim Jagielski {
136*b1cdbd2cSJim Jagielski return lcl_GetCell( xDoc, rPos )->getValue();
137*b1cdbd2cSJim Jagielski }
138*b1cdbd2cSJim Jagielski
139*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
140*b1cdbd2cSJim Jagielski
SolverComponent(const uno::Reference<uno::XComponentContext> &)141*b1cdbd2cSJim Jagielski SolverComponent::SolverComponent( const uno::Reference<uno::XComponentContext>& /* rSMgr */ ) :
142*b1cdbd2cSJim Jagielski OPropertyContainer( GetBroadcastHelper() ),
143*b1cdbd2cSJim Jagielski mbMaximize( sal_True ),
144*b1cdbd2cSJim Jagielski mbNonNegative( sal_False ),
145*b1cdbd2cSJim Jagielski mbInteger( sal_False ),
146*b1cdbd2cSJim Jagielski mnTimeout( 100 ),
147*b1cdbd2cSJim Jagielski mnEpsilonLevel( 0 ),
148*b1cdbd2cSJim Jagielski mbLimitBBDepth( sal_True ),
149*b1cdbd2cSJim Jagielski mbSuccess( sal_False ),
150*b1cdbd2cSJim Jagielski mfResultValue( 0.0 )
151*b1cdbd2cSJim Jagielski {
152*b1cdbd2cSJim Jagielski // for XPropertySet implementation:
153*b1cdbd2cSJim Jagielski registerProperty( C2U(STR_NONNEGATIVE), PROP_NONNEGATIVE, 0, &mbNonNegative, getCppuType( &mbNonNegative ) );
154*b1cdbd2cSJim Jagielski registerProperty( C2U(STR_INTEGER), PROP_INTEGER, 0, &mbInteger, getCppuType( &mbInteger ) );
155*b1cdbd2cSJim Jagielski registerProperty( C2U(STR_TIMEOUT), PROP_TIMEOUT, 0, &mnTimeout, getCppuType( &mnTimeout ) );
156*b1cdbd2cSJim Jagielski registerProperty( C2U(STR_EPSILONLEVEL), PROP_EPSILONLEVEL, 0, &mnEpsilonLevel, getCppuType( &mnEpsilonLevel ) );
157*b1cdbd2cSJim Jagielski registerProperty( C2U(STR_LIMITBBDEPTH), PROP_LIMITBBDEPTH, 0, &mbLimitBBDepth, getCppuType( &mbLimitBBDepth ) );
158*b1cdbd2cSJim Jagielski }
159*b1cdbd2cSJim Jagielski
~SolverComponent()160*b1cdbd2cSJim Jagielski SolverComponent::~SolverComponent()
161*b1cdbd2cSJim Jagielski {
162*b1cdbd2cSJim Jagielski }
163*b1cdbd2cSJim Jagielski
IMPLEMENT_FORWARD_XINTERFACE2(SolverComponent,SolverComponent_Base,OPropertyContainer)164*b1cdbd2cSJim Jagielski IMPLEMENT_FORWARD_XINTERFACE2( SolverComponent, SolverComponent_Base, OPropertyContainer )
165*b1cdbd2cSJim Jagielski IMPLEMENT_FORWARD_XTYPEPROVIDER2( SolverComponent, SolverComponent_Base, OPropertyContainer )
166*b1cdbd2cSJim Jagielski
167*b1cdbd2cSJim Jagielski cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const
168*b1cdbd2cSJim Jagielski {
169*b1cdbd2cSJim Jagielski uno::Sequence<beans::Property> aProps;
170*b1cdbd2cSJim Jagielski describeProperties( aProps );
171*b1cdbd2cSJim Jagielski return new cppu::OPropertyArrayHelper( aProps );
172*b1cdbd2cSJim Jagielski }
173*b1cdbd2cSJim Jagielski
getInfoHelper()174*b1cdbd2cSJim Jagielski cppu::IPropertyArrayHelper& SAL_CALL SolverComponent::getInfoHelper()
175*b1cdbd2cSJim Jagielski {
176*b1cdbd2cSJim Jagielski return *getArrayHelper();
177*b1cdbd2cSJim Jagielski }
178*b1cdbd2cSJim Jagielski
getPropertySetInfo()179*b1cdbd2cSJim Jagielski uno::Reference<beans::XPropertySetInfo> SAL_CALL SolverComponent::getPropertySetInfo() throw(uno::RuntimeException)
180*b1cdbd2cSJim Jagielski {
181*b1cdbd2cSJim Jagielski return createPropertySetInfo( getInfoHelper() );
182*b1cdbd2cSJim Jagielski }
183*b1cdbd2cSJim Jagielski
184*b1cdbd2cSJim Jagielski // XSolverDescription
185*b1cdbd2cSJim Jagielski
getComponentDescription()186*b1cdbd2cSJim Jagielski OUString SAL_CALL SolverComponent::getComponentDescription() throw (uno::RuntimeException)
187*b1cdbd2cSJim Jagielski {
188*b1cdbd2cSJim Jagielski return lcl_GetResourceString( RID_SOLVER_COMPONENT );
189*b1cdbd2cSJim Jagielski }
190*b1cdbd2cSJim Jagielski
getStatusDescription()191*b1cdbd2cSJim Jagielski OUString SAL_CALL SolverComponent::getStatusDescription() throw (uno::RuntimeException)
192*b1cdbd2cSJim Jagielski {
193*b1cdbd2cSJim Jagielski return maStatus;
194*b1cdbd2cSJim Jagielski }
195*b1cdbd2cSJim Jagielski
getPropertyDescription(const OUString & rPropertyName)196*b1cdbd2cSJim Jagielski OUString SAL_CALL SolverComponent::getPropertyDescription( const OUString& rPropertyName ) throw (uno::RuntimeException)
197*b1cdbd2cSJim Jagielski {
198*b1cdbd2cSJim Jagielski sal_uInt32 nResId = 0;
199*b1cdbd2cSJim Jagielski sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
200*b1cdbd2cSJim Jagielski switch (nHandle)
201*b1cdbd2cSJim Jagielski {
202*b1cdbd2cSJim Jagielski case PROP_NONNEGATIVE:
203*b1cdbd2cSJim Jagielski nResId = RID_PROPERTY_NONNEGATIVE;
204*b1cdbd2cSJim Jagielski break;
205*b1cdbd2cSJim Jagielski case PROP_INTEGER:
206*b1cdbd2cSJim Jagielski nResId = RID_PROPERTY_INTEGER;
207*b1cdbd2cSJim Jagielski break;
208*b1cdbd2cSJim Jagielski case PROP_TIMEOUT:
209*b1cdbd2cSJim Jagielski nResId = RID_PROPERTY_TIMEOUT;
210*b1cdbd2cSJim Jagielski break;
211*b1cdbd2cSJim Jagielski case PROP_EPSILONLEVEL:
212*b1cdbd2cSJim Jagielski nResId = RID_PROPERTY_EPSILONLEVEL;
213*b1cdbd2cSJim Jagielski break;
214*b1cdbd2cSJim Jagielski case PROP_LIMITBBDEPTH:
215*b1cdbd2cSJim Jagielski nResId = RID_PROPERTY_LIMITBBDEPTH;
216*b1cdbd2cSJim Jagielski break;
217*b1cdbd2cSJim Jagielski default:
218*b1cdbd2cSJim Jagielski {
219*b1cdbd2cSJim Jagielski // unknown - leave empty
220*b1cdbd2cSJim Jagielski }
221*b1cdbd2cSJim Jagielski }
222*b1cdbd2cSJim Jagielski OUString aRet;
223*b1cdbd2cSJim Jagielski if ( nResId )
224*b1cdbd2cSJim Jagielski aRet = lcl_GetResourceString( nResId );
225*b1cdbd2cSJim Jagielski return aRet;
226*b1cdbd2cSJim Jagielski }
227*b1cdbd2cSJim Jagielski
228*b1cdbd2cSJim Jagielski // XSolver: settings
229*b1cdbd2cSJim Jagielski
getDocument()230*b1cdbd2cSJim Jagielski uno::Reference<sheet::XSpreadsheetDocument> SAL_CALL SolverComponent::getDocument() throw(uno::RuntimeException)
231*b1cdbd2cSJim Jagielski {
232*b1cdbd2cSJim Jagielski return mxDoc;
233*b1cdbd2cSJim Jagielski }
234*b1cdbd2cSJim Jagielski
setDocument(const uno::Reference<sheet::XSpreadsheetDocument> & _document)235*b1cdbd2cSJim Jagielski void SAL_CALL SolverComponent::setDocument( const uno::Reference<sheet::XSpreadsheetDocument>& _document )
236*b1cdbd2cSJim Jagielski throw(uno::RuntimeException)
237*b1cdbd2cSJim Jagielski {
238*b1cdbd2cSJim Jagielski mxDoc = _document;
239*b1cdbd2cSJim Jagielski }
240*b1cdbd2cSJim Jagielski
getObjective()241*b1cdbd2cSJim Jagielski table::CellAddress SAL_CALL SolverComponent::getObjective() throw(uno::RuntimeException)
242*b1cdbd2cSJim Jagielski {
243*b1cdbd2cSJim Jagielski return maObjective;
244*b1cdbd2cSJim Jagielski }
245*b1cdbd2cSJim Jagielski
setObjective(const table::CellAddress & _objective)246*b1cdbd2cSJim Jagielski void SAL_CALL SolverComponent::setObjective( const table::CellAddress& _objective ) throw(uno::RuntimeException)
247*b1cdbd2cSJim Jagielski {
248*b1cdbd2cSJim Jagielski maObjective = _objective;
249*b1cdbd2cSJim Jagielski }
250*b1cdbd2cSJim Jagielski
getVariables()251*b1cdbd2cSJim Jagielski uno::Sequence<table::CellAddress> SAL_CALL SolverComponent::getVariables() throw(uno::RuntimeException)
252*b1cdbd2cSJim Jagielski {
253*b1cdbd2cSJim Jagielski return maVariables;
254*b1cdbd2cSJim Jagielski }
255*b1cdbd2cSJim Jagielski
setVariables(const uno::Sequence<table::CellAddress> & _variables)256*b1cdbd2cSJim Jagielski void SAL_CALL SolverComponent::setVariables( const uno::Sequence<table::CellAddress>& _variables )
257*b1cdbd2cSJim Jagielski throw(uno::RuntimeException)
258*b1cdbd2cSJim Jagielski {
259*b1cdbd2cSJim Jagielski maVariables = _variables;
260*b1cdbd2cSJim Jagielski }
261*b1cdbd2cSJim Jagielski
getConstraints()262*b1cdbd2cSJim Jagielski uno::Sequence<sheet::SolverConstraint> SAL_CALL SolverComponent::getConstraints() throw(uno::RuntimeException)
263*b1cdbd2cSJim Jagielski {
264*b1cdbd2cSJim Jagielski return maConstraints;
265*b1cdbd2cSJim Jagielski }
266*b1cdbd2cSJim Jagielski
setConstraints(const uno::Sequence<sheet::SolverConstraint> & _constraints)267*b1cdbd2cSJim Jagielski void SAL_CALL SolverComponent::setConstraints( const uno::Sequence<sheet::SolverConstraint>& _constraints )
268*b1cdbd2cSJim Jagielski throw(uno::RuntimeException)
269*b1cdbd2cSJim Jagielski {
270*b1cdbd2cSJim Jagielski maConstraints = _constraints;
271*b1cdbd2cSJim Jagielski }
272*b1cdbd2cSJim Jagielski
getMaximize()273*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL SolverComponent::getMaximize() throw(uno::RuntimeException)
274*b1cdbd2cSJim Jagielski {
275*b1cdbd2cSJim Jagielski return mbMaximize;
276*b1cdbd2cSJim Jagielski }
277*b1cdbd2cSJim Jagielski
setMaximize(sal_Bool _maximize)278*b1cdbd2cSJim Jagielski void SAL_CALL SolverComponent::setMaximize( sal_Bool _maximize ) throw(uno::RuntimeException)
279*b1cdbd2cSJim Jagielski {
280*b1cdbd2cSJim Jagielski mbMaximize = _maximize;
281*b1cdbd2cSJim Jagielski }
282*b1cdbd2cSJim Jagielski
283*b1cdbd2cSJim Jagielski // XSolver: get results
284*b1cdbd2cSJim Jagielski
getSuccess()285*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL SolverComponent::getSuccess() throw(uno::RuntimeException)
286*b1cdbd2cSJim Jagielski {
287*b1cdbd2cSJim Jagielski return mbSuccess;
288*b1cdbd2cSJim Jagielski }
289*b1cdbd2cSJim Jagielski
getResultValue()290*b1cdbd2cSJim Jagielski double SAL_CALL SolverComponent::getResultValue() throw(uno::RuntimeException)
291*b1cdbd2cSJim Jagielski {
292*b1cdbd2cSJim Jagielski return mfResultValue;
293*b1cdbd2cSJim Jagielski }
294*b1cdbd2cSJim Jagielski
getSolution()295*b1cdbd2cSJim Jagielski uno::Sequence<double> SAL_CALL SolverComponent::getSolution() throw(uno::RuntimeException)
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski return maSolution;
298*b1cdbd2cSJim Jagielski }
299*b1cdbd2cSJim Jagielski
300*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
301*b1cdbd2cSJim Jagielski
solve()302*b1cdbd2cSJim Jagielski void SAL_CALL SolverComponent::solve() throw(uno::RuntimeException)
303*b1cdbd2cSJim Jagielski {
304*b1cdbd2cSJim Jagielski uno::Reference<frame::XModel> xModel( mxDoc, uno::UNO_QUERY );
305*b1cdbd2cSJim Jagielski if ( !xModel.is() )
306*b1cdbd2cSJim Jagielski throw uno::RuntimeException();
307*b1cdbd2cSJim Jagielski
308*b1cdbd2cSJim Jagielski maStatus = OUString();
309*b1cdbd2cSJim Jagielski mbSuccess = false;
310*b1cdbd2cSJim Jagielski
311*b1cdbd2cSJim Jagielski xModel->lockControllers();
312*b1cdbd2cSJim Jagielski
313*b1cdbd2cSJim Jagielski // collect variables in vector (?)
314*b1cdbd2cSJim Jagielski
315*b1cdbd2cSJim Jagielski std::vector<table::CellAddress> aVariableCells;
316*b1cdbd2cSJim Jagielski for (sal_Int32 nPos=0; nPos<maVariables.getLength(); nPos++)
317*b1cdbd2cSJim Jagielski aVariableCells.push_back( maVariables[nPos] );
318*b1cdbd2cSJim Jagielski size_t nVariables = aVariableCells.size();
319*b1cdbd2cSJim Jagielski size_t nVar = 0;
320*b1cdbd2cSJim Jagielski
321*b1cdbd2cSJim Jagielski // collect all dependent cells
322*b1cdbd2cSJim Jagielski
323*b1cdbd2cSJim Jagielski ScSolverCellHashMap aCellsHash;
324*b1cdbd2cSJim Jagielski aCellsHash[maObjective].reserve( nVariables + 1 ); // objective function
325*b1cdbd2cSJim Jagielski
326*b1cdbd2cSJim Jagielski for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
327*b1cdbd2cSJim Jagielski {
328*b1cdbd2cSJim Jagielski table::CellAddress aCellAddr = maConstraints[nConstrPos].Left;
329*b1cdbd2cSJim Jagielski aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: left hand side
330*b1cdbd2cSJim Jagielski
331*b1cdbd2cSJim Jagielski if ( maConstraints[nConstrPos].Right >>= aCellAddr )
332*b1cdbd2cSJim Jagielski aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side
333*b1cdbd2cSJim Jagielski }
334*b1cdbd2cSJim Jagielski
335*b1cdbd2cSJim Jagielski // set all variables to zero
336*b1cdbd2cSJim Jagielski //! store old values?
337*b1cdbd2cSJim Jagielski //! use old values as initial values?
338*b1cdbd2cSJim Jagielski std::vector<table::CellAddress>::const_iterator aVarIter;
339*b1cdbd2cSJim Jagielski for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter )
340*b1cdbd2cSJim Jagielski {
341*b1cdbd2cSJim Jagielski lcl_SetValue( mxDoc, *aVarIter, 0.0 );
342*b1cdbd2cSJim Jagielski }
343*b1cdbd2cSJim Jagielski
344*b1cdbd2cSJim Jagielski // read initial values from all dependent cells
345*b1cdbd2cSJim Jagielski ScSolverCellHashMap::iterator aCellsIter;
346*b1cdbd2cSJim Jagielski for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter )
347*b1cdbd2cSJim Jagielski {
348*b1cdbd2cSJim Jagielski double fValue = lcl_GetValue( mxDoc, aCellsIter->first );
349*b1cdbd2cSJim Jagielski aCellsIter->second.push_back( fValue ); // store as first element, as-is
350*b1cdbd2cSJim Jagielski }
351*b1cdbd2cSJim Jagielski
352*b1cdbd2cSJim Jagielski // loop through variables
353*b1cdbd2cSJim Jagielski for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter )
354*b1cdbd2cSJim Jagielski {
355*b1cdbd2cSJim Jagielski lcl_SetValue( mxDoc, *aVarIter, 1.0 ); // set to 1 to examine influence
356*b1cdbd2cSJim Jagielski
357*b1cdbd2cSJim Jagielski // read value change from all dependent cells
358*b1cdbd2cSJim Jagielski for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter )
359*b1cdbd2cSJim Jagielski {
360*b1cdbd2cSJim Jagielski double fChanged = lcl_GetValue( mxDoc, aCellsIter->first );
361*b1cdbd2cSJim Jagielski double fInitial = aCellsIter->second.front();
362*b1cdbd2cSJim Jagielski aCellsIter->second.push_back( fChanged - fInitial );
363*b1cdbd2cSJim Jagielski }
364*b1cdbd2cSJim Jagielski
365*b1cdbd2cSJim Jagielski lcl_SetValue( mxDoc, *aVarIter, 2.0 ); // minimal test for linearity
366*b1cdbd2cSJim Jagielski
367*b1cdbd2cSJim Jagielski for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter )
368*b1cdbd2cSJim Jagielski {
369*b1cdbd2cSJim Jagielski double fInitial = aCellsIter->second.front();
370*b1cdbd2cSJim Jagielski double fCoeff = aCellsIter->second.back(); // last appended: coefficient for this variable
371*b1cdbd2cSJim Jagielski double fTwo = lcl_GetValue( mxDoc, aCellsIter->first );
372*b1cdbd2cSJim Jagielski
373*b1cdbd2cSJim Jagielski bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) ||
374*b1cdbd2cSJim Jagielski rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff );
375*b1cdbd2cSJim Jagielski // second comparison is needed in case fTwo is zero
376*b1cdbd2cSJim Jagielski if ( !bLinear )
377*b1cdbd2cSJim Jagielski maStatus = lcl_GetResourceString( RID_ERROR_NONLINEAR );
378*b1cdbd2cSJim Jagielski }
379*b1cdbd2cSJim Jagielski
380*b1cdbd2cSJim Jagielski lcl_SetValue( mxDoc, *aVarIter, 0.0 ); // set back to zero for examining next variable
381*b1cdbd2cSJim Jagielski }
382*b1cdbd2cSJim Jagielski
383*b1cdbd2cSJim Jagielski xModel->unlockControllers();
384*b1cdbd2cSJim Jagielski
385*b1cdbd2cSJim Jagielski if ( maStatus.getLength() )
386*b1cdbd2cSJim Jagielski return;
387*b1cdbd2cSJim Jagielski
388*b1cdbd2cSJim Jagielski //
389*b1cdbd2cSJim Jagielski // build parameter arrays for CoinMP
390*b1cdbd2cSJim Jagielski //
391*b1cdbd2cSJim Jagielski
392*b1cdbd2cSJim Jagielski // set objective function
393*b1cdbd2cSJim Jagielski
394*b1cdbd2cSJim Jagielski const std::vector<double>& rObjCoeff = aCellsHash[maObjective];
395*b1cdbd2cSJim Jagielski double* pObjectCoeffs = new double[nVariables];
396*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
397*b1cdbd2cSJim Jagielski pObjectCoeffs[nVar] = rObjCoeff[nVar+1];
398*b1cdbd2cSJim Jagielski double nObjectConst = rObjCoeff[0]; // constant term of objective
399*b1cdbd2cSJim Jagielski
400*b1cdbd2cSJim Jagielski // add rows
401*b1cdbd2cSJim Jagielski
402*b1cdbd2cSJim Jagielski size_t nRows = maConstraints.getLength();
403*b1cdbd2cSJim Jagielski size_t nCompSize = nVariables * nRows;
404*b1cdbd2cSJim Jagielski double* pCompMatrix = new double[nCompSize]; // first collect all coefficients, row-wise
405*b1cdbd2cSJim Jagielski for (size_t i=0; i<nCompSize; i++)
406*b1cdbd2cSJim Jagielski pCompMatrix[i] = 0.0;
407*b1cdbd2cSJim Jagielski
408*b1cdbd2cSJim Jagielski double* pRHS = new double[nRows];
409*b1cdbd2cSJim Jagielski char* pRowType = new char[nRows];
410*b1cdbd2cSJim Jagielski for (size_t i=0; i<nRows; i++)
411*b1cdbd2cSJim Jagielski {
412*b1cdbd2cSJim Jagielski pRHS[i] = 0.0;
413*b1cdbd2cSJim Jagielski pRowType[i] = 'N';
414*b1cdbd2cSJim Jagielski }
415*b1cdbd2cSJim Jagielski
416*b1cdbd2cSJim Jagielski for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
417*b1cdbd2cSJim Jagielski {
418*b1cdbd2cSJim Jagielski // integer constraints are set later
419*b1cdbd2cSJim Jagielski sheet::SolverConstraintOperator eOp = maConstraints[nConstrPos].Operator;
420*b1cdbd2cSJim Jagielski if ( eOp == sheet::SolverConstraintOperator_LESS_EQUAL ||
421*b1cdbd2cSJim Jagielski eOp == sheet::SolverConstraintOperator_GREATER_EQUAL ||
422*b1cdbd2cSJim Jagielski eOp == sheet::SolverConstraintOperator_EQUAL )
423*b1cdbd2cSJim Jagielski {
424*b1cdbd2cSJim Jagielski double fDirectValue = 0.0;
425*b1cdbd2cSJim Jagielski bool bRightCell = false;
426*b1cdbd2cSJim Jagielski table::CellAddress aRightAddr;
427*b1cdbd2cSJim Jagielski const uno::Any& rRightAny = maConstraints[nConstrPos].Right;
428*b1cdbd2cSJim Jagielski if ( rRightAny >>= aRightAddr )
429*b1cdbd2cSJim Jagielski bRightCell = true; // cell specified as right-hand side
430*b1cdbd2cSJim Jagielski else
431*b1cdbd2cSJim Jagielski rRightAny >>= fDirectValue; // constant value
432*b1cdbd2cSJim Jagielski
433*b1cdbd2cSJim Jagielski table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left;
434*b1cdbd2cSJim Jagielski
435*b1cdbd2cSJim Jagielski const std::vector<double>& rLeftCoeff = aCellsHash[aLeftAddr];
436*b1cdbd2cSJim Jagielski double* pValues = &pCompMatrix[nConstrPos * nVariables];
437*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
438*b1cdbd2cSJim Jagielski pValues[nVar] = rLeftCoeff[nVar+1];
439*b1cdbd2cSJim Jagielski
440*b1cdbd2cSJim Jagielski // if left hand cell has a constant term, put into rhs value
441*b1cdbd2cSJim Jagielski double fRightValue = -rLeftCoeff[0];
442*b1cdbd2cSJim Jagielski
443*b1cdbd2cSJim Jagielski if ( bRightCell )
444*b1cdbd2cSJim Jagielski {
445*b1cdbd2cSJim Jagielski const std::vector<double>& rRightCoeff = aCellsHash[aRightAddr];
446*b1cdbd2cSJim Jagielski // modify pValues with rhs coefficients
447*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
448*b1cdbd2cSJim Jagielski pValues[nVar] -= rRightCoeff[nVar+1];
449*b1cdbd2cSJim Jagielski
450*b1cdbd2cSJim Jagielski fRightValue += rRightCoeff[0]; // constant term
451*b1cdbd2cSJim Jagielski }
452*b1cdbd2cSJim Jagielski else
453*b1cdbd2cSJim Jagielski fRightValue += fDirectValue;
454*b1cdbd2cSJim Jagielski
455*b1cdbd2cSJim Jagielski switch ( eOp )
456*b1cdbd2cSJim Jagielski {
457*b1cdbd2cSJim Jagielski case sheet::SolverConstraintOperator_LESS_EQUAL: pRowType[nConstrPos] = 'L'; break;
458*b1cdbd2cSJim Jagielski case sheet::SolverConstraintOperator_GREATER_EQUAL: pRowType[nConstrPos] = 'G'; break;
459*b1cdbd2cSJim Jagielski case sheet::SolverConstraintOperator_EQUAL: pRowType[nConstrPos] = 'E'; break;
460*b1cdbd2cSJim Jagielski default:
461*b1cdbd2cSJim Jagielski OSL_ENSURE( false, "unexpected enum type" );
462*b1cdbd2cSJim Jagielski }
463*b1cdbd2cSJim Jagielski pRHS[nConstrPos] = fRightValue;
464*b1cdbd2cSJim Jagielski }
465*b1cdbd2cSJim Jagielski }
466*b1cdbd2cSJim Jagielski
467*b1cdbd2cSJim Jagielski // Find non-zero coefficients, column-wise
468*b1cdbd2cSJim Jagielski
469*b1cdbd2cSJim Jagielski int* pMatrixBegin = new int[nVariables+1];
470*b1cdbd2cSJim Jagielski int* pMatrixCount = new int[nVariables];
471*b1cdbd2cSJim Jagielski double* pMatrix = new double[nCompSize]; // not always completely used
472*b1cdbd2cSJim Jagielski int* pMatrixIndex = new int[nCompSize];
473*b1cdbd2cSJim Jagielski int nMatrixPos = 0;
474*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
475*b1cdbd2cSJim Jagielski {
476*b1cdbd2cSJim Jagielski int nBegin = nMatrixPos;
477*b1cdbd2cSJim Jagielski for (size_t nRow=0; nRow<nRows; nRow++)
478*b1cdbd2cSJim Jagielski {
479*b1cdbd2cSJim Jagielski double fCoeff = pCompMatrix[ nRow * nVariables + nVar ]; // row-wise
480*b1cdbd2cSJim Jagielski if ( fCoeff != 0.0 )
481*b1cdbd2cSJim Jagielski {
482*b1cdbd2cSJim Jagielski pMatrix[nMatrixPos] = fCoeff;
483*b1cdbd2cSJim Jagielski pMatrixIndex[nMatrixPos] = nRow;
484*b1cdbd2cSJim Jagielski ++nMatrixPos;
485*b1cdbd2cSJim Jagielski }
486*b1cdbd2cSJim Jagielski }
487*b1cdbd2cSJim Jagielski pMatrixBegin[nVar] = nBegin;
488*b1cdbd2cSJim Jagielski pMatrixCount[nVar] = nMatrixPos - nBegin;
489*b1cdbd2cSJim Jagielski }
490*b1cdbd2cSJim Jagielski pMatrixBegin[nVariables] = nMatrixPos;
491*b1cdbd2cSJim Jagielski delete[] pCompMatrix;
492*b1cdbd2cSJim Jagielski pCompMatrix = NULL;
493*b1cdbd2cSJim Jagielski
494*b1cdbd2cSJim Jagielski // apply settings to all variables
495*b1cdbd2cSJim Jagielski
496*b1cdbd2cSJim Jagielski double* pLowerBounds = new double[nVariables];
497*b1cdbd2cSJim Jagielski double* pUpperBounds = new double[nVariables];
498*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
499*b1cdbd2cSJim Jagielski {
500*b1cdbd2cSJim Jagielski pLowerBounds[nVar] = mbNonNegative ? 0.0 : -DBL_MAX;
501*b1cdbd2cSJim Jagielski pUpperBounds[nVar] = DBL_MAX;
502*b1cdbd2cSJim Jagielski
503*b1cdbd2cSJim Jagielski // bounds could possibly be further restricted from single-cell constraints
504*b1cdbd2cSJim Jagielski }
505*b1cdbd2cSJim Jagielski
506*b1cdbd2cSJim Jagielski char* pColType = new char[nVariables];
507*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
508*b1cdbd2cSJim Jagielski pColType[nVar] = mbInteger ? 'I' : 'C';
509*b1cdbd2cSJim Jagielski
510*b1cdbd2cSJim Jagielski // apply single-var integer constraints
511*b1cdbd2cSJim Jagielski
512*b1cdbd2cSJim Jagielski for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
513*b1cdbd2cSJim Jagielski {
514*b1cdbd2cSJim Jagielski sheet::SolverConstraintOperator eOp = maConstraints[nConstrPos].Operator;
515*b1cdbd2cSJim Jagielski if ( eOp == sheet::SolverConstraintOperator_INTEGER ||
516*b1cdbd2cSJim Jagielski eOp == sheet::SolverConstraintOperator_BINARY )
517*b1cdbd2cSJim Jagielski {
518*b1cdbd2cSJim Jagielski table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left;
519*b1cdbd2cSJim Jagielski // find variable index for cell
520*b1cdbd2cSJim Jagielski for (nVar=0; nVar<nVariables; nVar++)
521*b1cdbd2cSJim Jagielski if ( AddressEqual( aVariableCells[nVar], aLeftAddr ) )
522*b1cdbd2cSJim Jagielski {
523*b1cdbd2cSJim Jagielski if ( eOp == sheet::SolverConstraintOperator_INTEGER )
524*b1cdbd2cSJim Jagielski pColType[nVar] = 'I';
525*b1cdbd2cSJim Jagielski else
526*b1cdbd2cSJim Jagielski {
527*b1cdbd2cSJim Jagielski pColType[nVar] = 'B';
528*b1cdbd2cSJim Jagielski pLowerBounds[nVar] = 0.0;
529*b1cdbd2cSJim Jagielski pUpperBounds[nVar] = 1.0;
530*b1cdbd2cSJim Jagielski }
531*b1cdbd2cSJim Jagielski }
532*b1cdbd2cSJim Jagielski }
533*b1cdbd2cSJim Jagielski }
534*b1cdbd2cSJim Jagielski
535*b1cdbd2cSJim Jagielski int nObjectSense = mbMaximize ? SOLV_OBJSENS_MAX : SOLV_OBJSENS_MIN;
536*b1cdbd2cSJim Jagielski
537*b1cdbd2cSJim Jagielski HPROB hProb = CoinCreateProblem("");
538*b1cdbd2cSJim Jagielski int nResult = CoinLoadProblem( hProb, nVariables, nRows, nMatrixPos, 0,
539*b1cdbd2cSJim Jagielski nObjectSense, nObjectConst, pObjectCoeffs,
540*b1cdbd2cSJim Jagielski pLowerBounds, pUpperBounds, pRowType, pRHS, NULL,
541*b1cdbd2cSJim Jagielski pMatrixBegin, pMatrixCount, pMatrixIndex, pMatrix,
542*b1cdbd2cSJim Jagielski NULL, NULL, NULL );
543*b1cdbd2cSJim Jagielski nResult = CoinLoadInteger( hProb, pColType );
544*b1cdbd2cSJim Jagielski
545*b1cdbd2cSJim Jagielski delete[] pColType;
546*b1cdbd2cSJim Jagielski delete[] pMatrixIndex;
547*b1cdbd2cSJim Jagielski delete[] pMatrix;
548*b1cdbd2cSJim Jagielski delete[] pMatrixCount;
549*b1cdbd2cSJim Jagielski delete[] pMatrixBegin;
550*b1cdbd2cSJim Jagielski delete[] pUpperBounds;
551*b1cdbd2cSJim Jagielski delete[] pLowerBounds;
552*b1cdbd2cSJim Jagielski delete[] pRowType;
553*b1cdbd2cSJim Jagielski delete[] pRHS;
554*b1cdbd2cSJim Jagielski delete[] pObjectCoeffs;
555*b1cdbd2cSJim Jagielski
556*b1cdbd2cSJim Jagielski CoinSetRealOption( hProb, COIN_REAL_MAXSECONDS, mnTimeout );
557*b1cdbd2cSJim Jagielski CoinSetRealOption( hProb, COIN_REAL_MIPMAXSEC, mnTimeout );
558*b1cdbd2cSJim Jagielski
559*b1cdbd2cSJim Jagielski // TODO: handle (or remove) settings: epsilon, B&B depth
560*b1cdbd2cSJim Jagielski
561*b1cdbd2cSJim Jagielski // solve model
562*b1cdbd2cSJim Jagielski
563*b1cdbd2cSJim Jagielski nResult = CoinCheckProblem( hProb );
564*b1cdbd2cSJim Jagielski nResult = CoinOptimizeProblem( hProb, 0 );
565*b1cdbd2cSJim Jagielski
566*b1cdbd2cSJim Jagielski mbSuccess = ( nResult == SOLV_CALL_SUCCESS );
567*b1cdbd2cSJim Jagielski if ( mbSuccess )
568*b1cdbd2cSJim Jagielski {
569*b1cdbd2cSJim Jagielski // get solution
570*b1cdbd2cSJim Jagielski
571*b1cdbd2cSJim Jagielski maSolution.realloc( nVariables );
572*b1cdbd2cSJim Jagielski CoinGetSolutionValues( hProb, maSolution.getArray(), NULL, NULL, NULL );
573*b1cdbd2cSJim Jagielski mfResultValue = CoinGetObjectValue( hProb );
574*b1cdbd2cSJim Jagielski }
575*b1cdbd2cSJim Jagielski else
576*b1cdbd2cSJim Jagielski {
577*b1cdbd2cSJim Jagielski int nSolutionStatus = CoinGetSolutionStatus( hProb );
578*b1cdbd2cSJim Jagielski if ( nSolutionStatus == 1 )
579*b1cdbd2cSJim Jagielski maStatus = lcl_GetResourceString( RID_ERROR_INFEASIBLE );
580*b1cdbd2cSJim Jagielski else if ( nSolutionStatus == 2 )
581*b1cdbd2cSJim Jagielski maStatus = lcl_GetResourceString( RID_ERROR_UNBOUNDED );
582*b1cdbd2cSJim Jagielski // TODO: detect timeout condition and report as RID_ERROR_TIMEOUT
583*b1cdbd2cSJim Jagielski // (currently reported as infeasible)
584*b1cdbd2cSJim Jagielski }
585*b1cdbd2cSJim Jagielski
586*b1cdbd2cSJim Jagielski CoinUnloadProblem( hProb );
587*b1cdbd2cSJim Jagielski }
588*b1cdbd2cSJim Jagielski
589*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
590*b1cdbd2cSJim Jagielski
591*b1cdbd2cSJim Jagielski // XServiceInfo
592*b1cdbd2cSJim Jagielski
SolverComponent_getSupportedServiceNames()593*b1cdbd2cSJim Jagielski uno::Sequence< OUString > SolverComponent_getSupportedServiceNames()
594*b1cdbd2cSJim Jagielski {
595*b1cdbd2cSJim Jagielski uno::Sequence< OUString > aServiceNames( 1 );
596*b1cdbd2cSJim Jagielski aServiceNames[ 0 ] = OUString::createFromAscii( "com.sun.star.sheet.Solver" );
597*b1cdbd2cSJim Jagielski return aServiceNames;
598*b1cdbd2cSJim Jagielski }
599*b1cdbd2cSJim Jagielski
SolverComponent_getImplementationName()600*b1cdbd2cSJim Jagielski OUString SolverComponent_getImplementationName()
601*b1cdbd2cSJim Jagielski {
602*b1cdbd2cSJim Jagielski return OUString::createFromAscii( "com.sun.star.comp.Calc.Solver" );
603*b1cdbd2cSJim Jagielski }
604*b1cdbd2cSJim Jagielski
getImplementationName()605*b1cdbd2cSJim Jagielski OUString SAL_CALL SolverComponent::getImplementationName() throw(uno::RuntimeException)
606*b1cdbd2cSJim Jagielski {
607*b1cdbd2cSJim Jagielski return SolverComponent_getImplementationName();
608*b1cdbd2cSJim Jagielski }
609*b1cdbd2cSJim Jagielski
supportsService(const OUString & rServiceName)610*b1cdbd2cSJim Jagielski sal_Bool SAL_CALL SolverComponent::supportsService( const OUString& rServiceName ) throw(uno::RuntimeException)
611*b1cdbd2cSJim Jagielski {
612*b1cdbd2cSJim Jagielski const uno::Sequence< OUString > aServices = SolverComponent_getSupportedServiceNames();
613*b1cdbd2cSJim Jagielski const OUString* pArray = aServices.getConstArray();
614*b1cdbd2cSJim Jagielski const OUString* pArrayEnd = pArray + aServices.getLength();
615*b1cdbd2cSJim Jagielski return ::std::find( pArray, pArrayEnd, rServiceName ) != pArrayEnd;
616*b1cdbd2cSJim Jagielski }
617*b1cdbd2cSJim Jagielski
getSupportedServiceNames()618*b1cdbd2cSJim Jagielski uno::Sequence<OUString> SAL_CALL SolverComponent::getSupportedServiceNames() throw(uno::RuntimeException)
619*b1cdbd2cSJim Jagielski {
620*b1cdbd2cSJim Jagielski return SolverComponent_getSupportedServiceNames();
621*b1cdbd2cSJim Jagielski }
622*b1cdbd2cSJim Jagielski
SolverComponent_createInstance(const uno::Reference<uno::XComponentContext> & rSMgr)623*b1cdbd2cSJim Jagielski uno::Reference<uno::XInterface> SolverComponent_createInstance( const uno::Reference<uno::XComponentContext>& rSMgr )
624*b1cdbd2cSJim Jagielski throw(uno::Exception)
625*b1cdbd2cSJim Jagielski {
626*b1cdbd2cSJim Jagielski return (cppu::OWeakObject*) new SolverComponent( rSMgr );
627*b1cdbd2cSJim Jagielski }
628*b1cdbd2cSJim Jagielski
629*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
630*b1cdbd2cSJim Jagielski
631*b1cdbd2cSJim Jagielski extern "C"
632*b1cdbd2cSJim Jagielski {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)633*b1cdbd2cSJim Jagielski SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(
634*b1cdbd2cSJim Jagielski const sal_Char ** ppEnvTypeName, uno_Environment ** )
635*b1cdbd2cSJim Jagielski {
636*b1cdbd2cSJim Jagielski *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
637*b1cdbd2cSJim Jagielski }
638*b1cdbd2cSJim Jagielski
639*b1cdbd2cSJim Jagielski // -------------------------------------------------------------------------
640*b1cdbd2cSJim Jagielski
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void *)641*b1cdbd2cSJim Jagielski SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
642*b1cdbd2cSJim Jagielski {
643*b1cdbd2cSJim Jagielski OUString aImplName( OUString::createFromAscii( pImplName ) );
644*b1cdbd2cSJim Jagielski void* pRet = 0;
645*b1cdbd2cSJim Jagielski
646*b1cdbd2cSJim Jagielski if( pServiceManager )
647*b1cdbd2cSJim Jagielski {
648*b1cdbd2cSJim Jagielski uno::Reference< lang::XSingleComponentFactory > xFactory;
649*b1cdbd2cSJim Jagielski if( aImplName.equals( SolverComponent_getImplementationName() ) )
650*b1cdbd2cSJim Jagielski xFactory = cppu::createSingleComponentFactory(
651*b1cdbd2cSJim Jagielski SolverComponent_createInstance,
652*b1cdbd2cSJim Jagielski OUString::createFromAscii( pImplName ),
653*b1cdbd2cSJim Jagielski SolverComponent_getSupportedServiceNames() );
654*b1cdbd2cSJim Jagielski
655*b1cdbd2cSJim Jagielski if( xFactory.is() )
656*b1cdbd2cSJim Jagielski {
657*b1cdbd2cSJim Jagielski xFactory->acquire();
658*b1cdbd2cSJim Jagielski pRet = xFactory.get();
659*b1cdbd2cSJim Jagielski }
660*b1cdbd2cSJim Jagielski }
661*b1cdbd2cSJim Jagielski return pRet;
662*b1cdbd2cSJim Jagielski }
663*b1cdbd2cSJim Jagielski }
664*b1cdbd2cSJim Jagielski
665