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 "XFormsBindContext.hxx"
28 
29 #include "xformsapi.hxx"
30 
31 #include <xmloff/xmlimp.hxx>
32 #include "xmloff/xmlerror.hxx"
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/xmltkmap.hxx>
35 #include "xmloff/xmlnmspe.hxx"
36 #include <xmloff/nmspmap.hxx>
37 
38 #include <com/sun/star/container/XNameContainer.hpp>
39 #include <com/sun/star/xforms/XModel.hpp>
40 
41 #include <tools/debug.hxx>
42 
43 using rtl::OUString;
44 using com::sun::star::beans::XPropertySet;
45 using com::sun::star::uno::Reference;
46 using com::sun::star::uno::makeAny;
47 using com::sun::star::uno::UNO_QUERY;
48 using com::sun::star::uno::UNO_QUERY_THROW;
49 using com::sun::star::container::XNameContainer;
50 using com::sun::star::xml::sax::XAttributeList;
51 using com::sun::star::xforms::XModel;
52 using namespace xmloff::token;
53 
54 
55 
56 
57 static struct SvXMLTokenMapEntry aAttributeMap[] =
58 {
59     TOKEN_MAP_ENTRY( NONE, NODESET ),
60     TOKEN_MAP_ENTRY( NONE, ID ),
61     TOKEN_MAP_ENTRY( NONE, READONLY ),
62     TOKEN_MAP_ENTRY( NONE, RELEVANT ),
63     TOKEN_MAP_ENTRY( NONE, REQUIRED ),
64     TOKEN_MAP_ENTRY( NONE, CONSTRAINT ),
65     TOKEN_MAP_ENTRY( NONE, CALCULATE ),
66     TOKEN_MAP_ENTRY( NONE, TYPE ),
67     XML_TOKEN_MAP_END
68 };
69 
70 // helper function; see below
71 void lcl_fillNamespaceContainer( const SvXMLNamespaceMap&,
72                                  Reference<XNameContainer>& );
73 
XFormsBindContext(SvXMLImport & rImport,sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<XPropertySet> & xModel)74 XFormsBindContext::XFormsBindContext(
75     SvXMLImport& rImport,
76     sal_uInt16 nPrefix,
77     const OUString& rLocalName,
78     const Reference<XPropertySet>& xModel ) :
79         TokenContext( rImport, nPrefix, rLocalName, aAttributeMap, aEmptyMap ),
80         mxModel( xModel, UNO_QUERY_THROW ),
81         mxBinding( NULL )
82 {
83     // attach binding to model
84     mxBinding = mxModel->createBinding();
85     DBG_ASSERT( mxBinding.is(), "can't create binding" );
86     mxModel->getBindings()->insert( makeAny( mxBinding ) );
87 }
88 
~XFormsBindContext()89 XFormsBindContext::~XFormsBindContext()
90 {
91 }
92 
HandleAttribute(sal_uInt16 nToken,const OUString & rValue)93 void XFormsBindContext::HandleAttribute( sal_uInt16 nToken,
94                                          const OUString& rValue )
95 {
96     switch( nToken )
97     {
98     case XML_NODESET:
99         lcl_setValue( mxBinding, OUSTRING("BindingExpression"), rValue );
100         break;
101     case XML_ID:
102         lcl_setValue( mxBinding, OUSTRING("BindingID"), rValue );
103         break;
104     case XML_READONLY:
105         lcl_setValue( mxBinding, OUSTRING("ReadonlyExpression"), rValue );
106         break;
107     case XML_RELEVANT:
108         lcl_setValue( mxBinding, OUSTRING("RelevantExpression"), rValue );
109         break;
110     case XML_REQUIRED:
111         lcl_setValue( mxBinding, OUSTRING("RequiredExpression"), rValue );
112         break;
113     case XML_CONSTRAINT:
114         lcl_setValue( mxBinding, OUSTRING("ConstraintExpression"), rValue );
115         break;
116     case XML_CALCULATE:
117         lcl_setValue( mxBinding, OUSTRING("CalculateExpression"), rValue );
118         break;
119     case XML_TYPE:
120         lcl_setValue( mxBinding, OUSTRING("Type"),
121                       makeAny( lcl_getTypeName( mxModel->getDataTypeRepository(),
122                                        GetImport().GetNamespaceMap(),
123                                        rValue ) ) );
124         break;
125     default:
126         DBG_ERROR( "should not happen" );
127         break;
128     }
129 }
130 
StartElement(const Reference<XAttributeList> & xAttributeList)131 void XFormsBindContext::StartElement(
132     const Reference<XAttributeList>& xAttributeList )
133 {
134     // we need to register the namespaces
135     Reference<XNameContainer> xContainer(
136         mxBinding->getPropertyValue( OUSTRING("BindingNamespaces") ),
137         UNO_QUERY );
138 
139     DBG_ASSERT( xContainer.is(), "binding should have a namespace container" );
140     if( xContainer.is() )
141         lcl_fillNamespaceContainer( GetImport().GetNamespaceMap(), xContainer);
142 
143     // call super-class for attribute handling
144     TokenContext::StartElement( xAttributeList );
145 }
146 
147 /** will be called for each child element */
HandleChild(sal_uInt16,sal_uInt16,const OUString &,const Reference<XAttributeList> &)148 SvXMLImportContext* XFormsBindContext::HandleChild(
149     sal_uInt16,
150     sal_uInt16,
151     const OUString&,
152     const Reference<XAttributeList>& )
153 {
154     DBG_ERROR( "no children supported" );
155     return NULL;
156 }
157 
158 
lcl_fillNamespaceContainer(const SvXMLNamespaceMap & aMap,Reference<XNameContainer> & xContainer)159 void lcl_fillNamespaceContainer(
160     const SvXMLNamespaceMap& aMap,
161     Reference<XNameContainer>& xContainer )
162 {
163     sal_uInt16 nKeyIter = aMap.GetFirstKey();
164     do
165     {
166         // get prefix and namespace
167         const OUString& sPrefix = aMap.GetPrefixByKey( nKeyIter );
168         const OUString& sNamespace = aMap.GetNameByKey( nKeyIter );
169 
170         // as a hack, we will ignore our own 'default' namespaces
171         DBG_ASSERT( sPrefix.getLength() > 0, "no prefix?" );
172         if( sPrefix.getStr()[0] != sal_Unicode( '_' )  &&
173             nKeyIter >= XML_OLD_NAMESPACE_META_IDX )
174         {
175             // insert prefix (use replace if already known)
176             if( xContainer->hasByName( sPrefix ) )
177                 xContainer->replaceByName( sPrefix, makeAny( sNamespace ) );
178             else
179                 xContainer->insertByName( sPrefix, makeAny( sNamespace ) );
180         }
181 
182         // proceed to next
183         nKeyIter = aMap.GetNextKey( nKeyIter );
184     }
185     while( nKeyIter != XML_NAMESPACE_UNKNOWN );
186 }
187