Home | History | Annotate | Download | only in annotation
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dx.rop.annotation;
     18 
     19 import com.android.dx.rop.cst.CstType;
     20 import com.android.dx.util.MutabilityControl;
     21 import java.util.Collection;
     22 import java.util.Collections;
     23 import java.util.Iterator;
     24 import java.util.TreeMap;
     25 
     26 /**
     27  * List of {@link Annotation} instances.
     28  */
     29 public final class Annotations extends MutabilityControl
     30         implements Comparable<Annotations> {
     31     /** {@code non-null;} immutable empty instance */
     32     public static final Annotations EMPTY = new Annotations();
     33 
     34     static {
     35         EMPTY.setImmutable();
     36     }
     37 
     38     /** {@code non-null;} map from types to annotations */
     39     private final TreeMap<CstType, Annotation> annotations;
     40 
     41     /**
     42      * Constructs an immutable instance which is the combination of the
     43      * two given instances. The two instances must contain disjoint sets
     44      * of types.
     45      *
     46      * @param a1 {@code non-null;} an instance
     47      * @param a2 {@code non-null;} the other instance
     48      * @return {@code non-null;} the combination
     49      * @throws IllegalArgumentException thrown if there is a duplicate type
     50      */
     51     public static Annotations combine(Annotations a1, Annotations a2) {
     52         Annotations result = new Annotations();
     53 
     54         result.addAll(a1);
     55         result.addAll(a2);
     56         result.setImmutable();
     57 
     58         return result;
     59     }
     60 
     61     /**
     62      * Constructs an immutable instance which is the combination of the
     63      * given instance with the given additional annotation. The latter's
     64      * type must not already appear in the former.
     65      *
     66      * @param annotations {@code non-null;} the instance to augment
     67      * @param annotation {@code non-null;} the additional annotation
     68      * @return {@code non-null;} the combination
     69      * @throws IllegalArgumentException thrown if there is a duplicate type
     70      */
     71     public static Annotations combine(Annotations annotations,
     72             Annotation annotation) {
     73         Annotations result = new Annotations();
     74 
     75         result.addAll(annotations);
     76         result.add(annotation);
     77         result.setImmutable();
     78 
     79         return result;
     80     }
     81 
     82     /**
     83      * Constructs an empty instance.
     84      */
     85     public Annotations() {
     86         annotations = new TreeMap<CstType, Annotation>();
     87     }
     88 
     89     /** {@inheritDoc} */
     90     @Override
     91     public int hashCode() {
     92         return annotations.hashCode();
     93     }
     94 
     95     /** {@inheritDoc} */
     96     @Override
     97     public boolean equals(Object other) {
     98         if (! (other instanceof Annotations)) {
     99             return false;
    100         }
    101 
    102         Annotations otherAnnotations = (Annotations) other;
    103 
    104         return annotations.equals(otherAnnotations.annotations);
    105     }
    106 
    107     /** {@inheritDoc} */
    108     public int compareTo(Annotations other) {
    109         Iterator<Annotation> thisIter = annotations.values().iterator();
    110         Iterator<Annotation> otherIter = other.annotations.values().iterator();
    111 
    112         while (thisIter.hasNext() && otherIter.hasNext()) {
    113             Annotation thisOne = thisIter.next();
    114             Annotation otherOne = otherIter.next();
    115 
    116             int result = thisOne.compareTo(otherOne);
    117             if (result != 0) {
    118                 return result;
    119             }
    120         }
    121 
    122         if (thisIter.hasNext()) {
    123             return 1;
    124         } else if (otherIter.hasNext()) {
    125             return -1;
    126         }
    127 
    128         return 0;
    129     }
    130 
    131     /** {@inheritDoc} */
    132     public String toString() {
    133         StringBuilder sb = new StringBuilder();
    134         boolean first = true;
    135 
    136         sb.append("annotations{");
    137 
    138         for (Annotation a : annotations.values()) {
    139             if (first) {
    140                 first = false;
    141             } else {
    142                 sb.append(", ");
    143             }
    144             sb.append(a.toHuman());
    145         }
    146 
    147         sb.append("}");
    148         return sb.toString();
    149     }
    150 
    151     /**
    152      * Gets the number of elements in this instance.
    153      *
    154      * @return {@code >= 0;} the size
    155      */
    156     public int size() {
    157         return annotations.size();
    158     }
    159 
    160     /**
    161      * Adds an element to this instance. There must not already be an
    162      * element of the same type.
    163      *
    164      * @param annotation {@code non-null;} the element to add
    165      * @throws IllegalArgumentException thrown if there is a duplicate type
    166      */
    167     public void add(Annotation annotation) {
    168         throwIfImmutable();
    169 
    170         if (annotation == null) {
    171             throw new NullPointerException("annotation == null");
    172         }
    173 
    174         CstType type = annotation.getType();
    175 
    176         if (annotations.containsKey(type)) {
    177             throw new IllegalArgumentException("duplicate type: " +
    178                     type.toHuman());
    179         }
    180 
    181         annotations.put(type, annotation);
    182     }
    183 
    184     /**
    185      * Adds all of the elements of the given instance to this one. The
    186      * instances must not have any duplicate types.
    187      *
    188      * @param toAdd {@code non-null;} the annotations to add
    189      * @throws IllegalArgumentException thrown if there is a duplicate type
    190      */
    191     public void addAll(Annotations toAdd) {
    192         throwIfImmutable();
    193 
    194         if (toAdd == null) {
    195             throw new NullPointerException("toAdd == null");
    196         }
    197 
    198         for (Annotation a : toAdd.annotations.values()) {
    199             add(a);
    200         }
    201     }
    202 
    203     /**
    204      * Gets the set of annotations contained in this instance. The
    205      * result is always unmodifiable.
    206      *
    207      * @return {@code non-null;} the set of annotations
    208      */
    209     public Collection<Annotation> getAnnotations() {
    210         return Collections.unmodifiableCollection(annotations.values());
    211     }
    212 }
    213