|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.javacore.jmiimpl.javamodel; import java.util.ArrayList; import org.netbeans.jmi.javamodel.BehavioralFeature; import org.netbeans.jmi.javamodel.Element; import org.netbeans.jmi.javamodel.JavaDoc; import org.netbeans.jmi.javamodel.StatementBlock; import org.netbeans.lib.java.parser.ASTree; import org.netbeans.lib.java.parser.ParserTokens; import org.netbeans.lib.java.parser.Token; import org.netbeans.mdr.storagemodel.StorableObject; import org.netbeans.modules.javacore.parser.*; import javax.jmi.reflect.ConstraintViolationException; import java.util.List; import java.util.Stack; import java.lang.ref.WeakReference; /** * * @author Martin Matula, Vladimir Hudec */ public abstract class BehavioralFeatureImpl extends FeatureImpl implements BehavioralFeature { protected String bodyText; private BodyReference body; protected boolean bodyInited = false; private StatementBlock hardBody; /** Creates a new instance of InitializerImpl */ public BehavioralFeatureImpl(StorableObject s) { super(s); } /** The method has to make sure that the AST infos of children are also updated. */ protected void matchElementInfo(ElementInfo newInfo) { super.matchElementInfo(newInfo); resetBody(); } protected void uninitialize() { super.uninitialize(); hardBody = null; retrieveBody(); } protected void resetBody() { StatementBlock temp = retrieveBody(); if (temp != null) { body = null; hardBody = null; changeChild(temp, null); temp.refDelete(); } bodyInited = false; } protected void objectChanged(int mask) { super.objectChanged(mask); if ((mask | CHANGED_CHILDREN) == mask) { StatementBlock body = retrieveBody(); if (body != null) { hardBody = body; } } } protected StatementBlock retrieveBody() { if (body == null) return null; StatementBlock result = (StatementBlock) body.get(); return result; } protected abstract ASTree getBodyAST(); public java.lang.String getBodyText() { if (isChanged(CHANGED_BODY)) { if (hardBody != null) { throw new ConstraintViolationException(null, null, "Cannot ask for body text after the body was changed."); // NOI18N } return bodyText; } else { ASTree body=getBodyAST(); if (body.getType() == ParserTokens.SEMICOLON) { return null; } else { ASTProvider parser=getParser(); if (parser==null) return null; Token firstToken=parser.getToken(body.getFirstToken()); Token lastToken=parser.getToken(body.getLastToken()); // remove { } from body text return parser.getSourceText().substring(firstToken.getEndOffset(),lastToken.getStartOffset()); } } } public void setBodyText(java.lang.String newValue) { if (!childrenInited) { initChildren(); } StatementBlock body = retrieveBody(); if (bodyInited && body != null) { changeChild(body, null); } objectChanged(CHANGED_BODY); bodyInited = true; bodyText = newValue; body = null; } public StatementBlock getBody() { if (isChanged(CHANGED_BODY) && bodyText != null) { throw new ConstraintViolationException(null, null, "Cannot ask for body after the body text was changed."); // NOI18N } StatementBlock body = retrieveBody(); if (!bodyInited) { body = initBody(); } return body; } protected void resetChildren() { resetBody(); } public StatementBlock initBody() { bodyInited = false; if (!childrenInited) { initChildren(); } StatementBlock body = retrieveBody(); FeatureInfo bodyTree = (FeatureInfo) getElementInfo(); if (bodyTree != null) { ASTree bodyAST = getBodyAST(); if (bodyAST.getType() == ParserTokens.SEMICOLON) { body = null; } else { bodyTree.doAttribution(this); body = (StatementBlock) initOrCreate(body, bodyAST); } } this.body = body == null ? null : new BodyReference(body); bodyInited = true; return body; } protected void setData(List annotations, String javadocText, JavaDoc javadoc, StatementBlock body, String bodyText) { super.setData(annotations, javadocText, javadoc); if (bodyText == null) { changeChild(null, body); this.hardBody = body; this.body = body == null ? null : new BodyReference(body); } else { if (body != null) { throw new ConstraintViolationException(null, null, "Cannot set both bodyText and body."); // NOI18N } this.bodyText = bodyText; } bodyInited = true; } public void setBody(StatementBlock newValue) { StatementBlock body = retrieveBody(); if (!bodyInited) { body = initBody(); } changeChild(body, newValue); hardBody = newValue; this.body = newValue == null ? null : new BodyReference(newValue); bodyText = null; objectChanged(CHANGED_BODY); } public List getChildren() { List list = super.getChildren(); if (!isChanged(CHANGED_BODY) || bodyText == null) { addIfNotNull(list, getBody()); } return list; } protected List getInitedChildren() { List list = new ArrayList(1); StatementBlock body = retrieveBody(); if (bodyInited && (!isChanged(CHANGED_BODY) || bodyText == null)) { addIfNotNull(list, body); } return list; } public void replaceChild(Element oldElement, Element newElement) { StatementBlock body = retrieveBody(); if (bodyInited && oldElement.equals(body)) { setBody((StatementBlock) newElement); return; } super.replaceChild(oldElement, newElement); } protected String indentBody(String oldBody) { StringBuffer sb = new StringBuffer(); int state = 0; StringBuffer line = new StringBuffer(); int level = 0; int raiseLevel = 0; int bracket = 0; boolean isStatement = false; boolean previousStatement = false; int questionMark = 0; Stack stack = new Stack(); for (int i = 0; i < oldBody.length(); i++) { char ch = oldBody.charAt(i); if (ch == '\n') { if (i != 0) sb.append(getBodyIndentation()).append(getInnerIndentation(level)).append(line).append(ch); else sb.append(ch); line = new StringBuffer(); if (state != 8) state = 0; level += raiseLevel; if (isStatement && !previousStatement) { level++; } else if (!isStatement && previousStatement) { level--; } previousStatement = isStatement; raiseLevel = 0; } else { switch (state) { case 0: // leading whitespaces if (!Character.isWhitespace(ch)) { state = 1; } else { break; } case 1: // code switch (ch) { case '/': state = 2; break; case '"': state = 10; isStatement = true; break; case '\'': state = 4; isStatement = true; break; case '{': if (bracket == 0 && questionMark == 0) { if (!stack.isEmpty()) { stack.push("bracket"); // NOI18N } isStatement = false; raiseLevel++; } else { isStatement = true; } break; case '}': if (bracket == 0 && questionMark == 0) { if (!stack.isEmpty()) { if ("colon".equals(stack.pop())) level--; // NOI18N } isStatement = false; if (line.length() == 0) { level--; } else { raiseLevel--; } } else { isStatement = true; } break; case ';': if (bracket == 0) { isStatement = false; } else { isStatement = true; } questionMark = 0; break; case '?': questionMark++; isStatement = true; break; case '(': bracket++; isStatement = true; break; case ')': bracket--; isStatement = true; break; case ':': if (questionMark > 0) { questionMark--; } else { if (!stack.isEmpty() && stack.peek().equals("colon")) { // NOI18N level--; raiseLevel++; } else { stack.push("colon"); // NOI18N raiseLevel++; } isStatement = false; break; } isStatement = true; break; default: if (!Character.isWhitespace(ch)) { isStatement = true; } break; } if (ch != '\n') { line.append(ch); } break; case 2: // maybe a comment (/) - is it followed by another / or *? if (ch == '/') { state = 3; } else if (ch == '*') { state = 8; } else { isStatement = true; state = 1; } line.append(ch); break; case 3: // simple comment line.append(ch); break; case 8: // multi-line comment if (ch == '*') { state = 9; } line.append(ch); break; case 9: // end of comment? if (ch == '/') { state = 1; } else if (ch != '*') { state = 8; } line.append(ch); break; case 4: // char literal if (ch == '\\') { // escape state = 11; } else if (ch == '\'') { state = 1; } line.append(ch); break; case 11: // escape in char literal state = 4; line.append(ch); break; case 10: // string literal if (ch == '\\') { state = 12; } else if (ch == '"') { state = 1; } line.append(ch); break; case 12: // escape in string literal state = 10; line.append(ch); break; } } } if (line.length()>0) sb.append(getBodyIndentation()).append(getInnerIndentation(level)).append(line).append('\n'); return sb.toString(); } /** * Generates body and appends it to the buffer provided as a parameter. * If the body was set as a text, it uses the bodyText field, otherwise * it generates it from the model elements. * (Considers StatementBlock as a root.) * * NOTE: Should be called only when the body was changed! * * @param buf buffer to append to */ protected void generateBody(StringBuffer buf) { StatementBlock body = retrieveBody(); if (!bodyInited) { body = initBody(); } if (bodyText != null && bodyText.length() > 0 && !bodyText.equals("\n")) { // NOI18N formatElementPart(BODY_OPEN_CURLY, buf); buf.append(indentBody(bodyText)); formatElementPart(BODY_CLOSE_CURLY, buf); } else if (body != null) { buf.append(((StatementBlockImpl) body).getSourceText()); } else { formatElementPart(BODY_OPEN_CURLY, buf); formatElementPart(BODY_CLOSE_CURLY, buf); } } /** * Creates diff items for the body. When body text change, it adds * one diff item for the whole body. Otherwise it collects changes * from StatementBlock. * * todo (#pf): StatementBlock partial changes not implmeneted yet. * * @param diffList list of DiffElement, method adds new items to it */ protected void createBodyDiffs(List diffList) { ASTProvider parser = getParser(); if (hardBody == null) {// we have changed bodyText, not statement block if (isChanged(CHANGED_BODY)) { int startOffset; int endOffset; StringBuffer buf = new StringBuffer(); if (bodyText == null) { Token bodyStart = parser.getToken(getBodyAST().getFirstToken() - 1); startOffset = bodyStart.getEndOffset(); buf.append(';'); } else { Token bodyStart = parser.getToken(getBodyAST().getFirstToken()); startOffset = bodyStart.getStartOffset(); formatElementPart(BODY_OPEN_CURLY, buf); buf.append(indentBody(bodyText)); formatElementPart(BODY_CLOSE_CURLY, buf); } Token bodyEnd = parser.getToken(getBodyAST().getLastToken()); endOffset = bodyEnd.getEndOffset(); diffList.add(new DiffElement(startOffset, endOffset, buf.toString())); } } else { // statement block of body has been changed getChildDiff(diffList, parser, getBodyAST(), (MetadataElement) getBody(), CHANGED_BODY); } } private class BodyReference extends WeakReference { BodyReference(StatementBlock body) { super(body); } public Object get() { Object result = super.get(); if (result==null) { body = null; bodyInited = false; } return result; } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.