/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kie.workbench.common.screens.datamodeller.backend.server.indexing; import java.util.List; import org.drools.core.base.ClassTypeResolver; import org.jboss.forge.roaster.model.Type; import org.jboss.forge.roaster.model.source.AnnotationSource; import org.jboss.forge.roaster.model.source.EnumConstantSource.Body; import org.jboss.forge.roaster.model.source.FieldSource; import org.jboss.forge.roaster.model.source.Import; import org.jboss.forge.roaster.model.source.JavaAnnotationSource; import org.jboss.forge.roaster.model.source.JavaClassSource; import org.jboss.forge.roaster.model.source.JavaEnumSource; import org.jboss.forge.roaster.model.source.JavaInterfaceSource; import org.jboss.forge.roaster.model.source.JavaSource; import org.jboss.forge.roaster.model.source.MethodSource; import org.jboss.forge.roaster.model.source.ParameterSource; import org.kie.workbench.common.services.datamodeller.util.DriverUtils; import org.kie.workbench.common.services.refactoring.backend.server.impact.ResourceReferenceCollector; import org.kie.workbench.common.services.refactoring.model.index.Resource; import org.kie.workbench.common.services.refactoring.service.PartType; import org.kie.workbench.common.services.refactoring.service.ResourceType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SuppressWarnings("unchecked") public class JavaSourceVisitor extends ResourceReferenceCollector { private static final Logger logger = LoggerFactory.getLogger( JavaSourceVisitor.class ); private final JavaSource javaSource; private final ClassTypeResolver classTypeResolver; private final Resource resParts; public JavaSourceVisitor(JavaSource javaSource, ClassLoader classLoader, Resource resParts) { this.javaSource = javaSource; this.classTypeResolver = DriverUtils.createClassTypeResolver( javaSource, classLoader ); this.resParts = resParts; } public void visit(JavaSource javaSource) { // Imports List<Import> imports = javaSource.getImports(); for( Import javaImport : imports ) { visit(javaImport); } if( javaSource instanceof Body ) { visit((Body) javaSource); } else if( javaSource instanceof JavaAnnotationSource ) { visit((JavaAnnotationSource) javaSource); } else if( javaSource instanceof JavaClassSource ) { visit((JavaClassSource) javaSource); } else if( javaSource instanceof JavaEnumSource ) { visit((JavaEnumSource) javaSource); } else if( javaSource instanceof JavaInterfaceSource ) { visit((JavaInterfaceSource) javaSource); } } public void visit(AnnotationSource<? extends JavaClassSource> annoSource) { addJavaResourceReference(annoSource.getQualifiedName()); } public void visit( Body body) { for( AnnotationSource annoSource : body.getAnnotations() ) { visit(annoSource); } for( FieldSource fieldSource : body.getFields() ) { visit(fieldSource); } for( MethodSource methodSource : body.getMethods() ) { visit(methodSource); } } public void visit(FieldSource<? extends JavaSource> fieldSource) { Type fieldType = fieldSource.getType(); String fieldClassName; // the javadoc for Named.getName() is misleading: // the FieldSource.getName() (which is implemented by FieldImpl.getName()) // returns the (fully-qualified!) name of the field String fieldName = fieldSource.getName(); resParts.addPart(fieldName, PartType.FIELD); try { if ( DriverUtils.isManagedType( fieldType, classTypeResolver ) ) { if ( fieldType.isPrimitive() ) { fieldClassName = fieldType.getName(); } else if ( DriverUtils.isSimpleClass( fieldType ) ) { fieldClassName = classTypeResolver.getFullTypeName( fieldType.getName() ); } else { //if this point was reached, we know it's a Collection. // Managed type check was done previously. Type elementsType = ( (List<Type>) fieldType.getTypeArguments() ).get( 0 ); fieldClassName = classTypeResolver.getFullTypeName( elementsType.getName() ); } } else { // mriet: not complete sure why we don't just do this instead of using DriverUtils? fieldClassName = fieldType.getQualifiedName(); } addJavaResourceReference(fieldClassName); } catch ( Exception e ) { logger.error( "Unable to index java class field for class: " + javaSource.getQualifiedName() + ", fieldName: " + fieldName + " fieldType: " + fieldType ); } // Field annotations for( AnnotationSource annoSource : fieldSource.getAnnotations() ) { visit(annoSource); } } public void visit(JavaAnnotationSource javaAnnoSource) { for( AnnotationSource annoSource : javaAnnoSource.getAnnotations() ) { visit(annoSource); } } public void visit(JavaClassSource javaClassSource) { if ( javaClassSource.getSuperType() != null ) { try { String superClass = classTypeResolver.getFullTypeName( javaClassSource.getSuperType() ); addJavaResourceReference(superClass); // TODO: add relationship information ( child ) } catch ( ClassNotFoundException e ) { logger.error( "Unable to index super class name for class: " + javaClassSource.getQualifiedName() ); } } List<String> implementedInterfaces = javaClassSource.getInterfaces(); if ( implementedInterfaces != null ) { for ( String implementedInterface : implementedInterfaces ) { try { implementedInterface = classTypeResolver.getFullTypeName( implementedInterface ); addJavaResourceReference(implementedInterface); // TODO: add relationship information ( implements ) } catch ( ClassNotFoundException e ) { logger.error( "Unable to index implemented interface qualified name for class: " + javaClassSource.getQualifiedName() + ", interface: " + implementedInterface, e ); } } } for( AnnotationSource<? extends JavaClassSource> annoSource : javaClassSource.getAnnotations() ) { visit(annoSource); } for( FieldSource<? extends JavaClassSource> fieldSource : javaClassSource.getFields() ) { visit(fieldSource); } for( MethodSource<? extends JavaClassSource> methodSource : javaClassSource.getMethods() ) { visit(methodSource); } } public void visit(JavaEnumSource javaEnumSource) { for( AnnotationSource annoSource : javaEnumSource.getAnnotations() ) { visit(annoSource); } for( FieldSource fieldSource : javaEnumSource.getFields() ) { visit(fieldSource); } for( MethodSource methodSource : javaEnumSource.getMethods() ) { visit(methodSource); } } public void visit(Import javaImport) { String refClassName = javaImport.getQualifiedName(); if( javaImport.isWildcard() ) { logger.warn("Import " + javaImport.getQualifiedName() + " used in class."); } else { addJavaResourceReference(refClassName); } } public void visit(JavaInterfaceSource interfaceSource) { for( AnnotationSource annoSource : interfaceSource.getAnnotations() ) { visit(annoSource); } for( FieldSource<JavaInterfaceSource> fieldSource : interfaceSource.getFields() ) { visit(fieldSource); } for( MethodSource methodSource : interfaceSource.getMethods() ) { visit(methodSource); } } public void visit(MethodSource<? extends JavaClassSource> methodSource) { for( ParameterSource<? extends JavaClassSource> paramSource : methodSource.getParameters() ) { // Method parameters addJavaResourceReference(paramSource.getType().getQualifiedName()); // Method parameter annotations for( AnnotationSource<? extends JavaClassSource> annoSource : paramSource.getAnnotations() ) { visit(annoSource) ; } } Type<? extends JavaClassSource> returnType = methodSource.getReturnType(); if (returnType != null) { String returnTypeQualifiedName = returnType.getQualifiedName(); if ( !returnTypeQualifiedName.endsWith( ".void" ) ) { addJavaResourceReference( returnTypeQualifiedName ); } } // method annotations for( AnnotationSource<? extends JavaClassSource> annoSource : methodSource.getAnnotations() ) { visit(annoSource); } } public void addJavaResourceReference(String fullyQualifiedName) { super.addResourceReference(fullyQualifiedName, ResourceType.JAVA); } }