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.

Example: Different implementation of 'Method'

In this example, we will implement the "Method" model differently by using ObservableList instead of ArrayList.

Original code:

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);
    }
}

The new class 'ObservableMethodImpl'

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);
    }
}

Changing the default implementation

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.
    }
}
⚠️ **GitHub.com Fallback** ⚠️