void visit()

in grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy [66:297]


    void visit(ClassNode classNode, SourceUnit sourceUnit) {
        if (classNode.getNodeMetaData(AstUtils.TRANSFORM_APPLIED_MARKER) == APPLIED_MARKER) {
            return
        }

        if ((classNode instanceof InnerClassNode) || classNode.isEnum()) {
            // do not apply transform to enums or inner classes
            return
        }

        def mapWith = AstUtils.getPropertyFromHierarchy(classNode, GormProperties.MAPPING_STRATEGY)
        String mapWithValue = mapWith?.initialExpression?.text

        if(mapWithValue != null && (mapWithValue != ('hibernate') || mapWithValue != GormProperties.DEFAULT_MAPPING_STRATEGY)) {
            return
        }

        new GormEntityTransformation(compilationUnit: compilationUnit).visit(classNode, sourceUnit)
        
        ClassNode managedEntityClassNode = ClassHelper.make(ManagedEntity)
        ClassNode attributeInterceptableClassNode = ClassHelper.make(PersistentAttributeInterceptable)
        ClassNode entityEntryClassNode = ClassHelper.make(EntityEntry)
        ClassNode persistentAttributeInterceptorClassNode = ClassHelper.make(PersistentAttributeInterceptor)

        classNode.addInterface(managedEntityClassNode)
        classNode.addInterface(attributeInterceptableClassNode)
        String interceptorFieldName = '$$_hibernate_attributeInterceptor'
        String entryHolderFieldName = '$$_hibernate_entityEntryHolder'
        String previousManagedEntityFieldName = '$$_hibernate_previousManagedEntity'
        String nextManagedEntityFieldName = '$$_hibernate_nextManagedEntity'

        def staticCompilationVisitor = new StaticCompilationVisitor(sourceUnit, classNode)

        AnnotationNode transientAnnotationNode = new AnnotationNode(ClassHelper.make(Transient.class))
        FieldNode entityEntryHolderField = classNode.addField(entryHolderFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, entityEntryClassNode, null)
        entityEntryHolderField
                 .addAnnotation(transientAnnotationNode)

        FieldNode previousManagedEntityField = classNode.addField(previousManagedEntityFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, managedEntityClassNode, null)
        previousManagedEntityField
                 .addAnnotation(transientAnnotationNode)

        FieldNode nextManagedEntityField = classNode.addField(nextManagedEntityFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, managedEntityClassNode, null)
        nextManagedEntityField
                 .addAnnotation(transientAnnotationNode)

        FieldNode interceptorField = classNode.addField(interceptorFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, persistentAttributeInterceptorClassNode, null)
        interceptorField
                 .addAnnotation(transientAnnotationNode)



        // add method: PersistentAttributeInterceptor $$_hibernate_getInterceptor()
        def getInterceptorMethod = new MethodNode(
                '$$_hibernate_getInterceptor',
                Modifier.PUBLIC,
                persistentAttributeInterceptorClassNode,
                AstUtils.ZERO_PARAMETERS,
                null,
                returnS(varX(interceptorField))
        )
        classNode.addMethod(getInterceptorMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, getInterceptorMethod)
        staticCompilationVisitor.visitMethod(getInterceptorMethod)

        // add method: void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor)
        def p1 = param(persistentAttributeInterceptorClassNode, "interceptor")
        def setInterceptorMethod = new MethodNode(
                '$$_hibernate_setInterceptor',
                Modifier.PUBLIC,
                ClassHelper.VOID_TYPE,
                params(p1),
                null,
                assignS( varX(interceptorField), varX(p1) )
        )
        classNode.addMethod(setInterceptorMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, setInterceptorMethod)
        staticCompilationVisitor.visitMethod(setInterceptorMethod)

        // add method: Object $$_hibernate_getEntityInstance()
        def getEntityInstanceMethod = new MethodNode(
                '$$_hibernate_getEntityInstance',
                Modifier.PUBLIC,
                ClassHelper.OBJECT_TYPE,
                AstUtils.ZERO_PARAMETERS,
                null,
                returnS(varX("this"))
        )
        classNode.addMethod(getEntityInstanceMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, getEntityInstanceMethod)
        staticCompilationVisitor.visitMethod(getEntityInstanceMethod)


        // add method: EntityEntry $$_hibernate_getEntityEntry()
        def getEntityEntryMethod = new MethodNode(
                '$$_hibernate_getEntityEntry',
                Modifier.PUBLIC,
                entityEntryClassNode,
                AstUtils.ZERO_PARAMETERS,
                null,
                returnS(varX(entityEntryHolderField))
        )
        classNode.addMethod(getEntityEntryMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, getEntityEntryMethod)
        staticCompilationVisitor.visitMethod(getEntityEntryMethod)

        // add method: void $$_hibernate_setEntityEntry(EntityEntry entityEntry)
        def entityEntryParam = param(entityEntryClassNode, "entityEntry")
        def setEntityEntryMethod = new MethodNode(
                '$$_hibernate_setEntityEntry',
                Modifier.PUBLIC,
                ClassHelper.VOID_TYPE,
                params(entityEntryParam),
                null,
                assignS( varX(entityEntryHolderField), varX(entityEntryParam) )
        )
        classNode.addMethod(setEntityEntryMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, setEntityEntryMethod)
        staticCompilationVisitor.visitMethod(setEntityEntryMethod)

        // add method: ManagedEntity $$_hibernate_getPreviousManagedEntity()
        def getPreviousManagedEntityMethod = new MethodNode(
                '$$_hibernate_getPreviousManagedEntity',
                Modifier.PUBLIC,
                managedEntityClassNode,
                AstUtils.ZERO_PARAMETERS,
                null,
                returnS(varX(previousManagedEntityField))
        )
        classNode.addMethod(getPreviousManagedEntityMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, getPreviousManagedEntityMethod)
        staticCompilationVisitor.visitMethod(getPreviousManagedEntityMethod)

        // add method: ManagedEntity $$_hibernate_getNextManagedEntity() {
        def getNextManagedEntityMethod = new MethodNode(
                '$$_hibernate_getNextManagedEntity',
                Modifier.PUBLIC,
                managedEntityClassNode,
                AstUtils.ZERO_PARAMETERS,
                null,
                returnS(varX(nextManagedEntityField))
        )
        classNode.addMethod(getNextManagedEntityMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, getNextManagedEntityMethod)
        staticCompilationVisitor.visitMethod(getNextManagedEntityMethod)

        // add method: void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous)
        def previousParam = param(managedEntityClassNode, "previous")
        def setPreviousManagedEntityMethod = new MethodNode(
                '$$_hibernate_setPreviousManagedEntity',
                Modifier.PUBLIC,
                ClassHelper.VOID_TYPE,
                params(previousParam),
                null,
                assignS( varX(previousManagedEntityField), varX(previousParam) )
        )
        classNode.addMethod(setPreviousManagedEntityMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, setPreviousManagedEntityMethod)
        staticCompilationVisitor.visitMethod(setPreviousManagedEntityMethod)

        // add method: void $$_hibernate_setNextManagedEntity(ManagedEntity next)
        def nextParam = param(managedEntityClassNode, "next")
        def setNextManagedEntityMethod = new MethodNode(
                '$$_hibernate_setNextManagedEntity',
                Modifier.PUBLIC,
                ClassHelper.VOID_TYPE,
                params(nextParam),
                null,
                assignS( varX(nextManagedEntityField), varX(nextParam) )
        )
        classNode.addMethod(setNextManagedEntityMethod)
        AnnotatedNodeUtils.markAsGenerated(classNode, setNextManagedEntityMethod)
        staticCompilationVisitor.visitMethod(setNextManagedEntityMethod)

        List<MethodNode> allMethods = classNode.getMethods()
        for(MethodNode methodNode in allMethods) {
            if(methodNode.getAnnotations(ClassHelper.make(DirtyCheckedProperty))) {
                if(AstUtils.isGetter(methodNode)) {
                    def codeVisitor = new ClassCodeVisitorSupport() {
                        @Override
                        protected SourceUnit getSourceUnit() {
                            return sourceUnit
                        }

                        @Override
                        void visitReturnStatement(ReturnStatement statement) {
                            ReturnStatement rs = (ReturnStatement)statement
                            def i = varX(interceptorField)
                            def propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodNode.getName())

                            def returnType = methodNode.getReturnType()
                            final boolean isPrimitive = ClassHelper.isPrimitiveType(returnType)
                            String readMethodName = isPrimitive ? "read${NameUtils.capitalize(returnType.getName())}" : "readObject"
                            def readObjectCall = callX(i, readMethodName, args(varX("this"), constX(propertyName), rs.getExpression()))
                            def ternaryExpr = ternaryX(
                                    equalsNullX(varX(interceptorField)),
                                    rs.getExpression(),
                                    readObjectCall
                            )
                            staticCompilationVisitor.visitTernaryExpression ternaryExpr
                            rs.setExpression(ternaryExpr)

                        }
                    }
                    codeVisitor.visitMethod(methodNode)
                }
                else {
                    Statement code = methodNode.code
                    if(code instanceof BlockStatement) {
                        BlockStatement bs = (BlockStatement)code
                        Parameter parameter = methodNode.getParameters()[0]
                        ClassNode parameterType = parameter.type
                        final boolean isPrimitive = ClassHelper.isPrimitiveType(parameterType)
                        String writeMethodName = isPrimitive ? "write${NameUtils.capitalize(parameterType.getName())}" : "writeObject"
                        String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodNode.getName())
                        def interceptorFieldExpr = fieldX(interceptorField)
                        def ifStatement = ifS( neX(interceptorFieldExpr, constX(null) ),
                            assignS(
                                varX(parameter),
                                callX( interceptorFieldExpr, writeMethodName, args( varX("this"), constX(propertyName), propX(varX("this"), propertyName), varX(parameter)))
                            )
                        )
                        staticCompilationVisitor.visitIfElse((IfStatement)ifStatement)
                        bs.getStatements().add(0, ifStatement)
                    }
                }

            }
        }

        classNode.putNodeMetaData(AstUtils.TRANSFORM_APPLIED_MARKER, APPLIED_MARKER)
    }