| /********************************************************************** |
| * This file is part of "Object Teams Development Tooling"-Software |
| * |
| * Copyright 2010 GK Software AG |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * $Id$ |
| * |
| * Please visit http://www.eclipse.org/objectteams for updates and contact. |
| * |
| * Contributors: |
| * Stephan Herrmann - Initial API and implementation |
| **********************************************************************/ |
| package org.eclipse.objectteams.otdt.core.hierarchy; |
| |
| import java.util.HashSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.internal.compiler.env.IGenericType; |
| import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
| import org.eclipse.jdt.internal.core.JavaModelStatus; |
| import org.eclipse.objectteams.otdt.core.IOTType; |
| import org.eclipse.objectteams.otdt.core.OTModelManager; |
| |
| // both base type and directly used: |
| import org.eclipse.jdt.core.IType; |
| |
| import base org.eclipse.jdt.internal.core.BinaryType; |
| import base org.eclipse.jdt.internal.core.SourceType; |
| import base org.eclipse.jdt.internal.core.hierarchy.HierarchyBuilder; |
| import base org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy; |
| import base org.eclipse.objectteams.otdt.core.PhantomType; |
| import base org.eclipse.objectteams.otdt.internal.core.OTType; |
| |
| /** |
| * Adapt the regular Java TypeHierarchy as to handle implicit inheritance, too. |
| * |
| * |
| * @author stephan |
| */ |
| @SuppressWarnings("restriction") |
| public team class OTTypeHierarchies { |
| |
| /** How does a given type relate to the focus type? */ |
| enum FocusRelation { |
| /** a type is a subtype of the focus type. */ |
| BELOW, |
| /** a type is the focus type itself. */ |
| EQUAL, |
| /** a type is a supertype of the focus type. */ |
| ABOVE, |
| /** a type is neither sub- nor supertype of the focus type. */ |
| UNRELATED; |
| |
| public static FocusRelation compute(ReferenceBinding focusType, ReferenceBinding typeBinding) { |
| if (focusType.isRole()) |
| focusType = focusType.getRealType(); |
| if (typeBinding.isRole()) |
| typeBinding = typeBinding.getRealType(); |
| if (focusType.equals(typeBinding)) return EQUAL; |
| if (focusType.isCompatibleWith(typeBinding)) return ABOVE; |
| if (typeBinding.isCompatibleWith(focusType)) return BELOW; |
| return UNRELATED; |
| } |
| } |
| |
| private static final IType[] NO_TYPE = new IType[0]; |
| |
| // === singleton infrastructure: === |
| |
| private static OTTypeHierarchies instance; |
| public OTTypeHierarchies() { |
| instance = this; |
| } |
| /** Get the singleton instance of this team, which was created and activated by OT/Equinox. */ |
| public static OTTypeHierarchies getInstance() { return instance; } |
| |
| |
| /** |
| * The stateful part of this team, implemented as a nested team. |
| */ |
| protected team class OTTypeHierarchy playedBy TypeHierarchy |
| { |
| // === "Imports" (callout) from plain TypeHierarchy: === |
| |
| @SuppressWarnings("decapsulation") IType getFocusType() -> get IType focusType; |
| ConnectedType getSuperclass(IType type) -> IType getSuperclass(IType type); |
| ConnectedType[] getAllSuperclassesUnfiltered(IType type) -> IType[] getAllSuperclasses(IType type); |
| IType[] getSuperInterfaces(IType type) -> IType[] getSuperInterfaces(IType type); |
| IType[] getAllSuperInterfaces(IType type) -> IType[] getAllSuperInterfaces(IType type); |
| |
| |
| // === Adapt TypeHierarchy (callin bindings): === |
| |
| precedence unwrapping, filtering1, superlinearize; // order: outer callins unwrap and filter, inner callin performs computation |
| precedence filtering2, tsuperadding; |
| |
| // --- considure implicit inheritance for some queries: ---- |
| |
| // make getSuperclass() traverse the superclass linearization of the focus type: |
| superlinearize: |
| ConnectedType getSuperclassLinearized(ConnectedType type) <- replace IType getSuperclass(IType type); |
| |
| // augment original queries to capture tsub-types, too: |
| @SuppressWarnings("decapsulation") |
| addTSubs <- replace getSubtypesForType; // adjust internal method as to capture calls from getAllSubtypes(IType), too. |
| tsuperadding: |
| addTSubs <- replace getSubclasses; |
| |
| // --- filtering (duplicates and phantoms) and unwrapping (OTTypes): --- |
| |
| // make some methods aware of our phantom mode: |
| filtering1: |
| ConnectedType[] phantomFilterWrapper() |
| <- replace |
| IType[] getAllClasses(), |
| IType[] getImplementingClasses(IType type), |
| IType[] getAllSuperclasses(IType type) |
| when (!this.phantomMode); |
| |
| // filter intermediate results only at these top-level queries: |
| filtering2: |
| filterDuplicatesAndPhantoms <- replace getSubclasses, getSubtypes, getAllSubtypes, getImplementingClasses; // includes unwrapping of OTTypes |
| |
| // all top-level queries unwrap and given OTTypes: |
| unwrapping: |
| ensureJavaType <- replace getAllSuperclasses, getAllSuperInterfaces, getAllSupertypes, |
| getCachedFlags, getExtendingInterfaces, |
| getSuperclass, getSuperInterfaces, getSupertypes; |
| |
| /** |
| * This role adds to ITypes the capability of connecting to all direct and indirect tsuper types, |
| * which includes linearization of all super types (implicit & explicit). |
| */ |
| @SuppressWarnings("abstractrelevantrole") |
| protected abstract class ConnectedType playedBy IType |
| { |
| /** Is this type a phantom role? */ |
| protected boolean isPhantom; |
| |
| /** The direct tsuper types of this type. */ |
| protected ConnectedType[] directTSupers; |
| |
| /** All direct & indirect tsuper classes in a linearized form. All classes in this list have the same simple name. */ |
| protected List<ConnectedType> allTSupersLinearized; |
| |
| /** This type's relation to the focus type. */ |
| private FocusRelation focusRelation; |
| |
| // the last item in allTSupersLinearized, used as a token for switching from implicit to explicit supers |
| private ConnectedType lastTSuper = null; |
| |
| /** the root of the tsuper chain through which this connected type was reached. */ |
| protected ConnectedType tsuperChainRoot; |
| |
| /** All known direct tsub types of this type. */ |
| protected Set<ConnectedType> knownTSubTypes; |
| |
| |
| protected ConnectedType(IType type) { |
| this.tsuperChainRoot = this; |
| } |
| |
| public void init(boolean isPhantom, ConnectedType[] tsuperclassHandles, FocusRelation focusRelation) { |
| this.isPhantom = isPhantom; |
| this.directTSupers = tsuperclassHandles; |
| this.focusRelation = focusRelation; |
| } |
| |
| /** Combine indirect tsuper classes into the list of all linearized tsuper types. */ |
| @SuppressWarnings("ambiguouslowering") // method contains takes an Object argument |
| public void combineTSupers(ConnectedType focusLayerType, ConnectedType[] tsuperclassHandles) { |
| this.tsuperChainRoot = focusLayerType.tsuperChainRoot; |
| if (this.allTSupersLinearized == null) |
| this.allTSupersLinearized = new LinkedList<ConnectedType>(); |
| for (ConnectedType type : tsuperclassHandles) |
| if (!this.allTSupersLinearized.contains(type)) |
| this.allTSupersLinearized.add(type); |
| } |
| |
| /** Get the next type in the tsuper linearization. */ |
| protected ConnectedType getTSuperType() { |
| if (this.focusRelation == FocusRelation.BELOW) { |
| // only follow the path towards the focus type: |
| if (this.directTSupers != null) |
| for (ConnectedType directTSuper : this.directTSupers) |
| if (directTSuper.focusRelation == FocusRelation.EQUAL || directTSuper.focusRelation == FocusRelation.BELOW) |
| return directTSuper; |
| return null; // no tsuper leading to focus |
| } |
| // shortcut if no tsupers: |
| if (this.allTSupersLinearized == null || this.allTSupersLinearized.size() == 0) |
| return null; |
| // when starting from the focus layer return the first tsuper role: |
| if (isInFocusLayer(this)) |
| return this.allTSupersLinearized.get(0); |
| // when type is contained in the list of tsuperRoles return the next tsuper role from the list |
| for (int i = 0; i < this.allTSupersLinearized.size()-1; i++) |
| if (this.allTSupersLinearized.get(i) == this) |
| return this.allTSupersLinearized.get(i+1); |
| return null; // end reached |
| } |
| |
| /** Is this the last element in the list of tsuper roles? */ |
| protected boolean isLastTSuper() { |
| if (this.allTSupersLinearized == null || this.allTSupersLinearized.size() == 0) // optimize: don's store empty list? |
| return false; |
| if (this.lastTSuper == null) |
| this.lastTSuper = this.allTSupersLinearized.get(this.allTSupersLinearized.size()-1); |
| return this.lastTSuper == this; |
| } |
| |
| /** If this is a phantom type, get the real tsuper class that this is derived (copied) from. */ |
| protected ConnectedType getRealTSuper() throws JavaModelException { |
| if (!isPhantom) |
| return this; |
| if (this.allTSupersLinearized != null) |
| for(ConnectedType other : this.allTSupersLinearized) |
| if (!other.isPhantom) |
| return other; |
| throw new JavaModelException(new JavaModelStatus(JavaModelStatus.ERROR, this, "no non-phantom type found in allTSupersLinearized")); //$NON-NLS-1$ |
| } |
| |
| /** Get all tsuper types yet respecting phantom mode. */ |
| protected ConnectedType[] getAllTSuperTypes() |
| { |
| if (this.focusRelation == FocusRelation.BELOW && this.directTSupers != null) { |
| // special handling for types below the focus: transitively collect tsupers: |
| ConnectedType direct = getTSuperType(); // only the one path towards focus |
| if (direct == null) |
| return new ConnectedType[0]; |
| ConnectedType[] indirect = direct.getAllTSuperTypes(); // NB: recursion may enter the focus cone |
| if (indirect == null) |
| return new ConnectedType[] {direct}; |
| // merge direct and indirect: |
| int len = indirect.length; |
| ConnectedType[] result = new ConnectedType[len+1]; |
| result[0] = direct; |
| System.arraycopy(indirect, 0, result, 1, len); |
| return result; |
| } |
| |
| int size; |
| if (this.allTSupersLinearized != null && (size = this.allTSupersLinearized.size()) > 0) |
| { |
| // focus level => all types from the linearization: |
| if (isInFocusLayer(this)) |
| return this.allTSupersLinearized.toArray(new ConnectedType[size]); |
| |
| // not focus, search in linearization for this type ... |
| int skip = 0; |
| boolean found = false; |
| while (skip < size) |
| if (this.allTSupersLinearized.get(skip++) == this) { |
| found = true; |
| break; |
| } |
| if (found) { // .. and take the tail after this type: |
| if (skip < size) { // if found at last pos, there's no tail |
| ConnectedType[] result = new ConnectedType[size-skip]; |
| for (int i=0; skip<size;) |
| result[i++] = this.allTSupersLinearized.get(skip++); |
| return result; |
| } |
| } |
| } |
| return new ConnectedType[0]; |
| } |
| |
| /** Register a known tsub type of this type. */ |
| protected void addTSubType(ConnectedType tsub) { |
| if (this.knownTSubTypes == null) |
| this.knownTSubTypes = new HashSet<ConnectedType>(); |
| this.knownTSubTypes.add(tsub); |
| } |
| |
| toString => toString; // for debugging |
| |
| } |
| // binding source variant of IType |
| protected class ConnectedSourceType extends ConnectedType playedBy SourceType { /*just class binding, no details*/ } |
| |
| // binding binary variant of IType |
| protected class ConnectedBinaryType extends ConnectedType playedBy BinaryType { /*just class binding, no details*/ } |
| |
| // binding binary variant of IType |
| protected class ConnectedPhantomType extends ConnectedType playedBy PhantomType { /*just class binding, no details*/ } |
| |
| // binding binary variant of IType |
| protected class ConnectedOTType extends ConnectedType playedBy OTType { /*just class binding, no details*/ } |
| |
| // === start main part of nested team OTTypeHierarchy === |
| |
| /** Should the hierarchy show phantom roles? */ |
| protected boolean phantomMode; |
| |
| /** |
| * Connect the found tsuper classes into the connected type for the given type. |
| */ |
| protected void connectTSupers(IType as ConnectedType connectedType, |
| boolean isPhantom, |
| IType as ConnectedType tsuperclassHandles[], |
| boolean[] arePhantoms, |
| FocusRelation focusRelation) |
| { |
| connectedType.init(isPhantom, tsuperclassHandles, focusRelation); |
| |
| // connect tsuperclassHandles into the appropriate ConnectedType: |
| switch (focusRelation) { |
| case EQUAL: |
| connectedType.allTSupersLinearized = new LinkedList<ConnectedType>(); |
| for (int i = 0; i < tsuperclassHandles.length; i++) |
| connectedType.allTSupersLinearized.add(tsuperclassHandles[i]); |
| break; |
| case ABOVE: |
| ConnectedType focusLayerType = connectedType.tsuperChainRoot; |
| focusLayerType.combineTSupers(focusLayerType, tsuperclassHandles); |
| connectedType.allTSupersLinearized = focusLayerType.allTSupersLinearized; // share the same list |
| break; |
| case BELOW: |
| // don't merge into focus' up-chain |
| break; |
| default: // UNRELATED |
| // if (isInFocusLayer(connectedType)) { |
| // connectedType.allTSupersLinearized = new LinkedList<ConnectedType>(); |
| // for (int i = 0; i < tsuperclassHandles.length; i++) |
| // connectedType.allTSupersLinearized.add(tsuperclassHandles[i]); |
| // } |
| // otherwise shouldn't be relevant? |
| } |
| // connect each in tsuperclassHandles back to the tsuperChainRoot: |
| for (int i = 0; i < tsuperclassHandles.length; i++) { |
| if (focusRelation == FocusRelation.EQUAL || focusRelation == FocusRelation.ABOVE) |
| tsuperclassHandles[i].tsuperChainRoot = connectedType.tsuperChainRoot; |
| tsuperclassHandles[i].isPhantom = arePhantoms[i]; |
| // and remember the type-tsub link: |
| tsuperclassHandles[i].addTSubType(connectedType); |
| } |
| } |
| |
| boolean isInFocusLayer(IType type) { |
| IType focusType = getFocusType(); |
| if (type.equals(focusType)) |
| return true; |
| return focusType.getParent().equals(type.getParent()); // FIXME(SH) elaborate more |
| } |
| |
| boolean isStrictlyBelowFocusType(IType type) { |
| IType focusType = getFocusType(); |
| if (focusType.equals(type)) |
| return false; |
| return isBelowFocusType(focusType, type); |
| } |
| |
| private boolean isBelowFocusType(IType focusType, IType type) { |
| if (focusType.equals(type)) |
| return true; |
| return false; |
| } |
| |
| /** Given that 'type' is element of a superclass linearization return the next super in the chain. */ |
| @SuppressWarnings("basecall") |
| callin ConnectedType getSuperclassLinearized(ConnectedType type) { |
| // check for tsuper type in the computed list: |
| ConnectedType tsuperType = type.getTSuperType(); |
| if (tsuperType != null) |
| return tsuperType; |
| // if type is the last in the list ... |
| if (type.isLastTSuper()) { |
| // ...we're done with tsupers, start over with super of the focus level type: |
| return base.getSuperclassLinearized(type.tsuperChainRoot); |
| } |
| return base.getSuperclassLinearized(type); |
| } |
| |
| // ==== handling for phantom mode: ==== |
| |
| ConnectedType[] maybeSubstitutePhantoms(ConnectedType[] roles) throws JavaModelException { |
| if (this.phantomMode) |
| return roles; |
| ConnectedType[] substituted = new ConnectedType[roles.length]; |
| for (int i = 0; i < roles.length; i++) |
| substituted[i] = roles[i].getRealTSuper(); |
| return substituted; |
| } |
| |
| protected ConnectedType[] filterPhantomRoles(ConnectedType[] roles) { |
| ConnectedType[] substituted = new ConnectedType[roles.length]; |
| int n = 0; |
| for (int i = 0; i < roles.length; i++) |
| if (!roles[i].isPhantom) |
| substituted[n++] = roles[i]; |
| if (n<roles.length) |
| System.arraycopy(substituted, 0, substituted=new ConnectedType[n], 0, n); |
| return substituted; |
| } |
| |
| // wrappers for use in multiple callin bindings |
| callin ConnectedType[] phantomFilterWrapper() { |
| return filterPhantomRoles(base.phantomFilterWrapper()); |
| } |
| |
| callin ConnectedType[] filterDuplicatesAndPhantoms(IType type) { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| return filterDupsAndPhants(base.filterDuplicatesAndPhantoms(type)); |
| } |
| |
| protected ConnectedType[] filterDupsAndPhants(ConnectedType[] unfiltered) { |
| if (unfiltered == null) |
| return unfiltered; |
| Set<ConnectedType> filtered = new HashSet<ConnectedType>(); |
| for(ConnectedType type : unfiltered) |
| if (this.phantomMode || !type.isPhantom) |
| filtered.add(type); |
| return filtered.toArray(new ConnectedType[filtered.size()]); |
| } |
| |
| callin void ensureJavaType(IType type) { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| base.ensureJavaType(type); |
| } |
| |
| // ==== adjusting some subtype queries for tsubs: |
| |
| callin ConnectedType[] addTSubs(ConnectedType type) { |
| ConnectedType[] res1 = base.addTSubs(type); |
| Set<ConnectedType> tsubs = type.knownTSubTypes; |
| |
| if (tsubs == null || tsubs.size() == 0) |
| return this.phantomMode ? res1 : filterDupsAndPhants(res1); |
| |
| Set<ConnectedType> result = new HashSet<ConnectedType>(); |
| result.addAll(tsubs); |
| for (ConnectedType t1 : res1) |
| result.add(t1); |
| return result.toArray(new ConnectedType[result.size()]); |
| } |
| |
| |
| // ==== queries for clients (wrapped by methods of enclosing team, see there for documentation): ==== |
| |
| protected IType[] getAllTSuperTypes(IType as ConnectedType type) { |
| ConnectedType[] result = type.getAllTSuperTypes(); |
| return this.phantomMode ? result : filterPhantomRoles(result); |
| // FIXME(SH) return without intermediate local var -> CCE |
| // like: return type.getAllTSuperTypes(); |
| } |
| |
| protected IType[] getDirectTSupers(IType as ConnectedType type) throws JavaModelException { |
| if (type.directTSupers == null) |
| return NO_TYPE; |
| return maybeSubstitutePhantoms(type.directTSupers); |
| } |
| |
| protected IType getPlainSuperclass(IType type) throws JavaModelException { |
| try { |
| OTTypeHierarchies.this.deactivate(); |
| ConnectedType result = getSuperclass(type); |
| if (this.phantomMode || result == null) |
| return result; |
| return result.getRealTSuper(); |
| } finally { |
| OTTypeHierarchies.this.activate(); |
| } |
| } |
| |
| // sole purpose of this wrapper: array-lowering |
| protected IType[] getAllSuperclasses(IType type) { |
| return getAllSuperclassesUnfiltered(type); |
| } |
| } |
| |
| /** |
| * This role adapts the HierarchyBuilder in order to record information about implicit inheritance, too. |
| */ |
| protected class OTHierarchyBuilder playedBy HierarchyBuilder { |
| |
| @SuppressWarnings("decapsulation") |
| OTTypeHierarchy getHierarchy() -> get TypeHierarchy hierarchy; |
| |
| connectTSupers <- before hookableConnect; |
| |
| private void connectTSupers(ReferenceBinding focusType, ReferenceBinding typeBinding, IGenericType type, IType typeHandle, boolean isPhantom, |
| IType superclassHandle, IType[] tsuperclassHandles, boolean[] arePhantoms, IType[] superinterfaceHandles) |
| { |
| if (tsuperclassHandles!= null) { |
| FocusRelation focusRelation = FocusRelation.compute(focusType, typeBinding); |
| getHierarchy().connectTSupers(typeHandle, isPhantom, tsuperclassHandles, arePhantoms, focusRelation); |
| } |
| } |
| } |
| |
| /** |
| * API: Query all direct and indirect implicit superclasses of the given type. |
| * If phantomMode is set to <code>false</code> any phantom roles will be filtered from the result. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super types are queried |
| * @return a non-null array of ordered implicit super classes |
| * @throws JavaModelException If the tsuper linearization is corrupt |
| */ |
| public IType[] getAllTSuperTypes(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| return otHierarchy.getAllTSuperTypes(type); |
| } |
| |
| /** |
| * API: Query all direct implicit superclasses of the given type. |
| * If phantomMode is set to <code>false</code> any phantom roles will be translated to its real origin. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super types are queried |
| * @return a non-null array of ordered implicit super classes |
| * @throws JavaModelException If the tsuper linearization is corrupt |
| */ |
| public IType[] getTSuperTypes(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| return otHierarchy.getDirectTSupers(type); |
| } |
| |
| /** |
| * API: Query all direct, implicit and explicit superclasses of the given type. |
| * If phantomMode is set to <code>false</code> any phantom roles will be substituted with their real origin. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super types are queried |
| * @return a non-null array of ordered super classes. |
| * @throws JavaModelException If the tsuper linearization is corrupt |
| */ |
| public IType[] getSuperclasses(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| // have superclass (otherwise type == java.lang.Object?) |
| IType superclass = otHierarchy.getPlainSuperclass(type); |
| if (superclass == null) |
| return NO_TYPE; |
| |
| // check direct tsupers: |
| IType[] directTSupers = getTSuperTypes(otHierarchy, type); |
| if (directTSupers == null) |
| return new IType[] { superclass }; |
| |
| // found both => merge |
| int count = directTSupers.length; |
| IType[] merged = new IType[count+1]; |
| System.arraycopy(directTSupers, 0, merged, 0, count); |
| merged[count] = superclass; |
| return merged; |
| } |
| |
| /** |
| * API: Query all direct and indirect, implicit and explicit superclasses of the given type. |
| * If phantomMode is set to <code>false</code> any phantom roles will be filtered from the result. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super types are queried |
| * @return a non-null array of ordered super classes. |
| * @throws JavaModelException if accessing type failed |
| */ |
| public IType[] getAllSuperclasses(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (type.isInterface()) |
| return NO_TYPE; |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| return otHierarchy.getAllSuperclasses(type); |
| } |
| |
| /** |
| * API: Query the explicit superclass of the given type. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super type is queried |
| * @return the superclass |
| * @throws JavaModelException If the tsuper linearization is corrupt |
| */ |
| public IType getExplicitSuperclass(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| // have superclass (otherwise type == java.lang.Object?) |
| return otHierarchy.getPlainSuperclass(type); |
| } |
| |
| /** Get ALL super types: classes and interfaces, explicit and implicit, direct and indirect. */ |
| public IType[] getAllSupertypes(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| IType[] superclasses = otHierarchy.getAllSuperclasses(type); |
| IType[] superinterfaces = otHierarchy.getAllSuperInterfaces(type); |
| int l1 = superclasses.length, l2 = superinterfaces.length; |
| IType[] result = new IType[l1+l2]; |
| System.arraycopy(superclasses, 0, result, 0, l1); |
| System.arraycopy(superinterfaces, 0, result, l1, l2); |
| return result; |
| } |
| |
| /** |
| * API: Query the superinterfaces of the given type, plus if it's a role interface the tsuper interfaces. |
| * tsuper's direct superinterfaces are also counted as direct interfaces. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super types are queried |
| * @return the superinterfaces |
| * @throws JavaModelException If the tsuper linearization is corrupt |
| */ |
| public IType[] getSuperInterfaces(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| IType[] superinterfaces = otHierarchy.getSuperInterfaces(type); |
| if (!OTModelManager.isRole(type)) |
| return superinterfaces; |
| Set<IType> all = new HashSet<IType>(); |
| for (IType iType : superinterfaces) |
| all.add(iType); |
| for (IType tsuperinterface : otHierarchy.getDirectTSupers(type)) { |
| if (type.isInterface()) // otherwise just traverse tsuper to find more super interfaces |
| all.add(tsuperinterface); |
| for (IType tsupersuper : otHierarchy.getSuperInterfaces(tsuperinterface)) |
| all.add(tsupersuper); |
| } |
| return all.toArray(new IType[all.size()]); |
| } |
| |
| /** |
| * API: Query the superinterfaces of the given type: explicit & implicit, direct & indirect. |
| * |
| * @param otHierarchy a hierarchy that has been focused on the given type |
| * @param type the focus type whose super types are queried |
| * @return the superinterfaces |
| * @throws JavaModelException If the tsuper linearization is corrupt |
| */ |
| public IType[] getAllSuperInterfaces(TypeHierarchy as OTTypeHierarchy otHierarchy, IType type) throws JavaModelException { |
| if (!OTModelManager.isRole(type)) |
| return otHierarchy.getAllSuperInterfaces(type); |
| if (type instanceof IOTType) type = (IType) ((IOTType)type).getCorrespondingJavaElement(); |
| Set<IType> all = new HashSet<IType>(); |
| getAllSuperInterfaces2(otHierarchy, type, all); |
| return all.toArray(new IType[all.size()]); |
| } |
| // recursive helper for above |
| private void getAllSuperInterfaces2(OTTypeHierarchy otHierarchy, IType seed, Set<IType> collected) throws JavaModelException { |
| for (IType tsuperinterface : otHierarchy.getAllTSuperTypes(seed)) { |
| if (seed.isInterface()) { // otherwise just traverse tsuper to find more super interfaces |
| collected.add(tsuperinterface); |
| } |
| getAllSuperInterfaces2(otHierarchy, tsuperinterface, collected); |
| } |
| for (IType superinterface : otHierarchy.getAllSuperInterfaces(seed)) { |
| collected.add(superinterface); |
| getAllSuperInterfaces2(otHierarchy, superinterface, collected); |
| } |
| } |
| |
| /** |
| * Configure whether the given hierarchy should consider phantom roles or not. |
| * Depending on the query used, phantom roles will either be filtered out or replaced with their real origins. |
| * In order for the phantom modes to be respected, the hierarchy must not be directly consulted but only |
| * via the fassade methods of this team. |
| */ |
| public void setPhantomMode(TypeHierarchy as OTTypeHierarchy otHierarchy, boolean mode) { |
| otHierarchy.phantomMode = mode; |
| } |
| } |