package com.chrylis.gjt.transform;

import static org.codehaus.groovy.ast.ClassHelper.make;

import java.lang.reflect.Modifier;

import javax.persistence.Version;

import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.transform.GroovyASTTransformation;

import com.chrylis.gjt.annotation.GjtVersion;

@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class GjtVersionAstTransformation extends AbstractGjtAstTransformation<GjtVersion> {

    public static final String VERSION_FIELD_NAME = "version";
    
    @Override
    public Class<GjtVersion> annotationClass() {
        return GjtVersion.class;
    }

    @Override
    public boolean canApplyToClassOnly() {
        return true;
    }

    @Override
    protected void doVisit(AnnotationNode annotationNode, AnnotatedNode annotatedNode) {
        ClassNode entityClass = (ClassNode) annotatedNode;
        
        FieldNode versionField = entityClass.getField(VERSION_FIELD_NAME);
        
        // don't add the version field if it already exists on this class or is visible from a superclass
        if (versionField != null) {
            if(versionField.getOwner().equals(entityClass)) {
                addError("Class annotated with GjtVersion cannot have a version field declared", versionField);
            } else if (!Modifier.isPrivate(versionField.getModifiers())) {
                addError("Class annotated with GjtVersion cannot have a version field declared because the field exists in the parent class: " + versionField.getOwner().getName(), versionField);
            }
            
            return;
        }
        
        versionField = entityClass.addField(VERSION_FIELD_NAME, ACC_PRIVATE, make(Long.class), new ConstantExpression(null));
        versionField.addAnnotation(new AnnotationNode(make(Version.class)));
    }
}

@@ -330,24 +330,69 @@
 .FieldNode;%0A
+import org.codehaus.groovy.ast.PropertyNode;%0A
 import org.c
@@ -1923,28 +1923,44 @@
         
-versionField
+PropertyNode versionProperty
  = entit
@@ -1969,21 +1969,24 @@
 lass.add
-Field
+Property
 (VERSION
@@ -2007,14 +2007,13 @@
 CC_P
-RIVATE
+UBLIC
 , ma
@@ -2056,16 +2056,127 @@
 on(null)
+, null, null);%0A        versionField = versionProperty.getField();%0A        versionField.setModifiers(ACC_PRIVATE
 );%0A     

Make version field into a property