Source Code Cross Referenced for TypeHierarchy.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » core » hierarchy » 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 Eclipse » jdt » org.eclipse.jdt.internal.core.hierarchy 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.jdt.internal.core.hierarchy;
0011:
0012:        import java.io.IOException;
0013:        import java.io.InputStream;
0014:        import java.io.OutputStream;
0015:        import java.util.ArrayList;
0016:        import java.util.HashMap;
0017:        import java.util.Hashtable;
0018:        import java.util.Iterator;
0019:        import java.util.Map;
0020:
0021:        import org.eclipse.core.runtime.CoreException;
0022:        import org.eclipse.core.runtime.IPath;
0023:        import org.eclipse.core.runtime.IProgressMonitor;
0024:        import org.eclipse.core.runtime.ISafeRunnable;
0025:        import org.eclipse.core.runtime.IStatus;
0026:        import org.eclipse.core.runtime.OperationCanceledException;
0027:        import org.eclipse.core.runtime.SafeRunner;
0028:        import org.eclipse.jdt.core.*;
0029:        import org.eclipse.jdt.core.search.IJavaSearchScope;
0030:        import org.eclipse.jdt.core.search.SearchEngine;
0031:        import org.eclipse.jdt.internal.core.*;
0032:        import org.eclipse.jdt.internal.core.util.Messages;
0033:        import org.eclipse.jdt.internal.core.util.Util;
0034:
0035:        /**
0036:         * @see ITypeHierarchy
0037:         */
0038:        public class TypeHierarchy implements  ITypeHierarchy,
0039:                IElementChangedListener {
0040:
0041:            public static boolean DEBUG = false;
0042:
0043:            static final byte VERSION = 0x0000;
0044:            // SEPARATOR
0045:            static final byte SEPARATOR1 = '\n';
0046:            static final byte SEPARATOR2 = ',';
0047:            static final byte SEPARATOR3 = '>';
0048:            static final byte SEPARATOR4 = '\r';
0049:            // general info
0050:            static final byte COMPUTE_SUBTYPES = 0x0001;
0051:
0052:            // type info
0053:            static final byte CLASS = 0x0000;
0054:            static final byte INTERFACE = 0x0001;
0055:            static final byte COMPUTED_FOR = 0x0002;
0056:            static final byte ROOT = 0x0004;
0057:
0058:            // cst
0059:            static final byte[] NO_FLAGS = new byte[] {};
0060:            static final int SIZE = 10;
0061:
0062:            /**
0063:             * The Java Project in which the hierarchy is being built - this
0064:             * provides the context for determining a classpath and namelookup rules.
0065:             * Possibly null.
0066:             */
0067:            protected IJavaProject project;
0068:            /**
0069:             * The type the hierarchy was specifically computed for,
0070:             * possibly null.
0071:             */
0072:            protected IType focusType;
0073:
0074:            /*
0075:             * The working copies that take precedence over original compilation units
0076:             */
0077:            protected ICompilationUnit[] workingCopies;
0078:
0079:            protected Map classToSuperclass;
0080:            protected Map typeToSuperInterfaces;
0081:            protected Map typeToSubtypes;
0082:            protected Map typeFlags;
0083:            protected TypeVector rootClasses = new TypeVector();
0084:            protected ArrayList interfaces = new ArrayList(10);
0085:            public ArrayList missingTypes = new ArrayList(4);
0086:
0087:            protected static final IType[] NO_TYPE = new IType[0];
0088:
0089:            /**
0090:             * The progress monitor to report work completed too.
0091:             */
0092:            protected IProgressMonitor progressMonitor = null;
0093:
0094:            /**
0095:             * Change listeners - null if no one is listening.
0096:             */
0097:            protected ArrayList changeListeners = null;
0098:
0099:            /*
0100:             * A map from Openables to ArrayLists of ITypes
0101:             */
0102:            public Map files = null;
0103:
0104:            /**
0105:             * A region describing the packages considered by this
0106:             * hierarchy. Null if not activated.
0107:             */
0108:            protected Region packageRegion = null;
0109:
0110:            /**
0111:             * A region describing the projects considered by this
0112:             * hierarchy. Null if not activated.
0113:             */
0114:            protected Region projectRegion = null;
0115:
0116:            /**
0117:             * Whether this hierarchy should contains subtypes.
0118:             */
0119:            protected boolean computeSubtypes;
0120:
0121:            /**
0122:             * The scope this hierarchy should restrain itsef in.
0123:             */
0124:            IJavaSearchScope scope;
0125:
0126:            /*
0127:             * Whether this hierarchy needs refresh
0128:             */
0129:            public boolean needsRefresh = true;
0130:
0131:            /*
0132:             * Collects changes to types
0133:             */
0134:            protected ChangeCollector changeCollector;
0135:
0136:            /**
0137:             * Creates an empty TypeHierarchy
0138:             */
0139:            public TypeHierarchy() {
0140:                // Creates an empty TypeHierarchy
0141:            }
0142:
0143:            /**
0144:             * Creates a TypeHierarchy on the given type.
0145:             */
0146:            public TypeHierarchy(IType type, ICompilationUnit[] workingCopies,
0147:                    IJavaProject project, boolean computeSubtypes) {
0148:                this (type, workingCopies, SearchEngine
0149:                        .createJavaSearchScope(new IJavaElement[] { project }),
0150:                        computeSubtypes);
0151:                this .project = project;
0152:            }
0153:
0154:            /**
0155:             * Creates a TypeHierarchy on the given type.
0156:             */
0157:            public TypeHierarchy(IType type, ICompilationUnit[] workingCopies,
0158:                    IJavaSearchScope scope, boolean computeSubtypes) {
0159:                this .focusType = type == null ? null
0160:                        : (IType) ((JavaElement) type).unresolved(); // unsure the focus type is unresolved (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=92357)
0161:                this .workingCopies = workingCopies;
0162:                this .computeSubtypes = computeSubtypes;
0163:                this .scope = scope;
0164:            }
0165:
0166:            /**
0167:             * Initializes the file, package and project regions
0168:             */
0169:            protected void initializeRegions() {
0170:
0171:                IType[] allTypes = getAllTypes();
0172:                for (int i = 0; i < allTypes.length; i++) {
0173:                    IType type = allTypes[i];
0174:                    Openable o = (Openable) ((JavaElement) type)
0175:                            .getOpenableParent();
0176:                    if (o != null) {
0177:                        ArrayList types = (ArrayList) this .files.get(o);
0178:                        if (types == null) {
0179:                            types = new ArrayList();
0180:                            this .files.put(o, types);
0181:                        }
0182:                        types.add(type);
0183:                    }
0184:                    IPackageFragment pkg = type.getPackageFragment();
0185:                    this .packageRegion.add(pkg);
0186:                    IJavaProject declaringProject = type.getJavaProject();
0187:                    if (declaringProject != null) {
0188:                        this .projectRegion.add(declaringProject);
0189:                    }
0190:                    checkCanceled();
0191:                }
0192:            }
0193:
0194:            /**
0195:             * Adds all of the elements in the collection to the list if the
0196:             * element is not already in the list.
0197:             */
0198:            private void addAllCheckingDuplicates(ArrayList list,
0199:                    IType[] collection) {
0200:                for (int i = 0; i < collection.length; i++) {
0201:                    IType element = collection[i];
0202:                    if (!list.contains(element)) {
0203:                        list.add(element);
0204:                    }
0205:                }
0206:            }
0207:
0208:            /**
0209:             * Adds the type to the collection of interfaces.
0210:             */
0211:            protected void addInterface(IType type) {
0212:                this .interfaces.add(type);
0213:            }
0214:
0215:            /**
0216:             * Adds the type to the collection of root classes
0217:             * if the classes is not already present in the collection.
0218:             */
0219:            protected void addRootClass(IType type) {
0220:                if (this .rootClasses.contains(type))
0221:                    return;
0222:                this .rootClasses.add(type);
0223:            }
0224:
0225:            /**
0226:             * Adds the given subtype to the type.
0227:             */
0228:            protected void addSubtype(IType type, IType subtype) {
0229:                TypeVector subtypes = (TypeVector) this .typeToSubtypes
0230:                        .get(type);
0231:                if (subtypes == null) {
0232:                    subtypes = new TypeVector();
0233:                    this .typeToSubtypes.put(type, subtypes);
0234:                }
0235:                if (!subtypes.contains(subtype)) {
0236:                    subtypes.add(subtype);
0237:                }
0238:            }
0239:
0240:            /**
0241:             * @see ITypeHierarchy
0242:             */
0243:            public synchronized void addTypeHierarchyChangedListener(
0244:                    ITypeHierarchyChangedListener listener) {
0245:                ArrayList listeners = this .changeListeners;
0246:                if (listeners == null) {
0247:                    this .changeListeners = listeners = new ArrayList();
0248:                }
0249:
0250:                // register with JavaCore to get Java element delta on first listener added
0251:                if (listeners.size() == 0) {
0252:                    JavaCore.addElementChangedListener(this );
0253:                }
0254:
0255:                // add listener only if it is not already present
0256:                if (listeners.indexOf(listener) == -1) {
0257:                    listeners.add(listener);
0258:                }
0259:            }
0260:
0261:            private static Integer bytesToFlags(byte[] bytes) {
0262:                if (bytes != null && bytes.length > 0) {
0263:                    return new Integer(new String(bytes));
0264:                } else {
0265:                    return null;
0266:                }
0267:            }
0268:
0269:            /**
0270:             * cacheFlags.
0271:             */
0272:            public void cacheFlags(IType type, int flags) {
0273:                this .typeFlags.put(type, new Integer(flags));
0274:            }
0275:
0276:            /**
0277:             * Caches the handle of the superclass for the specified type.
0278:             * As a side effect cache this type as a subtype of the superclass.
0279:             */
0280:            protected void cacheSuperclass(IType type, IType super class) {
0281:                if (super class != null) {
0282:                    this .classToSuperclass.put(type, super class);
0283:                    addSubtype(super class, type);
0284:                }
0285:            }
0286:
0287:            /**
0288:             * Caches all of the superinterfaces that are specified for the
0289:             * type.
0290:             */
0291:            protected void cacheSuperInterfaces(IType type,
0292:                    IType[] super interfaces) {
0293:                this .typeToSuperInterfaces.put(type, super interfaces);
0294:                for (int i = 0; i < super interfaces.length; i++) {
0295:                    IType super interface = super interfaces[i];
0296:                    if (super interface != null) {
0297:                        addSubtype(super interface, type);
0298:                    }
0299:                }
0300:            }
0301:
0302:            /**
0303:             * Checks with the progress monitor to see whether the creation of the type hierarchy
0304:             * should be canceled. Should be regularly called
0305:             * so that the user can cancel.
0306:             *
0307:             * @exception OperationCanceledException if cancelling the operation has been requested
0308:             * @see IProgressMonitor#isCanceled
0309:             */
0310:            protected void checkCanceled() {
0311:                if (this .progressMonitor != null
0312:                        && this .progressMonitor.isCanceled()) {
0313:                    throw new OperationCanceledException();
0314:                }
0315:            }
0316:
0317:            /**
0318:             * Compute this type hierarchy.
0319:             */
0320:            protected void compute() throws JavaModelException, CoreException {
0321:                if (this .focusType != null) {
0322:                    HierarchyBuilder builder = new IndexBasedHierarchyBuilder(
0323:                            this , this .scope);
0324:                    builder.build(this .computeSubtypes);
0325:                } // else a RegionBasedTypeHierarchy should be used
0326:            }
0327:
0328:            /**
0329:             * @see ITypeHierarchy
0330:             */
0331:            public boolean contains(IType type) {
0332:                // classes
0333:                if (this .classToSuperclass.get(type) != null) {
0334:                    return true;
0335:                }
0336:
0337:                // root classes
0338:                if (this .rootClasses.contains(type))
0339:                    return true;
0340:
0341:                // interfaces
0342:                if (this .interfaces.contains(type))
0343:                    return true;
0344:
0345:                return false;
0346:            }
0347:
0348:            /**
0349:             * Determines if the change effects this hierarchy, and fires
0350:             * change notification if required.
0351:             */
0352:            public void elementChanged(ElementChangedEvent event) {
0353:                // type hierarchy change has already been fired
0354:                if (this .needsRefresh)
0355:                    return;
0356:
0357:                if (isAffected(event.getDelta())) {
0358:                    this .needsRefresh = true;
0359:                    fireChange();
0360:                }
0361:            }
0362:
0363:            /**
0364:             * @see ITypeHierarchy
0365:             */
0366:            public boolean exists() {
0367:                if (!this .needsRefresh)
0368:                    return true;
0369:
0370:                return (this .focusType == null || this .focusType.exists())
0371:                        && this .javaProject().exists();
0372:            }
0373:
0374:            /**
0375:             * Notifies listeners that this hierarchy has changed and needs
0376:             * refreshing. Note that listeners can be removed as we iterate
0377:             * through the list.
0378:             */
0379:            public void fireChange() {
0380:                ArrayList listeners = this .changeListeners;
0381:                if (listeners == null) {
0382:                    return;
0383:                }
0384:                if (DEBUG) {
0385:                    System.out
0386:                            .println("FIRING hierarchy change [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
0387:                    if (this .focusType != null) {
0388:                        System.out
0389:                                .println("    for hierarchy focused on " + ((JavaElement) this .focusType).toStringWithAncestors()); //$NON-NLS-1$
0390:                    }
0391:                }
0392:                // clone so that a listener cannot have a side-effect on this list when being notified
0393:                listeners = (ArrayList) listeners.clone();
0394:                for (int i = 0; i < listeners.size(); i++) {
0395:                    final ITypeHierarchyChangedListener listener = (ITypeHierarchyChangedListener) listeners
0396:                            .get(i);
0397:                    SafeRunner.run(new ISafeRunnable() {
0398:                        public void handleException(Throwable exception) {
0399:                            Util
0400:                                    .log(exception,
0401:                                            "Exception occurred in listener of Type hierarchy change notification"); //$NON-NLS-1$
0402:                        }
0403:
0404:                        public void run() throws Exception {
0405:                            listener.typeHierarchyChanged(TypeHierarchy.this );
0406:                        }
0407:                    });
0408:                }
0409:            }
0410:
0411:            private static byte[] flagsToBytes(Integer flags) {
0412:                if (flags != null) {
0413:                    return flags.toString().getBytes();
0414:                } else {
0415:                    return NO_FLAGS;
0416:                }
0417:            }
0418:
0419:            /**
0420:             * @see ITypeHierarchy
0421:             */
0422:            public IType[] getAllClasses() {
0423:
0424:                TypeVector classes = this .rootClasses.copy();
0425:                for (Iterator iter = this .classToSuperclass.keySet().iterator(); iter
0426:                        .hasNext();) {
0427:                    classes.add((IType) iter.next());
0428:                }
0429:                return classes.elements();
0430:            }
0431:
0432:            /**
0433:             * @see ITypeHierarchy
0434:             */
0435:            public IType[] getAllInterfaces() {
0436:                IType[] collection = new IType[this .interfaces.size()];
0437:                this .interfaces.toArray(collection);
0438:                return collection;
0439:            }
0440:
0441:            /**
0442:             * @see ITypeHierarchy
0443:             */
0444:            public IType[] getAllSubtypes(IType type) {
0445:                return getAllSubtypesForType(type);
0446:            }
0447:
0448:            /**
0449:             * @see #getAllSubtypes(IType)
0450:             */
0451:            private IType[] getAllSubtypesForType(IType type) {
0452:                ArrayList subTypes = new ArrayList();
0453:                getAllSubtypesForType0(type, subTypes);
0454:                IType[] subClasses = new IType[subTypes.size()];
0455:                subTypes.toArray(subClasses);
0456:                return subClasses;
0457:            }
0458:
0459:            /**
0460:             */
0461:            private void getAllSubtypesForType0(IType type, ArrayList subs) {
0462:                IType[] subTypes = getSubtypesForType(type);
0463:                if (subTypes.length != 0) {
0464:                    for (int i = 0; i < subTypes.length; i++) {
0465:                        IType subType = subTypes[i];
0466:                        subs.add(subType);
0467:                        getAllSubtypesForType0(subType, subs);
0468:                    }
0469:                }
0470:            }
0471:
0472:            /**
0473:             * @see ITypeHierarchy
0474:             */
0475:            public IType[] getAllSuperclasses(IType type) {
0476:                IType super class = getSuperclass(type);
0477:                TypeVector super s = new TypeVector();
0478:                while (super class != null) {
0479:                    super s.add(super class);
0480:                    super class = getSuperclass(super class);
0481:                }
0482:                return super s.elements();
0483:            }
0484:
0485:            /**
0486:             * @see ITypeHierarchy
0487:             */
0488:            public IType[] getAllSuperInterfaces(IType type) {
0489:                ArrayList super s = new ArrayList();
0490:                if (this .typeToSuperInterfaces.get(type) == null) {
0491:                    return NO_TYPE;
0492:                }
0493:                getAllSuperInterfaces0(type, super s);
0494:                IType[] super interfaces = new IType[super s.size()];
0495:                super s.toArray(super interfaces);
0496:                return super interfaces;
0497:            }
0498:
0499:            private void getAllSuperInterfaces0(IType type, ArrayList super s) {
0500:                IType[] super interfaces = (IType[]) this .typeToSuperInterfaces
0501:                        .get(type);
0502:                if (super interfaces != null && super interfaces.length != 0) {
0503:                    addAllCheckingDuplicates(super s, super interfaces);
0504:                    for (int i = 0; i < super interfaces.length; i++) {
0505:                        getAllSuperInterfaces0(super interfaces[i], super s);
0506:                    }
0507:                }
0508:                IType super class = (IType) this .classToSuperclass.get(type);
0509:                if (super class != null) {
0510:                    getAllSuperInterfaces0(super class, super s);
0511:                }
0512:            }
0513:
0514:            /**
0515:             * @see ITypeHierarchy
0516:             */
0517:            public IType[] getAllSupertypes(IType type) {
0518:                ArrayList super s = new ArrayList();
0519:                if (this .typeToSuperInterfaces.get(type) == null) {
0520:                    return NO_TYPE;
0521:                }
0522:                getAllSupertypes0(type, super s);
0523:                IType[] super types = new IType[super s.size()];
0524:                super s.toArray(super types);
0525:                return super types;
0526:            }
0527:
0528:            private void getAllSupertypes0(IType type, ArrayList super s) {
0529:                IType[] super interfaces = (IType[]) this .typeToSuperInterfaces
0530:                        .get(type);
0531:                if (super interfaces != null && super interfaces.length != 0) {
0532:                    addAllCheckingDuplicates(super s, super interfaces);
0533:                    for (int i = 0; i < super interfaces.length; i++) {
0534:                        getAllSuperInterfaces0(super interfaces[i], super s);
0535:                    }
0536:                }
0537:                IType super class = (IType) this .classToSuperclass.get(type);
0538:                if (super class != null) {
0539:                    super s.add(super class);
0540:                    getAllSupertypes0(super class, super s);
0541:                }
0542:            }
0543:
0544:            /**
0545:             * @see ITypeHierarchy
0546:             */
0547:            public IType[] getAllTypes() {
0548:                IType[] classes = getAllClasses();
0549:                int classesLength = classes.length;
0550:                IType[] allInterfaces = getAllInterfaces();
0551:                int interfacesLength = allInterfaces.length;
0552:                IType[] all = new IType[classesLength + interfacesLength];
0553:                System.arraycopy(classes, 0, all, 0, classesLength);
0554:                System.arraycopy(allInterfaces, 0, all, classesLength,
0555:                        interfacesLength);
0556:                return all;
0557:            }
0558:
0559:            /**
0560:             * @see ITypeHierarchy#getCachedFlags(IType)
0561:             */
0562:            public int getCachedFlags(IType type) {
0563:                Integer flagObject = (Integer) this .typeFlags.get(type);
0564:                if (flagObject != null) {
0565:                    return flagObject.intValue();
0566:                }
0567:                return -1;
0568:            }
0569:
0570:            /**
0571:             * @see ITypeHierarchy
0572:             */
0573:            public IType[] getExtendingInterfaces(IType type) {
0574:                if (!this .isInterface(type))
0575:                    return NO_TYPE;
0576:                return getExtendingInterfaces0(type);
0577:            }
0578:
0579:            /**
0580:             * Assumes that the type is an interface
0581:             * @see #getExtendingInterfaces
0582:             */
0583:            private IType[] getExtendingInterfaces0(IType extendedInterface) {
0584:                Iterator iter = this .typeToSuperInterfaces.entrySet()
0585:                        .iterator();
0586:                ArrayList interfaceList = new ArrayList();
0587:                while (iter.hasNext()) {
0588:                    Map.Entry entry = (Map.Entry) iter.next();
0589:                    IType type = (IType) entry.getKey();
0590:                    if (!this .isInterface(type)) {
0591:                        continue;
0592:                    }
0593:                    IType[] super Interfaces = (IType[]) entry.getValue();
0594:                    if (super Interfaces != null) {
0595:                        for (int i = 0; i < super Interfaces.length; i++) {
0596:                            IType super Interface = super Interfaces[i];
0597:                            if (super Interface.equals(extendedInterface)) {
0598:                                interfaceList.add(type);
0599:                            }
0600:                        }
0601:                    }
0602:                }
0603:                IType[] extendingInterfaces = new IType[interfaceList.size()];
0604:                interfaceList.toArray(extendingInterfaces);
0605:                return extendingInterfaces;
0606:            }
0607:
0608:            /**
0609:             * @see ITypeHierarchy
0610:             */
0611:            public IType[] getImplementingClasses(IType type) {
0612:                if (!this .isInterface(type)) {
0613:                    return NO_TYPE;
0614:                }
0615:                return getImplementingClasses0(type);
0616:            }
0617:
0618:            /**
0619:             * Assumes that the type is an interface
0620:             * @see #getImplementingClasses
0621:             */
0622:            private IType[] getImplementingClasses0(IType interfce) {
0623:
0624:                Iterator iter = this .typeToSuperInterfaces.entrySet()
0625:                        .iterator();
0626:                ArrayList iMenters = new ArrayList();
0627:                while (iter.hasNext()) {
0628:                    Map.Entry entry = (Map.Entry) iter.next();
0629:                    IType type = (IType) entry.getKey();
0630:                    if (this .isInterface(type)) {
0631:                        continue;
0632:                    }
0633:                    IType[] types = (IType[]) entry.getValue();
0634:                    for (int i = 0; i < types.length; i++) {
0635:                        IType iFace = types[i];
0636:                        if (iFace.equals(interfce)) {
0637:                            iMenters.add(type);
0638:                        }
0639:                    }
0640:                }
0641:                IType[] implementers = new IType[iMenters.size()];
0642:                iMenters.toArray(implementers);
0643:                return implementers;
0644:            }
0645:
0646:            /**
0647:             * @see ITypeHierarchy
0648:             */
0649:            public IType[] getRootClasses() {
0650:                return this .rootClasses.elements();
0651:            }
0652:
0653:            /**
0654:             * @see ITypeHierarchy
0655:             */
0656:            public IType[] getRootInterfaces() {
0657:                IType[] allInterfaces = getAllInterfaces();
0658:                IType[] roots = new IType[allInterfaces.length];
0659:                int rootNumber = 0;
0660:                for (int i = 0; i < allInterfaces.length; i++) {
0661:                    IType[] super Interfaces = getSuperInterfaces(allInterfaces[i]);
0662:                    if (super Interfaces == null || super Interfaces.length == 0) {
0663:                        roots[rootNumber++] = allInterfaces[i];
0664:                    }
0665:                }
0666:                IType[] result = new IType[rootNumber];
0667:                if (result.length > 0) {
0668:                    System.arraycopy(roots, 0, result, 0, rootNumber);
0669:                }
0670:                return result;
0671:            }
0672:
0673:            /**
0674:             * @see ITypeHierarchy
0675:             */
0676:            public IType[] getSubclasses(IType type) {
0677:                if (this .isInterface(type)) {
0678:                    return NO_TYPE;
0679:                }
0680:                TypeVector vector = (TypeVector) this .typeToSubtypes.get(type);
0681:                if (vector == null)
0682:                    return NO_TYPE;
0683:                else
0684:                    return vector.elements();
0685:            }
0686:
0687:            /**
0688:             * @see ITypeHierarchy
0689:             */
0690:            public IType[] getSubtypes(IType type) {
0691:                return getSubtypesForType(type);
0692:            }
0693:
0694:            /**
0695:             * Returns an array of subtypes for the given type - will never return null.
0696:             */
0697:            private IType[] getSubtypesForType(IType type) {
0698:                TypeVector vector = (TypeVector) this .typeToSubtypes.get(type);
0699:                if (vector == null)
0700:                    return NO_TYPE;
0701:                else
0702:                    return vector.elements();
0703:            }
0704:
0705:            /**
0706:             * @see ITypeHierarchy
0707:             */
0708:            public IType getSuperclass(IType type) {
0709:                if (this .isInterface(type)) {
0710:                    return null;
0711:                }
0712:                return (IType) this .classToSuperclass.get(type);
0713:            }
0714:
0715:            /**
0716:             * @see ITypeHierarchy
0717:             */
0718:            public IType[] getSuperInterfaces(IType type) {
0719:                IType[] types = (IType[]) this .typeToSuperInterfaces.get(type);
0720:                if (types == null) {
0721:                    return NO_TYPE;
0722:                }
0723:                return types;
0724:            }
0725:
0726:            /**
0727:             * @see ITypeHierarchy
0728:             */
0729:            public IType[] getSupertypes(IType type) {
0730:                IType super class = getSuperclass(type);
0731:                if (super class == null) {
0732:                    return getSuperInterfaces(type);
0733:                } else {
0734:                    TypeVector super Types = new TypeVector(
0735:                            getSuperInterfaces(type));
0736:                    super Types.add(super class);
0737:                    return super Types.elements();
0738:                }
0739:            }
0740:
0741:            /**
0742:             * @see ITypeHierarchy
0743:             */
0744:            public IType getType() {
0745:                return this .focusType;
0746:            }
0747:
0748:            /**
0749:             * Adds the new elements to a new array that contains all of the elements of the old array.
0750:             * Returns the new array.
0751:             */
0752:            protected IType[] growAndAddToArray(IType[] array, IType[] additions) {
0753:                if (array == null || array.length == 0) {
0754:                    return additions;
0755:                }
0756:                IType[] old = array;
0757:                array = new IType[old.length + additions.length];
0758:                System.arraycopy(old, 0, array, 0, old.length);
0759:                System.arraycopy(additions, 0, array, old.length,
0760:                        additions.length);
0761:                return array;
0762:            }
0763:
0764:            /**
0765:             * Adds the new element to a new array that contains all of the elements of the old array.
0766:             * Returns the new array.
0767:             */
0768:            protected IType[] growAndAddToArray(IType[] array, IType addition) {
0769:                if (array == null || array.length == 0) {
0770:                    return new IType[] { addition };
0771:                }
0772:                IType[] old = array;
0773:                array = new IType[old.length + 1];
0774:                System.arraycopy(old, 0, array, 0, old.length);
0775:                array[old.length] = addition;
0776:                return array;
0777:            }
0778:
0779:            /*
0780:             * Whether fine-grained deltas where collected and affects this hierarchy.
0781:             */
0782:            public boolean hasFineGrainChanges() {
0783:                ChangeCollector collector = this .changeCollector;
0784:                return collector != null && collector.needsRefresh();
0785:            }
0786:
0787:            /**
0788:             * Returns whether one of the subtypes in this hierarchy has the given simple name
0789:             * or this type has the given simple name.
0790:             */
0791:            private boolean hasSubtypeNamed(String simpleName) {
0792:                if (this .focusType != null
0793:                        && this .focusType.getElementName().equals(simpleName)) {
0794:                    return true;
0795:                }
0796:                IType[] types = this .focusType == null ? getAllTypes()
0797:                        : getAllSubtypes(this .focusType);
0798:                for (int i = 0, length = types.length; i < length; i++) {
0799:                    if (types[i].getElementName().equals(simpleName)) {
0800:                        return true;
0801:                    }
0802:                }
0803:                return false;
0804:            }
0805:
0806:            /**
0807:             * Returns whether one of the types in this hierarchy has the given simple name.
0808:             */
0809:            private boolean hasTypeNamed(String simpleName) {
0810:                IType[] types = this .getAllTypes();
0811:                for (int i = 0, length = types.length; i < length; i++) {
0812:                    if (types[i].getElementName().equals(simpleName)) {
0813:                        return true;
0814:                    }
0815:                }
0816:                return false;
0817:            }
0818:
0819:            /**
0820:             * Returns whether the simple name of the given type or one of its supertypes is 
0821:             * the simple name of one of the types in this hierarchy.
0822:             */
0823:            boolean includesTypeOrSupertype(IType type) {
0824:                try {
0825:                    // check type
0826:                    if (hasTypeNamed(type.getElementName()))
0827:                        return true;
0828:
0829:                    // check superclass
0830:                    String super className = type.getSuperclassName();
0831:                    if (super className != null) {
0832:                        int lastSeparator = super className.lastIndexOf('.');
0833:                        String simpleName = super className
0834:                                .substring(lastSeparator + 1);
0835:                        if (hasTypeNamed(simpleName))
0836:                            return true;
0837:                    }
0838:
0839:                    // check superinterfaces
0840:                    String[] super interfaceNames = type
0841:                            .getSuperInterfaceNames();
0842:                    if (super interfaceNames != null) {
0843:                        for (int i = 0, length = super interfaceNames.length; i < length; i++) {
0844:                            String super interfaceName = super interfaceNames[i];
0845:                            int lastSeparator = super interfaceName
0846:                                    .lastIndexOf('.');
0847:                            String simpleName = super interfaceName
0848:                                    .substring(lastSeparator + 1);
0849:                            if (hasTypeNamed(simpleName))
0850:                                return true;
0851:                        }
0852:                    }
0853:                } catch (JavaModelException e) {
0854:                    // ignore
0855:                }
0856:                return false;
0857:            }
0858:
0859:            /**
0860:             * Initializes this hierarchy's internal tables with the given size.
0861:             */
0862:            protected void initialize(int size) {
0863:                if (size < 10) {
0864:                    size = 10;
0865:                }
0866:                int smallSize = (size / 2);
0867:                this .classToSuperclass = new HashMap(size);
0868:                this .interfaces = new ArrayList(smallSize);
0869:                this .missingTypes = new ArrayList(smallSize);
0870:                this .rootClasses = new TypeVector();
0871:                this .typeToSubtypes = new HashMap(smallSize);
0872:                this .typeToSuperInterfaces = new HashMap(smallSize);
0873:                this .typeFlags = new HashMap(smallSize);
0874:
0875:                this .projectRegion = new Region();
0876:                this .packageRegion = new Region();
0877:                this .files = new HashMap(5);
0878:            }
0879:
0880:            /**
0881:             * Returns true if the given delta could change this type hierarchy
0882:             */
0883:            public synchronized boolean isAffected(IJavaElementDelta delta) {
0884:                IJavaElement element = delta.getElement();
0885:                switch (element.getElementType()) {
0886:                case IJavaElement.JAVA_MODEL:
0887:                    return isAffectedByJavaModel(delta, element);
0888:                case IJavaElement.JAVA_PROJECT:
0889:                    return isAffectedByJavaProject(delta, element);
0890:                case IJavaElement.PACKAGE_FRAGMENT_ROOT:
0891:                    return isAffectedByPackageFragmentRoot(delta, element);
0892:                case IJavaElement.PACKAGE_FRAGMENT:
0893:                    return isAffectedByPackageFragment(delta,
0894:                            (PackageFragment) element);
0895:                case IJavaElement.CLASS_FILE:
0896:                case IJavaElement.COMPILATION_UNIT:
0897:                    return isAffectedByOpenable(delta, element);
0898:                }
0899:                return false;
0900:            }
0901:
0902:            /**
0903:             * Returns true if any of the children of a project, package
0904:             * fragment root, or package fragment have changed in a way that
0905:             * effects this type hierarchy.
0906:             */
0907:            private boolean isAffectedByChildren(IJavaElementDelta delta) {
0908:                if ((delta.getFlags() & IJavaElementDelta.F_CHILDREN) > 0) {
0909:                    IJavaElementDelta[] children = delta.getAffectedChildren();
0910:                    for (int i = 0; i < children.length; i++) {
0911:                        if (isAffected(children[i])) {
0912:                            return true;
0913:                        }
0914:                    }
0915:                }
0916:                return false;
0917:            }
0918:
0919:            /**
0920:             * Returns true if the given java model delta could affect this type hierarchy
0921:             */
0922:            private boolean isAffectedByJavaModel(IJavaElementDelta delta,
0923:                    IJavaElement element) {
0924:                switch (delta.getKind()) {
0925:                case IJavaElementDelta.ADDED:
0926:                case IJavaElementDelta.REMOVED:
0927:                    return element.equals(this .javaProject().getJavaModel());
0928:                case IJavaElementDelta.CHANGED:
0929:                    return isAffectedByChildren(delta);
0930:                }
0931:                return false;
0932:            }
0933:
0934:            /**
0935:             * Returns true if the given java project delta could affect this type hierarchy
0936:             */
0937:            private boolean isAffectedByJavaProject(IJavaElementDelta delta,
0938:                    IJavaElement element) {
0939:                int kind = delta.getKind();
0940:                int flags = delta.getFlags();
0941:                if ((flags & IJavaElementDelta.F_OPENED) != 0) {
0942:                    kind = IJavaElementDelta.ADDED; // affected in the same way
0943:                }
0944:                if ((flags & IJavaElementDelta.F_CLOSED) != 0) {
0945:                    kind = IJavaElementDelta.REMOVED; // affected in the same way
0946:                }
0947:                switch (kind) {
0948:                case IJavaElementDelta.ADDED:
0949:                    try {
0950:                        // if the added project is on the classpath, then the hierarchy has changed
0951:                        IClasspathEntry[] classpath = ((JavaProject) this 
0952:                                .javaProject()).getExpandedClasspath();
0953:                        for (int i = 0; i < classpath.length; i++) {
0954:                            if (classpath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT
0955:                                    && classpath[i].getPath().equals(
0956:                                            element.getPath())) {
0957:                                return true;
0958:                            }
0959:                        }
0960:                        if (this .focusType != null) {
0961:                            // if the hierarchy's project is on the added project classpath, then the hierarchy has changed
0962:                            classpath = ((JavaProject) element)
0963:                                    .getExpandedClasspath();
0964:                            IPath hierarchyProject = javaProject().getPath();
0965:                            for (int i = 0; i < classpath.length; i++) {
0966:                                if (classpath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT
0967:                                        && classpath[i].getPath().equals(
0968:                                                hierarchyProject)) {
0969:                                    return true;
0970:                                }
0971:                            }
0972:                        }
0973:                        return false;
0974:                    } catch (JavaModelException e) {
0975:                        return false;
0976:                    }
0977:                case IJavaElementDelta.REMOVED:
0978:                    // removed project - if it contains packages we are interested in
0979:                    // then the type hierarchy has changed
0980:                    IJavaElement[] pkgs = this .packageRegion.getElements();
0981:                    for (int i = 0; i < pkgs.length; i++) {
0982:                        IJavaProject javaProject = pkgs[i].getJavaProject();
0983:                        if (javaProject != null && javaProject.equals(element)) {
0984:                            return true;
0985:                        }
0986:                    }
0987:                    return false;
0988:                case IJavaElementDelta.CHANGED:
0989:                    return isAffectedByChildren(delta);
0990:                }
0991:                return false;
0992:            }
0993:
0994:            /**
0995:             * Returns true if the given package fragment delta could affect this type hierarchy
0996:             */
0997:            private boolean isAffectedByPackageFragment(
0998:                    IJavaElementDelta delta, PackageFragment element) {
0999:                switch (delta.getKind()) {
1000:                case IJavaElementDelta.ADDED:
1001:                    // if the package fragment is in the projects being considered, this could
1002:                    // introduce new types, changing the hierarchy
1003:                    return this .projectRegion.contains(element);
1004:                case IJavaElementDelta.REMOVED:
1005:                    // is a change if the package fragment contains types in this hierarchy
1006:                    return packageRegionContainsSamePackageFragment(element);
1007:                case IJavaElementDelta.CHANGED:
1008:                    // look at the files in the package fragment
1009:                    return isAffectedByChildren(delta);
1010:                }
1011:                return false;
1012:            }
1013:
1014:            /**
1015:             * Returns true if the given package fragment root delta could affect this type hierarchy
1016:             */
1017:            private boolean isAffectedByPackageFragmentRoot(
1018:                    IJavaElementDelta delta, IJavaElement element) {
1019:                switch (delta.getKind()) {
1020:                case IJavaElementDelta.ADDED:
1021:                    return this .projectRegion.contains(element);
1022:                case IJavaElementDelta.REMOVED:
1023:                case IJavaElementDelta.CHANGED:
1024:                    int flags = delta.getFlags();
1025:                    if ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) > 0) {
1026:                        // check if the root is in the classpath of one of the projects of this hierarchy
1027:                        if (this .projectRegion != null) {
1028:                            IPackageFragmentRoot root = (IPackageFragmentRoot) element;
1029:                            IPath rootPath = root.getPath();
1030:                            IJavaElement[] elements = this .projectRegion
1031:                                    .getElements();
1032:                            for (int i = 0; i < elements.length; i++) {
1033:                                JavaProject javaProject = (JavaProject) elements[i];
1034:                                try {
1035:                                    IClasspathEntry entry = javaProject
1036:                                            .getClasspathEntryFor(rootPath);
1037:                                    if (entry != null) {
1038:                                        return true;
1039:                                    }
1040:                                } catch (JavaModelException e) {
1041:                                    // igmore this project
1042:                                }
1043:                            }
1044:                        }
1045:                    }
1046:                    if ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) > 0
1047:                            || (flags & IJavaElementDelta.F_CONTENT) > 0) {
1048:                        // 1. removed from classpath - if it contains packages we are interested in
1049:                        // the the type hierarchy has changed
1050:                        // 2. content of a jar changed - if it contains packages we are interested in
1051:                        // the the type hierarchy has changed
1052:                        IJavaElement[] pkgs = this .packageRegion.getElements();
1053:                        for (int i = 0; i < pkgs.length; i++) {
1054:                            if (pkgs[i].getParent().equals(element)) {
1055:                                return true;
1056:                            }
1057:                        }
1058:                        return false;
1059:                    }
1060:                }
1061:                return isAffectedByChildren(delta);
1062:            }
1063:
1064:            /**
1065:             * Returns true if the given type delta (a compilation unit delta or a class file delta)
1066:             * could affect this type hierarchy.
1067:             */
1068:            protected boolean isAffectedByOpenable(IJavaElementDelta delta,
1069:                    IJavaElement element) {
1070:                if (element instanceof  CompilationUnit) {
1071:                    CompilationUnit cu = (CompilationUnit) element;
1072:                    ChangeCollector collector = this .changeCollector;
1073:                    if (collector == null) {
1074:                        collector = new ChangeCollector(this );
1075:                    }
1076:                    try {
1077:                        collector.addChange(cu, delta);
1078:                    } catch (JavaModelException e) {
1079:                        if (DEBUG)
1080:                            e.printStackTrace();
1081:                    }
1082:                    if (cu.isWorkingCopy()) {
1083:                        // changes to working copies are batched
1084:                        this .changeCollector = collector;
1085:                        return false;
1086:                    } else {
1087:                        return collector.needsRefresh();
1088:                    }
1089:                } else if (element instanceof  ClassFile) {
1090:                    switch (delta.getKind()) {
1091:                    case IJavaElementDelta.REMOVED:
1092:                        return this .files.get(element) != null;
1093:                    case IJavaElementDelta.ADDED:
1094:                        IType type = ((ClassFile) element).getType();
1095:                        String typeName = type.getElementName();
1096:                        if (hasSupertype(typeName)
1097:                                || subtypesIncludeSupertypeOf(type)
1098:                                || this .missingTypes.contains(typeName)) {
1099:
1100:                            return true;
1101:                        }
1102:                        break;
1103:                    case IJavaElementDelta.CHANGED:
1104:                        IJavaElementDelta[] children = delta
1105:                                .getAffectedChildren();
1106:                        for (int i = 0, length = children.length; i < length; i++) {
1107:                            IJavaElementDelta child = children[i];
1108:                            IJavaElement childElement = child.getElement();
1109:                            if (childElement instanceof  IType) {
1110:                                type = (IType) childElement;
1111:                                boolean hasVisibilityChange = (delta.getFlags() & IJavaElementDelta.F_MODIFIERS) > 0;
1112:                                boolean hasSupertypeChange = (delta.getFlags() & IJavaElementDelta.F_SUPER_TYPES) > 0;
1113:                                if ((hasVisibilityChange && hasSupertype(type
1114:                                        .getElementName()))
1115:                                        || (hasSupertypeChange && includesTypeOrSupertype(type))) {
1116:                                    return true;
1117:                                }
1118:                            }
1119:                        }
1120:                        break;
1121:                    }
1122:                }
1123:                return false;
1124:            }
1125:
1126:            private boolean isInterface(IType type) {
1127:                int flags = this .getCachedFlags(type);
1128:                if (flags == -1) {
1129:                    try {
1130:                        return type.isInterface();
1131:                    } catch (JavaModelException e) {
1132:                        return false;
1133:                    }
1134:                } else {
1135:                    return Flags.isInterface(flags);
1136:                }
1137:            }
1138:
1139:            /**
1140:             * Returns the java project this hierarchy was created in.
1141:             */
1142:            public IJavaProject javaProject() {
1143:                return this .focusType.getJavaProject();
1144:            }
1145:
1146:            protected static byte[] readUntil(InputStream input, byte separator)
1147:                    throws JavaModelException, IOException {
1148:                return readUntil(input, separator, 0);
1149:            }
1150:
1151:            protected static byte[] readUntil(InputStream input,
1152:                    byte separator, int offset) throws IOException,
1153:                    JavaModelException {
1154:                int length = 0;
1155:                byte[] bytes = new byte[SIZE];
1156:                byte b;
1157:                while ((b = (byte) input.read()) != separator && b != -1) {
1158:                    if (bytes.length == length) {
1159:                        System.arraycopy(bytes, 0,
1160:                                bytes = new byte[length * 2], 0, length);
1161:                    }
1162:                    bytes[length++] = b;
1163:                }
1164:                if (b == -1) {
1165:                    throw new JavaModelException(new JavaModelStatus(
1166:                            IStatus.ERROR));
1167:                }
1168:                System.arraycopy(bytes, 0, bytes = new byte[length + offset],
1169:                        offset, length);
1170:                return bytes;
1171:            }
1172:
1173:            public static ITypeHierarchy load(IType type, InputStream input,
1174:                    WorkingCopyOwner owner) throws JavaModelException {
1175:                try {
1176:                    TypeHierarchy typeHierarchy = new TypeHierarchy();
1177:                    typeHierarchy.initialize(1);
1178:
1179:                    IType[] types = new IType[SIZE];
1180:                    int typeCount = 0;
1181:
1182:                    byte version = (byte) input.read();
1183:
1184:                    if (version != VERSION) {
1185:                        throw new JavaModelException(new JavaModelStatus(
1186:                                IStatus.ERROR));
1187:                    }
1188:                    byte generalInfo = (byte) input.read();
1189:                    if ((generalInfo & COMPUTE_SUBTYPES) != 0) {
1190:                        typeHierarchy.computeSubtypes = true;
1191:                    }
1192:
1193:                    byte b;
1194:                    byte[] bytes;
1195:
1196:                    // read project
1197:                    bytes = readUntil(input, SEPARATOR1);
1198:                    if (bytes.length > 0) {
1199:                        typeHierarchy.project = (IJavaProject) JavaCore
1200:                                .create(new String(bytes));
1201:                        typeHierarchy.scope = SearchEngine
1202:                                .createJavaSearchScope(new IJavaElement[] { typeHierarchy.project });
1203:                    } else {
1204:                        typeHierarchy.project = null;
1205:                        typeHierarchy.scope = SearchEngine
1206:                                .createWorkspaceScope();
1207:                    }
1208:
1209:                    // read missing type
1210:                    {
1211:                        bytes = readUntil(input, SEPARATOR1);
1212:                        byte[] missing;
1213:                        int j = 0;
1214:                        int length = bytes.length;
1215:                        for (int i = 0; i < length; i++) {
1216:                            b = bytes[i];
1217:                            if (b == SEPARATOR2) {
1218:                                missing = new byte[i - j];
1219:                                System.arraycopy(bytes, j, missing, 0, i - j);
1220:                                typeHierarchy.missingTypes.add(new String(
1221:                                        missing));
1222:                                j = i + 1;
1223:                            }
1224:                        }
1225:                        System.arraycopy(bytes, j, missing = new byte[length
1226:                                - j], 0, length - j);
1227:                        typeHierarchy.missingTypes.add(new String(missing));
1228:                    }
1229:
1230:                    // read types
1231:                    while ((b = (byte) input.read()) != SEPARATOR1 && b != -1) {
1232:                        bytes = readUntil(input, SEPARATOR4, 1);
1233:                        bytes[0] = b;
1234:                        IType element = (IType) JavaCore.create(new String(
1235:                                bytes), owner);
1236:
1237:                        if (types.length == typeCount) {
1238:                            System.arraycopy(types, 0,
1239:                                    types = new IType[typeCount * 2], 0,
1240:                                    typeCount);
1241:                        }
1242:                        types[typeCount++] = element;
1243:
1244:                        // read flags
1245:                        bytes = readUntil(input, SEPARATOR4);
1246:                        Integer flags = bytesToFlags(bytes);
1247:                        if (flags != null) {
1248:                            typeHierarchy.cacheFlags(element, flags.intValue());
1249:                        }
1250:
1251:                        // read info
1252:                        byte info = (byte) input.read();
1253:
1254:                        if ((info & INTERFACE) != 0) {
1255:                            typeHierarchy.addInterface(element);
1256:                        }
1257:                        if ((info & COMPUTED_FOR) != 0) {
1258:                            if (!element.equals(type)) {
1259:                                throw new JavaModelException(
1260:                                        new JavaModelStatus(IStatus.ERROR));
1261:                            }
1262:                            typeHierarchy.focusType = element;
1263:                        }
1264:                        if ((info & ROOT) != 0) {
1265:                            typeHierarchy.addRootClass(element);
1266:                        }
1267:                    }
1268:
1269:                    // read super class
1270:                    while ((b = (byte) input.read()) != SEPARATOR1 && b != -1) {
1271:                        bytes = readUntil(input, SEPARATOR3, 1);
1272:                        bytes[0] = b;
1273:                        int subClass = new Integer(new String(bytes))
1274:                                .intValue();
1275:
1276:                        // read super type
1277:                        bytes = readUntil(input, SEPARATOR1);
1278:                        int super Class = new Integer(new String(bytes))
1279:                                .intValue();
1280:
1281:                        typeHierarchy.cacheSuperclass(types[subClass],
1282:                                types[super Class]);
1283:                    }
1284:
1285:                    // read super interface
1286:                    while ((b = (byte) input.read()) != SEPARATOR1 && b != -1) {
1287:                        bytes = readUntil(input, SEPARATOR3, 1);
1288:                        bytes[0] = b;
1289:                        int subClass = new Integer(new String(bytes))
1290:                                .intValue();
1291:
1292:                        // read super interface
1293:                        bytes = readUntil(input, SEPARATOR1);
1294:                        IType[] super Interfaces = new IType[(bytes.length / 2) + 1];
1295:                        int interfaceCount = 0;
1296:
1297:                        int j = 0;
1298:                        byte[] b2;
1299:                        for (int i = 0; i < bytes.length; i++) {
1300:                            if (bytes[i] == SEPARATOR2) {
1301:                                b2 = new byte[i - j];
1302:                                System.arraycopy(bytes, j, b2, 0, i - j);
1303:                                j = i + 1;
1304:                                super Interfaces[interfaceCount++] = types[new Integer(
1305:                                        new String(b2)).intValue()];
1306:                            }
1307:                        }
1308:                        b2 = new byte[bytes.length - j];
1309:                        System.arraycopy(bytes, j, b2, 0, bytes.length - j);
1310:                        super Interfaces[interfaceCount++] = types[new Integer(
1311:                                new String(b2)).intValue()];
1312:                        System.arraycopy(super Interfaces, 0,
1313:                                super Interfaces = new IType[interfaceCount], 0,
1314:                                interfaceCount);
1315:
1316:                        typeHierarchy.cacheSuperInterfaces(types[subClass],
1317:                                super Interfaces);
1318:                    }
1319:                    if (b == -1) {
1320:                        throw new JavaModelException(new JavaModelStatus(
1321:                                IStatus.ERROR));
1322:                    }
1323:                    return typeHierarchy;
1324:                } catch (IOException e) {
1325:                    throw new JavaModelException(e,
1326:                            IJavaModelStatusConstants.IO_EXCEPTION);
1327:                }
1328:            }
1329:
1330:            /**
1331:             * Returns <code>true</code> if an equivalent package fragment is included in the package
1332:             * region. Package fragments are equivalent if they both have the same name.
1333:             */
1334:            protected boolean packageRegionContainsSamePackageFragment(
1335:                    PackageFragment element) {
1336:                IJavaElement[] pkgs = this .packageRegion.getElements();
1337:                for (int i = 0; i < pkgs.length; i++) {
1338:                    PackageFragment pkg = (PackageFragment) pkgs[i];
1339:                    if (Util.equalArraysOrNull(pkg.names, element.names))
1340:                        return true;
1341:                }
1342:                return false;
1343:            }
1344:
1345:            /**
1346:             * @see ITypeHierarchy
1347:             * TODO (jerome) should use a PerThreadObject to build the hierarchy instead of synchronizing
1348:             * (see also isAffected(IJavaElementDelta))
1349:             */
1350:            public synchronized void refresh(IProgressMonitor monitor)
1351:                    throws JavaModelException {
1352:                try {
1353:                    this .progressMonitor = monitor;
1354:                    if (monitor != null) {
1355:                        monitor.beginTask(this .focusType != null ? Messages
1356:                                .bind(Messages.hierarchy_creatingOnType,
1357:                                        this .focusType.getFullyQualifiedName())
1358:                                : Messages.hierarchy_creating, 100);
1359:                    }
1360:                    long start = -1;
1361:                    if (DEBUG) {
1362:                        start = System.currentTimeMillis();
1363:                        if (this .computeSubtypes) {
1364:                            System.out
1365:                                    .println("CREATING TYPE HIERARCHY [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
1366:                        } else {
1367:                            System.out
1368:                                    .println("CREATING SUPER TYPE HIERARCHY [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
1369:                        }
1370:                        if (this .focusType != null) {
1371:                            System.out
1372:                                    .println("  on type " + ((JavaElement) this .focusType).toStringWithAncestors()); //$NON-NLS-1$
1373:                        }
1374:                    }
1375:
1376:                    compute();
1377:                    initializeRegions();
1378:                    this .needsRefresh = false;
1379:                    this .changeCollector = null;
1380:
1381:                    if (DEBUG) {
1382:                        if (this .computeSubtypes) {
1383:                            System.out
1384:                                    .println("CREATED TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
1385:                        } else {
1386:                            System.out
1387:                                    .println("CREATED SUPER TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
1388:                        }
1389:                        System.out.println(this .toString());
1390:                    }
1391:                } catch (JavaModelException e) {
1392:                    throw e;
1393:                } catch (CoreException e) {
1394:                    throw new JavaModelException(e);
1395:                } finally {
1396:                    if (monitor != null) {
1397:                        monitor.done();
1398:                    }
1399:                    this .progressMonitor = null;
1400:                }
1401:            }
1402:
1403:            /**
1404:             * @see ITypeHierarchy
1405:             */
1406:            public synchronized void removeTypeHierarchyChangedListener(
1407:                    ITypeHierarchyChangedListener listener) {
1408:                ArrayList listeners = this .changeListeners;
1409:                if (listeners == null) {
1410:                    return;
1411:                }
1412:                listeners.remove(listener);
1413:
1414:                // deregister from JavaCore on last listener removed
1415:                if (listeners.isEmpty()) {
1416:                    JavaCore.removeElementChangedListener(this );
1417:                }
1418:            }
1419:
1420:            /**
1421:             * @see ITypeHierarchy
1422:             */
1423:            public void store(OutputStream output, IProgressMonitor monitor)
1424:                    throws JavaModelException {
1425:                try {
1426:                    // compute types in hierarchy
1427:                    Hashtable hashtable = new Hashtable();
1428:                    Hashtable hashtable2 = new Hashtable();
1429:                    int count = 0;
1430:
1431:                    if (this .focusType != null) {
1432:                        Integer index = new Integer(count++);
1433:                        hashtable.put(this .focusType, index);
1434:                        hashtable2.put(index, this .focusType);
1435:                    }
1436:                    Object[] types = this .classToSuperclass.entrySet()
1437:                            .toArray();
1438:                    for (int i = 0; i < types.length; i++) {
1439:                        Map.Entry entry = (Map.Entry) types[i];
1440:                        Object t = entry.getKey();
1441:                        if (hashtable.get(t) == null) {
1442:                            Integer index = new Integer(count++);
1443:                            hashtable.put(t, index);
1444:                            hashtable2.put(index, t);
1445:                        }
1446:                        Object super Class = entry.getValue();
1447:                        if (super Class != null
1448:                                && hashtable.get(super Class) == null) {
1449:                            Integer index = new Integer(count++);
1450:                            hashtable.put(super Class, index);
1451:                            hashtable2.put(index, super Class);
1452:                        }
1453:                    }
1454:                    types = this .typeToSuperInterfaces.entrySet().toArray();
1455:                    for (int i = 0; i < types.length; i++) {
1456:                        Map.Entry entry = (Map.Entry) types[i];
1457:                        Object t = entry.getKey();
1458:                        if (hashtable.get(t) == null) {
1459:                            Integer index = new Integer(count++);
1460:                            hashtable.put(t, index);
1461:                            hashtable2.put(index, t);
1462:                        }
1463:                        Object[] sp = (Object[]) entry.getValue();
1464:                        if (sp != null) {
1465:                            for (int j = 0; j < sp.length; j++) {
1466:                                Object super Interface = sp[j];
1467:                                if (sp[j] != null
1468:                                        && hashtable.get(super Interface) == null) {
1469:                                    Integer index = new Integer(count++);
1470:                                    hashtable.put(super Interface, index);
1471:                                    hashtable2.put(index, super Interface);
1472:                                }
1473:                            }
1474:                        }
1475:                    }
1476:                    // save version of the hierarchy format
1477:                    output.write(VERSION);
1478:
1479:                    // save general info
1480:                    byte generalInfo = 0;
1481:                    if (this .computeSubtypes) {
1482:                        generalInfo |= COMPUTE_SUBTYPES;
1483:                    }
1484:                    output.write(generalInfo);
1485:
1486:                    // save project
1487:                    if (this .project != null) {
1488:                        output.write(this .project.getHandleIdentifier()
1489:                                .getBytes());
1490:                    }
1491:                    output.write(SEPARATOR1);
1492:
1493:                    // save missing types
1494:                    for (int i = 0; i < this .missingTypes.size(); i++) {
1495:                        if (i != 0) {
1496:                            output.write(SEPARATOR2);
1497:                        }
1498:                        output.write(((String) this .missingTypes.get(i))
1499:                                .getBytes());
1500:
1501:                    }
1502:                    output.write(SEPARATOR1);
1503:
1504:                    // save types
1505:                    for (int i = 0; i < count; i++) {
1506:                        IType t = (IType) hashtable2.get(new Integer(i));
1507:
1508:                        // n bytes
1509:                        output.write(t.getHandleIdentifier().getBytes());
1510:                        output.write(SEPARATOR4);
1511:                        output.write(flagsToBytes((Integer) this .typeFlags
1512:                                .get(t)));
1513:                        output.write(SEPARATOR4);
1514:                        byte info = CLASS;
1515:                        if (this .focusType != null && this .focusType.equals(t)) {
1516:                            info |= COMPUTED_FOR;
1517:                        }
1518:                        if (this .interfaces.contains(t)) {
1519:                            info |= INTERFACE;
1520:                        }
1521:                        if (this .rootClasses.contains(t)) {
1522:                            info |= ROOT;
1523:                        }
1524:                        output.write(info);
1525:                    }
1526:                    output.write(SEPARATOR1);
1527:
1528:                    // save superclasses
1529:                    types = this .classToSuperclass.entrySet().toArray();
1530:                    for (int i = 0; i < types.length; i++) {
1531:                        Map.Entry entry = (Map.Entry) types[i];
1532:                        IJavaElement key = (IJavaElement) entry.getKey();
1533:                        IJavaElement value = (IJavaElement) entry.getValue();
1534:
1535:                        output.write(((Integer) hashtable.get(key)).toString()
1536:                                .getBytes());
1537:                        output.write('>');
1538:                        output.write(((Integer) hashtable.get(value))
1539:                                .toString().getBytes());
1540:                        output.write(SEPARATOR1);
1541:                    }
1542:                    output.write(SEPARATOR1);
1543:
1544:                    // save superinterfaces
1545:                    types = this .typeToSuperInterfaces.entrySet().toArray();
1546:                    for (int i = 0; i < types.length; i++) {
1547:                        Map.Entry entry = (Map.Entry) types[i];
1548:                        IJavaElement key = (IJavaElement) entry.getKey();
1549:                        IJavaElement[] values = (IJavaElement[]) entry
1550:                                .getValue();
1551:
1552:                        if (values.length > 0) {
1553:                            output.write(((Integer) hashtable.get(key))
1554:                                    .toString().getBytes());
1555:                            output.write(SEPARATOR3);
1556:                            for (int j = 0; j < values.length; j++) {
1557:                                IJavaElement value = values[j];
1558:                                if (j != 0)
1559:                                    output.write(SEPARATOR2);
1560:                                output.write(((Integer) hashtable.get(value))
1561:                                        .toString().getBytes());
1562:                            }
1563:                            output.write(SEPARATOR1);
1564:                        }
1565:                    }
1566:                    output.write(SEPARATOR1);
1567:                } catch (IOException e) {
1568:                    throw new JavaModelException(e,
1569:                            IJavaModelStatusConstants.IO_EXCEPTION);
1570:                }
1571:            }
1572:
1573:            /**
1574:             * Returns whether the simple name of a supertype of the given type is 
1575:             * the simple name of one of the subtypes in this hierarchy or the
1576:             * simple name of this type.
1577:             */
1578:            boolean subtypesIncludeSupertypeOf(IType type) {
1579:                // look for superclass
1580:                String super className = null;
1581:                try {
1582:                    super className = type.getSuperclassName();
1583:                } catch (JavaModelException e) {
1584:                    if (DEBUG) {
1585:                        e.printStackTrace();
1586:                    }
1587:                    return false;
1588:                }
1589:                if (super className == null) {
1590:                    super className = "Object"; //$NON-NLS-1$
1591:                }
1592:                int dot = -1;
1593:                String simpleSuper = (dot = super className.lastIndexOf('.')) > -1 ? super className
1594:                        .substring(dot + 1)
1595:                        : super className;
1596:                if (hasSubtypeNamed(simpleSuper)) {
1597:                    return true;
1598:                }
1599:
1600:                // look for super interfaces
1601:                String[] interfaceNames = null;
1602:                try {
1603:                    interfaceNames = type.getSuperInterfaceNames();
1604:                } catch (JavaModelException e) {
1605:                    if (DEBUG)
1606:                        e.printStackTrace();
1607:                    return false;
1608:                }
1609:                for (int i = 0, length = interfaceNames.length; i < length; i++) {
1610:                    dot = -1;
1611:                    String interfaceName = interfaceNames[i];
1612:                    String simpleInterface = (dot = interfaceName
1613:                            .lastIndexOf('.')) > -1 ? interfaceName
1614:                            .substring(dot) : interfaceName;
1615:                    if (hasSubtypeNamed(simpleInterface)) {
1616:                        return true;
1617:                    }
1618:                }
1619:
1620:                return false;
1621:            }
1622:
1623:            /**
1624:             * @see ITypeHierarchy
1625:             */
1626:            public String toString() {
1627:                StringBuffer buffer = new StringBuffer();
1628:                buffer.append("Focus: "); //$NON-NLS-1$
1629:                buffer
1630:                        .append(this .focusType == null ? "<NONE>" : ((JavaElement) this .focusType).toStringWithAncestors(false/*don't show key*/)); //$NON-NLS-1$
1631:                buffer.append("\n"); //$NON-NLS-1$
1632:                if (exists()) {
1633:                    if (this .focusType != null) {
1634:                        buffer.append("Super types:\n"); //$NON-NLS-1$
1635:                        toString(buffer, this .focusType, 1, true);
1636:                        buffer.append("Sub types:\n"); //$NON-NLS-1$
1637:                        toString(buffer, this .focusType, 1, false);
1638:                    } else {
1639:                        buffer.append("Sub types of root classes:\n"); //$NON-NLS-1$
1640:                        IJavaElement[] roots = Util.sortCopy(getRootClasses());
1641:                        for (int i = 0; i < roots.length; i++) {
1642:                            toString(buffer, (IType) roots[i], 1, false);
1643:                        }
1644:                    }
1645:                    if (this .rootClasses.size > 1) {
1646:                        buffer.append("Root classes:\n"); //$NON-NLS-1$
1647:                        IJavaElement[] roots = Util.sortCopy(getRootClasses());
1648:                        for (int i = 0, length = roots.length; i < length; i++) {
1649:                            toString(buffer, (IType) roots[i], 1, false);
1650:                        }
1651:                    } else if (this .rootClasses.size == 0) {
1652:                        // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24691
1653:                        buffer.append("No root classes"); //$NON-NLS-1$
1654:                    }
1655:                } else {
1656:                    buffer.append("(Hierarchy became stale)"); //$NON-NLS-1$
1657:                }
1658:                return buffer.toString();
1659:            }
1660:
1661:            /**
1662:             * Append a String to the given buffer representing the hierarchy for the type,
1663:             * beginning with the specified indentation level.
1664:             * If ascendant, shows the super types, otherwise show the sub types.
1665:             */
1666:            private void toString(StringBuffer buffer, IType type, int indent,
1667:                    boolean ascendant) {
1668:                IType[] types = ascendant ? getSupertypes(type)
1669:                        : getSubtypes(type);
1670:                IJavaElement[] sortedTypes = Util.sortCopy(types);
1671:                for (int i = 0; i < sortedTypes.length; i++) {
1672:                    for (int j = 0; j < indent; j++) {
1673:                        buffer.append("  "); //$NON-NLS-1$
1674:                    }
1675:                    JavaElement element = (JavaElement) sortedTypes[i];
1676:                    buffer.append(element
1677:                            .toStringWithAncestors(false/*don't show key*/));
1678:                    buffer.append('\n');
1679:                    toString(buffer, types[i], indent + 1, ascendant);
1680:                }
1681:            }
1682:
1683:            /**
1684:             * Returns whether one of the types in this hierarchy has a supertype whose simple 
1685:             * name is the given simple name.
1686:             */
1687:            boolean hasSupertype(String simpleName) {
1688:                for (Iterator iter = this .classToSuperclass.values().iterator(); iter
1689:                        .hasNext();) {
1690:                    IType super Type = (IType) iter.next();
1691:                    if (super Type.getElementName().equals(simpleName)) {
1692:                        return true;
1693:                    }
1694:                }
1695:                return false;
1696:            }
1697:
1698:            /**
1699:             * @see IProgressMonitor
1700:             */
1701:            protected void worked(int work) {
1702:                if (this.progressMonitor != null) {
1703:                    this.progressMonitor.worked(work);
1704:                    checkCanceled();
1705:                }
1706:            }
1707:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.