Skip to content

Instantly share code, notes, and snippets.

@mark-jay
Last active March 19, 2016 19:21
Show Gist options
  • Select an option

  • Save mark-jay/daf667434404bfb36745 to your computer and use it in GitHub Desktop.

Select an option

Save mark-jay/daf667434404bfb36745 to your computer and use it in GitHub Desktop.
// --------------------------------------------------------------------------------
// abstract generic stuff:
public abstract class AbstractEntity {
ID, hibernate-version, reflective to-string/equals/hashcode
}
public UIWindowFactory {
public <T extends AbstractEntity> AbstractUIWindow<T> getUIWindow(T entity) {...}
}
public abstract class AbstractUIWindow<T extends AbstractEntity> {
public com.vaddin.Window generateEditWindow(T entity) { generateDefaultReflectiveEditWindow(entity); }
protected final com.vaddin.Window generateDefaultReflectiveEditWindow(T entity) {
// reflective-based implementation for general case.
}
// the same could be done for view(read-only edit)
public List<ValidationError> validate(T entity) { /* default reflective-based implementation */ }
}
public MigratorFactory {
public <Base extends AbstractEntity, Target extends Base> Migrator<Base, Target> getMigrator(Base entity, Class<Target> targetClass) {...}
}
public abstract class Migrator<Base extends AbstractEntity, Target extends Base> {
public abstract Target migrate(Base base);
protected Target reflectiveMigrate(Base base) { /* implementation */ }
}
public class MainUI {
public void openForm(AbstractEntity entity) {
UIWindowFactory.getUIWindow(entity).show();
}
public List<Class<? extends AbstractEntity>> getMigrationOptions(Class<AbstractEntity> entity) {
return getAllKnownSubclasses(entity.getClass().getSuperclass());
}
public Migrator<Base, Target> migrateAndOpen(Base entity, Class<Target> targetClass) {
try {
openForm(MigratorFactory.getMigrator(entity, targetClass).migrate(entity));
} catch (Exception e) {
/* show error */
}
}
}
// --------------------------------------------------------------------------------
// the first iteration
// enitties:
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="vversion",
discriminatorType=DiscriminatorType.STRING)
abstract class Person extends AbstractEntity {}
@DiscriminatorValue("V1")
class PersonV1 extends Person {
String firstName, lastName, street
}
// UI:
public class PersonV1UIWindow extends AbstractUIWindow<PersonV1> {} // nothing specific, let's just use default reflective implementation
// --------------------------------------------------------------------------------
// the second iteration
@DiscriminatorValue("V2")
class PersonV2 extends Person {
String firstName, String patronymic, Address address
}
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="vversion",
discriminatorType=DiscriminatorType.STRING)
abstract class Address extends AbstractEntity {}
@DiscriminatorValue("V1")
class AddressV1 extends Address {
String street, String house;
}
// UI:
public class PersonV2UIWindow extends AbstractUIWindow<PersonV1> {} // nothing specific, let's just use default reflective implementation
// Migrator:
public class PersonV2Migrator extends Migrator<Person, PersonV2> {
public abstract PersonV2 migrate(Person base) {
PersonV2 result = reflectiveMigrate(base); // mostly done automatically
if (base instanceOf PersonV1) {
result.setAddress(new Address(((PersonV1)base).getStreet(), null)); // and something is done manually
}
return result;
}
}
// --------------------------------------------------------------------------------
/*
-- database structure
Person { int id, version, varchar vversion, firstName, lastName, street; int address_id foreign key to address }
Address { int id, version, varchar vversion, street, house }
-- specific constraints examples:
alter table Person
add check (vversion != 'V1' or street not null)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment