/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.tobago.apt;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Filer;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.PackageDeclaration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ClassUtils;
import org.apache.myfaces.tobago.apt.annotation.BodyContent;
import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
import org.apache.myfaces.tobago.apt.annotation.Tag;
import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
import org.apache.myfaces.tobago.apt.annotation.Taglib;
import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Locale;
public class TobagoAnnotationVisitor extends TaglibAnnotationVisitor {
public TobagoAnnotationVisitor(AnnotationProcessorEnvironment env) {
super(env);
}
@Override
protected void writeTaglib(PackageDeclaration packageDeclaration, Taglib taglibAnnotation, Document document)
throws IOException, TransformerException {
Writer writer = null;
try {
getEnv().getMessager().printNotice("Create DOM");
String fileName = taglibAnnotation.fileName().substring(0, taglibAnnotation.fileName().length() - 3) + "xml";
writer = getEnv().getFiler().createTextFile(
Filer.Location.SOURCE_TREE, packageDeclaration.getQualifiedName(), new File(fileName), null);
TransformerFactory transFactory = TransformerFactory.newInstance();
transFactory.setAttribute("indent-number", 2);
Transformer transformer = transFactory.newTransformer();
// TODO transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,
// "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN");
// TODO transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
// "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult(writer));
getEnv().getMessager().printNotice("Write to file " + packageDeclaration.getQualifiedName() + "." + fileName);
} finally {
IOUtils.closeQuietly(writer);
}
}
@Override
protected Element createTag(Declaration decl, Tag tag, String className, Document document, boolean deprecated) {
Element tagElement = document.createElement("tag");
addDescription(decl, tagElement, document, false);
addLeafTextElement(tag.name(), "name", tagElement, document);
addLeafTextElement(className, "tag-class", tagElement, document);
BodyContent bodyContent = tag.bodyContent();
BodyContentDescription contentDescription = decl.getAnnotation(BodyContentDescription.class);
// TODO more error checking
if (contentDescription != null) {
if (bodyContent.equals(BodyContent.JSP)
&& contentDescription.contentType().length() > 0) {
throw new IllegalArgumentException(
"contentType " + contentDescription.contentType() + " for bodyContent JSP not allowed!");
} else if (bodyContent.equals(BodyContent.TAGDEPENDENT)
&& contentDescription.contentType().length() == 0) {
throw new IllegalArgumentException("contentType should set for tagdependent bodyContent");
}
}
addLeafTextElement(bodyContent.toString(), "body-content", tagElement, document);
if (contentDescription != null) {
Element bodyContentDescription = document.createElement("body-content-description");
for (int i = 0; i < contentDescription.anyClassOf().length; i++) {
Element clazz = document.createElement("class");
String typeClass = contentDescription.anyClassOf()[i];
addLeafTextElement(ClassUtils.getShortClassName(typeClass), "name", clazz, document);
addLeafTextElement(ClassUtils.getPackageName(typeClass), "package", clazz, document);
bodyContentDescription.appendChild(clazz);
}
if (contentDescription.anyTagOf().length() > 0) {
addLeafTextElement(contentDescription.anyTagOf(), "tags", bodyContentDescription, document);
}
if (contentDescription.contentType().length() > 0) {
addLeafTextElement(contentDescription.contentType(), "content-type", bodyContentDescription, document);
}
tagElement.appendChild(bodyContentDescription);
}
return tagElement;
}
@Override
protected void addAttribute(MethodDeclaration method, Element tagElement, Document document) {
TagAttribute tagAttribute = method.getAnnotation(TagAttribute.class);
if (tagAttribute != null) {
UIComponentTagAttribute uiTagAttribute = null;
try {
uiTagAttribute = method.getAnnotation(UIComponentTagAttribute.class);
} catch (RuntimeException e) {
e.printStackTrace();
}
String simpleName = method.getSimpleName();
if (simpleName.startsWith("set")) {
Element attribute = document.createElement("attribute");
addDescription(method, attribute, document);
addLeafTextElement(simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH)
+ simpleName.substring(4), "name", attribute, document);
addLeafTextElement(Boolean.toString(tagAttribute.required()), "required", attribute, document);
addLeafTextElement(Boolean.toString(tagAttribute.rtexprvalue()), "rtexprvalue", attribute, document);
if (uiTagAttribute != null) {
addLeafTextElement(uiTagAttribute.expression().toString(), "ui-attribute-expression", attribute, document);
String[] uiTypeClasses = uiTagAttribute.type();
if (uiTypeClasses.length > 0) {
Element uiAttributeType = document.createElement("ui-attribute-type");
for (String typeClass : uiTypeClasses) {
Element clazz = document.createElement("class");
addLeafTextElement(ClassUtils.getShortClassName(typeClass), "name", clazz, document);
addLeafTextElement(ClassUtils.getPackageName(typeClass), "package", clazz, document);
uiAttributeType.appendChild(clazz);
}
attribute.appendChild(uiAttributeType);
}
if (uiTagAttribute.defaultValue().length() > 0) {
addLeafTextElement(uiTagAttribute.defaultValue(), "ui-attribute-default-value", attribute, document);
}
}
tagElement.appendChild(attribute);
} else {
throw new IllegalArgumentException("Only setter allowed found: " + simpleName);
}
}
}
}