KickJava   Java API By Example, From Geeks To Geeks.

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


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
36 package com.micronova.util;
37
38 import java.util.*;
39 import java.net.*;
40 import org.w3c.dom.*;
41
42 /**
43
44 Nested map that accepts keys such as "@customer.name" which is
45 resolved to the value of "name" in the submap which is the value of
46 "customer" The underscore character "_" is reserved as the special key
47 name prefix. Especially the value of "_" itself is a list, and its
48 elements are accessible as "@_.0", "@_.1", .... For example,
49 "@customer._.0.name" indicates the 0-th customer's name ("customer._.0" is another instance of NestedMap).
50
51 The following special keys are supported:
52
53 __encoded: Form-encoded pairs "X=Y&...", where X is all the nested key names.
54 E.g., it is something like "customer.firstname=john&customer.lastname=doe"
55
56 __source: copy from source
57
58 __param: a map consisting of (nested-kay-name, value) pairs.
59
60 __keyList: returns list of key Strings at this level (not nested)
61
62 __entryList: returns list of (key, value) pairs (not nested)
63
64 __valueList: returns list of values (not nested)
65
66 __keyListSorted: returns list of keys in sorted order
67
68 __entryListSorted: returns list of (key, value) pairs, sorted by key (not nested)
69 __encodedSorted: same as __encoded, but sorted by key
70
71 __listSize: size of "_" list
72
73 __listActualSize: actual size of "_" list
74
75 __json: JSON-like presentation
76
77 __xml: XML presentation
78
79 __dom: DOM presentation
80
81 __attrList: XML attribute list presentation ('x="aaaa" y="bbbb" ...' with XML-escaping)
82
83 #[expression]: [expression] is taken as non-nested expression
84
85 */

