/*
* xulfaces : bring XUL power to Java
*
* Copyright (C) 2005 Olivier SCHMITT
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.xulfaces.annotation.processor.faces.component;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xulfaces.annotation.faces.ATTRIBUTE;
import org.xulfaces.annotation.faces.COMPONENT;
import org.xulfaces.annotation.processor.VelocityTemplateEngine;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.TypeDeclaration;
/**
*
* @author kito31
* @version $Id: ComponentAnnotationProcessor.java,v 1.3 2007/04/01 16:40:58 kito31 Exp $
*/
public class ComponentAnnotationProcessor implements AnnotationProcessor {
private static final Log log = LogFactory.getLog(ComponentAnnotationProcessor.class);
private AnnotationProcessorEnvironment apEnv;
public ComponentAnnotationProcessor(AnnotationProcessorEnvironment env) {
this.apEnv = env;
}
public void process() {
String path = this.apEnv.getOptions().get("-s");
if (path == null) {
throw new NullPointerException("Destination directory is null ! (use -s dirname) ");
}
for (TypeDeclaration typeDeclaration : apEnv.getTypeDeclarations()) {
try {
Class currentClass = Class.forName(typeDeclaration.getQualifiedName());
COMPONENT componentAnnotation = typeDeclaration.getAnnotation(COMPONENT.class);
if (componentAnnotation != null) {
String sourceCode = "";
try {
String name = currentClass.getName();
name = "src/main/java/" + name.replace(".", "/") + ".java";
log.debug(name);
BufferedReader bufferedReader = new BufferedReader(new FileReader(name));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
sourceCode = sourceCode + line + "\n";
}
bufferedReader.close();
} catch (Exception e) {
log.error(e);
throw new RuntimeException(e);
}
if (log.isDebugEnabled()) {
log.debug(sourceCode);
}
if (sourceCode != null) {
boolean containsGenerationTags = false;
LineNumberReader sourceFileReader = new LineNumberReader(new StringReader(sourceCode));
StringBuffer sourceCodeBuffer = new StringBuffer();
log.debug("Line number " + sourceFileReader.getLineNumber());
String line = null;
boolean startGeneration = false;
while ((line = sourceFileReader.readLine()) != null) {
if (line.contains("@StartGeneration")) {
sourceCodeBuffer.append(line);
sourceCodeBuffer.append("\n");
startGeneration = true;
containsGenerationTags = true;
log.debug("Processing COMPONENT " + componentAnnotation.classname());
Component component = new Component(componentAnnotation, currentClass);
sourceCodeBuffer.append(processComponentAnnotation(component, currentClass));
}
else {
if(startGeneration){
if (line.contains("@EndGeneration")) {
sourceCodeBuffer.append(line);
sourceCodeBuffer.append("\n");
startGeneration = false;
}
}
else {
sourceCodeBuffer.append(line);
sourceCodeBuffer.append("\n");
}
}
}
if (containsGenerationTags) {
try {
String name = currentClass.getName();
name = "src/main/java/" + name.replace(".", "/") + ".java";
log.debug("Generate file " + name);
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(name));
bufferedWriter.write(sourceCodeBuffer.toString());
bufferedWriter.flush();
bufferedWriter.close();
} catch (Exception e) {
log.error(e);
throw new RuntimeException(e);
}
}
}
}
} catch (Exception e) {
log.error(e);
}
}
}
private String processComponentAnnotation(Component component, Class currentClass) {
for (Field field : currentClass.getDeclaredFields()) {
ATTRIBUTE attributeAnnotation = field.getAnnotation(ATTRIBUTE.class);
if (attributeAnnotation != null) {
log.debug("Processing ATTRIBUTE" + attributeAnnotation.name());
Attribute attribute = new Attribute(attributeAnnotation, field);
component.getAttributes().add(attribute);
}
}
StringWriter writerForGeneratedCode = new StringWriter();
VelocityTemplateEngine engine = new VelocityTemplateEngine();
try {
engine.configure();
engine.prepareRender();
engine.setContextValue("component", component);
engine.renderTemplate(writerForGeneratedCode, "componentAttributeGetSet.vm");
if (log.isDebugEnabled()) {
log.debug(writerForGeneratedCode.toString());
}
return writerForGeneratedCode.toString();
} catch (Exception e) {
log.error(e);
throw new RuntimeException(e);
}
}
public class Component {
String type;
String classname;
List<Attribute> attributes = new ArrayList();
public Component(COMPONENT component, Class currentClass) {
this.type = component.type();
this.classname = currentClass.getName();
}
public List<Attribute> getAttributes() {
return attributes;
}
public void setAttributes(List<Attribute> attributes) {
this.attributes = attributes;
}
public String getClassname() {
return classname;
}
public void setClassname(String classname) {
this.classname = classname;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
public class Attribute {
String name;
String type = "";
String description = "TODO !!";
String suffix = "";
boolean supportsMethodBinding = false;
public Attribute(ATTRIBUTE componentAttribute, Field field) {
this.name = field.getName();
this.suffix = this.name.substring(0, 1).toUpperCase() + this.name.substring(1);
if (this.name.equals("")) {
this.name = field.getName();
}
this.type = componentAttribute.type();
if (this.type.equals("")) {
this.type = field.getType().getName();
}
this.description = componentAttribute.description();
this.supportsMethodBinding = componentAttribute.supportsMethodBinding();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public boolean isSupportsMethodBinding() {
return supportsMethodBinding;
}
public void setSupportsMethodBinding(boolean methodBinded) {
this.supportsMethodBinding = methodBinded;
}
}
}