Skip to content

Commit

Permalink
Merge pull request #40 from tacianosilva/issue39
Browse files Browse the repository at this point in the history
Fix bug - Absence of the annotation modifier in external class extraction

Awesome! Thanks, @tacianosilva !
  • Loading branch information
joaoarthurbm committed Apr 7, 2016
2 parents 37f0660 + 8d31334 commit ab2e9d3
Show file tree
Hide file tree
Showing 18 changed files with 350 additions and 23 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<dw.groupId>org.designwizard</dw.groupId>
<dw.artifactId>designwizard</dw.artifactId>
<dw.version>1.4</dw.version>
<dw.version>1.4.0.3</dw.version>
</properties>

<groupId>org.designwizard</groupId>
<artifactId>designwizard</artifactId>
<version>1.4</version>
<version>1.4.0.3</version>

<packaging>jar</packaging>

Expand Down
16 changes: 11 additions & 5 deletions src/org/designwizard/design/Design.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@ public void packageExtracted(String entity) {
}

@Override
public void annotationExtracted(String entity) {
if (!this.entities.containsKey(entity)) {
ClassNode annotation = new ClassNode(entity);
public void annotationExtracted(String entityName) {
if (!this.entities.containsKey(entityName)) {
ClassNode annotation = new ClassNode(entityName);
annotation.modifiers.add(Modifier.ANNOTATION);
this.entities.put(entity, annotation);
}
this.entities.put(entityName, annotation);
} else {
// If the entity extracted without the annotation modifier and It was using as Annotation.
ClassNode classNode = (ClassNode) this.entities.get(entityName);
if (classNode != null && !classNode.isAnnotation()) {
classNode.modifiers.add(Modifier.ANNOTATION);
}
}
}

public Set<ClassNode> getAllAnnotations() {
Expand Down
186 changes: 186 additions & 0 deletions src_tests/tests/org/designwizard/design/AnnotationsExtractTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package tests.org.designwizard.design;

import java.util.HashSet;
import java.util.Set;

import org.designwizard.api.DesignWizard;
import org.designwizard.design.ClassNode;
import org.designwizard.exception.InexistentEntityException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import junit.framework.TestCase;

/**
* Test for Issue 39 - Absence of the annotation modifier in external class extraction
* Link: https://github.com/joaoarthurbm/designwizard/issues/39
*
* The error occurs when an internal class (extraction project class) calls one of its methods
* to an external class of the annotation type. The extraction of external classes is simplified
* and only creates a corresponding ClassNode without assigning extra information
* (for example, does not extract modifiers).
*
* As the extraction process extracted the external class in a method call, before it appears
* as entry in a class, the ClassNode of the external class appears without annotation modifier.
* This modifier will only be identified when the external class is used to annotate a project class.
*
* However, the extraction code only adds the modifier in new ClassNodes and did not update
* the classNodes already extracted.
*
* The code below the method {@code Design#annotationExtracted(String)} is responsible
* for the annotation extraction.
*
* @author Taciano Morais Silva <tacianosilva@gmail.com>
*/
public class AnnotationsExtractTest extends TestCase {

private DesignWizard dw;

@Before
public void setUp() throws Exception {
String arquivoJar = "classes/tests/org/designwizard/design/mocks/annotations/issue39/";
dw = new DesignWizard(arquivoJar);
}

@After
public void tearDown() throws Exception {

}

@Test
public void testAllClasses() throws InexistentEntityException {
// Internal Classes of the project
Set<ClassNode> classes = dw.getAllClasses();

assertEquals("total classes: ", 8, classes.size());
}

@Test
public void testAllAnnotations() throws InexistentEntityException {
//Total used annotation (internal e external)
Set<ClassNode> annotations = dw.getAllAnnotations();

assertEquals("total annotations: ", 7, annotations.size());
}

@Test
public void testExtractAnnotationA() throws InexistentEntityException {
//external annotation and unused
ClassNode entityA = dw.getClass("tests.org.designwizard.design.mocks.annotations.external.AnnotationA");

assertNotNull("AnnotationA is not null?", entityA);
assertTrue("AnnotationA is annotation?", !entityA.isAnnotation());

// Classes annotated by external annotationA
Set<ClassNode> classesA = classesByAnnotation(dw,
"tests.org.designwizard.design.mocks.annotations.external.AnnotationA");
assertEquals("Num classes annotated by AnnotationB", 0, classesA.size());
}

@Test
public void testExtractAnnotationB() throws InexistentEntityException {
//external annotation and used
ClassNode entityB = dw.getClass("tests.org.designwizard.design.mocks.annotations.external.AnnotationB");

assertNotNull("AnnotationA is not null?", entityB);
assertTrue("AnnotationA is annotation?", entityB.isAnnotation());

// Classes annotated by external annotationB
Set<ClassNode> classesB = classesByAnnotation(dw,
"tests.org.designwizard.design.mocks.annotations.external.AnnotationB");
assertEquals("Num classes annotated by AnnotationB", 1, classesB.size());
}

@Test
public void testExtractAnnotationC() throws InexistentEntityException {
//external annotation, is not called and unused (it isn't extracted)
try {
dw.getClass("tests.org.designwizard.design.mocks.annotations.external.AnnotationC");
fail("This method must throw the exception: InexistentEntityException");
} catch(InexistentEntityException e) {
assertTrue(true);
}
}

@Test
public void testExtractAnnotationD() throws InexistentEntityException {
//internal annotation and used
ClassNode entityD = dw.getClass("tests.org.designwizard.design.mocks.annotations.issue39.AnnotationD");

assertNotNull("AnnotationA is not null?", entityD);
assertTrue("AnnotationA is annotation?", entityD.isAnnotation());

// Classes annotated by internal annotationD
Set<ClassNode> classesD = classesByAnnotation(dw,
"tests.org.designwizard.design.mocks.annotations.issue39.AnnotationD");
assertEquals("Num classes annotated by AnnotationD", 1, classesD.size());
}

@Test
public void testExtractAnnotationE() throws InexistentEntityException {
//internal annotation and unused
ClassNode entityE = dw.getClass("tests.org.designwizard.design.mocks.annotations.issue39.AnnotationE");

assertNotNull("AnnotationA is not null?", entityE);
assertTrue("AnnotationA is annotation?", entityE.isAnnotation());

// Classes annotated by internal annotationE
Set<ClassNode> classesE = classesByAnnotation(dw,
"tests.org.designwizard.design.mocks.annotations.issue39.AnnotationE");
assertEquals("Num classes annotated by AnnotationE", 0, classesE.size());
}

@Test
public void testExtractAnnotationF() throws InexistentEntityException {
//internal annotation and used
ClassNode entityF = dw.getClass("tests.org.designwizard.design.mocks.annotations.issue39.AnnotationF");

assertNotNull("AnnotationA is not null?", entityF);
assertTrue("AnnotationA is annotation?", entityF.isAnnotation());

// Classes annotated by internal annotationF
Set<ClassNode> classesF = classesByAnnotation(dw,
"tests.org.designwizard.design.mocks.annotations.issue39.AnnotationF");
assertEquals("Num classes annotated by AnnotationF", 1, classesF.size());
}

@Test
public void testExtractAnnotationG() throws InexistentEntityException {
//internal annotation and unused
ClassNode entityG = dw.getClass("tests.org.designwizard.design.mocks.annotations.issue39.AnnotationG");

assertNotNull("AnnotationA is not null?", entityG);
assertTrue("AnnotationA is annotation?", entityG.isAnnotation());

// Classes annotated by internal annotationG
Set<ClassNode> classesG = classesByAnnotation(dw,
"tests.org.designwizard.design.mocks.annotations.issue39.AnnotationG");
assertEquals("Num classes annotated by AnnotationG", 0, classesG.size());
}

public static Set<ClassNode> classesByAnnotation(DesignWizard dw, String annotationName) throws InexistentEntityException {

Set<ClassNode> allClasses = dw.getAllClasses();
ClassNode annotationNode = dw.getAnnotation(annotationName);

Set<ClassNode> classes = new HashSet<ClassNode>();

for (ClassNode classNode : allClasses) {
if (hasAnnotation(classNode, annotationNode)) {
classes.add(classNode);
}
}
return classes;
}

public static Boolean hasAnnotation(ClassNode aClass, ClassNode annotation) {
Set<ClassNode> annotations = aClass.getAnnotations();

if (annotations.contains(annotation)) {
return true;
}
return false;

}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package tests.org.designwizard.design;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Set;

import org.designwizard.api.DesignWizard;
Expand All @@ -17,7 +10,9 @@
import org.junit.Before;
import org.junit.Test;

public class AnnotationsOfClassTest {
import junit.framework.TestCase;

public class AnnotationsOfClassTest extends TestCase {

DesignWizard dw;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package tests.org.designwizard.design;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Set;

import org.designwizard.api.DesignWizard;
Expand All @@ -14,7 +10,9 @@
import org.junit.Before;
import org.junit.Test;

public class AnnotationsOfFieldTest {
import junit.framework.TestCase;

public class AnnotationsOfFieldTest extends TestCase {

DesignWizard dw;

Expand Down
4 changes: 2 additions & 2 deletions src_tests/tests/org/designwizard/design/MethodNodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,15 +322,15 @@ public void testMethodsWithRegularExpressions() throws InexistentEntityException
Set<MethodNode> methodsFinishingWithParenteses = dw.getMethods(".*(String(\\W))$");
assertFalse(methodsFinishingWithParenteses.isEmpty());
assertTrue(methodsFinishingWithParenteses.contains(dw.getMethod("org.designwizard.design.Design.packageExtracted(java.lang.String)")));
assertTrue(methodsFinishingWithParenteses.size() == 124);
assertTrue(methodsFinishingWithParenteses.size() == 125);

// Testa o retorno das method que contém a string "get" ou ".set"
Set<MethodNode> methodsThatContainsGetOrSet = dw.getMethods(".*get.*|.*(\\W)set.*");
assertFalse(methodsThatContainsGetOrSet.isEmpty());
assertTrue(methodsThatContainsGetOrSet.contains(dw.getMethod("org.designwizard.design.Design.setReturnType(java.lang.String,java.lang.String)")));
assertTrue(methodsThatContainsGetOrSet.contains(dw.getMethod("org.designwizard.design.PackageNode.getAllMethods()")));
assertFalse(methodsThatContainsGetOrSet.contains(dw.getMethod("org.designwizard.api.util.FileUtil.reset()")));
assertTrue(methodsThatContainsGetOrSet.size() == 217);
assertTrue(methodsThatContainsGetOrSet.size() == 218);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tests.org.designwizard.design.mocks.annotations.external;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationA {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tests.org.designwizard.design.mocks.annotations.external;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationB {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tests.org.designwizard.design.mocks.annotations.external;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationC {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package tests.org.designwizard.design.mocks.annotations.issue39;

import tests.org.designwizard.design.mocks.annotations.external.AnnotationB;

@AnnotationB
public class AnnotatedObjectB {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package tests.org.designwizard.design.mocks.annotations.issue39;

@AnnotationD
public class AnnotatedObjectD {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package tests.org.designwizard.design.mocks.annotations.issue39;

@AnnotationF
public class AnnotatedObjectF {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tests.org.designwizard.design.mocks.annotations.issue39;

import java.util.HashSet;
import java.util.Set;

import tests.org.designwizard.design.mocks.annotations.external.AnnotationA;
import tests.org.designwizard.design.mocks.annotations.external.AnnotationB;

public class AnnotationAccess {

private Set<Class> loadExternalAnnotation() {
Set<Class> set = new HashSet<Class>();

Class<AnnotationA> annotationA = AnnotationA.class;
Class<AnnotationB> annotationB = AnnotationB.class;
Class<AnnotationF> annotationF = AnnotationF.class;
Class<AnnotationG> annotationG = AnnotationG.class;

//External Annotation and unused.
set.add(annotationA);

//External Annotation and used.
set.add(annotationB);

//Internal Annotation and used.
set.add(annotationF);

//Internal Annotation and unused.
set.add(annotationG);

return set;
}

public static void main(String[] args) {

AnnotationAccess access = new AnnotationAccess();

Set<Class> annotations = access.loadExternalAnnotation();

for (Class annotation : annotations) {
System.out.println(annotation.getCanonicalName());
}
}
}
Loading

0 comments on commit ab2e9d3

Please sign in to comment.