You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2013/02/08 15:53:02 UTC

svn commit: r1444033 [2/3] - in /myfaces/tobago/trunk: tobago-core/ tobago-core/src/main/java/org/apache/myfaces/tobago/component/ tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/ tobago-example/tobago-example-addressbook-cdi/ to...

Added: myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java?rev=1444033&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java (added)
+++ myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java Fri Feb  8 14:53:00 2013
@@ -0,0 +1,129 @@
+/*
+ * 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.processor;
+
+import org.w3c.dom.Document;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+@SupportedSourceVersion(SourceVersion.RELEASE_5)
+public abstract class AbstractGenerator extends AbstractProcessor {
+
+  static final String JSF_VERSION = "jsfVersion";
+
+  private List<TypeElement> types;
+  private List<PackageElement> packages;
+
+  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+    if (annotations.size() == 0) {
+      // TDB Why this case happen?
+      return false;
+    }
+
+    types = new ArrayList<TypeElement>();
+    packages = new ArrayList<PackageElement>();
+    for (TypeElement element : annotations) {
+      final Collection<? extends Element> elementsAnnotatedWith = roundEnv
+          .getElementsAnnotatedWith(element);
+      for (Element e : elementsAnnotatedWith) {
+        if (e instanceof TypeElement) {
+          if (!types.contains(e)) { // todo: optimize, O(n^2)?
+            types.add((TypeElement) e);
+          }
+        }
+        if (e instanceof PackageElement) {
+          if (!packages.contains(e)) {
+            packages.add((PackageElement) e);
+          }
+        }
+      }
+    }
+
+    Collections.sort(types, new Comparator<TypeElement>() {
+      public int compare(TypeElement d1, TypeElement d2) {
+        return d1.getSimpleName().toString().compareTo(d2.getSimpleName().toString());
+      }
+    });
+
+    configure();
+
+    try {
+      generate();
+    } catch (Exception e) {
+      error(e);
+    }
+
+    return false;
+  }
+
+  protected abstract void configure();
+
+  protected abstract void generate() throws Exception;
+
+  protected void info(String message) {
+    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message);
+  }
+
+  protected void warn(String message) {
+    processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, message);
+  }
+
+  protected void error(Exception e) {
+    final StringWriter out = new StringWriter();
+    e.printStackTrace(new PrintWriter(out));
+    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + e.getMessage() + "\n" + out.toString());
+  }
+
+  protected void addLeafTextElement(String text, String node, org.w3c.dom.Element parent, Document document) {
+    org.w3c.dom.Element element = document.createElement(node);
+    element.appendChild(document.createTextNode(text));
+    parent.appendChild(element);
+  }
+
+  protected void addLeafCDATAElement(String text, String node, org.w3c.dom.Element parent, Document document) {
+    org.w3c.dom.Element element = document.createElement(node);
+    element.appendChild(document.createCDATASection(text));
+    parent.appendChild(element);
+  }
+
+  public List<TypeElement> getTypes() {
+    return types;
+  }
+
+  public List<PackageElement> getPackages() {
+    return packages;
+  }
+}

Copied: myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java (from r1420062, myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/CheckstyleConfigAnnotationVisitor.java)
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java?p2=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java&p1=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/CheckstyleConfigAnnotationVisitor.java&r1=1420062&r2=1444033&rev=1444033&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/CheckstyleConfigAnnotationVisitor.java (original)
+++ myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java Fri Feb  8 14:53:00 2013
@@ -17,24 +17,28 @@
  * under the License.
  */
 
-package org.apache.myfaces.tobago.apt;
+package org.apache.myfaces.tobago.apt.processor;
+
 
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.apt.Filer;
-import com.sun.mirror.declaration.ClassDeclaration;
-import com.sun.mirror.declaration.InterfaceDeclaration;
-import com.sun.mirror.declaration.MethodDeclaration;
-import com.sun.mirror.declaration.PackageDeclaration;
-import com.sun.mirror.type.InterfaceType;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.myfaces.tobago.apt.annotation.ExtensionTag;
 import org.apache.myfaces.tobago.apt.annotation.Tag;
 import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.TagGeneration;
 import org.apache.myfaces.tobago.apt.annotation.Taglib;
 import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -44,23 +48,42 @@ import javax.xml.transform.TransformerEx
 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.Collection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 
