TRINIDAD-1707 - JSF2: Need to include Design Time metadata in Facelets taglib

Added code to generate taglib metadata
diff --git a/maven-faces-plugin/src/main/java/org/apache/myfaces/trinidadbuild/plugin/faces/GenerateFaceletsTaglibsMojo.java b/maven-faces-plugin/src/main/java/org/apache/myfaces/trinidadbuild/plugin/faces/GenerateFaceletsTaglibsMojo.java
index 486e4d2..dc2a4fe 100644
--- a/maven-faces-plugin/src/main/java/org/apache/myfaces/trinidadbuild/plugin/faces/GenerateFaceletsTaglibsMojo.java
+++ b/maven-faces-plugin/src/main/java/org/apache/myfaces/trinidadbuild/plugin/faces/GenerateFaceletsTaglibsMojo.java
@@ -48,8 +48,11 @@
 import org.apache.myfaces.trinidadbuild.plugin.faces.parse.ConverterBean;
 import org.apache.myfaces.trinidadbuild.plugin.faces.parse.FacesConfigBean;
 import org.apache.myfaces.trinidadbuild.plugin.faces.parse.ValidatorBean;
+import org.apache.myfaces.trinidadbuild.plugin.faces.parse.PropertyBean;
+import org.apache.myfaces.trinidadbuild.plugin.faces.parse.MethodSignatureBean;
 import org.apache.myfaces.trinidadbuild.plugin.faces.util.FilteredIterator;
 import org.apache.myfaces.trinidadbuild.plugin.faces.util.XIncludeFilter;
+import org.apache.myfaces.trinidadbuild.plugin.faces.generator.taglib.TagAttributeFilter;
 
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.project.MavenProject;
@@ -269,6 +272,15 @@
   {
     stream.writeCharacters("\n  ");
     stream.writeStartElement("tag");
+    
+    if (component.getDescription() != null)
+    {
+      stream.writeCharacters("\n    ");
+      stream.writeStartElement("description");
+      stream.writeCData(component.getDescription());
+      stream.writeEndElement();
+    }
+    
     stream.writeCharacters("\n    ");
     stream.writeStartElement("tag-name");
     stream.writeCharacters(component.getTagName().getLocalPart());
@@ -303,6 +315,19 @@
 
     stream.writeCharacters("\n    ");
     stream.writeEndElement();
+    
+    Iterator properties = component.properties(true);
+    properties = new FilteredIterator(properties, new TagAttributeFilter());
+    while (properties.hasNext())
+    {
+      PropertyBean property = (PropertyBean)properties.next();
+      writeTagAttribute(stream,
+                         property.getPropertyName(),
+                         property.getDescription(),
+                         property.getUnsupportedAgents(),
+                         property);
+    }
+    
     stream.writeCharacters("\n  ");
     stream.writeEndElement();
   }
@@ -316,6 +341,15 @@
   {
     stream.writeCharacters("\n  ");
     stream.writeStartElement("tag");
+    
+    if (validator.getDescription() != null)
+    {
+      stream.writeCharacters("\n    ");
+      stream.writeStartElement("description");
+      stream.writeCData(validator.getDescription());
+      stream.writeEndElement();
+    }
+    
     stream.writeCharacters("\n    ");
     stream.writeStartElement("tag-name");
     stream.writeCharacters(validator.getTagName().getLocalPart());
@@ -341,6 +375,22 @@
 
     stream.writeCharacters("\n    ");
     stream.writeEndElement();
+    
+    // validators need an id attribute
+    writeTagAttribute(stream, "id", "the identifier for the validator", null, null);
+
+    Iterator properties = validator.properties();
+    properties = new FilteredIterator(properties, new TagAttributeFilter());
+    while (properties.hasNext())
+    {
+      PropertyBean property = (PropertyBean)properties.next();
+      writeTagAttribute(stream,
+                         property.getPropertyName(),
+                         property.getDescription(),
+                         property.getUnsupportedAgents(),
+                         property);
+    }
+    
     stream.writeCharacters("\n  ");
     stream.writeEndElement();
   }
