Skip to content

Commit

Permalink
WINDUP-698: JPA tables not resolved for Entity that extends base class
Browse files Browse the repository at this point in the history
  • Loading branch information
jsight committed May 9, 2018
1 parent f7e294d commit 303912d
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 8 deletions.
@@ -1,7 +1,11 @@
package org.jboss.windup.rules.apps.javaee.rules;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.jboss.windup.ast.java.data.TypeReferenceLocation;
import org.jboss.windup.config.AbstractRuleProvider;
Expand All @@ -12,12 +16,14 @@
import org.jboss.windup.config.operation.Iteration;
import org.jboss.windup.config.operation.iteration.AbstractIterationOperation;
import org.jboss.windup.config.phase.InitialAnalysisPhase;
import org.jboss.windup.graph.model.FileReferenceModel;
import org.jboss.windup.graph.model.WindupVertexFrame;
import org.jboss.windup.graph.service.GraphService;
import org.jboss.windup.config.projecttraversal.ProjectTraversalCache;
import org.jboss.windup.rules.apps.java.condition.JavaClass;
import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel;
import org.jboss.windup.rules.apps.java.model.JavaClassModel;
import org.jboss.windup.rules.apps.java.model.JavaSourceFileModel;
import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel;
import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationListTypeValueModel;
import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationLiteralTypeValueModel;
Expand Down Expand Up @@ -47,6 +53,7 @@ public class DiscoverJPAAnnotationsRuleProvider extends AbstractRuleProvider
private static final String TABLE_ANNOTATIONS_LIST = "tableAnnotations";
private static final String NAMED_QUERY_LIST = "namedQuery";
private static final String NAMED_QUERIES_LIST = "namedQueries";
private static final String DISCRIMINATOR_VALUE_LIST = "discriminatorValueList";

