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