001: /*******************************************************************************
002: * Copyright (c) 2005, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.core;
011:
012: import org.eclipse.jdt.internal.core.util.KeyKind;
013: import org.eclipse.jdt.internal.core.util.KeyToSignature;
014:
015: /**
016: * Utility class to decode or create a binding key.
017: * <p>
018: * This class is not intended to be subclassed by clients.
019: * </p>
020: *
021: * @see org.eclipse.jdt.core.dom.IBinding#getKey()
022: * @since 3.1
023: */
024: public final class BindingKey {
025:
026: private String key;
027:
028: /**
029: * Creates a new binding key.
030: *
031: * @param key the key to decode
032: */
033: public BindingKey(String key) {
034: this .key = key;
035: }
036:
037: /**
038: * Creates a new array type binding key from the given type binding key and the given array dimension.
039: * <p>
040: * For example:
041: * <pre>
042: * <code>
043: * createArrayTypeBindingKey("Ljava/lang/Object;", 1) -> "[Ljava/lang/Object;"
044: * createArrayTypeBindingKey("I", 2) -> "[[I"
045: * </code>
046: * </pre>
047: * </p>
048: *
049: * @param typeKey the binding key of the given type
050: * @param arrayDimension the given array dimension
051: * @return a new array type binding key
052: */
053: public static String createArrayTypeBindingKey(String typeKey,
054: int arrayDimension) {
055: // Note this implementation is heavily dependent on ArrayTypeBinding#computeUniqueKey()
056: StringBuffer buffer = new StringBuffer();
057: while (arrayDimension-- > 0)
058: buffer.append('[');
059: buffer.append(typeKey);
060: return buffer.toString();
061: }
062:
063: /**
064: * Creates a new parameterized type binding key from the given generic type binding key and the given argument type binding keys.
065: * If the argument type keys array is empty, then a raw type binding key is created.
066: * <p>
067: * For example:
068: * <pre>
069: * <code>
070: * createParameterizedTypeBindingKey(
071: * "Ljava/util/Map<TK;TV;>;",
072: * new String[] {"Ljava/lang/String;", "Ljava/lang/Object;"}) ->
073: * "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;"
074: * createParameterizedTypeBindingKey(
075: * "Ljava/util/List<TE;>;", new String[] {}) ->
076: * "Ljava/util/List<>;"
077: * </code>
078: * </pre>
079: * </p>
080: *
081: * @param genericTypeKey the binding key of the generic type
082: * @param argumentTypeKeys the possibly empty list of binding keys of argument types
083: * @return a new parameterized type binding key
084: */
085: public static String createParameterizedTypeBindingKey(
086: String genericTypeKey, String[] argumentTypeKeys) {
087: // Note this implementation is heavily dependent on ParameterizedTypeBinding#computeUniqueKey() and its subclasses
088: StringBuffer buffer = new StringBuffer();
089: buffer.append(Signature.getTypeErasure(genericTypeKey));
090: buffer.insert(buffer.length() - 1, '<');
091: for (int i = 0, length = argumentTypeKeys.length; i < length; i++) {
092: String argumentTypeKey = argumentTypeKeys[i];
093: buffer.insert(buffer.length() - 1, argumentTypeKey);
094: }
095: buffer.insert(buffer.length() - 1, '>');
096: return buffer.toString();
097: }
098:
099: /**
100: * Creates a new type binding key from the given type name. The type name must be either
101: * a fully qualified name, an array type name or a primitive type name.
102: * If the type name is fully qualified, then it is expected to be dot-based.
103: * Note that inner types, generic types and parameterized types are not supported.
104: * <p>
105: * For example:
106: * <pre>
107: * <code>
108: * createTypeBindingKey("int") -> "I"
109: * createTypeBindingKey("java.lang.String") -> "Ljava/lang/String;"
110: * createTypeBindingKey("boolean[]") -> "[Z"
111: * </code>
112: * </pre>
113: * </p>
114: *
115: * @param typeName the possibly qualified type name
116: * @return a new type binding key
117: */
118: public static String createTypeBindingKey(String typeName) {
119: // Note this implementation is heavily dependent on TypeBinding#computeUniqueKey() and its subclasses
120: return Signature.createTypeSignature(
121: typeName.replace('.', '/'), true/*resolved*/);
122: }
123:
124: /**
125: * Creates a new type variable binding key from the given type variable name and the given declaring key.
126: * The declaring key can either be a type binding key or a method binding key.
127: * <p>
128: * For example:
129: * <pre>
130: * <code>
131: * createTypeVariableBindingKey("T", "Ljava/util/List<TE;>;") ->
132: * "Ljava/util/List<TE;>;:TT;"
133: * createTypeVariableBindingKey("SomeTypeVariable", "Lp/X;.foo()V") ->
134: * "Lp/X;.foo()V:TSomeTypeVariable;"
135: * </code>
136: * </pre>
137: * </p>
138: *
139: * @param typeVariableName the name of the given type variable
140: * @param declaringKey the binding key of the type or method the type variable belongs to
141: * @return a new type variable binding key
142: */
143: public static String createTypeVariableBindingKey(
144: String typeVariableName, String declaringKey) {
145: // Note this implementation is heavily dependent on TypeVariableBinding#computeUniqueKey()
146: StringBuffer buffer = new StringBuffer();
147: buffer.append(declaringKey);
148: buffer.append(':');
149: buffer.append('T');
150: buffer.append(typeVariableName);
151: buffer.append(';');
152: return buffer.toString();
153: }
154:
155: /**
156: * Creates a new wildcard type binding key from the given type binding key and the given wildcard kind
157: * (one of {@link Signature#C_STAR}, {@link Signature#C_SUPER}, or {@link Signature#C_EXTENDS}.
158: * If the wildcard is {@link Signature#C_STAR}, the given type binding key is ignored.
159: * <p>
160: * For example:
161: * <pre>
162: * <code>
163: * createWilcardTypeBindingKey(null, Signature.C_STAR) -> "*"
164: * createWilcardTypeBindingKey("Ljava/util/List<TE;>;",
165: * Signature.C_SUPER) -> "-Ljava/util/List<TE;>;"
166: * createWilcardTypeBindingKey("Ljava/util/ArrayList;", Signature.C_EXTENDS) ->
167: * "+Ljava/util/ArrayList;"
168: * </code>
169: * </pre>
170: * </p>
171: *
172: * @param typeKey the binding key of the given type
173: * @param kind one of {@link Signature#C_STAR}, {@link Signature#C_SUPER}, or {@link Signature#C_EXTENDS}
174: * @return a new wildcard type binding key
175: */
176: public static String createWilcardTypeBindingKey(String typeKey,
177: char kind) {
178: // Note this implementation is heavily dependent on WildcardBinding#computeUniqueKey()
179: switch (kind) {
180: case Signature.C_STAR:
181: return "*"; //$NON-NLS-1$
182: case Signature.C_SUPER:
183: return '-' + typeKey;
184: case Signature.C_EXTENDS:
185: return '+' + typeKey;
186: }
187: return null;
188: }
189:
190: /**
191: * Returns the thrown exception signatures of the element represented by this binding key.
192: * If this binding key does not represent a method or does not throw any exception,
193: * returns an empty array.
194: *
195: * @return the thrown exceptions signatures
196: * @since 3.3
197: */
198: public String[] getThrownExceptions() {
199: KeyToSignature keyToSignature = new KeyToSignature(this .key,
200: KeyToSignature.THROWN_EXCEPTIONS);
201: keyToSignature.parse();
202: return keyToSignature.getThrownExceptions();
203: }
204:
205: /**
206: * Returns the type argument signatures of the element represented by this binding key.
207: * If this binding key doesn't represent a parameterized type or a parameterized method,
208: * returns an empty array.
209: *
210: * @return the type argument signatures
211: */
212: public String[] getTypeArguments() {
213: KeyToSignature keyToSignature = new KeyToSignature(this .key,
214: KeyToSignature.TYPE_ARGUMENTS);
215: keyToSignature.parse();
216: return keyToSignature.getTypeArguments();
217: }
218:
219: /**
220: * Returns whether this binding key represents a raw type.
221: *
222: * @return whether this binding key represents a raw type
223: */
224: public boolean isRawType() {
225: KeyKind kind = new KeyKind(this .key);
226: kind.parse();
227: return (kind.flags & KeyKind.F_RAW_TYPE) != 0;
228: }
229:
230: /**
231: * Returns whether this binding key represents a parameterized type, or if its declaring type is a parameterized type.
232: *
233: * @return whether this binding key represents a parameterized type
234: */
235: public boolean isParameterizedType() {
236: KeyKind kind = new KeyKind(this .key);
237: kind.parse();
238: return (kind.flags & KeyKind.F_PARAMETERIZED_TYPE) != 0;
239: }
240:
241: /**
242: * Returns whether this binding key represents a parameterized method, or if its declaring method is a parameterized method.
243: *
244: * @return whether this binding key represents a parameterized method
245: */
246: public boolean isParameterizedMethod() {
247: KeyKind kind = new KeyKind(this .key);
248: kind.parse();
249: return (kind.flags & KeyKind.F_PARAMETERIZED_METHOD) != 0;
250: }
251:
252: /**
253: * Transforms this binding key into a resolved signature.
254: * If this binding key represents a field, the returned signature is
255: * the declaring type's signature.
256: *
257: * @return the resolved signature for this binding key
258: * @see Signature
259: * @since 3.2
260: */
261: public String toSignature() {
262: KeyToSignature keyToSignature = new KeyToSignature(this .key,
263: KeyToSignature.SIGNATURE);
264: keyToSignature.parse();
265: return keyToSignature.signature.toString();
266: }
267:
268: /* (non-Javadoc)
269: * @see java.lang.Object#toString()
270: */
271: public String toString() {
272: return this.key;
273: }
274: }
|