Source Code Cross Referenced for CodeStructure.java in  » IDE-Netbeans » form » org » netbeans » modules » form » codestructure » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » form » org.netbeans.modules.form.codestructure 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.form.codestructure;
0043:
0044:        import java.util.*;
0045:        import java.lang.reflect.*;
0046:        import org.netbeans.modules.form.FormJavaSource;
0047:
0048:        /**
0049:         * Class representing code structure of one form. Also manages a pool
0050:         * of variables for code expressions, and a undo/redo queue.
0051:         *
0052:         * @author Tomas Pavek
0053:         */
0054:
0055:        public class CodeStructure {
0056:
0057:            public static final CodeExpression[] EMPTY_PARAMS = new CodeExpression[0];
0058:
0059:            private static final int VARIABLE_CREATE = 1;
0060:            private static final int VARIABLE_RENAME = 2;
0061:            private static final int VARIABLE_RELEASE = 3;
0062:            private static final int VARIABLE_ATTACH = 4;
0063:            private static final int VARIABLE_DETACH = 5;
0064:
0065:            private static UsingCodeObject globalUsingObject;
0066:
0067:            private Map<String, Variable> namesToVariables = new HashMap<String, Variable>(
0068:                    50);
0069:            private Map<Object/*?*/, Variable> expressionsToVariables = new HashMap<Object, Variable>(
0070:                    50);
0071:            private Set<String> externalVariables = null;
0072:
0073:            private int defaultVariableType = -1;
0074:
0075:            private boolean undoRedoRecording = false;
0076:            private int undoRedoMark = 0;
0077:            private int oldestMark = 0;
0078:            private int lastUndone = -1;
0079:            private int undoRedoHardLimit = 10000;
0080:            private Map<Integer, CodeStructureChange> undoMap;
0081:            private Map<Integer, CodeStructureChange> redoMap;
0082:
0083:            private FormJavaSource javaSource;
0084:
0085:            // --------
0086:            // constructor
0087:
0088:            public CodeStructure(boolean startUndoRedoRecording) {
0089:                if (startUndoRedoRecording)
0090:                    setUndoRedoRecording(true);
0091:            }
0092:
0093:            public void setFormJavaSource(FormJavaSource formJavaSource) {
0094:                javaSource = formJavaSource;
0095:            }
0096:
0097:            // -------
0098:            // expressions
0099:
0100:            /** Creates a new expression based on a constructor. */
0101:            public CodeExpression createExpression(Constructor ctor,
0102:                    CodeExpression[] params) {
0103:                CodeExpressionOrigin origin = new CodeSupport.ConstructorOrigin(
0104:                        ctor, params);
0105:                return new DefaultCodeExpression(this , origin);
0106:            }
0107:
0108:            /** Creates a new expression based on a method. */
0109:            public CodeExpression createExpression(CodeExpression parent,
0110:                    Method method, CodeExpression[] params) {
0111:                CodeExpressionOrigin origin = new CodeSupport.MethodOrigin(
0112:                        parent, method, params);
0113:                return new DefaultCodeExpression(this , origin);
0114:            }
0115:
0116:            /** Creates a new expression based on a field. */
0117:            public CodeExpression createExpression(CodeExpression parent,
0118:                    Field field) {
0119:                CodeExpressionOrigin origin = new CodeSupport.FieldOrigin(
0120:                        parent, field);
0121:                return new DefaultCodeExpression(this , origin);
0122:            }
0123:
0124:            /** Creates a new expression from based on a value. */
0125:            public CodeExpression createExpression(Class type, Object value,
0126:                    String javaInitStr) {
0127:                return new DefaultCodeExpression(this ,
0128:                        new CodeSupport.ValueOrigin(type, value, javaInitStr));
0129:            }
0130:
0131:            /** Creates a new expression of an arbitrary origin. /*/
0132:            public CodeExpression createExpression(CodeExpressionOrigin origin) {
0133:                return new DefaultCodeExpression(this , origin);
0134:            }
0135:
0136:            /** Creates an expression representing null value. */
0137:            public CodeExpression createNullExpression(Class type) {
0138:                return new DefaultCodeExpression(this ,
0139:                        new CodeSupport.ValueOrigin(type, null, "null")); // NOI18N
0140:            }
0141:
0142:            /** Creates an expression with no origin. The origin must be set
0143:             * explicitly before the expression is used. */
0144:            public CodeExpression createDefaultExpression() {
0145:                return new DefaultCodeExpression(this );
0146:            }
0147:
0148:            /** Prevents an expression from being removed automatically from structure
0149:             * when no more used (by any UsingCodeObject). */
0150:            public void registerExpression(CodeExpression expression) {
0151:                if (globalUsingObject == null)
0152:                    globalUsingObject = new GlobalUsingObject();
0153:
0154:                expression.addUsingObject(globalUsingObject,
0155:                        UsedCodeObject.USING, CodeStructure.class);
0156:            }
0157:
0158:            /** Removes an expression from the structure completely. */
0159:            public static void removeExpression(CodeExpression expression) {
0160:                unregisterUsedCodeObject(expression);
0161:                unregisterUsingCodeObject(expression);
0162:
0163:                expression.getCodeStructure().removeExpressionFromVariable(
0164:                        expression);
0165:            }
0166:
0167:            /** Filters out expressions whose origin uses given or equal meta object.
0168:             * Passed expressions are returned in an array. */
0169:            public static CodeExpression[] filterExpressions(Iterator it,
0170:                    Object originMetaObject) {
0171:                List<CodeExpression> list = new ArrayList<CodeExpression>();
0172:                while (it.hasNext()) {
0173:                    CodeExpression exp = (CodeExpression) it.next();
0174:                    if (originMetaObject
0175:                            .equals(exp.getOrigin().getMetaObject()))
0176:                        list.add(exp);
0177:                }
0178:                return list.toArray(new CodeExpression[list.size()]);
0179:            }
0180:
0181:            // --------
0182:            // statements
0183:
0184:            /** Creates a new method statement. */
0185:            public static CodeStatement createStatement(
0186:                    CodeExpression expression, Method m, CodeExpression[] params) {
0187:                CodeStatement statement = new CodeSupport.MethodStatement(
0188:                        expression, m, params);
0189:                registerUsingCodeObject(statement);
0190:                return statement;
0191:            }
0192:
0193:            /** Creates a new field statement. */
0194:            public static CodeStatement createStatement(
0195:                    CodeExpression expression, Field f, CodeExpression assignExp) {
0196:                CodeStatement statement = new CodeSupport.FieldStatement(
0197:                        expression, f, assignExp);
0198:                registerUsingCodeObject(statement);
0199:                return statement;
0200:            }
0201:
0202:            /** Removes a statement from the structure completely. */
0203:            public static void removeStatement(CodeStatement statement) {
0204:                unregisterUsingCodeObject(statement);
0205:            }
0206:
0207:            /** Removes all statements provided by an Iterator. */
0208:            public static void removeStatements(Iterator it) {
0209:                List list = new ArrayList();
0210:                while (it.hasNext())
0211:                    list.add(it.next());
0212:
0213:                for (int i = 0, n = list.size(); i < n; i++)
0214:                    unregisterUsingCodeObject((CodeStatement) list.get(i));
0215:            }
0216:
0217:            /** Filters out statements using given or equal meta object. Passed
0218:             * statements are returned in an array. */
0219:            public static CodeStatement[] filterStatements(Iterator it,
0220:                    Object metaObject) {
0221:                List<CodeStatement> list = new ArrayList<CodeStatement>();
0222:                while (it.hasNext()) {
0223:                    CodeStatement statement = (CodeStatement) it.next();
0224:                    if (metaObject.equals(statement.getMetaObject()))
0225:                        list.add(statement);
0226:                }
0227:                return list.toArray(new CodeStatement[list.size()]);
0228:            }
0229:
0230:            // --------
0231:            // statements code group
0232:
0233:            /** Creates a default group of statements. */
0234:            public CodeGroup createCodeGroup() {
0235:                return new CodeSupport.DefaultCodeGroup();
0236:            }
0237:
0238:            // --------
0239:            // origins
0240:
0241:            /** Creates an expression origin from a constructor. */
0242:            public static CodeExpressionOrigin createOrigin(Constructor ctor,
0243:                    CodeExpression[] params) {
0244:                return new CodeSupport.ConstructorOrigin(ctor, params);
0245:            }
0246:
0247:            /** Creates an expression origin from a method. */
0248:            public static CodeExpressionOrigin createOrigin(
0249:                    CodeExpression parent, Method m, CodeExpression[] params) {
0250:                return new CodeSupport.MethodOrigin(parent, m, params);
0251:            }
0252:
0253:            /** Creates an expression origin from a field. */
0254:            public static CodeExpressionOrigin createOrigin(
0255:                    CodeExpression parent, Field f) {
0256:                return new CodeSupport.FieldOrigin(parent, f);
0257:            }
0258:
0259:            /** Creates an expression origin from a value (and provided java string). */
0260:            public static CodeExpressionOrigin createOrigin(Class type,
0261:                    Object value, String javaStr) {
0262:                return new CodeSupport.ValueOrigin(type, value, javaStr);
0263:            }
0264:
0265:            // -------
0266:            // getting to expressions and statements dependent on given expression
0267:            // (used as their parent or parameter)
0268:
0269:            /** Returns an iterator of expressions that are defined by given
0270:             * expression. These expressions use the given expression as the parent
0271:             * of origin). */
0272:            public static Iterator getDefinedExpressionsIterator(
0273:                    CodeExpression exp) {
0274:                return exp.getUsingObjectsIterator(UsedCodeObject.DEFINED,
0275:                        CodeExpression.class);
0276:            }
0277:
0278:            /** Returns an iterator of exppressions that use given expression as
0279:             * a parameter in their origin. */
0280:            public static Iterator getUsingExpressionsIterator(
0281:                    CodeExpression exp) {
0282:                return exp.getUsingObjectsIterator(UsedCodeObject.USING,
0283:                        CodeExpression.class);
0284:            }
0285:
0286:            /** Returns an iterator of statements that are defined by given
0287:             * expression. These statements use the given expression as the parent. */
0288:            public static Iterator getDefinedStatementsIterator(
0289:                    CodeExpression exp) {
0290:                return exp.getUsingObjectsIterator(UsedCodeObject.DEFINED,
0291:                        CodeStatement.class);
0292:            }
0293:
0294:            /** Returns an iterator of statements that use given expression as
0295:             * a parameter. */
0296:            public static Iterator getUsingStatementsIterator(CodeExpression exp) {
0297:                return exp.getUsingObjectsIterator(UsedCodeObject.USING,
0298:                        CodeStatement.class);
0299:            }
0300:
0301:            // -------
0302:            // managing references between code objects
0303:
0304:            // Registers usage of expressions used by a statement.
0305:            static void registerUsingCodeObject(CodeStatement statement) {
0306:                CodeExpression parent = statement.getParentExpression();
0307:                if (parent != null)
0308:                    parent.addUsingObject(statement, UsedCodeObject.DEFINED,
0309:                            CodeStatement.class);
0310:
0311:                CodeExpression[] params = statement.getStatementParameters();
0312:                if (params != null)
0313:                    for (int i = 0; i < params.length; i++)
0314:                        params[i].addUsingObject(statement,
0315:                                UsedCodeObject.USING, CodeStatement.class);
0316:            }
0317:
0318:            // Registers usage of expressions used by the origin of an expression.
0319:            static void registerUsingCodeObject(CodeExpression expression) {
0320:                CodeExpressionOrigin origin = expression.getOrigin();
0321:                CodeExpression parent = origin.getParentExpression();
0322:
0323:                if (parent != null)
0324:                    parent.addUsingObject(expression, UsedCodeObject.DEFINED,
0325:                            CodeExpression.class);
0326:
0327:                CodeExpression[] params = origin.getCreationParameters();
0328:                if (params != null)
0329:                    for (int i = 0; i < params.length; i++)
0330:                        params[i].addUsingObject(expression,
0331:                                UsedCodeObject.USING, CodeExpression.class);
0332:            }
0333:
0334:            // Unregisters usage of all objects used by a using object.
0335:            static void unregisterUsingCodeObject(UsingCodeObject usingObject) {
0336:                Iterator it = usingObject.getUsedObjectsIterator();
0337:                while (it.hasNext()) {
0338:                    UsedCodeObject usedObject = (UsedCodeObject) it.next();
0339:                    if (!usedObject.removeUsingObject(usingObject)) {
0340:                        // usedObject is no more used, so it should be removed
0341:                        if (usedObject instanceof  UsingCodeObject)
0342:                            unregisterUsingCodeObject((UsingCodeObject) usedObject);
0343:                    }
0344:                }
0345:            }
0346:
0347:            // Unregisters usage of just one object used by a using object.
0348:            static void unregisterObjectUsage(UsingCodeObject usingObject,
0349:                    UsedCodeObject usedObject) {
0350:                if (!usedObject.removeUsingObject(usingObject)) {
0351:                    // usedObject is no more used, so it should be removed
0352:                    if (usedObject instanceof  UsingCodeObject)
0353:                        unregisterUsingCodeObject((UsingCodeObject) usedObject);
0354:                }
0355:            }
0356:
0357:            // This method just notifies all objects using given used object that
0358:            // the used object is removed from the structure.
0359:            static void unregisterUsedCodeObject(UsedCodeObject usedObject) {
0360:                List usingObjects = new ArrayList();
0361:                Iterator it = usedObject.getUsingObjectsIterator(0, null);
0362:                while (it.hasNext())
0363:                    usingObjects.add(it.next());
0364:
0365:                it = usingObjects.iterator();
0366:                while (it.hasNext()) {
0367:                    UsingCodeObject usingObject = (UsingCodeObject) it.next();
0368:                    if (!usingObject.usedObjectRemoved(usedObject)) {
0369:                        // usingObject cannot exist without removed usedObject
0370:                        if (usingObject instanceof  UsedCodeObject)
0371:                            unregisterUsedCodeObject((UsedCodeObject) usingObject);
0372:                        unregisterUsingCodeObject(usingObject);
0373:                    }
0374:                }
0375:            }
0376:
0377:            private static class GlobalUsingObject implements  UsingCodeObject {
0378:                public void usageRegistered(UsedCodeObject usedObject) {
0379:                }
0380:
0381:                public boolean usedObjectRemoved(UsedCodeObject usedObject) {
0382:                    return true;
0383:                }
0384:
0385:                public UsedCodeObject getDefiningObject() {
0386:                    return null;
0387:                }
0388:
0389:                public Iterator getUsedObjectsIterator() {
0390:                    return null;
0391:                }
0392:            }
0393:
0394:            // -------
0395:            // variables
0396:
0397:            /** Creates a new variable. It is empty - with no expression attached. */
0398:            public CodeVariable createVariable(int type, Class declaredType,
0399:                    String name) {
0400:                if (getVariable(name) != null)
0401:                    return null; // variable already exists, cannot create new one
0402:
0403:                if (type < 0 || name == null)
0404:                    throw new IllegalArgumentException();
0405:
0406:                Variable var = new Variable(type, declaredType, "", name); // NOI18N
0407:                namesToVariables.put(name, var);
0408:
0409:                if (undoRedoRecording)
0410:                    logUndoableChange(new VariableChange(VARIABLE_CREATE, var));
0411:
0412:                return var;
0413:            }
0414:
0415:            /** Renames variable of name oldName to newName. */
0416:            public boolean renameVariable(String oldName, String newName) {
0417:                Variable var = namesToVariables.get(oldName);
0418:                if (var == null || newName == null
0419:                        || newName.equals(var.getName())
0420:                        || namesToVariables.get(newName) != null)
0421:                    return false;
0422:
0423:                namesToVariables.remove(oldName);
0424:                var.name = newName;
0425:                namesToVariables.put(newName, var);
0426:
0427:                if (undoRedoRecording) {
0428:                    VariableChange change = new VariableChange(VARIABLE_RENAME,
0429:                            var);
0430:                    change.oldName = oldName;
0431:                    change.newName = newName;
0432:                    logUndoableChange(change);
0433:                }
0434:
0435:                return true;
0436:            }
0437:
0438:            /** Releases variable of given name. */
0439:            public CodeVariable releaseVariable(String name) {
0440:                Variable var = namesToVariables.remove(name);
0441:                if (var == null)
0442:                    return null; // there is no such variable
0443:
0444:                Map expressionsMap = var.expressionsMap;
0445:                if (expressionsMap == null)
0446:                    return var;
0447:
0448:                Iterator it = expressionsMap.values().iterator();
0449:                while (it.hasNext())
0450:                    expressionsToVariables.remove(it.next());
0451:
0452:                if (undoRedoRecording)
0453:                    logUndoableChange(new VariableChange(VARIABLE_RELEASE, var));
0454:
0455:                return var;
0456:            }
0457:
0458:            /** Checks whether given name is already used by some variable. */
0459:            public boolean isVariableNameReserved(String name) {
0460:                return namesToVariables.get(name) != null
0461:                        || javaSource.containsField(name, true);
0462:            }
0463:
0464:            public CodeVariable createVariableForExpression(
0465:                    CodeExpression expression, int type, String name) {
0466:                CodeVariable var = (expression == null) ? null : expression
0467:                        .getVariable();
0468:                String typeParameters = (var == null) ? "" : var
0469:                        .getDeclaredTypeParameters(); // NOI18N
0470:                return createVariableForExpression(expression, type,
0471:                        typeParameters, name);
0472:            }
0473:
0474:            /** Creates a new variable and attaches given expression to it. If the
0475:             * requested name is already in use, then a free name is found. If null
0476:             * is provided as the name, then expression's short class name is used. */
0477:            public CodeVariable createVariableForExpression(
0478:                    CodeExpression expression, int type, String typeParameters,
0479:                    String name) {
0480:                if (expression == null)
0481:                    throw new IllegalArgumentException();
0482:
0483:                if (getVariable(expression) != null)
0484:                    return null; // variable already exists, cannot create new one
0485:
0486:                if (type < 0)
0487:                    throw new IllegalArgumentException();
0488:
0489:                if (expressionsToVariables.get(expression) != null)
0490:                    removeExpressionFromVariable(expression);
0491:
0492:                name = getFreeVariableName(name, expression.getOrigin()
0493:                        .getType());
0494:
0495:                Variable var = new Variable(type, expression.getOrigin()
0496:                        .getType(), typeParameters, name);
0497:                CodeStatement statement = createVariableAssignment(var,
0498:                        expression);
0499:                var.addCodeExpression(expression, statement);
0500:
0501:                namesToVariables.put(name, var);
0502:                expressionsToVariables.put(expression, var);
0503:
0504:                if (undoRedoRecording) {
0505:                    logUndoableChange(new VariableChange(VARIABLE_CREATE, var));
0506:                    VariableChange change = new VariableChange(VARIABLE_ATTACH,
0507:                            var);
0508:                    change.expression = expression;
0509:                    change.statement = statement;
0510:                    logUndoableChange(change);
0511:                }
0512:
0513:                return var;
0514:            }
0515:
0516:            private String getFreeVariableName(String name, Class type) {
0517:                if (name == null || namesToVariables.get(name) != null) {
0518:                    // variable name not provided or already being used
0519:                    int n = 0;
0520:                    String baseName;
0521:                    if (name != null) { // already used name provided
0522:                        // try to find number suffix
0523:                        int i = name.length();
0524:                        int exp = 1;
0525:                        while (--i >= 0) {
0526:                            char c = name.charAt(i);
0527:                            if (c >= '0' && c <= '9') {
0528:                                n += (c - '0') * exp;
0529:                                exp *= 10;
0530:                            } else
0531:                                break;
0532:                        }
0533:
0534:                        baseName = i >= 0 ? name.substring(0, i + 1) : name;
0535:                    } else { // derive default name from class type, add "1" as suffix
0536:                        String typeName = type.getName();
0537:                        int i = typeName.lastIndexOf('$'); // NOI18N
0538:                        if (i < 0) {
0539:                            i = typeName.lastIndexOf('+'); // NOI18N
0540:                            if (i < 0)
0541:                                i = typeName.lastIndexOf('.'); // NOI18N
0542:                        }
0543:                        baseName = Character
0544:                                .toLowerCase(typeName.charAt(i + 1))
0545:                                + typeName.substring(i + 2);
0546:                    }
0547:
0548:                    javaSource.refresh();
0549:                    do { // find a free name
0550:                        name = baseName + (++n);
0551:                    } while (namesToVariables.get(name) != null
0552:                            || javaSource.containsField(name, false));
0553:                }
0554:                return name;
0555:            }
0556:
0557:            public String getExternalVariableName(Class type,
0558:                    String suggestedName, boolean register) {
0559:                String name = getFreeVariableName(suggestedName, type);
0560:                if (register) {
0561:                    createVariable(CodeVariable.LOCAL, type, name);
0562:                    if (externalVariables == null) {
0563:                        externalVariables = new HashSet<String>();
0564:                    }
0565:                    externalVariables.add(name);
0566:                }
0567:                return name;
0568:            }
0569:
0570:            public void clearExternalVariableNames() {
0571:                if (externalVariables != null) {
0572:                    for (Iterator it = externalVariables.iterator(); it
0573:                            .hasNext();) {
0574:                        releaseVariable((String) it.next());
0575:                    }
0576:                    externalVariables.clear();
0577:                }
0578:            }
0579:
0580:            /** Attaches an expression to a variable. The variable will be used in the
0581:             * code instead of the expression. */
0582:            public void attachExpressionToVariable(CodeExpression expression,
0583:                    CodeVariable variable) {
0584:                if (expression == null)
0585:                    return;
0586:                // [should we check also expression type ??]
0587:
0588:                if (variable.getAssignment(expression) != null)
0589:                    return; // expression already attached
0590:
0591:                // check if this variable can have multiple expressions attached
0592:                int mask = CodeVariable.LOCAL
0593:                        | CodeVariable.EXPLICIT_DECLARATION;
0594:                if ((variable.getType() & mask) == CodeVariable.LOCAL
0595:                        && variable.getAttachedExpressions().size() > 0) { // local variable without a standalone declaration cannot be used
0596:                    // for multiple expressions
0597:                    throw new IllegalStateException(
0598:                            "Standalone local variable declaration required for: " // NOI18N
0599:                                    + variable.getName());
0600:                }
0601:
0602:                Variable prevVar = expressionsToVariables.get(expression);
0603:                if (prevVar != null && prevVar != variable)
0604:                    removeExpressionFromVariable(expression);
0605:
0606:                Variable var = (Variable) variable;
0607:                CodeStatement statement = createVariableAssignment(var,
0608:                        expression);
0609:
0610:                var.addCodeExpression(expression, statement);
0611:                expressionsToVariables.put(expression, var);
0612:
0613:                if (undoRedoRecording) {
0614:                    VariableChange change = new VariableChange(VARIABLE_ATTACH,
0615:                            var);
0616:                    change.expression = expression;
0617:                    change.statement = statement;
0618:                    logUndoableChange(change);
0619:                }
0620:            }
0621:
0622:            /** Releases an expression from using a variable. */
0623:            public void removeExpressionFromVariable(CodeExpression expression) {
0624:                if (expression == null)
0625:                    return;
0626:
0627:                Variable var = expressionsToVariables.remove(expression);
0628:                if (var == null)
0629:                    return;
0630:
0631:                CodeStatement statement = var.removeCodeExpression(expression);
0632:
0633:                if (undoRedoRecording) {
0634:                    VariableChange change = new VariableChange(VARIABLE_DETACH,
0635:                            var);
0636:                    change.expression = expression;
0637:                    change.statement = statement;
0638:                    logUndoableChange(change);
0639:                }
0640:
0641:                if (var.expressionsMap.isEmpty()
0642:                        && (var.getType() & CodeVariable.EXPLICIT_RELEASE) == 0)
0643:                    // release unused variable
0644:                    releaseVariable(var.getName());
0645:            }
0646:
0647:            /** Returns variable of given name. */
0648:            public CodeVariable getVariable(String name) {
0649:                return namesToVariables.get(name);
0650:            }
0651:
0652:            /** Returns variable of an expression. */
0653:            public CodeVariable getVariable(CodeExpression expression) {
0654:                return expressionsToVariables.get(expression);
0655:            }
0656:
0657:            /** Returns an iterator of variables of given criterions. */
0658:            public Iterator getVariablesIterator(int type, int typeMask,
0659:                    Class declaredType) {
0660:                return new VariablesIterator(namesToVariables.values()
0661:                        .iterator(), type, typeMask, declaredType);
0662:            }
0663:
0664:            /** Returns all variables in this CodeStructure. */
0665:            public Collection getAllVariables() {
0666:                return Collections.unmodifiableCollection(namesToVariables
0667:                        .values());
0668:            }
0669:
0670:            // ---------
0671:
0672:            /** WARNING: This method will be removed in full two-way editing
0673:             *           implementation. DO NOT USE! */
0674:            public void setDefaultVariableType(int type) {
0675:                if (type < 0) {
0676:                    defaultVariableType = -1; // global default will be used
0677:                } else {
0678:                    type &= CodeVariable.ALL_MASK;
0679:                    if ((type & CodeVariable.SCOPE_MASK) == CodeVariable.NO_VARIABLE)
0680:                        type |= CodeVariable.FIELD;
0681:                    int fdMask = CodeVariable.EXPLICIT_DECLARATION
0682:                            | CodeVariable.FINAL;
0683:                    if ((type & fdMask) == fdMask)
0684:                        type &= ~CodeVariable.EXPLICIT_DECLARATION;
0685:
0686:                    defaultVariableType = type;
0687:                }
0688:            }
0689:
0690:            int getDefaultVariableType() {
0691:                return defaultVariableType > -1 ? defaultVariableType
0692:                        : CodeVariable.FIELD | CodeVariable.PRIVATE;
0693:            }
0694:
0695:            // ---------
0696:
0697:            protected Map getNamesToVariablesMap() {
0698:                return namesToVariables;
0699:            }
0700:
0701:            protected Map getExpressionsToVariables() {
0702:                return expressionsToVariables;
0703:            }
0704:
0705:            private CodeStatement createVariableAssignment(CodeVariable var,
0706:                    CodeExpression expression) {
0707:                CodeStatement statement = new CodeSupport.AssignVariableStatement(
0708:                        var, expression);
0709:
0710:                // important: assignment statement does not register usage of code
0711:                // expressions (assigned expression, parameters) - so it does not hold
0712:                // the expressions in the structure
0713:
0714:                return statement;
0715:            }
0716:
0717:            // --------
0718:            // undo/redo processing
0719:
0720:            public void setUndoRedoRecording(boolean record) {
0721:                undoRedoRecording = record;
0722:                if (record && undoMap == null) {
0723:                    undoMap = new HashMap<Integer, CodeStructureChange>(500);
0724:                    redoMap = new HashMap<Integer, CodeStructureChange>(100);
0725:                }
0726:            }
0727:
0728:            public boolean isUndoRedoRecording() {
0729:                return undoRedoRecording;
0730:            }
0731:
0732:            void logUndoableChange(CodeStructureChange change) {
0733:                redoMap.clear();
0734:                lastUndone = -1;
0735:
0736:                if (undoMap.size() == 0)
0737:                    oldestMark = undoRedoMark;
0738:
0739:                t("adding undoable change " + undoRedoMark); // NOI18N
0740:
0741:                undoMap.put(new Integer(undoRedoMark++), change);
0742:
0743:                if (undoMap.size() > undoRedoHardLimit)
0744:                    t("undo/redo hard limit reached: " // NOI18N
0745:                            + undoMap.size() + " > " + undoRedoHardLimit); // NOI18N
0746:
0747:                while (undoMap.size() > undoRedoHardLimit) {
0748:                    Object mark = new Integer(oldestMark++);
0749:                    undoMap.remove(mark);
0750:                }
0751:            }
0752:
0753:            public Object markForUndo() {
0754:                redoMap.clear();
0755:
0756:                t("mark for undo: " + undoRedoMark); // NOI18N
0757:
0758:                Object newMark = new Integer(undoRedoMark);
0759:
0760:                return newMark;
0761:            }
0762:
0763:            public void releaseUndoableChanges(Object fromMark, Object toMark) {
0764:                int m1 = ((Integer) fromMark).intValue();
0765:                int m2 = ((Integer) toMark).intValue();
0766:
0767:                t("release marks from " + m1 + " to " + m2); // NOI18N
0768:
0769:                while (m1 < m2) {
0770:                    Object m = new Integer(m1);
0771:                    undoMap.remove(m);
0772:                    redoMap.remove(m);
0773:                    m1++;
0774:                }
0775:            }
0776:
0777:            public boolean undoToMark(Object mark) {
0778:                int lastMark = ((Integer) mark).intValue();
0779:                int currentMark = undoRedoMark;
0780:                if (currentMark <= lastMark)
0781:                    return false; // invalid parameter
0782:
0783:                t("undo to mark " + mark); // NOI18N
0784:
0785:                if (undoMap.get(mark) == null) {
0786:                    t("mark already dropped from the queue"); // NOI18N
0787:                    return false;
0788:                }
0789:
0790:                boolean undoRedoOn = undoRedoRecording;
0791:                undoRedoRecording = false;
0792:
0793:                while (currentMark > lastMark) {
0794:                    Integer key = new Integer(--currentMark);
0795:                    CodeStructureChange change = undoMap.remove(key);
0796:                    if (change != null) {
0797:                        change.undo();
0798:                        redoMap.put(key, change);
0799:                        lastUndone = currentMark;
0800:
0801:                        t("undone: " + key); // NOI18N
0802:                    }
0803:                }
0804:
0805:                if (undoRedoOn)
0806:                    undoRedoRecording = true;
0807:
0808:                return true;
0809:            }
0810:
0811:            public boolean redoToMark(Object mark) {
0812:                if (lastUndone < 0)
0813:                    return false;
0814:                int toMark = ((Integer) mark).intValue();
0815:                if (lastUndone >= toMark || toMark > undoRedoMark)
0816:                    return false; // invalid parameter
0817:
0818:                t("redo to mark " + mark); // NOI18N
0819:
0820:                boolean undoRedoOn = undoRedoRecording;
0821:                undoRedoRecording = false;
0822:
0823:                while (lastUndone < toMark) {
0824:                    Integer key = new Integer(lastUndone++);
0825:                    CodeStructureChange change = redoMap.remove(key);
0826:                    if (change != null) {
0827:                        change.redo();
0828:                        undoMap.put(key, change);
0829:
0830:                        t("redone: " + key); // NOI18N
0831:                    }
0832:                }
0833:
0834:                if (undoRedoOn)
0835:                    undoRedoRecording = true;
0836:
0837:                return true;
0838:            }
0839:
0840:            // --------
0841:            // inner classes
0842:
0843:            final class Variable implements  CodeVariable {
0844:                private int type;
0845:                private Class declaredType;
0846:                private String declaredTypeParameters;
0847:                private String name;
0848:                private Map<CodeExpression, CodeStatement> expressionsMap;
0849:                private CodeStatement declarationStatement;
0850:
0851:                Variable(int type, Class declaredType,
0852:                        String declaredTypeParameters, String name) {
0853:                    if ((type & FINAL) != 0)
0854:                        type &= ~EXPLICIT_DECLARATION;
0855:                    this .type = type;
0856:                    this .declaredType = declaredType;
0857:                    this .declaredTypeParameters = declaredTypeParameters;
0858:                    this .name = name;
0859:                }
0860:
0861:                public int getType() {
0862:                    return (type & DEFAULT_TYPE) != DEFAULT_TYPE ? type
0863:                            : getDefaultVariableType();
0864:                }
0865:
0866:                public String getName() {
0867:                    return name;
0868:                }
0869:
0870:                public Class getDeclaredType() {
0871:                    return declaredType;
0872:                }
0873:
0874:                public String getDeclaredTypeParameters() {
0875:                    return declaredTypeParameters;
0876:                }
0877:
0878:                public Collection getAttachedExpressions() {
0879:                    return expressionsMap != null ? Collections
0880:                            .unmodifiableCollection(expressionsMap.keySet())
0881:                            : Collections.EMPTY_LIST;
0882:                }
0883:
0884:                public CodeStatement getDeclaration() {
0885:                    if (declarationStatement == null)
0886:                        declarationStatement = new CodeSupport.DeclareVariableStatement(
0887:                                this );
0888:                    return declarationStatement;
0889:                }
0890:
0891:                public CodeStatement getAssignment(CodeExpression expression) {
0892:                    return expressionsMap != null ? expressionsMap
0893:                            .get(expression) : null;
0894:                }
0895:
0896:                // -------
0897:
0898:                void addCodeExpression(CodeExpression expression,
0899:                        CodeStatement statement) {
0900:                    if (expressionsMap == null)
0901:                        expressionsMap = new HashMap<CodeExpression, CodeStatement>();
0902:                    expressionsMap.put(expression, statement);
0903:                }
0904:
0905:                CodeStatement removeCodeExpression(CodeExpression expression) {
0906:                    if (expressionsMap != null)
0907:                        return expressionsMap.remove(expression);
0908:                    return null;
0909:                }
0910:            }
0911:
0912:            private static final class VariablesIterator implements  Iterator {
0913:                private int type;
0914:                private int typeMask;
0915:                private Class declaredType;
0916:
0917:                private Iterator subIterator;
0918:
0919:                private CodeVariable currentVar;
0920:
0921:                public VariablesIterator(Iterator subIterator, int type,
0922:                        int typeMask, Class declaredType) {
0923:                    this .type = type;
0924:                    this .typeMask = typeMask;
0925:                    this .declaredType = declaredType;
0926:                    this .subIterator = subIterator;
0927:                }
0928:
0929:                public boolean hasNext() {
0930:                    if (currentVar != null)
0931:                        return true;
0932:
0933:                    while (subIterator.hasNext()) {
0934:                        CodeVariable var = (CodeVariable) subIterator.next();
0935:                        if ((type < 0 || (type & typeMask) == (var.getType() & typeMask))
0936:                                && (declaredType == null || declaredType
0937:                                        .equals(var.getDeclaredType()))) {
0938:                            currentVar = var;
0939:                            return true;
0940:                        }
0941:                    }
0942:
0943:                    return false;
0944:                }
0945:
0946:                public Object next() {
0947:                    if (!hasNext())
0948:                        throw new NoSuchElementException();
0949:
0950:                    CodeVariable var = currentVar;
0951:                    currentVar = null;
0952:                    return var;
0953:                }
0954:
0955:                public void remove() {
0956:                    throw new UnsupportedOperationException();
0957:                }
0958:            }
0959:
0960:            // --------
0961:
0962:            private class VariableChange implements  CodeStructureChange {
0963:                private int changeType;
0964:                private Variable variable;
0965:                private CodeExpression expression;
0966:                private CodeStatement statement;
0967:                private String oldName;
0968:                private String newName;
0969:
0970:                VariableChange(int type, Variable var) {
0971:                    changeType = type;
0972:                    variable = var;
0973:                }
0974:
0975:                public void undo() {
0976:                    switch (changeType) {
0977:                    case VARIABLE_CREATE:
0978:                        namesToVariables.remove(variable.name);
0979:                        break;
0980:                    case VARIABLE_RENAME:
0981:                        namesToVariables.remove(newName);
0982:                        variable.name = oldName;
0983:                        namesToVariables.put(oldName, variable);
0984:                        break;
0985:                    case VARIABLE_RELEASE:
0986:                        Iterator<CodeStatement> it = variable.expressionsMap
0987:                                .values().iterator();
0988:                        while (it.hasNext())
0989:                            expressionsToVariables.put(it.next(), variable);
0990:                        namesToVariables.put(variable.name, variable);
0991:                        break;
0992:                    case VARIABLE_ATTACH:
0993:                        expressionsToVariables.remove(expression);
0994:                        variable.expressionsMap.remove(expression);
0995:                        break;
0996:                    case VARIABLE_DETACH:
0997:                        variable.expressionsMap.put(expression, statement);
0998:                        expressionsToVariables.put(expression, variable);
0999:                        break;
1000:                    }
1001:                }
1002:
1003:                public void redo() {
1004:                    switch (changeType) {
1005:                    case VARIABLE_CREATE:
1006:                        namesToVariables.put(variable.name, variable);
1007:                        break;
1008:                    case VARIABLE_RENAME:
1009:                        namesToVariables.remove(oldName);
1010:                        variable.name = newName;
1011:                        namesToVariables.put(newName, variable);
1012:                        break;
1013:                    case VARIABLE_RELEASE:
1014:                        namesToVariables.remove(variable.name);
1015:                        Iterator it = variable.expressionsMap.values()
1016:                                .iterator();
1017:                        while (it.hasNext())
1018:                            expressionsToVariables.remove(it.next());
1019:                        break;
1020:                    case VARIABLE_ATTACH:
1021:                        variable.expressionsMap.put(expression, statement);
1022:                        expressionsToVariables.put(expression, variable);
1023:                        break;
1024:                    case VARIABLE_DETACH:
1025:                        expressionsToVariables.remove(expression);
1026:                        variable.expressionsMap.remove(expression);
1027:                        break;
1028:                    }
1029:                }
1030:            }
1031:
1032:            // ---------------
1033:
1034:            /** For debugging purposes only. */
1035:            static private int traceCount = 0;
1036:            /** For debugging purposes only. */
1037:            static private final boolean TRACE = false;
1038:
1039:            /** For debugging purposes only. */
1040:            static void t(String str) {
1041:                if (TRACE)
1042:                    if (str != null)
1043:                        System.out.println("CodeStructure " + (++traceCount)
1044:                                + ": " + str); // NOI18N
1045:                    else
1046:                        System.out.println(""); // NOI18N
1047:            }
1048:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.