86
87 public class NestedMap extends MapBean
88 {
89     /** special characters */
90
91     public final static char SEPARATOR = '.';
92     public final static char ESCAPE = '_';
93     public final static char NESTED = '@';
94     public final static char NONNESTED = '#';
95
96     /** special keynames following "_" prefix */
97
98     public final static String JavaDoc ENCODED = "_encoded";
99     public final static String JavaDoc XML = "_xml";
100     public final static String JavaDoc DOM = "_dom";
101     public final static String JavaDoc JSON = "_json";
102     public final static String JavaDoc ATTRLIST = "_attrList";
103     public final static String JavaDoc CLEAR = "_clear";
104     public final static String JavaDoc PARAM = "_param";
105     public final static String JavaDoc SOURCE= "_source";
106     public final static String JavaDoc LIST = "";
107     public final static String JavaDoc LISTSIZE = "_listSize";
108     public final static String JavaDoc LISTACTUALSIZE = "_listActualSize";
109     public final static String JavaDoc KEYLIST = "_keyList";
110     public final static String JavaDoc ENTRYLIST = "_entryList";
111     public final static String JavaDoc VALUELIST = "_valueList";
112     public final static String JavaDoc KEYLISTSORTED = "_keyListSorted";
113     public final static String JavaDoc ENTRYLISTSORTED = "_entryListSorted";
114     public final static String JavaDoc ENCODEDSORTED = "_encodedSorted";
115     public final static String JavaDoc ENCODING = "_encoding";
116
117     /** special keys for creating submaps and sublists */
118
119     public final static String JavaDoc CREATESUBMAP = "CREATESUBMAP";
120     public final static String JavaDoc CREATESUBLIST = "CREATESUBLIST";
121
122     /** list key */
123
124     public final static String JavaDoc LISTKEY = ESCAPE + LIST;
125
126     /** default character encoding */
127
128     protected String JavaDoc _encoding = "utf-8";
129
130     /** used to indicate that a special key ("_xxx") is not supported */
131
132     protected final static String JavaDoc UNSUPPORTED = "UNSUPPORTED";
133
134     /** map of acceptable keys. If this is not null, then a runtime exception is thrown when a non-acceptable key is used - if the value of a key in this map is "r" (string), only read access (get) for the given key is accepted, and if "w" then only write access is accepted, and if any other non-null value, then both read and write access is accepted. */
135
136     protected NestedMap _acceptable = null;
137
138     /** sets _acceptable map. */
139
140     public void setAcceptable(Object JavaDoc object)
141     {
142         if (object == null)
143         {
144             _acceptable = null;
145         }
146         else
147         {
148             _acceptable = TypeUtil.isNestedMap(object);
149         }
150     }
151
152     /** secondary map for special keys */
153
154     protected NestedMap _secondary;
155
156     /** get secondary map, creating a new map if null if doesCreate is true */
157
158     protected NestedMap getSecondaryMap(boolean doesCreate)
159     {
160         NestedMap secondary = _secondary;
161
162         if (secondary == null)
163         {
164             if (doesCreate)
165             {
166                 secondary = new NestedMap();
167                 _secondary = secondary;
168             }
169         }
170
171         return secondary;
172     }
173
174     /** getObject on the secondary */
175
176     protected Object JavaDoc getSecondary(Object JavaDoc key)
177     {
178         NestedMap secondary = getSecondaryMap(false);
179
180         if (secondary == null)
181         {
182             return null;
183         }
184         else
185         {
186             return secondary.get(key);
187         }
188     }
189
190     /** putObject on the secondary */
191
192     protected Object JavaDoc putSecondary(Object JavaDoc key, Object JavaDoc value)
193     {
194         NestedMap secondary = getSecondaryMap(true);
195         
196         return secondary.put(key, value);
197     }
198
199     /** shallow copy the secondary */
200
201     public void copySecondary(NestedMap map)
202     {
203         NestedMap mapSecondary = map.getSecondaryMap(false);
204
205         if (mapSecondary != null)
206         {
207             NestedMap secondary = getSecondaryMap(true);
208
209             secondary.copy(mapSecondary);
210         }
211     }
212
213     /** clears secondary */
214
215     public void clearSecondary()
216     {
217         _secondary = null;
218     }
219
220     /** clears all, including the secondary */
221
222     public void clear()
223     {
224         clearSecondary();
225
226         super.clear();
227     }
228
229     /** returns special key valules or UNSUPPORTED */
230
231     protected Object JavaDoc getSpecial(String JavaDoc keyString)
232     {
233         Object JavaDoc returnValue = UNSUPPORTED;
234
235         if (LIST.equals(keyString))
236         {
237             returnValue = getSubList();
238         }
239         else if (PARAM.equals(keyString))
240         {
241             try
242             {
243                 returnValue = exportParams();
244             }
245             catch (Exception JavaDoc e)
246             {
247                 e.printStackTrace();
248                 returnValue = null;
249             }
250         }
251         else if (ENCODED.equals(keyString))
252         {
253             try
254             {
255                 returnValue = encodeMap((Map)exportParams(), _encoding, false);
256             }
257             catch (Exception JavaDoc e)
258             {
259                 e.printStackTrace();
260                 returnValue = null;
261             }
262         }
263         else if (ENCODEDSORTED.equals(keyString))
264         {
265             try
266             {
267                 returnValue = encodeMap((Map)exportParams(), _encoding, true);
268             }
269             catch (Exception JavaDoc e)
270             {
271                 e.printStackTrace();
272                 returnValue = null;
273             }
274         }
275         else if (XML.equals(keyString))
276         {
277             try
278             {
279                 returnValue = XMLUtil.output(XMLUtil.createSource(XMLMap.encode(this)), new NestedMap("omit-xml-declaration=yes"));
280             }
281             catch (Exception JavaDoc e)
282             {
283                 throw new RuntimeException JavaDoc(e);
284             }
285         }
286         else if (DOM.equals(keyString))
287         {
288             try
289             {
290                 returnValue = XMLMap.encode(this);
291             }
292             catch (Exception JavaDoc e)
293             {
294                 throw new RuntimeException JavaDoc(e);
295             }
296         }
297         else if (JSON.equals(keyString))
298         {
299             returnValue = StringUtil.encodeJSON(this);
300         }
301         else if (ATTRLIST.equals(keyString))
302         {
303             returnValue = XMLUtil.encodeAttrList(this);
304         }
305         else if (LISTSIZE.equals(keyString))
306         {
307             List list = getSubList();
308             
309             returnValue = new Integer JavaDoc(list.size());
310         }
311         else if (LISTACTUALSIZE.equals(keyString))
312         {
313             List list = getSubList();
314             
315             returnValue = new Integer JavaDoc(TypeUtil.getActualSize(list));
316         }
317         else if (KEYLIST.equals(keyString))
318         {
319             returnValue = makeList(keySet());
320         }
321         else if (ENTRYLIST.equals(keyString))
322         {
323             returnValue = makeList(entrySet());
324         }
325         else if (VALUELIST.equals(keyString))
326         {
327             returnValue = makeList(values());
328         }
329         else if (KEYLISTSORTED.equals(keyString))
330         {
331             returnValue = makeList((new TreeMap(this)).keySet());
332         }
333         else if (ENTRYLISTSORTED.equals(keyString))
334         {
335             returnValue = makeList((new TreeMap(this)).entrySet());
336         }
337         else if (ENCODING.equals(keyString))
338         {
339             returnValue = _encoding;
340         }
341
342         return returnValue;
343     }
344
345     /** URL-encode a string using given encoding */
346
347     public static String JavaDoc encodeString(String JavaDoc string, String JavaDoc encoding) throws Exception JavaDoc
348     {
349         return URLEncoder.encode(string, encoding);
350     }
351
352     /** URL-decode a string using given encoding */
353
354     public static String JavaDoc decodeString(String JavaDoc string, String JavaDoc encoding) throws Exception JavaDoc
355     {
356         return URLDecoder.decode(string, encoding);
357     }
358
359     /** copy from another nested map */
360
361     public void copy(NestedMap map)
362     {
363         Iterator iterator = map.entrySet().iterator();
364             
365         while (iterator.hasNext())
366         {
367             Map.Entry entry = (Map.Entry)iterator.next();
368             
369             Object JavaDoc key = entry.getKey();
370             
371             putMapObject(key, entry.getValue());
372         }
373
374         copySecondary(map);
375     }
376
377     /** copies from given source object. The source object can be either a Map, a List, or a URL-style encoded String ("a=x&b=y..."). If source is a Map, then shallow copy is made from the source map. If source is an URL-style encoded String, then it is decoded into the NestedMap. If source is a list, then the "_" list of the NestedMap is populated with new NestedMaps generated using each list element (again a Map, a List, or a URL-style encoded String) as the source. */
378
379     public void copyFromSource(Object JavaDoc source) throws Exception JavaDoc
380     {
381         if (source instanceof Node)
382         {
383             source = ((NestedMap)XMLMap.decode((Node)source)).values().toArray()[0];
384         }
385
386         if (source instanceof Map)
387         {
388             Map sourceMap = (Map)source;
389             
390             Iterator iterator = sourceMap.entrySet().iterator();
391             
392             while (iterator.hasNext())
393             {
394                 Map.Entry entry = (Map.Entry)iterator.next();
395                 
396                 putObject(this, entry.getKey(), entry.getValue());
397             }
398         }
399         else if (source instanceof String JavaDoc)
400         {
401             String JavaDoc sourceString = source.toString().trim();
402
403             if (sourceString.startsWith("{") || (sourceString.startsWith("[")))
404             {
405                 copyFromSource(StringUtil.decodeJSON(sourceString));
406             }
407             else if (sourceString.startsWith("<"))
408             {
409                 copyFromSource(((NestedMap)XMLMap.decode(sourceString)).values().toArray()[0]);
410             }
411             else
412             {
413                 importParams(sourceString);
414             }
415         }
416         else
417         {
418             List list = TypeUtil.isList(source);
419
420             if (list != null)
421             {
422                 Iterator iterator = list.iterator();
423             
424                 List mapList = getSubList();
425
426                 while (iterator.hasNext())
427                 {
428                     Object JavaDoc item = iterator.next();
429
430                     if (item instanceof Map)
431                     {
432                         NestedMap itemMap = new NestedMap();
433
434                         itemMap.copyFromSource(item);
435                         
436                         mapList.add(itemMap);
437                     }
438                     else
439                     {
440                         mapList.add(item);
441                     }
442                 }
443             }
444         }
445     }
446
447     /** constructs an empty nested map */
448
449     public NestedMap()
450     {
451         super();
452     }
453
454     /** constructs a nested map initialized from the given source object */
455
456     public NestedMap(Object JavaDoc source) throws Exception JavaDoc
457     {
458         super();
459
460         copyFromSource(source);
461     }
462
463     /** create a new List */
464
465     protected List createList()
466     {
467         return (List)getObject(this, CREATESUBLIST);
468     }
469
470     /** create a new NestedMap */
471
472     protected NestedMap createMap()
473     {
474         return (NestedMap)getObject(this, CREATESUBMAP);
475     }
476
477     /** returns the "_" sublist, creating one if it doesn't exist and doesCreate is true */
478
479     public List getSubList(boolean doesCreate)
480     {
481         List list = (List)getMapObject(LISTKEY);
482         
483         if (list == null)
484         {
485             if (doesCreate)
486             {
487                 list = createList();
488
489                 putMapObject(LISTKEY, list);
490             }
491         }
492
493         return list;
494     }
495
496     public List getSubList()
497     {
498         return getSubList(true);
499     }
500
501     /** returns subMap for given key, creating one if it doesn't exist when doesCreate is true*/
502
503     public NestedMap getSubMap(Object JavaDoc key, boolean doesCreate)
504     {
505         NestedMap map = (NestedMap)get(key);
506         
507         if (map == null)
508         {
509             if (doesCreate)
510             {
511                 map = createMap();
512                 put(key, map);
513             }
514         }
515
516         return map;
517     }
518
519     /** returns subMap for given key, automatically creating it (doesCreate = true) */
520
521     public NestedMap getSubMap(Object JavaDoc key)
522     {
523         return getSubMap(key, true);
524     }
525
526     /** returns subMap at given index in the given list, creating one if it doesn't exist when doesCreate is true */
527
528     public NestedMap getSubMap(List list, int index, boolean doesCreate)
529     {
530         NestedMap map = null;
531
532         if (list != null)
533         {
534             map = (NestedMap)list.get(index);
535         
536             if (map == null)
537             {
538                 if (doesCreate)
539                 {
540                     map = createMap();
541                     list.set(index, map);
542                 }
543             }
544         }
545             
546         return map;
547     }
548
549
550     /** returns subMap at given index in the given list, creating one if it doesn't exist */
551
552     public NestedMap getSubMap(List list, int index)
553     {
554         return getSubMap(list, index, true);
555     }
556
557     /** returns subMap at given index of the sublist, creating one if it doesn't exist when doesCreate is true */
558
559     public NestedMap getSubMap(int index, boolean doesCreate)
560     {
561         return getSubMap(getSubList(doesCreate), index, doesCreate);
562     }
563
564     /** returns subMap at given index of the sublist, creating one if it doesn't exist */
565
566     public NestedMap getSubMap(int index)
567     {
568         return getSubMap(index, true);
569     }
570
571     /** get element using nested expression */
572
573     public Object JavaDoc getElement(String JavaDoc name)
574     {
575         return getElement(name, false);
576     }
577
578     /** get element using nested expression */
579
580     protected Object JavaDoc getElement(String JavaDoc name, boolean isList)
581     {
582         String JavaDoc key = name;
583         String JavaDoc indexPart = null;
584         String JavaDoc subKey = null;
585
586         int breakIndex = name.indexOf(SEPARATOR);
587
588         if (breakIndex >= 0)
589         {
590             key = name.substring(0, breakIndex);
591             subKey = name.substring(breakIndex + 1);
592         }
593
594         if (isList)
595         {
596             List list = (List)get(LISTKEY);
597
598             if (TypeUtil.isEmptyString(key))
599             {
600                 return list;
601             }
602             else
603             {
604                 int index = Integer.parseInt(key);
605
606                 if (index < 0)
607                 {
608                     index = list.size() + index;
609                 }
610
611                 Object JavaDoc listItem = list.get(index);
612
613                 if (TypeUtil.isEmptyString(subKey))
614                 {
615                     return listItem;
616                 }
617                 else if (listItem != null)
618                 {
619                     return ((NestedMap)listItem).getElement(subKey, false);
620                 }
621                 else
622                 {
623                     return null;
624                 }
625             }
626         }
627         else
628         {
629             Object JavaDoc keyObject = get(key);
630
631             if (TypeUtil.isEmptyString(subKey))
632             {
633                 return keyObject;
634             }
635             else
636             {
637                 if (LISTKEY.equals(key))
638                 {
639                     return getElement(subKey, true);
640                 }
641                 else if (keyObject != null)
642                 {
643                     return ((NestedMap)keyObject).getElement(subKey, false);
644                 }
645                 else
646                 {
647                     return null;
648                 }
649             }
650         }
651     }
652
653     /** sets element using expression */
654
655     public void setElement(String JavaDoc name, Object JavaDoc value)
656     {
657         // name = name.replaceAll("\\[([^]]*)\\]", ".$1");
658

659         setElement(name, value, false);
660     }
661
662     /** set element using nested expression */
663
664     protected void setElement(String JavaDoc name, Object JavaDoc value, boolean isList)
665     {
666         String JavaDoc key = name;
667         String JavaDoc indexPart = null;
668         String JavaDoc subKey = null;
669
670         int breakIndex = name.indexOf(SEPARATOR);
671         
672         if (breakIndex >= 0)
673         {
674             key = name.substring(0, breakIndex);
675             subKey = name.substring(breakIndex + 1);
676         }
677
678         if (isList)
679         {
680             List list = getSubList();
681
682             int listSize = list.size();
683
684             int index = -1;
685
686             boolean isInsertMode = false;
687             boolean isIgnoreNullMode = false;
688
689             if ("".equals(key))
690             {
691                 key = "*";
692             }
693
694             if (key.startsWith("*"))
695             {
696                 isInsertMode = true;
697                 key = key.substring(1);
698
699                 if (key.startsWith("*"))
700                 {
701                     isIgnoreNullMode = true;
702                     key = key.substring(1);
703                 }
704             }
705
706             if (key.length() == 0)
707             {
708                 index = listSize;
709             }
710             else
711             {
712                 index = Integer.parseInt(key);
713
714                 if (index < 0)
715                 {
716                     index = listSize + index;
717                 }
718             }
719
720             if (value == REMOVE)
721             {
722                 value = null;
723             }
724
725             if (TypeUtil.isEmptyString(subKey))
726             {
727                 if (isInsertMode)
728                 {
729                     if (value != null)
730                     {
731                         if (index == listSize)
732                         {
733                             list.add(value);
734                         }
735                         else
736                         {
737                             list.add(index, value);
738                         }
739                     }
740                     else if ((listSize > 0) && (!isIgnoreNullMode))
741                     {
742                         if (index == listSize)
743                         {
744                             list.remove(listSize - 1);
745                         }
746                         else
747                         {
748                             list.remove(index);
749                         }
750                     }
751                 }
752                 else
753                 {
754                     list.set(index, value);
755                 }
756             }
757             else
758             {
759                 NestedMap subStruct = getSubMap(list, index);
760                 subStruct.setElement(subKey, value);
761             }
762         }
763         else
764         {
765             if (LISTKEY.equals(key))
766             {
767                 if (TypeUtil.isEmptyString(subKey))
768                 {
769                     putMapObject(key, value);
770                 }
771                 else
772                 {
773                     setElement(subKey, value, true);
774                 }
775             }
776             else
777             {
778                 if (TypeUtil.isEmptyString(subKey))
779                 {
780                     put(key, value);
781                 }
782                 else
783                 {
784                     Object JavaDoc mapObject = get(key);
785
786                     if ((mapObject == null) || (mapObject instanceof NestedMap))
787                     {
788                         NestedMap subStruct = getSubMap(key);
789                         subStruct.setElement(subKey, value);
790                     }
791                 }
792             }
793         }
794     }
795
796     /** decode a nested map */
797
798     public void decode(Map parameters) throws Exception JavaDoc
799     {
800         Iterator iterator = parameters.keySet().iterator();
801
802         while (iterator.hasNext())
803         {
804             String JavaDoc name = (String JavaDoc)iterator.next();
805
806             if (name != null)
807             {
808                 if (!name.equals(ENCODED))
809                 {
810                     Object JavaDoc value = parameters.get(name);
811
812                     setElement(name, value);
813                 }
814             }
815         }
816     }
817
818     /** encode a nested map */
819
820     protected void encode(String JavaDoc prefix, NestedMap map)
821     {
822         Iterator iterator = keySet().iterator();
823
824         while (iterator.hasNext())
825         {
826             String JavaDoc key = (String JavaDoc)iterator.next();
827
828             if (key != null)
829             {
830                 if (key.equals(LISTKEY))
831                 {
832                     List list = getSubList();
833
834                     for (int i = list.size(); --i >= 0;)
835                     {
836                         Object JavaDoc value = list.get(i);
837                         
838                         if (value != null)
839                         {
840                             if (value instanceof NestedMap)
841                             {
842                                 ((NestedMap)value).encode(prefix + ESCAPE + SEPARATOR + i + SEPARATOR, map);
843                             }
844                             else
845                             {
846                                 map.putMapObject(prefix + ESCAPE + SEPARATOR + i, value);
847                             }
848                         }
849                     }
850                 }
851                 else
852                 {
853                     Object JavaDoc value = getMapObject(key);
854
855                     if (value != null)
856                     {
857                         if (value instanceof NestedMap)
858                         {
859                             ((NestedMap)value).encode(prefix + key + SEPARATOR, map);
860                         }
861                         else
862                         {
863                             map.putMapObject(prefix + key, value);
864                         }
865                     }
866                 }
867             }
868         }
869     }
870
871     /** export into nested key/value pairs */
872
873     public Map exportParams() throws Exception JavaDoc
874     {
875         NestedMap map = new NestedMap();
876
877         encode("", map);
878
879         return map;
880     }
881
882     /** import from nested form-data string */
883
884     public void importParams(String JavaDoc encoded) throws Exception JavaDoc
885     {
886         if (encoded != null)
887         {
888             encoded = encoded.replaceAll("[\\s]", "");
889
890             Map allMap = new HashMap(decodeMap(encoded, _encoding));
891
892             decode(allMap);
893         }
894     }
895
896     /** import from parameter map (nested key/value pairs) */
897
898     public void importParams(Map parameters) throws Exception JavaDoc
899     {
900         String JavaDoc encoded = (String JavaDoc)parameters.get(ENCODED);
901
902         importParams(encoded);
903
904         decode(parameters);
905     }
906
907     /** gets an object */
908
909     public Object JavaDoc getObject(Object JavaDoc mapSource, Object JavaDoc key)
910     {
911         if (key == CREATESUBMAP)
912         {
913             return new NestedMap();
914         }
915         else if (key == CREATESUBLIST)
916         {
917             return new SparseList();
918         }
919
920         Object JavaDoc returnValue = null;
921
922         if (key != null)
923         {
924             String JavaDoc keyString = key.toString();
925
926             char prefix = 0;
927
928             if (keyString.length() > 0)
929             {
930                 prefix = keyString.charAt(0);
931             }
932
933             if (prefix == NESTED)
934             {
935                 returnValue = getElement(keyString.substring(1));
936             }
937             else if (prefix == ESCAPE)
938             {
939                 String JavaDoc specialKey = keyString.substring(1);
940
941                 Object JavaDoc specialValue = getSpecial(specialKey);
942
943                 if (specialValue != UNSUPPORTED)
944                 {
945                     returnValue = specialValue;
946                 }
947                 else
948                 {
949                     returnValue = getSecondary(specialKey);
950                 }
951             }
952             else
953             {
954                 if (prefix == NONNESTED)
955                 {
956                     keyString = keyString.substring(1);
957                 }
958
959                 NestedMap acceptable = _acceptable;
960             
961                 if (acceptable != null)
962                 {
963                     Object JavaDoc acceptance = acceptable.get(keyString);
964
965                     if ((acceptance == null) || ("w".equals(acceptance)))
966                     {
967                         throw new RuntimeException JavaDoc(keyString + " is not acceptable for get operation");
968                     }
969                 }
970
971                 returnValue = super.getObject(mapSource, keyString);
972             }
973         }
974
975         return returnValue;
976     }
977
978     /** makes a list from a collection */
979
980     protected List makeList(Collection collection)
981     {
982         List list = new ArrayList();
983
984         Iterator iterator = collection.iterator();
985
986         while (iterator.hasNext())
987         {
988             list.add(iterator.next());
989         }
990
991         return list;
992     }
993
994     /** puts an object */
995
996     public Object JavaDoc putObject(Object JavaDoc mapSource, Object JavaDoc key, Object JavaDoc value)
997     {
998         if (key != null)
999         {
1000            String JavaDoc keyString = key.toString();
1001
1002            char prefix = 0;
1003
1004            if (keyString.length() > 0)
1005            {
1006                prefix = keyString.charAt(0);
1007            }
1008            
1009            if (prefix == NESTED)
1010            {
1011                setElement(keyString.substring(1), value);
1012                return this;
1013            }
1014            else if (prefix == ESCAPE)
1015            {
1016                keyString = keyString.substring(1);
1017
1018                if (ENCODED.equals(keyString))
1019                {
1020                    try
1021                    {
1022                        importParams(value.toString());
1023                    }
1024                    catch (Exception JavaDoc e)
1025                    {
1026                        throw new RuntimeException JavaDoc(e);
1027                    }
1028                    
1029                    return this;
1030                }
1031                else if (XML.equals(keyString))
1032                {
1033                    try
1034                    {
1035                        copyFromSource(value.toString());
1036                    }
1037                    catch (Exception JavaDoc e)
1038                    {
1039                        throw new RuntimeException JavaDoc(e);
1040                    }
1041
1042                    return this;
1043                }
1044                else if (DOM.equals(keyString))
1045                {
1046                    try
1047                    {
1048                        copyFromSource(value);
1049                    }
1050                    catch (Exception JavaDoc e)
1051                    {
1052                        throw new RuntimeException JavaDoc(e);
1053                    }
1054
1055                    return this;
1056                }
1057                else if (JSON.equals(keyString))
1058                {
1059                    try
1060                    {
1061                        copyFromSource(value.toString());
1062                    }
1063                    catch (Exception JavaDoc e)
1064                    {
1065                        throw new RuntimeException JavaDoc(e);
1066                    }
1067
1068                    return this;
1069                }
1070                else if (SOURCE.equals(keyString))
1071                {
1072                    try
1073                    {
1074                        copyFromSource(value);
1075                    }
1076                    catch (Exception JavaDoc e)
1077                    {
1078                        throw new RuntimeException JavaDoc(e);
1079                    }
1080
1081                    return this;
1082                }
1083                else if (PARAM.equals(keyString))
1084                {
1085                    try
1086                    {
1087                        importParams((Map)value);
1088                    }
1089                    catch (Exception JavaDoc e)
1090                    {
1091                        throw new RuntimeException JavaDoc(e);
1092                    }
1093                
1094                    return this;
1095                }
1096                else if (CLEAR.equals(keyString))
1097                {
1098                    clear();
1099                    return this;
1100                }
1101                else if (ENCODING.equals(keyString))
1102                {
1103                    _encoding = (String JavaDoc)value;
1104                    return this;
1105                }
1106                else if (!LIST.equals(keyString))
1107                {
1108                    return putSecondary(keyString, value);
1109                }
1110            }
1111            else if (prefix == NONNESTED)
1112            {
1113                key = keyString.substring(1);
1114            }
1115        }
1116
1117        if (value == null)
1118        {
1119            value = REMOVE;
1120        }
1121        else
1122        {
1123            NestedMap acceptable = _acceptable;
1124        
1125            if (acceptable != null)
1126            {
1127                Object JavaDoc acceptance = acceptable.get(key);
1128
1129                if ((acceptance == null) || ("r".equals(acceptance)))
1130                {
1131                    throw new RuntimeException JavaDoc(key + " is not acceptable for put operation");
1132                }
1133            }
1134        }
1135
1136        return super.putObject(mapSource, key, value);
1137    }
1138
1139    /** encodes a NestedMap into FormData-style string */
1140
1141    public static String JavaDoc encodeMap(Map map, String JavaDoc encoding, boolean doesSort) throws Exception JavaDoc
1142    {
1143        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1144
1145        Map cloneMap = (doesSort) ? ((Map)new TreeMap(map)) : ((Map)new HashMap(map));
1146
1147        boolean isAppended = false;
1148
1149        Iterator iterator = cloneMap.entrySet().iterator();
1150
1151        while (iterator.hasNext())
1152        {
1153            Map.Entry entry = (Map.Entry)iterator.next();
1154
1155            Object JavaDoc key = entry.getKey();
1156            Object JavaDoc value = entry.getValue();
1157
1158            String JavaDoc keyString = (key != null) ? key.toString() : "";
1159            String JavaDoc valueString = (value != null) ? value.toString() : "";
1160
1161            if (isAppended)
1162            {
1163                buffer.append("&");
1164            }
1165
1166            buffer.append(encodeString(keyString, encoding));
1167            buffer.append("=");
1168            buffer.append(encodeString(valueString, encoding));
1169
1170            isAppended = true;
1171        }
1172
1173        return buffer.toString();
1174    }
1175
1176    /** decodes a FormData-style string into nested map */
1177
1178    public static NestedMap decodeMap(String JavaDoc string, String JavaDoc encoding) throws Exception JavaDoc
1179    {
1180        NestedMap map = new NestedMap();
1181
1182        String JavaDoc[] lines = string.split("&");
1183
1184        for (int i = 0; i < lines.length; i ++)
1185        {
1186            String JavaDoc[] parts = lines[i].split("=", 2);
1187
1188            if (parts.length == 2)
1189            {
1190                String JavaDoc key = decodeString(parts[0], encoding);
1191                String JavaDoc value = decodeString(parts[1], encoding);
1192
1193                if ("".equals(key))
1194                {
1195                    key = null;
1196                }
1197
1198                if ((key != null) && (value != null))
1199                {
1200                    map.setElement(key, value);
1201                }
1202            }
1203        }
1204
1205        return map;
1206    }
1207}
1208
Popular Tags