View Javadoc
1   /**
2    * The contents of this file are subject to the Mozilla Public License Version 1.1
3    * (the "License"); you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
5    * Software distributed under the License is distributed on an "AS IS" basis,
6    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
7    * specific language governing rights and limitations under the License.
8    *
9    * The Original Code is ""  Description:
10   * ""
11   *
12   * The Initial Developer of the Original Code is University Health Network. Copyright (C)
13   * 2001.  All Rights Reserved.
14   *
15   * Contributor(s): ______________________________________.
16   *
17   * Alternatively, the contents of this file may be used under the terms of the
18   * GNU General Public License (the  "GPL"), in which case the provisions of the GPL are
19   * applicable instead of those above.  If you wish to allow use of your version of this
20   * file only under the terms of the GPL and not to allow others to use your version
21   * of this file under the MPL, indicate your decision by deleting  the provisions above
22   * and replace  them with the notice and other provisions required by the GPL License.
23   * If you do not delete the provisions above, a recipient may use your version of
24   * this file under either the MPL or the GPL.
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  			// Find corresponding close tag
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 	 * @return the currentTagName
144 	 */
145 	public String getCurrentTagName() {
146 		return myCurrentTagName;
147 	}
148 
149 	/**
150 	 * @return the currentTagRepetition
151 	 */
152 	public int getCurrentTagRepetition() {
153 		return myCurrentTagRepetition;
154 	}
155 
156 	/**
157 	 * @return the position
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 	 * @param theCalculateRepetitions
195 	 *            the calculateRepetitions to set
196 	 */
197 	public void setCalculateRepetitions(boolean theCalculateRepetitions) {
198 		myCalculateRepetitions = theCalculateRepetitions;
199 	}
200 
201 	public void setPosition(int thePosition) {
202 		myPosition = thePosition;
203 	}
204 
205 }