View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.apt;
21  
22  import com.sun.mirror.apt.AnnotationProcessorEnvironment;
23  import com.sun.mirror.apt.Filer;
24  import com.sun.mirror.declaration.Declaration;
25  import com.sun.mirror.declaration.MethodDeclaration;
26  import com.sun.mirror.declaration.PackageDeclaration;
27  import org.apache.commons.io.IOUtils;
28  import org.apache.commons.lang.ClassUtils;
29  import org.apache.myfaces.tobago.apt.annotation.BodyContent;
30  import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
31  import org.apache.myfaces.tobago.apt.annotation.Tag;
32  import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
33  import org.apache.myfaces.tobago.apt.annotation.Taglib;
34  import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
35  import org.w3c.dom.Document;
36  import org.w3c.dom.Element;
37  
38  import javax.xml.transform.OutputKeys;
39  import javax.xml.transform.Transformer;
40  import javax.xml.transform.TransformerException;
41  import javax.xml.transform.TransformerFactory;
42  import javax.xml.transform.dom.DOMSource;
43  import javax.xml.transform.stream.StreamResult;
44  import java.io.File;
45  import java.io.IOException;
46  import java.io.Writer;
47  import java.util.Locale;
48  
49  public class TobagoAnnotationVisitor extends TaglibAnnotationVisitor {
50  
51    public TobagoAnnotationVisitor(AnnotationProcessorEnvironment env) {
52      super(env);
53    }
54  
55    @Override
56    protected void writeTaglib(PackageDeclaration packageDeclaration, Taglib taglibAnnotation, Document document)
57        throws IOException, TransformerException {
58      Writer writer = null;
59      try {
60        getEnv().getMessager().printNotice("Create DOM");
61        String fileName = taglibAnnotation.fileName().substring(0, taglibAnnotation.fileName().length() - 3) + "xml";
62  
63        writer = getEnv().getFiler().createTextFile(
64            Filer.Location.SOURCE_TREE, packageDeclaration.getQualifiedName(), new File(fileName), null);
65        TransformerFactory transFactory = TransformerFactory.newInstance();
66        transFactory.setAttribute("indent-number", 2);
67        Transformer transformer = transFactory.newTransformer();
68        // TODO transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
69        //   "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN");
70        // TODO transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
71        //   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd");
72        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
73        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
74        transformer.transform(new DOMSource(document), new StreamResult(writer));
75        getEnv().getMessager().printNotice("Write to file " + packageDeclaration.getQualifiedName() + "." + fileName);
76      } finally {
77        IOUtils.closeQuietly(writer);
78      }
79    }
80  
81    @Override
82    protected Element createTag(Declaration decl, Tag tag, String className, Document document, boolean deprecated) {
83      Element tagElement = document.createElement("tag");
84      addDescription(decl, tagElement, document, false);
85      addLeafTextElement(tag.name(), "name", tagElement, document);
86      addLeafTextElement(className, "tag-class", tagElement, document);
87  
88      BodyContent bodyContent = tag.bodyContent();
89      BodyContentDescription contentDescription = decl.getAnnotation(BodyContentDescription.class);
90      // TODO more error checking
91      if (contentDescription != null) {
92        if (bodyContent.equals(BodyContent.JSP)
93            && contentDescription.contentType().length() > 0) {
94          throw new IllegalArgumentException(
95              "contentType " + contentDescription.contentType() + " for bodyContent JSP not allowed!");
96        } else if (bodyContent.equals(BodyContent.TAGDEPENDENT)
97            && contentDescription.contentType().length() == 0) {
98          throw new IllegalArgumentException("contentType should set for tagdependent bodyContent");
99        }
100     }
101 
102     addLeafTextElement(bodyContent.toString(), "body-content", tagElement, document);
103     if (contentDescription != null) {
104       Element bodyContentDescription = document.createElement("body-content-description");
105       for (int i = 0; i < contentDescription.anyClassOf().length; i++) {
106         Element clazz = document.createElement("class");
107         String typeClass = contentDescription.anyClassOf()[i];
108         addLeafTextElement(ClassUtils.getShortClassName(typeClass), "name", clazz, document);
109         addLeafTextElement(ClassUtils.getPackageName(typeClass), "package", clazz, document);
110         bodyContentDescription.appendChild(clazz);
111       }
112       if (contentDescription.anyTagOf().length() > 0) {
113         addLeafTextElement(contentDescription.anyTagOf(), "tags", bodyContentDescription, document);
114       }
115       if (contentDescription.contentType().length() > 0) {
116         addLeafTextElement(contentDescription.contentType(), "content-type", bodyContentDescription, document);
117       }
118       tagElement.appendChild(bodyContentDescription);
119     }
120 
121     return tagElement;
122   }
123 
124   @Override
125   protected void addAttribute(MethodDeclaration method, Element tagElement, Document document) {
126     TagAttribute tagAttribute = method.getAnnotation(TagAttribute.class);
127     if (tagAttribute != null) {
128       UIComponentTagAttribute uiTagAttribute = null;
129       try {
130         uiTagAttribute = method.getAnnotation(UIComponentTagAttribute.class);
131       } catch (RuntimeException e) {
132         e.printStackTrace();
133       }
134       String simpleName = method.getSimpleName();
135       if (simpleName.startsWith("set")) {
136         Element attribute = document.createElement("attribute");
137         addDescription(method, attribute, document);
138         addLeafTextElement(simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH)
139             + simpleName.substring(4), "name", attribute, document);
140         addLeafTextElement(Boolean.toString(tagAttribute.required()), "required", attribute, document);
141         addLeafTextElement(Boolean.toString(tagAttribute.rtexprvalue()), "rtexprvalue", attribute, document);
142         if (uiTagAttribute != null) {
143           addLeafTextElement(uiTagAttribute.expression().toString(), "ui-attribute-expression", attribute, document);
144 
145           String[] uiTypeClasses = uiTagAttribute.type();
146           if (uiTypeClasses.length > 0) {
147             Element uiAttributeType = document.createElement("ui-attribute-type");
148             for (String typeClass : uiTypeClasses) {
149               Element clazz = document.createElement("class");
150               addLeafTextElement(ClassUtils.getShortClassName(typeClass), "name", clazz, document);
151               addLeafTextElement(ClassUtils.getPackageName(typeClass), "package", clazz, document);
152               uiAttributeType.appendChild(clazz);
153             }
154             attribute.appendChild(uiAttributeType);
155           }
156           if (uiTagAttribute.defaultValue().length() > 0) {
157             addLeafTextElement(uiTagAttribute.defaultValue(), "ui-attribute-default-value", attribute, document);
158           }
159 
160         }
161 
162         tagElement.appendChild(attribute);
163       } else {
164         throw new IllegalArgumentException("Only setter allowed found: " + simpleName);
165       }
166     }
167   }
168 }