OSDN Git Service

179d9ede38a1f02eb7c9424cd9d56e90b2ed4565
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / xml / XMLInsertHilight.java
1 /*\r
2  * This file is part of NixNote/NeighborNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\r
8  * Software distributed under the License is distributed\r
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
10  * express or implied. See the GPL for the specific language\r
11  * governing rights and limitations.\r
12  *\r
13  * You should have received a copy of the GPL along with this\r
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
15  * or write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
17  *\r
18 */\r
19 \r
20 \r
21 package cx.fbn.nevernote.xml;\r
22 \r
23 import java.util.ArrayList;\r
24 import java.util.List;\r
25 import java.util.regex.Matcher;\r
26 import java.util.regex.Pattern;\r
27 \r
28 import com.trolltech.qt.xml.QDomDocument;\r
29 import com.trolltech.qt.xml.QDomDocumentFragment;\r
30 import com.trolltech.qt.xml.QDomElement;\r
31 import com.trolltech.qt.xml.QDomNode;\r
32 import com.trolltech.qt.xml.QDomNodeList;\r
33 import com.trolltech.qt.xml.QDomText;\r
34 \r
35 public class XMLInsertHilight {\r
36         private final QDomDocument doc;\r
37         List<String> terms;\r
38         List<QDomNode> oldNodes;\r
39         List<QDomNode> newNodes;\r
40         \r
41         public XMLInsertHilight(QDomDocument d, List<String> t) {\r
42                 doc = d;\r
43                 terms = t;\r
44                 oldNodes = new ArrayList<QDomNode>();\r
45                 newNodes = new ArrayList<QDomNode>();\r
46                 scanTags();\r
47         }\r
48         public QDomDocument getDoc() {\r
49                 for (int i=0; i<oldNodes.size(); i++) {\r
50                         oldNodes.get(i).parentNode().replaceChild(newNodes.get(i), oldNodes.get(i));\r
51                 }\r
52                 return doc;\r
53         }\r
54         // Start looking through the tree.\r
55         private void scanTags() {\r
56 //              QDomElement element = doc.firstChildElement();\r
57 //              parseChildren(element.firstChild());\r
58                 if (doc.hasChildNodes())\r
59                         parseNodes(doc.childNodes());\r
60                 return;\r
61         }\r
62         \r
63         private void parseNodes(QDomNodeList nodes) {\r
64                 for (int i=0; i<nodes.size(); i++) {\r
65                         QDomNode node = nodes.at(i);\r
66                         if (node.hasChildNodes()) {\r
67                                 parseNodes(node.childNodes());\r
68                         }\r
69                         scanWords(node);\r
70                 }\r
71 }\r
72         \r
73         \r
74         // Parse through individual nodes\r
75         public void parseChildren(QDomNode node) {\r
76                 for(; !node.isNull(); node = node.nextSibling()) {\r
77                         if (node.hasChildNodes()) {\r
78                                 QDomNodeList l = node.childNodes();\r
79                                 for (int i=0; i<l.size(); i++)\r
80                                         parseChildren(l.at(i));\r
81                         }\r
82                         if (node.isText()) {\r
83                                 scanWords(node);\r
84                         }\r
85                 }\r
86         }\r
87         \r
88         // We found a text node, so we need to search for things to hilight\r
89         private void scanWords(QDomNode node) {\r
90                 String value = node.nodeValue();\r
91                 QDomDocumentFragment fragment = doc.createDocumentFragment();\r
92                 boolean matchFound = false;\r
93                 int previousPosition = 0;\r
94                 String valueEnd = "";\r
95         \r
96                 String regex = buildRegex();\r
97                         \r
98                 Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);\r
99                 Matcher matcher = pattern.matcher(value);\r
100                         \r
101                 while (matcher.find()) {\r
102                         matchFound = true;\r
103                         String valueStart = "";\r
104                         int start = matcher.start();\r
105                         int end = matcher.end();\r
106                         if (value.substring(start).startsWith(" "))\r
107                                         start++;\r
108                                 if (value.substring(start, end).endsWith(" "))\r
109                                         end--;\r
110                         \r
111                         if (matcher.start() > 0) {\r
112                                 valueStart = value.substring(previousPosition,start); \r
113                         } \r
114                         String valueMiddle = value.substring(start, end);\r
115                         valueEnd = "";\r
116                         if (matcher.end() < value.length()) {\r
117                                 valueEnd = value.substring(end);\r
118                         }\r
119                         \r
120                         previousPosition = end;\r
121                         if (!valueStart.equals("")) {\r
122                                 QDomText startText = doc.createTextNode(valueStart);\r
123                                 fragment.appendChild(startText);\r
124                         }\r
125                         \r
126                         QDomElement hilight = doc.createElement("en-hilight");\r
127                         hilight.appendChild(doc.createTextNode(valueMiddle));\r
128                         fragment.appendChild(hilight);\r
129                 }\r
130                 if (matchFound) {\r
131                         if (previousPosition != value.length()) {\r
132                                 QDomText endText = doc.createTextNode(valueEnd);\r
133                                 fragment.appendChild(endText);\r
134                         }\r
135                         newNodes.add(fragment);\r
136                         oldNodes.add(node);\r
137                 }\r
138         }\r
139         \r
140         \r
141         private String buildRegex() {\r
142                 StringBuffer regex = new StringBuffer();\r
143                 \r
144                 // Remove any empty terms of it screws things up later\r
145                 for (int j=terms.size()-1; j>=0; j--) {\r
146                         if (terms.get(j).trim().equals(""))\r
147                                 terms.remove(j);\r
148                 }\r
149                 \r
150                 for (int i=0; i<terms.size(); i++) {\r
151                         String term = terms.get(i);\r
152                         if (term.indexOf("*") > -1) {\r
153                                 term = term.replace("*", "");\r
154                         } else {\r
155                                 term = "\\b"+term+"\\b";\r
156                         }\r
157                         regex.append(term);\r
158                         if (i<terms.size()-1)\r
159                                 regex.append("|"); \r
160                 }\r
161                 \r
162                 return regex.toString();\r
163         }\r
164         \r
165 \r
166 }\r