View Javadoc
1   package net.sourceforge.jenesis4java.impl;
2   
3   /*
4    * #%L
5    * Jenesis 4 Java Code Generator
6    * %%
7    * Copyright (C) 2000 - 2015 jenesis4java
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /**
26   * Copyright (C) 2008, 2010 Richard van Nieuwenhoven - ritchie [at] gmx [dot] at
27   * Copyright (C) 2000, 2001 Paul Cody Johnston - pcj@inxar.org <br>
28   * This file is part of Jenesis4java. Jenesis4java is free software: you can
29   * redistribute it and/or modify it under the terms of the GNU Lesser General
30   * Public License as published by the Free Software Foundation, either version 3
31   * of the License, or (at your option) any later version.<br>
32   * Jenesis4java is distributed in the hope that it will be useful, but WITHOUT
33   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
35   * details.<br>
36   * You should have received a copy of the GNU Lesser General Public License
37   * along with Jenesis4java. If not, see <http://www.gnu.org/licenses/>.
38   */
39  
40  import net.sourceforge.jenesis4java.*;
41  import net.sourceforge.jenesis4java.impl.MVM.MCodeable;
42  import net.sourceforge.jenesis4java.impl.util.ListTypeSelector;
43  import net.sourceforge.jenesis4java.impl.util.VisitorUtils;
44  
45  import java.util.ArrayList;
46  import java.util.Iterator;
47  import java.util.List;
48  
49  class MAnnotation extends MCodeable implements Annotation {
50  
51      static class MAnnotationAttribute extends MCodeable implements AnnotationAttribute {
52  
53          private String name;
54  
55          private final List<Expression> values = new ArrayList<>(2);
56  
57          private boolean isArray;
58  
59          private Annotation[] valueAnnotations;
60  
61          MAnnotationAttribute(MVM vm) {
62              super(vm);
63          }
64  
65          @Override
66          public MAnnotationAttribute addValue(Expression value) {
67              values.add(value);
68              return this;
69          }
70  
71          @Override
72          public AnnotationAttribute addValues(Iterable<Expression> values) {
73              for (Expression value : values) {
74                  addValue(value);
75              }
76  
77              return null;
78          }
79  
80          @Override
81          public MAnnotationAttribute addValueAnnotation(Annotation valueAnnotation) {
82              Annotation[] oldValue = valueAnnotations;
83              if (oldValue == null) {
84                  oldValue = new Annotation[0];
85              }
86              valueAnnotations = new Annotation[oldValue.length + 1];
87              System.arraycopy(oldValue, 0, valueAnnotations, 0, oldValue.length);
88              valueAnnotations[oldValue.length] = valueAnnotation;
89              return this;
90          }
91  
92          @Override
93          public List<Expression> getValuesCopy() {
94              return new ArrayList<>(values);
95          }
96  
97          @Override
98          public String getName() {
99              return name;
100         }
101 
102         @Override
103         public Expression getValue() {
104             if (!values.isEmpty()) {
105                 return values.get(0);
106             } else {
107                 return null;
108             }
109         }
110 
111         @Override
112         public boolean isDefaultValueAttribute() {
113             return name.isEmpty();
114         }
115 
116         @Override
117         public Annotation getValueAnnotation() {
118             if (valueAnnotations != null && valueAnnotations.length > 0) {
119                 return valueAnnotations[0];
120             } else {
121                 return null;
122             }
123         }
124 
125         @Override
126         public Annotation[] getValueAnnotations() {
127             return valueAnnotations;
128         }
129 
130         @Override
131         public boolean isArray() {
132             return isArray || values != null && values.size() > 1 || valueAnnotations != null && valueAnnotations.length > 1;
133         }
134 
135         @Override
136         @Deprecated
137         public MAnnotationAttribute setArray(boolean isArray) {
138             this.isArray = isArray;
139             return this;
140         }
141 
142         private static String nullToEmpty(String string) {
143             if (string == null) {
144                 return "";
145             } else {
146                 return string;
147             }
148         }
149 
150         @Override
151         public MAnnotationAttribute setName(String name) {
152             this.name = nullToEmpty(name);
153             return this;
154         }
155 
156         @Override
157         public MAnnotationAttribute setValue(Expression value) {
158             values.clear();
159             values.add(value);
160             return this;
161         }
162 
163         @Override
164         public MAnnotationAttribute setValueAnnotation(Annotation valueAnnotation) {
165             valueAnnotations = new Annotation[]{
166                 valueAnnotation
167             };
168             return this;
169         }
170 
171         @Override
172         public MAnnotationAttribute setValueAnnotations(Annotation[] valueAnnotations) {
173             this.valueAnnotations = valueAnnotations;
174             return this;
175         }
176 
177         @Override
178         public CodeWriter toCode(CodeWriter out) {
179             if (!isArray() && valueAnnotations != null && valueAnnotations.length == 1) {
180                 out.indentLine();
181             }
182             if (name != null && !name.trim().isEmpty()) {
183                 out.write(name);
184                 out.write(" = ");
185             }
186             if (isArray()) {
187                 out.write('{');
188                 out.indentLine();
189             }
190             if (!values.isEmpty()) {
191                 for (int index = 0; index < values.size(); index++) {
192                     if (index > 0) {
193                         out.write(", ");
194                     }
195                     out.write(values.get(index));
196                 }
197             } else if (valueAnnotations != null) {
198                 for (int index = 0; index < valueAnnotations.length; index++) {
199                     if (index > 0) {
200                         out.write(", ");
201                         out.newLine();
202                     }
203                     out.write(valueAnnotations[index]);
204                 }
205             }
206             if (isArray()) {
207                 out.dedentLine();
208                 out.write('}');
209             } else if (valueAnnotations != null && valueAnnotations.length == 1) {
210                 out.dedentLine();
211             }
212             return out;
213         }
214 
215         @Override
216         public void visit(ReplacingVisitor visitor) {
217             super.visit(visitor);
218             VisitorUtils.visit(values, this, visitor);
219             VisitorUtils.visit(valueAnnotations, this, visitor);
220         }
221     }
222 
223     private String name;
224 
225     private String text;
226 
227     private List<AnnotationAttribute> annotationAttributes = new ArrayList<>();
228 
229     MAnnotation(MVM vm, String text) {
230         super(vm);
231         checkArgument(!text.startsWith("@"), "name must not start with @");
232         this.text = text;
233     }
234 
235     private static void checkArgument(boolean condition, String message) {
236         if (!condition) {
237             throw new IllegalArgumentException(message);
238         }
239     }
240 
241     @Override
242     public MAnnotation addAnnotationAttribute(AnnotationAttribute annotation) {
243         annotationAttributes.add(annotation);
244         return this;
245     }
246 
247     @Override
248     public AnnotationAttribute addAnnotationAttribute(String attributeName) {
249         MAnnotationAttribute attribute = new MAnnotationAttribute(vm);
250         attribute.setName(attributeName);
251         addAnnotationAttribute(attribute);
252         return attribute;
253     }
254 
255     @Override
256     public AnnotationAttribute addAnnotationAttribute(String name, Expression value) {
257         AnnotationAttribute attribute = addAnnotationAttribute(name);
258         attribute.setValue(value);
259         return attribute;
260     }
261 
262     @Override
263     public AnnotationAttribute getAnnotationAttribute(String name) {
264         for (Object element : annotationAttributes) {
265             AnnotationAttribute annotationAttribute = (AnnotationAttribute) element;
266             if (annotationAttribute.getName().equals(name)) {
267                 return annotationAttribute;
268             }
269         }
270         return null;
271     }
272 
273     @Override
274     public List<AnnotationAttribute> getAnnotationAttributes() {
275         return ListTypeSelector.select(annotationAttributes, AnnotationAttribute.class);
276     }
277 
278     @Override
279     public String getEffectiveName() {
280         return name != null ? name : text;
281     }
282 
283     @Override
284     @Deprecated
285     public String getName() {
286         return name;
287     }
288 
289     @Override
290     @Deprecated
291     public String getText() {
292         return text;
293     }
294 
295     @Override
296     @Deprecated
297     public MAnnotation setName(String name) {
298         this.name = name;
299         return this;
300     }
301 
302     @Override
303     @Deprecated
304     public MAnnotation setText(String text) {
305         this.text = text;
306         return this;
307     }
308 
309     @Override
310     public AnnotationAttribute addDefaultValueAttribute(Expression... values) {
311         MAnnotationAttribute defaultValueAttribute = new MAnnotationAttribute(vm);
312         defaultValueAttribute.setName("");
313         for (Expression value : values) {
314             defaultValueAttribute.addValue(value);
315         }
316         this.addAnnotationAttribute(defaultValueAttribute);
317         return defaultValueAttribute;
318     }
319 
320     @Override
321     public CodeWriter toCode(CodeWriter out) {
322         super.toCode(out);
323 
324         List<AnnotationAttribute> annotationAttributes = attributesWithValue(this.annotationAttributes);
325 
326         if (annotationAttributes.isEmpty() && (name == null || "".equals(name))) {
327             out.write("@" + text);
328         } else if (annotationAttributes.isEmpty()) {
329             out.write("@" + name + "(" + text + ")");
330         } else {
331             out.write("@");
332             if (name != null && !name.trim().isEmpty()) {
333                 out.write(name);
334             } else if (text != null && !text.trim().isEmpty()) {
335                 out.write(text);
336             }
337             out.write("(");
338             for (Iterator<AnnotationAttribute> iterator = annotationAttributes.iterator(); iterator.hasNext();) {
339                 out.write(iterator.next());
340                 if (iterator.hasNext()) {
341                     out.write(", ");
342                 }
343             }
344             out.write(")");
345         }
346         return out;
347     }
348 
349     private List<AnnotationAttribute> attributesWithValue(List<AnnotationAttribute> allAnnotationAttributes) {
350         List<AnnotationAttribute> attributesWithNonNullValue = new ArrayList<>(allAnnotationAttributes.size());
351         for (AnnotationAttribute attribute : allAnnotationAttributes) {
352             if (attribute.getValue() != null || attribute.getValueAnnotations() != null) {
353                 attributesWithNonNullValue.add(attribute);
354             }
355         }
356         return attributesWithNonNullValue;
357     }
358 
359     @Override
360     public void visit(ReplacingVisitor visitor) {
361         super.visit(visitor);
362         VisitorUtils.visit(annotationAttributes, this, visitor);
363     }
364 }