1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package ca.uhn.hl7v2.testpanel.util;
27
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 public class XmlScanner {
32
33 private static final Logger ourLog = LoggerFactory.getLogger(XmlScanner.class);
34
35 private boolean myCalculateRepetitions;
36 private String myCurrentTagName;
37 private int myCurrentTagRepetition;
38 private String myDocument;
39 private int myPosition;
40
41 public XmlScanner(String theDocument) {
42 myDocument = theDocument;
43 }
44
45 public void decrementPositionByOne() {
46 myPosition--;
47 }
48
49 public boolean findTagEnclosingCurrentPosition() {
50 if (myPosition >= myDocument.length()) {
51 return false;
52 }
53
54 int currentPosition = myPosition;
55 int originalPosition = myPosition;
56
57 String currentTagName;
58 int tagStart;
59 do {
60 tagStart = indexOfOpenTagBackwards(currentPosition);
61
62 if (tagStart == -1) {
63 return false;
64 }
65
66 int tagEnd = indexOfTagNameEnd(tagStart + 1);
67 if (tagEnd == -1) {
68 return false;
69 }
70
71 currentTagName = myDocument.substring(tagStart + 1, tagEnd);
72
73
74 int closePosition = myDocument.indexOf("</" + currentTagName + ">", tagStart);
75 if (closePosition == -1) {
76 return false;
77 }
78
79 if (closePosition > myPosition) {
80 break;
81 } else {
82 currentPosition = tagStart - 1;
83 }
84
85 } while (currentPosition >= 0);
86
87 if (currentTagName == null) {
88 return false;
89 }
90
91 myCurrentTagName = currentTagName;
92 myPosition = tagStart;
93
94 if (myCalculateRepetitions) {
95 XmlScanner parentScanner = new XmlScanner(myDocument);
96 parentScanner.setPosition(myPosition - 1);
97 if (parentScanner.findTagEnclosingCurrentPosition()) {
98 int parentTagStart = parentScanner.getPosition();
99 myCurrentTagRepetition = countCloseTags(myCurrentTagName, parentTagStart, originalPosition) + 1;
100 }
101 }
102
103 return true;
104
105 }
106
107 private int countCloseTags(String theCurrentTagName, int theStart, int theEnd) {
108 int retVal = 0;
109
110 if (ourLog.isTraceEnabled()) {
111 ourLog.trace("Searching for </" + theCurrentTagName + "> within " + theStart + "-" + theEnd + " : "+ myDocument.substring(theStart, theEnd));
112 }
113
114 for (int i = theStart; i + 3 + theCurrentTagName.length() < theEnd; i++) {
115 if (myDocument.charAt(i) == '<') {
116 if (myDocument.charAt(i + 1) == '/') {
117 int beginIndex = i + 2;
118 int endIndex = beginIndex + theCurrentTagName.length();
119
120 String substring = myDocument.substring(beginIndex, endIndex);
121 if (substring.equals(theCurrentTagName)) {
122 if (myDocument.charAt(beginIndex + theCurrentTagName.length()) == '>') {
123
124 if (ourLog.isTraceEnabled()) {
125 ourLog.info("At " + beginIndex + "-" + endIndex + " found: " + substring);
126 }
127
128 retVal++;
129 }
130 }
131 }
132 }
133 }
134
135 if (ourLog.isTraceEnabled()) {
136 ourLog.info("Found " + retVal);
137 }
138
139 return retVal;
140 }
141
142
143
144
145 public String getCurrentTagName() {
146 return myCurrentTagName;
147 }
148
149
150
151
152 public int getCurrentTagRepetition() {
153 return myCurrentTagRepetition;
154 }
155
156
157
158
159 public int getPosition() {
160 return myPosition;
161 }
162
163 private int indexOfOpenTagBackwards(int theIndex) {
164 for (int i = theIndex; i >= 0; i--) {
165 if (myDocument.charAt(i) == '<') {
166 if ((i + 1) < myDocument.length() && myDocument.charAt(i + 1) != '/') {
167 return i;
168 }
169 }
170 }
171 return -1;
172 }
173
174 private int indexOfTagNameEnd(int theTagStart) {
175 for (int i = theTagStart; i < myDocument.length(); i++) {
176 char nextChar = myDocument.charAt(i);
177 if (Character.isLetterOrDigit(nextChar)) {
178 continue;
179 }
180
181 switch (nextChar) {
182 case '_':
183 case '.':
184 continue;
185 }
186
187 return i;
188 }
189
190 return -1;
191 }
192
193
194
195
196
197 public void setCalculateRepetitions(boolean theCalculateRepetitions) {
198 myCalculateRepetitions = theCalculateRepetitions;
199 }
200
201 public void setPosition(int thePosition) {
202 myPosition = thePosition;
203 }
204
205 }