1 34 35 36 package com.micronova.util; 37 38 import java.util.*; 39 import java.net.*; 40 import org.w3c.dom.*; 41 42 86 87 public class NestedMap extends MapBean 88 { 89 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 97 98 public final static String ENCODED = "_encoded"; 99 public final static String XML = "_xml"; 100 public final static String DOM = "_dom"; 101 public final static String JSON = "_json"; 102 public final static String ATTRLIST = "_attrList"; 103 public final static String CLEAR = "_clear"; 104 public final static String PARAM = "_param"; 105 public final static String SOURCE= "_source"; 106 public final static String LIST = ""; 107 public final static String LISTSIZE = "_listSize"; 108 public final static String LISTACTUALSIZE = "_listActualSize"; 109 public final static String KEYLIST = "_keyList"; 110 public final static String ENTRYLIST = "_entryList"; 111 public final static String VALUELIST = "_valueList"; 112 public final static String KEYLISTSORTED = "_keyListSorted"; 113 public final static String ENTRYLISTSORTED = "_entryListSorted"; 114 public final static String ENCODEDSORTED = "_encodedSorted"; 115 public final static String ENCODING = "_encoding"; 116 117 118 119 public final static String CREATESUBMAP = "CREATESUBMAP"; 120 public final static String CREATESUBLIST = "CREATESUBLIST"; 121 122 123 124 public final static String LISTKEY = ESCAPE + LIST; 125 126 127 128 protected String _encoding = "utf-8"; 129 130 131 132 protected final static String UNSUPPORTED = "UNSUPPORTED"; 133 134 135 136 protected NestedMap _acceptable = null; 137 138 139 140 public void setAcceptable(Object object) 141 { 142 if (object == null) 143 { 144 _acceptable = null; 145 } 146 else 147 { 148 _acceptable = TypeUtil.isNestedMap(object); 149 } 150 } 151 152 153 154 protected NestedMap _secondary; 155 156 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 175 176 protected Object getSecondary(Object 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 191 192 protected Object putSecondary(Object key, Object value) 193 { 194 NestedMap secondary = getSecondaryMap(true); 195 196 return secondary.put(key, value); 197 } 198 199 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 214 215 public void clearSecondary() 216 { 217 _secondary = null; 218 } 219 220 221 222 public void clear() 223 { 224 clearSecondary(); 225 226 super.clear(); 227 } 228 229 230 231 protected Object getSpecial(String keyString) 232 { 233 Object 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 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 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 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 e) 282 { 283 throw new RuntimeException (e); 284 } 285 } 286 else if (DOM.equals(keyString)) 287 { 288 try 289 { 290 returnValue = XMLMap.encode(this); 291 } 292 catch (Exception e) 293 { 294 throw new RuntimeException (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 (list.size()); 310 } 311 else if (LISTACTUALSIZE.equals(keyString)) 312 { 313 List list = getSubList(); 314 315 returnValue = new Integer (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 346 347 public static String encodeString(String string, String encoding) throws Exception 348 { 349 return URLEncoder.encode(string, encoding); 350 } 351 352 353 354 public static String decodeString(String string, String encoding) throws Exception 355 { 356 return URLDecoder.decode(string, encoding); 357 } 358 359 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 key = entry.getKey(); 370 371 putMapObject(key, entry.getValue()); 372 } 373 374 copySecondary(map); 375 } 376 377 378 379 public void copyFromSource(Object source) throws Exception 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 ) 400 { 401 String 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 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 448 449 public NestedMap() 450 { 451 super(); 452 } 453 454 455 456 public NestedMap(Object source) throws Exception 457 { 458 super(); 459 460 copyFromSource(source); 461 } 462 463 464 465 protected List createList() 466 { 467 return (List)getObject(this, CREATESUBLIST); 468 } 469 470 471 472 protected NestedMap createMap() 473 { 474 return (NestedMap)getObject(this, CREATESUBMAP); 475 } 476 477 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 502 503 public NestedMap getSubMap(Object 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 520 521 public NestedMap getSubMap(Object key) 522 { 523 return getSubMap(key, true); 524 } 525 526 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 551 552 public NestedMap getSubMap(List list, int index) 553 { 554 return getSubMap(list, index, true); 555 } 556 557 558 559 public NestedMap getSubMap(int index, boolean doesCreate) 560 { 561 return getSubMap(getSubList(doesCreate), index, doesCreate); 562 } 563 564 565 566 public NestedMap getSubMap(int index) 567 { 568 return getSubMap(index, true); 569 } 570 571 572 573 public Object getElement(String name) 574 { 575 return getElement(name, false); 576 } 577 578 579 580 protected Object getElement(String name, boolean isList) 581 { 582 String key = name; 583 String indexPart = null; 584 String 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 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 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 654 655 public void setElement(String name, Object value) 656 { 657 659 setElement(name, value, false); 660 } 661 662 663 664 protected void setElement(String name, Object value, boolean isList) 665 { 666 String key = name; 667 String indexPart = null; 668 String 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 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 797 798 public void decode(Map parameters) throws Exception 799 { 800 Iterator iterator = parameters.keySet().iterator(); 801 802 while (iterator.hasNext()) 803 { 804 String name = (String )iterator.next(); 805 806 if (name != null) 807 { 808 if (!name.equals(ENCODED)) 809 { 810 Object value = parameters.get(name); 811 812 setElement(name, value); 813 } 814 } 815 } 816 } 817 818 819 820 protected void encode(String prefix, NestedMap map) 821 { 822 Iterator iterator = keySet().iterator(); 823 824 while (iterator.hasNext()) 825 { 826 String key = (String )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 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 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 872 873 public Map exportParams() throws Exception 874 { 875 NestedMap map = new NestedMap(); 876 877 encode("", map); 878 879 return map; 880 } 881 882 883 884 public void importParams(String encoded) throws Exception 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 897 898 public void importParams(Map parameters) throws Exception 899 { 900 String encoded = (String )parameters.get(ENCODED); 901 902 importParams(encoded); 903 904 decode(parameters); 905 } 906 907 908 909 public Object getObject(Object mapSource, Object 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 returnValue = null; 921 922 if (key != null) 923 { 924 String 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 specialKey = keyString.substring(1); 940 941 Object 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 acceptance = acceptable.get(keyString); 964 965 if ((acceptance == null) || ("w".equals(acceptance))) 966 { 967 throw new RuntimeException (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 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 995 996 public Object putObject(Object mapSource, Object key, Object value) 997 { 998 if (key != null) 999 { 1000 String 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 e) 1025 { 1026 throw new RuntimeException (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 e) 1038 { 1039 throw new RuntimeException (e); 1040 } 1041 1042 return this; 1043 } 1044 else if (DOM.equals(keyString)) 1045 { 1046 try 1047 { 1048 copyFromSource(value); 1049 } 1050 catch (Exception e) 1051 { 1052 throw new RuntimeException (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 e) 1064 { 1065 throw new RuntimeException (e); 1066 } 1067 1068 return this; 1069 } 1070 else if (SOURCE.equals(keyString)) 1071 { 1072 try 1073 { 1074 copyFromSource(value); 1075 } 1076 catch (Exception e) 1077 { 1078 throw new RuntimeException (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 e) 1090 { 1091 throw new RuntimeException (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 )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 acceptance = acceptable.get(key); 1128 1129 if ((acceptance == null) || ("r".equals(acceptance))) 1130 { 1131 throw new RuntimeException (key + " is not acceptable for put operation"); 1132 } 1133 } 1134 } 1135 1136 return super.putObject(mapSource, key, value); 1137 } 1138 1139 1140 1141 public static String encodeMap(Map map, String encoding, boolean doesSort) throws Exception 1142 { 1143 StringBuffer buffer = new StringBuffer (); 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 key = entry.getKey(); 1156 Object value = entry.getValue(); 1157 1158 String keyString = (key != null) ? key.toString() : ""; 1159 String 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 1177 1178 public static NestedMap decodeMap(String string, String encoding) throws Exception 1179 { 1180 NestedMap map = new NestedMap(); 1181 1182 String [] lines = string.split("&"); 1183 1184 for (int i = 0; i < lines.length; i ++) 1185 { 1186 String [] parts = lines[i].split("=", 2); 1187 1188 if (parts.length == 2) 1189 { 1190 String key = decodeString(parts[0], encoding); 1191 String 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 |