/* * 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.CstType; import com.android.dx.util.MutabilityControl; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.TreeMap; /** * List of {@link Annotation} instances. */ public final class Annotations extends MutabilityControl implements Comparable { /** {@code non-null;} immutable empty instance */ public static final Annotations EMPTY = new Annotations(); static { EMPTY.setImmutable(); } /** {@code non-null;} map from types to annotations */ private final TreeMap annotations; /** * Constructs an immutable instance which is the combination of the * two given instances. The two instances must contain disjoint sets * of types. * * @param a1 {@code non-null;} an instance * @param a2 {@code non-null;} the other instance * @return {@code non-null;} the combination * @throws IllegalArgumentException thrown if there is a duplicate type */ public static Annotations combine(Annotations a1, Annotations a2) { Annotations result = new Annotations(); result.addAll(a1); result.addAll(a2); result.setImmutable(); return result; } /** * Constructs an immutable instance which is the combination of the * given instance with the given additional annotation. The latter's * type must not already appear in the former. * * @param annotations {@code non-null;} the instance to augment * @param annotation {@code non-null;} the additional annotation * @return {@code non-null;} the combination * @throws IllegalArgumentException thrown if there is a duplicate type */ public static Annotations combine(Annotations annotations, Annotation annotation) { Annotations result = new Annotations(); result.addAll(annotations); result.add(annotation); result.setImmutable(); return result; } /** * Constructs an empty instance. */ public Annotations() { annotations = new TreeMap(); } /** {@inheritDoc} */ @Override public int hashCode() { return annotations.hashCode(); } /** {@inheritDoc} */ @Override public boolean equals(Object other) { if (! (other instanceof Annotations)) { return false; } Annotations otherAnnotations = (Annotations) other; return annotations.equals(otherAnnotations.annotations); } /** {@inheritDoc} */ public int compareTo(Annotations other) { Iterator thisIter = annotations.values().iterator(); Iterator otherIter = other.annotations.values().iterator(); while (thisIter.hasNext() && otherIter.hasNext()) { Annotation thisOne = thisIter.next(); Annotation otherOne = otherIter.next(); int result = thisOne.compareTo(otherOne); if (result != 0) { return result; } } if (thisIter.hasNext()) { return 1; } else if (otherIter.hasNext()) { return -1; } return 0; } /** {@inheritDoc} */ public String toString() { StringBuilder sb = new StringBuilder(); boolean first = true; sb.append("annotations{"); for (Annotation a : annotations.values()) { if (first) { first = false; } else { sb.append(", "); } sb.append(a.toHuman()); } sb.append("}"); return sb.toString(); } /** * Gets the number of elements in this instance. * * @return {@code >= 0;} the size */ public int size() { return annotations.size(); } /** * Adds an element to this instance. There must not already be an * element of the same type. * * @param annotation {@code non-null;} the element to add * @throws IllegalArgumentException thrown if there is a duplicate type */ public void add(Annotation annotation) { throwIfImmutable(); if (annotation == null) { throw new NullPointerException("annotation == null"); } CstType type = annotation.getType(); if (annotations.containsKey(type)) { throw new IllegalArgumentException("duplicate type: " + type.toHuman()); } annotations.put(type, annotation); } /** * Adds all of the elements of the given instance to this one. The * instances must not have any duplicate types. * * @param toAdd {@code non-null;} the annotations to add * @throws IllegalArgumentException thrown if there is a duplicate type */ public void addAll(Annotations toAdd) { throwIfImmutable(); if (toAdd == null) { throw new NullPointerException("toAdd == null"); } for (Annotation a : toAdd.annotations.values()) { add(a); } } /** * Gets the set of annotations contained in this instance. The * result is always unmodifiable. * * @return {@code non-null;} the set of annotations */ public Collection getAnnotations() { return Collections.unmodifiableCollection(annotations.values()); } }