From eae715584b234d8e4d5c71c7a4f96e142109f5ef Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 10 Feb 2012 08:25:33 -0600 Subject: [PATCH] HHH-7049 - Add tests of org.hibernate.metamodel.internal.source stuff --- .../attribute/ColumnValuesSourceImpl.java | 6 ++ .../attribute/DerivedValueSourceImpl.java | 8 +- .../source/hbm/ColumnAttributeSourceImpl.java | 6 ++ .../internal/source/hbm/ColumnSourceImpl.java | 7 ++ .../internal/source/hbm/FormulaImpl.java | 6 ++ .../source/hbm/RootEntitySourceImpl.java | 26 +++-- .../spi/source/RelationalValueSource.java | 22 +++++ .../internal/source/AssertSourcesTest.java | 96 ++++++++++++++++++- 8 files changed, 164 insertions(+), 13 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java index c5b6368b4f..261b5d1f6c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java @@ -26,6 +26,7 @@ import org.hibernate.metamodel.spi.relational.Datatype; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * @author Steve Ebersole @@ -41,6 +42,11 @@ void setOverrideColumnValues(ColumnValues columnValues) { this.columnValues = columnValues; } + @Override + public Nature getNature() { + return Nature.COLUMN; + } + @Override public String getName() { return columnValues.getName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/DerivedValueSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/DerivedValueSourceImpl.java index 061a461623..cc104dd3cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/DerivedValueSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/DerivedValueSourceImpl.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.internal.source.annotations.attribute; import org.hibernate.metamodel.spi.source.DerivedValueSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * @author Strong Liu @@ -35,7 +36,12 @@ public class DerivedValueSourceImpl implements DerivedValueSource { this.formulaValue = formulaValue; } - @Override + @Override + public Nature getNature() { + return Nature.DERIVED; + } + + @Override public String getExpression() { return formulaValue.getExpression(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java index e7009ac4d8..869410202d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java @@ -26,6 +26,7 @@ import org.hibernate.metamodel.spi.relational.Datatype; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * Implementation of a {@link ColumnSource} when the column is declared as just the name via the column XML @@ -61,6 +62,11 @@ class ColumnAttributeSourceImpl implements ColumnSource { this.isForceNotNull = isForceNotNull; } + @Override + public Nature getNature() { + return Nature.COLUMN; + } + @Override public boolean isIncludedInInsert() { return includedInInsert; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java index c080d7bfa2..4cbd5b4ff8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java @@ -27,6 +27,7 @@ import org.hibernate.metamodel.spi.relational.Datatype; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.source.ColumnSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * @author Steve Ebersole @@ -45,6 +46,7 @@ class ColumnSourceImpl implements ColumnSource { boolean isIncludedInUpdate) { this(tableName, columnElement, isIncludedInInsert, isIncludedInUpdate, false); } + ColumnSourceImpl( String tableName, JaxbColumnElement columnElement, @@ -58,6 +60,11 @@ class ColumnSourceImpl implements ColumnSource { includedInUpdate = isIncludedInUpdate; } + @Override + public Nature getNature() { + return Nature.COLUMN; + } + @Override public String getName() { return columnElement.getName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java index 5bba7f3fcb..383b7c65b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/FormulaImpl.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.internal.source.hbm; import org.hibernate.metamodel.spi.source.DerivedValueSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; /** * @author Steve Ebersole @@ -37,6 +38,11 @@ class FormulaImpl implements DerivedValueSource { this.expression = expression; } + @Override + public Nature getNature() { + return Nature.DERIVED; + } + @Override public String getExpression() { return expression; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java index 04a1585435..2da6ad35f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java @@ -29,6 +29,7 @@ import org.hibernate.internal.jaxb.mapping.hbm.JaxbCacheElement; import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.Value; import org.hibernate.metamodel.spi.binding.Caching; import org.hibernate.metamodel.spi.binding.IdGenerator; import org.hibernate.metamodel.spi.source.MappingException; @@ -150,16 +151,25 @@ public OptimisticLockStyle getOptimisticLockStyle() { } } + private Value cachingHolder = new Value( + new Value.DeferredInitializer() { + @Override + public Caching initialize() { + final JaxbCacheElement cache = entityElement().getCache(); + if ( cache == null ) { + return null; + } + final String region = cache.getRegion() != null ? cache.getRegion() : getEntityName(); + final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() ); + final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() ); + return new Caching( region, accessType, cacheLazyProps ); + } + } + ); + @Override public Caching getCaching() { - final JaxbCacheElement cache = entityElement().getCache(); - if ( cache == null ) { - return null; - } - final String region = cache.getRegion() != null ? cache.getRegion() : getEntityName(); - final AccessType accessType = Enum.valueOf( AccessType.class, cache.getUsage() ); - final boolean cacheLazyProps = !"non-lazy".equals( cache.getInclude() ); - return new Caching( region, accessType, cacheLazyProps ); + return cachingHolder.getValue(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java index 1a3a07d863..a3608a169b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RelationalValueSource.java @@ -36,4 +36,26 @@ public interface RelationalValueSource { * @return returns the name of the table that contains this value. */ public String getContainingTableName(); + + /** + * Retrieve the nature of this relational value. Is it a column? Or is it a derived value (formula)? + * + * @return The nature. + */ + public Nature getNature(); + + public static enum Nature { + COLUMN( ColumnSource.class ), + DERIVED( DerivedValueSource.class ); + + private final Class specificContractClass; + + private Nature(Class specificContractClass) { + this.specificContractClass = specificContractClass; + } + + public Class getSpecificContractClass() { + return specificContractClass; + } + } } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java index 3ff9f591ff..d18428657a 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java @@ -24,18 +24,25 @@ package org.hibernate.metamodel.internal.source; import java.util.Iterator; +import java.util.List; -import org.hibernate.metamodel.Metadata; +import org.hibernate.EntityMode; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.internal.MetadataBuilderImpl; import org.hibernate.metamodel.internal.MetadataImpl; -import org.hibernate.metamodel.internal.source.annotations.AnnotationMetadataSourceProcessorImpl; import org.hibernate.metamodel.internal.source.hbm.HbmMetadataSourceProcessorImpl; import org.hibernate.metamodel.spi.MetadataSourceProcessor; import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.ColumnSource; import org.hibernate.metamodel.spi.source.EntityHierarchy; -import org.hibernate.metamodel.spi.source.MetadataImplementor; +import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; import org.hibernate.metamodel.spi.source.RootEntitySource; +import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; +import org.hibernate.metamodel.spi.source.SingularAttributeNature; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.TableSource; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; @@ -43,7 +50,10 @@ import org.hibernate.testing.junit4.BaseUnitTestCase; +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; /** @@ -76,9 +86,87 @@ private void testUserEntitySources(MetadataSourceProcessor processor) { EntityHierarchy hierarchy = hierarchies.next(); assertFalse( hierarchies.hasNext() ); assertTrue( hierarchy.getHierarchyInheritanceType() == InheritanceType.NO_INHERITANCE ); + RootEntitySource entitySource = hierarchy.getRootEntitySource(); assertFalse( entitySource.subclassEntitySources().iterator().hasNext() ); - // finish up with assertions on attributes, etc + assertEquals( User.class.getName(), entitySource.getClassName() ); + assertEquals( User.class.getName(), entitySource.getEntityName() ); + assertNull( User.class.getName(), entitySource.getJpaEntityName() ); + + assertEquals( EntityMode.POJO, entitySource.getEntityMode() ); + assertNull( entitySource.getCaching() ); + assertNull( entitySource.getDiscriminatorSource() ); + assertNull( entitySource.getDiscriminatorMatchValue() ); + + assertTrue( entitySource.getJpaCallbackClasses() == null || entitySource.getJpaCallbackClasses().isEmpty() ); + + TableSource primaryTable = entitySource.getPrimaryTable(); + // todo : should sources be responsible for figuring out logical names? + // these are the things that need to match in terms of lookup keys + assertNull( primaryTable.getLogicalName() ); + assertNull( primaryTable.getExplicitCatalogName() ); + assertNull( primaryTable.getExplicitSchemaName() ); + assertNull( primaryTable.getExplicitTableName() ); + + assertFalse( entitySource.getSecondaryTables().iterator().hasNext() ); + assertTrue( + entitySource.getSynchronizedTableNames() == null + || entitySource.getSynchronizedTableNames().isEmpty() + ); + + IdentifierSource identifierSource = entitySource.getIdentifierSource(); + assertNotNull( identifierSource ); + assertEquals( IdentifierSource.Nature.SIMPLE, identifierSource.getNature() ); + SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource; + SingularAttributeSource identifierAttributeSource = simpleIdentifierSource.getIdentifierAttributeSource(); + assertEquals( "id", identifierAttributeSource.getName() ); + assertTrue( identifierAttributeSource.isSingular() ); + assertFalse( identifierAttributeSource.isVirtualAttribute() ); + // todo : see note about semantic interpretation below ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // todo : also, it's not really the attribute that is insertable/updatable; it is its individual values + assertTrue( identifierAttributeSource.isInsertable() ); + assertFalse( identifierAttributeSource.isUpdatable() ); + // todo : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + assertFalse( identifierAttributeSource.isLazy() ); + assertEquals( SingularAttributeNature.BASIC, identifierAttributeSource.getNature() ); + assertEquals( PropertyGeneration.INSERT, identifierAttributeSource.getGeneration() ); + assertNull( identifierAttributeSource.getPropertyAccessorName() ); + + // todo : here is an interesting question in terms of who is responsible for semantic interpretation + // really an attribute for identifier should never be included in updates + // and it should only be included in inserts only in certain cases + // and should never be nullable + // ^^ all because this is the PK. That is the semantic interpretation of those values based on that context. + // + // So do sources simply return explicit user values? Or do they consider such semantic analysis? + assertTrue( identifierAttributeSource.areValuesIncludedInInsertByDefault() ); + assertTrue( identifierAttributeSource.areValuesIncludedInUpdateByDefault() ); + assertFalse( identifierAttributeSource.areValuesNullableByDefault() ); + + // todo : return collections? or iterables? + // todo : empty collections? or null? + assertEquals( 0, identifierAttributeSource.relationalValueSources().size() ); +// RelationalValueSource relationalValueSource = identifierAttributeSource.relationalValueSources().get( 0 ); +// assertNull( relationalValueSource.getContainingTableName() ); +// assertEquals( RelationalValueSource.Nature.COLUMN, relationalValueSource.getNature() ); +// ColumnSource columnSource = (ColumnSource) relationalValueSource; +// assertNull( columnSource.getName() ); +// assertNull( columnSource.getReadFragment() ); +// assertNull( columnSource.getWriteFragment() ); +// assertNull( columnSource.getDefaultValue() ); +// assertNull( columnSource.getSqlType() ); +// assertNull( columnSource.getCheckCondition() ); +// assertNull( columnSource.getComment() ); +// assertNull( columnSource.getDatatype() ); +// assertNull( columnSource.getSize() ); +// // todo : technically, pk has to be unique, but this another semantic case +// assertFalse( columnSource.isUnique() ); +// // todo : see comments above +// assertFalse( columnSource.isIncludedInInsert() ); +// assertFalse( columnSource.isIncludedInUpdate() ); +// assertFalse( columnSource.isNullable() ); + + } }