diff options
Diffstat (limited to 'dx/src/com/android/dx/rop/annotation/Annotation.java')
-rw-r--r-- | dx/src/com/android/dx/rop/annotation/Annotation.java | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/rop/annotation/Annotation.java b/dx/src/com/android/dx/rop/annotation/Annotation.java new file mode 100644 index 0000000..ad6d67e --- /dev/null +++ b/dx/src/com/android/dx/rop/annotation/Annotation.java @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dx.rop.annotation; + +import com.android.dx.rop.cst.Constant; +import com.android.dx.rop.cst.CstAnnotation; +import com.android.dx.rop.cst.CstFieldRef; +import com.android.dx.rop.cst.CstLiteralBits; +import com.android.dx.rop.cst.CstMethodRef; +import com.android.dx.rop.cst.CstNat; +import com.android.dx.rop.cst.CstType; +import com.android.dx.rop.cst.CstUtf8; +import com.android.dx.rop.cst.TypedConstant; +import com.android.dx.util.Hex; +import com.android.dx.util.MutabilityControl; +import com.android.dx.util.ToHuman; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.TreeMap; + +/** + * An annotation on an element of a class. Annotations have an + * associated type and additionally consist of a set of (name, value) + * pairs, where the names are unique. + */ +public final class Annotation extends MutabilityControl + implements Comparable<Annotation>, ToHuman { + /** {@code non-null;} type of the annotation */ + private final CstType type; + + /** {@code non-null;} the visibility of the annotation */ + private final AnnotationVisibility visibility; + + /** {@code non-null;} map from names to {@link NameValuePair} instances */ + private final TreeMap<CstUtf8, NameValuePair> elements; + + /** + * Construct an instance. It initially contains no elements. + * + * @param type {@code non-null;} type of the annotation + * @param visibility {@code non-null;} the visibility of the annotation + */ + public Annotation(CstType type, AnnotationVisibility visibility) { + if (type == null) { + throw new NullPointerException("type == null"); + } + + if (visibility == null) { + throw new NullPointerException("visibility == null"); + } + + this.type = type; + this.visibility = visibility; + this.elements = new TreeMap<CstUtf8, NameValuePair>(); + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object other) { + if (! (other instanceof Annotation)) { + return false; + } + + Annotation otherAnnotation = (Annotation) other; + + if (! (type.equals(otherAnnotation.type) + && (visibility == otherAnnotation.visibility))) { + return false; + } + + return elements.equals(otherAnnotation.elements); + } + + /** {@inheritDoc} */ + public int hashCode() { + int hash = type.hashCode(); + hash = (hash * 31) + elements.hashCode(); + hash = (hash * 31) + visibility.hashCode(); + return hash; + } + + /** {@inheritDoc} */ + public int compareTo(Annotation other) { + int result = type.compareTo(other.type); + + if (result != 0) { + return result; + } + + result = visibility.compareTo(other.visibility); + + if (result != 0) { + return result; + } + + Iterator<NameValuePair> thisIter = elements.values().iterator(); + Iterator<NameValuePair> otherIter = other.elements.values().iterator(); + + while (thisIter.hasNext() && otherIter.hasNext()) { + NameValuePair thisOne = thisIter.next(); + NameValuePair otherOne = otherIter.next(); + + result = thisOne.compareTo(otherOne); + if (result != 0) { + return result; + } + } + + if (thisIter.hasNext()) { + return 1; + } else if (otherIter.hasNext()) { + return -1; + } + + return 0; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return toHuman(); + } + + /** {@inheritDoc} */ + public String toHuman() { + StringBuilder sb = new StringBuilder(); + + sb.append(visibility.toHuman()); + sb.append("-annotation "); + sb.append(type.toHuman()); + sb.append(" {"); + + boolean first = true; + for (NameValuePair pair : elements.values()) { + if (first) { + first = false; + } else { + sb.append(", "); + } + sb.append(pair.getName().toHuman()); + sb.append(": "); + sb.append(pair.getValue().toHuman()); + } + + sb.append("}"); + return sb.toString(); + } + + /** + * Gets the type of this instance. + * + * @return {@code non-null;} the type + */ + public CstType getType() { + return type; + } + + /** + * Gets the visibility of this instance. + * + * @return {@code non-null;} the visibility + */ + public AnnotationVisibility getVisibility() { + return visibility; + } + + /** + * Put an element into the set of (name, value) pairs for this instance. + * If there is a preexisting element with the same name, it will be + * replaced by this method. + * + * @param pair {@code non-null;} the (name, value) pair to place into this instance + */ + public void put(NameValuePair pair) { + throwIfImmutable(); + + if (pair == null) { + throw new NullPointerException("pair == null"); + } + + elements.put(pair.getName(), pair); + } + + /** + * Add an element to the set of (name, value) pairs for this instance. + * It is an error to call this method if there is a preexisting element + * with the same name. + * + * @param pair {@code non-null;} the (name, value) pair to add to this instance + */ + public void add(NameValuePair pair) { + throwIfImmutable(); + + if (pair == null) { + throw new NullPointerException("pair == null"); + } + + CstUtf8 name = pair.getName(); + + if (elements.get(name) != null) { + throw new IllegalArgumentException("name already added: " + name); + } + + elements.put(name, pair); + } + + /** + * Gets the set of name-value pairs contained in this instance. The + * result is always unmodifiable. + * + * @return {@code non-null;} the set of name-value pairs + */ + public Collection<NameValuePair> getNameValuePairs() { + return Collections.unmodifiableCollection(elements.values()); + } +} |