1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include "ChartPlotAreaOOoTContext.hxx"
21 #include "TransformerBase.hxx"
22 #include <xmloff/namespacemap.hxx>
23 #include <xmloff/xmlnamespace.hxx>
24 #include <xmloff/xmltoken.hxx>
25 #include "DeepTContext.hxx"
26 #include "ActionMapTypesOOo.hxx"
27 #include "MutableAttrList.hxx"
28 #include <osl/diagnose.h>
29 
30 using namespace ::com::sun::star;
31 using namespace ::xmloff::token;
32 
33 using ::com::sun::star::uno::Reference;
34 
35 class XMLAxisOOoContext : public XMLPersElemContentTContext
36 {
37 public:
38     XMLAxisOOoContext( XMLTransformerBase& rTransformer,
39                        const OUString& rQName );
40 
41     virtual void StartElement( const Reference< xml::sax::XAttributeList >& rAttrList ) override;
42 
IsCategoryAxis() const43     bool IsCategoryAxis() const { return m_bIsCategoryAxis;}
44 
45 private:
46     bool m_bIsCategoryAxis;
47 };
48 
XMLAxisOOoContext(XMLTransformerBase & rTransformer,const OUString & rQName)49 XMLAxisOOoContext::XMLAxisOOoContext(
50     XMLTransformerBase& rTransformer,
51     const OUString& rQName ) :
52         XMLPersElemContentTContext( rTransformer, rQName ),
53         m_bIsCategoryAxis( false )
54 {}
55 
StartElement(const Reference<xml::sax::XAttributeList> & rAttrList)56 void XMLAxisOOoContext::StartElement(
57     const Reference< xml::sax::XAttributeList >& rAttrList )
58 {
59     Reference< xml::sax::XAttributeList > xAttrList( rAttrList );
60     rtl::Reference<XMLMutableAttributeList> pMutableAttrList;
61     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
62     for( sal_Int16 i=0; i < nAttrCount; i++ )
63     {
64         const OUString& rAttrName = xAttrList->getNameByIndex( i );
65         OUString aLocalName;
66         sal_uInt16 nPrefix =
67             GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName );
68 
69         if( nPrefix == XML_NAMESPACE_CHART &&
70             IsXMLToken( aLocalName, XML_CLASS ) )
71         {
72             if( !pMutableAttrList )
73             {
74                 pMutableAttrList = new XMLMutableAttributeList( xAttrList );
75                 xAttrList = pMutableAttrList;
76             }
77 
78             const OUString& rAttrValue = xAttrList->getValueByIndex( i );
79             XMLTokenEnum eToken = XML_TOKEN_INVALID;
80             if( IsXMLToken( rAttrValue, XML_DOMAIN ) ||
81                 IsXMLToken( rAttrValue, XML_CATEGORY ))
82             {
83                 eToken = XML_X;
84                 if( IsXMLToken( rAttrValue, XML_CATEGORY ) )
85                     m_bIsCategoryAxis = true;
86             }
87             else if( IsXMLToken( rAttrValue, XML_VALUE ))
88             {
89                 eToken = XML_Y;
90             }
91             else if( IsXMLToken( rAttrValue, XML_SERIES ))
92             {
93                 eToken = XML_Z;
94             }
95             else
96             {
97                 OSL_FAIL( "ChartAxis: Invalid attribute value" );
98             }
99 
100             if( eToken != XML_TOKEN_INVALID )
101             {
102                 OUString aNewAttrQName(
103                     GetTransformer().GetNamespaceMap().GetQNameByKey(
104                         XML_NAMESPACE_CHART, GetXMLToken( XML_DIMENSION )));
105                 pMutableAttrList->RenameAttributeByIndex( i, aNewAttrQName );
106                 pMutableAttrList->SetValueByIndex( i, GetXMLToken( eToken ));
107             }
108         }
109     }
110 
111     XMLPersElemContentTContext::StartElement( xAttrList );
112 }
113 
XMLChartPlotAreaOOoTContext(XMLTransformerBase & rTransformer,const OUString & rQName)114 XMLChartPlotAreaOOoTContext::XMLChartPlotAreaOOoTContext(
115     XMLTransformerBase & rTransformer, const OUString & rQName ) :
116         XMLProcAttrTransformerContext( rTransformer, rQName, OOO_SHAPE_ACTIONS )
117 {
118 }
119 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const OUString & rQName,const uno::Reference<xml::sax::XAttributeList> & xAttrList)120 rtl::Reference<XMLTransformerContext> XMLChartPlotAreaOOoTContext::CreateChildContext(
121     sal_uInt16 nPrefix,
122     const OUString& rLocalName,
123     const OUString& rQName,
124     const uno::Reference< xml::sax::XAttributeList >& xAttrList )
125 {
126     rtl::Reference<XMLTransformerContext> pContext;
127 
128     if( XML_NAMESPACE_CHART == nPrefix &&
129         IsXMLToken( rLocalName, XML_AXIS ) )
130     {
131         rtl::Reference<XMLAxisOOoContext> pAxisContext( new XMLAxisOOoContext( GetTransformer(), rQName ));
132         AddContent( pAxisContext );
133         pContext = pAxisContext;
134     }
135     else if( XML_NAMESPACE_CHART == nPrefix &&
136              IsXMLToken( rLocalName, XML_CATEGORIES ) )
137     {
138         pContext.set(new XMLPersAttrListTContext( GetTransformer(), rQName ));
139 
140         // put categories at correct axis
141         bool bFound =false;
142 
143         // iterate over axis elements
144         for( const auto& rChildContext : m_aChildContexts )
145         {
146             XMLAxisOOoContext * pAxisContext = rChildContext.get();
147             if( pAxisContext != nullptr )
148             {
149                 // iterate over attributes to find category axis
150                 Reference< xml::sax::XAttributeList > xNewAttrList( pAxisContext->GetAttrList());
151                 sal_Int16 nAttrCount = xNewAttrList.is() ? xNewAttrList->getLength() : 0;
152 
153                 for( sal_Int16 i=0; i < nAttrCount; i++ )
154                 {
155                     const OUString & rAttrName = xNewAttrList->getNameByIndex( i );
156                     OUString aLocalName;
157                     sal_uInt16 nNewPrefix =
158                         GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
159                                                                              &aLocalName );
160                     if( nNewPrefix == XML_NAMESPACE_CHART &&
161                         pAxisContext->IsCategoryAxis() &&
162                         IsXMLToken( aLocalName, XML_DIMENSION ) )
163                     {
164                         // category axis found
165                         pAxisContext->AddContent( pContext );
166                         bFound = true;
167                         break;
168                     }
169                 }
170             }
171 
172             if (bFound)
173                 break;
174         }
175         OSL_ENSURE( bFound, "No suitable axis for categories found." );
176     }
177     else
178     {
179         ExportContent();
180         pContext =  XMLProcAttrTransformerContext::CreateChildContext(
181             nPrefix, rLocalName, rQName, xAttrList );
182     }
183 
184     return pContext;
185 }
186 
EndElement()187 void XMLChartPlotAreaOOoTContext::EndElement()
188 {
189     ExportContent();
190     XMLProcAttrTransformerContext::EndElement();
191 }
192 
AddContent(rtl::Reference<XMLAxisOOoContext> const & pContext)193 void XMLChartPlotAreaOOoTContext::AddContent(rtl::Reference<XMLAxisOOoContext> const & pContext)
194 {
195     OSL_ENSURE( pContext.is() && pContext->IsPersistent(),
196                 "non-persistent context" );
197     m_aChildContexts.push_back(pContext);
198 }
199 
200 
ExportContent()201 void XMLChartPlotAreaOOoTContext::ExportContent()
202 {
203     for( auto& rChildContext : m_aChildContexts )
204     {
205         rChildContext->Export();
206     }
207 
208     m_aChildContexts.clear();
209 }
210 
211 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
212