1 19 20 package org.netbeans.modules.form.codestructure; 21 22 import java.util.*; 23 import java.lang.reflect.*; 24 import org.netbeans.modules.form.FormJavaSource; 25 26 32 33 public class CodeStructure { 34 35 public static final CodeExpression[] EMPTY_PARAMS = new CodeExpression[0]; 36 37 private static final int VARIABLE_CREATE = 1; 38 private static final int VARIABLE_RENAME = 2; 39 private static final int VARIABLE_RELEASE = 3; 40 private static final int VARIABLE_ATTACH = 4; 41 private static final int VARIABLE_DETACH = 5; 42 43 private static UsingCodeObject globalUsingObject; 44 45 private Map namesToVariables = new HashMap(50); 46 private Map expressionsToVariables = new HashMap(50); 47 private Set externalVariables = null; 48 49 private static int globalDefaultVariableType = CodeVariable.FIELD 50 | CodeVariable.PRIVATE; 51 private int defaultVariableType = -1; 52 53 private boolean undoRedoRecording = false; 54 private int undoRedoMark = 0; 55 private int oldestMark = 0; 56 private int lastUndone = -1; 57 private int undoRedoHardLimit = 10000; 58 private Map undoMap; 59 private Map redoMap; 60 61 private FormJavaSource javaSource; 62 63 66 public CodeStructure(boolean startUndoRedoRecording) { 67 if (startUndoRedoRecording) 68 setUndoRedoRecording(true); 69 } 70 71 public void setFormJavaSource(FormJavaSource formJavaSource) { 72 javaSource = formJavaSource; 73 } 74 75 78 79 public CodeExpression createExpression(Constructor ctor, 80 CodeExpression[] params) 81 { 82 CodeExpressionOrigin origin = 83 new CodeSupport.ConstructorOrigin(ctor, params); 84 return new DefaultCodeExpression(this, origin); 85 } 86 87 88 public CodeExpression createExpression(CodeExpression parent, 89 Method method, 90 CodeExpression[] params) 91 { 92 CodeExpressionOrigin origin = new CodeSupport.MethodOrigin( 93 parent, method, params); 94 return new DefaultCodeExpression(this, origin); 95 } 96 97 98 public CodeExpression createExpression(CodeExpression parent, Field field) { 99 CodeExpressionOrigin origin = new CodeSupport.FieldOrigin(parent, field); 100 return new DefaultCodeExpression(this, origin); 101 } 102 103 104 public CodeExpression createExpression(Class type, 105 Object value, 106 String javaInitStr) 107 { 108 return new DefaultCodeExpression(this, new CodeSupport.ValueOrigin( 109 type, value, javaInitStr)); 110 } 111 112 113 public CodeExpression createExpression(CodeExpressionOrigin origin) { 114 return new DefaultCodeExpression(this, origin); 115 } 116 117 118 public CodeExpression createNullExpression(Class type) { 119 return new DefaultCodeExpression(this, new CodeSupport.ValueOrigin( 120 type, null, "null")); } 122 123 125 public CodeExpression createDefaultExpression() { 126 return new DefaultCodeExpression(this); 127 } 128 129 131 public void registerExpression(CodeExpression expression) { 132 if (globalUsingObject == null) 133 globalUsingObject = new GlobalUsingObject(); 134 135 expression.addUsingObject(globalUsingObject, 136 UsedCodeObject.USING, 137 CodeStructure.class); 138 } 139 140 141 public static void removeExpression(CodeExpression expression) { 142 unregisterUsedCodeObject(expression); 143 unregisterUsingCodeObject(expression); 144 145 expression.getCodeStructure().removeExpressionFromVariable(expression); 146 } 147 148 150 public static CodeExpression[] filterExpressions(Iterator it, 151 Object originMetaObject) 152 { 153 List list = new ArrayList(); 154 while (it.hasNext()) { 155 CodeExpression exp = (CodeExpression) it.next(); 156 if (originMetaObject.equals(exp.getOrigin().getMetaObject())) 157 list.add(exp); 158 } 159 return (CodeExpression[]) list.toArray(new CodeExpression[list.size()]); 160 } 161 162 165 166 public static CodeStatement createStatement(CodeExpression expression, 167 Method m, 168 CodeExpression[] params) 169 { 170 CodeStatement statement = new CodeSupport.MethodStatement( 171 expression, m, params); 172 registerUsingCodeObject(statement); 173 return statement; 174 } 175 176 177 public static CodeStatement createStatement(CodeExpression expression, 178 Field f, 179 CodeExpression assignExp) 180 { 181 CodeStatement statement = new CodeSupport.FieldStatement( 182 expression, f, assignExp); 183 registerUsingCodeObject(statement); 184 return statement; 185 } 186 187 188 public static void removeStatement(CodeStatement statement) { 189 unregisterUsingCodeObject(statement); 190 } 191 192 193 public static void removeStatements(Iterator it) { 194 List list = new ArrayList(); 195 while (it.hasNext()) 196 list.add(it.next()); 197 198 for (int i=0, n=list.size(); i < n; i++) 199 unregisterUsingCodeObject((CodeStatement) list.get(i)); 200 } 201 202 204 public static CodeStatement[] filterStatements(Iterator it, 205 Object metaObject) 206 { 207 List list = new ArrayList(); 208 while (it.hasNext()) { 209 CodeStatement statement = (CodeStatement) it.next(); 210 if (metaObject.equals(statement.getMetaObject())) 211 list.add(statement); 212 } 213 return (CodeStatement[]) list.toArray(new CodeStatement[list.size()]); 214 } 215 216 219 220 public CodeGroup createCodeGroup() { 221 return new CodeSupport.DefaultCodeGroup(); 222 } 223 224 227 228 public static CodeExpressionOrigin createOrigin(Constructor ctor, 229 CodeExpression[] params) 230 { 231 return new CodeSupport.ConstructorOrigin(ctor, params); 232 } 233 234 235 public static CodeExpressionOrigin createOrigin(CodeExpression parent, 236 Method m, 237 CodeExpression[] params) 238 { 239 return new CodeSupport.MethodOrigin(parent, m, params); 240 } 241 242 243 public static CodeExpressionOrigin createOrigin(CodeExpression parent, 244 Field f) 245 { 246 return new CodeSupport.FieldOrigin(parent, f); 247 } 248 249 250 public static CodeExpressionOrigin createOrigin(Class type, 251 Object value, 252 String javaStr) 253 { 254 return new CodeSupport.ValueOrigin(type, value, javaStr); 255 } 256 257 261 264 public static Iterator getDefinedExpressionsIterator(CodeExpression exp) { 265 return exp.getUsingObjectsIterator(UsedCodeObject.DEFINED, 266 CodeExpression.class); 267 } 268 269 271 public static Iterator getUsingExpressionsIterator(CodeExpression exp) { 272 return exp.getUsingObjectsIterator(UsedCodeObject.USING, 273 CodeExpression.class); 274 } 275 276 278 public static Iterator getDefinedStatementsIterator(CodeExpression exp) { 279 return exp.getUsingObjectsIterator(UsedCodeObject.DEFINED, 280 CodeStatement.class); 281 } 282 283 285 public static Iterator getUsingStatementsIterator(CodeExpression exp) { 286 return exp.getUsingObjectsIterator(UsedCodeObject.USING, 287 CodeStatement.class); 288 } 289 290 293 static void registerUsingCodeObject(CodeStatement statement) { 295 CodeExpression parent = statement.getParentExpression(); 296 if (parent != null) 297 parent.addUsingObject( 298 statement, UsedCodeObject.DEFINED, CodeStatement.class); 299 300 CodeExpression[] params = statement.getStatementParameters(); 301 if (params != null) 302 for (int i=0; i < params.length; i++) 303 params[i].addUsingObject( 304 statement, UsedCodeObject.USING, CodeStatement.class); 305 } 306 307 static void registerUsingCodeObject(CodeExpression expression) { 309 CodeExpressionOrigin origin = expression.getOrigin(); 310 CodeExpression parent = origin.getParentExpression(); 311 312 if (parent != null) 313 parent.addUsingObject(expression, 314 UsedCodeObject.DEFINED, 315 CodeExpression.class); 316 317 CodeExpression[] params = origin.getCreationParameters(); 318 if (params != null) 319 for (int i=0; i < params.length; i++) 320 params[i].addUsingObject(expression, 321 UsedCodeObject.USING, 322 CodeExpression.class); 323 } 324 325 static void unregisterUsingCodeObject(UsingCodeObject usingObject) { 327 Iterator it = usingObject.getUsedObjectsIterator(); 328 while (it.hasNext()) { 329 UsedCodeObject usedObject = (UsedCodeObject) it.next(); 330 if (!usedObject.removeUsingObject(usingObject)) { 331 if (usedObject instanceof UsingCodeObject) 333 unregisterUsingCodeObject((UsingCodeObject)usedObject); 334 } 335 } 336 } 337 338 static void unregisterObjectUsage(UsingCodeObject usingObject, 340 UsedCodeObject usedObject) 341 { 342 if (!usedObject.removeUsingObject(usingObject)) { 343 if (usedObject instanceof UsingCodeObject) 345 unregisterUsingCodeObject((UsingCodeObject)usedObject); 346 } 347 } 348 349 static void unregisterUsedCodeObject(UsedCodeObject usedObject) { 352 List usingObjects = new ArrayList(); 353 Iterator it = usedObject.getUsingObjectsIterator(0, null); 354 while (it.hasNext()) 355 usingObjects.add(it.next()); 356 357 it = usingObjects.iterator(); 358 while (it.hasNext()) { 359 UsingCodeObject usingObject = (UsingCodeObject) it.next(); 360 if (!usingObject.usedObjectRemoved(usedObject)) { 361 if (usingObject instanceof UsedCodeObject) 363 unregisterUsedCodeObject((UsedCodeObject)usingObject); 364 unregisterUsingCodeObject(usingObject); 365 } 366 } 367 } 368 369 private static class GlobalUsingObject implements UsingCodeObject { 370 public void usageRegistered(UsedCodeObject usedObject) { 371 } 372 public boolean usedObjectRemoved(UsedCodeObject usedObject) { 373 return true; 374 } 375 public UsedCodeObject getDefiningObject() { 376 return null; 377 } 378 public Iterator getUsedObjectsIterator() { 379 return null; 380 } 381 } 382 383 386 387 public CodeVariable createVariable(int type, 388 Class declaredType, 389 String name) 390 { 391 if (getVariable(name) != null) 392 return null; 394 if (type < 0 || name == null) 395 throw new IllegalArgumentException (); 396 397 Variable var = new Variable(type, declaredType, name); 398 namesToVariables.put(name, var); 399 400 if (undoRedoRecording) 401 logUndoableChange(new VariableChange(VARIABLE_CREATE, var)); 402 403 return var; 404 } 405 406 407 public boolean renameVariable(String oldName, String newName) { 408 Variable var = (Variable) namesToVariables.get(oldName); 409 if (var == null || newName == null 410 || newName.equals(var.getName()) 411 || namesToVariables.get(newName) != null) 412 return false; 413 414 namesToVariables.remove(oldName); 415 var.name = newName; 416 namesToVariables.put(newName, var); 417 418 if (undoRedoRecording) { 419 VariableChange change = new VariableChange(VARIABLE_RENAME, var); 420 change.oldName = oldName; 421 change.newName = newName; 422 logUndoableChange(change); 423 } 424 425 return true; 426 } 427 428 429 public CodeVariable releaseVariable(String name) { 430 Variable var = (Variable) namesToVariables.remove(name); 431 if (var == null) 432 return null; 434 Map expressionsMap = var.expressionsMap; 435 if (expressionsMap == null) 436 return var; 437 438 Iterator it = expressionsMap.values().iterator(); 439 while (it.hasNext()) 440 expressionsToVariables.remove(it.next()); 441 442 if (undoRedoRecording) 443 logUndoableChange(new VariableChange(VARIABLE_RELEASE, var)); 444 445 return var; 446 } 447 448 449 public boolean isVariableNameReserved(String name) { 450 return namesToVariables.get(name) != null || javaSource.containsField(name, true); 451 } 452 453 456 public CodeVariable createVariableForExpression(CodeExpression expression, 457 int type, 458 String name) 459 { 460 if (expression == null) 461 throw new IllegalArgumentException (); 462 463 if (getVariable(expression) != null) 464 return null; 466 if (type < 0) 467 throw new IllegalArgumentException (); 468 469 if (expressionsToVariables.get(expression) != null) 470 removeExpressionFromVariable(expression); 471 472 name = getFreeVariableName(name, expression.getOrigin().getType()); 473 474 Variable var = new Variable(type, 475 expression.getOrigin().getType(), 476 name); 477 CodeStatement statement = createVariableAssignment(var, expression); 478 var.addCodeExpression(expression, statement); 479 480 namesToVariables.put(name, var); 481 expressionsToVariables.put(expression, var); 482 483 if (undoRedoRecording) { 484 logUndoableChange(new VariableChange(VARIABLE_CREATE, var)); 485 VariableChange change = new VariableChange(VARIABLE_ATTACH, var); 486 change.expression = expression; 487 change.statement = statement; 488 logUndoableChange(change); 489 } 490 491 return var; 492 } 493 494 private String getFreeVariableName(String name, Class type) { 495 if (name == null || namesToVariables.get(name) != null) { 496 int n = 0; 498 String baseName; 499 if (name != null) { int i = name.length(); 502 int exp = 1; 503 while (--i >= 0) { 504 char c = name.charAt(i); 505 if (c >= '0' && c <= '9') { 506 n += (c - '0') * exp; 507 exp *= 10; 508 } 509 else break; 510 } 511 512 baseName = i >= 0 ? name.substring(0, i+1) : name; 513 } 514 else { String typeName = type.getName(); 516 int i = typeName.lastIndexOf('$'); if (i < 0) { 518 i = typeName.lastIndexOf('+'); if (i < 0) 520 i = typeName.lastIndexOf('.'); } 522 baseName = Character.toLowerCase(typeName.charAt(i+1)) 523 + typeName.substring(i+2); 524 } 525 526 javaSource.refresh(); 527 do { name = baseName + (++n); 529 } 530 while ( namesToVariables.get(name) != null || javaSource.containsField(name, false) ); 531 } 532 return name; 533 } 534 535 public String getExternalVariableName(Class type, String suggestedName, boolean register) { 536 String name = getFreeVariableName(suggestedName, type); 537 if (register) { 538 createVariable(CodeVariable.LOCAL, type, name); 539 if(externalVariables == null) { 540 externalVariables = new HashSet(); 541 } 542 externalVariables.add(name); 543 } 544 return name; 545 } 546 547 public void clearExternalVariableNames() { 548 if(externalVariables!=null) { 549 for (Iterator it = externalVariables.iterator(); it.hasNext();) { 550 releaseVariable((String ) it.next()); 551 } 552 externalVariables.clear(); 553 } 554 } 555 556 558 public void attachExpressionToVariable(CodeExpression expression, 559 CodeVariable variable) 560 { 561 if (expression == null) 562 return; 563 565 if (variable.getAssignment(expression) != null) 566 return; 568 int mask = CodeVariable.LOCAL 570 | CodeVariable.EXPLICIT_DECLARATION; 571 if ((variable.getType() & mask) == CodeVariable.LOCAL 572 && variable.getAttachedExpressions().size() > 0) 573 { throw new IllegalStateException ( 576 "Standalone local variable declaration required for: " + variable.getName()); 578 } 579 580 Variable prevVar = (Variable) expressionsToVariables.get(expression); 581 if (prevVar != null && prevVar != variable) 582 removeExpressionFromVariable(expression); 583 584 Variable var = (Variable) variable; 585 CodeStatement statement = createVariableAssignment(var, expression); 586 587 var.addCodeExpression(expression, statement); 588 expressionsToVariables.put(expression, var); 589 590 if (undoRedoRecording) { 591 VariableChange change = new VariableChange(VARIABLE_ATTACH, var); 592 change.expression = expression; 593 change.statement = statement; 594 logUndoableChange(change); 595 } 596 } 597 598 599 public void removeExpressionFromVariable(CodeExpression expression) { 600 if (expression == null) 601 return; 602 603 Variable var = (Variable) expressionsToVariables.remove(expression); 604 if (var == null) 605 return; 606 607 CodeStatement statement = var.removeCodeExpression(expression); 608 609 if (undoRedoRecording) { 610 VariableChange change = new VariableChange(VARIABLE_DETACH, var); 611 change.expression = expression; 612 change.statement = statement; 613 logUndoableChange(change); 614 } 615 616 if (var.expressionsMap.isEmpty() 617 && (var.getType() & CodeVariable.EXPLICIT_RELEASE) == 0) 618 releaseVariable(var.getName()); 620 } 621 622 623 public CodeVariable getVariable(String name) { 624 return (Variable) namesToVariables.get(name); 625 } 626 627 628 public CodeVariable getVariable(CodeExpression expression) { 629 return (Variable) expressionsToVariables.get(expression); 630 } 631 632 633 public Iterator getVariablesIterator(int type, int typeMask, 634 Class declaredType) 635 { 636 return new VariablesIterator(namesToVariables.values().iterator(), type, typeMask, declaredType); 637 } 638 639 640 public Collection getAllVariables() { 641 return Collections.unmodifiableCollection(namesToVariables.values()); 642 } 643 644 646 648 public static void setGlobalDefaultVariableType(int type) { 649 if (type < 0) { 650 globalDefaultVariableType = CodeVariable.FIELD 651 | CodeVariable.PRIVATE; 652 } 653 else { 654 type &= CodeVariable.ALL_MASK; 655 if ((type & CodeVariable.SCOPE_MASK) == CodeVariable.NO_VARIABLE) 656 type |= CodeVariable.FIELD; 657 int fdMask = CodeVariable.EXPLICIT_DECLARATION | CodeVariable.FINAL; 658 if ((type & fdMask) == fdMask) 659 type &= ~CodeVariable.EXPLICIT_DECLARATION; 660 661 globalDefaultVariableType = type; 662 } 663 } 664 665 667 public void setDefaultVariableType(int type) { 668 if (type < 0) { 669 defaultVariableType = -1; } 671 else { 672 type &= CodeVariable.ALL_MASK; 673 if ((type & CodeVariable.SCOPE_MASK) == CodeVariable.NO_VARIABLE) 674 type |= CodeVariable.FIELD; 675 int fdMask = CodeVariable.EXPLICIT_DECLARATION | CodeVariable.FINAL; 676 if ((type & fdMask) == fdMask) 677 type &= ~CodeVariable.EXPLICIT_DECLARATION; 678 679 defaultVariableType = type; 680 } 681 } 682 683 static int getGlobalDefaultVariableType() { 684 return globalDefaultVariableType; 685 } 686 687 int getDefaultVariableType() { 688 return defaultVariableType > -1 ? 689 defaultVariableType : globalDefaultVariableType; 690 } 691 692 694 protected Map getNamesToVariablesMap() { 695 return namesToVariables; 696 } 697 698 protected Map getExpressionsToVariables() { 699 return expressionsToVariables; 700 } 701 702 private CodeStatement createVariableAssignment(CodeVariable var, 703 CodeExpression expression) 704 { 705 CodeStatement statement = 706 new CodeSupport.AssignVariableStatement(var, expression); 707 708 712 return statement; 713 } 714 715 718 public void setUndoRedoRecording(boolean record) { 719 undoRedoRecording = record; 720 if (record && undoMap == null) { 721 undoMap = new HashMap(500); 722 redoMap = new HashMap(100); 723 } 724 } 725 726 public boolean isUndoRedoRecording() { 727 return undoRedoRecording; 728 } 729 730 void logUndoableChange(CodeStructureChange change) { 731 redoMap.clear(); 732 lastUndone = -1; 733 734 if (undoMap.size() == 0) 735 oldestMark = undoRedoMark; 736 737 t("adding undoable change "+undoRedoMark); 739 undoMap.put(new Integer (undoRedoMark++), change); 740 741 if (undoMap.size() > undoRedoHardLimit) 742 t("undo/redo hard limit reached: " +undoMap.size()+" > "+undoRedoHardLimit); 745 while (undoMap.size() > undoRedoHardLimit) { 746 Object mark = new Integer (oldestMark++); 747 undoMap.remove(mark); 748 } 749 } 750 751 public Object markForUndo() { 752 redoMap.clear(); 753 754 t("mark for undo: "+undoRedoMark); 756 Object newMark = new Integer (undoRedoMark); 757 758 return newMark; 759 } 760 761 public void releaseUndoableChanges(Object fromMark, Object toMark) { 762 int m1 = ((Integer )fromMark).intValue(); 763 int m2 = ((Integer )toMark).intValue(); 764 765 t("release marks from " + m1 + " to " + m2); 767 while (m1 < m2) { 768 Object m = new Integer (m1); 769 undoMap.remove(m); 770 redoMap.remove(m); 771 m1++; 772 } 773 } 774 775 public boolean undoToMark(Object mark) { 776 int lastMark = ((Integer )mark).intValue(); 777 int currentMark = undoRedoMark; 778 if (currentMark <= lastMark) 779 return false; 781 t("undo to mark "+mark); 783 if (undoMap.get(mark) == null) { 784 t("mark already dropped from the queue"); return false; 786 } 787 788 boolean undoRedoOn = undoRedoRecording; 789 undoRedoRecording = false; 790 791 while (currentMark > lastMark) { 792 Object key = new Integer (--currentMark); 793 CodeStructureChange change = (CodeStructureChange) 794 undoMap.remove(key); 795 if (change != null) { 796 change.undo(); 797 redoMap.put(key, change); 798 lastUndone = currentMark; 799 800 t("undone: "+key); } 802 } 803 804 if (undoRedoOn) 805 undoRedoRecording = true; 806 807 return true; 808 } 809 810 public boolean redoToMark(Object mark) { 811 if (lastUndone < 0) 812 return false; 813 int toMark = ((Integer )mark).intValue(); 814 if (lastUndone >= toMark || toMark > undoRedoMark) 815 return false; 817 t("redo to mark "+mark); 819 boolean undoRedoOn = undoRedoRecording; 820 undoRedoRecording = false; 821 822 while (lastUndone < toMark) { 823 Object key = new Integer (lastUndone++); 824 CodeStructureChange change = (CodeStructureChange) 825 redoMap.remove(key); 826 if (change != null) { 827 change.redo(); 828 undoMap.put(key, change); 829 830 t("redone: "+key); } 832 } 833 834 if (undoRedoOn) 835 undoRedoRecording = true; 836 837 return true; 838 } 839 840 843 final class Variable implements CodeVariable { 844 private int type; 845 private Class declaredType; 846 private String name; 847 private Map expressionsMap; 848 private CodeStatement declarationStatement; 849 850 Variable(int type, Class declaredType, String name) { 851 if ((type & FINAL) != 0) 852 type &= ~EXPLICIT_DECLARATION; 853 this.type = type; 854 this.declaredType = declaredType; 855 this.name = name; 856 } 857 858 public int getType() { 859 return (type & DEFAULT_TYPE) != DEFAULT_TYPE ? 860 type : getDefaultVariableType(); 861 } 862 863 public String getName() { 864 return name; 865 } 866 867 public Class getDeclaredType() { 868 return declaredType; 869 } 870 871 public Collection getAttachedExpressions() { 872 return expressionsMap != null ? 873 Collections.unmodifiableCollection(expressionsMap.keySet()) : 874 Collections.EMPTY_LIST; 875 } 876 877 public CodeStatement getDeclaration() { 878 if (declarationStatement == null) 879 declarationStatement = 880 new CodeSupport.DeclareVariableStatement(this); 881 return declarationStatement; 882 } 883 884 public CodeStatement getAssignment(CodeExpression expression) { 885 return expressionsMap != null ? 886 (CodeStatement) expressionsMap.get(expression) : null; 887 } 888 889 891 void addCodeExpression(CodeExpression expression, 892 CodeStatement statement) 893 { 894 if (expressionsMap == null) 895 expressionsMap = new HashMap(); 896 expressionsMap.put(expression, statement); 897 } 898 899 CodeStatement removeCodeExpression(CodeExpression expression) { 900 if (expressionsMap != null) 901 return (CodeStatement) expressionsMap.remove(expression); 902 return null; 903 } 904 } 905 906 private static final class VariablesIterator implements Iterator { 907 private int type; 908 private int typeMask; 909 private Class declaredType; 910 911 private Iterator subIterator; 912 913 private CodeVariable currentVar; 914 915 public VariablesIterator(Iterator subIterator, int type, int typeMask, Class declaredType) { 916 this.type = type; 917 this.typeMask = typeMask; 918 this.declaredType = declaredType; 919 this.subIterator = subIterator; 920 } 921 922 public boolean hasNext() { 923 if (currentVar != null) 924 return true; 925 926 while (subIterator.hasNext()) { 927 CodeVariable var = (CodeVariable) subIterator.next(); 928 if ((type < 0 929 || (type & typeMask) == (var.getType() & typeMask)) 930 && 931 (declaredType == null 932 || declaredType.equals(var.getDeclaredType()))) 933 { 934 currentVar = var; 935 return true; 936 } 937 } 938 939 return false; 940 } 941 942 public Object next() { 943 if (!hasNext()) 944 throw new NoSuchElementException(); 945 946 CodeVariable var = currentVar; 947 currentVar = null; 948 return var; 949 } 950 951 public void remove() { 952 throw new UnsupportedOperationException (); 953 } 954 } 955 956 958 private class VariableChange implements CodeStructureChange { 959 private int changeType; 960 private Variable variable; 961 private CodeExpression expression; 962 private CodeStatement statement; 963 private String oldName; 964 private String newName; 965 966 VariableChange(int type, Variable var) { 967 changeType = type; 968 variable = var; 969 } 970 971 public void undo() { 972 switch (changeType) { 973 case VARIABLE_CREATE: 974 namesToVariables.remove(variable.name); 975 break; 976 case VARIABLE_RENAME: 977 namesToVariables.remove(newName); 978 variable.name = oldName; 979 namesToVariables.put(oldName, variable); 980 break; 981 case VARIABLE_RELEASE: 982 Iterator it = variable.expressionsMap.values().iterator(); 983 while (it.hasNext()) 984 expressionsToVariables.put(it.next(), variable); 985 namesToVariables.put(variable.name, variable); 986 break; 987 case VARIABLE_ATTACH: 988 expressionsToVariables.remove(expression); 989 variable.expressionsMap.remove(expression); 990 break; 991 case VARIABLE_DETACH: 992 variable.expressionsMap.put(expression, statement); 993 expressionsToVariables.put(expression, variable); 994 break; 995 } 996 } 997 998 public void redo() { 999 switch (changeType) { 1000 case VARIABLE_CREATE: 1001 namesToVariables.put(variable.name, variable); 1002 break; 1003 case VARIABLE_RENAME: 1004 namesToVariables.remove(oldName); 1005 variable.name = newName; 1006 namesToVariables.put(newName, variable); 1007 break; 1008 case VARIABLE_RELEASE: 1009 namesToVariables.remove(variable.name); 1010 Iterator it = variable.expressionsMap.values().iterator(); 1011 while (it.hasNext()) 1012 expressionsToVariables.remove(it.next()); 1013 break; 1014 case VARIABLE_ATTACH: 1015 variable.expressionsMap.put(expression, statement); 1016 expressionsToVariables.put(expression, variable); 1017 break; 1018 case VARIABLE_DETACH: 1019 expressionsToVariables.remove(expression); 1020 variable.expressionsMap.remove(expression); 1021 break; 1022 } 1023 } 1024 } 1025 1026 1028 1029 static private int traceCount = 0; 1030 1031 static private final boolean TRACE = false; 1032 1033 static void t(String str) { 1034 if (TRACE) 1035 if (str != null) 1036 System.out.println("CodeStructure "+(++traceCount)+": "+str); else 1038 System.out.println(""); } 1040} 1041 | Popular Tags |