@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
Expand All @@ -58,6 +65,7 @@ public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
.or(JavaClass.references("javax.persistence.Table").at(TypeReferenceLocation.ANNOTATION).as(TABLE_ANNOTATIONS_LIST))
.or(JavaClass.references("javax.persistence.NamedQuery").at(TypeReferenceLocation.ANNOTATION).as(NAMED_QUERY_LIST))
.or(JavaClass.references("javax.persistence.NamedQueries").at(TypeReferenceLocation.ANNOTATION).as(NAMED_QUERIES_LIST))
.or(JavaClass.references("javax.persistence.DiscriminatorValue").at(TypeReferenceLocation.ANNOTATION).as(DISCRIMINATOR_VALUE_LIST))
)
.perform(Iteration.over(ENTITY_ANNOTATIONS).perform(new AbstractIterationOperation<JavaTypeReferenceModel>()
{
Expand Down Expand Up @@ -85,17 +93,59 @@ private String getAnnotationLiteralValue(JavaAnnotationTypeReferenceModel model,
}
}

private void extractEntityBeanMetadata(GraphRewrite event, JavaTypeReferenceModel entityTypeReference)
private JavaAnnotationTypeReferenceModel findTableAnnotation(GraphRewrite event, List<AbstractJavaSourceModel> sourceModels)
{
for (AbstractJavaSourceModel sourceModel : sourceModels)
{
Optional<JavaAnnotationTypeReferenceModel> tableAnnotation = sourceModel.getAllTypeReferences().stream()
.filter(reference -> reference instanceof JavaAnnotationTypeReferenceModel)
.map(reference -> (JavaAnnotationTypeReferenceModel)reference)
.filter(annotationReference -> annotationReference.getResolvedSourceSnippit() != null && annotationReference.getResolvedSourceSnippit().contains("javax.persistence.Table"))
.findFirst();

if (tableAnnotation.isPresent())
return tableAnnotation.get();
else
return findTableAnnotation(event, getParentSourceFiles(event, sourceModel));
}
return null;
}

private List<AbstractJavaSourceModel> getParentSourceFiles(GraphRewrite event, AbstractJavaSourceModel sourceModel)
{
List<AbstractJavaSourceModel> result = new ArrayList<>();
if (sourceModel == null)
return result;

for (JavaClassModel javaClass : sourceModel.getJavaClasses())
{
JavaClassModel parentClass = javaClass.getExtends();
if (parentClass == null)
continue;

AbstractJavaSourceModel parentJavaSourceModel = parentClass.getDecompiledSource();
if (parentJavaSourceModel == null)
parentJavaSourceModel = parentClass.getOriginalSource();

if (parentJavaSourceModel == null)
{
LOG.warning("Could not find Java source for class: " + parentClass.getQualifiedName());
continue;
}

result.add(parentJavaSourceModel);
}
return result;
}

private JavaAnnotationTypeReferenceModel findTableAnnotation(GraphRewrite event, JavaTypeReferenceModel entityTypeReference)
{
LOG.log(Level.INFO, () -> "extractEntityBeanMetadata() with " + entityTypeReference.getDescription());
entityTypeReference.getFile().setGenerateSourceReport(true);
JavaAnnotationTypeReferenceModel entityAnnotationTypeReference = (JavaAnnotationTypeReferenceModel) entityTypeReference;
JavaAnnotationTypeReferenceModel tableAnnotationTypeReference = null;

final Iterable<? extends WindupVertexFrame> annotations_list = Variables.instance(event).findVariable(TABLE_ANNOTATIONS_LIST);
if (annotations_list != null)
final Iterable<? extends WindupVertexFrame> tableAnnotationList = Variables.instance(event).findVariable(TABLE_ANNOTATIONS_LIST);
if (tableAnnotationList != null)
{
for (WindupVertexFrame annotationTypeReferenceBase : annotations_list)
for (WindupVertexFrame annotationTypeReferenceBase : tableAnnotationList)
{
JavaAnnotationTypeReferenceModel annotationTypeReference = (JavaAnnotationTypeReferenceModel) annotationTypeReferenceBase;
if (annotationTypeReference.getFile().equals(entityTypeReference.getFile()))
Expand All @@ -106,6 +156,22 @@ private void extractEntityBeanMetadata(GraphRewrite event, JavaTypeReferenceMode
}
}

if (tableAnnotationTypeReference == null)
{
AbstractJavaSourceModel sourceModel = entityTypeReference.getFile();
tableAnnotationTypeReference = findTableAnnotation(event, getParentSourceFiles(event, sourceModel));
}

return tableAnnotationTypeReference;
}

private void extractEntityBeanMetadata(GraphRewrite event, JavaTypeReferenceModel entityTypeReference)
{
LOG.log(Level.INFO, () -> "extractEntityBeanMetadata() with " + entityTypeReference.getDescription());
entityTypeReference.getFile().setGenerateSourceReport(true);
JavaAnnotationTypeReferenceModel entityAnnotationTypeReference = (JavaAnnotationTypeReferenceModel) entityTypeReference;
JavaAnnotationTypeReferenceModel tableAnnotationTypeReference = findTableAnnotation(event, entityTypeReference);

JavaClassModel ejbClass = getJavaClass(entityTypeReference);

String ejbName = getAnnotationLiteralValue(entityAnnotationTypeReference, "name");
Expand Down
@@ -0,0 +1,75 @@
package org.jboss.windup.rules.apps.javaee.tests;

import org.apache.commons.io.FileUtils;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.windup.exec.WindupProcessor;
import org.jboss.windup.exec.configuration.WindupConfiguration;
import org.jboss.windup.graph.GraphContext;
import org.jboss.windup.graph.GraphContextFactory;
import org.jboss.windup.graph.model.ProjectModel;
import org.jboss.windup.graph.model.resource.FileModel;
import org.jboss.windup.graph.service.GraphService;
import org.jboss.windup.rules.apps.java.condition.SourceMode;
import org.jboss.windup.rules.apps.java.config.SourceModeOption;
import org.jboss.windup.rules.apps.javaee.AbstractTest;
import org.jboss.windup.rules.apps.javaee.model.EjbMessageDrivenModel;
import org.jboss.windup.rules.apps.javaee.model.JPAEntityModel;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import javax.inject.Inject;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*/
@RunWith(Arquillian.class)
public class DiscoverJPAAnnotationsTest extends AbstractTest
{
@Inject
private WindupProcessor processor;

@Inject
private GraphContextFactory factory;

@Test
public void testJPAMetadataExtraction() throws Exception
{
try (GraphContext context = factory.create(true))
{
String inputPath = "src/test/resources/jpa";

Path outputPath = Paths.get(FileUtils.getTempDirectory().toString(), "windup_"
+ UUID.randomUUID().toString());
FileUtils.deleteDirectory(outputPath.toFile());
Files.createDirectories(outputPath);

WindupConfiguration windupConfiguration = new WindupConfiguration()
.setGraphContext(context);
windupConfiguration.addInputPath(Paths.get(inputPath));
windupConfiguration.setOutputDirectory(outputPath);
windupConfiguration.setOptionValue(SourceModeOption.NAME, true);
processor.execute(windupConfiguration);

GraphService<JPAEntityModel> jpaEntityModelService = new GraphService<>(context, JPAEntityModel.class);
int jpaEntitiesFound = 0;
for (JPAEntityModel jpaEntityModel : jpaEntityModelService.findAll())
{
//Assert.assertEquals("ChatBeanDestination", msgDriven.getDestination().getJndiLocation());
if (jpaEntityModel.getEntityName().equals("SubclassWithDiscriminator"))
Assert.assertEquals("SimpleEntityTable", jpaEntityModel.getTableName());
else if (jpaEntityModel.getEntityName().equals("BaseEntity"))
Assert.assertEquals("SimpleEntityTable", jpaEntityModel.getTableName());
else
Assert.fail("Unknown entity found with name: " + jpaEntityModel.getEntityName());

jpaEntitiesFound++;
}
Assert.assertEquals(2, jpaEntitiesFound);
}
}
}
8 changes: 8 additions & 0 deletions rules-java-ee/tests/src/test/resources/jpa/BaseEntity.java
@@ -0,0 +1,8 @@
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="SimpleEntityTable")
public class BaseEntity {

}
@@ -0,0 +1,10 @@

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.NamedQuery;

@Entity
@DiscriminatorValue("DV")
public class SubclassWithDiscriminator extends BaseEntity {

}
Expand Up @@ -233,7 +233,7 @@ private void addParsedClassToFile(GraphRewrite event, EvaluationContext context,
{
Extendable<?> extendable = (Extendable<?>) javaSource;
String superclassName = extendable.getSuperType();
if (Strings.isNullOrEmpty(superclassName))
if (!Strings.isNullOrEmpty(superclassName))
javaClassModel.setExtends(javaClassService.getOrCreatePhantom(superclassName));
}

Expand Down

0 comments on commit 303912d

Please sign in to comment.