Mercurial > repos > pfrommolt > ngsrich
comparison NGSrich_0.5.5/src/org/jdom/ProcessingInstruction.java @ 0:89ad0a9cca52 default tip
Uploaded
author | pfrommolt |
---|---|
date | Mon, 21 Nov 2011 08:12:19 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:89ad0a9cca52 |
---|---|
1 /*-- | |
2 | |
3 $Id: ProcessingInstruction.java,v 1.47 2007/11/10 05:28:59 jhunter Exp $ | |
4 | |
5 Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin. | |
6 All rights reserved. | |
7 | |
8 Redistribution and use in source and binary forms, with or without | |
9 modification, are permitted provided that the following conditions | |
10 are met: | |
11 | |
12 1. Redistributions of source code must retain the above copyright | |
13 notice, this list of conditions, and the following disclaimer. | |
14 | |
15 2. Redistributions in binary form must reproduce the above copyright | |
16 notice, this list of conditions, and the disclaimer that follows | |
17 these conditions in the documentation and/or other materials | |
18 provided with the distribution. | |
19 | |
20 3. The name "JDOM" must not be used to endorse or promote products | |
21 derived from this software without prior written permission. For | |
22 written permission, please contact <request_AT_jdom_DOT_org>. | |
23 | |
24 4. Products derived from this software may not be called "JDOM", nor | |
25 may "JDOM" appear in their name, without prior written permission | |
26 from the JDOM Project Management <request_AT_jdom_DOT_org>. | |
27 | |
28 In addition, we request (but do not require) that you include in the | |
29 end-user documentation provided with the redistribution and/or in the | |
30 software itself an acknowledgement equivalent to the following: | |
31 "This product includes software developed by the | |
32 JDOM Project (http://www.jdom.org/)." | |
33 Alternatively, the acknowledgment may be graphical using the logos | |
34 available at http://www.jdom.org/images/logos. | |
35 | |
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT | |
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
47 SUCH DAMAGE. | |
48 | |
49 This software consists of voluntary contributions made by many | |
50 individuals on behalf of the JDOM Project and was originally | |
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and | |
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information | |
53 on the JDOM Project, please see <http://www.jdom.org/>. | |
54 | |
55 */ | |
56 | |
57 package org.jdom; | |
58 | |
59 import java.util.*; | |
60 | |
61 /** | |
62 * An XML processing instruction. Methods allow the user to obtain the target of | |
63 * the PI as well as its data. The data can always be accessed as a String or, | |
64 * if the data appears akin to an attribute list, can be retrieved as name/value | |
65 * pairs. | |
66 * | |
67 * @version $Revision: 1.47 $, $Date: 2007/11/10 05:28:59 $ | |
68 * @author Brett McLaughlin | |
69 * @author Jason Hunter | |
70 * @author Steven Gould | |
71 */ | |
72 | |
73 public class ProcessingInstruction extends Content { | |
74 | |
75 private static final String CVS_ID = | |
76 "@(#) $RCSfile: ProcessingInstruction.java,v $ $Revision: 1.47 $ $Date: 2007/11/10 05:28:59 $ $Name: jdom_1_1_1 $"; | |
77 | |
78 /** The target of the PI */ | |
79 protected String target; | |
80 | |
81 /** The data for the PI as a String */ | |
82 protected String rawData; | |
83 | |
84 /** The data for the PI in name/value pairs */ | |
85 protected Map mapData; | |
86 | |
87 /** | |
88 * Default, no-args constructor for implementations | |
89 * to use if needed. | |
90 */ | |
91 protected ProcessingInstruction() { } | |
92 | |
93 /** | |
94 * This will create a new <code>ProcessingInstruction</code> | |
95 * with the specified target and data. | |
96 * | |
97 * @param target <code>String</code> target of PI. | |
98 * @param data <code>Map</code> data for PI, in | |
99 * name/value pairs | |
100 * @throws IllegalTargetException if the given target is illegal | |
101 * as a processing instruction name. | |
102 */ | |
103 public ProcessingInstruction(String target, Map data) { | |
104 setTarget(target); | |
105 setData(data); | |
106 } | |
107 | |
108 /** | |
109 * This will create a new <code>ProcessingInstruction</code> | |
110 * with the specified target and data. | |
111 * | |
112 * @param target <code>String</code> target of PI. | |
113 * @param data <code>String</code> data for PI. | |
114 * @throws IllegalTargetException if the given target is illegal | |
115 * as a processing instruction name. | |
116 */ | |
117 public ProcessingInstruction(String target, String data) { | |
118 setTarget(target); | |
119 setData(data); | |
120 } | |
121 | |
122 /** | |
123 * This will set the target for the PI. | |
124 * | |
125 * @param newTarget <code>String</code> new target of PI. | |
126 * @return <code>ProcessingInstruction</code> - this PI modified. | |
127 */ | |
128 public ProcessingInstruction setTarget(String newTarget) { | |
129 String reason; | |
130 if ((reason = Verifier.checkProcessingInstructionTarget(newTarget)) | |
131 != null) { | |
132 throw new IllegalTargetException(newTarget, reason); | |
133 } | |
134 | |
135 target = newTarget; | |
136 return this; | |
137 } | |
138 | |
139 /** | |
140 * Returns the XPath 1.0 string value of this element, which is the | |
141 * data of this PI. | |
142 * | |
143 * @return the data of this PI | |
144 */ | |
145 public String getValue() { | |
146 return rawData; | |
147 } | |
148 | |
149 | |
150 /** | |
151 * This will retrieve the target of the PI. | |
152 * | |
153 * @return <code>String</code> - target of PI. | |
154 */ | |
155 public String getTarget() { | |
156 return target; | |
157 } | |
158 | |
159 /** | |
160 * This will return the raw data from all instructions. | |
161 * | |
162 * @return <code>String</code> - data of PI. | |
163 */ | |
164 public String getData() { | |
165 return rawData; | |
166 } | |
167 | |
168 /** | |
169 * This will return a <code>List</code> containing the names of the | |
170 * "attribute" style pieces of name/value pairs in this PI's data. | |
171 * | |
172 * @return <code>List</code> - the <code>List</code> containing the | |
173 * "attribute" names. | |
174 */ | |
175 public List getPseudoAttributeNames() { | |
176 Set mapDataSet = mapData.entrySet(); | |
177 List nameList = new ArrayList(); | |
178 for (Iterator i = mapDataSet.iterator(); i.hasNext();) { | |
179 String wholeSet = (i.next()).toString(); | |
180 String attrName = wholeSet.substring(0,(wholeSet.indexOf("="))); | |
181 nameList.add(attrName); | |
182 } | |
183 return nameList; | |
184 } | |
185 | |
186 /** | |
187 * This will set the raw data for the PI. | |
188 * | |
189 * @param data <code>String</code> data of PI. | |
190 * @return <code>ProcessingInstruction</code> - this PI modified. | |
191 */ | |
192 public ProcessingInstruction setData(String data) { | |
193 String reason = Verifier.checkProcessingInstructionData(data); | |
194 if (reason != null) { | |
195 throw new IllegalDataException(data, reason); | |
196 } | |
197 | |
198 this.rawData = data; | |
199 this.mapData = parseData(data); | |
200 return this; | |
201 } | |
202 | |
203 /** | |
204 * This will set the name/value pairs within the passed | |
205 * <code>Map</code> as the pairs for the data of | |
206 * this PI. The keys should be the pair name | |
207 * and the values should be the pair values. | |
208 * | |
209 * @param data new map data to use | |
210 * @return <code>ProcessingInstruction</code> - modified PI. | |
211 */ | |
212 public ProcessingInstruction setData(Map data) { | |
213 String temp = toString(data); | |
214 | |
215 String reason = Verifier.checkProcessingInstructionData(temp); | |
216 if (reason != null) { | |
217 throw new IllegalDataException(temp, reason); | |
218 } | |
219 | |
220 this.rawData = temp; | |
221 this.mapData = data; | |
222 return this; | |
223 } | |
224 | |
225 | |
226 /** | |
227 * This will return the value for a specific | |
228 * name/value pair on the PI. If no such pair is | |
229 * found for this PI, null is returned. | |
230 * | |
231 * @param name <code>String</code> name of name/value pair | |
232 * to lookup value for. | |
233 * @return <code>String</code> - value of name/value pair. | |
234 */ | |
235 public String getPseudoAttributeValue(String name) { | |
236 return (String)mapData.get(name); | |
237 } | |
238 | |
239 /** | |
240 * This will set a pseudo attribute with the given name and value. | |
241 * If the PI data is not already in a pseudo-attribute format, this will | |
242 * replace the existing data. | |
243 * | |
244 * @param name <code>String</code> name of pair. | |
245 * @param value <code>String</code> value for pair. | |
246 * @return <code>ProcessingInstruction</code> this PI modified. | |
247 */ | |
248 public ProcessingInstruction setPseudoAttribute(String name, String value) { | |
249 String reason = Verifier.checkProcessingInstructionData(name); | |
250 if (reason != null) { | |
251 throw new IllegalDataException(name, reason); | |
252 } | |
253 | |
254 reason = Verifier.checkProcessingInstructionData(value); | |
255 if (reason != null) { | |
256 throw new IllegalDataException(value, reason); | |
257 } | |
258 | |
259 this.mapData.put(name, value); | |
260 this.rawData = toString(mapData); | |
261 return this; | |
262 } | |
263 | |
264 | |
265 /** | |
266 * This will remove the pseudo attribute with the specified name. | |
267 * | |
268 * @param name name of pseudo attribute to remove | |
269 * @return <code>boolean</code> - whether the requested | |
270 * instruction was removed. | |
271 */ | |
272 public boolean removePseudoAttribute(String name) { | |
273 if ((mapData.remove(name)) != null) { | |
274 rawData = toString(mapData); | |
275 return true; | |
276 } | |
277 | |
278 return false; | |
279 } | |
280 | |
281 /** | |
282 * This will convert the Map to a string representation. | |
283 * | |
284 * @param mapData <code>Map</code> PI data to convert | |
285 * @return a string representation of the Map as appropriate for a PI | |
286 */ | |
287 private String toString(Map mapData) { | |
288 StringBuffer rawData = new StringBuffer(); | |
289 | |
290 Iterator i = mapData.keySet().iterator(); | |
291 while (i.hasNext()) { | |
292 String name = (String)i.next(); | |
293 String value = (String)mapData.get(name); | |
294 rawData.append(name) | |
295 .append("=\"") | |
296 .append(value) | |
297 .append("\" "); | |
298 } | |
299 // Remove last space, if we did any appending | |
300 if (rawData.length() > 0) { | |
301 rawData.setLength(rawData.length() - 1); | |
302 } | |
303 | |
304 return rawData.toString(); | |
305 } | |
306 | |
307 /** | |
308 * This will parse and load the instructions for the PI. | |
309 * This is separated to allow it to occur once and then be reused. | |
310 */ | |
311 private Map parseData(String rawData) { | |
312 // The parsing here is done largely "by hand" which means the code | |
313 // gets a little tricky/messy. The following conditions should | |
314 // now be handled correctly: | |
315 // <?pi href="http://hi/a=b"?> Reads OK | |
316 // <?pi href = 'http://hi/a=b' ?> Reads OK | |
317 // <?pi href\t = \t'http://hi/a=b'?> Reads OK | |
318 // <?pi href = "http://hi/a=b"?> Reads OK | |
319 // <?pi?> Empty Map | |
320 // <?pi id=22?> Empty Map | |
321 // <?pi id='22?> Empty Map | |
322 | |
323 Map data = new HashMap(); | |
324 | |
325 // System.out.println("rawData: " + rawData); | |
326 | |
327 // The inputData variable holds the part of rawData left to parse | |
328 String inputData = rawData.trim(); | |
329 | |
330 // Iterate through the remaining inputData string | |
331 while (!inputData.trim().equals("")) { | |
332 //System.out.println("parseData() looking at: " + inputData); | |
333 | |
334 // Search for "name =", "name=" or "name1 name2..." | |
335 String name = ""; | |
336 String value = ""; | |
337 int startName = 0; | |
338 char previousChar = inputData.charAt(startName); | |
339 int pos = 1; | |
340 for (; pos<inputData.length(); pos++) { | |
341 char currentChar = inputData.charAt(pos); | |
342 if (currentChar == '=') { | |
343 name = inputData.substring(startName, pos).trim(); | |
344 // Get the boundaries on the quoted string | |
345 // We use boundaries so we know where to start next | |
346 int[] bounds = extractQuotedString( | |
347 inputData.substring(pos+1)); | |
348 // A null value means a parse error and we return empty! | |
349 if (bounds == null) { | |
350 return new HashMap(); | |
351 } | |
352 value = inputData.substring(bounds[0]+pos+1, | |
353 bounds[1]+pos+1); | |
354 pos += bounds[1] + 1; // skip past value | |
355 break; | |
356 } | |
357 else if (Character.isWhitespace(previousChar) | |
358 && !Character.isWhitespace(currentChar)) { | |
359 startName = pos; | |
360 } | |
361 | |
362 previousChar = currentChar; | |
363 } | |
364 | |
365 // Remove the first pos characters; they have been processed | |
366 inputData = inputData.substring(pos); | |
367 | |
368 // System.out.println("Extracted (name, value) pair: (" | |
369 // + name + ", '" + value+"')"); | |
370 | |
371 // If both a name and a value have been found, then add | |
372 // them to the data Map | |
373 if (name.length() > 0 && value != null) { | |
374 //if (data.containsKey(name)) { | |
375 // A repeat, that's a parse error, so return a null map | |
376 //return new HashMap(); | |
377 //} | |
378 //else { | |
379 data.put(name, value); | |
380 //} | |
381 } | |
382 } | |
383 | |
384 return data; | |
385 } | |
386 | |
387 /** | |
388 * This is a helper routine, only used by parseData, to extract a | |
389 * quoted String from the input parameter, rawData. A quoted string | |
390 * can use either single or double quotes, but they must match up. | |
391 * A singly quoted string can contain an unbalanced amount of double | |
392 * quotes, or vice versa. For example, the String "JDOM's the best" | |
393 * is legal as is 'JDOM"s the best'. | |
394 * | |
395 * @param rawData the input string from which a quoted string is to | |
396 * be extracted. | |
397 * @return the first quoted string encountered in the input data. If | |
398 * no quoted string is found, then the empty string, "", is | |
399 * returned. | |
400 * @see #parseData | |
401 */ | |
402 private static int[] extractQuotedString(String rawData) { | |
403 // Remembers whether we're actually in a quoted string yet | |
404 boolean inQuotes = false; | |
405 | |
406 // Remembers which type of quoted string we're in | |
407 char quoteChar = '"'; | |
408 | |
409 // Stores the position of the first character inside | |
410 // the quoted string (i.e. the start of the return string) | |
411 int start = 0; | |
412 | |
413 // Iterate through the input string looking for the start | |
414 // and end of the quoted string | |
415 for (int pos=0; pos < rawData.length(); pos++) { | |
416 char currentChar = rawData.charAt(pos); | |
417 if (currentChar=='"' || currentChar=='\'') { | |
418 if (!inQuotes) { | |
419 // We're entering a quoted string | |
420 quoteChar = currentChar; | |
421 inQuotes = true; | |
422 start = pos+1; | |
423 } | |
424 else if (quoteChar == currentChar) { | |
425 // We're leaving a quoted string | |
426 inQuotes = false; | |
427 return new int[] { start, pos }; | |
428 } | |
429 // Otherwise we've encountered a quote | |
430 // inside a quote, so just continue | |
431 } | |
432 } | |
433 | |
434 return null; | |
435 } | |
436 | |
437 /** | |
438 * This returns a <code>String</code> representation of the | |
439 * <code>ProcessingInstruction</code>, suitable for debugging. If the XML | |
440 * representation of the <code>ProcessingInstruction</code> is desired, | |
441 * {@link org.jdom.output.XMLOutputter#outputString(ProcessingInstruction)} | |
442 * should be used. | |
443 * | |
444 * @return <code>String</code> - information about the | |
445 * <code>ProcessingInstruction</code> | |
446 */ | |
447 public String toString() { | |
448 return new StringBuffer() | |
449 .append("[ProcessingInstruction: ") | |
450 .append(new org.jdom.output.XMLOutputter().outputString(this)) | |
451 .append("]") | |
452 .toString(); | |
453 } | |
454 | |
455 /** | |
456 * This will return a clone of this <code>ProcessingInstruction</code>. | |
457 * | |
458 * @return <code>Object</code> - clone of this | |
459 * <code>ProcessingInstruction</code>. | |
460 */ | |
461 public Object clone() { | |
462 ProcessingInstruction pi = (ProcessingInstruction) super.clone(); | |
463 | |
464 // target and rawdata are immutable and references copied by | |
465 // Object.clone() | |
466 | |
467 // Create a new Map object for the clone (since Map isn't Cloneable) | |
468 if (mapData != null) { | |
469 pi.mapData = parseData(rawData); | |
470 } | |
471 return pi; | |
472 } | |
473 } |