-public class CheckstyleConfigAnnotationVisitor extends AbstractAnnotationVisitor {
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib"})
+@SupportedOptions({
+    CheckstyleConfigGenerator.TARGET_CHECKSTYLE})
+public class CheckstyleConfigGenerator extends AbstractGenerator {
+
+  static final String TARGET_CHECKSTYLE = "targetCheckstyle";
 
   private Set<String> tagSet = new HashSet<String>();
 
-  public CheckstyleConfigAnnotationVisitor(AnnotationProcessorEnvironment env) {
-    super(env);
+  private String targetCheckstyle;
+
+  public void configure() {
+    final Map<String, String> options = processingEnv.getOptions();
+    targetCheckstyle = options.get(TARGET_CHECKSTYLE);
+
+    info("Generating the tobago-checkstyle.xml"); // XXX name?
+    info("Options:");
+    info(TARGET_CHECKSTYLE + ": " + targetCheckstyle);
   }
 
-  public void process() throws Exception {
+  public void generate() throws ParserConfigurationException, IOException, TransformerException,
+      ClassNotFoundException {
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     dbf.setValidating(false);
     DocumentBuilder parser = dbf.newDocumentBuilder();
@@ -68,9 +91,9 @@ public class CheckstyleConfigAnnotationV
     Element module = document.createElement("module");
     module.setAttribute("name", "Checker");
 
-    for (PackageDeclaration packageDeclaration : getCollectedPackageDeclarations()) {
-      Taglib taglibAnnotation = packageDeclaration.getAnnotation(Taglib.class);
-      createCheckstyleConfig(taglibAnnotation, packageDeclaration, module, document);
+    for (PackageElement packageElement : getPackages()) {
+      Taglib taglibAnnotation = packageElement.getAnnotation(Taglib.class);
+      createCheckstyleConfig(taglibAnnotation, packageElement, module, document);
     }
 
     document.appendChild(module);
@@ -79,24 +102,17 @@ public class CheckstyleConfigAnnotationV
   }
 
   private Document createCheckstyleConfig(
-      Taglib taglibAnnotation, PackageDeclaration packageDeclaration, Element module, Document document)
-      throws ParserConfigurationException {
+      Taglib taglibAnnotation, PackageElement packageElement, Element module, Document document)
+      throws ParserConfigurationException, ClassNotFoundException {
     resetDuplicateList();
 
-
     addLib(taglibAnnotation, module, document);
 
-    for (ClassDeclaration declaration : getCollectedClassDeclarations()) {
-      if (declaration.getPackage().equals(packageDeclaration)) {
-        appendTag(declaration, taglibAnnotation.shortName(), module, document);
+    for (TypeElement typeElement : getTypes()) {
+      if (processingEnv.getElementUtils().getPackageOf(typeElement).equals(packageElement)) {
+        appendTag(typeElement, taglibAnnotation.shortName(), module, document);
       }
     }
-    for (InterfaceDeclaration declaration : getCollectedInterfaceDeclarations()) {
-      if (declaration.getPackage().equals(packageDeclaration)) {
-        appendTag(declaration, taglibAnnotation.shortName(), module, document);
-      }
-    }
-
     return document;
   }
 
@@ -104,61 +120,55 @@ public class CheckstyleConfigAnnotationV
       IOException, TransformerException {
     Writer writer = null;
     try {
-      getEnv().getMessager().printNotice("Create DOM");
       final String path = "checkstyle-tobago.xml";
-      writer = getEnv().getFiler().createTextFile(
-          Filer.Location.SOURCE_TREE,
-          "",
-          new File(path),
-          null);
+      final String name = (StringUtils.isNotBlank(targetCheckstyle) ? targetCheckstyle + '/' : "") + path;
+      final FileObject resource = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", name);
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
       TransformerFactory transFactory = TransformerFactory.newInstance();
       transFactory.setAttribute("indent-number", 2);
       Transformer transformer = transFactory.newTransformer();
-
       transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//Puppy Crawl//DTD Check Configuration 1.2//EN");
       transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.puppycrawl.com/dtds/configuration_1_2.dtd");
-
       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
       transformer.transform(new DOMSource(document), new StreamResult(writer));
-      getEnv().getMessager().printNotice("Write to file '" + path + "'");
     } finally {
       IOUtils.closeQuietly(writer);
     }
   }
 
-  protected void appendTag(ClassDeclaration declaration, String taglib, Element parent, Document document) {
-    Tag annotationTag = declaration.getAnnotation(Tag.class);
-    checkDuplicates(annotationTag.name());
-    if (declaration.getAnnotation(Deprecated.class) != null) {
-      addTag(taglib, parent, annotationTag.name(), document);
-    }
-    addAttributes(declaration, taglib, parent, annotationTag.name(), document);
-    if (StringUtils.isNotEmpty(annotationTag.deprecatedName())) {
-      addTag(taglib, parent, annotationTag.deprecatedName(), document);
-      addAttributes(declaration, taglib, parent, annotationTag.deprecatedName(), document);
-    }
-  }
-
-  protected void appendTag(InterfaceDeclaration declaration, String taglib, Element parent, Document document) {
-    Tag annotationTag = declaration.getAnnotation(Tag.class);
+  protected void appendTag(TypeElement typeElement, String taglib, Element parent, Document document)
+      throws ClassNotFoundException {
+    Tag annotationTag = typeElement.getAnnotation(Tag.class);
     if (annotationTag != null) {
       checkDuplicates(annotationTag.name());
       // TODO configure replacement
-
-      String className =
-          declaration.getQualifiedName().substring(0, declaration.getQualifiedName().length() - "Declaration".length());
-      if (declaration.getAnnotation(UIComponentTag.class) != null) {
-        className = "org.apache.myfaces.tobago.internal.taglib." + StringUtils.capitalize(annotationTag.name()) + "Tag";
+      final String className;
+      if (typeElement.getAnnotation(TagGeneration.class) != null) {
+        className = typeElement.getAnnotation(TagGeneration.class).className();
+        info("G");
+      } else if (typeElement.getAnnotation(ExtensionTag.class) != null) {
+        className = typeElement.getQualifiedName().toString();
+        info("X");
+      } else if (typeElement.getAnnotation(UIComponentTag.class) != null) {
+        className = "org.apache.myfaces.tobago.internal.taglib." + StringUtils.capitalize(annotationTag.name())
+            + "Tag";
+        info("C");
+      } else {
+        className = typeElement.getQualifiedName().toString()
+            .substring(0, typeElement.getQualifiedName().length() - "Declaration".length());
+        info("?");
+        throw new RuntimeException("Not used, or?"); // XXX
       }
-      String msg = "Replacing: " + declaration.getQualifiedName() + " -> " + className;
-      getEnv().getMessager().printNotice(msg);
-      if (declaration.getAnnotation(Deprecated.class) != null) {
+      info("Replacing: " + typeElement.getQualifiedName() + " -> " + className);
+      if (typeElement.getAnnotation(Deprecated.class) != null) {
         addTag(taglib, parent, annotationTag.name(), document);
       }
-      addAttributes(declaration, taglib, parent, annotationTag.name(), document);
-      if (StringUtils.isNotEmpty(annotationTag.deprecatedName())) {
+      addAttributes(typeElement, taglib, parent, annotationTag.name(), document);
+      if (annotationTag.deprecatedName() != null && annotationTag.deprecatedName().length() > 0) {
         addTag(taglib, parent, annotationTag.deprecatedName(), document);
-        addAttributes(declaration, taglib, parent, annotationTag.name(), document);
+        addAttributes(typeElement, taglib, parent, annotationTag.name(), document);
       }
     }
   }
@@ -168,9 +178,9 @@ public class CheckstyleConfigAnnotationV
     final String format = "<" + taglib + ":" + tagName + "\\b";
     final String message = "The tag '" + tagName + "' is deprecated.";
 
-    Element module = createRegexpModule(format, message, document);
+    Element tag = createRegexpModule(format, message, document);
 
-    parent.appendChild(module);
+    parent.appendChild(tag);
   }
 
   private void checkDuplicates(String tagName) {
@@ -181,48 +191,31 @@ public class CheckstyleConfigAnnotationV
     }
   }
 
-  protected void addAttributes(
-      Collection<InterfaceType> interfaces, String taglib, Element parent, String tagName, Document document) {
-    for (InterfaceType type : interfaces) {
-      addAttributes(type.getDeclaration(), taglib, parent, tagName, document);
-    }
-  }
-
-  protected void addAttributes(
-      InterfaceDeclaration type, String taglib, Element parent, String tagName, Document document) {
-    addAttributes(type.getSuperinterfaces(), taglib, parent, tagName, document);
-    for (MethodDeclaration declaration : getCollectedMethodDeclarations()) {
-      if (declaration.getDeclaringType().equals(type)) {
-        addAttribute(declaration, taglib, parent, tagName, document);
-      }
-    }
+  private void resetDuplicateList() {
+    tagSet = new HashSet<String>();
   }
 
-  protected void addAttributes(
-      ClassDeclaration d, String taglib, Element parent, String tagName, Document document) {
+  protected void addAttributes(TypeElement type, String taglib, Element tagElement, String tagName, Document document)
+      throws ClassNotFoundException {
 
-    for (MethodDeclaration declaration : getCollectedMethodDeclarations()) {
-      if (d.getQualifiedName().
-          equals(declaration.getDeclaringType().getQualifiedName())) {
-        addAttribute(declaration, taglib, parent, tagName, document);
+    for (javax.lang.model.element.Element element : getAllMembers(type)) {
+      if (element instanceof ExecutableElement) {
+        ExecutableElement executableElement = (ExecutableElement) element;
+        if (executableElement.getAnnotation(TagAttribute.class) == null
+            && executableElement.getAnnotation(UIComponentTagAttribute.class) == null) {
+          continue;
+        }
+        addAttribute(executableElement, taglib, tagElement, tagName, document);
       }
     }
-    addAttributes(d.getSuperinterfaces(), taglib, parent, tagName, document);
-    if (d.getSuperclass() != null) {
-      addAttributes(d.getSuperclass().getDeclaration(), taglib, parent, tagName, document);
-    }
-  }
-
-  private void resetDuplicateList() {
-    tagSet = new HashSet<String>();
   }
 
   protected void addAttribute(
-      MethodDeclaration declaration, String taglib, Element parent, String tagName, Document document) {
+      ExecutableElement declaration, String taglib, Element parent, String tagName, Document document) {
     TagAttribute tagAttribute = declaration.getAnnotation(TagAttribute.class);
     Deprecated deprecatedAnnotation = declaration.getAnnotation(Deprecated.class);
     if (tagAttribute != null && deprecatedAnnotation != null) {
-      String simpleName = declaration.getSimpleName();
+      String simpleName = declaration.getSimpleName().toString();
       if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
 
         String attributeStr = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
@@ -242,6 +235,17 @@ public class CheckstyleConfigAnnotationV
     }
   }
 
+  private List<? extends javax.lang.model.element.Element> getAllMembers(TypeElement type) {
+    final List<? extends javax.lang.model.element.Element> members
+        = new ArrayList<javax.lang.model.element.Element>(processingEnv.getElementUtils().getAllMembers(type));
+    Collections.sort(members, new Comparator<javax.lang.model.element.Element>() {
+      public int compare(javax.lang.model.element.Element d1, javax.lang.model.element.Element d2) {
+        return d1.getSimpleName().toString().compareTo(d2.getSimpleName().toString());
+      }
+    });
+    return members;
+  }
+
   private void addLib(Taglib taglibAnnotation, Element parent, Document document) {
 
     final String shortName = taglibAnnotation.shortName();
@@ -279,4 +283,5 @@ public class CheckstyleConfigAnnotationV
 
     return module;
   }
+
 }

Copied: myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java (from r1406180, myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/CreateComponentAnnotationVisitor.java)
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java?p2=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java&p1=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/CreateComponentAnnotationVisitor.java&r1=1406180&r2=1444033&rev=1444033&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/CreateComponentAnnotationVisitor.java (original)
+++ myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java Fri Feb  8 14:53:00 2013
@@ -17,16 +17,8 @@
  * under the License.
  */
 
-package org.apache.myfaces.tobago.apt;
+package org.apache.myfaces.tobago.apt.processor;
 
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.apt.Filer;
-import com.sun.mirror.declaration.ClassDeclaration;
-import com.sun.mirror.declaration.Declaration;
-import com.sun.mirror.declaration.InterfaceDeclaration;
-import com.sun.mirror.declaration.MethodDeclaration;
-import com.sun.mirror.declaration.TypeDeclaration;
-import com.sun.mirror.type.InterfaceType;
 import org.antlr.stringtemplate.StringTemplate;
 import org.antlr.stringtemplate.StringTemplateGroup;
 import org.apache.commons.io.IOUtils;
@@ -44,7 +36,15 @@ import org.apache.myfaces.tobago.apt.gen
 import org.apache.myfaces.tobago.apt.generate.RendererInfo;
 import org.apache.myfaces.tobago.apt.generate.TagInfo;
 
-import java.io.File;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.faces.component.UIComponent;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.FileObject;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -53,8 +53,6 @@ import java.io.Writer;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -62,7 +60,19 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
-public class CreateComponentAnnotationVisitor extends AbstractAnnotationVisitor {
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTag",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib",
+    "org.apache.myfaces.tobago.apt.annotation.TagGeneration"})
+@SupportedOptions({
+    ClassesGenerator.TAG_VERSION,
+    ClassesGenerator.JSF_VERSION})
+public class ClassesGenerator extends AbstractGenerator {
+
+  static final String TAG_VERSION = "tagVersion";
 
   private StringTemplateGroup rendererStringTemplateGroup;
   private StringTemplateGroup tagStringTemplateGroup;
@@ -70,25 +80,21 @@ public class CreateComponentAnnotationVi
   private StringTemplateGroup componentStringTemplateGroup;
   private Set<String> renderer = new HashSet<String>();
   private Set<String> ignoredProperties;
-  private String jsfVersion = "1.1";
-  private String tagVersion = "1.1";
+  private String jsfVersion;
+  private String tagVersion;
 
-  public CreateComponentAnnotationVisitor(AnnotationProcessorEnvironment env) {
-    super(env);
+  public void configure() {
+
+    final Map<String, String> options = processingEnv.getOptions();
+    jsfVersion = options.get(ClassesGenerator.JSF_VERSION);
+    tagVersion = options.get(ClassesGenerator.TAG_VERSION);
+    tagVersion = "1.2"; // XXX
+
+    info("Generating the classes *Tag, *Component, *Renderer");
+    info("Options:");
+    info(JSF_VERSION + ": " + jsfVersion);
+    info(TAG_VERSION + ": " + tagVersion);
 
-    for (Map.Entry<String, String> entry : getEnv().getOptions().entrySet()) {
-      if (entry.getKey().startsWith("-Ajsf-version=")) {
-        String version = entry.getKey().substring("-Ajsf-version=".length());
-        if ("1.2".equals(version)) {
-          jsfVersion = "1.2";
-          tagVersion = "1.2";
-        }
-        if ("2.0".equals(version)) {
-          jsfVersion = "2.0";
-          tagVersion = "1.2";
-        }
-      }
-    }
     InputStream stream = getClass().getClassLoader().getResourceAsStream("org/apache/myfaces/tobago/apt/renderer.stg");
     Reader reader = new InputStreamReader(stream);
     rendererStringTemplateGroup = new StringTemplateGroup(reader);
@@ -111,33 +117,29 @@ public class CreateComponentAnnotationVi
 
   }
 
-  public void process() {
-    for (InterfaceDeclaration declaration : getCollectedInterfaceDeclarations()) {
-      if (declaration.getAnnotation(UIComponentTag.class) != null) {
+  public void generate() throws Exception {
+    for (TypeElement element : getTypes()) {
+      if (element.getAnnotation(UIComponentTag.class) != null) {
         try {
-          createRenderer(declaration);
-          createTagOrComponent(declaration);
-        } catch (IllegalArgumentException e) {
-          getEnv().getMessager().printError("Error during processing of "
-                  + declaration.getAnnotation(UIComponentTag.class).uiComponent());
-          throw e;
+          createRenderer(element);
+          createTagOrComponent(element);
+        } catch (Exception e) {
+          throw new RuntimeException(
+              "Error during processing of " + element.getAnnotation(UIComponentTag.class).uiComponent(), e);
         }
-      }
-    }
-    for (ClassDeclaration declaration : getCollectedClassDeclarations()) {
-      if (declaration.getAnnotation(Tag.class) != null && declaration.getAnnotation(TagGeneration.class) != null) {
-        createTag(declaration);
+      } else if (element.getAnnotation(Tag.class) != null && element.getAnnotation(TagGeneration.class) != null) {
+        createTag(element);
       }
     }
   }
 
-  private void createTag(ClassDeclaration declaration) {
+  private void createTag(TypeElement declaration) throws IOException {
     List<PropertyInfo> properties = new ArrayList<PropertyInfo>();
     addPropertiesForTagOnly(declaration, properties);
     TagGeneration tagGeneration = declaration.getAnnotation(TagGeneration.class);
 
-    TagInfo tagInfo = new TagInfo(declaration.getQualifiedName(), tagGeneration.className());
-    tagInfo.setSuperClass(declaration.getQualifiedName());
+    TagInfo tagInfo = new TagInfo(declaration.getQualifiedName().toString(), tagGeneration.className());
+    tagInfo.setSuperClass(declaration.getQualifiedName().toString());
     StringTemplate stringTemplate = tagAbstractStringTemplateGroup.getInstanceOf("tag");
     stringTemplate.setAttribute("tagInfo", tagInfo);
     tagInfo.getProperties().addAll(properties);
@@ -146,28 +148,20 @@ public class CreateComponentAnnotationVi
     writeFile(tagInfo, stringTemplate);
   }
 
-  private void createTagOrComponent(InterfaceDeclaration declaration) {
+  private void createTagOrComponent(TypeElement declaration) throws IOException, ClassNotFoundException {
     UIComponentTag componentTag = declaration.getAnnotation(UIComponentTag.class);
     Tag tag = declaration.getAnnotation(Tag.class);
     Map<String, PropertyInfo> properties = new HashMap<String, PropertyInfo>();
     addProperties(declaration, properties);
     if (tag != null) {
       String className = "org.apache.myfaces.tobago.internal.taglib." + StringUtils.capitalize(tag.name()) + "Tag";
-      TagInfo tagInfo = new TagInfo(declaration.getQualifiedName(), className, componentTag.rendererType());
+      TagInfo tagInfo = new TagInfo(declaration.getQualifiedName().toString(), className, componentTag.rendererType());
       for (PropertyInfo property : properties.values()) {
         if (property.isTagAttribute()) {
           tagInfo.getProperties().add(property);
         }
       }
-      if (isUnifiedEL()) {
-        tagInfo.setSuperClass("org.apache.myfaces.tobago.internal.taglib.TobagoELTag");
-      } else {
-        if (tagInfo.getBodyContent() != null) {
-          tagInfo.setSuperClass("org.apache.myfaces.tobago.internal.taglib.TobagoBodyTag");
-        } else {
-          tagInfo.setSuperClass("org.apache.myfaces.tobago.internal.taglib.TobagoTag");
-        }
-      }
+      tagInfo.setSuperClass("org.apache.myfaces.tobago.internal.taglib.TobagoELTag");
       tagInfo.setComponentClassName(componentTag.uiComponent());
       tagInfo.addImport("org.apache.commons.lang.StringUtils");
       tagInfo.addImport("org.slf4j.Logger");
@@ -183,52 +177,40 @@ public class CreateComponentAnnotationVi
 
     if (componentTag.generate()) {
       StringTemplate componentStringTemplate = componentStringTemplateGroup.getInstanceOf("component");
-      ComponentInfo componentInfo 
-          = new ComponentInfo(declaration.getQualifiedName(), componentTag.uiComponent(), componentTag.rendererType());
-      
-/*
-      String p = componentTag.uiComponentBaseClass();
-      String c = componentTag.uiComponent();
-      String m = c.substring(0, 36) + "Abstract" + c.substring(36);
-      if (p.equals(m)) {
-        getEnv().getMessager().printNotice("*********** ok   " + c);
-      } else {
-        getEnv().getMessager().printNotice("*********** diff " + c + " " + p);
-      }
-*/
-      
+      ComponentInfo componentInfo = new ComponentInfo(declaration, componentTag);
       componentInfo.setSuperClass(componentTag.uiComponentBaseClass());
-      componentInfo.setComponentFamily(componentTag.componentFamily());
       componentInfo.setDescription(getDescription(declaration));
       componentInfo.setDeprecated(declaration.getAnnotation(Deprecated.class) != null);
-      List<String> elMethods = Collections.emptyList();
-      if (isUnifiedEL()) {
-        elMethods = checkForElMethods(componentInfo, componentTag.interfaces());
-      }
+      List<String> elMethods = checkForElMethods(componentInfo, componentTag.interfaces());
       for (String interfaces : componentTag.interfaces()) {
         componentInfo.addInterface(interfaces);
       }
-      if (componentTag.componentType().length() > 0) {
-        componentInfo.setComponentType(componentTag.componentType());
-      } else {
-        componentInfo.setComponentType(componentTag.uiComponent().replace(".component.UI", "."));
-      }
-      try {
-        Class componentBaseClass = Class.forName(componentTag.uiComponentBaseClass());
-        for (PropertyInfo info : properties.values()) {
-          String methodName
-              = (info.getType().equals("java.lang.Boolean") ? "is" : "get") + info.getUpperCamelCaseName();
 
-          try {
-            Method method = componentBaseClass.getMethod(methodName);
-            if (Modifier.isAbstract(method.getModifiers())) {
-              addPropertyToComponent(componentInfo, info, elMethods, false);
-            }
-          } catch (NoSuchMethodException e) {
-            addPropertyToComponent(componentInfo, info, elMethods, false);
+        Class<? extends UIComponent> facesClass
+            = Class.forName(componentTag.uiComponentFacesClass()).asSubclass(UIComponent.class);
+
+      for (PropertyInfo info : properties.values()) {
+        final String infoType = info.getType();
+        String methodName
+            = ((infoType.equals("java.lang.Boolean") || infoType.equals("boolean")) ? "is" : "get")
+            + info.getUpperCamelCaseName();
+
+        boolean generate = info.isGenerate();
+        try {
+          final Method method = facesClass.getMethod(methodName);
+          if (!Modifier.isAbstract(method.getModifiers())) {
+            generate = false;
           }
+        } catch (NoSuchMethodException e) {
+          // generate = true
+        }
+        if (generate) {
+          addPropertyToComponent(componentInfo, info, elMethods, false);
+        }
+
+//          }
         }
-        boolean found = false;
+/*        boolean found = false;
         for (Method method : componentBaseClass.getMethods()) {
           if ("invokeOnComponent".equals(method.getName())) {
             found = true;
@@ -244,18 +226,21 @@ public class CreateComponentAnnotationVi
         }
 
       } catch (ClassNotFoundException e) {
+      */
+/*
         Map<String, PropertyInfo> baseClassProperties = getBaseClassProperties(componentTag.uiComponentBaseClass());
         for (PropertyInfo info : properties.values()) {
           if (!baseClassProperties.containsValue(info)) {
             addPropertyToComponent(componentInfo, info, elMethods, false);
           }
         }
-      }
+*/
+/*      }
+*/
 
       componentStringTemplate.setAttribute("componentInfo", componentInfo);
       writeFile(componentInfo, componentStringTemplate);
     }
-
   }
 
   private List<String> checkForElMethods(ComponentInfo info, String[] interfaces) {
@@ -280,12 +265,14 @@ public class CreateComponentAnnotationVi
   }
 
   private Map<String, PropertyInfo> getBaseClassProperties(String baseClass) {
-    for (InterfaceDeclaration declaration : getCollectedInterfaceDeclarations()) {
-      if (declaration.getAnnotation(UIComponentTag.class) != null) {
-        if (declaration.getAnnotation(UIComponentTag.class).uiComponent().equals(baseClass)
-            && declaration.getAnnotation(UIComponentTag.class).generate()) {
+
+    for (TypeElement typeElement : getTypes()) {
+      info("bcp " + typeElement);
+      if (typeElement.getAnnotation(UIComponentTag.class) != null) {
+        if (typeElement.getAnnotation(UIComponentTag.class).uiComponent().equals(baseClass)
+            && typeElement.getAnnotation(UIComponentTag.class).generate()) {
           Map<String, PropertyInfo> properties = new HashMap<String, PropertyInfo>();
-          addProperties(declaration, properties);
+          addProperties(typeElement, properties);
           return properties;
         }
       }
@@ -295,13 +282,16 @@ public class CreateComponentAnnotationVi
 
   private ComponentPropertyInfo addPropertyToComponent(
       ComponentInfo componentInfo, PropertyInfo info, List<String> elMethods, boolean methodExpression) {
+
     ComponentPropertyInfo componentPropertyInfo = (ComponentPropertyInfo) info.fill(new ComponentPropertyInfo());
     String possibleUnifiedElAlternative = "set" + info.getUpperCamelCaseName() + "Expression";
     ComponentPropertyInfo elAlternative = null;
+
     if (elMethods.contains(possibleUnifiedElAlternative) && !methodExpression) {
       elAlternative = addPropertyToComponent(componentInfo, info, elMethods, true);
       componentPropertyInfo.setElAlternativeAvailable(true);
     }
+
     componentInfo.addImport(componentPropertyInfo.getUnmodifiedType());
     componentInfo.addImport("javax.faces.context.FacesContext");
 
@@ -320,7 +310,7 @@ public class CreateComponentAnnotationVi
     return componentPropertyInfo;
   }
 
-  private void createRenderer(TypeDeclaration declaration) {
+  private void createRenderer(TypeElement declaration) throws IOException {
 
     UIComponentTag componentTag = declaration.getAnnotation(UIComponentTag.class);
     String rendererType = componentTag.rendererType();
@@ -332,7 +322,7 @@ public class CreateComponentAnnotationVi
         return;
       }
       renderer.add(className);
-      RendererInfo info = new RendererInfo(declaration.getQualifiedName(), className, rendererType);
+      RendererInfo info = new RendererInfo(declaration.getQualifiedName().toString(), className, rendererType);
       if (componentTag.isLayout()) {
         info.setSuperClass("org.apache.myfaces.tobago.renderkit.AbstractLayoutRendererWrapper");
       } else if (componentTag.isTransparentForLayout()) {
@@ -346,34 +336,47 @@ public class CreateComponentAnnotationVi
     }
   }
 
-  protected void addPropertiesForTagOnly(ClassDeclaration type, List<PropertyInfo> properties) {
-    for (MethodDeclaration declaration : getCollectedMethodDeclarations()) {
-      if (declaration.getDeclaringType().equals(type)) {
-        addPropertyForTagOnly(declaration, properties);
+  protected void addPropertiesForTagOnly(TypeElement type, List<PropertyInfo> properties) {
+
+    final List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(type);
+    for (Element member : members) {
+      if (member instanceof ExecutableElement) {
+        final ExecutableElement executableElement = (ExecutableElement) member;
+        addPropertyForTagOnly(executableElement, properties);
       }
     }
   }
 
-  protected void addProperties(InterfaceDeclaration type, Map<String, PropertyInfo> properties) {
-    addProperties(type.getSuperinterfaces(), properties);
-    for (MethodDeclaration declaration : getCollectedMethodDeclarations()) {
-      if (declaration.getDeclaringType().equals(type)) {
-        addProperty(declaration, properties);
+  protected void addProperties(TypeElement type, Map<String, PropertyInfo> properties) {
+    addProperties(type.getInterfaces(), properties);
+    addProperties(type.getSuperclass(), properties);
+
+    final List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(type);
+    for (Element member : members) {
+      if (member instanceof ExecutableElement) {
+        final ExecutableElement executableElement = (ExecutableElement) member;
+        addProperty(executableElement, properties);
       }
     }
   }
 
-  protected void addProperties(Collection<InterfaceType> interfaces, Map<String, PropertyInfo> properties) {
-    for (InterfaceType type : interfaces) {
-      addProperties(type.getDeclaration(), properties);
+  protected void addProperties(List<? extends TypeMirror> interfaces, Map<String, PropertyInfo> properties) {
+    for (TypeMirror typeMirror : interfaces) {
+      addProperties(typeMirror, properties);
     }
   }
 
-  protected void addProperty(MethodDeclaration declaration, Map<String, PropertyInfo> properties) {
+  protected void addProperties(TypeMirror typeMirror, Map<String, PropertyInfo> properties) {
+    if (typeMirror.getKind() != TypeKind.NONE) {
+      addProperties((TypeElement) (processingEnv.getTypeUtils().asElement(typeMirror)), properties);
+    }
+  }
+
+  protected void addProperty(ExecutableElement declaration, Map<String, PropertyInfo> properties) {
     TagAttribute tagAttribute = declaration.getAnnotation(TagAttribute.class);
     UIComponentTagAttribute uiComponentTagAttribute = declaration.getAnnotation(UIComponentTagAttribute.class);
     if (uiComponentTagAttribute != null) {
-      String simpleName = declaration.getSimpleName();
+      String simpleName = declaration.getSimpleName().toString();
       if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
         String name = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
         if (ignoredProperties.contains(name)) {
@@ -411,15 +414,17 @@ public class CreateComponentAnnotationVi
         propertyInfo.setDeprecated(declaration.getAnnotation(Deprecated.class) != null);
         propertyInfo.setDescription(getDescription(declaration));
         propertyInfo.setTransient(uiComponentTagAttribute.isTransient());
+        propertyInfo.setGenerate(uiComponentTagAttribute.generate());
         if (properties.containsKey(name)) {
-          getEnv().getMessager().printWarning("Redefinition of attribute '" + name + "'.");
+          warn("Redefinition of attribute '" + name + "'.");
         }
         properties.put(name, propertyInfo);
       }
     }
   }
-  private String getDescription(Declaration d) {
-    String comment = d.getDocComment();
+
+  private String getDescription(Element element) {
+    String comment = processingEnv.getElementUtils().getDocComment(element);
     if (comment != null) {
       int index = comment.indexOf('@');
       if (index != -1) {
@@ -433,10 +438,10 @@ public class CreateComponentAnnotationVi
     return null;
   }
 
-  protected void addPropertyForTagOnly(MethodDeclaration declaration, List<PropertyInfo> properties) {
+  protected void addPropertyForTagOnly(ExecutableElement declaration, List<PropertyInfo> properties) {
     TagAttribute tagAttribute = declaration.getAnnotation(TagAttribute.class);
     if (tagAttribute != null) {
-      String simpleName = declaration.getSimpleName();
+      String simpleName = declaration.getSimpleName().toString();
       if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
         String attributeStr = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
         if (tagAttribute.name().length() > 0) {
@@ -449,20 +454,17 @@ public class CreateComponentAnnotationVi
     }
   }
 
-  private void writeFile(ClassInfo info, StringTemplate stringTemplate) {
+  private void writeFile(ClassInfo info, StringTemplate stringTemplate) throws IOException {
     Writer writer = null;
     try {
-      writer = getEnv().getFiler().createTextFile(Filer.Location.SOURCE_TREE, info.getPackageName(),
-          new File(info.getClassName() + ".java"), null);
+      final FileObject resource = processingEnv.getFiler().createSourceFile(
+          info.getPackageName() + '.' + info.getClassName());
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
       writer.append(stringTemplate.toString());
-    } catch (IOException e) {
-      e.printStackTrace();
     } finally {
       IOUtils.closeQuietly(writer);
     }
   }
-
-  private boolean isUnifiedEL() {
-    return !"1.1".equals(jsfVersion);
-  }
 }

Copied: myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FaceletGenerator.java (from r1406180, myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/FaceletAnnotationVisitor.java)
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FaceletGenerator.java?p2=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FaceletGenerator.java&p1=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/FaceletAnnotationVisitor.java&r1=1406180&r2=1444033&rev=1444033&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/FaceletAnnotationVisitor.java (original)
+++ myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FaceletGenerator.java Fri Feb  8 14:53:00 2013
@@ -17,16 +17,14 @@
  * under the License.
  */
 
-package org.apache.myfaces.tobago.apt;
+package org.apache.myfaces.tobago.apt.processor;
 
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.apt.Filer;
-import com.sun.mirror.declaration.InterfaceDeclaration;
-import com.sun.mirror.declaration.PackageDeclaration;
 import org.apache.commons.io.IOUtils;
 import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagGeneration;
 import org.apache.myfaces.tobago.apt.annotation.Taglib;
 import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.generate.TagInfo;
 import org.codehaus.modello.plugin.java.javasource.JClass;
 import org.codehaus.modello.plugin.java.javasource.JCompUnit;
 import org.codehaus.modello.plugin.java.javasource.JConstructor;
@@ -35,7 +33,11 @@ import org.codehaus.modello.plugin.java.
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.faces.component.UIComponent;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -45,34 +47,26 @@ import javax.xml.transform.TransformerEx
 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.lang.reflect.Field;
-import java.util.HashSet;
-import java.util.Set;
-
-/*
- * Date: 30.03.2006
- * Time: 19:26:18
- */
-public class FaceletAnnotationVisitor extends AbstractAnnotationVisitor {
-
-  public FaceletAnnotationVisitor(AnnotationProcessorEnvironment env) {
-    super(env);
-  }
 
-  public void process() throws Exception {
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute"})
+public class FaceletGenerator extends AbstractGenerator {
 
-    for (PackageDeclaration packageDeclaration : getCollectedPackageDeclarations()) {
-      Taglib taglibAnnotation = packageDeclaration.getAnnotation(Taglib.class);
+  public void configure() {
+    info("Generating the *.taglib.xml");
+  }
 
-      Set<String> tagSet = new HashSet<String>();
-      String packageName = "org.apache.myfaces.tobago.facelets";
+  public void generate() throws Exception {
 
-      JClass libraryClass = new JClass("TobagoTagLibrary");
-      libraryClass.setPackageName(packageName);
+    for (PackageElement packageElement : getPackages()) {
+      Taglib taglibAnnotation = packageElement.getAnnotation(Taglib.class);
 
+      JClass libraryClass = new JClass("org.apache.myfaces.tobago.facelets.TobagoTagLibrary");
       JCompUnit unit = new JCompUnit(libraryClass);
       libraryClass.setSuperClass("AbstractTobagoTagLibrary");
 
@@ -80,40 +74,41 @@ public class FaceletAnnotationVisitor ex
       nameSpace.getModifiers().setFinal(true);
       nameSpace.getModifiers().setStatic(true);
       nameSpace.getModifiers().makePublic();
-      nameSpace.setInitString("\""+taglibAnnotation.uri()+"\"");
+      nameSpace.setInitString("\"" + taglibAnnotation.uri() + "\"");
       libraryClass.addField(nameSpace);
 
       JField instance = new JField(libraryClass, "INSTANCE");
       instance.getModifiers().setFinal(true);
       instance.getModifiers().setStatic(true);
       instance.getModifiers().makePublic();
-      instance.setInitString("new "+libraryClass.getName(true) +"()");
+      instance.setInitString("new " + libraryClass.getName(true) + "()");
       libraryClass.addField(instance);
       JConstructor constructor = libraryClass.createConstructor();
       constructor.getSourceCode().add("super(NAMESPACE);");
 
-      for (InterfaceDeclaration decl : getCollectedInterfaceDeclarations()) {
-        if (decl.getPackage().equals(packageDeclaration)) {
-          appendComponent(constructor, decl, tagSet);
+      for (TypeElement typeElement : getTypes()) {
+        if (processingEnv.getElementUtils().getPackageOf(typeElement).equals(packageElement)) {
+          appendComponent(constructor, typeElement);
         }
       }
       Document document = createDocument(libraryClass);
 
-      writeFaceletTaglibConfig(taglibAnnotation, document, packageDeclaration);
+      writeFaceletTaglibConfig(taglibAnnotation, document, packageElement);
       writeFaceletTaglibHandler(unit, libraryClass);
     }
   }
 
-  private void writeFaceletTaglibConfig(Taglib taglibAnnotation, Document document,
-      PackageDeclaration packageDeclaration) throws IOException, TransformerException {
-    Writer faceletsConfigWriter = null;
+  private void writeFaceletTaglibConfig(
+      Taglib taglibAnnotation, Document document, PackageElement packageElement)
+      throws IOException, TransformerException {
+    Writer writer = null;
     try {
-      getEnv().getMessager().printNotice("Create facelets taglib config");
       String fileName =
-          taglibAnnotation.fileName().substring(0, taglibAnnotation.fileName().length()-3) + "taglib.xml";
-
-      faceletsConfigWriter =
-          getEnv().getFiler().createTextFile(Filer.Location.SOURCE_TREE, "", new File(fileName), null);
+          taglibAnnotation.fileName().substring(0, taglibAnnotation.fileName().length() - 3) + "taglib.xml";
+      final FileObject resource
+          = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", fileName);
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
       TransformerFactory transFactory = TransformerFactory.newInstance();
       transFactory.setAttribute("indent-number", 2);
       Transformer transformer = transFactory.newTransformer();
@@ -123,23 +118,27 @@ public class FaceletAnnotationVisitor ex
           "http://java.sun.com/dtd/facelet-taglib_1_0.dtd");
       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
       transformer.transform(new DOMSource(document),
-          new StreamResult(faceletsConfigWriter));
-      getEnv().getMessager().printNotice("Write to file " + packageDeclaration.getQualifiedName() + " " + fileName);
-    } finally{
-      IOUtils.closeQuietly(faceletsConfigWriter);
+          new StreamResult(writer));
+      info("Write to file " + packageElement.getQualifiedName() + " " + fileName);
+    } finally {
+      IOUtils.closeQuietly(writer);
     }
   }
 
   private void writeFaceletTaglibHandler(JCompUnit unit, JClass clazz) throws IOException {
-    JSourceWriter sourceWriter = null;
+    JSourceWriter writer = null;
     try {
-      Writer writer = getEnv().getFiler().createTextFile(Filer.Location.SOURCE_TREE,
-          unit.getPackageName(),
-          new File(clazz.getLocalName()+".java"), null);
-      sourceWriter = new JSourceWriter(writer);
-      unit.print(sourceWriter);
-    } finally{
-      IOUtils.closeQuietly(sourceWriter);
+      final FileObject resource = processingEnv.getFiler().createResource(
+          StandardLocation.SOURCE_OUTPUT, unit.getPackageName(), clazz.getLocalName() + ".java");
+      info("Writing to file: " + resource.toUri());
+      writer = new JSourceWriter(resource.openWriter());
+      unit.print(writer);
+    } finally {
+      try {
+        IOUtils.closeQuietly(writer);
+      } catch (NullPointerException e) {
+        // ignore, TODO: Why this will happen?
+      }
     }
   }
 
@@ -156,31 +155,34 @@ public class FaceletAnnotationVisitor ex
     return document;
   }
 
-  protected void appendComponent(JConstructor constructor, InterfaceDeclaration decl, Set<String> tagSet) {
-
-    Tag annotationTag = decl.getAnnotation(Tag.class);
+  protected void appendComponent(JConstructor constructor, TypeElement typeElement) {
+    Tag annotationTag = typeElement.getAnnotation(Tag.class);
     if (annotationTag != null) {
-      createTag(constructor, decl, annotationTag);
-
+      createTag(constructor, typeElement, annotationTag);
     }
   }
 
-  protected void createTag(JConstructor constructor, InterfaceDeclaration decl, Tag annotationTag) {
-    UIComponentTag componentTag = decl.getAnnotation(UIComponentTag.class);
+  protected void createTag(JConstructor constructor, TypeElement typeElement, Tag annotationTag) {
+    UIComponentTag componentTag = typeElement.getAnnotation(UIComponentTag.class);
     if (componentTag == null) {
       return;
     }
     try {
-      ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
-      Thread.currentThread().setContextClassLoader(UIComponent.class.getClassLoader());
-      Class uiComponentClass = Class.forName(componentTag.uiComponent());
+
+      TagGeneration tagGeneration = typeElement.getAnnotation(TagGeneration.class);
+      TagInfo tagInfo = new TagInfo(typeElement.getQualifiedName().toString(), tagGeneration.className());
+      tagInfo.getComponentType();
+
+//      ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
+//      Thread.currentThread().setContextClassLoader(UIComponent.class.getClassLoader());
+//      Class uiComponentClass = Class.forName(componentTag.uiComponent());
 
       StringBuilder addComponent = new StringBuilder("addTobagoComponent(\"");
       addComponent.append(annotationTag.name());
 
-      Field componentField = uiComponentClass.getField("COMPONENT_TYPE");
-      String componentType = (String) componentField.get(null);
-      Thread.currentThread().setContextClassLoader(currentClassLoader);
+//      Field componentField = uiComponentClass.getField("COMPONENT_TYPE");
+      String componentType = "hallo"; // xxx (String) componentField.get(null);
+//      Thread.currentThread().setContextClassLoader(currentClassLoader);
 
       addComponent.append("\", \"");
       addComponent.append(componentType);

Copied: myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java (from r1406180, myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/FacesConfigAnnotationProcessor.java)
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java?p2=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java&p1=myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/FacesConfigAnnotationProcessor.java&r1=1406180&r2=1444033&rev=1444033&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/FacesConfigAnnotationProcessor.java (original)
+++ myfaces/tobago/trunk/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java Fri Feb  8 14:53:00 2013
@@ -17,53 +17,675 @@
  * under the License.
  */
 
-package org.apache.myfaces.tobago.apt;
+package org.apache.myfaces.tobago.apt.processor;
 
-import com.sun.mirror.apt.AnnotationProcessor;
-import com.sun.mirror.apt.AnnotationProcessorEnvironment;
-import com.sun.mirror.declaration.AnnotationTypeDeclaration;
-import com.sun.mirror.declaration.Declaration;
-import com.sun.mirror.util.DeclarationVisitors;
+import org.apache.commons.io.IOUtils;
+import org.apache.myfaces.tobago.apt.annotation.Converter;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.Validator;
+import org.apache.myfaces.tobago.apt.generate.ComponentInfo;
+import org.codehaus.plexus.util.FileUtils;
+import org.jdom.Attribute;
+import org.jdom.Comment;
+import org.jdom.Document;
+import org.jdom.Namespace;
+import org.jdom.filter.ContentFilter;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
-import javax.xml.parsers.ParserConfigurationException;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
 import java.io.IOException;
-import java.util.Collection;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTag",
+    "org.apache.myfaces.tobago.apt.annotation.Facet",
+    "org.apache.myfaces.tobago.apt.annotation.Preliminary",
+    "org.apache.myfaces.tobago.apt.annotation.Converter",
+    "org.apache.myfaces.tobago.apt.annotation.Validator"})
+@SupportedOptions({
+    FacesConfigGenerator.SOURCE_FACES_CONFIG,
+    FacesConfigGenerator.TARGET_FACES_CONFIG,
+    FacesConfigGenerator.JSF_VERSION})
+public class FacesConfigGenerator extends AbstractGenerator {
 
+  static final String SOURCE_FACES_CONFIG = "sourceFacesConfig";
+  static final String TARGET_FACES_CONFIG = "targetFacesConfig";
+
+  private static final String SEPARATOR = System.getProperty("line.separator");
+  private static final String COMPONENT = "component";
+  private static final String COMPONENT_TYPE = "component-type";
+  private static final String COMPONENT_CLASS = "component-class";
+  private static final String COMPONENT_EXTENSION = "component-extension";
+  private static final String ALLOWED_CHILD_COMPONENTS = "allowed-child-components";
+  private static final String CATEGORY = "category";
+  private static final String DEPRECATED = "deprecated";
+  private static final String HIDDEN = "hidden";
+  private static final String FACET = "facet";
+  private static final String DISPLAY_NAME = "display-name";
+  private static final String DESCRIPTION = "description";
+  private static final String FACET_NAME = "facet-name";
+  private static final String FACET_EXTENSION = "facet-extension";
+  private static final String PROPERTY = "property";
+  private static final String PROPERTY_NAME = "property-name";
+  private static final String PROPERTY_CLASS = "property-class";
+  private static final String PROPERTY_EXTENSION = "property-extension";
+  private static final String VALUE_EXPRESSION = "value-expression"; //UIComponentTagAttribute.valueExpression()
+  private static final String PROPERTY_VALUES = "property-values"; //UIComponentTagAttribute.allowedValues()
+  private static final String READONLY = "read-only";
+  private static final String REQUIRED = "required"; //UITagAttribute.required()
+  private static final String DEFAULT_VALUE = "default-value";
+  private static final String ATTRIBUTE = "attribute";
+  private static final String ATTRIBUTE_NAME = "attribute-name";
+  private static final String ATTRIBUTE_CLASS = "attribute-class";
+  private static final String ATTRIBUTE_EXTENSION = "attribute-extension";
+  private static final String APPLICATION = "application";
+  private static final String FACTORY = "factory";
+  private static final String CONVERTER = "converter";
+  private static final String CONVERTER_ID = "converter-id";
+  private static final String CONVERTER_FOR_CLASS = "converter-for-class";
+  private static final String CONVERTER_CLASS = "converter-class";
+  private static final String VALIDATOR = "validator";
+  private static final String VALIDATOR_ID = "validator-id";
+  private static final String VALIDATOR_FOR_CLASS = "validator-for-class";
+  private static final String VALIDATOR_CLASS = "validator-class";
+  private static final String RENDERER = "renderer";
+  private static final String COMPONENT_FAMILY = "component-family";
+  private static final String RENDER_KIT = "render-kit";
+  private static final String RENDER_KIT_ID = "render-kit-id";
+  private static final String RENDER_KIT_CLASS = "render-kit-class";
+  private static final String RENDERER_TYPE = "renderer-type";
+  private static final String RENDERER_CLASS = "renderer-class";
+
+  private static final Set<String> IGNORED_PROPERTIES = new HashSet<String>(Arrays.asList("binding"));
+
+  private String jsfVersion;
+  private String sourceFacesConfigFile;
+  private String targetFacesConfigFile;
+
+  @Override
+  public void configure() {
+    final Map<String, String> options = processingEnv.getOptions();
+    jsfVersion = options.get(JSF_VERSION);
+    sourceFacesConfigFile = options.get(SOURCE_FACES_CONFIG);
+    targetFacesConfigFile = options.get(TARGET_FACES_CONFIG);
+
+    info("Generating the faces-config.xml");
+    info("Options:");
+    info(SOURCE_FACES_CONFIG + ": " + sourceFacesConfigFile);
+    info(TARGET_FACES_CONFIG + ": " + targetFacesConfigFile);
+    info(JSF_VERSION + ": " + jsfVersion);
+  }
+
+  @Override
+  protected void generate() throws Exception {
+    Document document;
+    Writer writer = null;
+    try {
+      String content = FileUtils.fileRead(sourceFacesConfigFile);
+      SAXBuilder builder = new SAXBuilder();
+      builder.setEntityResolver(new EntityResolver() {
+        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+          if ("-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN".equals(publicId)) {
+            InputStream stream = getClass().getResourceAsStream(
+                "/org/apache/myfaces/tobago/dtd/web-facesconfig_1_1.dtd");
+            return new InputSource(stream);
+          }
+          return null;
+        }
+      });
+      document = builder.build(new StringReader(content));
+
+      // Normalise line endings. For some reason, JDOM replaces \r\n inside a comment with \n.
+      normaliseLineEndings(document);
+
+      // rewrite DOM as a string to find differences, since text outside the root element is not tracked
+
+      org.jdom.Element rootElement = document.getRootElement();
+      if (is12()) {
+        rootElement.setNamespace(Namespace.getNamespace("http://java.sun.com/xml/ns/javaee"));
+        Namespace xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+        rootElement.addNamespaceDeclaration(Namespace.getNamespace("xi", "http://www.w3.org/2001/XInclude"));
+        rootElement.setAttribute(new Attribute("schemaLocation",
+            "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd", xsi));
+        rootElement.setAttribute("version", "1.2");
+      } else if (is20()) {
+        rootElement.setNamespace(Namespace.getNamespace("http://java.sun.com/xml/ns/javaee"));
+        Namespace xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+        rootElement.addNamespaceDeclaration(Namespace.getNamespace("xi", "http://www.w3.org/2001/XInclude"));
+        rootElement.setAttribute(new Attribute("schemaLocation",
+            "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd", xsi));
+        rootElement.setAttribute("version", "2.0");
+      }
+      Namespace namespace = rootElement.getNamespace();
+      if (is12() || is20()) {
+        applyNamespace(rootElement, namespace);
+      }
+      List<org.jdom.Element> components = rootElement.getChildren(COMPONENT, namespace);
+
+      List<org.jdom.Element> newComponents = new ArrayList<org.jdom.Element>();
+      List<org.jdom.Element> newRenderer = new ArrayList<org.jdom.Element>();
+      List<org.jdom.Element> newConverters = new ArrayList<org.jdom.Element>();
+      List<org.jdom.Element> newValidators = new ArrayList<org.jdom.Element>();
+
+      for (TypeElement element : getTypes()) {
+        if (element.getAnnotation(UIComponentTag.class) != null) {
+          addElement(element, newComponents, newRenderer, namespace);
+        } else if (element.getAnnotation(Converter.class) != null) {
+          addConverter(element, newConverters, namespace);
+        } else if (element.getAnnotation(Validator.class) != null) {
+          addValidator(element, newValidators, namespace);
+        }
+      }
+
+      List<org.jdom.Element> elementsToAdd = new ArrayList<org.jdom.Element>();
+      // sort out duplicates
+      for (org.jdom.Element newElement : newComponents) {
+        boolean found = containsElement(components, newElement);
+        if (!found) {
+          elementsToAdd.add(newElement);
+        }
+      }
+      if (!elementsToAdd.isEmpty()) {
+        // if faces-config contains no component section add the components after factory or application
+        int lastIndex = getIndexAfter(rootElement, COMPONENT, FACTORY, APPLICATION);
+        rootElement.addContent(lastIndex, elementsToAdd);
+      }
+      if (!newRenderer.isEmpty()) {
+        org.jdom.Element renderKit = new org.jdom.Element(RENDER_KIT, namespace);
+        org.jdom.Element renderKitId = new org.jdom.Element(RENDER_KIT_ID, namespace);
+        renderKitId.setText("tobago");
+        renderKit.addContent(renderKitId);
+        org.jdom.Element renderKitClass = new org.jdom.Element(RENDER_KIT_CLASS, namespace);
+        renderKitClass.setText("org.apache.myfaces.tobago.renderkit.TobagoRenderKit");
+        renderKit.addContent(renderKitClass);
+        renderKit.addContent(newRenderer);
+        int lastIndex = getIndexAfter(rootElement, CONVERTER, COMPONENT, FACTORY, APPLICATION);
+        rootElement.addContent(lastIndex, renderKit);
+      }
+      if (!newConverters.isEmpty()) {
+        int lastIndex = getIndexAfter(rootElement, RENDER_KIT, CONVERTER, COMPONENT, FACTORY, APPLICATION);
+        rootElement.addContent(lastIndex, newConverters);
+      }
+      if (!newValidators.isEmpty()) {
+        rootElement.addContent(newValidators);
+      }
+      final FileObject resource = processingEnv.getFiler().createResource(
+          StandardLocation.SOURCE_OUTPUT, "", targetFacesConfigFile);
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
+      StringWriter facesConfig = new StringWriter(1024);
+      Format format = Format.getPrettyFormat();
+      format.setLineSeparator(SEPARATOR);
+      XMLOutputter out = new XMLOutputter(format);
+      out.output(document, facesConfig);
+      writer.append(facesConfig.toString());
+
+    } finally {
+      IOUtils.closeQuietly(writer);
+    }
+  }
+
+  private void applyNamespace(org.jdom.Element parent, Namespace namespace) {
+    for (org.jdom.Element element : (List<org.jdom.Element>) parent.getChildren()) {
+      element.setNamespace(namespace);
+      applyNamespace(element, namespace);
+    }
+  }
+
+  private void addConverter(TypeElement typeElement, List<org.jdom.Element> newConverters, Namespace namespace) {
+    Converter converterAnn = typeElement.getAnnotation(Converter.class);
+    org.jdom.Element converter = new org.jdom.Element(CONVERTER, namespace);
+    if (converterAnn.id().length() > 0) {
+      org.jdom.Element converterId = new org.jdom.Element(CONVERTER_ID, namespace);
+      converterId.setText(converterAnn.id());
+      converter.addContent(converterId);
+    } else if (converterAnn.forClass().length() > 0) {
+      org.jdom.Element converterForClass = new org.jdom.Element(CONVERTER_FOR_CLASS, namespace);
+      converterForClass.setText(converterAnn.forClass());
+      converter.addContent(converterForClass);
+    }
+
+    org.jdom.Element converterClass = new org.jdom.Element(CONVERTER_CLASS, namespace);
+    converterClass.setText(typeElement.getQualifiedName().toString());
+    converter.addContent(converterClass);
+    newConverters.add(converter);
+  }
+
+  private void addValidator(TypeElement typeElement, List<org.jdom.Element> newValidators, Namespace namespace) {
+    Validator validatorAnn = typeElement.getAnnotation(Validator.class);
+    org.jdom.Element validator = new org.jdom.Element(VALIDATOR, namespace);
+    if (validatorAnn.id().length() > 0) {
+      org.jdom.Element validatorId = new org.jdom.Element(VALIDATOR_ID, namespace);
+      validatorId.setText(validatorAnn.id());
+      validator.addContent(validatorId);
+    } else if (validatorAnn.forClass().length() > 0) {
+      org.jdom.Element validatorForClass = new org.jdom.Element(VALIDATOR_FOR_CLASS, namespace);
+      validatorForClass.setText(validatorAnn.forClass());
+      validator.addContent(validatorForClass);
+    }
+
+    org.jdom.Element validatorClass = new org.jdom.Element(VALIDATOR_CLASS, namespace);
+    validatorClass.setText(typeElement.getQualifiedName().toString());
+    validator.addContent(validatorClass);
+    newValidators.add(validator);
+  }
+
+  private boolean containsElement(List<org.jdom.Element> components, org.jdom.Element newElement) {
+    return getEqualElement(components, newElement) != null;
+  }
+
+  private org.jdom.Element getEqualElement(List<org.jdom.Element> components, org.jdom.Element newElement) {
+    for (org.jdom.Element element : components) {
+      if (equals(element, newElement)) {
+        return element;
+      }
+    }
+    return null;
+  }
+
+  private int getIndexAfter(org.jdom.Element rootElement, String... tagNames) {
+    for (String tagName : tagNames) {
+      int index = getIndexAfter(rootElement, tagName);
+      if (index != 0) {
+        return index;
+      }
+    }
+    return 0;
+  }
+
+  private int getIndexAfter(org.jdom.Element rootElement, String tagName) {
+    List<org.jdom.Element> components = rootElement.getChildren(tagName, rootElement.getNamespace());
+    if (!components.isEmpty()) {
+      return rootElement.indexOf(components.get(components.size() - 1)) + 1;
+    }
+    return 0;
+  }
+
+  public boolean equals(org.jdom.Element element1, org.jdom.Element element2) {
+    Namespace namespace = element1.getNamespace();
+    if (element1.getName().equals(element2.getName()) && element1.getNamespace().equals(element2.getNamespace())) {
+      if (element1.getChildText(COMPONENT_CLASS, namespace).equals(element2.getChildText(COMPONENT_CLASS, namespace))) {
+        if (element1.getChildText(COMPONENT_TYPE, namespace).equals(element2.getChildText(COMPONENT_TYPE, namespace))) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  protected org.jdom.Element createComponentElement(
+      ComponentInfo componentInfo, UIComponentTag componentTag, Namespace namespace)
+      throws IOException, NoSuchFieldException, IllegalAccessException {
+    org.jdom.Element element = new org.jdom.Element(COMPONENT, namespace);
+    org.jdom.Element elementDisplayName = new org.jdom.Element(DISPLAY_NAME, namespace);
+    elementDisplayName.setText(componentInfo.getComponentClassName());
+    element.addContent(elementDisplayName);
+    org.jdom.Element elementType = new org.jdom.Element(COMPONENT_TYPE, namespace);
+    elementType.setText(componentInfo.getComponentType());
+    element.addContent(elementType);
+    org.jdom.Element elementClass = new org.jdom.Element(COMPONENT_CLASS, namespace);
+    elementClass.setText(componentTag.uiComponent());
+    element.addContent(elementClass);
+
+    return element;
+  }
+
+  protected void addRendererElement(
+      ComponentInfo componentInfo, UIComponentTag componentTag, List<org.jdom.Element> renderer, Namespace namespace)
+      throws IOException, NoSuchFieldException, IllegalAccessException {
+    String rendererType = componentTag.rendererType();
+    if (rendererType != null && rendererType.length() > 0) {
+      org.jdom.Element element = new org.jdom.Element(RENDERER, namespace);
+      String displayName = componentTag.displayName();
+      if (displayName.equals("")) {
+        displayName = componentInfo.getComponentClassName();
+      }
+      org.jdom.Element elementDisplayName = new org.jdom.Element(DISPLAY_NAME, namespace);
+      elementDisplayName.setText(displayName);
+      element.addContent(elementDisplayName);
+      org.jdom.Element elementComponentFamily = new org.jdom.Element(COMPONENT_FAMILY, namespace);
+      elementComponentFamily.addContent(componentInfo.getComponentFamily());
+      element.addContent(elementComponentFamily);
+      org.jdom.Element elementType = new org.jdom.Element(RENDERER_TYPE, namespace);
+      elementType.setText(rendererType);
+      element.addContent(elementType);
+      org.jdom.Element elementClass = new org.jdom.Element(RENDERER_CLASS, namespace);
+      String className = "org.apache.myfaces.tobago.renderkit." + rendererType + "Renderer";
+      elementClass.setText(className);
+      element.addContent(elementClass);
+      renderer.add(element);
+    }
+  }
+
+
+  private org.jdom.Element createElementExtension(
+      TypeElement typeElement, UIComponentTag uiComponentTag,
+      Namespace namespace) {
+    org.jdom.Element elementExtension = new org.jdom.Element(COMPONENT_EXTENSION, namespace);
+    org.jdom.Element elementAllowedChildComponents = new org.jdom.Element(ALLOWED_CHILD_COMPONENTS, namespace);
+    String[] allowedChildComponents = uiComponentTag.allowedChildComponenents();
+    String allowedComponentTypes = "";
+    for (String componentType : allowedChildComponents) {
+      allowedComponentTypes += componentType + " ";
+    }
+    elementAllowedChildComponents.setText(allowedComponentTypes);
+    elementExtension.addContent(elementAllowedChildComponents);
+    org.jdom.Element elementCategory = new org.jdom.Element(CATEGORY, namespace);
+    elementCategory.setText(uiComponentTag.category().toString());
+    elementExtension.addContent(elementCategory);
+    Deprecated deprecated = typeElement.getAnnotation(Deprecated.class);
+    if (deprecated != null) {
+      org.jdom.Element elementDeprecated = new org.jdom.Element(DEPRECATED, namespace);
+      elementDeprecated.setText("Warning: This component is deprecated!");
+      elementExtension.addContent(elementDeprecated);
+    }
+    org.jdom.Element elementHidden = new org.jdom.Element(HIDDEN, namespace);
+    elementHidden.setText(Boolean.toString(uiComponentTag.isHidden()));
+    elementExtension.addContent(elementHidden);
+
+    return elementExtension;
+  }
+
+  protected void addAttribute(
+      ExecutableElement executableElement, List<org.jdom.Element> attributes, List<org.jdom.Element> properties,
+      Namespace namespace) {
+    UIComponentTagAttribute componentAttribute = executableElement.getAnnotation(UIComponentTagAttribute.class);
+    if (componentAttribute != null) {
+      String simpleName = executableElement.getSimpleName().toString();
+      if (simpleName.startsWith("set")) {
+        String name = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
+        if (IGNORED_PROPERTIES.contains(name)) {
+          org.jdom.Element attribute = new org.jdom.Element(ATTRIBUTE, namespace);
+          org.jdom.Element attributeName = new org.jdom.Element(ATTRIBUTE_NAME, namespace);
+          org.jdom.Element attributeClass = new org.jdom.Element(ATTRIBUTE_CLASS, namespace);
+
+          attributeName.setText(name);
+          addClass(componentAttribute, attributeClass);
+
+          addDescription(executableElement, attribute, namespace);
+
+          attribute.addContent(attributeName);
+          attribute.addContent(attributeClass);
+          if (componentAttribute.defaultValue().length() > 0) {
+            org.jdom.Element defaultValue = new org.jdom.Element(DEFAULT_VALUE, namespace);
+            defaultValue.setText(componentAttribute.defaultValue());
+            attribute.addContent(defaultValue);
+          }
+
+          attribute.addContent(createPropertyOrAttributeExtension(ATTRIBUTE_EXTENSION, executableElement,
+              componentAttribute, namespace));
+
+          attributes.add(attribute);
+        } else {
+          org.jdom.Element property = new org.jdom.Element(PROPERTY, namespace);
+          org.jdom.Element propertyName = new org.jdom.Element(PROPERTY_NAME, namespace);
+          org.jdom.Element propertyClass = new org.jdom.Element(PROPERTY_CLASS, namespace);
+
+          propertyName.setText(name);
+          addClass(componentAttribute, propertyClass);
+
+          addDescription(executableElement, property, namespace);
+
+          property.addContent(propertyName);
+          property.addContent(propertyClass);
+          if (componentAttribute.defaultValue().length() > 0) {
+            org.jdom.Element defaultValue = new org.jdom.Element(DEFAULT_VALUE, namespace);
+            defaultValue.setText(componentAttribute.defaultValue());
+            property.addContent(defaultValue);
+          }
+
+          property.addContent(
+              createPropertyOrAttributeExtension(PROPERTY_EXTENSION, executableElement, componentAttribute, namespace));
+          properties.add(property);
+        }
+      } else {
+        throw new IllegalArgumentException("Only setter allowed found: " + simpleName);
+      }
+    }
+  }
+
+  private void addClass(UIComponentTagAttribute componentAttribute, org.jdom.Element attributeClass) {
+    if (componentAttribute.type().length > 1) {
+      attributeClass.setText(Object.class.getName());
+    } else if (componentAttribute.type().length == 1) {
+      String className = componentAttribute.type()[0];
+      if (componentAttribute.expression().isMethodExpression()) {
+        className = "javax.el.MethodExpression";
+      }
+      attributeClass.setText(className);
+    } else {
+      if (componentAttribute.expression().isMethodExpression()) {
+        attributeClass.setText("javax.el.MethodExpression");
+      }
+    }
+  }
+
+  private void addDescription(ExecutableElement element, org.jdom.Element attribute, Namespace namespace) {
+    String comment = processingEnv.getElementUtils().getDocComment(element);
+    if (comment != null) {
+      int index = comment.indexOf('@');
+      if (index != -1) {
+        comment = comment.substring(0, index);
+      }
+      comment = comment.trim();
+      if (comment.length() > 0) {
+        org.jdom.Element description = new org.jdom.Element(DESCRIPTION, namespace);
+        description.setText(comment);
+        attribute.addContent(description);
+      }
+    }
+  }
+
+  private org.jdom.Element createPropertyOrAttributeExtension(
+      String extensionType, ExecutableElement executableElement, UIComponentTagAttribute uiComponentTagAttribute,
+      Namespace namespace)
+      throws IllegalArgumentException {
+    org.jdom.Element extensionElement = new org.jdom.Element(extensionType, namespace);
+    org.jdom.Element valueExpression = new org.jdom.Element(VALUE_EXPRESSION, namespace);
+    valueExpression.setText(uiComponentTagAttribute.expression().toMetaDataString());
+    extensionElement.addContent(valueExpression);
+    String[] allowedValues = uiComponentTagAttribute.allowedValues();
+    if (allowedValues.length > 0) {
+      org.jdom.Element propertyValues = new org.jdom.Element(PROPERTY_VALUES, namespace);
+      String values = "";
+      for (String value : allowedValues) {
+        values += value + " ";
+      }
+      propertyValues.setText(values);
+      extensionElement.addContent(propertyValues);
+    }
+    Deprecated deprecated = executableElement.getAnnotation(Deprecated.class);
+    if (deprecated != null) {
+      org.jdom.Element elementDeprecated = new org.jdom.Element(DEPRECATED, namespace);
+      elementDeprecated.setText("Warning: This property is deprecated!");
+      extensionElement.addContent(elementDeprecated);
+    }
+    org.jdom.Element hidden = new org.jdom.Element(HIDDEN, namespace);
+    hidden.setText(Boolean.toString(uiComponentTagAttribute.isHidden()));
+    extensionElement.addContent(hidden);
+    org.jdom.Element readOnly = new org.jdom.Element(READONLY, namespace);
+    readOnly.setText(Boolean.toString(uiComponentTagAttribute.isReadOnly()));
+    extensionElement.addContent(readOnly);
+    TagAttribute tagAttribute = executableElement.getAnnotation(TagAttribute.class);
+    if (tagAttribute != null) {
+      org.jdom.Element required = new org.jdom.Element(REQUIRED, namespace);
+      required.setText(Boolean.toString(tagAttribute.required()));
+      extensionElement.addContent(required);
+    }
+
+    return extensionElement;
+  }
+
+  protected void addAttributes(
+      TypeElement typeElement, List<org.jdom.Element> attributes, List<org.jdom.Element> properties,
+      Namespace namespace) {
 /*
- * Date: Sep 25, 2006
- * Time: 9:26:19 PM
- */
-public class FacesConfigAnnotationProcessor implements AnnotationProcessor {
-  private final AnnotationProcessorEnvironment env;
-  private final Set<AnnotationTypeDeclaration> atds;
-
-  public FacesConfigAnnotationProcessor(Set<AnnotationTypeDeclaration> atds,
-      AnnotationProcessorEnvironment env) {
-    this.atds = atds;
-    this.env = env;
-    this.env.getMessager().printNotice("Starting annotation process");
-  }
-
-  public void process() {
-    FacesConfigAnnotationVisitor visitor = new FacesConfigAnnotationVisitor(env);
-
-    for (AnnotationTypeDeclaration atd : atds) {
-      env.getMessager().printNotice("Collecting annotation "+atd);
-      Collection<Declaration> decls = env.getDeclarationsAnnotatedWith(atd);
-      for (Declaration decl : decls) {
-        decl.accept(DeclarationVisitors.getDeclarationScanner(visitor, DeclarationVisitors.NO_OP));
+    addAttributes((List<TypeMirror>) typeElement.getInterfaces(), uiComponentClass, attributes, properties, namespace);
+    addAttributes(typeElement.getSuperclass(), uiComponentClass, attributes, properties, namespace);
+*/
+
+//    final List<ExecutableElement> members = new ArrayList<ExecutableElement>();
+    for (javax.lang.model.element.Element element : processingEnv.getElementUtils().getAllMembers(typeElement)) {
+      ExecutableElement executableElement = (ExecutableElement) element;
+      if (executableElement.getAnnotation(TagAttribute.class) == null
+          && executableElement.getAnnotation(UIComponentTagAttribute.class) == null) {
+        continue;
       }
+//      if (!members.contains(element)) {
+//        members.add((ExecutableElement) element);
+//      }
+      addAttribute(executableElement, attributes, properties, namespace);
     }
+/*
+    Collections.sort(members, new Comparator<ExecutableElement>() {
+      public int compare(ExecutableElement d1, ExecutableElement d2) {
+        return d1.getSimpleName().toString().compareTo(d2.getSimpleName().toString());
+      }
+    });
+*/
 
-    try {
-      visitor.process();
-    } catch (ParserConfigurationException e) {
-      // TODO
-      e.printStackTrace();
-    } catch (IOException e) {
-      e.printStackTrace();
+/*
+    for (ExecutableElement executableElement : members) {
+      addAttribute(executableElement, uiComponentClass, attributes, properties, namespace);
+    }
+*/
+  }
+
+/*
+  protected void addAttributes(
+      List<TypeMirror> interfaces, Class uiComponentClass, List<Element> attributes, List<Element> properties,
+      Namespace namespace) {
+    for (TypeMirror typeMirror : interfaces) {
+      addAttributes(typeMirror, uiComponentClass, attributes, properties, namespace);
+    }
+  }
+*/
+
+/*
+  protected void addAttributes(
+      TypeMirror typeMirror, Class uiComponentClass, List<Element> attributes, List<Element> properties,
+      Namespace namespace) {
+    if (typeMirror.getKind() != TypeKind.NONE) {
+      addAttributes((TypeElement) (environment.getTypeUtils().asElement(typeMirror)),
+          uiComponentClass, attributes, properties, namespace);
     }
   }
+*/
+
+  private void addFacets(UIComponentTag componentTag, Namespace namespace, org.jdom.Element element) {
+    Facet[] facets = componentTag.facets();
+    for (Facet facet : facets) {
+      org.jdom.Element facetElement = new org.jdom.Element(FACET, namespace);
+      String description = facet.description();
+      if (description != null && description.length() > 0) {
+        org.jdom.Element facetDescription = new org.jdom.Element(DESCRIPTION, namespace);
+        facetDescription.setText(description);
+        facetElement.addContent(facetDescription);
+      }
+      org.jdom.Element facetName = new org.jdom.Element(FACET_NAME, namespace);
+      facetName.setText(facet.name());
+      facetElement.addContent(facetName);
+      org.jdom.Element facetExtension = new org.jdom.Element(FACET_EXTENSION, namespace);
+      org.jdom.Element elementAllowedChildComponents = new org.jdom.Element(ALLOWED_CHILD_COMPONENTS, namespace);
+      String[] allowedChildComponents = facet.allowedChildComponenents();
+      String allowedComponentTypes = "";
+      for (String componentType : allowedChildComponents) {
+        allowedComponentTypes += componentType + " ";
+      }
+      elementAllowedChildComponents.setText(allowedComponentTypes);
+      facetExtension.addContent(elementAllowedChildComponents);
+      facetElement.addContent(facetExtension);
+      element.addContent(facetElement);
+    }
+  }
+
+  protected void addElement(
+      TypeElement typeElement, List<org.jdom.Element> components, List<org.jdom.Element> renderer,
+      final Namespace namespace) throws Exception {
+    UIComponentTag componentTag = typeElement.getAnnotation(UIComponentTag.class);
+    if (componentTag != null) {
+      ComponentInfo componentInfo = new ComponentInfo(typeElement, componentTag);
+      if (!componentTag.isComponentAlreadyDefined()) {
+        org.jdom.Element element = createComponentElement(componentInfo, componentTag, namespace);
+        if (element != null) {
+          if (!containsElement(components, element)) {
+            addFacets(componentTag, namespace, element);
+            List<org.jdom.Element> attributes = new ArrayList<org.jdom.Element>();
+            List<org.jdom.Element> properties = new ArrayList<org.jdom.Element>();
+            addAttributes(typeElement, attributes, properties, namespace);
+            if (!attributes.isEmpty()) {
+              Collections.sort(attributes, new Comparator<org.jdom.Element>() {
+                public int compare(org.jdom.Element d1, org.jdom.Element d2) {
+                  return d1.getChildText(ATTRIBUTE_NAME, namespace).compareTo(
+                      d2.getChildText(ATTRIBUTE_NAME, namespace));
+                }
+              });
+              element.addContent(attributes);
+            }
+            if (!properties.isEmpty()) {
+              Collections.sort(properties, new Comparator<org.jdom.Element>() {
+                public int compare(org.jdom.Element d1, org.jdom.Element d2) {
+                  return d1.getChildText(PROPERTY_NAME, namespace).compareTo(
+                      d2.getChildText(PROPERTY_NAME, namespace));
+                }
+              });
+              element.addContent(properties);
+            }
+            element.addContent(createElementExtension(typeElement, componentTag, namespace));
+            components.add(element);
+          } else {
+            // TODO add facet and attributes
+          }
+        }
+      }
+      addRendererElement(componentInfo, componentTag, renderer, namespace);
+    }
+  }
+
+  private void normaliseLineEndings(Document document) {
+    Iterator i = document.getDescendants(new ContentFilter(ContentFilter.COMMENT));
+    while (i.hasNext()) {
+      Comment c = (Comment) i.next();
+      c.setText(c.getText().replaceAll("\n", SEPARATOR));
+    }
+  }
+
+  private boolean is12() {
+    return "1.2".equals(jsfVersion);
+  }
+
+  private boolean is20() {
+    return "2.0".equals(jsfVersion);
+  }
 }