package org.hibernate.test.schemafilter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Namespace;
import org.hibernate.boot.model.relational.Sequence;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.mapping.Table;
import org.hibernate.tool.schema.internal.DefaultSchemaFilter;
import org.hibernate.tool.schema.internal.SchemaCreatorImpl;
import org.hibernate.tool.schema.internal.SchemaDropperImpl;
import org.hibernate.tool.schema.spi.SchemaFilter;
import org.hibernate.testing.AfterClassOnce;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Assert;
import org.junit.Test;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import static org.hibernate.test.schemafilter.RecordingTarget.Category.SCHEMA_CREATE;
import static org.hibernate.test.schemafilter.RecordingTarget.Category.SCHEMA_DROP;
import static org.hibernate.test.schemafilter.RecordingTarget.Category.TABLE_CREATE;
import static org.hibernate.test.schemafilter.RecordingTarget.Category.TABLE_DROP;
@TestForIssue(jiraKey = "HHH-9876")
@SuppressWarnings({"rawtypes", "unchecked"})
@RequiresDialectFeature( value = {DialectChecks.SupportSchemaCreation.class})
public class SchemaFilterTest extends BaseUnitTestCase {
private final StandardServiceRegistryImpl serviceRegistry;
private final Metadata metadata;
public SchemaFilterTest() {
Map settings = new HashMap();
settings.putAll( Environment.getProperties() );
settings.put( AvailableSettings.DIALECT, SQLServerDialect.class.getName() );
settings.put( AvailableSettings.FORMAT_SQL, false );
this.serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( settings );
MetadataSources ms = new MetadataSources( serviceRegistry );
ms.addAnnotatedClass( SchemaNoneEntity0.class );
ms.addAnnotatedClass( Schema1Entity1.class );
ms.addAnnotatedClass( Schema1Entity2.class );
ms.addAnnotatedClass( Schema2Entity3.class );
ms.addAnnotatedClass( Schema2Entity4.class );
this.metadata = ms.buildMetadata();
}
@AfterClassOnce
public void shutdown() {
serviceRegistry.destroy();
}
@Test
public void createSchema_unfiltered() {
RecordingTarget target = doCreation( new DefaultSchemaFilter() );
Assert.assertThat( target.getActions( SCHEMA_CREATE ), containsExactly( "the_schema_1", "the_schema_2" ) );
Assert.assertThat( target.getActions( TABLE_CREATE ), containsExactly(
"the_entity_0",
"the_schema_1.the_entity_1",
"the_schema_1.the_entity_2",
"the_schema_2.the_entity_3",
"the_schema_2.the_entity_4"
) );
}
@Test
public void createSchema_filtered() {
RecordingTarget target = doCreation( new TestSchemaFilter() );
Assert.assertThat( target.getActions( SCHEMA_CREATE ), containsExactly( "the_schema_1" ) );
Assert.assertThat(
target.getActions( TABLE_CREATE ),
containsExactly( "the_entity_0", "the_schema_1.the_entity_1" )
);
}
@Test
public void dropSchema_unfiltered() {
RecordingTarget target = doDrop( new DefaultSchemaFilter() );
Assert.assertThat( target.getActions( SCHEMA_DROP ), containsExactly( "the_schema_1", "the_schema_2" ) );
Assert.assertThat( target.getActions( TABLE_DROP ), containsExactly(
"the_entity_0",
"the_schema_1.the_entity_1",
"the_schema_1.the_entity_2",
"the_schema_2.the_entity_3",
"the_schema_2.the_entity_4"
) );
}
@Test
public void dropSchema_filtered() {
RecordingTarget target = doDrop( new TestSchemaFilter() );
Assert.assertThat( target.getActions( SCHEMA_DROP ), containsExactly( "the_schema_1" ) );
Assert.assertThat(
target.getActions( TABLE_DROP ),
containsExactly( "the_entity_0", "the_schema_1.the_entity_1" )
);
}
private RecordingTarget doCreation(SchemaFilter filter) {
RecordingTarget target = new RecordingTarget();
new SchemaCreatorImpl( serviceRegistry, filter ).doCreation( metadata, true, target );
return target;
}
private RecordingTarget doDrop(SchemaFilter filter) {
RecordingTarget target = new RecordingTarget();
new SchemaDropperImpl( serviceRegistry, filter ).doDrop( metadata, true, target );
return target;
}
private BaseMatcher<Set<String>> containsExactly(Object... expected) {
return containsExactly( new HashSet( Arrays.asList( expected ) ) );
}
private BaseMatcher<Set<String>> containsExactly(final Set expected) {
return new BaseMatcher<Set<String>>() {
@Override
public boolean matches(Object item) {
Set set = (Set) item;
return set.size() == expected.size()
&& set.containsAll( expected );
}
@Override
public void describeTo(Description description) {
description.appendText( "Is set containing exactly " + expected );
}
};
}
private static class TestSchemaFilter implements SchemaFilter {
@Override
public boolean includeNamespace(Namespace namespace) {
// exclude schema "the_schema_2"
Identifier identifier = namespace.getName().getSchema();
if ( identifier != null ) {
return !"the_schema_2".equals( identifier.getText() );
}
return true;
}
@Override
public boolean includeTable(Table table) {
// exclude table "the_entity_2"
return !"the_entity_2".equals( table.getName() );
}
@Override
public boolean includeSequence(Sequence sequence) {
return true;
}
}
@Entity
@javax.persistence.Table(name = "the_entity_1", schema = "the_schema_1")
public static class Schema1Entity1 {
@Id
private long id;
public long getId() {
return id;
}
public void setId( long id ) {
this.id = id;
}
}
@Entity
@javax.persistence.Table(name = "the_entity_2", schema = "the_schema_1")
public static class Schema1Entity2 {
@Id
private long id;
public long getId() {
return id;
}
public void setId( long id ) {
this.id = id;
}
}
@Entity
@javax.persistence.Table(name = "the_entity_3", schema = "the_schema_2")
public static class Schema2Entity3 {
@Id
private long id;
public long getId() {
return id;
}
public void setId( long id ) {
this.id = id;
}
}
@Entity
@javax.persistence.Table(name = "the_entity_4", schema = "the_schema_2")
public static class Schema2Entity4 {
@Id
private long id;
public long getId() {
return id;
}
public void setId( long id ) {
this.id = id;
}
}
@Entity
@javax.persistence.Table(name = "the_entity_0")
public static class SchemaNoneEntity0 {
@Id
private long id;
public long getId() {
return id;
}
public void setId( long id ) {
this.id = id;
}
}
}