ParameterAnnotationStruct.java revision fe107fb6e3f308ac5174ebdc5a794ee880c741d9
1/*
2 * Copyright (C) 2008 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
17package com.android.dx.dex.file;
18
19import com.android.dx.rop.annotation.Annotations;
20import com.android.dx.rop.annotation.AnnotationsList;
21import com.android.dx.rop.cst.CstMethodRef;
22import com.android.dx.util.AnnotatedOutput;
23import com.android.dx.util.Hex;
24import com.android.dx.util.ToHuman;
25import java.util.ArrayList;
26
27/**
28 * Association of a method and its parameter annotations.
29 */
30public final class ParameterAnnotationStruct
31        implements ToHuman, Comparable<ParameterAnnotationStruct> {
32    /** {@code non-null;} the method in question */
33    private final CstMethodRef method;
34
35    /** {@code non-null;} the associated annotations list */
36    private final AnnotationsList annotationsList;
37
38    /** {@code non-null;} the associated annotations list, as an item */
39    private final UniformListItem<AnnotationSetRefItem> annotationsItem;
40
41    /**
42     * Constructs an instance.
43     *
44     * @param method {@code non-null;} the method in question
45     * @param annotationsList {@code non-null;} the associated annotations list
46     */
47    public ParameterAnnotationStruct(CstMethodRef method,
48            AnnotationsList annotationsList) {
49        if (method == null) {
50            throw new NullPointerException("method == null");
51        }
52
53        if (annotationsList == null) {
54            throw new NullPointerException("annotationsList == null");
55        }
56
57        this.method = method;
58        this.annotationsList = annotationsList;
59
60        /*
61         * Construct an item for the annotations list. TODO: This
62         * requires way too much copying; fix it.
63         */
64
65        int size = annotationsList.size();
66        ArrayList<AnnotationSetRefItem> arrayList = new
67            ArrayList<AnnotationSetRefItem>(size);
68
69        for (int i = 0; i < size; i++) {
70            Annotations annotations = annotationsList.get(i);
71            AnnotationSetItem item = new AnnotationSetItem(annotations);
72            arrayList.add(new AnnotationSetRefItem(item));
73        }
74
75        this.annotationsItem = new UniformListItem<AnnotationSetRefItem>(
76                ItemType.TYPE_ANNOTATION_SET_REF_LIST, arrayList);
77    }
78
79    /** {@inheritDoc} */
80    public int hashCode() {
81        return method.hashCode();
82    }
83
84    /** {@inheritDoc} */
85    public boolean equals(Object other) {
86        if (! (other instanceof ParameterAnnotationStruct)) {
87            return false;
88        }
89
90        return method.equals(((ParameterAnnotationStruct) other).method);
91    }
92
93    /** {@inheritDoc} */
94    public int compareTo(ParameterAnnotationStruct other) {
95        return method.compareTo(other.method);
96    }
97
98    /** {@inheritDoc} */
99    public void addContents(DexFile file) {
100        MethodIdsSection methodIds = file.getMethodIds();
101        MixedItemSection wordData = file.getWordData();
102
103        methodIds.intern(method);
104        wordData.add(annotationsItem);
105    }
106
107    /** {@inheritDoc} */
108    public void writeTo(DexFile file, AnnotatedOutput out) {
109        int methodIdx = file.getMethodIds().indexOf(method);
110        int annotationsOff = annotationsItem.getAbsoluteOffset();
111
112        if (out.annotates()) {
113            out.annotate(0, "    " + method.toHuman());
114            out.annotate(4, "      method_idx:      " + Hex.u4(methodIdx));
115            out.annotate(4, "      annotations_off: " +
116                    Hex.u4(annotationsOff));
117        }
118
119        out.writeInt(methodIdx);
120        out.writeInt(annotationsOff);
121    }
122
123    /** {@inheritDoc} */
124    public String toHuman() {
125        StringBuilder sb = new StringBuilder();
126
127        sb.append(method.toHuman());
128        sb.append(": ");
129
130        boolean first = true;
131        for (AnnotationSetRefItem item : annotationsItem.getItems()) {
132            if (first) {
133                first = false;
134            } else {
135                sb.append(", ");
136            }
137            sb.append(item.toHuman());
138        }
139
140        return sb.toString();
141    }
142
143    /**
144     * Gets the method this item is for.
145     *
146     * @return {@code non-null;} the method
147     */
148    public CstMethodRef getMethod() {
149        return method;
150    }
151
152    /**
153     * Gets the associated annotations list.
154     *
155     * @return {@code non-null;} the annotations list
156     */
157    public AnnotationsList getAnnotationsList() {
158        return annotationsList;
159    }
160}
161