1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.xar

File XarPackage.java

 

Coverage histogram

../../../img/srcFileCovDistChart7.png
64% of files have more coverage

Code metrics

48
172
46
1
733
413
78
0.45
3.74
46
1.7

Classes

Class Line # Actions
XarPackage 66 172 0% 78 102
0.616541361.7%
 

Contributing tests

This file is covered by 26 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.xar;
21   
22    import java.io.File;
23    import java.io.IOException;
24    import java.io.InputStream;
25    import java.io.OutputStream;
26    import java.util.Collection;
27    import java.util.Enumeration;
28    import java.util.LinkedHashMap;
29    import java.util.Map;
30    import java.util.Objects;
31   
32    import javax.xml.parsers.DocumentBuilder;
33    import javax.xml.parsers.DocumentBuilderFactory;
34    import javax.xml.parsers.ParserConfigurationException;
35    import javax.xml.stream.XMLOutputFactory;
36    import javax.xml.stream.XMLStreamException;
37    import javax.xml.stream.XMLStreamWriter;
38   
39    import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
40    import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
41    import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
42    import org.apache.commons.compress.archivers.zip.ZipFile;
43    import org.apache.commons.io.input.CloseShieldInputStream;
44    import org.apache.commons.lang3.LocaleUtils;
45    import org.apache.commons.lang3.StringUtils;
46    import org.w3c.dom.Document;
47    import org.w3c.dom.Element;
48    import org.w3c.dom.Node;
49    import org.w3c.dom.NodeList;
50    import org.xml.sax.SAXException;
51    import org.xwiki.model.EntityType;
52    import org.xwiki.model.internal.reference.DefaultSymbolScheme;
53    import org.xwiki.model.internal.reference.LocalStringEntityReferenceSerializer;
54    import org.xwiki.model.reference.LocalDocumentReference;
55    import org.xwiki.xar.internal.XarUtils;
56    import org.xwiki.xar.internal.model.XarModel;
57   
58    import javanet.staxutils.IndentingXMLStreamWriter;
59   
60    /**
61    * Manipulate package.xml XAR package file.
62    *
63    * @version $Id: 3b4865efd5d02c21f1726919a252ad7e67c97f53 $
64    * @since 5.4RC1
65    */
 
