[hibernate-commits] Hibernate SVN: r20777 - in jpamodelgen/trunk/src: test/java/org/hibernate/jpamodelgen/test and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Oct 6 07:16:15 EDT 2010


Author: hardy.ferentschik
Date: 2010-10-06 07:16:11 -0400 (Wed, 06 Oct 2010)
New Revision: 20777

Added:
   jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/
   jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/Entity.java
   jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/SeparateCompilationUnitsTest.java
   jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/superclass/
   jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/superclass/MappedSuperclass.java
Modified:
   jpamodelgen/trunk/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java
Log:
METAGEN-35 Actual code changes and tests for the issue.

Modified: jpamodelgen/trunk/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java
===================================================================
--- jpamodelgen/trunk/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java	2010-10-05 14:08:57 UTC (rev 20776)
+++ jpamodelgen/trunk/src/main/java/org/hibernate/jpamodelgen/ClassWriter.java	2010-10-06 11:16:11 UTC (rev 20777)
@@ -31,6 +31,8 @@
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
 import javax.tools.Diagnostic;
 import javax.tools.FileObject;
 
@@ -38,9 +40,13 @@
 import org.hibernate.jpamodelgen.model.MetaEntity;
 
 /**
+ * Helper class to write the actual meta model class using the  {@link javax.annotation.processing.Filer} API.
+ *
  * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
  */
 public final class ClassWriter {
+	private static final String META_MODEL_CLASS_NAME_SUFFIX = "_";
 
 	private ClassWriter() {
 	}
@@ -51,7 +57,7 @@
 			StringBuffer body = generateBody( entity, context );
 
 			FileObject fo = context.getProcessingEnvironment().getFiler().createSourceFile(
-					metaModelPackage + "." + entity.getSimpleName() + "_"
+					getFullyQualifiedClassName( entity, metaModelPackage )
 			);
 			OutputStream os = fo.openOutputStream();
 			PrintWriter pw = new PrintWriter( os );
@@ -63,7 +69,6 @@
 
 			pw.flush();
 			pw.close();
-
 		}
 		catch ( FilerException filerEx ) {
 			context.logMessage(
@@ -87,15 +92,14 @@
 	 * @return body content
 	 */
 	private static StringBuffer generateBody(MetaEntity entity, Context context) {
-
 		StringWriter sw = new StringWriter();
 		PrintWriter pw = null;
 		try {
 			pw = new PrintWriter( sw );
 			if ( context.isAddGeneratedAnnotation() ) {
-				pw.println( "@" + entity.importType( Generated.class.getName() ) + "(\"JPA MetaModel for " + entity.getQualifiedName() + "\")" );
+				pw.println( writeGeneratedAnnotation( entity ) );
 			}
-			pw.println( "@" + entity.importType( "javax.persistence.metamodel.StaticMetamodel" ) + "(" + entity.getSimpleName() + ".class)" );
+			pw.println( writeStaticMetaModelAnnotation( entity ) );
 			printClassDeclaration( entity, pw, context );
 			pw.println();
 			List<MetaAttribute> members = entity.getMembers();
@@ -114,19 +118,62 @@
 	}
 
 	private static void printClassDeclaration(MetaEntity entity, PrintWriter pw, Context context) {
-		pw.print( "public abstract class " + entity.getSimpleName() + "_" );
+		pw.print( "public abstract class " + entity.getSimpleName() + META_MODEL_CLASS_NAME_SUFFIX );
 
 		final TypeMirror superClass = entity.getTypeElement().getSuperclass();
 		//superclass of Object is of NoType which returns some other kind
 		if ( superClass.getKind() == TypeKind.DECLARED ) {
 			//F..king Ch...t Have those people used their horrible APIs even once?
-			final Element superClassElement = ( ( DeclaredType ) superClass ).asElement();
-			String superClassName = ( ( TypeElement ) superClassElement ).getQualifiedName().toString();
-			if ( context.containsMetaEntity( superClassName )
-					|| context.containsMetaEmbeddable( superClassName ) ) {
-				pw.print( " extends " + superClassName + "_" );
+			final Element superClassElement = ( (DeclaredType) superClass ).asElement();
+			String superClassName = ( (TypeElement) superClassElement ).getQualifiedName().toString();
+			if ( extendsSuperMetaModel( superClassElement, entity.isMetaComplete(), context ) ) {
+				pw.print( " extends " + superClassName + META_MODEL_CLASS_NAME_SUFFIX );
 			}
 		}
 		pw.println( " {" );
 	}
+
+	/**
+	 * Checks whether this metamodel class needs to extend another metamodel class.
+	 * This methods checks whether the processor has generated a metamodel class for the super class, but it also
+	 * allows for the possibility that the metamodel class was generated in a previous compilation (eg it could be
+	 * part of a separate jar. See also METAGEN-35).
+	 *
+	 * @param superClassElement the super class element
+	 * @param entityMetaComplete flag indicating if the entity for which the metamodel should be generarted is metamodel
+	 * complete. If so we cannot use reflection to decide whether we have to add the extend clause
+	 * @param context the execution context
+	 *
+	 * @return {@code true} in case there is super class meta model to extend from {@code false} otherwise.
+	 */
+	private static boolean extendsSuperMetaModel(Element superClassElement, boolean entityMetaComplete, Context context) {
+		// if we processed the superclass in the same run we definitely need to extend
+		String superClassName = ( (TypeElement) superClassElement ).getQualifiedName().toString();
+		if ( context.containsMetaEntity( superClassName )
+				|| context.containsMetaEmbeddable( superClassName ) ) {
+			return true;
+		}
+
+		// to allow for the case that the metamodel class for the super entity is for example contained in another
+		// jar file we use reflection. However, we need to consider the fact that there is xml configuration
+		// and annotations should be ignored
+		if ( !entityMetaComplete && ( superClassElement.getAnnotation( Entity.class ) != null
+				|| superClassElement.getAnnotation( MappedSuperclass.class ) != null ) ) {
+			return true;
+		}
+
+		return false;
+	}
+
+	private static String getFullyQualifiedClassName(MetaEntity entity, String metaModelPackage) {
+		return metaModelPackage + "." + entity.getSimpleName() + META_MODEL_CLASS_NAME_SUFFIX;
+	}
+
+	private static String writeGeneratedAnnotation(MetaEntity entity) {
+		return "@" + entity.importType( Generated.class.getName() ) + "(\"JPA MetaModel for " + entity.getQualifiedName() + "\")";
+	}
+
+	private static String writeStaticMetaModelAnnotation(MetaEntity entity) {
+		return "@" + entity.importType( "javax.persistence.metamodel.StaticMetamodel" ) + "(" + entity.getSimpleName() + ".class)";
+	}
 }

Added: jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/Entity.java
===================================================================
--- jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/Entity.java	                        (rev 0)
+++ jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/Entity.java	2010-10-06 11:16:11 UTC (rev 20777)
@@ -0,0 +1,31 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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.
+ */
+
+// $Id:$
+package org.hibernate.jpamodelgen.test.separatecompilationunits;
+
+import org.hibernate.jpamodelgen.test.separatecompilationunits.superclass.MappedSuperclass;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at javax.persistence.Entity
+public class Entity extends MappedSuperclass {
+	private String name;
+}
+
+


Property changes on: jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/Entity.java
___________________________________________________________________
Name: svn:keywords
   + Id

Added: jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/SeparateCompilationUnitsTest.java
===================================================================
--- jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/SeparateCompilationUnitsTest.java	                        (rev 0)
+++ jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/SeparateCompilationUnitsTest.java	2010-10-06 11:16:11 UTC (rev 20777)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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.
+ */
+
+// $Id$
+
+package org.hibernate.jpamodelgen.test.separatecompilationunits;
+
+import java.io.File;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.hibernate.jpamodelgen.test.util.CompilationTest;
+
+import static org.hibernate.jpamodelgen.test.util.TestUtil.getMetaModelSourceAsString;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @author Hardy Ferentschik
+ * @see METAGEN-35
+ */
+public class SeparateCompilationUnitsTest extends CompilationTest {
+	@Test
+	public void testInheritance() throws Exception {
+		// need to work with the source file. Entity_.class won't get generated, because the mapped superclass
+		// will not be on the classpath
+		String entityMetaModel = getMetaModelSourceAsString( Entity.class );
+		assertTrue(
+				entityMetaModel.contains(
+						"extends org.hibernate.jpamodelgen.test.separatecompilationunits.superclass.MappedSuperclass"
+				)
+		);
+	}
+
+	@Override
+	@BeforeClass
+	// override compileAllTestEntities to compile the mapped super class explicitly
+	protected void compileAllTestEntities() throws Exception {
+		String superClassPackageName = getPackageNameOfCurrentTest() + ".superclass";
+		List<File> sourceFiles = getCompilationUnits(
+				CompilationTest.getSourceBaseDir(), superClassPackageName
+		);
+		compile( sourceFiles, superClassPackageName );
+
+		sourceFiles = getCompilationUnits( getSourceBaseDir(), getPackageNameOfCurrentTest() );
+		compile( sourceFiles, getPackageNameOfCurrentTest() );
+	}
+
+	@Override
+	protected String getPackageNameOfCurrentTest() {
+		return SeparateCompilationUnitsTest.class.getPackage().getName();
+	}
+}


Property changes on: jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/SeparateCompilationUnitsTest.java
___________________________________________________________________
Name: svn:keywords
   + Id

Added: jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/superclass/MappedSuperclass.java
===================================================================
--- jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/superclass/MappedSuperclass.java	                        (rev 0)
+++ jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/superclass/MappedSuperclass.java	2010-10-06 11:16:11 UTC (rev 20777)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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.
+ */
+
+// $Id:$
+package org.hibernate.jpamodelgen.test.separatecompilationunits.superclass;
+
+import javax.persistence.Id;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at javax.persistence.MappedSuperclass
+public class MappedSuperclass {
+	@Id
+	private long id;
+}
+
+


Property changes on: jpamodelgen/trunk/src/test/java/org/hibernate/jpamodelgen/test/separatecompilationunits/superclass/MappedSuperclass.java
___________________________________________________________________
Name: svn:keywords
   + Id



More information about the hibernate-commits mailing list