Skip to content

Commit

Permalink
EntityComponentFactory, Attribute type parameter removed, DefaultEnti…
Browse files Browse the repository at this point in the history
…tyComponentFactory refactored accordingly
  • Loading branch information
bjorndarri committed Sep 28, 2024
1 parent b7d72ba commit 97abcb4
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 63 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Codion Change Log
- SwingEntityTableModel bug fixed, constructor used refresh, which could be async, instead of adding items directly to the model.
### is.codion.swing.framework.ui
- EntityComponentFactory.caption() added, related refactoring.
- EntityComponentFactory, Attribute type parameter removed, DefaultEntityComponentFactory refactored accordingly.

## 0.18.15
### is.codion.common.core
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package is.codion.framework.demos.chinook.ui;

import is.codion.framework.demos.chinook.domain.Chinook.Album;
import is.codion.framework.domain.entity.attribute.Attribute;
import is.codion.plugin.imagepanel.NavigableImagePanel;
import is.codion.swing.common.ui.Utilities;
import is.codion.swing.common.ui.Windows;
Expand Down Expand Up @@ -92,11 +91,10 @@ private static BufferedImage readImage(byte[] bytes) {
}

private static final class TagEditComponentFactory
implements EntityComponentFactory<List<String>, Attribute<List<String>>, AlbumTagPanel> {
implements EntityComponentFactory<List<String>, AlbumTagPanel> {

@Override
public ComponentValue<List<String>, AlbumTagPanel> componentValue(Attribute<List<String>> attribute,
SwingEntityEditModel editModel,
public ComponentValue<List<String>, AlbumTagPanel> componentValue(SwingEntityEditModel editModel,
List<String> initialValue) {
return new TagComponentValue(initialValue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,23 @@
*/
package is.codion.framework.demos.chinook.ui;

import is.codion.framework.demos.chinook.domain.Chinook.InvoiceLine;
import is.codion.framework.domain.entity.Entity;
import is.codion.framework.domain.entity.attribute.ForeignKey;
import is.codion.swing.common.ui.component.value.ComponentValue;
import is.codion.swing.framework.model.SwingEntityEditModel;
import is.codion.swing.framework.ui.component.DefaultEntityComponentFactory;
import is.codion.swing.framework.ui.component.EntitySearchField;

public final class TrackComponentFactory extends DefaultEntityComponentFactory<Entity, ForeignKey, EntitySearchField> {
final class TrackComponentFactory extends DefaultEntityComponentFactory<Entity, EntitySearchField> {

TrackComponentFactory() {
super(InvoiceLine.TRACK_FK);
}

@Override
public ComponentValue<Entity, EntitySearchField> componentValue(ForeignKey foreignKey,
SwingEntityEditModel editModel,
public ComponentValue<Entity, EntitySearchField> componentValue(SwingEntityEditModel editModel,
Entity initialValue) {
ComponentValue<Entity, EntitySearchField> componentValue = super.componentValue(foreignKey, editModel, initialValue);
ComponentValue<Entity, EntitySearchField> componentValue = super.componentValue(editModel, initialValue);
EntitySearchField trackSearchField = componentValue.component();
trackSearchField.selectorFactory().set(new TrackSelectorFactory());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import is.codion.swing.framework.model.SwingEntityEditModel;
import is.codion.swing.framework.ui.EntityTableCellEditorFactory;
import is.codion.swing.framework.ui.EntityTablePanel;
import is.codion.swing.framework.ui.component.DefaultEntityComponentFactory;
import is.codion.swing.framework.ui.component.EntityComponentFactory;
import is.codion.swing.framework.ui.component.EntityComponents;

import javax.swing.JSpinner;
Expand All @@ -52,8 +52,7 @@ public final class TrackTablePanel extends EntityTablePanel {
public TrackTablePanel(TrackTableModel tableModel) {
super(tableModel, config -> config
.editComponentFactory(Track.RATING, new RatingComponentFactory())
.editComponentFactory(Track.MILLISECONDS, new MinutesSecondsComponentFactory(false,
tableModel.entityDefinition().attributes().definition(Track.MINUTES_SECONDS).caption()))
.editComponentFactory(Track.MILLISECONDS, new MinutesSecondsComponentFactory(tableModel))
.configureTable(tableBuilder -> tableBuilder
.cellRendererFactory(new RatingCellRendererFactory(tableModel, Track.RATING))
.cellEditorFactory(new TrackCellEditorFactory(tableModel.editModel())))
Expand Down Expand Up @@ -87,29 +86,26 @@ private BigDecimal getAmountFromUser() {
}

private static final class RatingComponentFactory
extends DefaultEntityComponentFactory<Integer, Attribute<Integer>, JSpinner> {
implements EntityComponentFactory<Integer, JSpinner> {

@Override
public ComponentValue<Integer, JSpinner> componentValue(Attribute<Integer> attribute,
SwingEntityEditModel editModel,
public ComponentValue<Integer, JSpinner> componentValue(SwingEntityEditModel editModel,
Integer initialValue) {
EntityComponents inputComponents = entityComponents(editModel.entityDefinition());

return inputComponents.integerSpinner(attribute)
return inputComponents.integerSpinner(Track.RATING)
.initialValue(initialValue)
.buildValue();
}
}

private static final class MinutesSecondsComponentFactory
extends DefaultEntityComponentFactory<Integer, Attribute<Integer>, MinutesSecondsPanel> {
implements EntityComponentFactory<Integer, MinutesSecondsPanel> {

private final boolean horizontal;
private final String caption;

private MinutesSecondsComponentFactory(boolean horizontal, String caption) {
this.horizontal = horizontal;
this.caption = caption;
private MinutesSecondsComponentFactory(TrackTableModel tableModel) {
this.caption = tableModel.entityDefinition().attributes().definition(Track.MINUTES_SECONDS).caption();
}

@Override
Expand All @@ -118,10 +114,9 @@ public Optional<String> caption() {
}

@Override
public ComponentValue<Integer, MinutesSecondsPanel> componentValue(Attribute<Integer> attribute,
SwingEntityEditModel editModel,
public ComponentValue<Integer, MinutesSecondsPanel> componentValue(SwingEntityEditModel editModel,
Integer initialValue) {
MinutesSecondsPanelValue minutesSecondsPanelValue = new MinutesSecondsPanelValue(horizontal);
MinutesSecondsPanelValue minutesSecondsPanelValue = new MinutesSecondsPanelValue(false);
minutesSecondsPanelValue.set(initialValue);

return minutesSecondsPanelValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public interface EditAttributeDialogBuilder<T> extends DialogBuilder<EditAttribu
* @param componentFactory the component factory, if null then the default is used
* @return this builder
*/
EditAttributeDialogBuilder<T> componentFactory(EntityComponentFactory<T, Attribute<T>, ?> componentFactory);
EditAttributeDialogBuilder<T> componentFactory(EntityComponentFactory<T, ?> componentFactory);

/**
* @param onValidationException called on validation exception
Expand Down Expand Up @@ -251,23 +251,22 @@ private static final class DefaultEditAttributeDialogBuilder<T> extends Abstract

private static final Logger LOG = LoggerFactory.getLogger(DefaultEditAttributeDialogBuilder.class);

private static final EntityComponentFactory<?, ?, ?> DEFAULT_COMPONENT_FACTORY = new EditEntityComponentFactory<>();

private final SwingEntityEditModel editModel;
private final Attribute<T> attribute;

private EntityComponentFactory<T, Attribute<T>, ?> componentFactory = (EntityComponentFactory<T, Attribute<T>, ?>) DEFAULT_COMPONENT_FACTORY;
private EntityComponentFactory<T, ?> componentFactory;
private Consumer<ValidationException> onValidationException = new DefaultValidationExceptionHandler();
private Consumer<Exception> onException = new DefaultExceptionHandler();

private DefaultEditAttributeDialogBuilder(SwingEntityEditModel editModel, Attribute<T> attribute) {
this.editModel = requireNonNull(editModel);
this.attribute = requireNonNull(attribute);
this.componentFactory = new EditEntityComponentFactory<>(attribute);
}

@Override
public EditAttributeDialogBuilder<T> componentFactory(EntityComponentFactory<T, Attribute<T>, ?> componentFactory) {
this.componentFactory = componentFactory == null ? (EntityComponentFactory<T, Attribute<T>, ?>) DEFAULT_COMPONENT_FACTORY : componentFactory;
public EditAttributeDialogBuilder<T> componentFactory(EntityComponentFactory<T, ?> componentFactory) {
this.componentFactory = componentFactory == null ? new EditEntityComponentFactory<>(attribute) : componentFactory;
return this;
}

Expand Down Expand Up @@ -306,7 +305,7 @@ public void edit(Collection<Entity> entities) {
.map(entity -> entity.get(attribute))
.collect(toSet());
T initialValue = values.size() == 1 ? values.iterator().next() : null;
ComponentValue<T, ?> componentValue = componentFactory.componentValue(attribute, editModel, initialValue);
ComponentValue<T, ?> componentValue = componentFactory.componentValue(editModel, initialValue);
InputValidator<T> validator = new InputValidator<>(entityDefinition, attribute, componentValue);
inputDialog(componentValue)
.owner(owner)
Expand Down Expand Up @@ -422,24 +421,28 @@ public boolean test(T value) {
}
}

private static final class EditEntityComponentFactory<T, A extends Attribute<T>, C extends JComponent> extends DefaultEntityComponentFactory<T, A, C> {
private static final class EditEntityComponentFactory<T, C extends JComponent> extends DefaultEntityComponentFactory<T, C> {

private static final int TEXT_INPUT_PANEL_COLUMNS = 20;

private EditEntityComponentFactory(Attribute<T> attribute) {
super(attribute);
}

@Override
public ComponentValue<T, C> componentValue(A attribute, SwingEntityEditModel editModel, T initialValue) {
public ComponentValue<T, C> componentValue(SwingEntityEditModel editModel, T initialValue) {
AttributeDefinition<T> attributeDefinition = editModel.entityDefinition()
.attributes().definition(attribute);
if (attributeDefinition.items().isEmpty() && attribute.type().isString()) {
.attributes().definition(attribute());
if (attributeDefinition.items().isEmpty() && attribute().type().isString()) {
//special handling for non-item based String attributes, text field panel instead of a text field
return (ComponentValue<T, C>) entityComponents(editModel.entityDefinition())
.textFieldPanel((Attribute<String>) attribute)
.textFieldPanel((Attribute<String>) attribute())
.initialValue((String) initialValue)
.columns(TEXT_INPUT_PANEL_COLUMNS)
.buildValue();
}

return super.componentValue(attribute, editModel, initialValue);
return super.componentValue(editModel, initialValue);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
public class EntityTableCellEditorFactory implements FilterTableCellEditorFactory<Attribute<?>> {

private final SwingEntityEditModel editModel;
private final EntityComponentFactory<Object, Attribute<Object>, JComponent> componentFactory = new DefaultEntityComponentFactory<>();

/**
* @param editModel the edit model
Expand All @@ -55,8 +54,11 @@ public Optional<TableCellEditor> tableCellEditor(FilterTableColumn<Attribute<?>>
return Optional.empty();
}

EntityComponentFactory<Object, JComponent> componentFactory =
new DefaultEntityComponentFactory<>((Attribute<Object>) column.identifier());

return Optional.of(filterTableCellEditor(() ->
componentFactory.componentValue((Attribute<Object>) column.identifier(), editModel, null)));
componentFactory.componentValue(editModel, null)));
}

private boolean nonUpdatableForeignKey(Attribute<?> attribute) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,7 @@ protected void onValidationException(ValidationException exception) {
protected <T> EntityDialogs.EditAttributeDialogBuilder<T> editDialogBuilder(Attribute<T> attribute) {
return EntityDialogs.editAttributeDialog(tableModel.editModel(), attribute)
.owner(this)
.componentFactory((EntityComponentFactory<T, Attribute<T>, ?>) configuration.editComponentFactories.get(attribute));
.componentFactory((EntityComponentFactory<T, ?>) configuration.editComponentFactories.get(attribute));
}

/**
Expand Down Expand Up @@ -2114,7 +2114,7 @@ public static final class Config {
private final EntityTablePanel tablePanel;
private final EntityDefinition entityDefinition;
private final ValueSet<Attribute<?>> editable;
private final Map<Attribute<?>, EntityComponentFactory<?, ?, ?>> editComponentFactories;
private final Map<Attribute<?>, EntityComponentFactory<?, ?>> editComponentFactories;
private final FilterTable.Builder<Entity, Attribute<?>> tableBuilder;

private TableConditionPanel.Factory<Attribute<?>> tableConditionPanelFactory = new DefaultTableConditionPanelFactory();
Expand Down Expand Up @@ -2415,7 +2415,7 @@ public Config deleteConfirmer(Confirmer deleteConfirmer) {
* @return this Config instance
*/
public <T, A extends Attribute<T>, C extends JComponent> Config editComponentFactory(A attribute,
EntityComponentFactory<T, A, C> componentFactory) {
EntityComponentFactory<T, C> componentFactory) {
entityDefinition.attributes().definition(attribute);
editComponentFactories.put(attribute, requireNonNull(componentFactory));
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,22 @@

/**
* A default {@link EntityComponentFactory} implementation.
* @param <T> the attribute type
* @param <C> the component type
*/
public class DefaultEntityComponentFactory<T, A extends Attribute<T>, C extends JComponent> implements EntityComponentFactory<T, A, C> {
public class DefaultEntityComponentFactory<T, C extends JComponent> implements EntityComponentFactory<T, C> {

private final Attribute<T> attribute;

/**
* @param attribute the attribute for which this factory creates a {@link ComponentValue}
*/
public DefaultEntityComponentFactory(Attribute<T> attribute) {
this.attribute = requireNonNull(attribute);
}

@Override
public ComponentValue<T, C> componentValue(A attribute, SwingEntityEditModel editModel, T initialValue) {
requireNonNull(attribute, "attribute");
public ComponentValue<T, C> componentValue(SwingEntityEditModel editModel, T initialValue) {
requireNonNull(editModel, "editModel");
EntityComponents inputComponents = entityComponents(editModel.entityDefinition());
if (attribute instanceof ForeignKey) {
Expand All @@ -58,6 +68,13 @@ public ComponentValue<T, C> componentValue(A attribute, SwingEntityEditModel edi
.buildValue();
}

/**
* @return the attribute
*/
protected final Attribute<T> attribute() {
return attribute;
}

private ComponentValue<T, C> createForeignKeyComponentValue(ForeignKey foreignKey, SwingEntityEditModel editModel,
Entity initialValue, EntityComponents inputComponents) {
if (editModel.entities().definition(foreignKey.referencedType()).smallDataset()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package is.codion.swing.framework.ui.component;

import is.codion.framework.domain.entity.attribute.Attribute;
import is.codion.swing.common.ui.component.value.ComponentValue;
import is.codion.swing.framework.model.SwingEntityEditModel;

Expand All @@ -28,21 +27,17 @@
/**
* A factory for {@link ComponentValue} instances.
* @param <T> the value type
* @param <A> the attribute type
* @param <C> the component type
*/
public interface EntityComponentFactory<T, A extends Attribute<T>, C extends JComponent> {
public interface EntityComponentFactory<T, C extends JComponent> {

/**
* Provides an input {@link ComponentValue} for editing a single attribute value
* for one or more entities, override to supply a specific {@link ComponentValue}
* implementations for attributes.
* @param attribute the attribute for which to create the {@link ComponentValue}
* Provides an input {@link ComponentValue} for editing a single attribute value for one or more entities.
* @param editModel the edit model used to create foreign key input models
* @param initialValue the initial value to display
* @return a new {@link ComponentValue} instance handling input for {@code attribute}
*/
ComponentValue<T, C> componentValue(A attribute, SwingEntityEditModel editModel, T initialValue);
ComponentValue<T, C> componentValue(SwingEntityEditModel editModel, T initialValue);

/**
* Provides a way to override the default attribute caption, when presenting the component to the user.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
import is.codion.common.user.User;
import is.codion.framework.db.EntityConnectionProvider;
import is.codion.framework.db.local.LocalEntityConnectionProvider;
import is.codion.framework.domain.entity.Entity;
import is.codion.framework.domain.entity.attribute.Attribute;
import is.codion.framework.domain.entity.attribute.ForeignKey;
import is.codion.swing.common.ui.component.text.NumberField;
import is.codion.swing.framework.model.SwingEntityEditModel;
import is.codion.swing.framework.ui.TestDomain;
import is.codion.swing.framework.ui.TestDomain.Detail;
Expand All @@ -45,12 +41,10 @@ public final class DefaultEntityComponentFactoryTest {

@Test
void test() {
EntityComponentFactory<Entity, ForeignKey, EntitySearchField> foreignKeyComponentFactory = new DefaultEntityComponentFactory<>();
foreignKeyComponentFactory.componentValue(Detail.MASTER_FK, editModel, null);
foreignKeyComponentFactory.componentValue(Detail.DETAIL_FK, editModel, null);
new DefaultEntityComponentFactory<>(Detail.MASTER_FK).componentValue(editModel, null);
new DefaultEntityComponentFactory<>(Detail.DETAIL_FK).componentValue(editModel, null);

EntityComponentFactory<Integer, Attribute<Integer>, NumberField<Integer>> integerComponentFactory = new DefaultEntityComponentFactory<>();
integerComponentFactory.componentValue(Detail.INT, editModel, null);
integerComponentFactory.componentValue(Detail.INT_DERIVED, editModel, null);
new DefaultEntityComponentFactory<>(Detail.INT).componentValue(editModel, null);
new DefaultEntityComponentFactory<>(Detail.INT_DERIVED).componentValue(editModel, null);
}
}

0 comments on commit 97abcb4

Please sign in to comment.