@@ -354,6 +404,15 @@
   {
     stream.writeCharacters("\n  ");
     stream.writeStartElement("tag");
+    
+    if (converter.getDescription() != null)
+    {
+      stream.writeCharacters("\n    ");
+      stream.writeStartElement("description");
+      stream.writeCData(converter.getDescription());
+      stream.writeEndElement();
+    }
+    
     stream.writeCharacters("\n    ");
     stream.writeStartElement("tag-name");
     stream.writeCharacters(converter.getTagName().getLocalPart());
@@ -379,9 +438,122 @@
 
     stream.writeCharacters("\n    ");
     stream.writeEndElement();
+    
+    // converters need an id attribute
+    writeTagAttribute(stream, "id", "the identifier for the converter", null, null);
+
+    Iterator properties = converter.properties();
+    properties = new FilteredIterator(properties, new TagAttributeFilter());
+    while (properties.hasNext())
+    {
+      PropertyBean property = (PropertyBean)properties.next();
+      writeTagAttribute(stream,
+                         property.getPropertyName(),
+                         property.getDescription(),
+                         property.getUnsupportedAgents(),
+                         property);
+    }
+    
     stream.writeCharacters("\n  ");
     stream.writeEndElement();
   }
+  
+  protected void writeTagAttribute(
+      XMLStreamWriter stream,
+      String          propertyName,
+      String          description,
+      String[]        unsupportedAgents,
+      PropertyBean    property) throws XMLStreamException
+    {
+      stream.writeCharacters("\n    ");
+      stream.writeStartElement("attribute");
+    
+      _writeTagAttributeDescription(stream, description, unsupportedAgents);
+      
+      stream.writeCharacters("\n      ");
+      stream.writeStartElement("name");
+
+      if (property != null)
+        stream.writeCharacters(property.getJspPropertyName());
+      else
+        stream.writeCharacters(propertyName);
+    
+      stream.writeEndElement();
+      
+      if (property != null)
+      {
+        if (property.isRequired())
+        {
+          stream.writeCharacters("\n    ");
+          stream.writeStartElement("required");
+          stream.writeCharacters("true");
+          stream.writeEndElement();
+        }
+        
+        MethodSignatureBean sig = null;
+        if ((property.isMethodExpression() || property.isMethodBinding()) && (sig = property.getMethodBindingSignature()) != null)
+        {
+          stream.writeCharacters("\n      ");
+          stream.writeStartElement("method-signature");
+          stream.writeCharacters(sig.getReturnType());
+          stream.writeCharacters(" myMethod(");
+          String[] params = sig.getParameterTypes();
+          for (int i = 0; i < params.length; i++)
+          {
+            if (i > 0)
+              stream.writeCharacters(", ");
+            stream.writeCharacters(params[i]);
+          }
+
+          stream.writeCharacters(")");
+          stream.writeEndElement();
+        }
+        else
+        {
+          String propertyClass = property.getPropertyClass();
+          stream.writeCharacters("\n      ");
+          stream.writeStartElement("type");
+          stream.writeCharacters(propertyClass);
+          stream.writeEndElement();
+        }
+        
+      }
+
+      stream.writeCharacters("\n    ");
+      stream.writeEndElement();
+    }
+    
+    private void _writeTagAttributeDescription(
+      XMLStreamWriter stream,
+      String          description,
+      String[]        unsupportedAgents) throws XMLStreamException
+    {
+
+      if (description != null ||
+          unsupportedAgents.length > 0)
+      {
+        stream.writeCharacters("\n      ");
+        stream.writeStartElement("description");
+
+        if (unsupportedAgents != null &&
+            unsupportedAgents.length > 0)
+        {
+          if (description == null)
+            description = "";
+
+          description += "\n\n    This attribute is not supported on the following agent types:\n";
+
+          for (int i=0; i < unsupportedAgents.length; i++)
+          {
+            description += " " + unsupportedAgents[i];
+            description += (i < unsupportedAgents.length - 1) ? "," : ".";
+          }
+        }
+
+        stream.writeCData(description);
+        stream.writeEndElement();
+      }
+    }
 
 
   /**