KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > micronova > util > XMLMap


1 /*
2
3 Copyright 2003-2007 MicroNova (R)
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or
7 without modification, are permitted provided that the following
8 conditions are met:
9
10     * Redistributions of source code must retain the above copyright
11     notice, this list of conditions and the following disclaimer.
12
13     * Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions and the following disclaimer in the
15     documentation and/or other materials provided with the distribution.
16
17     * Neither the name of MicroNova nor the names of its contributors
18     may be used to endorse or promote products derived from this
19     software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.
32
33 */

34
35 package com.micronova.util;
36
37 import java.util.*;
38 import java.io.*;
39 import java.text.*;
40 import java.util.regex.*;
41
42 import javax.xml.parsers.*;
43 import javax.xml.transform.*;
44 import javax.xml.transform.dom.*;
45 import javax.xml.transform.stream.*;
46 import javax.xml.transform.sax.*;
47 import org.w3c.dom.*;
48 import org.xml.sax.*;
49 import java.net.*;
50
51 /** XML utilities */
52
53 public class XMLMap
54 {
55     /** control keys */
56
57     public static final String JavaDoc TYPEATTRIBUTE = "typeAttribute";
58     public static final String JavaDoc INDEXATTRIBUTE = "indexAttribute";
59     public static final String JavaDoc DEFAULTTYPE = "defaultType";
60     public static final String JavaDoc MAPTYPE = "mapType";
61     public static final String JavaDoc LISTTYPE = "listType";
62     public static final String JavaDoc ITEMNAME = "itemName";
63     public static final String JavaDoc LISTNAME = "listName";
64     public static final String JavaDoc NAMEPREFIX = "namePrefix";
65     public static final String JavaDoc NAMESPACE = "namespace";
66     public static final String JavaDoc ROOTNAME = "rootName";
67     public static final String JavaDoc NAMEMAP = "nameMap";
68     public static final String JavaDoc ROOTATTRIBUTE = "rootAttribute";
69     public static final String JavaDoc HASATTRIBUTES = "hasAttributes";
70     public static final String JavaDoc DOESENCODENAMES = "doesEncodeNames";
71
72     public static final String JavaDoc ATTRIBUTE = "^";
73
74     public static boolean isNameStartChar(char c)
75     {
76         // ignore ':' for encoding
77

78         return (c == '_' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
79     }
80
81     public static boolean isNameChar(char c)
82     {
83         return (isNameStartChar(c) || c == '-' || c == '.' || (c >= '0' && c <= '9'));
84     }
85
86     public static String JavaDoc encodeName(String JavaDoc name)
87     {
88         char[] chars = name.toCharArray();
89         int length = chars.length;
90
91         if (length == 0)
92         {
93             return "_x_";
94         }
95
96         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
97
98         int index = 0;
99         boolean afterUnderscore = false;
100
101         if (length > 0)
102         {
103             char c = chars[0];
104
105             if (c == '_')
106             {
107                 afterUnderscore = true;
108                 index ++;
109             }
110             else if (isNameStartChar(c))
111             {
112                 buffer.append(c);
113                 index ++;
114             }
115             else if (isNameChar(c))
116             {
117                 buffer.append("_0");
118             }
119         }
120        
121         while (index < length)
122         {
123             char c = chars[index];
124
125             if (afterUnderscore)
126             {
127                 buffer.append('_');
128                 
129                 if ((c == '0') || (c == 'x') || (c == '_'))
130                 {
131                     buffer.append('_');
132                 }
133                 
134                 afterUnderscore = false;
135             }
136
137             if (c == '_')
138             {
139                 afterUnderscore = true;
140             }
141             else if (isNameChar(c))
142             {
143                 buffer.append(c);
144             }
145             else
146             {
147                 buffer.append("_x");
148                 String JavaDoc hex = Integer.toHexString((int)c);
149                 buffer.append(hex);
150                 buffer.append("_");
151             }
152
153             index ++;
154         }
155
156         if (afterUnderscore)
157         {
158             buffer.append("_");
159         }
160
161         return buffer.toString();
162     }
163
164     public static String JavaDoc decodeName(String JavaDoc encoded)
165     {
166         if (encoded.equals("_x_"))
167         {
168             return "";
169         }
170
171         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
172         StringBuffer JavaDoc hexBuffer = null;
173
174         char[] chars = encoded.toCharArray();
175         int length = chars.length;
176         boolean afterUnderscore = false;
177
178         for (int index = 0; index < length; index ++)
179         {
180             char c = chars[index];
181
182             if (afterUnderscore)
183             {
184                 if (c == '0')
185                 {
186                     // ignore
187
}
188                 else if (c == '_')
189                 {
190                     buffer.append('_');
191                 }
192                 else if (c == 'x')
193                 {
194                     if (hexBuffer == null)
195                     {
196                         hexBuffer = new StringBuffer JavaDoc();
197                     }
198
199                     hexBuffer.setLength(0);
200
201                     for (int j = index + 1; j < length; j ++)
202                     {
203                         char d = chars[j];
204
205                         if (d == '_')
206                         {
207                             index = j;
208                             break;
209                         }
210                         else
211                         {
212                             hexBuffer.append(d);
213                         }
214                     }
215
216                     buffer.append((char)Integer.parseInt(hexBuffer.toString(), 16));
217                 }
218                 else
219                 {
220                     buffer.append('_');
221                     buffer.append(c);
222                 }
223
224                 afterUnderscore = false;
225             }
226             else
227             {
228                 if (c == '_')
229                 {
230                     afterUnderscore = true;
231                 }
232                 else
233                 {
234                     buffer.append(c);
235                 }
236             }
237         }
238
239         if (afterUnderscore)
240         {
241             buffer.append('_');
242         }
243
244         return buffer.toString();
245     }
246    
247
248     /** default control map */
249
250     public static final Map defaultControlMap;
251
252     static
253     {
254         defaultControlMap = new HashMap();
255         
256         defaultControlMap.put(TYPEATTRIBUTE, null);
257         defaultControlMap.put(INDEXATTRIBUTE, "index");
258         defaultControlMap.put(DEFAULTTYPE, "string");
259         defaultControlMap.put(MAPTYPE, "map");
260         defaultControlMap.put(LISTTYPE, "list");
261         defaultControlMap.put(LISTNAME, "_");
262         defaultControlMap.put(ITEMNAME, "item");
263
264         defaultControlMap.put(ROOTNAME, "root");
265         defaultControlMap.put(NAMESPACE, "*");
266         defaultControlMap.put(DOESENCODENAMES, "true");
267     }
268
269     /** get control map */
270
271     protected static final Map getControlMap(Map map, String JavaDoc key)
272     {
273         Map value = null;
274
275         if (map != null)
276         {
277             value = (Map)map.get(key);
278         }
279
280         if (value == null)
281         {
282             value = (Map)defaultControlMap.get(key);
283         }
284
285         return value;
286     }
287
288     /** get control string */
289
290     protected static final String JavaDoc getControlString(Map map, String JavaDoc key)
291     {
292         String JavaDoc value = null;
293
294         if (map != null)
295         {
296             value = (String JavaDoc)map.get(key);
297         }
298
299         if (value == null)
300         {
301             value = (String JavaDoc)defaultControlMap.get(key);
302         }
303
304         return value;
305     }
306
307     /** add map entries as attributes */
308
309     protected static final Element addAttribute(Element element, Map map)
310     {
311         if (map != null)
312         {
313             Iterator iterator = map.entrySet().iterator();
314
315             while (iterator.hasNext())
316             {
317                 Map.Entry entry = (Map.Entry)iterator.next();
318
319                 element.setAttribute(entry.getKey().toString(), entry.getValue().toString());
320             }
321         }
322
323         return element;
324     }
325
326     /** generates XML representation of a map */
327
328     public static final Document encode(Object JavaDoc object) throws Exception JavaDoc
329     {
330         return encode(object, null);
331     }
332
333     /** generates XML representation of a map, according to the control map */
334
335     public static final Document encode(Object JavaDoc object, Map control) throws Exception JavaDoc
336     {
337         Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
338         
339         String JavaDoc name = getControlString(control, ROOTNAME);
340         boolean isEmptyName = TypeUtil.isEmptyString(name);
341
342         Element root = buildMapNode(document, (isEmptyName) ? "root" : name, object, getControlMap(control, ATTRIBUTE), control);
343
344         if (isEmptyName)
345         {
346             Node firstChild = root.getFirstChild();
347             if (firstChild instanceof Element)
348             {
349                 root = (Element)firstChild;
350             }
351         }
352
353         document.appendChild(root);
354
355         return document;
356     }
357
358 protected static final Element buildMapNode(Document document, String JavaDoc name, Object JavaDoc object, Map attributes, Map control)
359     {
360         String JavaDoc elementName = name;
361
362         boolean doesEncodeNames = TypeUtil.isTrue(getControlString(control, DOESENCODENAMES));
363
364         if (doesEncodeNames)
365         {
366             elementName = encodeName(elementName);
367         }
368
369         String JavaDoc namePrefix = getControlString(control, NAMEPREFIX);
370
371         if (!TypeUtil.isEmpty(namePrefix))
372         {
373             elementName = namePrefix + elementName;
374         }
375
376         Element element = document.createElement(elementName);
377
378         String JavaDoc typeAttribute = getControlString(control, TYPEATTRIBUTE);
379
380         if (object instanceof Map)
381         {
382             Map elementAttributes = (Map)((Map)object).get(ATTRIBUTE);
383
384             String JavaDoc mapType = getControlString(control, MAPTYPE);
385
386             if ((!TypeUtil.isEmpty(typeAttribute)) && (!TypeUtil.isEmpty(mapType)))
387             {
388                 element.setAttribute(typeAttribute, mapType);
389             }
390
391             TreeMap treeMap = new TreeMap((Map)object);
392
393             Iterator iterator = treeMap.entrySet().iterator();
394
395             while (iterator.hasNext())
396             {
397                 Map.Entry entry = (Map.Entry)iterator.next();
398
399                 Object JavaDoc key = entry.getKey();
400                 Object JavaDoc value = entry.getValue();
401
402                 if (key != null)
403                 {
404                     String JavaDoc keyString = key.toString();
405
406                     if (!ATTRIBUTE.equals(keyString))
407                     {
408                         if (value instanceof List)
409                         {
410                             String JavaDoc itemName = getControlString(control, LISTNAME);
411                             
412                             if ("*".equals(itemName))
413                             {
414                                 keyString = name;
415                             }
416                             else
417                             {
418                                 keyString = itemName;
419                             }
420                         }
421
422                         Map elementAttribute = null;
423
424                         if (elementAttributes != null)
425                         {
426                             elementAttribute = (Map)elementAttributes.get(keyString);
427                         }
428                         
429                         Element child = buildMapNode(document, keyString, value, elementAttribute, control);
430
431                         element.appendChild(child);
432                     }
433                 }
434             }
435         }
436         else if (object instanceof List)
437         {
438             String JavaDoc listType = getControlString(control, LISTTYPE);
439             String JavaDoc indexAttribute = getControlString(control, INDEXATTRIBUTE);
440
441             if ((!TypeUtil.isEmpty(typeAttribute)) && (!TypeUtil.isEmpty(listType)))
442             {
443                 element.setAttribute(typeAttribute, listType);
444             }
445
446             int index = 0;
447
448             Iterator iterator = ((List)object).iterator();
449
450             String JavaDoc itemName = getControlString(control, ITEMNAME);
451
452             while (iterator.hasNext())
453             {
454                 Object JavaDoc item = iterator.next();
455
456                 Element child = buildMapNode(document, itemName, item, attributes, control);
457
458                 if (!TypeUtil.isEmpty(indexAttribute))
459                 {
460                     child.setAttribute(indexAttribute, Integer.toString(index));
461                 }
462
463                 element.appendChild(child);
464
465                 index ++;
466             }
467         }
468         else
469         {
470             if (object != null)
471             {
472                 String JavaDoc defaultType = getControlString(control, DEFAULTTYPE);
473                 
474                 if ((!TypeUtil.isEmpty(typeAttribute)) && (!TypeUtil.isEmpty(defaultType)))
475                 {
476                     element.setAttribute(typeAttribute, defaultType);
477                 }
478
479                 Text text = document.createTextNode(object.toString());
480                 element.appendChild(text);
481             }
482         }
483
484         addAttribute(element, attributes);
485
486         return element;
487     }
488
489     /** convert XML back to NestedMap, using null namespace */
490
491     public static Object JavaDoc decode(Node node) throws Exception JavaDoc
492     {
493         return decode(node, null);
494     }
495
496     /** get node name, according to "namespace" */
497
498     public static String JavaDoc getNodeName(Node node, String JavaDoc namespace)
499     {
500         String JavaDoc nodeName = null;
501
502         String JavaDoc namespaceURI = node.getNamespaceURI();
503
504         String JavaDoc localName = node.getLocalName();
505
506         if (localName != null)
507         {
508             nodeName = localName;
509         }
510         else
511         {
512             nodeName = node.getNodeName();
513         }
514
515         if (!"_".equals(nodeName))
516         {
517             if (!"*".equals(namespace))
518             {
519                 if (namespaceURI != null)
520                 {
521                     if (!namespaceURI.equals(namespace))
522                     {
523                         nodeName = namespaceURI + "|" + nodeName;
524                     }
525                 }
526                 else
527                 {
528                     if ((namespace != null) && (!namespace.equals("")))
529                     {
530                         nodeName = "|" + nodeName;
531                     }
532                 }
533             }
534         }
535
536         return nodeName;
537     }
538
539     /** get attribute map */
540
541     public static NestedMap getAttributeMap(Node node, String JavaDoc namespace) throws Exception JavaDoc
542     {
543         NestedMap attributeMap = null;
544
545         NamedNodeMap attributeNodeMap = node.getAttributes();
546         
547         if (attributeNodeMap != null)
548         {
549             int attributeCount = attributeNodeMap.getLength();
550                         
551             if (attributeCount > 0)
552             {
553                 attributeMap = new NestedMap();
554                 
555                 while (--attributeCount >= 0)
556                 {
557                     Attr attr = (Attr)attributeNodeMap.item(attributeCount);
558                                 
559                     if (attr != null)
560                     {
561                         String JavaDoc attributeName = getNodeName(attr, namespace);
562                         
563                         
564                         attributeMap.put(attributeName, attr.getValue());
565                     }
566                 }
567             }
568         }
569
570         return attributeMap;
571     }
572
573     /** convert XML back to NestedMap */
574
575     public static Object JavaDoc decode(Node node, Map control) throws Exception JavaDoc
576     {
577         return decode(node, control, "/");
578     }
579
580     /** convert XML back to NestedMap */
581
582     public static Object JavaDoc decode(Node node, Map control, String JavaDoc path) throws Exception JavaDoc
583     {
584         NestedMap map = null;
585
586         String JavaDoc text = null;
587
588         node.normalize();
589
590         NodeList children = node.getChildNodes();
591
592         int childrenLength = children.getLength();
593
594         String JavaDoc namespace = getControlString(control, NAMESPACE);
595         boolean hasAttributes = TypeUtil.isTrue(getControlString(control, HASATTRIBUTES));
596         boolean doesEncodeNames = TypeUtil.isTrue(getControlString(control, DOESENCODENAMES));
597
598         Map nameMap = getControlMap(control, NAMEMAP);
599
600         for (int i = 0; i < childrenLength; i ++)
601         {
602             Node child = children.item(i);
603
604             int nodeType = child.getNodeType();
605
606             if (nodeType == Node.ELEMENT_NODE)
607             {
608                 if (map == null)
609                 {
610                     map = new NestedMap();
611                 }
612
613                 String JavaDoc nodeName = getNodeName(child, namespace);
614
615                 NestedMap attributeMap = null;
616                 
617                 if (hasAttributes)
618                 {
619                     NamedNodeMap attributeNodeMap = child.getAttributes();
620
621                     if (attributeNodeMap != null)
622                     {
623                         attributeMap = getAttributeMap(child, namespace);
624                     }
625                 }
626
627                 String JavaDoc nextPath = path + nodeName + "/";
628
629                 String JavaDoc target = getControlString(nameMap, nextPath);
630
631                 if (target == null)
632                 {
633                     target = getControlString(nameMap, nodeName);
634                     
635                     if (target == null)
636                     {
637                         target = nodeName;
638                     }
639                 }
640
641                 if (doesEncodeNames)
642                 {
643                     target = decodeName(target);
644                 }
645
646                 if ("_".equals(target))
647                 {
648                     NodeList listItems = child.getChildNodes();
649                     int listLength = listItems.getLength();
650
651                     for (int j = 0; j < listLength; j ++)
652                     {
653                         Node listItem = listItems.item(j);
654
655                         NestedMap listItemAttributeMap = getAttributeMap(listItem, namespace);
656
657                         String JavaDoc indexProperty = "*";
658
659                         if (listItemAttributeMap != null)
660                         {
661                             indexProperty = listItemAttributeMap.getString("index", indexProperty);
662                         }
663
664                         Object JavaDoc decoded = decode(listItem, control, nextPath);
665
666                         if (decoded != null)
667                         {
668                             map.put("@_." + indexProperty, decoded);
669
670                             if (hasAttributes && (listItemAttributeMap != null))
671                             {
672                                 map.put("@" + ATTRIBUTE + "._." + indexProperty, listItemAttributeMap);
673                             }
674                         }
675                     }
676                 }
677                 else
678                 {
679                     map.put(target, decode(child, control, nextPath));
680
681                     if (attributeMap != null)
682                     {
683                         map.put("@" + ATTRIBUTE + "." + target, attributeMap);
684                     }
685                 }
686             }
687             else if (nodeType == Node.TEXT_NODE)
688             {
689                 if (text == null)
690                 {
691                     text = child.getNodeValue();
692                 }
693                 else
694                 {
695                     text = text + child.getNodeValue();
696                 }
697             }
698         }
699
700         if (map != null)
701         {
702             return map;
703         }
704         else
705         {
706             return text;
707         }
708     }
709
710     public static Object JavaDoc decode(String JavaDoc string, Map control) throws Exception JavaDoc
711     {
712         return decode(XMLUtil.parse(string, control), control, "/");
713     }
714
715     public static Object JavaDoc decode(String JavaDoc string) throws Exception JavaDoc
716     {
717         return decode(string, null);
718     }
719 }
720
Popular Tags