// Path: asteroid-core/src/main/java/asteroid/A.java
// @SuppressWarnings("PMD.ShortClassName")
// public final class A {
// 
//     /**
//      * Entry point to get node builders.
//      *
//      * @since 0.1.0
//      */
//     public static final Nodes NODES = new Nodes();
// 
//     /**
//      * Entry point to access language modifiers
//      *
//      * @since 0.1.0
//      */
//     public static final Modifiers ACC = new Modifiers();
// 
//     /**
//      * Entry point to create statements.
//      *
//      * @since 0.1.0
//      */
//     public static final Statements STMT = new Statements();
// 
//     /**
//      * Entry point to create expressions
//      *
//      * @since 0.1.0
//      */
//     public static final Expressions EXPR = new Expressions();
// 
//     /**
//      * Entry point to get util functions
//      *
//      * @since 0.1.0
//      */
//     public static final Utils UTIL = new Utils();
// 
//     /**
//      * Entry point to get criterias
//      *
//      * @since 0.2.4
//      */
//     public static final Criterias CRITERIA = new Criterias();
// }
// 
// Path: asteroid-core/src/main/java/asteroid/AbstractGlobalTransformation.java
// public abstract class AbstractGlobalTransformation extends AbstractASTTransformation {
// 
//     /**
//      * {@inheritDoc}
//      *
//      * @since 0.2.0
//      */
//     @SuppressWarnings({"PMD.UnusedMethodParameter", "PMD.AvoidInstantiatingObjectsInLoops"})
//     public void visit(final ASTNode[] nodes, final SourceUnit sourceUnit) {
//         final List<ClassNode> classNodeList = (List<ClassNode>) collect(sourceUnit.getAST().getClasses());
// 
//         for (final ClassNode clazzNode : classNodeList) {
//             for (final Class<? extends Transformer> clazz : getTransformers()) {
//                 newInstance(clazz, new Object[] { sourceUnit })
//                     .visitClass(clazzNode);
//             }
//         }
//     }
// 
//     /**
//      * This method should return a list of visitor classes {@link
//      * Class} instances applied globally by this AST.
//      *
//      * @return all transformers that will be applied globally by this
//      * AST transformation
//      * @since 0.2.0
//      * @see Transformer
//      */
//     public abstract List<Class<? extends Transformer>> getTransformers();
// }
// 
// Path: asteroid-core/src/main/java/asteroid/transformer/AbstractClassNodeTransformer.java
// public abstract class AbstractClassNodeTransformer extends AbstractTransformer {
// 
//     private final Closure<Boolean> criteria;
// 
//     /**
//      * Every instance needs the source unit and the name of the class
//      * it's going to transform.
//      *
//      * To find classes eligible to be transformed by this {@link Transformer}
//      * a {@link Closure} returning a boolean is used as a criteria.
//      *
//      * You can create your own criteria or use one of the static
//      * methods present in this class. These methods will create a
//      * pre-defined criteria.
//      *
//      * The {@link Closure} used as a criteria will receive a {@link
//      * ClassNode} and return a {@link Boolean} value. If the closure
//      * returns true then the transformation will be apply, if not the
//      * {@link ClassNode} will be discarded.
//      *
//      * @param sourceUnit Needed to apply scope
//      * @param criteria used to locate target classes
//      * look for the qualified class)
//      * @since 0.2.0
//      * @see asteroid.Criterias#byClassNodeNameContains(String)
//      */
//     public AbstractClassNodeTransformer(final SourceUnit sourceUnit, final Closure<Boolean> criteria) {
//         super(sourceUnit);
//         this.criteria = criteria;
//     }
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public void visitClass(final ClassNode classNode) {
//         if (classNode == null || !this.criteria.call(classNode)) {
//             return;
//         }
// 
//         transformClass(classNode);
//     }
// 
//     /**
//      * Within this method developer could modify the {@link ClassNode}
//      * instance.
//      *
//      * @param classNode the {@link ClassNode}  you want to transform
//      * @since 0.2.0
//      */
//     public abstract void transformClass(final ClassNode classNode);
// 
// }


import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.AnnotationNode;
import asteroid.A;
import asteroid.Phase;
import asteroid.AbstractGlobalTransformation;
import asteroid.transformer.AbstractClassNodeTransformer;
        final ClassNode reference = A.NODES.clazz(AbstractGlobalTransformation.class).build();
        final Boolean isGlobal = A.UTIL.NODE.isOrExtendsUnsafe(annotated, reference);

        if (!isGlobal) {
            return;
        }

        final AnnotationNode annotation = A.UTIL.NODE.getAnnotationFrom(annotated, TX_NAME);
        final CompilePhase phase = extractCompilePhaseFromSafely(annotation);

        TransformationUtils.addASTAnnotationsFromTo(annotated, phase);
        A.UTIL.NODE.removeAnnotation(annotated, annotation);
    }

    @SuppressWarnings("PMD.AvoidCatchingGenericException")
    private CompilePhase extractCompilePhaseFromSafely(final AnnotationNode annotationNode) {
        try {
            return extractCompilePhaseFrom(annotationNode);
        } catch(IllegalArgumentException iaex){
            throw new GroovyBugError(PHASE_WRONG, iaex);
        } catch(Exception ex) {
            throw new GroovyBugError(PHASE_MISSING, ex);
        }
    }

    private CompilePhase extractCompilePhaseFrom(final AnnotationNode annotationNode) {
        final String       value         = A.UTIL.NODE.getStringValue(annotationNode);
        final String       phaseAsString = value
            .replace(PHASE_GROOVY, BLANK)
            .replace(PHASE_PFIX, BLANK)
// Path: asteroid-core/src/main/java/asteroid/A.java
// @SuppressWarnings("PMD.ShortClassName")
// public final class A {
// 
//     /**
//      * Entry point to get node builders.
//      *
//      * @since 0.1.0
//      */
//     public static final Nodes NODES = new Nodes();
// 
//     /**
//      * Entry point to access language modifiers
//      *
//      * @since 0.1.0
//      */
//     public static final Modifiers ACC = new Modifiers();
// 
//     /**
//      * Entry point to create statements.
//      *
//      * @since 0.1.0
//      */
//     public static final Statements STMT = new Statements();
// 
//     /**
//      * Entry point to create expressions
//      *
//      * @since 0.1.0
//      */
//     public static final Expressions EXPR = new Expressions();
// 
//     /**
//      * Entry point to get util functions
//      *
//      * @since 0.1.0
//      */
//     public static final Utils UTIL = new Utils();
// 
//     /**
//      * Entry point to get criterias
//      *
//      * @since 0.2.4
//      */
//     public static final Criterias CRITERIA = new Criterias();
// }
// 
// Path: asteroid-core/src/main/java/asteroid/AbstractGlobalTransformation.java
// public abstract class AbstractGlobalTransformation extends AbstractASTTransformation {
// 
//     /**
//      * {@inheritDoc}
//      *
//      * @since 0.2.0
//      */
//     @SuppressWarnings({"PMD.UnusedMethodParameter", "PMD.AvoidInstantiatingObjectsInLoops"})
//     public void visit(final ASTNode[] nodes, final SourceUnit sourceUnit) {
//         final List<ClassNode> classNodeList = (List<ClassNode>) collect(sourceUnit.getAST().getClasses());
// 
//         for (final ClassNode clazzNode : classNodeList) {
//             for (final Class<? extends Transformer> clazz : getTransformers()) {
//                 newInstance(clazz, new Object[] { sourceUnit })
//                     .visitClass(clazzNode);
//             }
//         }
//     }
// 
//     /**
//      * This method should return a list of visitor classes {@link
//      * Class} instances applied globally by this AST.
//      *
//      * @return all transformers that will be applied globally by this
//      * AST transformation
//      * @since 0.2.0
//      * @see Transformer
//      */
//     public abstract List<Class<? extends Transformer>> getTransformers();
// }
// 
// Path: asteroid-core/src/main/java/asteroid/transformer/AbstractClassNodeTransformer.java
// public abstract class AbstractClassNodeTransformer extends AbstractTransformer {
// 
//     private final Closure<Boolean> criteria;
// 
//     /**
//      * Every instance needs the source unit and the name of the class
//      * it's going to transform.
//      *
//      * To find classes eligible to be transformed by this {@link Transformer}
//      * a {@link Closure} returning a boolean is used as a criteria.
//      *
//      * You can create your own criteria or use one of the static
//      * methods present in this class. These methods will create a
//      * pre-defined criteria.
//      *
//      * The {@link Closure} used as a criteria will receive a {@link
//      * ClassNode} and return a {@link Boolean} value. If the closure
//      * returns true then the transformation will be apply, if not the
//      * {@link ClassNode} will be discarded.
//      *
//      * @param sourceUnit Needed to apply scope
//      * @param criteria used to locate target classes
//      * look for the qualified class)
//      * @since 0.2.0
//      * @see asteroid.Criterias#byClassNodeNameContains(String)
//      */
//     public AbstractClassNodeTransformer(final SourceUnit sourceUnit, final Closure<Boolean> criteria) {
//         super(sourceUnit);
//         this.criteria = criteria;
//     }
// 
//     /**
//      * {@inheritDoc}
//      */
//     @Override
//     public void visitClass(final ClassNode classNode) {
//         if (classNode == null || !this.criteria.call(classNode)) {
//             return;
//         }
// 
//         transformClass(classNode);
//     }
// 
//     /**
//      * Within this method developer could modify the {@link ClassNode}
//      * instance.
//      *
//      * @param classNode the {@link ClassNode}  you want to transform
//      * @since 0.2.0
//      */
//     public abstract void transformClass(final ClassNode classNode);
// 
// }


// Path: asteroid-core/src/main/java/asteroid/internal/TranslateToGlobalTransform.java
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.AnnotationNode;
import asteroid.A;
import asteroid.Phase;
import asteroid.AbstractGlobalTransformation;
import asteroid.transformer.AbstractClassNodeTransformer;

        final ClassNode reference = A.NODES.clazz(AbstractGlobalTransformation.class).build();
        final Boolean isGlobal = A.UTIL.NODE.isOrExtendsUnsafe(annotated, reference);

        if (!isGlobal) {
            return;
        }

        final AnnotationNode annotation = A.UTIL.NODE.getAnnotationFrom(annotated, TX_NAME);
        final CompilePhase phase = extractCompilePhaseFromSafely(annotation);

        TransformationUtils.addASTAnnotationsFromTo(annotated, phase);
        A.UTIL.NODE.removeAnnotation(annotated, annotation);
    }

    @SuppressWarnings("PMD.AvoidCatchingGenericException")
    private CompilePhase extractCompilePhaseFromSafely(final AnnotationNode annotationNode) {
        try {
            return extractCompilePhaseFrom(annotationNode);
        } catch(IllegalArgumentException iaex){
            throw new GroovyBugError(PHASE_WRONG, iaex);
        } catch(Exception ex) {
            throw new GroovyBugError(PHASE_MISSING, ex);
        }
    }

    private CompilePhase extractCompilePhaseFrom(final AnnotationNode annotationNode) {
        final String       value         = A.UTIL.NODE.getStringValue(annotationNode);
        final String       phaseAsString = value
            .replace(PHASE_GROOVY, BLANK)
            .replace(PHASE_PFIX, BLANK)
            .replace(PHASE_PFIX_SHORT, BLANK);