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

File LineBreakFilter.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

8
27
9
1
164
83
19
0.7
3
9
2.11

Classes

Class Line # Actions
LineBreakFilter 45 27 0% 19 0
1.0100%
 

Contributing tests

This file is covered by 20 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.officeimporter.internal.filter;
21   
22    import java.util.Arrays;
23    import java.util.List;
24    import java.util.Map;
25   
26    import javax.inject.Named;
27    import javax.inject.Singleton;
28   
29    import org.w3c.dom.Document;
30    import org.w3c.dom.Element;
31    import org.w3c.dom.Node;
32    import org.xwiki.component.annotation.Component;
33    import org.xwiki.xml.html.filter.AbstractHTMLFilter;
34    import org.xwiki.xml.html.filter.ElementSelector;
35   
36    /**
37    * Replaces {@code<br/>} elements placed in between block elements with {@code<div class="wikikmodel-emptyline"/>}.
38    *
39    * @version $Id: f77175bc400964009507ebb4d48dc7c41f66f708 $
40    * @since 1.8M1
41    */
42    @Component
43    @Named("officeimporter/linebreak")
44    @Singleton
 
45    public class LineBreakFilter extends AbstractHTMLFilter
46    {
47    /**
48    * List of block element tag names.
49    */
50    private static final String[] BLOCK_ELEMENT_TAGS =
51    new String[] {TAG_P, TAG_UL, TAG_OL, TAG_H1, TAG_H2, TAG_H3, TAG_H4, TAG_H5, TAG_H6, TAG_TABLE};
52   
53    /**
54    * Sort the block elements tag name array.
55    */
 
56  1 toggle static {
57  1 Arrays.sort(BLOCK_ELEMENT_TAGS);
58    }
59   
 
60  66 toggle @Override
61    public void filter(Document document, Map<String, String> cleaningParams)
62    {
63  66 List<Element> lineBreaksToReplace =
64    filterDescendants(document.getDocumentElement(), new String[] {TAG_BR}, new ElementSelector()
65    {
 
66  65 toggle @Override
67    public boolean isSelected(Element element)
68    {
69  65 Node prev = findPreviousNode(element);
70  65 Node next = findNextNode(element);
71  65 return !(null == prev && null == next) && (isBlockElement(prev) || isBlockElement(next));
72    }
73    });
74  66 for (Element lineBreak : lineBreaksToReplace) {
75  60 Node parent = lineBreak.getParentNode();
76  60 Element element = document.createElement(TAG_DIV);
77  60 element.setAttribute(ATTRIBUTE_CLASS, "wikimodel-emptyline");
78  60 parent.insertBefore(element, lineBreak);
79  60 parent.removeChild(lineBreak);
80    }
81    }
82   
83    /**
84    * Finds the previous sibling of the given element which is not a {@code <br/>}, an empty text node or a comment
85    * node.
86    *
87    * @param element the element to be analysed.
88    * @return previous sibling of the given element which is not a html line-break, an empty text node or a comment
89    * node.
90    */
 
91  65 toggle private Node findPreviousNode(Element element)
92    {
93  65 Node prev = element.getPreviousSibling();
94  98 while (prev != null && (isLineBreak(prev) || isEmptyTextNode(prev) || isCommentNode(prev))) {
95  33 prev = prev.getPreviousSibling();
96    }
97  65 return prev;
98    }
99   
100    /**
101    * Finds the next sibling of the given element which is not a {@code <br/>}, an empty text node or a comment node.
102    *
103    * @param element the element to be analysed.
104    * @return next sibling of the given element which is not a html line-break, an empty text node or a comment node.
105    */
 
106  65 toggle private Node findNextNode(Element element)
107    {
108  65 Node next = element.getNextSibling();
109  98 while (next != null && (isLineBreak(next) || isEmptyTextNode(next) || isCommentNode(next))) {
110  33 next = next.getNextSibling();
111    }
112  65 return next;
113    }
114   
115    /**
116    * Check whether the given node represents a block element.
117    *
118    * @param node the node to be checked.
119    * @return true if the node represents a block element.
120    */
 
121  80 toggle private boolean isBlockElement(Node node)
122    {
123  80 boolean isBlockElement = false;
124  80 if (null != node) {
125  60 for (String blockElement : BLOCK_ELEMENT_TAGS) {
126  600 isBlockElement = blockElement.equals(node.getNodeName()) ? true : isBlockElement;
127    }
128    }
129  80 return isBlockElement;
130    }
131   
132    /**
133    * Checks if a node represents empty text content (white space).
134    *
135    * @param node the {@link Node}.
136    * @return true if the node represents white space.
137    */
 
138  80 toggle private boolean isEmptyTextNode(Node node)
139    {
140  80 return null != node && node.getNodeType() == Node.TEXT_NODE && node.getTextContent().trim().equals("");
141    }
142   
143    /**
144    * Checks if a node represents an html comment.
145    *
146    * @param node the {@link Node}.
147    * @return true if the node is a comment node.
148    */
 
149  80 toggle private boolean isCommentNode(Node node)
150    {
151  80 return null != node && node.getNodeType() == Node.COMMENT_NODE;
152    }
153   
154    /**
155    * Checks if a node represents an html line break.
156    *
157    * @param node the {@link Node}
158    * @return true of the node represents a line break.
159    */
 
160  146 toggle private boolean isLineBreak(Node node)
161    {
162  146 return null != node && node.getNodeName().equals(TAG_BR);
163    }
164    }