66    public class XarPackage
67    {
68    private static final LocalStringEntityReferenceSerializer TOSTRING_SERIALIZER =
69    new LocalStringEntityReferenceSerializer(new DefaultSymbolScheme());
70   
71    /**
72    * Get all entries found in a XAR file.
73    *
74    * @param file the XAR file
75    * @return the entries of the passed XAR file
76    * @throws XarException when failing to parse the XAR package
77    * @throws IOException when failing to read the file
78    */
 
79  61 toggle public static Collection<XarEntry> getEntries(File file) throws XarException, IOException
80    {
81  61 XarPackage xarPackage = new XarPackage(file);
82   
83  61 return xarPackage.getEntries();
84    }
85   
86    /**
87    * @see #getPackageExtensionId()
88    */
89    private String packageExtensionId;
90   
91    /**
92    * @see #isPackagePreserveVersion()
93    */
94    private boolean packagePreserveVersion = true;
95   
96    /**
97    * @see #getPackageName()
98    */
99    private String packageName;
100   
101    /**
102    * @see #getPackageDescription()
103    */
104    private String packageDescription;
105   
106    /**
107    * @see #getPackageLicense()
108    */
109    private String packageLicense;
110   
111    /**
112    * @see #getPackageAuthor()
113    */
114    private String packageAuthor;
115   
116    /**
117    * @see #getPackageVersion()
118    */
119    private String packageVersion;
120   
121    /**
122    * @see #isPackageBackupPack()
123    */
124    private boolean packageBackupPack;
125   
126    private final Map<LocalDocumentReference, XarEntry> packageFiles =
127    new LinkedHashMap<LocalDocumentReference, XarEntry>();
128   
129    private final Map<LocalDocumentReference, XarEntry> entries = new LinkedHashMap<LocalDocumentReference, XarEntry>();
130   
131    /**
132    * Default constructor.
133    */
 
134  9 toggle public XarPackage()
135    {
136   
137    }
138   
139    /**
140    * @param zipFile the XAR file as a {@link ZipFile}
141    * @throws XarException when failing to parse the XAR package
142    * @throws IOException when failing to read the file
143    */
 
144  0 toggle public XarPackage(ZipFile zipFile) throws XarException, IOException
145    {
146  0 read(zipFile);
147    }
148   
149    /**
150    * @param file the XAR file
151    * @throws IOException when failing to read the file
152    * @throws XarException when failing to parse the XAR package
153    */
 
154  148 toggle public XarPackage(File file) throws IOException, XarException
155    {
156  148 ZipFile zipFile = new ZipFile(file);
157   
158  148 try {
159  148 read(zipFile);
160    } finally {
161  148 zipFile.close();
162    }
163    }
164   
165    /**
166    * @param xarStream an input stream the the XAR file
167    * @throws IOException when failing to read the file
168    * @throws XarException when failing to parse the XAR package
169    */
 
170  4 toggle public XarPackage(InputStream xarStream) throws IOException, XarException
171    {
172  4 read(xarStream);
173    }
174   
175    /**
176    * @param entries the entries in the XAR file
177    */
 
178  0 toggle public XarPackage(Collection<XarEntry> entries)
179    {
180  0 for (XarEntry entry : entries) {
181  0 this.entries.put(entry, entry);
182    }
183    }
184   
185    /**
186    * Find and add the entries located in the passed XAR file.
187    *
188    * @param xarStream an input stream to a XAR file
189    * @throws IOException when failing to read the file
190    * @throws XarException when failing to parse the XAR package
191    */
 
192  4 toggle public void read(InputStream xarStream) throws IOException, XarException
193    {
194  4 ZipArchiveInputStream zis = new ZipArchiveInputStream(xarStream, "UTF-8", false);
195   
196  4 try {
197  15 for (ZipArchiveEntry entry = zis.getNextZipEntry(); entry != null; entry = zis.getNextZipEntry()) {
198  11 if (!entry.isDirectory() && zis.canReadEntryData(entry)) {
199  8 readEntry(zis, entry);
200    }
201    }
202    } finally {
203  4 zis.close();
204    }
205    }
206   
207    /**
208    * Find and add the entries located in the passed XAR file.
209    *
210    * @param zipFile the XAR file
211    * @throws IOException when failing to read the file
212    * @throws XarException when failing to parse the XAR package
213    */
 
214  148 toggle public void read(ZipFile zipFile) throws IOException, XarException
215    {
216  148 Enumeration<ZipArchiveEntry> zipEntries = zipFile.getEntries();
217   
218  4003 while (zipEntries.hasMoreElements()) {
219  3855 ZipArchiveEntry entry = zipEntries.nextElement();
220   
221  3855 if (!entry.isDirectory()) {
222  3855 InputStream stream = zipFile.getInputStream(entry);
223   
224  3855 try {
225  3855 readEntry(stream, entry);
226    } finally {
227  3855 stream.close();
228    }
229    }
230    }
231    }
232   
 
233  3863 toggle private void readEntry(InputStream stream, ZipArchiveEntry entry) throws XarException, IOException
234    {
235  3863 if (entry.getName().equals(XarModel.PATH_PACKAGE)) {
236  152 readDescriptor(stream);
237    } else {
238  3711 LocalDocumentReference reference = XarUtils.getReference(stream);
239   
240    // Get current action associated to the document
241  3711 int defaultAction = getDefaultAction(reference);
242   
243    // Create entry
244  3711 XarEntry xarEntry = new XarEntry(reference, entry.getName(), defaultAction);
245   
246    // Register entry
247  3711 this.entries.put(xarEntry, xarEntry);
248   
249    // Update existing package file entry name
250  3711 updatePackageFileEntryName(xarEntry);
251    }
252    }
253   
254    /**
255    * @return the identifier of the extension stored in the XAR package
256    */
 
257  13 toggle public String getPackageExtensionId()
258    {
259  13 return this.packageExtensionId;
260    }
261   
262    /**
263    * @param packageExtensionId the identifier of the extension stored in the XAR package
264    */
 
265  0 toggle public void setPackageExtensionId(String packageExtensionId)
266    {
267  0 this.packageExtensionId = packageExtensionId;
268    }
269   
270    /**
271    * @return true if the history should be preserved by default
272    */
 
273  0 toggle public boolean isPackagePreserveVersion()
274    {
275  0 return this.packagePreserveVersion;
276    }
277   
278    /**
279    * @param preserveVersion true if the history should be preserved by default
280    * @deprecated since 7.2M1, use {@link #setPackagePreserveVersion(boolean)} instead
281    */
 
282  0 toggle @Deprecated
283    public void setPreserveVersion(boolean preserveVersion)
284    {
285  0 this.packagePreserveVersion = preserveVersion;
286    }
287   
288    /**
289    * @param packagePreserveVersion true if the history should be preserved by default
290    */
 
291  0 toggle public void setPackagePreserveVersion(boolean packagePreserveVersion)
292    {
293  0 this.packagePreserveVersion = packagePreserveVersion;
294    }
295   
296    /**
297    * @return the name of the package
298    */
 
299  5 toggle public String getPackageName()
300    {
301  5 return this.packageName;
302    }
303   
304    /**
305    * @param packageName the name of the package
306    */
 
307  0 toggle public void setPackageName(String packageName)
308    {
309  0 this.packageName = packageName;
310    }
311   
312    /**
313    * @return the description of package
314    */
 
315  5 toggle public String getPackageDescription()
316    {
317  5 return this.packageDescription;
318    }
319   
320    /**
321    * @param packageDescription the description of package
322    */
 
323  0 toggle public void setPackageDescription(String packageDescription)
324    {
325  0 this.packageDescription = packageDescription;
326    }
327   
328    /**
329    * @return the license of the package
330    */
 
331  5 toggle public String getPackageLicense()
332    {
333  5 return this.packageLicense;
334    }
335   
336    /**
337    * @param packageLicense the license of the package
338    */
 
339  0 toggle public void setPackageLicense(String packageLicense)
340    {
341  0 this.packageLicense = packageLicense;
342    }
343   
344    /**
345    * @return the author of the package
346    */
 
347  5 toggle public String getPackageAuthor()
348    {
349  5 return this.packageAuthor;
350    }
351   
352    /**
353    * @param packageAuthor the author of the package
354    */
 
355  0 toggle public void setPackageAuthor(String packageAuthor)
356    {
357  0 this.packageAuthor = packageAuthor;
358    }
359   
360    /**
361    * @return the version of the package
362    */
 
363  5 toggle public String getPackageVersion()
364    {
365  5 return this.packageVersion;
366    }
367   
368    /**
369    * @param packageVersion the version of the package
370    */
 
371  0 toggle public void setPackageVersion(String packageVersion)
372    {
373  0 this.packageVersion = packageVersion;
374    }
375   
376    /**
377    * @return true of the package is a backup
378    */
 
379  4 toggle public boolean isPackageBackupPack()
380    {
381  4 return this.packageBackupPack;
382    }
383   
384    /**
385    * @param packageBackupPack true of the package is a backup
386    */
 
387  0 toggle public void setPackageBackupPack(boolean packageBackupPack)
388    {
389  0 this.packageBackupPack = packageBackupPack;
390    }
391   
392    /**
393    * @return the entries listed in the package descriptor
394    * @since 7.2M1
395    */
 
396  1 toggle public Collection<XarEntry> getPackageFiles()
397    {
398  1 return this.packageFiles.values();
399    }
400   
401    /**
402    * Add a new entry to the package.
403    *
404    * @param reference the entry reference since 7.2M1
405    * @param action the default action associated to this XAR (not used at the moment)
406    */
 
407  0 toggle public void addPackageFile(LocalDocumentReference reference, int action)
408    {
409  0 this.packageFiles.put(reference, new XarEntry(reference, null, action));
410    }
411   
412    /**
413    * Add a new entry to the package.
414    *
415    * @param reference the entry reference
416    * @deprecated since 7.2M1, use {@link #addPackageFile(LocalDocumentReference, int)} instead
417    */
 
418  0 toggle @Deprecated
419    public void addEntry(LocalDocumentReference reference)
420    {
421  0 addEntry(reference, null);
422    }
423   
424    /**
425    * Add a new entry to the package.
426    *
427    * @param reference the entry reference
428    * @param entryName the name of the entry (ZIP style)
429    * @since 7.2M1
430    */
 
431  0 toggle public void addEntry(LocalDocumentReference reference, String entryName)
432    {
433  0 addEntry(reference, entryName, XarModel.ACTION_OVERWRITE);
434    }
435   
436    /**
437    * Add a new entry to the package.
438    *
439    * @param reference the entry reference
440    * @param entryName the name of the entry (ZIP style)
441    * @param action the default action associated to this XAR (not used at the moment)
442    * @since 7.2M1
443    */
 
444  0 toggle public void addEntry(LocalDocumentReference reference, String entryName, int action)
445    {
446  0 XarEntry entry = new XarEntry(reference, entryName, action);
447   
448  0 this.entries.put(reference, entry);
449  0 this.packageFiles.put(reference, entry);
450    }
451   
452    /**
453    * @return the entries of the package
454    */
 
455  200 toggle public Collection<XarEntry> getEntries()
456    {
457  200 return this.entries.values();
458    }
459   
460    /**
461    * @param reference the reference of the document
462    * @return the entry associated to the passage reference
463    */
 
464  268 toggle public XarEntry getEntry(LocalDocumentReference reference)
465    {
466  268 return this.entries.get(reference);
467    }
468   
469    /**
470    * Read a XML descriptor of a XAR package (usually names package.xml).
471    *
472    * @param stream the input stream to the XML file to parse
473    * @throws XarException when failing to parse the descriptor
474    * @throws IOException when failing to read the file
475    */
 
476  161 toggle public void readDescriptor(InputStream stream) throws XarException, IOException
477    {
478  161 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
479   
480  161 DocumentBuilder dBuilder;
481  161 try {
482  161 dBuilder = dbFactory.newDocumentBuilder();
483    } catch (ParserConfigurationException e) {
484  0 throw new XarException("Failed to create a new Document builder", e);
485    }
486   
487  161 Document doc;
488  161 try {
489    // DocumentBuilder#parse close the passed stream which is not what we want
490  161 doc = dBuilder.parse(new CloseShieldInputStream(stream));
491    } catch (SAXException e) {
492  0 throw new XarException("Failed to parse XML document", e);
493    }
494   
495    // Normalize the document
496  161 doc.getDocumentElement().normalize();
497   
498    // Read the document
499  161 NodeList children = doc.getChildNodes();
500  161 for (int i = 0; i < children.getLength(); ++i) {
501  161 Node node = children.item(i);
502  161 if (node.getNodeType() == Node.ELEMENT_NODE) {
503  161 Element element = (Element) node;
504  161 if (element.getTagName().equals(XarModel.ELEMENT_PACKAGE)) {
505  161 readDescriptorPackage(element);
506  161 break;
507    }
508    }
509    }
510    }
511   
 
512  161 toggle private void readDescriptorPackage(Element packageElement)
513    {
514  161 NodeList children = packageElement.getChildNodes();
515  2646 for (int i = 0; i < children.getLength(); ++i) {
516  2485 Node node = children.item(i);
517  2485 if (node.getNodeType() == Node.ELEMENT_NODE) {
518  1302 Element element = (Element) node;
519  1302 if (element.getTagName().equals(XarModel.ELEMENT_INFOS)) {
520  161 readDescriptorInfos(element);
521  1141 } else if (element.getTagName().equals(XarModel.ELEMENT_FILES)) {
522  161 readDescriptorFiles(element);
523    }
524    }
525    }
526    }
527   
 
528  161 toggle private void readDescriptorInfos(Element infos)
529    {
530  161 this.packageExtensionId = getElementText(infos, XarModel.ELEMENT_INFOS_EXTENSIONID, true);
531  161 this.packageVersion = getElementText(infos, XarModel.ELEMENT_INFOS_VERSION, false);
532  161 this.packageName = getElementText(infos, XarModel.ELEMENT_INFOS_NAME, false);
533  161 this.packageDescription = getElementText(infos, XarModel.ELEMENT_INFOS_DESCRIPTION, false);
534  161 this.packageLicense = getElementText(infos, XarModel.ELEMENT_INFOS_LICENSE, false);
535  161 this.packageAuthor = getElementText(infos, XarModel.ELEMENT_INFOS_AUTHOR, false);
536  161 this.packageBackupPack =
537    Boolean.valueOf(getElementText(infos, XarModel.ELEMENT_INFOS_ISBACKUPPACK, false)).booleanValue();
538  161 this.packagePreserveVersion =
539    Boolean.valueOf(getElementText(infos, XarModel.ELEMENT_INFOS_ISPRESERVEVERSION, false)).booleanValue();
540    }
541   
 
542  161 toggle private void readDescriptorFiles(Element files)
543    {
544  161 NodeList children = files.getChildNodes();
545  6804 for (int i = 0; i < children.getLength(); ++i) {
546  6643 Node node = children.item(i);
547  6643 if (node.getNodeType() == Node.ELEMENT_NODE) {
548  3311 Element element = (Element) node;
549  3311 if (element.getTagName().equals(XarModel.ELEMENT_FILES_FILE)) {
550  3311 String localeString = element.getAttribute(XarModel.ATTRIBUTE_LOCALE);
551  3311 String defaultActionString = element.getAttribute(XarModel.ATTRIBUTE_DEFAULTACTION);
552  3311 String referenceString = element.getTextContent();
553   
554    // Parse reference
555  3311 LocalDocumentReference reference =
556    new LocalDocumentReference(XarUtils.RESOLVER.resolve(referenceString, EntityType.DOCUMENT),
557    LocaleUtils.toLocale(localeString));
558   
559    // Parse default action
560  3311 int defaultAction = Integer.valueOf(defaultActionString);
561   
562    // Get entry name associated to the document
563  3311 String entryName = getEntryName(reference);
564   
565    // Create entry
566  3311 XarEntry packageFile = new XarEntry(reference, entryName, defaultAction);
567   
568    // Register package file entry
569  3311 this.packageFiles.put(packageFile, packageFile);
570   
571    // Update existing entry default action
572  3311 updateEntryDefaultAction(packageFile);
573    }
574    }
575    }
576    }
577   
 
578  3311 toggle private String getEntryName(LocalDocumentReference reference)
579    {
580  3311 String entryName = null;
581   
582  3311 XarEntry entry = this.entries.get(reference);
583  2485 if (entry != null) {
584  0 entryName = entry.getEntryName();
585    }
586   
587  3311 return entryName;
588    }
589   
 
590  3711 toggle private int getDefaultAction(LocalDocumentReference reference)
591    {
592  3711 int defaultAction = XarModel.ACTION_SKIP;
593   
594  3711 XarEntry packageFile = this.packageFiles.get(reference);
595  3711 if (packageFile != null) {
596  2409 defaultAction = packageFile.getDefaultAction();
597    }
598   
599  3711 return defaultAction;
600    }
601   
 
602  3311 toggle private void updateEntryDefaultAction(XarEntry packageFile)
603    {
604  2485 if (this.entries.containsKey(packageFile)) {
605  0 this.entries.put(packageFile, packageFile);
606    }
607    }
608   
 
609  3711 toggle private void updatePackageFileEntryName(XarEntry xarEntry)
610    {
611  3711 if (this.packageFiles.containsKey(xarEntry)) {
612  2409 this.packageFiles.put(xarEntry, xarEntry);
613    }
614    }
615   
 
616  1288 toggle private String getElementText(Element element, String tagName, boolean ignoreEmpty)
617    {
618  1288 NodeList nList = element.getElementsByTagName(tagName);
619   
620  1288 String value = nList.getLength() > 0 ? nList.item(0).getTextContent() : null;
621   
622  1288 if (value != null && ignoreEmpty && StringUtils.isEmpty(value)) {
623  1 value = null;
624    }
625   
626  1288 return value;
627    }
628   
629    /**
630    * Write and add the package descriptor to the passed ZIP stream.
631    *
632    * @param zipStream the ZIP stream in which to write
633    * @param encoding the encoding to use to write the descriptor
634    * @throws XarException when failing to parse the descriptor
635    * @throws IOException when failing to read the file
636    */
 
637  0 toggle public void write(ZipArchiveOutputStream zipStream, String encoding) throws XarException, IOException
638    {
639  0 ZipArchiveEntry zipentry = new ZipArchiveEntry(XarModel.PATH_PACKAGE);
640  0 zipStream.putArchiveEntry(zipentry);
641   
642  0 try {
643  0 write((OutputStream) zipStream, encoding);
644    } finally {
645  0 zipStream.closeArchiveEntry();
646    }
647    }
648   
649    /**
650    * Write the package descriptor to the passed stream as XML.
651    *
652    * @param stream the stream to the resulting XML file
653    * @param encoding the encoding to use to write the descriptor
654    * @throws XarException when failing to parse the descriptor
655    * @throws IOException when failing to read the file
656    */
 
657  0 toggle public void write(OutputStream stream, String encoding) throws XarException, IOException
658    {
659  0 XMLStreamWriter writer;
660  0 try {
661  0 writer = XMLOutputFactory.newInstance().createXMLStreamWriter(stream, encoding);
662    } catch (Exception e) {
663  0 throw new XarException("Failed to create an instance of XML stream writer", e);
664    }
665   
666  0 writer = new IndentingXMLStreamWriter(writer);
667   
668  0 try {
669  0 writer.writeStartDocument(encoding, "1.0");
670  0 write(writer);
671  0 writer.writeEndDocument();
672   
673  0 writer.flush();
674    } catch (Exception e) {
675  0 throw new XarException("Failed to write XML", e);
676    } finally {
677  0 try {
678  0 writer.close();
679    } catch (XMLStreamException e) {
680  0 throw new XarException("Failed to close XML writer", e);
681    }
682    }
683    }
684   
685    /**
686    * Write the package descriptor to the passed XML stream.
687    *
688    * @param writer the XML stream where to write
689    * @throws XMLStreamException when failing to write the file
690    */
 
691  0 toggle public void write(XMLStreamWriter writer) throws XMLStreamException
692    {
693  0 writer.writeStartElement(XarModel.ELEMENT_PACKAGE);
694   
695  0 writer.writeStartElement(XarModel.ELEMENT_INFOS);
696  0 writeElement(writer, XarModel.ELEMENT_INFOS_NAME, getPackageName(), true);
697  0 writeElement(writer, XarModel.ELEMENT_INFOS_DESCRIPTION, getPackageDescription(), true);
698  0 writeElement(writer, XarModel.ELEMENT_INFOS_LICENSE, getPackageLicense(), true);
699  0 writeElement(writer, XarModel.ELEMENT_INFOS_AUTHOR, getPackageAuthor(), true);
700  0 writeElement(writer, XarModel.ELEMENT_INFOS_VERSION, getPackageVersion(), true);
701  0 writeElement(writer, XarModel.ELEMENT_INFOS_ISBACKUPPACK, String.valueOf(isPackageBackupPack()), true);
702  0 writeElement(writer, XarModel.ELEMENT_INFOS_ISPRESERVEVERSION, String.valueOf(isPackagePreserveVersion()),
703    true);
704  0 writeElement(writer, XarModel.ELEMENT_INFOS_EXTENSIONID, getPackageExtensionId(), false);
705  0 writer.writeEndElement();
706   
707  0 writer.writeStartElement(XarModel.ELEMENT_FILES);
708  0 for (XarEntry entry : this.entries.values()) {
709  0 writer.writeStartElement(XarModel.ELEMENT_FILES_FILE);
710  0 writer.writeAttribute(XarModel.ATTRIBUTE_DEFAULTACTION, String.valueOf(entry.getDefaultAction()));
711  0 writer.writeAttribute(XarModel.ATTRIBUTE_LOCALE, Objects.toString(entry.getLocale(), ""));
712  0 writer.writeCharacters(TOSTRING_SERIALIZER.serialize(entry));
713  0 writer.writeEndElement();
714    }
715  0 writer.writeEndElement();
716    }
717   
 
718  0 toggle private void writeElement(XMLStreamWriter streamWriter, String localName, String value, boolean emptyIfNull)
719    throws XMLStreamException
720    {
721  0 if (value != null) {
722  0 if (value.isEmpty()) {
723  0 streamWriter.writeEmptyElement(localName);
724    } else {
725  0 streamWriter.writeStartElement(localName);
726  0 streamWriter.writeCharacters(value);
727  0 streamWriter.writeEndElement();
728    }
729  0 } else if (emptyIfNull) {
730  0 streamWriter.writeEmptyElement(localName);
731    }
732    }
733    }