Change the implementation of a model - Pyknic/CodeGen GitHub Wiki
One of the major advantages of this code generator is that every part of it is designed to be modular. If you want to create your own models, you can do that. If you want to change the implementation of an existing model, you can do that as well.
In this example, we will implement the "Method" model differently by using ObservableList instead of ArrayList.
public class MethodImpl implements Method {
private String name;
private Type type;
private Optional<Javadoc> javadoc;
private final List<AnnotationUsage> annotations;
private final List<Generic> generics;
private final List<Field> params;
private final List<String> code;
private final Set<Modifier> modifiers;
public MethodImpl(String name, Type type) {
this.name = name;
this.type = type;
this.javadoc = Optional.empty();
this.annotations = new ArrayList<>();
this.generics = new ArrayList<>();
this.params = new ArrayList<>();
this.code = new ArrayList<>();
this.modifiers = EnumSet.noneOf(Modifier.class);
}
private MethodImpl(final MethodImpl prototype) {
name = prototype.name;
type = prototype.type;
javadoc = Copier.copy(prototype.javadoc);
annotations = Copier.copy(prototype.annotations);
generics = Copier.copy(prototype.generics);
params = Copier.copy(prototype.params);
code = Copier.copy(prototype.code, s -> s);
modifiers = Copier.copy(prototype.modifiers, c -> c.copy(), EnumSet.noneOf(Modifier.class));
}
⋮
@Override
public List<Field> getFields() {
return params;
}
@Override
public List<String> getCode() {
return code;
}
@Override
public Set<Modifier> getModifiers() {
return modifiers;
}
⋮
@Override
public MethodImpl copy() {
return new MethodImpl(this);
}
}
public class ObservableMethodImpl implements Method {
private String name;
private Type type;
private Optional<Javadoc> javadoc;
private final ObservableList<AnnotationUsage> annotations;
private final ObservableList<Generic> generics;
private final ObservableList<Field> params;
private final ObservableList<String> code;
private final ObservableSet<Modifier> modifiers;
public ObservableMethodImpl(String name, Type type) {
this.name = name;
this.type = type;
this.javadoc = Optional.empty();
this.annotations = emptyList();
this.generics = emptyList();
this.params = emptyList();
this.code = emptyList();
this.modifiers = emptySet();
}
private ObservableMethodImpl(final ObservableMethodImpl prototype) {
name = prototype.name;
type = prototype.type;
javadoc = Copier.copy(prototype.javadoc);
annotations = Copier.copy(prototype.annotations, s -> s.copy(), emptyList());
generics = Copier.copy(prototype.generics, s -> s.copy(), emptyList());
params = Copier.copy(prototype.params, s -> s.copy(), emptyList());
code = Copier.copy(prototype.code, s -> s, emptyList());
modifiers = Copier.copy(prototype.modifiers, c -> c.copy(), emptySet());
}
private static <T> ObservableList<T> emptyList() {
return FXCollections.observableList(new ArrayList<T>());
}
private static ObservableSet<Modifier> emptySet() {
return FXCollections.observableSet(EnumSet.noneOf(Modifier.class));
}
⋮
@Override
public List<Field> getFields() {
return params;
}
@Override
public List<String> getCode() {
return code;
}
@Override
public Set<Modifier> getModifiers() {
return modifiers;
}
⋮
@Override
public ObservableMethodImpl copy() {
return new ObservableMethodImpl(this);
}
}
Now we have two different classes that follow the same interface. We must still switch which implementation should be used as default. This can be done using the "Method.setPrototype()"-method.
public class ChangeModelImplementationExample {
public static void main(String... params) {
Method.setPrototype(new ObservableMethodImpl(null, null));
final Method example = Method.of("main", Default.VOID); // Will use the new implementation.
}
}