1/*
2 * Copyright (C) 2010 Google Inc.
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.google.doclava;
18
19import com.google.clearsilver.jsilver.data.Data;
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Collection;
24
25public class AnnotationInstanceInfo implements Resolvable {
26  private ClassInfo mType;
27  private String mAnnotationName; // for debugging purposes TODO - remove
28  private ArrayList<AnnotationValueInfo> mElementValues;
29  private ArrayList<Resolution> mResolutions;
30
31  public AnnotationInstanceInfo() {
32      mType = null;
33      mElementValues = new ArrayList<AnnotationValueInfo>();
34    }
35
36  public AnnotationInstanceInfo(ClassInfo type, AnnotationValueInfo[] elementValues) {
37    mType = type;
38    mElementValues = new ArrayList<AnnotationValueInfo>(Arrays.asList(elementValues));
39  }
40
41  ClassInfo type() {
42    return mType;
43  }
44
45  public void setClass(ClassInfo cl) {
46      mType = cl;
47  }
48
49  public void setSimpleAnnotationName(String name) {
50      mAnnotationName = name;
51  }
52
53  ArrayList<AnnotationValueInfo> elementValues() {
54    return mElementValues;
55  }
56
57  public void addElementValue(AnnotationValueInfo info) {
58      mElementValues.add(info);
59  }
60
61  @Override
62  public String toString() {
63    StringBuilder str = new StringBuilder();
64    str.append("@");
65    if (mType == null) {
66        str.append(mAnnotationName);
67    } else {
68        str.append(mType.qualifiedName());
69    }
70    str.append("(");
71
72    for (AnnotationValueInfo value : mElementValues) {
73      if (value.element() != null) {
74          str.append(value.element().name());
75          str.append("=");
76      }
77
78      str.append(value.valueString());
79      if (value != mElementValues.get(mElementValues.size()-1)) {
80        str.append(",");
81      }
82    }
83    str.append(")");
84    return str.toString();
85  }
86
87  public void addResolution(Resolution resolution) {
88      if (mResolutions == null) {
89          mResolutions = new ArrayList<Resolution>();
90      }
91
92      mResolutions.add(resolution);
93  }
94
95  public void printResolutions() {
96      System.out.println("Resolutions for Annotation:");
97      for (Resolution r : mResolutions) {
98          System.out.println(r);
99      }
100  }
101
102  public boolean resolveResolutions() {
103      ArrayList<Resolution> resolutions = mResolutions;
104      mResolutions = new ArrayList<Resolution>();
105
106      boolean allResolved = true;
107      for (Resolution resolution : resolutions) {
108          StringBuilder qualifiedClassName = new StringBuilder();
109          InfoBuilder.resolveQualifiedName(resolution.getValue(), qualifiedClassName,
110                  resolution.getInfoBuilder());
111
112          // if we still couldn't resolve it, save it for the next pass
113          if ("".equals(qualifiedClassName.toString())) {
114              mResolutions.add(resolution);
115              allResolved = false;
116          } else if ("annotationTypeName".equals(resolution.getVariable())) {
117              setClass(InfoBuilder.Caches.obtainClass(qualifiedClassName.toString()));
118          }
119      }
120
121      return allResolved;
122  }
123
124  /**
125   * Convert the specified list of {@code AnnotationInstanceInfo} into an HDF-formatted list, and
126   * add the HDF list into the specified {@code Data}.
127   */
128  public static void makeLinkListHDF(Data data, String base, AnnotationInstanceInfo[] annotations) {
129    if (annotations == null) return;
130
131    final int N = annotations.length;
132    for (int i = 0; i < N; i++) {
133      AnnotationInstanceInfo aii = annotations[i];
134      final String aiiBase = base + "." + i;
135
136      // Serialize data about the annotation element values
137      for (int elemIdx = 0; elemIdx < aii.elementValues().size(); ++elemIdx) {
138        final String elemBase = aiiBase + ".elementValues." + elemIdx;
139        final AnnotationValueInfo value = aii.elementValues().get(elemIdx);
140        data.setValue(elemBase + ".name", value.element().name());
141        data.setValue(elemBase + ".value", value.valueString());
142      }
143
144      aii.type().makeShortDescrHDF(data, aiiBase);
145    }
146  }
147
148  /**
149   * Get a new list containing the set of annotations that are shared between
150   * the input annotations collection and the set of allowed annotations.
151   */
152  public static ArrayList<AnnotationInstanceInfo> getAnnotationsIntersection(
153          Collection<String> allowedAnnotations,
154          Collection<? extends AnnotationInstanceInfo> allAnnotations) {
155    ArrayList<AnnotationInstanceInfo> list = new ArrayList<AnnotationInstanceInfo>();
156    java.util.Objects.requireNonNull(allowedAnnotations);
157    if (allAnnotations != null) {
158      for (AnnotationInstanceInfo info : allAnnotations) {
159        if (allowedAnnotations.contains(info.type().qualifiedName())) {
160          list.add(info);
161        }
162      }
163    }
164    return list;
165  }
166
167  /**
168   * Get a new list containing the set of annotations that are shared between
169   * the input annotations collection and the names of annotations passed in
170   * the showAnnotations parameter
171   */
172  public static ArrayList<AnnotationInstanceInfo> getShowAnnotationsIntersection(
173          Collection<? extends AnnotationInstanceInfo> annotations) {
174    return getAnnotationsIntersection(Doclava.showAnnotations, annotations);
175  }
176
177  /**
178   * Get a new list containing the set of annotations that are shared between
179   * the input annotations collection and the names of annotations passed in
180   * the hideAnnotations parameter
181   */
182  public static ArrayList<AnnotationInstanceInfo> getHideAnnotationsIntersection(
183          Collection<? extends AnnotationInstanceInfo> annotations) {
184    return getAnnotationsIntersection(Doclava.hideAnnotations, annotations);
185  }
186}
187