Source Code Cross Referenced for ObjectContributorManager.java in  » IDE-Eclipse » ui-workbench » org » eclipse » ui » internal » 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 » ui workbench » org.eclipse.ui.internal 
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.ui.internal;
0011:
0012:        import java.util.ArrayList;
0013:        import java.util.Arrays;
0014:        import java.util.Collection;
0015:        import java.util.Collections;
0016:        import java.util.HashMap;
0017:        import java.util.HashSet;
0018:        import java.util.Hashtable;
0019:        import java.util.Iterator;
0020:        import java.util.List;
0021:        import java.util.Map;
0022:        import java.util.Set;
0023:
0024:        import org.eclipse.core.runtime.IAdaptable;
0025:        import org.eclipse.core.runtime.IAdapterManager;
0026:        import org.eclipse.core.runtime.IConfigurationElement;
0027:        import org.eclipse.core.runtime.IExtension;
0028:        import org.eclipse.core.runtime.Platform;
0029:        import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
0030:        import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
0031:        import org.eclipse.jface.viewers.IStructuredSelection;
0032:        import org.eclipse.ui.PlatformUI;
0033:        import org.eclipse.ui.internal.util.Util;
0034:
0035:        /**
0036:         * This class is a default implementation of <code>IObjectContributorManager</code>.
0037:         * It provides fast merging of contributions with the following semantics:
0038:         * <ul>
0039:         * <li> All of the matching contributors will be invoked per property lookup
0040:         * <li> The search order from a class with the definition<br>
0041:         *			<code>class X extends Y implements A, B</code><br>
0042:         *		is as follows:
0043:         * 		<il>
0044:         *			<li>the target's class: X
0045:         *			<li>X's superclasses in order to <code>Object</code>
0046:         *			<li>a depth-first traversal of the target class's interaces in the order 
0047:         *				returned by <code>getInterfaces()</code> (in the example, A and 
0048:         *				its superinterfaces then B and its superinterfaces)
0049:         *		</il>
0050:         * </ul>
0051:         *
0052:         * @see IObjectContributor
0053:         */
0054:        public abstract class ObjectContributorManager implements 
0055:                IExtensionChangeHandler {
0056:
0057:            /** 
0058:             * @since 3.1
0059:             */
0060:            private class ContributorRecord {
0061:                /**
0062:                 * @param contributor
0063:                 * @param targetType
0064:                 */
0065:                public ContributorRecord(IObjectContributor contributor,
0066:                        String targetType) {
0067:                    this .contributor = contributor;
0068:                    this .objectClassName = targetType;
0069:                }
0070:
0071:                String objectClassName;
0072:                IObjectContributor contributor;
0073:            }
0074:
0075:            /** Table of contributors. */
0076:            protected Map contributors;
0077:
0078:            /** Cache of object class contributor search paths; <code>null</code> if none. */
0079:            protected Map objectLookup;
0080:
0081:            /** Cache of resource adapter class contributor search paths; <code>null</code> if none. */
0082:            protected Map resourceAdapterLookup;
0083:
0084:            /** Cache of adaptable class contributor search paths; <code>null</code> if none. */
0085:            protected Map adaptableLookup;
0086:
0087:            protected Set contributorRecordSet;
0088:
0089:            /** 
0090:             * Constructs a new contributor manager.
0091:             */
0092:            public ObjectContributorManager() {
0093:                contributors = new Hashtable(5);
0094:                contributorRecordSet = new HashSet(5);
0095:                objectLookup = null;
0096:                resourceAdapterLookup = null;
0097:                adaptableLookup = null;
0098:                if (canHandleExtensionTracking()) {
0099:                    IExtensionTracker tracker = PlatformUI.getWorkbench()
0100:                            .getExtensionTracker();
0101:                    tracker.registerHandler(this , null);
0102:                }
0103:            }
0104:
0105:            /**
0106:             * Return whether or not the receiver handles extension
0107:             * tracking. Default is <code>true</code>. Subclasses may override.
0108:             * @return boolean <code>true</code> if it should be registered
0109:             * as an extension handler.
0110:             */
0111:            protected boolean canHandleExtensionTracking() {
0112:                return true;
0113:            }
0114:
0115:            /**
0116:             * Adds contributors for the given types to the result list.
0117:             */
0118:            private void addContributorsFor(List types, List result) {
0119:                for (Iterator classes = types.iterator(); classes.hasNext();) {
0120:                    Class clazz = (Class) classes.next();
0121:                    List contributorList = (List) contributors.get(clazz
0122:                            .getName());
0123:                    if (contributorList != null) {
0124:                        result.addAll(contributorList);
0125:                    }
0126:                }
0127:            }
0128:
0129:            /**
0130:             * Returns the class search order starting with <code>extensibleClass</code>.
0131:             * The search order is defined in this class' comment.
0132:             */
0133:            protected final List computeClassOrder(Class extensibleClass) {
0134:                ArrayList result = new ArrayList(4);
0135:                Class clazz = extensibleClass;
0136:                while (clazz != null) {
0137:                    result.add(clazz);
0138:                    clazz = clazz.getSuperclass();
0139:                }
0140:                return result;
0141:            }
0142:
0143:            /**
0144:             * Returns the interface search order for the class hierarchy described
0145:             * by <code>classList</code>.
0146:             * The search order is defined in this class' comment.
0147:             */
0148:            protected final List computeInterfaceOrder(List classList) {
0149:                ArrayList result = new ArrayList(4);
0150:                Map seen = new HashMap(4);
0151:                for (Iterator list = classList.iterator(); list.hasNext();) {
0152:                    Class[] interfaces = ((Class) list.next()).getInterfaces();
0153:                    internalComputeInterfaceOrder(interfaces, result, seen);
0154:                }
0155:                return result;
0156:            }
0157:
0158:            /**
0159:             * Flushes the cache of contributor search paths.  This is generally required
0160:             * whenever a contributor is added or removed.  
0161:             * <p>
0162:             * It is likely easier to just toss the whole cache rather than trying to be
0163:             * smart and remove only those entries affected.
0164:             */
0165:            public void flushLookup() {
0166:                objectLookup = null;
0167:                resourceAdapterLookup = null;
0168:                adaptableLookup = null;
0169:            }
0170:
0171:            /**
0172:             * Cache the real adapter class contributor search path.
0173:             */
0174:            private void cacheResourceAdapterLookup(Class adapterClass,
0175:                    List results) {
0176:                if (resourceAdapterLookup == null) {
0177:                    resourceAdapterLookup = new HashMap();
0178:                }
0179:                resourceAdapterLookup.put(adapterClass, results);
0180:            }
0181:
0182:            /**
0183:             * Cache the real adapter class contributor search path.
0184:             */
0185:            private void cacheAdaptableLookup(String adapterClass, List results) {
0186:                if (adaptableLookup == null) {
0187:                    adaptableLookup = new HashMap();
0188:                }
0189:                adaptableLookup.put(adapterClass, results);
0190:            }
0191:
0192:            /**
0193:             * Cache the object class contributor search path.
0194:             */
0195:            private void cacheObjectLookup(Class objectClass, List results) {
0196:                if (objectLookup == null) {
0197:                    objectLookup = new HashMap();
0198:                }
0199:                objectLookup.put(objectClass, results);
0200:            }
0201:
0202:            /**
0203:             * Get the contributions registered to this manager.
0204:             * 
0205:             * @return an unmodifiable <code>Collection</code> containing all registered
0206:             * contributions.  The objects in this <code>Collection</code> will be 
0207:             * <code>List</code>s containing the actual contributions.
0208:             * @since 3.0
0209:             */
0210:            public Collection getContributors() {
0211:                return Collections
0212:                        .unmodifiableCollection(contributors.values());
0213:            }
0214:
0215:            /**
0216:             * Return the list of contributors for the supplied class.
0217:             */
0218:            protected List addContributorsFor(Class objectClass) {
0219:
0220:                List classList = computeClassOrder(objectClass);
0221:                List result = new ArrayList();
0222:                addContributorsFor(classList, result);
0223:                classList = computeInterfaceOrder(classList); // interfaces
0224:                addContributorsFor(classList, result);
0225:                return result;
0226:            }
0227:
0228:            /**
0229:             * Returns true if contributors exist in the manager for
0230:             * this object and any of it's super classes, interfaces, or
0231:             * adapters.
0232:             * 
0233:             * @param object the object to test
0234:             * @return whether the object has contributors
0235:             */
0236:            public boolean hasContributorsFor(Object object) {
0237:
0238:                List contributors = getContributors(object);
0239:                return contributors.size() > 0;
0240:            }
0241:
0242:            /**
0243:             * Add interface Class objects to the result list based
0244:             * on the class hierarchy. Interfaces will be searched
0245:             * based on their position in the result list.
0246:             */
0247:            private void internalComputeInterfaceOrder(Class[] interfaces,
0248:                    List result, Map seen) {
0249:                List newInterfaces = new ArrayList(seen.size());
0250:                for (int i = 0; i < interfaces.length; i++) {
0251:                    Class interfac = interfaces[i];
0252:                    if (seen.get(interfac) == null) {
0253:                        result.add(interfac);
0254:                        seen.put(interfac, interfac);
0255:                        newInterfaces.add(interfac);
0256:                    }
0257:                }
0258:                for (Iterator newList = newInterfaces.iterator(); newList
0259:                        .hasNext();) {
0260:                    internalComputeInterfaceOrder(((Class) newList.next())
0261:                            .getInterfaces(), result, seen);
0262:                }
0263:            }
0264:
0265:            /**
0266:             * Return whether the given contributor is applicable to all elements in the
0267:             * selection.
0268:             * 
0269:             * @param selection
0270:             *            the selection
0271:             * @param contributor
0272:             *            the contributor
0273:             * @return whether it is applicable
0274:             */
0275:            public boolean isApplicableTo(IStructuredSelection selection,
0276:                    IObjectContributor contributor) {
0277:                Iterator elements = selection.iterator();
0278:                while (elements.hasNext()) {
0279:                    if (contributor.isApplicableTo(elements.next()) == false) {
0280:                        return false;
0281:                    }
0282:                }
0283:                return true;
0284:            }
0285:
0286:            /**
0287:             * Return whether the given contributor is applicable to all elements in the
0288:             * list.
0289:             * 
0290:             * @param list
0291:             *            the selection
0292:             * @param contributor
0293:             *            the contributor
0294:             * @return whether it is applicable
0295:             */
0296:
0297:            public boolean isApplicableTo(List list,
0298:                    IObjectContributor contributor) {
0299:                Iterator elements = list.iterator();
0300:                while (elements.hasNext()) {
0301:                    if (contributor.isApplicableTo(elements.next()) == false) {
0302:                        return false;
0303:                    }
0304:                }
0305:                return true;
0306:            }
0307:
0308:            /**
0309:             * Register a contributor.
0310:             * 
0311:             * @param contributor the contributor
0312:             * @param targetType the target type
0313:             */
0314:            public void registerContributor(IObjectContributor contributor,
0315:                    String targetType) {
0316:                List contributorList = (List) contributors.get(targetType);
0317:                if (contributorList == null) {
0318:                    contributorList = new ArrayList(5);
0319:                    contributors.put(targetType, contributorList);
0320:                }
0321:                contributorList.add(contributor);
0322:                flushLookup();
0323:
0324:                IConfigurationElement element = (IConfigurationElement) Util
0325:                        .getAdapter(contributor, IConfigurationElement.class);
0326:
0327:                //hook the object listener
0328:                if (element != null) {
0329:                    ContributorRecord contributorRecord = new ContributorRecord(
0330:                            contributor, targetType);
0331:                    contributorRecordSet.add(contributorRecord);
0332:                    PlatformUI.getWorkbench().getExtensionTracker()
0333:                            .registerObject(element.getDeclaringExtension(),
0334:                                    contributorRecord,
0335:                                    IExtensionTracker.REF_WEAK);
0336:                }
0337:            }
0338:
0339:            /**
0340:             * Unregister all contributors.
0341:             */
0342:            public void unregisterAllContributors() {
0343:                contributors = new Hashtable(5);
0344:                flushLookup();
0345:            }
0346:
0347:            /**
0348:             * Unregister a contributor from the target type.
0349:             * 
0350:             * @param contributor the contributor
0351:             * @param targetType the target type
0352:             */
0353:            public void unregisterContributor(IObjectContributor contributor,
0354:                    String targetType) {
0355:                List contributorList = (List) contributors.get(targetType);
0356:                if (contributorList == null) {
0357:                    return;
0358:                }
0359:                contributorList.remove(contributor);
0360:                if (contributorList.isEmpty()) {
0361:                    contributors.remove(targetType);
0362:                }
0363:                flushLookup();
0364:            }
0365:
0366:            /**
0367:             * Unregister all contributors for the target type.
0368:             * 
0369:             * @param targetType the target type
0370:             */
0371:            public void unregisterContributors(String targetType) {
0372:                contributors.remove(targetType);
0373:                flushLookup();
0374:            }
0375:
0376:            protected List getContributors(Object object) {
0377:                // Determine is the object is a resource
0378:                Object resource = LegacyResourceSupport
0379:                        .getAdaptedContributorResource(object);
0380:
0381:                // Fetch the unique adapters
0382:                List adapters = new ArrayList(Arrays.asList(Platform
0383:                        .getAdapterManager().computeAdapterTypes(
0384:                                object.getClass())));
0385:                removeCommonAdapters(adapters, Arrays
0386:                        .asList(new Class[] { object.getClass() }));
0387:
0388:                List contributors = new ArrayList();
0389:
0390:                // Calculate the contributors for this object class
0391:                addAll(contributors, getObjectContributors(object.getClass()));
0392:                // Calculate the contributors for resource classes
0393:                if (resource != null) {
0394:                    addAll(contributors, getResourceContributors(resource
0395:                            .getClass()));
0396:                }
0397:                // Calculate the contributors for each adapter type
0398:                if (adapters != null) {
0399:                    for (Iterator it = adapters.iterator(); it.hasNext();) {
0400:                        String adapter = (String) it.next();
0401:                        addAll(contributors, getAdaptableContributors(adapter));
0402:                    }
0403:                }
0404:
0405:                // Remove duplicates.  Note: this -must- maintain the element order to preserve menu order.
0406:                contributors = removeDups(contributors);
0407:
0408:                return contributors.isEmpty() ? Collections.EMPTY_LIST
0409:                        : new ArrayList(contributors);
0410:            }
0411:
0412:            /**
0413:             * Returns the contributions for the given class. This considers
0414:             * contributors on any super classes and interfaces.
0415:             * 
0416:             * @param objectClass the class to search for contributions.
0417:             * @return the contributions for the given class. This considers
0418:             * contributors on any super classes and interfaces.
0419:             * 
0420:             * @since 3.1
0421:             */
0422:            protected List getObjectContributors(Class objectClass) {
0423:                List objectList = null;
0424:                // Lookup the results in the cache first.
0425:                if (objectLookup != null) {
0426:                    objectList = (List) objectLookup.get(objectClass);
0427:                }
0428:                if (objectList == null) {
0429:                    objectList = addContributorsFor(objectClass);
0430:                    if (objectList.size() == 0) {
0431:                        objectList = Collections.EMPTY_LIST;
0432:                    } else {
0433:                        objectList = Collections.unmodifiableList(objectList);
0434:                    }
0435:                    cacheObjectLookup(objectClass, objectList);
0436:                }
0437:                return objectList;
0438:            }
0439:
0440:            /**
0441:             * Returns the contributions for the given <code>IResource</code>class. 
0442:             * This considers contributors on any super classes and interfaces. This
0443:             * will only return contributions that are adaptable.
0444:             * 
0445:             * @param resourceClass the class to search for contributions.
0446:             * @return the contributions for the given class. This considers
0447:             * adaptable contributors on any super classes and interfaces.
0448:             * 
0449:             * @since 3.1
0450:             */
0451:            protected List getResourceContributors(Class resourceClass) {
0452:                List resourceList = null;
0453:                if (resourceAdapterLookup != null) {
0454:                    resourceList = (List) resourceAdapterLookup
0455:                            .get(resourceClass);
0456:                }
0457:                if (resourceList == null) {
0458:                    resourceList = addContributorsFor(resourceClass);
0459:                    if (resourceList.size() == 0) {
0460:                        resourceList = Collections.EMPTY_LIST;
0461:                    } else {
0462:                        resourceList = Collections
0463:                                .unmodifiableList(filterOnlyAdaptableContributors(resourceList));
0464:                    }
0465:                    cacheResourceAdapterLookup(resourceClass, resourceList);
0466:                }
0467:                return resourceList;
0468:            }
0469:
0470:            /**
0471:             * Returns the contributions for the given type name. 
0472:             * 
0473:             * @param adapterType the class to search for contributions.
0474:             * @return the contributions for the given class. This considers
0475:             * contributors to this specific type.
0476:             * 
0477:             * @since 3.1
0478:             */
0479:            protected List getAdaptableContributors(String adapterType) {
0480:                List adaptableList = null;
0481:                // Lookup the results in the cache first, there are two caches
0482:                // one that stores non-adapter contributions and the other
0483:                // contains adapter contributions.
0484:                if (adaptableLookup != null) {
0485:                    adaptableList = (List) adaptableLookup.get(adapterType);
0486:                }
0487:                if (adaptableList == null) {
0488:                    // ignore resource adapters because these must be adapted via the
0489:                    // IContributorResourceAdapter.
0490:                    if (LegacyResourceSupport.isResourceType(adapterType)
0491:                            || LegacyResourceSupport
0492:                                    .isResourceMappingType(adapterType)) {
0493:                        adaptableList = Collections.EMPTY_LIST;
0494:                    } else {
0495:                        adaptableList = (List) contributors.get(adapterType);
0496:                        if (adaptableList == null || adaptableList.size() == 0) {
0497:                            adaptableList = Collections.EMPTY_LIST;
0498:                        } else {
0499:                            adaptableList = Collections
0500:                                    .unmodifiableList(filterOnlyAdaptableContributors(adaptableList));
0501:                        }
0502:                    }
0503:                    cacheAdaptableLookup(adapterType, adaptableList);
0504:                }
0505:                return adaptableList;
0506:            }
0507:
0508:            /**
0509:             * Prunes from the list of adapters type names that are in the class
0510:             * search order of every class in <code>results</code>.  
0511:             * @param adapters
0512:             * @param results
0513:             * @since 3.1
0514:             */
0515:            protected void removeCommonAdapters(List adapters, List results) {
0516:                for (Iterator it = results.iterator(); it.hasNext();) {
0517:                    Class clazz = ((Class) it.next());
0518:                    List commonTypes = computeCombinedOrder(clazz);
0519:                    for (Iterator it2 = commonTypes.iterator(); it2.hasNext();) {
0520:                        Class type = (Class) it2.next();
0521:                        adapters.remove(type.getName());
0522:                    }
0523:                }
0524:            }
0525:
0526:            /**
0527:             * Returns the class search order starting with <code>extensibleClass</code>.
0528:             * The search order is defined in this class' comment.
0529:             */
0530:            protected List computeCombinedOrder(Class inputClass) {
0531:                List result = new ArrayList(4);
0532:                Class clazz = inputClass;
0533:                while (clazz != null) {
0534:                    // add the class
0535:                    result.add(clazz);
0536:                    // add all the interfaces it implements
0537:                    Class[] interfaces = clazz.getInterfaces();
0538:                    for (int i = 0; i < interfaces.length; i++) {
0539:                        result.add(interfaces[i]);
0540:                    }
0541:                    // get the superclass
0542:                    clazz = clazz.getSuperclass();
0543:                }
0544:                return result;
0545:            }
0546:
0547:            private List filterOnlyAdaptableContributors(List contributors) {
0548:                List adaptableContributors = null;
0549:                for (Iterator it = contributors.iterator(); it.hasNext();) {
0550:                    IObjectContributor c = (IObjectContributor) it.next();
0551:                    if (c.canAdapt()) {
0552:                        if (adaptableContributors == null) {
0553:                            adaptableContributors = new ArrayList();
0554:                        }
0555:                        adaptableContributors.add(c);
0556:                    }
0557:                }
0558:                return adaptableContributors == null ? Collections.EMPTY_LIST
0559:                        : adaptableContributors;
0560:            }
0561:
0562:            /* (non-Javadoc)
0563:             * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
0564:             */
0565:            public void removeExtension(IExtension source, Object[] objects) {
0566:                for (int i = 0; i < objects.length; i++) {
0567:                    if (objects[i] instanceof  ContributorRecord) {
0568:                        ContributorRecord contributorRecord = (ContributorRecord) objects[i];
0569:                        unregisterContributor((contributorRecord).contributor,
0570:                                (contributorRecord).objectClassName);
0571:                        contributorRecordSet.remove(contributorRecord);
0572:                    }
0573:                }
0574:            }
0575:
0576:            /**
0577:             * Remove listeners and dispose of this manager.
0578:             * 
0579:             * @since 3.1
0580:             */
0581:            public void dispose() {
0582:                if (canHandleExtensionTracking()) {
0583:                    PlatformUI.getWorkbench().getExtensionTracker()
0584:                            .unregisterHandler(this );
0585:                }
0586:            }
0587:
0588:            /**
0589:             * Returns the list of contributors that are interested in the 
0590:             * given list of model elements.
0591:             * @param elements a list of model elements (<code>Object</code>)
0592:             * @return the list of interested contributors (<code>IObjectContributor</code>)
0593:             */
0594:            protected List getContributors(List elements) {
0595:                // Calculate the common class, interfaces, and adapters registered
0596:                // via the IAdapterManager.
0597:                List commonAdapters = new ArrayList();
0598:                List commonClasses = getCommonClasses(elements, commonAdapters);
0599:
0600:                // Get the resource class. It will be null if any of the
0601:                // elements are resources themselves or do not adapt to
0602:                // IResource.
0603:                Class resourceClass = getCommonResourceClass(elements);
0604:                Class resourceMappingClass = getResourceMappingClass(elements);
0605:
0606:                // Get the contributors.   
0607:
0608:                List contributors = new ArrayList();
0609:
0610:                // Add the resource contributions to avoid duplication
0611:                if (resourceClass != null) {
0612:                    addAll(contributors, getResourceContributors(resourceClass));
0613:                }
0614:                if (commonClasses != null && !commonClasses.isEmpty()) {
0615:                    for (int i = 0; i < commonClasses.size(); i++) {
0616:                        List results = getObjectContributors((Class) commonClasses
0617:                                .get(i));
0618:                        addAll(contributors, results);
0619:                    }
0620:                }
0621:                // Add the resource mappings explicitly to avoid possible duplication
0622:                if (resourceMappingClass == null) {
0623:                    // Still show the menus if the object is not adaptable but the adapter manager
0624:                    // has an entry for it
0625:                    resourceMappingClass = LegacyResourceSupport
0626:                            .getResourceMappingClass();
0627:                    if (resourceMappingClass != null
0628:                            && commonAdapters.contains(resourceMappingClass
0629:                                    .getName())) {
0630:                        addAll(contributors,
0631:                                getResourceContributors(resourceMappingClass));
0632:                    }
0633:                } else {
0634:                    contributors
0635:                            .addAll(getResourceContributors(resourceMappingClass));
0636:                }
0637:                if (!commonAdapters.isEmpty()) {
0638:                    for (Iterator it = commonAdapters.iterator(); it.hasNext();) {
0639:                        String adapter = (String) it.next();
0640:                        addAll(contributors, getAdaptableContributors(adapter));
0641:                    }
0642:                }
0643:
0644:                // Remove duplicates.  Note: this -must- maintain the element order to preserve menu order.
0645:                contributors = removeDups(contributors);
0646:
0647:                return contributors.isEmpty() ? Collections.EMPTY_LIST
0648:                        : new ArrayList(contributors);
0649:            }
0650:
0651:            /**
0652:             * Adds all items in toAdd to the given collection.  Optimized to avoid creating an iterator.
0653:             * This assumes that toAdd is efficient to index (i.e. it's an ArrayList or some other RandomAccessList),
0654:             * which is the case for all uses in this class.
0655:             */
0656:            private static void addAll(Collection collection, List toAdd) {
0657:                for (int i = 0, size = toAdd.size(); i < size; ++i) {
0658:                    collection.add(toAdd.get(i));
0659:                }
0660:            }
0661:
0662:            /**
0663:             * Removes duplicates from the given list, preserving order.
0664:             */
0665:            private static List removeDups(List list) {
0666:                if (list.size() <= 1) {
0667:                    return list;
0668:                }
0669:                HashSet set = new HashSet(list);
0670:                if (set.size() == list.size()) {
0671:                    return list;
0672:                }
0673:                ArrayList result = new ArrayList(set.size());
0674:                for (Iterator i = list.iterator(); i.hasNext();) {
0675:                    Object o = i.next();
0676:                    if (set.remove(o)) {
0677:                        result.add(o);
0678:                    }
0679:                }
0680:                return result;
0681:            }
0682:
0683:            /**
0684:             * Returns the common denominator class, interfaces, and adapters 
0685:             * for the given collection of objects.
0686:             */
0687:            private List getCommonClasses(List objects, List commonAdapters) {
0688:                if (objects == null || objects.size() == 0) {
0689:                    return null;
0690:                }
0691:
0692:                // Optimization: if n==1 (or if all objects are of the same class), then the common class is the object's class,
0693:                // and the common adapters are the adapters cached for that class in the adapter manager
0694:                // See bug 177592 for more details.
0695:                if (allSameClass(objects)) {
0696:
0697:                    Class clazz = objects.get(0).getClass();
0698:                    commonAdapters.addAll(Arrays.asList(Platform
0699:                            .getAdapterManager().computeAdapterTypes(clazz)));
0700:                    List result = new ArrayList(1);
0701:                    result.add(clazz);
0702:                    return result;
0703:                }
0704:
0705:                // Compute all the super classes, interfaces, and adapters 
0706:                // for the first element.
0707:                List classes = computeClassOrder(objects.get(0).getClass());
0708:                List adapters = computeAdapterOrder(classes);
0709:                List interfaces = computeInterfaceOrder(classes);
0710:
0711:                // Cache of all types found in the selection - this is needed
0712:                // to compute common adapters.
0713:                List lastCommonTypes = new ArrayList();
0714:
0715:                boolean classesEmpty = classes.isEmpty();
0716:                boolean interfacesEmpty = interfaces.isEmpty();
0717:
0718:                // Traverse the selection if there is more than one element selected.
0719:                for (int i = 1; i < objects.size(); i++) {
0720:                    // Compute all the super classes for the current element
0721:                    List otherClasses = computeClassOrder(objects.get(i)
0722:                            .getClass());
0723:                    if (!classesEmpty) {
0724:                        classesEmpty = extractCommonClasses(classes,
0725:                                otherClasses);
0726:                    }
0727:
0728:                    // Compute all the interfaces for the current element
0729:                    // and all of its super classes.
0730:                    List otherInterfaces = computeInterfaceOrder(otherClasses);
0731:                    if (!interfacesEmpty) {
0732:                        interfacesEmpty = extractCommonClasses(interfaces,
0733:                                otherInterfaces);
0734:                    }
0735:
0736:                    // Compute all the adapters provided for the calculated
0737:                    // classes and interfaces for this element.
0738:                    List classesAndInterfaces = new ArrayList(otherClasses);
0739:                    if (otherInterfaces != null) {
0740:                        classesAndInterfaces.addAll(otherInterfaces);
0741:                    }
0742:                    List otherAdapters = computeAdapterOrder(classesAndInterfaces);
0743:
0744:                    // Compute common adapters
0745:                    // Note here that an adapter can match a class or interface, that is
0746:                    // that an element in the selection may not adapt to a type but instead
0747:                    // be of that type.
0748:                    // If the selected classes doesn't have adapters, keep
0749:                    // adapters that match the given classes types (classes and interfaces).
0750:                    if (otherAdapters.isEmpty() && !adapters.isEmpty()) {
0751:                        removeNonCommonAdapters(adapters, classesAndInterfaces);
0752:                    } else {
0753:                        if (adapters.isEmpty()) {
0754:                            removeNonCommonAdapters(otherAdapters,
0755:                                    lastCommonTypes);
0756:                            if (!otherAdapters.isEmpty()) {
0757:                                adapters.addAll(otherAdapters);
0758:                            }
0759:                        } else {
0760:                            // Remove any adapters of the first element that
0761:                            // are not in the current element's adapter list.
0762:                            for (Iterator it = adapters.iterator(); it
0763:                                    .hasNext();) {
0764:                                String adapter = (String) it.next();
0765:                                if (!otherAdapters.contains(adapter)) {
0766:                                    it.remove();
0767:                                }
0768:                            }
0769:                        }
0770:                    }
0771:
0772:                    // Remember the common search order up to now, this is
0773:                    // used to match adapters against common classes or interfaces.
0774:                    lastCommonTypes.clear();
0775:                    lastCommonTypes.addAll(classes);
0776:                    lastCommonTypes.addAll(interfaces);
0777:
0778:                    if (interfacesEmpty && classesEmpty && adapters.isEmpty()) {
0779:                        // As soon as we detect nothing in common, just exit.
0780:                        return null;
0781:                    }
0782:                }
0783:
0784:                // Once the common classes, interfaces, and adapters are
0785:                // calculated, let's prune the lists to remove duplicates.       
0786:                ArrayList results = new ArrayList(4);
0787:                ArrayList super Classes = new ArrayList(4);
0788:                if (!classesEmpty) {
0789:                    for (int j = 0; j < classes.size(); j++) {
0790:                        if (classes.get(j) != null) {
0791:                            super Classes.add(classes.get(j));
0792:                        }
0793:                    }
0794:                    // Just keep the first super class
0795:                    if (!super Classes.isEmpty()) {
0796:                        results.add(super Classes.get(0));
0797:                    }
0798:                }
0799:
0800:                if (!interfacesEmpty) {
0801:                    removeCommonInterfaces(super Classes, interfaces, results);
0802:                }
0803:
0804:                // Remove adapters already included as common classes
0805:                if (!adapters.isEmpty()) {
0806:                    removeCommonAdapters(adapters, results);
0807:                    commonAdapters.addAll(adapters);
0808:                }
0809:                return results;
0810:            }
0811:
0812:            /**
0813:             * Returns <code>true</code> if all objects in the given list are of the same class,
0814:             * <code>false</code> otherwise.
0815:             */
0816:            private boolean allSameClass(List objects) {
0817:                int size = objects.size();
0818:                if (size <= 1)
0819:                    return true;
0820:                Class clazz = objects.get(0).getClass();
0821:                for (int i = 1; i < size; ++i) {
0822:                    if (!objects.get(i).getClass().equals(clazz)) {
0823:                        return false;
0824:                    }
0825:                }
0826:                return true;
0827:            }
0828:
0829:            private boolean extractCommonClasses(List classes, List otherClasses) {
0830:                boolean classesEmpty = true;
0831:                if (otherClasses.isEmpty()) {
0832:                    // When no super classes, then it is obvious there
0833:                    // are no common super classes with the first element
0834:                    // so clear its list.
0835:                    classes.clear();
0836:                } else {
0837:                    // Remove any super classes of the first element that 
0838:                    // are not in the current element's super classes list.
0839:                    for (int j = 0; j < classes.size(); j++) {
0840:                        if (classes.get(j) != null) {
0841:                            classesEmpty = false; // TODO: should this only be set if item not nulled out?
0842:                            if (!otherClasses.contains(classes.get(j))) {
0843:                                classes.set(j, null);
0844:                            }
0845:                        }
0846:                    }
0847:                }
0848:                return classesEmpty;
0849:            }
0850:
0851:            private void removeNonCommonAdapters(List adapters, List classes) {
0852:                for (int i = 0; i < classes.size(); i++) {
0853:                    Object o = classes.get(i);
0854:                    if (o != null) {
0855:                        Class clazz = (Class) o;
0856:                        String name = clazz.getName();
0857:                        if (adapters.contains(name)) {
0858:                            return;
0859:                        }
0860:                    }
0861:                }
0862:                adapters.clear();
0863:            }
0864:
0865:            private void removeCommonInterfaces(List super Classes, List types,
0866:                    List results) {
0867:                List dropInterfaces = null;
0868:                if (!super Classes.isEmpty()) {
0869:                    dropInterfaces = computeInterfaceOrder(super Classes);
0870:                }
0871:                for (int j = 0; j < types.size(); j++) {
0872:                    if (types.get(j) != null) {
0873:                        if (dropInterfaces != null
0874:                                && !dropInterfaces.contains(types.get(j))) {
0875:                            results.add(types.get(j));
0876:                        }
0877:                    }
0878:                }
0879:            }
0880:
0881:            private List computeAdapterOrder(List classList) {
0882:                Set result = new HashSet(4);
0883:                IAdapterManager adapterMgr = Platform.getAdapterManager();
0884:                for (Iterator list = classList.iterator(); list.hasNext();) {
0885:                    Class clazz = ((Class) list.next());
0886:                    String[] adapters = adapterMgr.computeAdapterTypes(clazz);
0887:                    for (int i = 0; i < adapters.length; i++) {
0888:                        String adapter = adapters[i];
0889:                        if (!result.contains(adapter)) {
0890:                            result.add(adapter);
0891:                        }
0892:                    }
0893:                }
0894:                return new ArrayList(result);
0895:            }
0896:
0897:            /**
0898:             * Returns the common denominator resource class for the given
0899:             * collection of objects.
0900:             * Do not return a resource class if the objects are resources
0901:             * themselves so as to prevent double registration of actions.
0902:             */
0903:            private Class getCommonResourceClass(List objects) {
0904:                if (objects == null || objects.size() == 0) {
0905:                    return null;
0906:                }
0907:                Class resourceClass = LegacyResourceSupport.getResourceClass();
0908:                if (resourceClass == null) {
0909:                    // resources plug-in not loaded - no resources. period.
0910:                    return null;
0911:                }
0912:
0913:                List testList = new ArrayList(objects.size());
0914:
0915:                for (int i = 0; i < objects.size(); i++) {
0916:                    Object object = objects.get(i);
0917:
0918:                    if (object instanceof  IAdaptable) {
0919:                        if (resourceClass.isInstance(object)) {
0920:                            continue;
0921:                        }
0922:
0923:                        Object resource = LegacyResourceSupport
0924:                                .getAdaptedContributorResource(object);
0925:
0926:                        if (resource == null) {
0927:                            //Not a resource and does not adapt. No common resource class
0928:                            return null;
0929:                        }
0930:                        testList.add(resource);
0931:                    } else {
0932:                        return null;
0933:                    }
0934:                }
0935:
0936:                return getCommonClass(testList);
0937:            }
0938:
0939:            /**
0940:             * Return the ResourceMapping class if the elements all adapt to it.
0941:             */
0942:            private Class getResourceMappingClass(List objects) {
0943:                if (objects == null || objects.size() == 0) {
0944:                    return null;
0945:                }
0946:                Class resourceMappingClass = LegacyResourceSupport
0947:                        .getResourceMappingClass();
0948:                if (resourceMappingClass == null) {
0949:                    // resources plug-in not loaded - no resources. period.
0950:                    return null;
0951:                }
0952:
0953:                for (int i = 0; i < objects.size(); i++) {
0954:                    Object object = objects.get(i);
0955:
0956:                    if (object instanceof  IAdaptable) {
0957:                        if (resourceMappingClass.isInstance(object)) {
0958:                            continue;
0959:                        }
0960:
0961:                        Object resourceMapping = LegacyResourceSupport
0962:                                .getAdaptedContributorResourceMapping(object);
0963:
0964:                        if (resourceMapping == null) {
0965:                            //Not a resource and does not adapt. No common resource class
0966:                            return null;
0967:                        }
0968:                    } else {
0969:                        return null;
0970:                    }
0971:                }
0972:                // If we get here then all objects adapt to ResourceMapping
0973:                return resourceMappingClass;
0974:            }
0975:
0976:            /**
0977:             * Returns the common denominator class for the given
0978:             * collection of objects.
0979:             */
0980:            private Class getCommonClass(List objects) {
0981:                if (objects == null || objects.size() == 0) {
0982:                    return null;
0983:                }
0984:                Class commonClass = objects.get(0).getClass();
0985:                // try easy
0986:                if (objects.size() == 1) {
0987:                    return commonClass;
0988:                    // try harder
0989:                }
0990:
0991:                for (int i = 1; i < objects.size(); i++) {
0992:                    Object object = objects.get(i);
0993:                    Class newClass = object.getClass();
0994:                    // try the short cut
0995:                    if (newClass.equals(commonClass)) {
0996:                        continue;
0997:                    }
0998:                    // compute common class
0999:                    commonClass = getCommonClass(commonClass, newClass);
1000:                    // give up
1001:                    if (commonClass == null) {
1002:                        return null;
1003:                    }
1004:                }
1005:                return commonClass;
1006:            }
1007:
1008:            /**
1009:             * Returns the common denominator class for
1010:             * two input classes.
1011:             */
1012:            private Class getCommonClass(Class class1, Class class2) {
1013:                List list1 = computeCombinedOrder(class1);
1014:                List list2 = computeCombinedOrder(class2);
1015:                for (int i = 0; i < list1.size(); i++) {
1016:                    for (int j = 0; j < list2.size(); j++) {
1017:                        Class candidate1 = (Class) list1.get(i);
1018:                        Class candidate2 = (Class) list2.get(j);
1019:                        if (candidate1.equals(candidate2)) {
1020:                            return candidate1;
1021:                        }
1022:                    }
1023:                }
1024:                // no common class
1025:                return null;
1026:            }
1027:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.