Annotation.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch/* 207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * Copyright (C) 2007 The Android Open Source Project 307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * 407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * Licensed under the Apache License, Version 2.0 (the "License"); 507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * you may not use this file except in compliance with the License. 607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * You may obtain a copy of the License at 707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * 807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * http://www.apache.org/licenses/LICENSE-2.0 907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * 107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * Unless required by applicable law or agreed to in writing, software 1107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS, 12c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * See the License for the specific language governing permissions and 1407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * limitations under the License. 1507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch */ 1607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 1707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochpackage com.android.dx.rop.annotation; 1807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 1907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochimport com.android.dx.rop.cst.CstString; 2007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochimport com.android.dx.rop.cst.CstType; 2107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochimport com.android.dx.util.MutabilityControl; 2207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochimport com.android.dx.util.ToHuman; 2307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciimport java.util.Collection; 257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciimport java.util.Collections; 267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciimport java.util.Iterator; 277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciimport java.util.TreeMap; 287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 29a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch/** 3007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * An annotation on an element of a class. Annotations have an 3107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * associated type and additionally consist of a set of (name, value) 3207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * pairs, where the names are unique. 3307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch */ 3407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochpublic final class Annotation extends MutabilityControl 3507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch implements Comparable<Annotation>, ToHuman { 3607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch /** {@code non-null;} type of the annotation */ 3707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch private final CstType type; 3807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 3907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch /** {@code non-null;} the visibility of the annotation */ 407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci private final AnnotationVisibility visibility; 417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci /** {@code non-null;} map from names to {@link NameValuePair} instances */ 437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci private final TreeMap<CstString, NameValuePair> elements; 4407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 4507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch /** 4607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * Construct an instance. It initially contains no elements. 4707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * 48c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * @param type {@code non-null;} type of the annotation 4907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch * @param visibility {@code non-null;} the visibility of the annotation 5007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch */ 51 public Annotation(CstType type, AnnotationVisibility visibility) { 52 if (type == null) { 53 throw new NullPointerException("type == null"); 54 } 55 56 if (visibility == null) { 57 throw new NullPointerException("visibility == null"); 58 } 59 60 this.type = type; 61 this.visibility = visibility; 62 this.elements = new TreeMap<CstString, NameValuePair>(); 63 } 64 65 /** {@inheritDoc} */ 66 @Override 67 public boolean equals(Object other) { 68 if (! (other instanceof Annotation)) { 69 return false; 70 } 71 72 Annotation otherAnnotation = (Annotation) other; 73 74 if (! (type.equals(otherAnnotation.type) 75 && (visibility == otherAnnotation.visibility))) { 76 return false; 77 } 78 79 return elements.equals(otherAnnotation.elements); 80 } 81 82 /** {@inheritDoc} */ 83 public int hashCode() { 84 int hash = type.hashCode(); 85 hash = (hash * 31) + elements.hashCode(); 86 hash = (hash * 31) + visibility.hashCode(); 87 return hash; 88 } 89 90 /** {@inheritDoc} */ 91 public int compareTo(Annotation other) { 92 int result = type.compareTo(other.type); 93 94 if (result != 0) { 95 return result; 96 } 97 98 result = visibility.compareTo(other.visibility); 99 100 if (result != 0) { 101 return result; 102 } 103 104 Iterator<NameValuePair> thisIter = elements.values().iterator(); 105 Iterator<NameValuePair> otherIter = other.elements.values().iterator(); 106 107 while (thisIter.hasNext() && otherIter.hasNext()) { 108 NameValuePair thisOne = thisIter.next(); 109 NameValuePair otherOne = otherIter.next(); 110 111 result = thisOne.compareTo(otherOne); 112 if (result != 0) { 113 return result; 114 } 115 } 116 117 if (thisIter.hasNext()) { 118 return 1; 119 } else if (otherIter.hasNext()) { 120 return -1; 121 } 122 123 return 0; 124 } 125 126 /** {@inheritDoc} */ 127 @Override 128 public String toString() { 129 return toHuman(); 130 } 131 132 /** {@inheritDoc} */ 133 public String toHuman() { 134 StringBuilder sb = new StringBuilder(); 135 136 sb.append(visibility.toHuman()); 137 sb.append("-annotation "); 138 sb.append(type.toHuman()); 139 sb.append(" {"); 140 141 boolean first = true; 142 for (NameValuePair pair : elements.values()) { 143 if (first) { 144 first = false; 145 } else { 146 sb.append(", "); 147 } 148 sb.append(pair.getName().toHuman()); 149 sb.append(": "); 150 sb.append(pair.getValue().toHuman()); 151 } 152 153 sb.append("}"); 154 return sb.toString(); 155 } 156 157 /** 158 * Gets the type of this instance. 159 * 160 * @return {@code non-null;} the type 161 */ 162 public CstType getType() { 163 return type; 164 } 165 166 /** 167 * Gets the visibility of this instance. 168 * 169 * @return {@code non-null;} the visibility 170 */ 171 public AnnotationVisibility getVisibility() { 172 return visibility; 173 } 174 175 /** 176 * Put an element into the set of (name, value) pairs for this instance. 177 * If there is a preexisting element with the same name, it will be 178 * replaced by this method. 179 * 180 * @param pair {@code non-null;} the (name, value) pair to place into this instance 181 */ 182 public void put(NameValuePair pair) { 183 throwIfImmutable(); 184 185 if (pair == null) { 186 throw new NullPointerException("pair == null"); 187 } 188 189 elements.put(pair.getName(), pair); 190 } 191 192 /** 193 * Add an element to the set of (name, value) pairs for this instance. 194 * It is an error to call this method if there is a preexisting element 195 * with the same name. 196 * 197 * @param pair {@code non-null;} the (name, value) pair to add to this instance 198 */ 199 public void add(NameValuePair pair) { 200 throwIfImmutable(); 201 202 if (pair == null) { 203 throw new NullPointerException("pair == null"); 204 } 205 206 CstString name = pair.getName(); 207 208 if (elements.get(name) != null) { 209 throw new IllegalArgumentException("name already added: " + name); 210 } 211 212 elements.put(name, pair); 213 } 214 215 /** 216 * Gets the set of name-value pairs contained in this instance. The 217 * result is always unmodifiable. 218 * 219 * @return {@code non-null;} the set of name-value pairs 220 */ 221 public Collection<NameValuePair> getNameValuePairs() { 222 return Collections.unmodifiableCollection(elements.values()); 223 } 224} 225