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 } |
