1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.jme3.export.xml; 34 35 import com.jme3.export.FormatVersion; 36 import com.jme3.export.JmeExporter; 37 import com.jme3.export.OutputCapsule; 38 import com.jme3.export.Savable; 39 import com.jme3.export.SavableClassUtil; 40 import com.jme3.util.IntMap; 41 import com.jme3.util.IntMap.Entry; 42 import java.io.IOException; 43 import java.nio.ByteBuffer; 44 import java.nio.FloatBuffer; 45 import java.nio.IntBuffer; 46 import java.nio.ShortBuffer; 47 import java.util.*; 48 import org.w3c.dom.DOMException; 49 import org.w3c.dom.Document; 50 import org.w3c.dom.Element; 51 52 /** 53 * Part of the jME XML IO system as introduced in the google code jmexml project. 54 * 55 * @author Kai Rabien (hevee) - original author of the code.google.com jmexml project 56 * @author Doug Daniels (dougnukem) - adjustments for jME 2.0 and Java 1.5 57 */ 58 public class DOMOutputCapsule implements OutputCapsule { 59 60 private static final String dataAttributeName = "data"; 61 private Document doc; 62 private Element currentElement; 63 private JmeExporter exporter; 64 private Map<Savable, Element> writtenSavables = new IdentityHashMap<Savable, Element>(); 65 DOMOutputCapsule(Document doc, JmeExporter exporter)66 public DOMOutputCapsule(Document doc, JmeExporter exporter) { 67 this.doc = doc; 68 this.exporter = exporter; 69 currentElement = null; 70 } 71 getDoc()72 public Document getDoc() { 73 return doc; 74 } 75 76 /** 77 * appends a new Element with the given name to currentElement, sets 78 * currentElement to be new Element, and returns the new Element as well 79 */ appendElement(String name)80 private Element appendElement(String name) { 81 Element ret = doc.createElement(name); 82 if (currentElement == null) { 83 ret.setAttribute("format_version", Integer.toString(FormatVersion.VERSION)); 84 doc.appendChild(ret); 85 } else { 86 currentElement.appendChild(ret); 87 } 88 currentElement = ret; 89 return ret; 90 } 91 encodeString(String s)92 private static String encodeString(String s) { 93 if (s == null) { 94 return null; 95 } 96 s = s.replaceAll("\\&", "&") 97 .replaceAll("\\\"", """) 98 .replaceAll("\\<", "<"); 99 return s; 100 } 101 write(byte value, String name, byte defVal)102 public void write(byte value, String name, byte defVal) throws IOException { 103 if (value == defVal) { 104 return; 105 } 106 currentElement.setAttribute(name, String.valueOf(value)); 107 } 108 write(byte[] value, String name, byte[] defVal)109 public void write(byte[] value, String name, byte[] defVal) throws IOException { 110 StringBuilder buf = new StringBuilder(); 111 if (value == null) { 112 value = defVal; 113 } 114 for (byte b : value) { 115 buf.append(b); 116 buf.append(" "); 117 } 118 //remove last space 119 buf.setLength(buf.length() - 1); 120 121 Element el = appendElement(name); 122 el.setAttribute("size", String.valueOf(value.length)); 123 el.setAttribute(dataAttributeName, buf.toString()); 124 currentElement = (Element) currentElement.getParentNode(); 125 } 126 write(byte[][] value, String name, byte[][] defVal)127 public void write(byte[][] value, String name, byte[][] defVal) throws IOException { 128 StringBuilder buf = new StringBuilder(); 129 if (value == null) { 130 value = defVal; 131 } 132 for (byte[] bs : value) { 133 for (byte b : bs) { 134 buf.append(b); 135 buf.append(" "); 136 } 137 buf.append(" "); 138 } 139 //remove last spaces 140 buf.setLength(buf.length() - 2); 141 142 Element el = appendElement(name); 143 el.setAttribute("size_outer", String.valueOf(value.length)); 144 el.setAttribute("size_inner", String.valueOf(value[0].length)); 145 el.setAttribute(dataAttributeName, buf.toString()); 146 currentElement = (Element) currentElement.getParentNode(); 147 } 148 write(int value, String name, int defVal)149 public void write(int value, String name, int defVal) throws IOException { 150 if (value == defVal) { 151 return; 152 } 153 currentElement.setAttribute(name, String.valueOf(value)); 154 } 155 write(int[] value, String name, int[] defVal)156 public void write(int[] value, String name, int[] defVal) throws IOException { 157 StringBuilder buf = new StringBuilder(); 158 if (value == null) { return; } 159 if (Arrays.equals(value, defVal)) { return; } 160 161 for (int b : value) { 162 buf.append(b); 163 buf.append(" "); 164 } 165 //remove last space 166 buf.setLength(Math.max(0, buf.length() - 1)); 167 168 Element el = appendElement(name); 169 el.setAttribute("size", String.valueOf(value.length)); 170 el.setAttribute(dataAttributeName, buf.toString()); 171 currentElement = (Element) currentElement.getParentNode(); 172 } 173 write(int[][] value, String name, int[][] defVal)174 public void write(int[][] value, String name, int[][] defVal) throws IOException { 175 if (value == null) return; 176 if(Arrays.deepEquals(value, defVal)) return; 177 178 Element el = appendElement(name); 179 el.setAttribute("size", String.valueOf(value.length)); 180 181 for (int i=0; i<value.length; i++) { 182 int[] array = value[i]; 183 write(array, "array_"+i, defVal==null?null:defVal[i]); 184 } 185 currentElement = (Element) el.getParentNode(); 186 } 187 write(float value, String name, float defVal)188 public void write(float value, String name, float defVal) throws IOException { 189 if (value == defVal) { 190 return; 191 } 192 currentElement.setAttribute(name, String.valueOf(value)); 193 } 194 write(float[] value, String name, float[] defVal)195 public void write(float[] value, String name, float[] defVal) throws IOException { 196 StringBuilder buf = new StringBuilder(); 197 if (value == null) { 198 value = defVal; 199 } 200 if (value != null) { 201 for (float b : value) { 202 buf.append(b); 203 buf.append(" "); 204 } 205 //remove last space 206 buf.setLength(buf.length() - 1); 207 } 208 209 Element el = appendElement(name); 210 el.setAttribute("size", value == null ? "0" : String.valueOf(value.length)); 211 el.setAttribute(dataAttributeName, buf.toString()); 212 currentElement = (Element) currentElement.getParentNode(); 213 } 214 write(float[][] value, String name, float[][] defVal)215 public void write(float[][] value, String name, float[][] defVal) throws IOException { 216 StringBuilder buf = new StringBuilder(); 217 if (value == null) return; 218 if(Arrays.deepEquals(value, defVal)) return; 219 220 for (float[] bs : value) { 221 for(float b : bs){ 222 buf.append(b); 223 buf.append(" "); 224 } 225 } 226 //remove last space 227 buf.setLength(buf.length() - 1); 228 229 Element el = appendElement(name); 230 el.setAttribute("size_outer", String.valueOf(value.length)); 231 el.setAttribute("size_inner", String.valueOf(value[0].length)); 232 el.setAttribute(dataAttributeName, buf.toString()); 233 currentElement = (Element) currentElement.getParentNode(); 234 } 235 write(double value, String name, double defVal)236 public void write(double value, String name, double defVal) throws IOException { 237 if (value == defVal) { 238 return; 239 } 240 currentElement.setAttribute(name, String.valueOf(value)); 241 } 242 write(double[] value, String name, double[] defVal)243 public void write(double[] value, String name, double[] defVal) throws IOException { 244 StringBuilder buf = new StringBuilder(); 245 if (value == null) { 246 value = defVal; 247 } 248 for (double b : value) { 249 buf.append(b); 250 buf.append(" "); 251 } 252 //remove last space 253 buf.setLength(buf.length() - 1); 254 255 Element el = appendElement(name); 256 el.setAttribute("size", String.valueOf(value.length)); 257 el.setAttribute(dataAttributeName, buf.toString()); 258 currentElement = (Element) currentElement.getParentNode(); 259 } 260 write(double[][] value, String name, double[][] defVal)261 public void write(double[][] value, String name, double[][] defVal) throws IOException { 262 if (value == null) return; 263 if(Arrays.deepEquals(value, defVal)) return; 264 265 Element el = appendElement(name); 266 el.setAttribute("size", String.valueOf(value.length)); 267 268 for (int i=0; i<value.length; i++) { 269 double[] array = value[i]; 270 write(array, "array_"+i, defVal==null?null:defVal[i]); 271 } 272 currentElement = (Element) el.getParentNode(); 273 } 274 write(long value, String name, long defVal)275 public void write(long value, String name, long defVal) throws IOException { 276 if (value == defVal) { 277 return; 278 } 279 currentElement.setAttribute(name, String.valueOf(value)); 280 } 281 write(long[] value, String name, long[] defVal)282 public void write(long[] value, String name, long[] defVal) throws IOException { 283 StringBuilder buf = new StringBuilder(); 284 if (value == null) { 285 value = defVal; 286 } 287 for (long b : value) { 288 buf.append(b); 289 buf.append(" "); 290 } 291 //remove last space 292 buf.setLength(buf.length() - 1); 293 294 Element el = appendElement(name); 295 el.setAttribute("size", String.valueOf(value.length)); 296 el.setAttribute(dataAttributeName, buf.toString()); 297 currentElement = (Element) currentElement.getParentNode(); 298 } 299 write(long[][] value, String name, long[][] defVal)300 public void write(long[][] value, String name, long[][] defVal) throws IOException { 301 if (value == null) return; 302 if(Arrays.deepEquals(value, defVal)) return; 303 304 Element el = appendElement(name); 305 el.setAttribute("size", String.valueOf(value.length)); 306 307 for (int i=0; i<value.length; i++) { 308 long[] array = value[i]; 309 write(array, "array_"+i, defVal==null?null:defVal[i]); 310 } 311 currentElement = (Element) el.getParentNode(); 312 } 313 write(short value, String name, short defVal)314 public void write(short value, String name, short defVal) throws IOException { 315 if (value == defVal) { 316 return; 317 } 318 currentElement.setAttribute(name, String.valueOf(value)); 319 } 320 write(short[] value, String name, short[] defVal)321 public void write(short[] value, String name, short[] defVal) throws IOException { 322 StringBuilder buf = new StringBuilder(); 323 if (value == null) { 324 value = defVal; 325 } 326 for (short b : value) { 327 buf.append(b); 328 buf.append(" "); 329 } 330 //remove last space 331 buf.setLength(buf.length() - 1); 332 333 Element el = appendElement(name); 334 el.setAttribute("size", String.valueOf(value.length)); 335 el.setAttribute(dataAttributeName, buf.toString()); 336 currentElement = (Element) currentElement.getParentNode(); 337 } 338 write(short[][] value, String name, short[][] defVal)339 public void write(short[][] value, String name, short[][] defVal) throws IOException { 340 if (value == null) return; 341 if(Arrays.deepEquals(value, defVal)) return; 342 343 Element el = appendElement(name); 344 el.setAttribute("size", String.valueOf(value.length)); 345 346 for (int i=0; i<value.length; i++) { 347 short[] array = value[i]; 348 write(array, "array_"+i, defVal==null?null:defVal[i]); 349 } 350 currentElement = (Element) el.getParentNode(); 351 } 352 write(boolean value, String name, boolean defVal)353 public void write(boolean value, String name, boolean defVal) throws IOException { 354 if (value == defVal) { 355 return; 356 } 357 currentElement.setAttribute(name, String.valueOf(value)); 358 } 359 write(boolean[] value, String name, boolean[] defVal)360 public void write(boolean[] value, String name, boolean[] defVal) throws IOException { 361 StringBuilder buf = new StringBuilder(); 362 if (value == null) { 363 value = defVal; 364 } 365 for (boolean b : value) { 366 buf.append(b); 367 buf.append(" "); 368 } 369 //remove last space 370 buf.setLength(Math.max(0, buf.length() - 1)); 371 372 Element el = appendElement(name); 373 el.setAttribute("size", String.valueOf(value.length)); 374 el.setAttribute(dataAttributeName, buf.toString()); 375 currentElement = (Element) currentElement.getParentNode(); 376 } 377 write(boolean[][] value, String name, boolean[][] defVal)378 public void write(boolean[][] value, String name, boolean[][] defVal) throws IOException { 379 if (value == null) return; 380 if(Arrays.deepEquals(value, defVal)) return; 381 382 Element el = appendElement(name); 383 el.setAttribute("size", String.valueOf(value.length)); 384 385 for (int i=0; i<value.length; i++) { 386 boolean[] array = value[i]; 387 write(array, "array_"+i, defVal==null?null:defVal[i]); 388 } 389 currentElement = (Element) el.getParentNode(); 390 } 391 write(String value, String name, String defVal)392 public void write(String value, String name, String defVal) throws IOException { 393 if (value == null || value.equals(defVal)) { 394 return; 395 } 396 currentElement.setAttribute(name, encodeString(value)); 397 } 398 write(String[] value, String name, String[] defVal)399 public void write(String[] value, String name, String[] defVal) throws IOException { 400 Element el = appendElement(name); 401 402 if (value == null) { 403 value = defVal; 404 } 405 406 el.setAttribute("size", String.valueOf(value.length)); 407 408 for (int i=0; i<value.length; i++) { 409 String b = value[i]; 410 appendElement("String_"+i); 411 String val = encodeString(b); 412 currentElement.setAttribute("value", val); 413 currentElement = el; 414 } 415 currentElement = (Element) currentElement.getParentNode(); 416 } 417 write(String[][] value, String name, String[][] defVal)418 public void write(String[][] value, String name, String[][] defVal) throws IOException { 419 if (value == null) return; 420 if(Arrays.deepEquals(value, defVal)) return; 421 422 Element el = appendElement(name); 423 el.setAttribute("size", String.valueOf(value.length)); 424 425 for (int i=0; i<value.length; i++) { 426 String[] array = value[i]; 427 write(array, "array_"+i, defVal==null?null:defVal[i]); 428 } 429 currentElement = (Element) el.getParentNode(); 430 } 431 write(BitSet value, String name, BitSet defVal)432 public void write(BitSet value, String name, BitSet defVal) throws IOException { 433 if (value == null || value.equals(defVal)) { 434 return; 435 } 436 StringBuilder buf = new StringBuilder(); 437 for (int i = value.nextSetBit(0); i >= 0; i = value.nextSetBit(i + 1)) { 438 buf.append(i); 439 buf.append(" "); 440 } 441 buf.setLength(Math.max(0, buf.length() - 1)); 442 currentElement.setAttribute(name, buf.toString()); 443 444 } 445 write(Savable object, String name, Savable defVal)446 public void write(Savable object, String name, Savable defVal) throws IOException { 447 if (object == null) { 448 return; 449 } 450 if (object.equals(defVal)) { 451 return; 452 } 453 454 Element old = currentElement; 455 Element el = writtenSavables.get(object); 456 457 String className = null; 458 if(!object.getClass().getName().equals(name)){ 459 className = object.getClass().getName(); 460 } 461 try { 462 doc.createElement(name); 463 } catch (DOMException e) { 464 // Ridiculous fallback behavior. 465 // Would be far better to throw than to totally disregard the 466 // specified "name" and write a class name instead! 467 // (Besides the fact we are clobbering the managed .getClassTag()). 468 name = "Object"; 469 className = object.getClass().getName(); 470 } 471 472 if (el != null) { 473 String refID = el.getAttribute("reference_ID"); 474 if (refID.length() == 0) { 475 refID = object.getClass().getName() + "@" + object.hashCode(); 476 el.setAttribute("reference_ID", refID); 477 } 478 el = appendElement(name); 479 el.setAttribute("ref", refID); 480 } else { 481 el = appendElement(name); 482 483 // jME3 NEW: Append version number(s) 484 int[] versions = SavableClassUtil.getSavableVersions(object.getClass()); 485 StringBuilder sb = new StringBuilder(); 486 for (int i = 0; i < versions.length; i++){ 487 sb.append(versions[i]); 488 if (i != versions.length - 1){ 489 sb.append(", "); 490 } 491 } 492 el.setAttribute("savable_versions", sb.toString()); 493 494 writtenSavables.put(object, el); 495 object.write(exporter); 496 } 497 if(className != null){ 498 el.setAttribute("class", className); 499 } 500 501 currentElement = old; 502 } 503 write(Savable[] objects, String name, Savable[] defVal)504 public void write(Savable[] objects, String name, Savable[] defVal) throws IOException { 505 if (objects == null) { 506 return; 507 } 508 if (Arrays.equals(objects, defVal)) { 509 return; 510 } 511 512 Element old = currentElement; 513 Element el = appendElement(name); 514 el.setAttribute("size", String.valueOf(objects.length)); 515 for (int i = 0; i < objects.length; i++) { 516 Savable o = objects[i]; 517 if(o == null){ 518 //renderStateList has special loading code, so we can leave out the null values 519 if(!name.equals("renderStateList")){ 520 Element before = currentElement; 521 appendElement("null"); 522 currentElement = before; 523 } 524 }else{ 525 write(o, o.getClass().getName(), null); 526 } 527 } 528 currentElement = old; 529 } 530 write(Savable[][] value, String name, Savable[][] defVal)531 public void write(Savable[][] value, String name, Savable[][] defVal) throws IOException { 532 if (value == null) return; 533 if(Arrays.deepEquals(value, defVal)) return; 534 535 Element el = appendElement(name); 536 el.setAttribute("size_outer", String.valueOf(value.length)); 537 el.setAttribute("size_inner", String.valueOf(value[0].length)); 538 for (Savable[] bs : value) { 539 for(Savable b : bs){ 540 write(b, b.getClass().getSimpleName(), null); 541 } 542 } 543 currentElement = (Element) currentElement.getParentNode(); 544 } 545 writeSavableArrayList(ArrayList array, String name, ArrayList defVal)546 public void writeSavableArrayList(ArrayList array, String name, ArrayList defVal) throws IOException { 547 if (array == null) { 548 return; 549 } 550 if (array.equals(defVal)) { 551 return; 552 } 553 Element old = currentElement; 554 Element el = appendElement(name); 555 currentElement = el; 556 el.setAttribute(XMLExporter.ATTRIBUTE_SIZE, String.valueOf(array.size())); 557 for (Object o : array) { 558 if(o == null) { 559 continue; 560 } 561 else if (o instanceof Savable) { 562 Savable s = (Savable) o; 563 write(s, s.getClass().getName(), null); 564 } else { 565 throw new ClassCastException("Not a Savable instance: " + o); 566 } 567 } 568 currentElement = old; 569 } 570 writeSavableArrayListArray(ArrayList[] objects, String name, ArrayList[] defVal)571 public void writeSavableArrayListArray(ArrayList[] objects, String name, ArrayList[] defVal) throws IOException { 572 if (objects == null) {return;} 573 if (Arrays.equals(objects, defVal)) {return;} 574 575 Element old = currentElement; 576 Element el = appendElement(name); 577 el.setAttribute(XMLExporter.ATTRIBUTE_SIZE, String.valueOf(objects.length)); 578 for (int i = 0; i < objects.length; i++) { 579 ArrayList o = objects[i]; 580 if(o == null){ 581 Element before = currentElement; 582 appendElement("null"); 583 currentElement = before; 584 }else{ 585 StringBuilder buf = new StringBuilder("SavableArrayList_"); 586 buf.append(i); 587 writeSavableArrayList(o, buf.toString(), null); 588 } 589 } 590 currentElement = old; 591 } 592 writeSavableArrayListArray2D(ArrayList[][] value, String name, ArrayList[][] defVal)593 public void writeSavableArrayListArray2D(ArrayList[][] value, String name, ArrayList[][] defVal) throws IOException { 594 if (value == null) return; 595 if(Arrays.deepEquals(value, defVal)) return; 596 597 Element el = appendElement(name); 598 int size = value.length; 599 el.setAttribute(XMLExporter.ATTRIBUTE_SIZE, String.valueOf(size)); 600 601 for (int i=0; i< size; i++) { 602 ArrayList[] vi = value[i]; 603 writeSavableArrayListArray(vi, "SavableArrayListArray_"+i, null); 604 } 605 currentElement = (Element) el.getParentNode(); 606 } 607 writeFloatBufferArrayList(ArrayList<FloatBuffer> array, String name, ArrayList<FloatBuffer> defVal)608 public void writeFloatBufferArrayList(ArrayList<FloatBuffer> array, String name, ArrayList<FloatBuffer> defVal) throws IOException { 609 if (array == null) { 610 return; 611 } 612 if (array.equals(defVal)) { 613 return; 614 } 615 Element el = appendElement(name); 616 el.setAttribute(XMLExporter.ATTRIBUTE_SIZE, String.valueOf(array.size())); 617 for (FloatBuffer o : array) { 618 write(o, XMLExporter.ELEMENT_FLOATBUFFER, null); 619 } 620 currentElement = (Element) el.getParentNode(); 621 } 622 writeSavableMap(Map<? extends Savable, ? extends Savable> map, String name, Map<? extends Savable, ? extends Savable> defVal)623 public void writeSavableMap(Map<? extends Savable, ? extends Savable> map, String name, Map<? extends Savable, ? extends Savable> defVal) throws IOException { 624 if (map == null) { 625 return; 626 } 627 if (map.equals(defVal)) { 628 return; 629 } 630 Element stringMap = appendElement(name); 631 632 Iterator<? extends Savable> keyIterator = map.keySet().iterator(); 633 while(keyIterator.hasNext()) { 634 Savable key = keyIterator.next(); 635 Element mapEntry = appendElement(XMLExporter.ELEMENT_MAPENTRY); 636 write(key, XMLExporter.ELEMENT_KEY, null); 637 Savable value = map.get(key); 638 write(value, XMLExporter.ELEMENT_VALUE, null); 639 currentElement = stringMap; 640 } 641 642 currentElement = (Element) stringMap.getParentNode(); 643 } 644 writeStringSavableMap(Map<String, ? extends Savable> map, String name, Map<String, ? extends Savable> defVal)645 public void writeStringSavableMap(Map<String, ? extends Savable> map, String name, Map<String, ? extends Savable> defVal) throws IOException { 646 if (map == null) { 647 return; 648 } 649 if (map.equals(defVal)) { 650 return; 651 } 652 Element stringMap = appendElement(name); 653 654 Iterator<String> keyIterator = map.keySet().iterator(); 655 while(keyIterator.hasNext()) { 656 String key = keyIterator.next(); 657 Element mapEntry = appendElement("MapEntry"); 658 mapEntry.setAttribute("key", key); 659 Savable s = map.get(key); 660 write(s, "Savable", null); 661 currentElement = stringMap; 662 } 663 664 currentElement = (Element) stringMap.getParentNode(); 665 } 666 writeIntSavableMap(IntMap<? extends Savable> map, String name, IntMap<? extends Savable> defVal)667 public void writeIntSavableMap(IntMap<? extends Savable> map, String name, IntMap<? extends Savable> defVal) throws IOException { 668 if (map == null) { 669 return; 670 } 671 if (map.equals(defVal)) { 672 return; 673 } 674 Element stringMap = appendElement(name); 675 676 for(Entry<? extends Savable> entry : map) { 677 int key = entry.getKey(); 678 Element mapEntry = appendElement("MapEntry"); 679 mapEntry.setAttribute("key", Integer.toString(key)); 680 Savable s = entry.getValue(); 681 write(s, "Savable", null); 682 currentElement = stringMap; 683 } 684 685 currentElement = (Element) stringMap.getParentNode(); 686 } 687 write(FloatBuffer value, String name, FloatBuffer defVal)688 public void write(FloatBuffer value, String name, FloatBuffer defVal) throws IOException { 689 if (value == null) { 690 return; 691 } 692 693 Element el = appendElement(name); 694 el.setAttribute("size", String.valueOf(value.limit())); 695 StringBuilder buf = new StringBuilder(); 696 int pos = value.position(); 697 value.rewind(); 698 int ctr = 0; 699 while (value.hasRemaining()) { 700 ctr++; 701 buf.append(value.get()); 702 buf.append(" "); 703 } 704 if (ctr != value.limit()) 705 throw new IOException("'" + name 706 + "' buffer contention resulted in write data consistency. " 707 + ctr + " values written when should have written " 708 + value.limit()); 709 buf.setLength(Math.max(0, buf.length() - 1)); 710 value.position(pos); 711 el.setAttribute(dataAttributeName, buf.toString()); 712 currentElement = (Element) el.getParentNode(); 713 } 714 write(IntBuffer value, String name, IntBuffer defVal)715 public void write(IntBuffer value, String name, IntBuffer defVal) throws IOException { 716 if (value == null) { 717 return; 718 } 719 if (value.equals(defVal)) { 720 return; 721 } 722 723 Element el = appendElement(name); 724 el.setAttribute("size", String.valueOf(value.limit())); 725 StringBuilder buf = new StringBuilder(); 726 int pos = value.position(); 727 value.rewind(); 728 int ctr = 0; 729 while (value.hasRemaining()) { 730 ctr++; 731 buf.append(value.get()); 732 buf.append(" "); 733 } 734 if (ctr != value.limit()) 735 throw new IOException("'" + name 736 + "' buffer contention resulted in write data consistency. " 737 + ctr + " values written when should have written " 738 + value.limit()); 739 buf.setLength(buf.length() - 1); 740 value.position(pos); 741 el.setAttribute(dataAttributeName, buf.toString()); 742 currentElement = (Element) el.getParentNode(); 743 } 744 write(ByteBuffer value, String name, ByteBuffer defVal)745 public void write(ByteBuffer value, String name, ByteBuffer defVal) throws IOException { 746 if (value == null) return; 747 if (value.equals(defVal)) return; 748 749 Element el = appendElement(name); 750 el.setAttribute("size", String.valueOf(value.limit())); 751 StringBuilder buf = new StringBuilder(); 752 int pos = value.position(); 753 value.rewind(); 754 int ctr = 0; 755 while (value.hasRemaining()) { 756 ctr++; 757 buf.append(value.get()); 758 buf.append(" "); 759 } 760 if (ctr != value.limit()) 761 throw new IOException("'" + name 762 + "' buffer contention resulted in write data consistency. " 763 + ctr + " values written when should have written " 764 + value.limit()); 765 buf.setLength(buf.length() - 1); 766 value.position(pos); 767 el.setAttribute(dataAttributeName, buf.toString()); 768 currentElement = (Element) el.getParentNode(); 769 } 770 write(ShortBuffer value, String name, ShortBuffer defVal)771 public void write(ShortBuffer value, String name, ShortBuffer defVal) throws IOException { 772 if (value == null) { 773 return; 774 } 775 if (value.equals(defVal)) { 776 return; 777 } 778 779 Element el = appendElement(name); 780 el.setAttribute("size", String.valueOf(value.limit())); 781 StringBuilder buf = new StringBuilder(); 782 int pos = value.position(); 783 value.rewind(); 784 int ctr = 0; 785 while (value.hasRemaining()) { 786 ctr++; 787 buf.append(value.get()); 788 buf.append(" "); 789 } 790 if (ctr != value.limit()) 791 throw new IOException("'" + name 792 + "' buffer contention resulted in write data consistency. " 793 + ctr + " values written when should have written " 794 + value.limit()); 795 buf.setLength(buf.length() - 1); 796 value.position(pos); 797 el.setAttribute(dataAttributeName, buf.toString()); 798 currentElement = (Element) el.getParentNode(); 799 } 800 write(Enum value, String name, Enum defVal)801 public void write(Enum value, String name, Enum defVal) throws IOException { 802 if (value == defVal) { 803 return; 804 } 805 currentElement.setAttribute(name, String.valueOf(value)); 806 807 } 808 writeByteBufferArrayList(ArrayList<ByteBuffer> array, String name, ArrayList<ByteBuffer> defVal)809 public void writeByteBufferArrayList(ArrayList<ByteBuffer> array, 810 String name, ArrayList<ByteBuffer> defVal) throws IOException { 811 if (array == null) { 812 return; 813 } 814 if (array.equals(defVal)) { 815 return; 816 } 817 Element el = appendElement(name); 818 el.setAttribute("size", String.valueOf(array.size())); 819 for (ByteBuffer o : array) { 820 write(o, "ByteBuffer", null); 821 } 822 currentElement = (Element) el.getParentNode(); 823 824 } 825 }