1 19 package org.netbeans.modules.javacore.jmiimpl.javamodel; 20 21 import java.util.ArrayList ; 22 import org.netbeans.jmi.javamodel.BehavioralFeature; 23 import org.netbeans.jmi.javamodel.Element; 24 import org.netbeans.jmi.javamodel.JavaDoc; 25 import org.netbeans.jmi.javamodel.StatementBlock; 26 import org.netbeans.lib.java.parser.ASTree; 27 import org.netbeans.lib.java.parser.ParserTokens; 28 import org.netbeans.lib.java.parser.Token; 29 import org.netbeans.mdr.storagemodel.StorableObject; 30 import org.netbeans.modules.javacore.parser.*; 31 import javax.jmi.reflect.ConstraintViolationException; 32 import java.util.List ; 33 import java.util.Stack ; 34 import java.lang.ref.WeakReference ; 35 36 37 41 public abstract class BehavioralFeatureImpl extends FeatureImpl implements BehavioralFeature { 42 protected String bodyText; 43 private BodyReference body; 44 protected boolean bodyInited = false; 45 private StatementBlock hardBody; 46 47 48 49 public BehavioralFeatureImpl(StorableObject s) { 50 super(s); 51 } 52 53 55 protected void matchElementInfo(ElementInfo newInfo) { 56 super.matchElementInfo(newInfo); 57 resetBody(); 58 } 59 60 protected void uninitialize() { 61 super.uninitialize(); 62 hardBody = null; 63 retrieveBody(); 64 } 65 66 protected void resetBody() { 67 StatementBlock temp = retrieveBody(); 68 if (temp != null) { 69 body = null; 70 hardBody = null; 71 changeChild(temp, null); 72 temp.refDelete(); 73 } 74 bodyInited = false; 75 } 76 77 protected void objectChanged(int mask) { 78 super.objectChanged(mask); 79 if ((mask | CHANGED_CHILDREN) == mask) { 80 StatementBlock body = retrieveBody(); 81 if (body != null) { 82 hardBody = body; 83 } 84 } 85 } 86 87 protected StatementBlock retrieveBody() { 88 if (body == null) return null; 89 StatementBlock result = (StatementBlock) body.get(); 90 return result; 91 } 92 93 protected abstract ASTree getBodyAST(); 94 95 public java.lang.String getBodyText() { 96 checkUpToDate(); 97 if (isChanged(CHANGED_BODY)) { 98 if (hardBody != null) { 99 throw new ConstraintViolationException(null, null, "Cannot ask for body text after the body was changed."); } 101 return bodyText; 102 } else { 103 ASTProvider parser=getParser(); 104 if (parser==null) 105 return null; 106 ASTree body=getBodyAST(); 107 if (body.getType() == ParserTokens.SEMICOLON) { 108 return null; 109 } else { 110 Token firstToken=parser.getToken(body.getFirstToken()); 111 Token lastToken=parser.getToken(body.getLastToken()); 112 113 return parser.getSourceText().substring(firstToken.getEndOffset(),lastToken.getStartOffset()); 115 } 116 } 117 } 118 119 public void setBodyText(String newValue) { 120 if (!childrenInited) { 121 initChildren(); 122 } 123 StatementBlock temp = retrieveBody(); 124 if (bodyInited && temp != null) { 125 resetBody(); 126 } 127 objectChanged(CHANGED_BODY); 128 bodyInited = true; 129 bodyText = newValue; 130 } 131 132 public StatementBlock getBody() { 133 checkUpToDate(); 134 if (isChanged(CHANGED_BODY) && bodyText != null) { 135 throw new ConstraintViolationException(null, null, "Cannot ask for body after the body text was changed."); } 137 StatementBlock body = retrieveBody(); 138 if (!bodyInited) { 139 body = initBody(); 140 } 141 return body; 142 } 143 144 protected void resetChildren() { 145 super.resetChildren(); 146 resetBody(); 147 } 148 149 public StatementBlock initBody() { 150 bodyInited = false; 151 if (!childrenInited) { 152 initChildren(); 153 } 154 StatementBlock body = retrieveBody(); 155 FeatureInfo info = (FeatureInfo) getElementInfo(); 156 if (getASTree() != null) { 157 ASTree bodyAST = getBodyAST(); 158 if (bodyAST.getType() == ParserTokens.SEMICOLON) { 159 body = null; 160 } else { 161 info.doAttribution(this); 162 body = (StatementBlock) initOrCreate(body, bodyAST); 163 } 164 } 165 this.body = body == null ? null : new BodyReference(body); 166 bodyInited = true; 167 return body; 168 } 169 170 protected void setData(List annotations, String javadocText, JavaDoc javadoc, StatementBlock body, String bodyText) { 171 super.setData(annotations, javadocText, javadoc); 172 if (bodyText == null) { 173 changeChild(null, body); 174 this.hardBody = body; 175 this.body = body == null ? null : new BodyReference(body); 176 } else { 177 if (body != null) { 178 throw new ConstraintViolationException(null, null, "Cannot set both bodyText and body."); } 180 this.bodyText = bodyText; 181 } 182 bodyInited = true; 183 } 184 185 public void setBody(StatementBlock newValue) { 186 StatementBlock body = retrieveBody(); 187 if (!bodyInited) { 188 body = initBody(); 189 } 190 changeChild(body, newValue); 191 hardBody = newValue; 192 this.body = newValue == null ? null : new BodyReference(newValue); 193 bodyText = null; 194 objectChanged(CHANGED_BODY); 195 } 196 197 public List getChildren() { 198 List list = new ArrayList (); 199 if (!isChanged(CHANGED_BODY) || bodyText == null) { 200 addIfNotNull(list, getBody()); 201 } 202 return list; 203 } 204 205 public void fixImports(Element scope, Element original) { 206 BehavioralFeature bhFeature = (BehavioralFeature)original; 207 StatementBlockImpl newBody = (StatementBlockImpl)getBody(); 208 StatementBlock oldBody = bhFeature.getBody(); 209 210 if (newBody != null && oldBody != null) { 211 newBody.fixImports(scope,oldBody); 212 } 213 super.fixImports(scope,original); 214 } 215 216 protected List getInitedChildren() { 217 List list = super.getInitedChildren(); 218 StatementBlock body = retrieveBody(); 219 if (bodyInited && (!isChanged(CHANGED_BODY) || bodyText == null)) { 220 addIfNotNull(list, body); 221 } 222 return list; 223 } 224 225 public void replaceChild(Element oldElement, Element newElement) { 226 StatementBlock body = retrieveBody(); 227 if (bodyInited && oldElement.equals(body)) { 228 setBody((StatementBlock) newElement); 229 return; 230 } 231 super.replaceChild(oldElement, newElement); 232 } 233 234 protected String indentBody(String oldBody) { 235 StringBuffer sb = new StringBuffer (); 236 int state = 0; 237 StringBuffer line = new StringBuffer (); 238 int level = 0; 239 int raiseLevel = 0; 240 int bracket = 0; 241 boolean isStatement = false; 242 boolean previousStatement = false; 243 int questionMark = 0; 244 Stack stack = new Stack (); 245 for (int i = 0; i < oldBody.length(); i++) { 246 char ch = oldBody.charAt(i); 247 if (ch == '\n') { 248 if (i != 0) 249 sb.append(getBodyIndentation()).append(getInnerIndentation(level)).append(line).append(ch); 250 else 251 sb.append(ch); 252 line = new StringBuffer (); 253 if (state != 8) state = 0; 254 level += raiseLevel; 255 if (isStatement && !previousStatement) { 256 level++; 257 } else if (!isStatement && previousStatement) { 258 level--; 259 } 260 previousStatement = isStatement; 261 raiseLevel = 0; 262 } else { 263 switch (state) { 264 case 0: if (!Character.isWhitespace(ch)) { 266 state = 1; 267 } else { 268 break; 269 } 270 case 1: switch (ch) { 272 case '/': 273 state = 2; 274 break; 275 case '"': 276 state = 10; 277 isStatement = true; 278 break; 279 case '\'': 280 state = 4; 281 isStatement = true; 282 break; 283 case '{': 284 if (bracket == 0 && questionMark == 0) { 285 if (!stack.isEmpty()) { 286 stack.push("bracket"); } 288 isStatement = false; 289 raiseLevel++; 290 } else { 291 isStatement = true; 292 } 293 break; 294 case '}': 295 if (bracket == 0 && questionMark == 0) { 296 if (!stack.isEmpty()) { 297 if ("colon".equals(stack.pop())) level--; } 299 isStatement = false; 300 if (line.length() == 0) { 301 level--; 302 } else { 303 raiseLevel--; 304 } 305 } else { 306 isStatement = true; 307 } 308 break; 309 case ';': 310 if (bracket == 0) { 311 isStatement = false; 312 } else { 313 isStatement = true; 314 } 315 questionMark = 0; 316 break; 317 case '?': 318 questionMark++; 319 isStatement = true; 320 break; 321 case '(': 322 bracket++; 323 isStatement = true; 324 break; 325 case ')': 326 bracket--; 327 isStatement = true; 328 break; 329 case ':': 330 if (questionMark > 0) { 331 questionMark--; 332 } else { 333 if (!stack.isEmpty() && stack.peek().equals("colon")) { level--; 335 raiseLevel++; 336 } else { 337 stack.push("colon"); raiseLevel++; 339 } 340 isStatement = false; 341 break; 342 } 343 isStatement = true; 344 break; 345 default: 346 if (!Character.isWhitespace(ch)) { 347 isStatement = true; 348 } 349 break; 350 } 351 if (ch != '\n') { 352 line.append(ch); 353 } 354 break; 355 case 2: if (ch == '/') { 357 state = 3; 358 } else if (ch == '*') { 359 state = 8; 360 } else { 361 isStatement = true; 362 state = 1; 363 } 364 line.append(ch); 365 break; 366 case 3: line.append(ch); 368 break; 369 case 8: if (ch == '*') { 371 state = 9; 372 } 373 line.append(ch); 374 break; 375 case 9: if (ch == '/') { 377 state = 1; 378 } else if (ch != '*') { 379 state = 8; 380 } 381 line.append(ch); 382 break; 383 case 4: if (ch == '\\') { state = 11; 386 } else if (ch == '\'') { 387 state = 1; 388 } 389 line.append(ch); 390 break; 391 case 11: state = 4; 393 line.append(ch); 394 break; 395 case 10: if (ch == '\\') { 397 state = 12; 398 } else if (ch == '"') { 399 state = 1; 400 } 401 line.append(ch); 402 break; 403 case 12: state = 10; 405 line.append(ch); 406 break; 407 } 408 } 409 } 410 if (line.length()>0) 411 sb.append(getBodyIndentation()).append(getInnerIndentation(level)).append(line).append('\n'); 412 return sb.toString(); 413 } 414 415 425 protected void generateBody(StringBuffer buf) { 426 StatementBlock body = retrieveBody(); 427 if (!bodyInited) { 428 body = initBody(); 429 } 430 if (bodyText != null && bodyText.length() > 0 && !bodyText.equals("\n")) { if (bodyText.startsWith("\n") || bodyText.startsWith("\r\n")) { 432 buf.append(getElementPrefix(BODY_OPEN_CURLY)).append('{'); } else { 434 formatElementPart(BODY_OPEN_CURLY, buf); 435 } 436 buf.append(indentBody(bodyText)); 437 formatElementPart(BODY_CLOSE_CURLY, buf); 438 } else if (body != null) { 439 buf.append(((StatementBlockImpl) body).getSourceText()); 440 } else { 441 formatElementPart(BODY_OPEN_CURLY, buf); 442 formatElementPart(BODY_CLOSE_CURLY, buf); 443 } 444 } 445 446 455 protected void createBodyDiffs(List diffList) { 456 ASTProvider parser = getParser(); 457 if (hardBody == null) { if (isChanged(CHANGED_BODY)) { 459 int startOffset; 460 int endOffset; 461 StringBuffer buf = new StringBuffer (); 462 if (bodyText == null) { 463 Token bodyStart = parser.getToken(getBodyAST().getFirstToken() - 1); 464 startOffset = bodyStart.getEndOffset(); 465 buf.append(';'); 466 } else { 467 Token bodyStart = parser.getToken(getBodyAST().getFirstToken()); 468 startOffset = bodyStart.getStartOffset(); 469 if (bodyText.startsWith("\n") || bodyText.startsWith("\r\n")) { 470 buf.append('{'); } else { 472 buf.append(IndentUtil.leftTrim(formatElementPart(BODY_OPEN_CURLY))); 473 } 474 buf.append(indentBody(bodyText)); 475 formatElementPart(BODY_CLOSE_CURLY, buf); 476 } 477 Token bodyEnd = parser.getToken(getBodyAST().getLastToken()); 478 endOffset = bodyEnd.getEndOffset(); 479 diffList.add(new DiffElement(startOffset, endOffset, buf.toString())); 480 } 481 } else { getChildDiff(diffList, parser, getBodyAST(), (MetadataElement) getBody(), CHANGED_BODY); 483 } 484 } 485 486 protected void _delete() { 487 if (bodyInited && body != null) { 489 deleteChild((StatementBlock) body.get()); 490 } 491 super._delete(); 493 } 494 495 private class BodyReference extends WeakReference { 496 BodyReference(StatementBlock body) { 497 super(body); 498 } 499 500 public Object get() { 501 Object result = super.get(); 502 if (result==null) { 503 body = null; 504 bodyInited = false; 505 } 506 return result; 507 } 508 } 509 } 510 | Popular Tags |