xref: /trunk/main/xmloff/source/xforms/xformsapi.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 
31 #include "xformsapi.hxx"
32 
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/xforms/XFormsSupplier.hpp>
38 #include <com/sun/star/xforms/XDataTypeRepository.hpp>
39 #include <com/sun/star/xforms/XModel.hpp>
40 #include <com/sun/star/container/XNameContainer.hpp>
41 #include <com/sun/star/xsd/DataTypeClass.hpp>
42 
43 #include <unotools/processfactory.hxx>
44 #include <tools/debug.hxx>
45 
46 #include <xmloff/xmltoken.hxx>
47 #include <xmloff/nmspmap.hxx>
48 #include <xmloff/xmlnmspe.hxx>
49 #include <xmloff/xmltkmap.hxx>
50 
51 using rtl::OUString;
52 using com::sun::star::uno::Reference;
53 using com::sun::star::uno::Sequence;
54 using com::sun::star::uno::UNO_QUERY;
55 using com::sun::star::uno::UNO_QUERY_THROW;
56 using com::sun::star::beans::XPropertySet;
57 using com::sun::star::container::XNameAccess;
58 using com::sun::star::lang::XMultiServiceFactory;
59 using com::sun::star::xforms::XFormsSupplier;
60 using com::sun::star::xforms::XDataTypeRepository;
61 using com::sun::star::container::XNameContainer;
62 using utl::getProcessServiceFactory;
63 using com::sun::star::uno::makeAny;
64 using com::sun::star::uno::Any;
65 using com::sun::star::uno::Exception;
66 
67 using namespace com::sun::star;
68 using namespace xmloff::token;
69 
70 Reference<XPropertySet> lcl_createPropertySet( const OUString& rServiceName )
71 {
72     Reference<XMultiServiceFactory> xFactory = getProcessServiceFactory();
73     DBG_ASSERT( xFactory.is(), "can't get service factory" );
74 
75     Reference<XPropertySet> xModel( xFactory->createInstance( rServiceName ),
76                                     UNO_QUERY_THROW );
77     DBG_ASSERT( xModel.is(), "can't create model" );
78 
79     return xModel;
80 }
81 
82 Reference<XPropertySet> lcl_createXFormsModel()
83 {
84     return lcl_createPropertySet( OUSTRING( "com.sun.star.xforms.Model" ) );
85 }
86 
87 Reference<XPropertySet> lcl_createXFormsBinding()
88 {
89     return lcl_createPropertySet( OUSTRING( "com.sun.star.xforms.Binding" ) );
90 }
91 
92 void lcl_addXFormsModel(
93     const Reference<frame::XModel>& xDocument,
94     const Reference<XPropertySet>& xModel )
95 {
96     bool bSuccess = false;
97     try
98     {
99         Reference<XFormsSupplier> xSupplier( xDocument, UNO_QUERY );
100         if( xSupplier.is() )
101         {
102             Reference<XNameContainer> xForms = xSupplier->getXForms();
103             if( xForms.is() )
104             {
105                 OUString sName;
106                 xModel->getPropertyValue( OUSTRING("ID")) >>= sName;
107                 xForms->insertByName( sName, makeAny( xModel ) );
108                 bSuccess = true;
109             }
110         }
111     }
112     catch( const Exception& )
113     {
114         ; // no success!
115     }
116 
117     // TODO: implement proper error handling
118     DBG_ASSERT( bSuccess, "can't import model" );
119 }
120 
121 Reference<XPropertySet> lcl_findXFormsBindingOrSubmission(
122     Reference<frame::XModel>& xDocument,
123     const rtl::OUString& rBindingID,
124     bool bBinding )
125 {
126     // find binding by iterating over all models, and look for the
127     // given binding ID
128 
129     Reference<XPropertySet> xRet;
130     try
131     {
132         // get supplier
133         Reference<XFormsSupplier> xSupplier( xDocument, UNO_QUERY );
134         if( xSupplier.is() )
135         {
136             // get XForms models
137             Reference<XNameContainer> xForms = xSupplier->getXForms();
138             if( xForms.is() )
139             {
140                 // iterate over all models
141                 Sequence<OUString> aNames = xForms->getElementNames();
142                 const OUString* pNames = aNames.getConstArray();
143                 sal_Int32 nNames = aNames.getLength();
144                 for( sal_Int32 n = 0; (n < nNames) && !xRet.is(); n++ )
145                 {
146                     Reference<xforms::XModel> xModel(
147                         xForms->getByName( pNames[n] ), UNO_QUERY );
148                     if( xModel.is() )
149                     {
150                         // ask model for bindings
151                         Reference<XNameAccess> xBindings(
152                             bBinding
153                                 ? xModel->getBindings()
154                                 : xModel->getSubmissions(),
155                             UNO_QUERY_THROW );
156 
157                         // finally, ask binding for name
158                         if( xBindings->hasByName( rBindingID ) )
159                             xRet.set( xBindings->getByName( rBindingID ),
160                                       UNO_QUERY );
161                     }
162                 }
163             }
164         }
165     }
166     catch( const Exception& )
167     {
168         ; // no success!
169     }
170 
171     // TODO: if (!xRet.is()) rImport.SetError(...);
172 
173     return xRet;
174 }
175 
176 Reference<XPropertySet> lcl_findXFormsBinding(
177     Reference<frame::XModel>& xDocument,
178     const rtl::OUString& rBindingID )
179 {
180     return lcl_findXFormsBindingOrSubmission( xDocument, rBindingID, true );
181 }
182 
183 Reference<XPropertySet> lcl_findXFormsSubmission(
184     Reference<frame::XModel>& xDocument,
185     const rtl::OUString& rBindingID )
186 {
187     return lcl_findXFormsBindingOrSubmission( xDocument, rBindingID, false );
188 }
189 
190 void lcl_setValue( Reference<XPropertySet>& xPropertySet,
191                    const OUString& rName,
192                    const Any rAny )
193 {
194     xPropertySet->setPropertyValue( rName, rAny );
195 }
196 
197 
198 Reference<XPropertySet> lcl_getXFormsModel( const Reference<frame::XModel>& xDoc )
199 {
200     Reference<XPropertySet> xRet;
201     try
202     {
203         Reference<XFormsSupplier> xSupplier( xDoc, UNO_QUERY );
204         if( xSupplier.is() )
205         {
206             Reference<XNameContainer> xForms = xSupplier->getXForms();
207             if( xForms.is() )
208             {
209                 Sequence<OUString> aNames = xForms->getElementNames();
210                 if( aNames.getLength() > 0 )
211                     xRet.set( xForms->getByName( aNames[0] ), UNO_QUERY );
212             }
213         }
214     }
215     catch( const Exception& )
216     {
217         ; // no success!
218     }
219 
220     return xRet;
221 }
222 
223 #define TOKEN_MAP_ENTRY(NAMESPACE,TOKEN) { XML_NAMESPACE_##NAMESPACE, xmloff::token::XML_##TOKEN, xmloff::token::XML_##TOKEN }
224 static SvXMLTokenMapEntry aTypes[] =
225 {
226     TOKEN_MAP_ENTRY( XSD, STRING  ),
227     TOKEN_MAP_ENTRY( XSD, DECIMAL ),
228     TOKEN_MAP_ENTRY( XSD, DOUBLE ),
229     TOKEN_MAP_ENTRY( XSD, FLOAT ),
230     TOKEN_MAP_ENTRY( XSD, BOOLEAN ),
231     TOKEN_MAP_ENTRY( XSD, ANYURI ),
232     TOKEN_MAP_ENTRY( XSD, DATETIME_XSD ),
233     TOKEN_MAP_ENTRY( XSD, DATE ),
234     TOKEN_MAP_ENTRY( XSD, TIME ),
235     TOKEN_MAP_ENTRY( XSD, YEAR ),
236     TOKEN_MAP_ENTRY( XSD, MONTH ),
237     TOKEN_MAP_ENTRY( XSD, DAY ),
238     XML_TOKEN_MAP_END
239 };
240 
241 sal_uInt16 lcl_getTypeClass(
242     const Reference<XDataTypeRepository>&
243     #ifdef DBG_UTIL
244     xRepository
245     #endif
246     ,
247     const SvXMLNamespaceMap& rNamespaceMap,
248     const OUString& rXMLName )
249 {
250     // translate name into token for local name
251     OUString sLocalName;
252     sal_uInt16 nPrefix = rNamespaceMap.GetKeyByAttrName(rXMLName, &sLocalName);
253     SvXMLTokenMap aMap( aTypes );
254     sal_uInt16 mnToken = aMap.Get( nPrefix, sLocalName );
255 
256     sal_uInt16 nTypeClass = com::sun::star::xsd::DataTypeClass::STRING;
257     if( mnToken != XML_TOK_UNKNOWN )
258     {
259         // we found an XSD name: then get the proper API name for it
260         DBG_ASSERT( xRepository.is(), "can't find type without repository");
261         switch( mnToken )
262         {
263         case XML_STRING:
264             nTypeClass = com::sun::star::xsd::DataTypeClass::STRING;
265             break;
266         case XML_ANYURI:
267             nTypeClass = com::sun::star::xsd::DataTypeClass::anyURI;
268             break;
269         case XML_DECIMAL:
270             nTypeClass = com::sun::star::xsd::DataTypeClass::DECIMAL;
271             break;
272         case XML_DOUBLE:
273             nTypeClass = com::sun::star::xsd::DataTypeClass::DOUBLE;
274             break;
275         case XML_FLOAT:
276             nTypeClass = com::sun::star::xsd::DataTypeClass::FLOAT;
277             break;
278         case XML_BOOLEAN:
279             nTypeClass = com::sun::star::xsd::DataTypeClass::BOOLEAN;
280             break;
281         case XML_DATETIME_XSD:
282             nTypeClass = com::sun::star::xsd::DataTypeClass::DATETIME;
283             break;
284         case XML_DATE:
285             nTypeClass = com::sun::star::xsd::DataTypeClass::DATE;
286             break;
287         case XML_TIME:
288             nTypeClass = com::sun::star::xsd::DataTypeClass::TIME;
289             break;
290         case XML_YEAR:
291             nTypeClass = com::sun::star::xsd::DataTypeClass::gYear;
292             break;
293         case XML_DAY:
294             nTypeClass = com::sun::star::xsd::DataTypeClass::gDay;
295             break;
296         case XML_MONTH:
297             nTypeClass = com::sun::star::xsd::DataTypeClass::gMonth;
298             break;
299 
300             /* data types not yet supported:
301             nTypeClass = com::sun::star::xsd::DataTypeClass::DURATION;
302             nTypeClass = com::sun::star::xsd::DataTypeClass::gYearMonth;
303             nTypeClass = com::sun::star::xsd::DataTypeClass::gMonthDay;
304             nTypeClass = com::sun::star::xsd::DataTypeClass::hexBinary;
305             nTypeClass = com::sun::star::xsd::DataTypeClass::base64Binary;
306             nTypeClass = com::sun::star::xsd::DataTypeClass::QName;
307             nTypeClass = com::sun::star::xsd::DataTypeClass::NOTATION;
308             */
309         }
310     }
311 
312     return nTypeClass;
313 }
314 
315 
316 rtl::OUString lcl_getTypeName(
317     const Reference<XDataTypeRepository>& xRepository,
318     const SvXMLNamespaceMap& rNamespaceMap,
319     const OUString& rXMLName )
320 {
321     OUString sLocalName;
322     sal_uInt16 nPrefix = rNamespaceMap.GetKeyByAttrName(rXMLName, &sLocalName);
323     SvXMLTokenMap aMap( aTypes );
324     sal_uInt16 mnToken = aMap.Get( nPrefix, sLocalName );
325     return ( mnToken == XML_TOK_UNKNOWN )
326         ? rXMLName
327         : lcl_getBasicTypeName( xRepository, rNamespaceMap, rXMLName );
328 }
329 
330 rtl::OUString lcl_getBasicTypeName(
331     const Reference<XDataTypeRepository>& xRepository,
332     const SvXMLNamespaceMap& rNamespaceMap,
333     const OUString& rXMLName )
334 {
335     OUString sTypeName = rXMLName;
336     try
337     {
338         sTypeName =
339             xRepository->getBasicDataType(
340                 lcl_getTypeClass( xRepository, rNamespaceMap, rXMLName ) )
341             ->getName();
342     }
343     catch( const Exception& )
344     {
345         DBG_ERROR( "exception during type creation" );
346     }
347     return sTypeName;
348 }
349