summaryrefslogtreecommitdiff
path: root/dx/src/com/android/dx/rop/annotation/Annotation.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/rop/annotation/Annotation.java')
-rw-r--r--dx/src/com/android/dx/rop/annotation/Annotation.java232
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());
+ }
+}