xref: /aoo4110/main/sccomp/source/solver/solver.cxx (revision b1cdbd2c)
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