1 19 20 package org.netbeans.modules.javacore.jmiimpl.javamodel; 21 22 import java.lang.reflect.Modifier ; 23 import java.util.List ; 24 import java.util.ListIterator ; 25 import javax.jmi.reflect.ConstraintViolationException; 26 import org.netbeans.jmi.javamodel.*; 27 import org.netbeans.lib.java.parser.ASTree; 28 import org.netbeans.lib.java.parser.ASTreeTypes; 29 import org.netbeans.lib.java.parser.Token; 30 import org.netbeans.mdr.storagemodel.StorableObject; 31 import org.netbeans.modules.javacore.JMManager; 32 import org.netbeans.modules.javacore.internalapi.JavaModelUtil; 33 import org.netbeans.modules.javacore.parser.*; 34 import org.openide.util.Utilities; 35 36 37 42 public abstract class FieldImpl extends FeatureImpl implements Field { 43 private static final ElementInfo DEFAULT_INFO = new FieldInfo(null, FieldInfo.FIELD_TYPE, null, 0, null, FieldInfo.SINGLE_FIELD_INDEX, null); 44 45 protected String initialValueText; 46 protected InitialValue initialValue; 47 private boolean initValueInited = false; 48 private boolean elementsInited = false; 49 private TypeReference typeName = null; 50 private int dimCount = 0; 51 private boolean internalSetDim = false; 52 53 54 public FieldImpl(StorableObject s) { 55 super(s); 56 } 57 58 public String toString() { 59 return "field " + getName(); } 61 62 protected ElementInfo getDefaultInfo() { 63 return DEFAULT_INFO; 64 } 65 66 public List getChildren() { 67 List list = super.getChildren(); 68 addIfNotNull(list, getTypeName()); 69 if (!isChanged(CHANGED_INITIAL_VALUE) || initialValueText == null) { 70 addIfNotNull(list, getInitialValue()); 71 } 72 return list; 73 } 74 75 public void fixImports(Element scope, Element original) { 76 Field field = (Field)original; 77 MetadataElement newInitVal = (MetadataElement)getInitialValue(); 78 InitialValue oldInitVal = field.getInitialValue(); 79 80 if (newInitVal != null && oldInitVal != null) { 81 newInitVal.fixImports(scope,oldInitVal); 82 } 83 setTypeName(JavaModelUtil.resolveImportsForType(scope,field.getType())); 84 setDimCount(0); 85 super.fixImports(scope,original); 86 } 87 88 protected List getInitedChildren() { 89 List list = super.getInitedChildren(); 90 if (elementsInited) { 91 addIfNotNull(list, typeName); 92 } 93 if (initValueInited && (!isChanged(CHANGED_INITIAL_VALUE) || initialValueText == null)) { 94 addIfNotNull(list, initialValue); 95 } 96 return list; 97 } 98 99 protected void initASTElements() { 100 elementsInited = false; 101 if (!childrenInited) { 102 initChildren(); 103 } 104 FieldInfo info = (FieldInfo) getElementInfo(); 105 ASTree tree = info.getTypeAST(this); 106 typeName = (TypeReference) initOrCreate(typeName, tree); 107 elementsInited = true; 108 } 109 110 protected void initChildren() { 111 childrenInited = false; 112 super.initChildren(); 113 childrenInited = true; 114 if (elementsInited) { 115 initASTElements(); 116 } 117 if (initValueInited) { 118 JMManager.getTransactionMutex().addBFeatureToInitQueue(this); 119 } 120 } 121 122 protected void resetChildren() { 123 super.resetChildren(); 124 resetASTElements(); 125 } 126 127 protected void setData(List annotations, int modifiers, String javadocText, JavaDoc javadoc, boolean isFinal, TypeReference typeName, int dimCount, InitialValue initialValue, String initialValueText) { 128 super.setData(annotations, javadocText, javadoc); 129 if (initialValueText == null) { 130 changeChild(null, initialValue); 131 this.initialValue = initialValue; 132 } else { 133 if (initialValue != null) { 134 throw new ConstraintViolationException(null, null, "Cannot set both initialValue and initialValueText."); } 136 this.initialValueText = initialValueText; 137 } 138 changeChild(null, typeName); 139 this.typeName = typeName; 140 this.dimCount = dimCount; 141 setTypeRef(typeReferenceToTypeRef(typeName, dimCount)); 142 initValueInited = true; 143 elementsInited = true; 144 } 145 146 public void initInitValue() { 147 initValueInited = false; 148 if (!elementsInited) { 149 initASTElements(); 150 } 151 FieldInfo initValInfo = (FieldInfo) getElementInfo(); 152 if (initValInfo != null) { 153 initValInfo.doAttribution(this); 154 initialValue = (InitialValue) initOrCreate(initialValue, extractInitialValue()); 155 } 156 initValueInited = true; 157 } 158 159 protected void matchPersistent(ElementInfo info) { 160 super.matchPersistent(info); 161 boolean inFieldGroup = refImmediateComposite() instanceof FieldGroup; 162 FieldInfo newInfo = (FieldInfo) info; 163 164 if (newInfo.modifiers != getSourceModifiers()) { 165 if (inFieldGroup) { 166 super_setModifiers(newInfo.modifiers); 167 } else { 168 setModifiers(newInfo.modifiers); 169 } 170 } 171 172 if (!isPersisted()) { 173 setPersisted(true); 174 persist(); 175 setTypeRef(newInfo.type); 176 persistChildren(getPersistentList("annotations", super_getAnnotations()), ((FeatureInfo) info).annotations); 177 } else { 178 if (!Utilities.compareObjects(newInfo.type, getTypeRef())) { 179 if (refImmediateComposite() instanceof FieldGroup) { 180 setTypeRef(newInfo.type); 181 } else { 182 setType(resolveType(newInfo.type)); 183 } 184 } 185 processMembers(getAnnotations(), newInfo.annotations); 186 } 187 } 188 189 protected void matchModifiers(ElementInfo info) { 190 } 191 192 194 protected void matchElementInfo(ElementInfo newInfo) { 195 super.matchElementInfo(newInfo); 196 resetASTElements(); 197 } 198 199 protected void resetASTElements() { 200 if (elementsInited) { 201 if (initialValue != null) { 202 InitialValue temp = initialValue; 203 initialValue = null; 204 changeChild(temp, null); 205 temp.refDelete(); 206 } 207 208 if (typeName != null) { 209 TypeReference temp = typeName; 210 typeName = null; 211 changeChild(temp, null); 212 temp.refDelete(); 213 } 214 initValueInited = false; 215 elementsInited = false; 216 } 217 } 218 219 221 225 public Type getType() { 226 checkUpToDate(); 227 MetadataElement parent = (MetadataElement) refImmediateComposite(); 228 if (parent instanceof FieldGroup && parent.isChanged()) { 229 FieldGroup group = (FieldGroup) parent; 230 Type t=group.getType(); 231 int dims=getDimCount(); 232 233 if (dims>0) { 234 int i; 235 ArrayClass arrClass=((JavaModelPackage)t.refImmediatePackage()).getArray(); 236 237 for(i=0;i<dims;i++) { 238 t=arrClass.resolveArray(t); 239 } 240 } 241 return t; 242 } else { 243 return resolveType(getTypeRef()); 244 } 245 } 246 247 private void fireTypeNameChange(TypeReference typeReference) { 248 Object oldValue = null; 249 Object newValue = null; 250 if (elementsInited && !disableChanges) { 251 oldValue = getTypeName(); 252 newValue = typeReference; 253 } 254 fireAttrChange("typeName", oldValue, newValue); } 256 257 262 public void setType(Type newValue) { 263 TypeRef tr = typeToTypeRef(newValue); 264 TypeReference typeReference = null; 265 if (!disableChanges) { 266 updateDimCount(tr); 267 typeReference = (TypeReference) typeRefToTypeReference(tr, getDimCount()); 268 } 269 fireTypeNameChange(typeReference); 270 _setTypeName(typeReference, tr); 271 } 272 273 private void updateDimCount(TypeRef tr) { 274 int dimCount = getDimCount(); 275 if (tr instanceof ArrayRef) { 276 if (((ArrayRef) tr).dimCount < dimCount) { 277 _setDimCount(((ArrayRef) tr).dimCount); 278 } 279 } else if (dimCount > 0) { 280 _setDimCount(0); 281 } 282 } 283 284 private void _setDimCount(int dimCount) { 285 internalSetDim = true; 286 try { 287 setDimCount(dimCount); 288 } finally { 289 internalSetDim = false; 290 } 291 } 292 293 public TypeReference getTypeName() { 294 checkUpToDate(); 295 if (!elementsInited) { 296 initASTElements(); 297 } 298 MetadataElement parent = (MetadataElement) refImmediateComposite(); 299 if (parent instanceof FieldGroup) { 300 FieldGroup group = (FieldGroup) parent; 301 return group.getTypeName(); 302 } 303 return typeName; 304 } 305 306 public void setTypeName(TypeReference typeName) { 307 _setTypeName(typeName, typeReferenceToTypeRef(typeName, getDimCount())); 308 } 309 310 public void _setTypeName(TypeReference typeName, TypeRef typeRef) { 311 if (!disableChanges) { 312 objectChanged(CHANGED_TYPE); 313 if (typeName != this.typeName) { 314 splitGroup(); 315 } 316 changeChild(getTypeName(), typeName); 317 this.typeName = typeName; 318 } 319 setTypeRef(typeRef); 320 } 321 322 public void setModifiers(int newValue) { 323 objectChanged(CHANGED_MODIFIERS); 324 splitGroup(); 325 super_setModifiers(newValue); 326 } 327 328 public int getModifiers() { 329 MetadataElement parent = (MetadataElement) refImmediateComposite(); 330 if (parent instanceof FieldGroup) { 331 return ((FieldGroup) parent).getModifiers(); 332 } 333 ClassDefinition cd = getDeclaringClass(); 334 int mods = super.getModifiers(); 335 if (cd instanceof JavaClass && ((JavaClass)cd).isInterface()) { 336 return mods | Modifier.STATIC | Modifier.FINAL; 337 } else { 338 return mods; 339 } 340 } 341 342 public void setJavadocText(String newValue) { 343 super.setJavadocText(newValue); 344 splitGroup(); 345 } 346 347 private void splitGroup() { 348 MetadataElement parent = (MetadataElement) refImmediateComposite(); 349 if (parent instanceof FieldGroup) { 350 if (!elementsInited) { 351 initASTElements(); 352 } 353 FieldGroupImpl group = (FieldGroupImpl) parent; 354 int modifiers = group.getSourceModifiers(); 355 Type type = getType(); 356 JavaModelPackage pkg = (JavaModelPackage) refImmediatePackage(); 357 TypeReference typeName = group.getTypeName(); 358 TypeReference typeNameCopy1 = (TypeReference)typeName.duplicate(); 359 TypeReference typeNameCopy2 = (TypeReference)typeName.duplicate(); 360 int i = group.getFields().indexOf(this); 361 ClassDefinition cls = (ClassDefinition) group.refImmediateComposite(); 362 int j = cls.getContents().indexOf(group); 363 if (i == (group.getFields().size() - 1)) { 364 j++; 365 } else if (i != 0) { 366 FieldGroup newGroup = pkg.getFieldGroup().createFieldGroup(null, null, group.getSourceModifiers(), 367 null, null, null, null); 368 newGroup.setTypeName(typeNameCopy1); 369 ListIterator fields = group.getFields().listIterator(i + 1); 370 while (fields.hasNext()) { 371 Field field = (Field) fields.next(); 372 fields.remove(); 373 newGroup.getFields().add(field); 374 } 375 j++; 376 cls.getContents().add(j, newGroup); 377 } 378 group.getFields().remove(this); 379 cls.getContents().add(j, this); 380 if (group.getFields().isEmpty()) { 381 group.refDelete(); 382 } 383 setTypeRef(typeToTypeRef(type)); 384 this.typeName = typeNameCopy2; 385 super_setModifiers(modifiers); 387 } 388 } 389 390 394 public boolean isFinal(){ 395 return Modifier.isFinal(getModifiers()); 396 } 397 402 public void setFinal(boolean newValue){ 403 if (newValue) { 405 setModifiers(getSourceModifiers() | Modifier.FINAL); 406 } else { 407 setModifiers(getSourceModifiers() & ~Modifier.FINAL); 408 } 409 } 410 411 415 public InitialValue getInitialValue() { 416 checkUpToDate(); 417 if (isChanged(CHANGED_INITIAL_VALUE) && initialValueText != null) { 418 throw new ConstraintViolationException(null, null, "Cannot ask for initial value after the initial value text was changed."); } 420 if (!initValueInited) { 421 initInitValue(); 422 } 423 return initialValue; 424 } 425 430 public void setInitialValue(InitialValue newValue){ 431 if (!initValueInited) { 432 initInitValue(); 433 } 434 changeChild(initialValue, newValue); 435 initialValue = newValue; 436 initialValueText = null; 437 objectChanged(CHANGED_INITIAL_VALUE); 438 } 439 443 public java.lang.String getInitialValueText(){ 444 if (isChanged(CHANGED_INITIAL_VALUE)) { 445 if (initialValue != null) { 446 throw new ConstraintViolationException(null, null, "Cannot ask for initial value text after the initial value was changed."); } 448 return initialValueText; 449 } else { 450 return extractInitialValueText(); 451 } 452 } 453 454 private ASTree extractVariableDeclarator() { 455 ASTree fieldTree = getASTree(); 456 if (fieldTree != null && fieldTree.getType() != ASTreeTypes.VARIABLE_DECLARATOR) { 457 return fieldTree.getSubTrees()[2]; 458 } 459 return fieldTree; 460 } 461 462 private ASTree extractInitialValue() { 463 return extractVariableDeclarator().getSubTrees()[2]; 464 } 465 466 private String extractInitialValueText() { 467 ASTProvider parser = getParser(); 468 if (parser == null) 469 return null; 470 ASTree initValue = extractInitialValue(); 471 if (initValue == null) 472 return null; 473 return parser.getText(initValue); 474 } 475 476 481 public void setInitialValueText(java.lang.String newValue){ 482 if (!elementsInited) { 483 initASTElements(); 484 } 485 if (initValueInited && initialValue != null) { 486 changeChild(initialValue, null); 487 } 488 objectChanged(CHANGED_INITIAL_VALUE); 489 initialValueText = newValue; 490 initialValue = null; 491 initValueInited = true; 492 } 493 494 String getRawText() { 498 if (!initValueInited) { 499 initInitValue(); 500 } 501 StringBuffer buf = new StringBuffer (); 503 if (!(refImmediateComposite() instanceof FieldGroup)) { 504 if (isNew()) generateNewJavaDoc(buf); 505 generateNewModifiers(buf); 506 if (getTypeName() != null) { 507 buf.append(((MetadataElement) getTypeName()).getSourceText()); 508 } else { 509 buf.append(getType().getName()); 510 } 511 buf.append(' '); } 513 buf.append(getName()); 514 appendDims(buf, getDimCount()); 515 if (initialValueText != null && initialValueText.trim().length() != 0) { 516 formatElementPart(FIELD_EQUALS, buf); 517 buf.append(initialValueText); 518 } else { 519 if (initialValue != null) { 520 formatElementPart(FIELD_EQUALS, buf); 521 buf.append(((MetadataElement) initialValue).getSourceText()); 522 } 523 } 524 if (!(refImmediateComposite() instanceof FieldGroup)) { 525 if (isNew() || getASTree().getType() == ASTreeTypes.VARIABLE_DECLARATOR) { 526 buf.append(";"); } else { 530 buf.append(IndentUtil.reformatTokenWithPads(this, getASTree().getLastToken())); 531 } 532 } 533 return buf.toString(); 534 } 535 536 public void getDiff(List diffList) { 537 ASTProvider parser = getParser(); 539 ASTree tree = getASTree(); 540 ASTree[] children = tree.getSubTrees(); 541 542 replaceJavaDoc(diffList); 544 if (tree.getType() != ASTreeTypes.VARIABLE_DECLARATOR) { 546 if (isChanged(CHANGED_MODIFIERS) || isChanged(CHANGED_ANNOTATION)) { 548 diffModifiers(diffList, children[TYPE], parser); 549 } else if (children[0] != null) { 550 FieldInfo astInfo=(FieldInfo)getElementInfo(); 551 552 getCollectionDiff(diffList, parser, CHANGED_ANNOTATION, astInfo.annotations, getAnnotations(), parser.getToken(children[0].getLastToken()).getEndOffset(), " "); } 554 getChildDiff(diffList, parser, children[TYPE], (MetadataElement) getTypeName(), CHANGED_TYPE); 556 } 557 ASTree[] varDeclarator; 559 if (tree.getType() == ASTreeTypes.VARIABLE_DECLARATOR) { 560 varDeclarator = tree.getSubTrees(); 561 } else { 562 varDeclarator = children[VARIABLE_DECLARATORS].getSubTrees(); 563 } 564 if (isChanged(CHANGED_NAME)) { 565 Token identifier = (Token) varDeclarator[0]; 566 int startOffset = identifier.getStartOffset(); 567 int endOffset = identifier.getEndOffset(); 568 diffList.add(new DiffElement(startOffset, endOffset, getName())); 569 } 570 if (isChanged(CHANGED_DIM_COUNT)) { 571 replaceNode(diffList, parser, varDeclarator[1], appendDims(new StringBuffer (), getDimCount()).toString(), getEndOffset(getParser(), varDeclarator[0]), ""); 572 } 573 if (isChanged(CHANGED_INITIAL_VALUE)) { 575 int startOffset = 0, endOffset = 0; 576 String text = initialValue == null ? initialValueText : 577 ((MetadataElement) getInitialValue()).getSourceText(); 578 if (varDeclarator[2] != null) { 580 Token startToken; 581 if (text == null || text.trim().length() == 0) { 582 startToken = parser.getToken((varDeclarator[1] == null ? varDeclarator[0] : varDeclarator[1]).getLastToken()); 583 startOffset = startToken.getEndOffset(); 584 } else { 585 startToken = parser.getToken(varDeclarator[2].getFirstToken()); 586 startOffset = startToken.getStartOffset(); 587 } 588 Token endToken = parser.getToken(varDeclarator[2].getLastToken()); 589 endOffset = endToken.getEndOffset(); 590 } 591 else { 593 Token lastTokenOfDecl = parser.getToken(tree.getLastToken()); 596 if (tree.getType() == ASTreeTypes.VARIABLE_DECLARATOR) 597 startOffset = lastTokenOfDecl.getEndOffset(); else 599 startOffset = lastTokenOfDecl.getStartOffset(); endOffset = startOffset; 602 if (text != null) { 603 StringBuffer buf = new StringBuffer (); 604 formatElementPart(FIELD_EQUALS, buf); 605 text = buf + text; 606 } 607 } 608 diffList.add(new DiffElement(startOffset, endOffset, text == null ? "" : text)); 609 } else if (initialValue != null && ((MetadataElement) initialValue).isChanged()) { 610 ((MetadataElement) initialValue).getDiff(diffList); 611 } 612 } 613 614 616 protected ASTree getPartStartTree(ElementPartKind part) { 617 if (ElementPartKindEnum.HEADER.equals(part)) { 618 return getASTree(); 619 } 620 return super.getPartStartTree(part); 621 } 622 623 625 protected ASTree getPartEndTree(ElementPartKind part) { 626 if (ElementPartKindEnum.HEADER.equals(part)) { 627 ASTree[] headerParts = getASTree().getSubTrees(); 628 for (int i = 2; true; i--) { 629 ASTree result = headerParts[i]; 630 if (result != null) { 631 return result; 632 } 633 } 634 } 635 return super.getPartEndTree(part); 636 } 637 638 640 protected ASTree getPartTree(ElementPartKind part) { 641 if (ElementPartKindEnum.NAME.equals(part)) { 643 if (getASTree().getType() == ASTreeTypes.FIELD_DECLARATION) { 644 ASTree[] children = getASTree().getSubTrees(); 645 return children[2].getSubTrees()[0]; 646 } else { 647 return getASTree(); 648 } 649 } 650 throw new IllegalArgumentException ("Invalid part for this element: " + part); } 652 653 private static final int TYPE = 1; 655 private static final int VARIABLE_DECLARATORS = 2; 656 657 public void replaceChild(Element oldElement, Element newElement) { 658 if (elementsInited && oldElement.equals(typeName)) { 659 setTypeName((TypeReference) newElement); 660 return; 661 } 662 if (initValueInited && oldElement.equals(initialValue)) { 663 setInitialValue((InitialValue) newElement); 664 return; 665 } 666 super.replaceChild(oldElement, newElement); 667 } 668 669 public int getDimCount() { 670 if (isChanged(CHANGED_DIM_COUNT)) { 671 return dimCount; 672 } else { 673 ASTree tree = extractVariableDeclarator(); 674 if (tree != null) { 675 ASTree dims = tree.getSubTrees()[1]; 676 if (dims != null) { 677 return (dims.getLastToken() - dims.getFirstToken() + 1) / 2; 678 } 679 } 680 return 0; 681 } 682 } 683 684 public void setDimCount(int dimCount) { 685 objectChanged(CHANGED_DIM_COUNT); 686 this.dimCount = dimCount; 687 if (!internalSetDim) { 688 setTypeRef(typeReferenceToTypeRef(getTypeName(), dimCount)); 690 } 691 } 692 693 void childChanged(MetadataElement mpi) { 694 super.childChanged(mpi); 695 if (elementsInited) { 696 if (mpi == typeName) { 697 setTypeName((TypeReference) mpi); 698 } 699 } 700 } 701 702 public Element duplicate(JavaModelPackage targetExtent) { 703 InitialValue initVal; 704 String initValText; 705 706 if (isChanged(CHANGED_INITIAL_VALUE) && initialValueText != null) { 707 initVal = null; 708 initValText = initialValueText; 709 } else { 710 initVal = (InitialValue) duplicateElement(getInitialValue(), targetExtent); 711 initValText = null; 712 } 713 714 return targetExtent.getField().createField( 715 getName(), 716 duplicateList(getAnnotations(), targetExtent), 717 getModifiers(), 718 null, 719 (JavaDoc) duplicateElement(getJavadoc(), targetExtent), 720 isFinal(), 721 (TypeReference) duplicateElement(getTypeName(), targetExtent), 722 getDimCount(), 723 initVal, 724 initValText 725 ); 726 } 727 728 protected void _delete() { 729 if (elementsInited) { 730 deleteChild(typeName); 731 } 732 if (initValueInited) { 733 deleteChild(initialValue); 734 } 735 super._delete(); 736 } 737 } 738 | Popular Tags |