1package annotator.find;
2
3import plume.Pair;
4
5/**
6 * Specifies an annotation to be inserted into a source file.
7 */
8public class AnnotationInsertion extends Insertion {
9
10    /**
11     * The annotation to insert.
12     */
13    private final String annotation;
14    private String type;
15    private boolean generateBound;
16    private boolean generateExtends;
17    private boolean wasGenerateExtends;
18
19    /**
20     * Creates a new insertion.
21     *
22     * @param annotation the annotation to insert, which starts with "@"
23     * @param criteria where to insert the annotation
24     * @param separateLine whether to insert the annotation on its own
25     */
26    public AnnotationInsertion(String annotation, Criteria criteria, boolean separateLine) {
27        super(criteria, separateLine);
28        this.annotation = annotation;
29        type = null;
30        generateBound = false;
31        generateExtends = false;
32        wasGenerateExtends = false;
33    }
34
35    /**
36     * Creates a new insertion with an empty criteria and the text inserted on
37     * the same line.
38     *
39     * @param annotation the text to insert
40     */
41    public AnnotationInsertion(String annotation) {
42        this(annotation, new Criteria(), false);
43    }
44
45    public boolean isGenerateExtends() {
46        return generateExtends;
47    }
48
49    public boolean isGenerateBound() {
50        return generateBound;
51    }
52
53    public void setGenerateExtends(boolean generateExtends) {
54        this.generateExtends = generateExtends;
55        this.wasGenerateExtends |= generateExtends;
56    }
57
58    public void setGenerateBound(boolean b) {
59        generateBound = b;
60    }
61
62    /**
63     * Gets the insertion text.
64     *
65     * @param comments
66     *            if true, the annotation will be surrounded by block comments
67     * @param abbreviate
68     *            if true, the package name will be removed from the annotation.
69     *            The package name can be retrieved again by calling the
70     *            {@link #getPackageName()} method.
71     * @return the text to insert
72     */
73    protected String getText(boolean comments, boolean abbreviate) {
74        String result = annotation;
75        if (abbreviate) {
76            Pair<String, String> ps = removePackage(result);
77            String packageName = ps.a;
78            if (packageName != null) {
79                packageNames.add(packageName);
80                result = ps.b;
81            }
82        }
83        if (!result.startsWith("@")) {
84            throw new Error("Illegal insertion, must start with @: " + result);
85        }
86
87        // We insert a "new " when annotating a variable initializer that is a
88        // bare array expression (e.g., as in "int[] a = {0, 1};")  Since the
89        // syntax doesn't permit adding the type annotation in front of the
90        // expression, we generate the explicit "new"
91        // (as in "int[] a = new int[] {0, 1}") to provide a legal insertion site.
92
93        if (type != null) {
94            result = "new " + result + " " + type;
95        } else if (generateBound) {
96            result += " Object &";
97        } else if (generateExtends) {
98            result = " extends " + result + " Object";
99        }
100        return comments ? "/*" + result + "*/" : result;
101    }
102
103    /**
104     * Gets the raw, unmodified annotation that was passed into the constructor.
105     * @return the annotation
106     */
107    public String getAnnotation() {
108        return annotation;
109    }
110
111    /** {@inheritDoc} */
112    protected boolean addLeadingSpace(boolean gotSeparateLine, int pos,
113            char precedingChar) {
114        if (generateExtends || precedingChar == '.') {
115            return false;
116        }
117        return super.addLeadingSpace(gotSeparateLine, pos, precedingChar);
118    }
119
120    /**
121     * {@inheritDoc}
122     */
123    @Override
124    protected boolean addTrailingSpace(boolean gotSeparateLine) {
125        // Never add a trailing space on a type parameter bound.
126        return !wasGenerateExtends && super.addTrailingSpace(gotSeparateLine);
127    }
128
129    /** {@inheritDoc} */
130    public Kind getKind() {
131        return Kind.ANNOTATION;
132    }
133
134    public String toString() {
135        return annotation + " " + super.toString();
136    }
137
138    public void setType(String s) {
139        this.type = s;
140    }
141}
142