1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package goldengate.common.xml;
22
23 import java.io.File;
24 import java.io.FileWriter;
25 import java.io.IOException;
26 import java.io.InvalidObjectException;
27 import java.util.List;
28
29 import org.dom4j.Document;
30 import org.dom4j.DocumentException;
31 import org.dom4j.DocumentHelper;
32 import org.dom4j.Element;
33 import org.dom4j.io.OutputFormat;
34 import org.dom4j.io.SAXReader;
35 import org.dom4j.io.XMLWriter;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class XmlUtil {
53
54
55
56
57
58
59
60
61 static public Document getDocument(String filename) throws IOException,
62 DocumentException {
63 File file = new File(filename);
64 if (!file.canRead()) {
65 throw new IOException("File is not readable: " + filename);
66 }
67 return getDocument(file);
68 }
69
70
71
72
73
74
75
76
77 static public Document getDocument(File file) throws IOException,
78 DocumentException {
79 if (!file.canRead()) {
80 throw new IOException("File is not readable: " + file.getPath());
81 }
82 SAXReader reader = new SAXReader();
83 return reader.read(file);
84 }
85
86
87
88
89
90
91
92
93
94 static public Document readDocument(String document)
95 throws DocumentException {
96 return DocumentHelper.parseText(document);
97 }
98
99
100
101
102
103
104 static public String writeToString(Document document) {
105 return document.asXML();
106 }
107
108
109
110
111
112
113 static public String writeToString(Element element) {
114 return element.asXML();
115 }
116
117
118
119
120
121 static public Document createEmptyDocument() {
122 return DocumentHelper.createDocument();
123 }
124
125
126
127
128
129
130
131
132 static public void saveDocument(String filename, Document document)
133 throws IOException {
134 File file = new File(filename);
135 saveDocument(file, document);
136 }
137
138
139
140
141
142
143
144
145 static public void saveDocument(File file, Document document)
146 throws IOException {
147 if (file.exists() && (!file.canWrite())) {
148 throw new IOException("File is not writable: " + file.getPath());
149 }
150 OutputFormat format = OutputFormat.createPrettyPrint();
151 XMLWriter writer = new XMLWriter(new FileWriter(file), format);
152 writer.write(document);
153 writer.flush();
154 writer.close();
155 }
156
157
158
159
160
161
162
163
164 static public void saveElement(String filename, Element element)
165 throws IOException {
166 File file = new File(filename);
167 saveElement(file, element);
168 }
169
170
171
172
173
174
175
176
177 static public void saveElement(File file, Element element)
178 throws IOException {
179 if (file.exists() && (!file.canWrite())) {
180 throw new IOException("File is not writable: " + file.getPath());
181 }
182 OutputFormat format = OutputFormat.createPrettyPrint();
183 XMLWriter writer = new XMLWriter(new FileWriter(file), format);
184 writer.write(element);
185 writer.flush();
186 writer.close();
187 }
188
189
190
191
192
193
194 static public Element getRootElement(Document document) {
195 return document.getRootElement();
196 }
197
198
199
200
201
202
203
204
205
206
207 static public Element addOrSetElement(Element ref, String path, String value) {
208 Element current = addOrGetElement(ref, path);
209 current.setText(value);
210 return current;
211 }
212
213
214
215
216
217
218
219
220
221 static public Element addOrGetElement(Element ref, String path) {
222 String[] pathes = path.split("/");
223 Element current = ref;
224 for (String nodename: pathes) {
225 if (nodename.length() > 0) {
226 Element exist = current.element(nodename);
227 if (exist == null) {
228 current = current.addElement(nodename);
229 } else {
230 current = exist;
231 }
232 }
233 }
234 return current;
235 }
236
237
238
239
240
241
242
243
244
245 static public Element addAndSetElementMultiple(Element ref, String path,
246 String value) {
247 Element current = addAndGetElementMultiple(ref, path);
248 current.setText(value);
249 return current;
250 }
251
252
253
254
255
256
257
258
259 static public Element addAndGetElementMultiple(Element ref, String path) {
260 String[] pathes = path.split("/");
261 Element current = ref;
262 for (int i = 0; i < pathes.length - 1; i ++) {
263 String nodename = pathes[i];
264 if (nodename.length() > 0) {
265 Element exist = current.element(nodename);
266 if (exist == null) {
267 current = current.addElement(nodename);
268 } else {
269 current = exist;
270 }
271 }
272 }
273 String nodename = pathes[pathes.length - 1];
274 if (nodename.length() > 0) {
275 current = current.addElement(nodename);
276 }
277 return current;
278 }
279
280
281
282
283
284
285
286
287
288 static public Element getParentElement(Element ref, String path)
289 throws DocumentException {
290 String npath = path;
291 while (npath.charAt(0) == '/') {
292 npath = npath.substring(1);
293 }
294 Element current = (Element) ref.selectSingleNode(npath);
295 if (current == null) {
296 throw new DocumentException("Node not found: " + path);
297 }
298 return current.getParent();
299 }
300
301
302
303
304
305
306
307
308
309 static public Element getElement(Element ref, String path)
310 throws DocumentException {
311 String npath = path;
312 while (npath.charAt(0) == '/') {
313 npath = npath.substring(1);
314 }
315 Element current = (Element) ref.selectSingleNode(npath);
316 if (current == null) {
317 throw new DocumentException("Node not found: " + path);
318 }
319 return current;
320 }
321
322
323
324
325
326
327
328
329
330 @SuppressWarnings("unchecked")
331 static public List<Element> getElementMultiple(Element ref, String path)
332 throws DocumentException {
333 String npath = path;
334 while (npath.charAt(0) == '/') {
335 npath = npath.substring(1);
336 }
337 List<Element> list = ref.selectNodes(npath);
338 if (list == null || list.isEmpty()) {
339 throw new DocumentException("Nodes not found: " + path);
340 }
341 return list;
342 }
343
344
345
346
347
348
349
350
351
352
353 static public Element addOrSetElement(Document doc, String path,
354 String value) {
355 Element current = addOrGetElement(doc, path);
356 current.setText(value);
357 return current;
358 }
359
360
361
362
363
364
365
366
367
368 static public Element addOrGetElement(Document doc, String path) {
369 String[] pathes = path.split("/");
370 int rank = 0;
371 for (rank = 0; rank < pathes.length; rank ++) {
372 if (pathes[rank].length() > 0) {
373 break;
374 }
375 }
376 if (rank >= pathes.length) {
377 return null;
378 }
379 Element current = (Element) doc.selectSingleNode(pathes[rank]);
380 if (current == null) {
381 current = doc.addElement(pathes[rank]);
382 }
383 for (int i = rank + 1; i < pathes.length; i ++) {
384 String nodename = pathes[i];
385 if (nodename.length() > 0) {
386 Element exist = current.element(nodename);
387 if (exist == null) {
388 current = current.addElement(nodename);
389 } else {
390 current = exist;
391 }
392 }
393 }
394 return current;
395 }
396
397
398
399
400
401
402
403
404
405 static public Element addAndSetElementMultiple(Document doc, String path,
406 String value) {
407 Element current = addAndGetElementMultiple(doc, path);
408 current.setText(value);
409 return current;
410 }
411
412
413
414
415
416
417
418
419 static public Element addAndGetElementMultiple(Document doc, String path) {
420 String[] pathes = path.split("/");
421 int rank = 0;
422 for (rank = 0; rank < pathes.length; rank ++) {
423 if (pathes[rank].length() > 0) {
424 break;
425 }
426 }
427 if (rank >= pathes.length) {
428 return null;
429 }
430 Element current = (Element) doc.selectSingleNode(pathes[rank]);
431 if (current == null) {
432 current = doc.addElement(pathes[rank]);
433 }
434 if (rank == pathes.length - 1) {
435
436
437 return current;
438 }
439 for (int i = rank + 1; i < pathes.length - 1; i ++) {
440 String nodename = pathes[i];
441 if (nodename.length() > 0) {
442 Element exist = current.element(nodename);
443 if (exist == null) {
444 current = current.addElement(nodename);
445 } else {
446 current = exist;
447 }
448 }
449 }
450 String nodename = pathes[pathes.length - 1];
451 if (nodename.length() > 0) {
452 current = current.addElement(nodename);
453 }
454 return current;
455 }
456
457
458
459
460
461
462
463
464
465 static public Element getParentElement(Document doc, String path)
466 throws DocumentException {
467 Element current = (Element) doc.selectSingleNode(path);
468 if (current == null) {
469 throw new DocumentException("Node not found: " + path);
470 }
471 return current.getParent();
472 }
473
474
475
476
477
478
479
480
481 static public Element getElement(Document doc, String path)
482 throws DocumentException {
483 Element current = (Element) doc.selectSingleNode(path);
484 if (current == null) {
485 throw new DocumentException("Node not found: " + path);
486 }
487 return current;
488 }
489
490
491
492
493
494
495
496
497 @SuppressWarnings("unchecked")
498 static public List<Element> getElementMultiple(Document doc, String path)
499 throws DocumentException {
500 List<Element> list = doc.selectNodes(path);
501 if (list == null || list.isEmpty()) {
502 throw new DocumentException("Nodes not found: " + path);
503 }
504 return list;
505 }
506
507
508
509
510
511
512
513
514 static public XmlValue[] read(Document doc, XmlDecl[] decls) {
515 XmlValue[] values = null;
516 int len = decls.length;
517 values = new XmlValue[len];
518 for (int i = 0; i < len; i ++) {
519 XmlValue value = new XmlValue(decls[i]);
520 values[i] = value;
521 if (decls[i].isSubXml()) {
522 if (decls[i].isMultiple()) {
523 List<Element> elts;
524 try {
525 elts = getElementMultiple(doc, decls[i].getXmlPath());
526 } catch (DocumentException e) {
527 continue;
528 }
529 for (Element element: elts) {
530 XmlValue[] newValue = read(element,
531 decls[i].getSubXml());
532 if (newValue == null) {
533 continue;
534 }
535 try {
536 value.addValue(newValue);
537 } catch (InvalidObjectException e) {
538 continue;
539 }
540 }
541 } else {
542 Element element;
543 try {
544 element = getElement(doc, decls[i].getXmlPath());
545 } catch (DocumentException e) {
546 continue;
547 }
548 XmlValue[] newValue = read(element, decls[i].getSubXml());
549 if (newValue == null) {
550 continue;
551 }
552 try {
553 value.setValue(newValue);
554 } catch (InvalidObjectException e) {
555 continue;
556 }
557 }
558 } else if (decls[i].isMultiple()) {
559 List<Element> elts;
560 try {
561 elts = getElementMultiple(doc, decls[i].getXmlPath());
562 } catch (DocumentException e) {
563 continue;
564 }
565 for (Element element: elts) {
566 String svalue = element.getText();
567 try {
568 value.addFromString(svalue);
569 } catch (InvalidObjectException e) {
570 continue;
571 }
572 }
573 } else {
574 Element element;
575 try {
576 element = getElement(doc, decls[i].getXmlPath());
577 } catch (DocumentException e) {
578 continue;
579 }
580 String svalue = element.getText();
581 value.setFromString(svalue);
582 }
583 }
584 return values;
585 }
586
587
588
589
590
591
592
593
594 static public XmlValue[] read(Element ref, XmlDecl[] decls) {
595 XmlValue[] values = null;
596 int len = decls.length;
597 values = new XmlValue[len];
598 for (int i = 0; i < len; i ++) {
599 XmlValue value = new XmlValue(decls[i]);
600 values[i] = value;
601 if (decls[i].isSubXml()) {
602 if (decls[i].isMultiple()) {
603 List<Element> elts;
604 try {
605 elts = getElementMultiple(ref, decls[i].getXmlPath());
606 } catch (DocumentException e) {
607 continue;
608 }
609 for (Element element: elts) {
610 XmlValue[] newValue = read(element,
611 decls[i].getSubXml());
612 if (newValue == null) {
613 continue;
614 }
615 try {
616 value.addValue(newValue);
617 } catch (InvalidObjectException e) {
618 continue;
619 }
620 }
621 } else {
622 Element element;
623 try {
624 element = getElement(ref, decls[i].getXmlPath());
625 } catch (DocumentException e) {
626 continue;
627 }
628 XmlValue[] newValue = read(element, decls[i].getSubXml());
629 if (newValue == null) {
630 continue;
631 }
632 try {
633 value.setValue(newValue);
634 } catch (InvalidObjectException e) {
635 continue;
636 }
637 }
638 } else if (decls[i].isMultiple()) {
639 List<Element> elts;
640 try {
641 elts = getElementMultiple(ref, decls[i].getXmlPath());
642 } catch (DocumentException e) {
643 continue;
644 }
645 for (Element element: elts) {
646 String svalue = element.getText();
647 try {
648 value.addFromString(svalue);
649 } catch (InvalidObjectException e) {
650 continue;
651 }
652 }
653 } else {
654 Element element;
655 try {
656 element = getElement(ref, decls[i].getXmlPath());
657 } catch (DocumentException e) {
658 continue;
659 }
660 String svalue = element.getText();
661 value.setFromString(svalue);
662 }
663 }
664 return values;
665 }
666
667
668
669
670
671
672
673 @SuppressWarnings("unchecked")
674 public static void write(Document doc, XmlValue[] values) {
675 int len = values.length;
676 for (int i = 0; i < len; i ++) {
677 if (values[i] != null) {
678 if (values[i].isSubXml()) {
679 if (values[i].isMultiple()) {
680 List<XmlValue[]> list = (List<XmlValue[]>) values[i]
681 .getList();
682 for (XmlValue[] object: list) {
683 Element ref = addAndGetElementMultiple(doc,
684 values[i].getXmlPath());
685 write(ref, object);
686 }
687 } else {
688 Element ref = addOrGetElement(doc,
689 values[i].getXmlPath());
690 write(ref, values[i].getSubXml());
691 }
692 } else if (values[i].isMultiple()) {
693 List<?> list = values[i].getList();
694 for (Object object: list) {
695 addAndSetElementMultiple(doc, values[i].getXmlPath(),
696 object.toString());
697 }
698 } else {
699 addOrSetElement(doc, values[i].getXmlPath(),
700 values[i].getIntoString());
701 }
702 }
703 }
704 }
705
706
707
708
709
710
711
712 @SuppressWarnings("unchecked")
713 public static void write(Element ref, XmlValue[] values) {
714 int len = values.length;
715 for (int i = 0; i < len; i ++) {
716 if (values[i] != null) {
717 if (values[i].isSubXml()) {
718 if (values[i].isMultiple()) {
719 List<XmlValue[]> list = (List<XmlValue[]>) values[i]
720 .getList();
721 for (XmlValue[] object: list) {
722 Element newref = addAndGetElementMultiple(ref,
723 values[i].getXmlPath());
724 write(newref, object);
725 }
726 } else {
727 Element newref = addOrGetElement(ref,
728 values[i].getXmlPath());
729 write(newref, values[i].getSubXml());
730 }
731 } else if (values[i].isMultiple()) {
732 List<?> list = values[i].getList();
733 for (Object object: list) {
734 addAndSetElementMultiple(ref, values[i].getXmlPath(),
735 object.toString());
736 }
737 } else {
738 addOrSetElement(ref, values[i].getXmlPath(),
739 values[i].getIntoString());
740 }
741 }
742 }
743 }
744
745
746
747
748
749 @SuppressWarnings("unchecked")
750 public static void main(String[] args) {
751 XmlDecl[] decls = {
752 new XmlDecl("n1", XmlType.BOOLEAN, "/root/bool", false),
753 new XmlDecl("n2", XmlType.FLOAT, "/root/float", false),
754 new XmlDecl("n3", XmlType.STRING, "/root/string", false),
755 new XmlDecl("n4", XmlType.INTEGER, "/root/int", false),
756 new XmlDecl("n5", XmlType.BOOLEAN, "/root/sub1/sub2/bool",
757 false),
758 new XmlDecl("n6", XmlType.BOOLEAN, "/root/sub1/sub3/bool", true),
759 new XmlDecl("n7", XmlType.BOOLEAN,
760 "/root/sub4/sub5/sub6/sub7/bool", false) };
761 String xmltree = "<root><bool>true</bool><float>1.2</float><string>my string to read</string><int>5</int>"
762 + "<sub1>"
763 + "<sub2><bool>1</bool></sub2>"
764 + "<sub3>"
765 + "<bool>false</bool><bool>true</bool><bool>0</bool>"
766 + "</sub3>"
767 + "</sub1>"
768 + "<sub4><sub5><sub6><sub7><bool>True</bool></sub7></sub6></sub5></sub4>"
769 + "</root>";
770
771 Document document = null;
772 try {
773 document = readDocument(xmltree);
774 } catch (DocumentException e) {
775 e.printStackTrace();
776 return;
777 }
778 try {
779 saveDocument("D:\\Tools\\test-src.xml", document);
780 } catch (IOException e) {
781 e.printStackTrace();
782 return;
783 }
784 XmlValue[] values = read(document, decls);
785 Document newDoc = createEmptyDocument();
786 write(newDoc, values);
787 String text = writeToString(newDoc);
788 System.err.println(text);
789 try {
790 saveDocument("D:\\Tools\\test.xml", newDoc);
791 } catch (IOException e) {
792 e.printStackTrace();
793 return;
794 }
795 try {
796 newDoc = getDocument("D:\\Tools\\test.xml");
797 } catch (IOException e) {
798 e.printStackTrace();
799 return;
800 } catch (DocumentException e) {
801 e.printStackTrace();
802 return;
803 }
804 values = read(newDoc, decls);
805 XmlHash hash = new XmlHash(values);
806 XmlValue value = hash.get("n6");
807 if (value != null) {
808 if (value.isMultiple()) {
809 try {
810 value.addFromString("true");
811 } catch (InvalidObjectException e) {
812 e.printStackTrace();
813 }
814 }
815 }
816 value = hash.get("n3");
817 if (value != null) {
818 if (!value.isMultiple()) {
819 try {
820 value.setValue("New String as replacement");
821 } catch (InvalidObjectException e) {
822 e.printStackTrace();
823 }
824 }
825 }
826 newDoc = createEmptyDocument();
827 write(newDoc, values);
828 try {
829 saveDocument("D:\\Tools\\test2.xml", newDoc);
830 } catch (IOException e) {
831 e.printStackTrace();
832 return;
833 }
834 Element elt = null;
835 try {
836 elt = getElement(newDoc, "/root/sub4");
837 } catch (DocumentException e1) {
838 e1.printStackTrace();
839 return;
840 }
841 XmlValue[] oldValues = read(document, decls);
842 write(elt, oldValues);
843 try {
844 saveDocument("D:\\Tools\\test3.xml", newDoc);
845 } catch (IOException e) {
846 e.printStackTrace();
847 return;
848 }
849 write(newDoc, oldValues);
850 try {
851 saveDocument("D:\\Tools\\test4.xml", newDoc);
852 } catch (IOException e) {
853 e.printStackTrace();
854 return;
855 }
856 try {
857 saveElement("D:\\Tools\\test5.xml",
858 (Element) elt.selectSingleNode("root"));
859 } catch (IOException e) {
860 e.printStackTrace();
861 return;
862 }
863
864 System.err.println("\n\nXVAL TESTING\n");
865 XmlDecl[] subdecls1 = {
866 new XmlDecl("n11", XmlType.BOOLEAN, "/n11/bool", false),
867 new XmlDecl("n12", XmlType.FLOAT, "/n11/float", true) };
868 XmlDecl[] subdecls2 = {
869 new XmlDecl("n21", XmlType.BOOLEAN, "/n21/bool", false),
870 new XmlDecl("n22", XmlType.FLOAT, "/n21/float", true) };
871 XmlDecl[] maindecls = {
872 new XmlDecl("n1", XmlType.BOOLEAN, "/root/bool", false),
873 new XmlDecl("n2", XmlType.FLOAT, "/root/float", false),
874 new XmlDecl("n3", XmlType.STRING, "/root/string", false),
875 new XmlDecl("n4", XmlType.INTEGER, "/root/int", false),
876 new XmlDecl("n5", XmlType.BOOLEAN, "/root/sub1/sub2/bool",
877 false),
878 new XmlDecl("n6", XmlType.BOOLEAN, "/root/sub1/sub3/bool", true),
879 new XmlDecl("n7", XmlType.BOOLEAN,
880 "/root/sub4/sub5/sub6/sub7/bool", false),
881 new XmlDecl("n10", XmlType.XVAL, "/root/sub8", subdecls1, false),
882 new XmlDecl("n20", XmlType.XVAL, "/root/sub9", subdecls2, true) };
883 xmltree = "<root><bool>true</bool><float>1.2</float><string>my string to read</string><int>5</int>"
884 + "<sub1>"
885 + "<sub2><bool>1</bool></sub2>"
886 + "<sub3>"
887 + "<bool>false</bool><bool>true</bool><bool>0</bool>"
888 + "</sub3>"
889 + "</sub1>"
890 + "<sub4><sub5><sub6><sub7><bool>True</bool></sub7></sub6></sub5></sub4>"
891 + "<sub8><n11><bool>true</bool><float>1.2</float><float>1.3</float><float>1.4</float></n11></sub8>"
892 + "<sub9><n21><bool>true</bool><float>2.2</float><float>2.3</float><float>2.4</float></n21></sub9>"
893 + "<sub9><n21><bool>false</bool><float>3.2</float><float>3.3</float><float>3.4</float></n21></sub9>"
894 + "<sub9><n21><bool>true</bool><float>4.2</float><float>4.3</float><float>4.4</float></n21></sub9>"
895 + "</root>";
896 document = null;
897 try {
898 document = readDocument(xmltree);
899 } catch (DocumentException e) {
900 e.printStackTrace();
901 return;
902 }
903 try {
904 saveDocument("D:\\Tools\\xtest-src.xml", document);
905 } catch (IOException e) {
906 e.printStackTrace();
907 return;
908 }
909 values = read(document, maindecls);
910 newDoc = createEmptyDocument();
911 write(newDoc, values);
912 text = writeToString(newDoc);
913 System.err.println(text);
914 try {
915 saveDocument("D:\\Tools\\xtest.xml", newDoc);
916 } catch (IOException e) {
917 e.printStackTrace();
918 return;
919 }
920 try {
921 newDoc = getDocument("D:\\Tools\\xtest.xml");
922 } catch (IOException e) {
923 e.printStackTrace();
924 return;
925 } catch (DocumentException e) {
926 e.printStackTrace();
927 return;
928 }
929 values = read(newDoc, maindecls);
930 hash = new XmlHash(values);
931 value = hash.get("n10");
932 if (value != null) {
933 if (!value.isMultiple()) {
934 XmlValue[] subvalues = value.getSubXml();
935 XmlHash subhash = new XmlHash(subvalues);
936 value = subhash.get("n12");
937 try {
938 value.addFromString("10.3");
939 } catch (InvalidObjectException e) {
940 e.printStackTrace();
941 }
942 }
943 }
944 value = hash.get("n20");
945 if (value != null) {
946 if (value.isMultiple()) {
947 List<XmlValue[]> listvalues = (List<XmlValue[]>)value.getList();
948 XmlValue[] subvalues = listvalues.get(0);
949 XmlValue[] subvalues2 = new XmlValue[subvalues.length];
950
951 for (int i = 0; i < subvalues.length; i++) {
952 subvalues2[i] = new XmlValue(subvalues[i]);
953 }
954
955 listvalues.add(subvalues2);
956 XmlHash subhash = new XmlHash(subvalues2);
957 value = subhash.get("n21");
958 try {
959 value.setValue(Boolean.FALSE);
960 } catch (InvalidObjectException e) {
961 e.printStackTrace();
962 }
963 }
964 }
965 newDoc = createEmptyDocument();
966 write(newDoc, values);
967 try {
968 saveDocument("D:\\Tools\\xtest2.xml", newDoc);
969 } catch (IOException e) {
970 e.printStackTrace();
971 return;
972 }
973 elt = null;
974 try {
975 elt = getElement(newDoc, "/root/sub9");
976 } catch (DocumentException e1) {
977 e1.printStackTrace();
978 return;
979 }
980 try {
981 saveElement("D:\\Tools\\xtest5.xml",
982 elt);
983 } catch (IOException e) {
984 e.printStackTrace();
985 return;
986 }
987 }
988
989
990
991
992
993
994
995
996 public static void writeXML(String filename, String encoding, Document document) throws IOException {
997 OutputFormat format = OutputFormat.createPrettyPrint();
998 if (encoding != null) {
999 format.setEncoding(encoding);
1000 } else {
1001 format.setEncoding("ISO-8859-1");
1002 }
1003 XMLWriter writer = null;
1004 writer = new XMLWriter(new FileWriter(filename), format);
1005 writer.write(document);
1006 try {
1007 writer.close();
1008 } catch (IOException e) {
1009 }
1010 }
1011 }