LibreOffice Module xmloff (master)  1
XMLEventExport.cxx
Go to the documentation of this file.
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 
21 
22 #include <com/sun/star/beans/PropertyValue.hpp>
23 
24 #include <com/sun/star/document/XEventsSupplier.hpp>
25 
26 #include <com/sun/star/container/XNameReplace.hpp>
27 #include <sal/log.hxx>
28 #include <osl/diagnose.h>
29 #include <xmloff/xmlexp.hxx>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmlnamespace.hxx>
32 #include <xmloff/namespacemap.hxx>
33 
34 
35 using namespace ::com::sun::star::uno;
36 
37 using ::com::sun::star::beans::PropertyValue;
38 using ::com::sun::star::document::XEventsSupplier;
39 using ::com::sun::star::container::XNameReplace;
40 using ::com::sun::star::container::XNameAccess;
42 
43 constexpr OUStringLiteral gsEventType(u"EventType");
44 
46  rExport(rExp),
47  bExtNamespace(false)
48 {
49 }
50 
52 {
53  // delete all handlers
54  aHandlerMap.clear();
55 }
56 
57 void XMLEventExport::AddHandler( const OUString& rName,
58  std::unique_ptr<XMLEventExportHandler> pHandler )
59 {
60  assert(pHandler);
61  aHandlerMap[rName] = std::move(pHandler);
62 }
63 
65  const XMLEventNameTranslation* pTransTable )
66 {
67  if (nullptr != pTransTable)
68  {
69  // put translation table into map
70  for(const XMLEventNameTranslation* pTrans = pTransTable;
71  pTrans->sAPIName != nullptr;
72  pTrans++)
73  {
74  aNameTranslationMap[OUString::createFromAscii(pTrans->sAPIName)] =
75  XMLEventName(pTrans->nPrefix, pTrans->sXMLName);
76  }
77  }
78  // else? ignore!
79 }
80 
81 void XMLEventExport::Export( Reference<XEventsSupplier> const & rSupplier,
82  bool bWhitespace)
83 {
84  if (rSupplier.is())
85  {
86  Export(rSupplier->getEvents(), bWhitespace);
87  }
88  // else: no supplier, no export -> ignore!
89 }
90 
91 void XMLEventExport::Export( Reference<XNameReplace> const & rReplace,
92  bool bWhitespace)
93 {
94  Reference<XNameAccess> xAccess(rReplace);
95  Export(xAccess, bWhitespace);
96 }
97 
99  bool bWhitespace)
100 {
101  // early out if we don't actually get any events
102  if (!rAccess.is())
103  {
104  return;
105  }
106 
107  // have we already processed an element?
108  bool bStarted = false;
109 
110  // iterate over all event types
111  const Sequence<OUString> aNames = rAccess->getElementNames();
112  for(const auto& rName : aNames)
113  {
114  // translate name
115  NameMap::iterator aIter = aNameTranslationMap.find(rName);
116  if (aIter != aNameTranslationMap.end())
117  {
118  const XMLEventName& rXmlName = aIter->second;
119 
120  // get PropertyValues for this event
121  Any aAny = rAccess->getByName( rName );
122  Sequence<PropertyValue> aValues;
123  aAny >>= aValues;
124 
125  // now export the current event
126  ExportEvent( aValues, rXmlName, bWhitespace, bStarted );
127  }
128  else
129  {
130  // don't proceed further
131  SAL_WARN("xmloff", "Unknown event name:" << rName );
132  }
133  }
134 
135  // close <script:events> element (if it was opened before)
136  if (bStarted)
137  {
138  EndElement(bWhitespace);
139  }
140 }
141 
143 {
144  // set bExtNamespace flag to use XML_NAMESPACE_OFFICE_EXT namespace
145  // for events element (not for child elements)
146  bExtNamespace = true;
147  Export(rAccess);
148  bExtNamespace = false; // reset for future Export calls
149 }
150 
153  Sequence<PropertyValue>& rEventValues,
154  const OUString& rApiEventName,
155  bool bUseWhitespace )
156 {
157  // translate the name
158  NameMap::iterator aIter = aNameTranslationMap.find(rApiEventName);
159  if (aIter != aNameTranslationMap.end())
160  {
161  const XMLEventName& rXmlName = aIter->second;
162 
163  // export the event ...
164  bool bStarted = false;
165  ExportEvent( rEventValues, rXmlName, bUseWhitespace, bStarted );
166 
167  // ... and close the container element (if necessary)
168  if (bStarted)
169  {
170  EndElement(bUseWhitespace);
171  }
172  }
173  else
174  {
175  // don't proceed further
176  SAL_WARN("xmloff", "Unknown event name:" << rApiEventName );
177  }
178 }
179 
180 
183  Sequence<PropertyValue>& rEventValues,
184  const XMLEventName& rXmlEventName,
185  bool bUseWhitespace,
186  bool& rExported )
187 {
188  // search for EventType value and then delegate to EventHandler
189  const PropertyValue* pValue = std::find_if(rEventValues.begin(), rEventValues.end(),
190  [](const PropertyValue& rValue) { return gsEventType == rValue.Name; });
191 
192  if (pValue == rEventValues.end())
193  return;
194 
195  // found! Now find handler and delegate
196  OUString sType;
197  pValue->Value >>= sType;
198 
199  if (aHandlerMap.count(sType))
200  {
201  if (! rExported)
202  {
203  // OK, we have't yet exported the enclosing
204  // element. So we do that now.
205  rExported = true;
206  StartElement(bUseWhitespace);
207  }
208 
209  OUString aEventQName(
211  rXmlEventName.m_nPrefix, rXmlEventName.m_aName ) );
212 
213  // delegate to proper ExportEventHandler
214  aHandlerMap[sType]->Export(rExport, aEventQName,
215  rEventValues, bUseWhitespace);
216  }
217  else
218  {
219  if ( sType != "None" )
220  {
221  OSL_FAIL("unknown event type returned by API");
222  // unknown type -> error (ignore)
223  }
224  // else: we ignore None fields
225  }
226 }
227 
228 
229 void XMLEventExport::StartElement(bool bWhitespace)
230 {
231  if (bWhitespace)
232  {
234  }
238  bWhitespace);
239 }
240 
241 void XMLEventExport::EndElement(bool bWhitespace)
242 {
245  rExport.EndElement(nNamespace, XML_EVENT_LISTENERS, bWhitespace);
246  if (bWhitespace)
247  {
249  }
250 }
251 
252 
253 // implement aStandardEventTable (defined in xmlevent.hxx)
255 {
256  { "OnSelect", XML_NAMESPACE_DOM, "select" }, // "on-select"
257  { "OnInsertStart", XML_NAMESPACE_OFFICE, "insert-start" }, // "on-insert-start"
258  { "OnInsertDone", XML_NAMESPACE_OFFICE, "insert-done" }, // "on-insert-done"
259  { "OnMailMerge", XML_NAMESPACE_OFFICE, "mail-merge" }, // "on-mail-merge"
260  { "OnAlphaCharInput", XML_NAMESPACE_OFFICE, "alpha-char-input" }, // "on-alpha-char-input"
261  { "OnNonAlphaCharInput", XML_NAMESPACE_OFFICE, "non-alpha-char-input" }, // "on-non-alpha-char-input"
262  { "OnResize", XML_NAMESPACE_DOM, "resize" }, // "on-resize"
263  { "OnMove", XML_NAMESPACE_OFFICE, "move" }, // "on-move"
264  { "OnPageCountChange", XML_NAMESPACE_OFFICE, "page-count-change" }, // "on-page-count-change"
265  { "OnMouseOver", XML_NAMESPACE_DOM, "mouseover" }, // "on-mouse-over"
266  { "OnClick", XML_NAMESPACE_DOM, "click" }, // "on-click"
267  { "OnMouseOut", XML_NAMESPACE_DOM, "mouseout" }, // "on-mouse-out"
268  { "OnLoadError", XML_NAMESPACE_OFFICE, "load-error" }, // "on-load-error"
269  { "OnLoadCancel", XML_NAMESPACE_OFFICE, "load-cancel" }, // "on-load-cancel"
270  { "OnLoadDone", XML_NAMESPACE_OFFICE, "load-done" }, // "on-load-done"
271  { "OnLoad", XML_NAMESPACE_DOM, "load" }, // "on-load"
272  { "OnUnload", XML_NAMESPACE_DOM, "unload" }, // "on-unload"
273  { "OnStartApp", XML_NAMESPACE_OFFICE, "start-app" }, // "on-start-app"
274  { "OnCloseApp", XML_NAMESPACE_OFFICE, "close-app" }, // "on-close-app"
275  { "OnNew", XML_NAMESPACE_OFFICE, "new" }, // "on-new"
276  { "OnSave", XML_NAMESPACE_OFFICE, "save" }, // "on-save"
277  { "OnSaveAs", XML_NAMESPACE_OFFICE, "save-as" }, // "on-save-as"
278  { "OnFocus", XML_NAMESPACE_DOM, "DOMFocusIn" }, // "on-focus"
279  { "OnUnfocus", XML_NAMESPACE_DOM, "DOMFocusOut" }, // "on-unfocus"
280  { "OnPrint", XML_NAMESPACE_OFFICE, "print" }, // "on-print"
281  { "OnError", XML_NAMESPACE_DOM, "error" }, // "on-error"
282  { "OnLoadFinished", XML_NAMESPACE_OFFICE, "load-finished" }, // "on-load-finished"
283  { "OnSaveFinished", XML_NAMESPACE_OFFICE, "save-finished" }, // "on-save-finished"
284  { "OnModifyChanged", XML_NAMESPACE_OFFICE, "modify-changed" }, // "on-modify-changed"
285  { "OnPrepareUnload", XML_NAMESPACE_OFFICE, "prepare-unload" }, // "on-prepare-unload"
286  { "OnNewMail", XML_NAMESPACE_OFFICE, "new-mail" }, // "on-new-mail"
287  { "OnToggleFullscreen", XML_NAMESPACE_OFFICE, "toggle-fullscreen" }, // "on-toggle-fullscreen"
288  { "OnSaveDone", XML_NAMESPACE_OFFICE, "save-done" }, // "on-save-done"
289  { "OnSaveAsDone", XML_NAMESPACE_OFFICE, "save-as-done" }, // "on-save-as-done"
290  { "OnCopyTo", XML_NAMESPACE_OFFICE, "copy-to" },
291  { "OnCopyToDone", XML_NAMESPACE_OFFICE, "copy-to-done" },
292  { "OnViewCreated", XML_NAMESPACE_OFFICE, "view-created" },
293  { "OnPrepareViewClosing", XML_NAMESPACE_OFFICE, "prepare-view-closing" },
294  { "OnViewClosed", XML_NAMESPACE_OFFICE, "view-close" },
295  { "OnVisAreaChanged", XML_NAMESPACE_OFFICE, "visarea-changed" }, // "on-visarea-changed"
296  { "OnCreate", XML_NAMESPACE_OFFICE, "create" },
297  { "OnSaveAsFailed", XML_NAMESPACE_OFFICE, "save-as-failed" },
298  { "OnSaveFailed", XML_NAMESPACE_OFFICE, "save-failed" },
299  { "OnCopyToFailed", XML_NAMESPACE_OFFICE, "copy-to-failed" },
300  { "OnTitleChanged", XML_NAMESPACE_OFFICE, "title-changed" },
301  { "OnModeChanged", XML_NAMESPACE_OFFICE, "mode-changed" },
302  { "OnSaveTo", XML_NAMESPACE_OFFICE, "save-to" },
303  { "OnSaveToDone", XML_NAMESPACE_OFFICE, "save-to-done" },
304  { "OnSaveToFailed", XML_NAMESPACE_OFFICE, "save-to-failed" },
305  { "OnSubComponentOpened", XML_NAMESPACE_OFFICE, "subcomponent-opened" },
306  { "OnSubComponentClosed", XML_NAMESPACE_OFFICE, "subcomponent-closed" },
307  { "OnStorageChanged", XML_NAMESPACE_OFFICE, "storage-changed" },
308  { "OnMailMergeFinished", XML_NAMESPACE_OFFICE, "mail-merge-finished" },
309  { "OnFieldMerge", XML_NAMESPACE_OFFICE, "field-merge" },
310  { "OnFieldMergeFinished", XML_NAMESPACE_OFFICE, "field-merge-finished" },
311  { "OnLayoutFinished", XML_NAMESPACE_OFFICE, "layout-finished" },
312  { "OnDoubleClick", XML_NAMESPACE_OFFICE, "dblclick" },
313  { "OnRightClick", XML_NAMESPACE_OFFICE, "contextmenu" },
314  { "OnChange", XML_NAMESPACE_OFFICE, "content-changed" },
315  { "OnCalculate", XML_NAMESPACE_OFFICE, "calculated" },
316 
317  { nullptr, 0, nullptr }
318 };
319 
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void AddTranslationTable(const XMLEventNameTranslation *pTransTable)
register additional event names
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
void ExportExt(css::uno::Reference< css::container::XNameAccess > const &xAccess)
export the events, but write element (for new file format additions) ...
SAL_DLLPRIVATE void StartElement(bool bUseWhitespace)
export the start element
OUString m_aName
Definition: xmlevent.hxx:49
XMLEventExport(SvXMLExport &rExport)
constexpr OUStringLiteral gsEventType(u"EventType")
constexpr sal_uInt16 XML_NAMESPACE_DOM
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void StartElement(sal_uInt16 nPrefix, enum::xmloff::token::XMLTokenEnum eName, bool bIgnWSOutside)
Definition: xmlexp.cxx:2123
void AddHandler(const OUString &rName, std::unique_ptr< XMLEventExportHandler > pHandler)
register an EventExportHandler for a particular script type
HandlerMap aHandlerMap
OptionalString sType
void ExportSingleEvent(css::uno::Sequence< css::beans::PropertyValue > &rEventValues, const OUString &rApiEventName, bool bUseWhitespace=true)
export a single event (writes element)
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:391
sal_uInt16 m_nPrefix
Definition: xmlevent.hxx:48
void IgnorableWhitespace()
Definition: xmlexp.cxx:2219
void EndElement(sal_uInt16 nPrefix, enum::xmloff::token::XMLTokenEnum eName, bool bIgnWSInside)
Definition: xmlexp.cxx:2180
SAL_DLLPRIVATE void EndElement(bool bUseWhitespace)
export the end element
SvXMLExport & rExport
OReadImagesDocumentHandler::Image_XML_Namespace nNamespace
NameMap aNameTranslationMap
constexpr sal_uInt16 XML_NAMESPACE_OFFICE_EXT
#define SAL_WARN(area, stream)
const XMLEventNameTranslation aStandardEventTable[]
a translation table for the events defined in the XEventsSupplier service (implemented in XMLEventExp...
css::uno::Any const SvXMLExport & rExport
Definition: ImageStyle.hxx:38
SAL_DLLPRIVATE void ExportEvent(css::uno::Sequence< css::beans::PropertyValue > &rEventValues, const XMLEventName &rXmlEventName, bool bUseWhitespace, bool &rExported)
export one event (start container-element if necessary)
XMLEventNameTranslation: define tables that translate between event names as used in the XML file for...
Definition: xmlevent.hxx:75
const char * sAPIName
Definition: xmlevent.hxx:77
void Export(css::uno::Reference< css::document::XEventsSupplier > const &xAccess, bool bUseWhitespace=true)
export the events (calls EventExport::Export(Reference) )