Added primitive foreign key stuff.

This commit is contained in:
Andrew Lalis 2021-02-07 21:37:07 +01:00
parent f47b2449d3
commit db140733ae
7 changed files with 92 additions and 12 deletions

View File

@ -1,10 +1,7 @@
package nl.andrewlalis.erme.control.actions.edits; package nl.andrewlalis.erme.control.actions.edits;
import lombok.Setter; import lombok.Setter;
import nl.andrewlalis.erme.model.Attribute; import nl.andrewlalis.erme.model.*;
import nl.andrewlalis.erme.model.AttributeType;
import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@ -49,6 +46,7 @@ public class AddAttributeAction extends AbstractAction {
Relation r = selectedRelations.get(0); Relation r = selectedRelations.get(0);
Component c = (Component) e.getSource(); Component c = (Component) e.getSource();
String name = JOptionPane.showInputDialog(c, "Enter the name of the attribute.", "Attribute Name", JOptionPane.PLAIN_MESSAGE); String name = JOptionPane.showInputDialog(c, "Enter the name of the attribute.", "Attribute Name", JOptionPane.PLAIN_MESSAGE);
if (name == null) return;
Integer index = (Integer) JOptionPane.showInputDialog( Integer index = (Integer) JOptionPane.showInputDialog(
c, c,
"Select the index to insert this attribute at.", "Select the index to insert this attribute at.",
@ -67,7 +65,38 @@ public class AddAttributeAction extends AbstractAction {
AttributeType.values(), AttributeType.values(),
AttributeType.PLAIN AttributeType.PLAIN
); );
if (name != null && index != null && type != null) { if (type.equals(AttributeType.FOREIGN_KEY)) {
if (this.model.getRelations().size() < 2) {
JOptionPane.showMessageDialog(c, "There should be at least 2 relations present in the model.", "Not Enough Relations", JOptionPane.WARNING_MESSAGE);
return;
}
Relation fkRelation = (Relation) JOptionPane.showInputDialog(
c,
"Select the relation that this foreign key references.",
"Foreign Key Relation Reference",
JOptionPane.PLAIN_MESSAGE,
null,
this.model.getRelations().toArray(new Relation[0]),
this.model.getRelations().stream().findFirst().orElse(null)
);
List<Attribute> eligibleAttributes = fkRelation.getReferencableAttributes();
if (eligibleAttributes.isEmpty()) {
JOptionPane.showMessageDialog(c, "There are no referencable attributes in the selected relation.", "No Referencable Attributes", JOptionPane.WARNING_MESSAGE);
return;
}
Attribute fkAttribute = (Attribute) JOptionPane.showInputDialog(
c,
"Select the attribute that this foreign key references.",
"Foreign Key Attribute Reference",
JOptionPane.PLAIN_MESSAGE,
null,
eligibleAttributes.toArray(new Attribute[0]),
eligibleAttributes.get(0)
);
if (fkAttribute != null) {
r.addAttribute(new ForeignKeyAttribute(r, name, fkAttribute));
}
} else {
r.addAttribute(new Attribute(r, type, name), index); r.addAttribute(new Attribute(r, type, name), index);
} }
} }

View File

@ -1,6 +1,7 @@
package nl.andrewlalis.erme.model; package nl.andrewlalis.erme.model;
import lombok.Getter; import lombok.Getter;
import nl.andrewlalis.erme.view.view_models.AttributeViewModel;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.util.Objects;
@ -14,6 +15,8 @@ public class Attribute implements Serializable {
private AttributeType type; private AttributeType type;
private String name; private String name;
private AttributeViewModel viewModel;
public Attribute(Relation relation, AttributeType type, String name) { public Attribute(Relation relation, AttributeType type, String name) {
this.relation = relation; this.relation = relation;
this.type = type; this.type = type;
@ -30,6 +33,13 @@ public class Attribute implements Serializable {
this.relation.getModel().fireChangedEvent(); this.relation.getModel().fireChangedEvent();
} }
public AttributeViewModel getViewModel() {
if (this.viewModel == null) {
this.viewModel = new AttributeViewModel(this);
}
return this.viewModel;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -0,0 +1,25 @@
package nl.andrewlalis.erme.model;
import lombok.Getter;
@Getter
public class ForeignKeyAttribute extends Attribute {
private Attribute reference;
public ForeignKeyAttribute(Relation relation, String name, Attribute reference) {
super(relation, AttributeType.FOREIGN_KEY, name);
this.reference = reference;
}
public ForeignKeyAttribute(Relation relation, String name, String referencedRelationName, String referencedAttributeName) {
this(relation, name, relation.getModel().findAttribute(referencedRelationName, referencedAttributeName));
if (this.getReference() == null) {
throw new IllegalArgumentException("Unknown attribute name.");
}
}
public void setReference(Attribute reference) {
this.reference = reference;
this.getRelation().getModel().fireChangedEvent();
}
}

View File

@ -40,6 +40,18 @@ public class MappingModel implements Serializable {
return this.relations.stream().filter(Relation::isSelected).collect(Collectors.toList()); return this.relations.stream().filter(Relation::isSelected).collect(Collectors.toList());
} }
public Attribute findAttribute(String relationName, String attributeName) {
for (Relation r : this.getRelations()) {
if (!r.getName().equals(relationName)) continue;
for (Attribute a : r.getAttributes()) {
if (a.getName().equals(attributeName)) {
return a;
}
}
}
return null;
}
public void addChangeListener(ModelChangeListener listener) { public void addChangeListener(ModelChangeListener listener) {
if (this.changeListeners == null) { if (this.changeListeners == null) {
this.changeListeners = new HashSet<>(); this.changeListeners = new HashSet<>();

View File

@ -8,6 +8,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* Represents a single "relation" or table in the diagram. * Represents a single "relation" or table in the diagram.
@ -64,6 +65,12 @@ public class Relation implements Serializable {
return this.viewModel; return this.viewModel;
} }
public List<Attribute> getReferencableAttributes() {
return this.attributes.stream()
.filter(a -> a.getType() == AttributeType.ID_KEY || a.getType() == AttributeType.PARTIAL_ID_KEY)
.collect(Collectors.toList());
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -1,9 +1,6 @@
package nl.andrewlalis.erme.view; package nl.andrewlalis.erme.view;
import nl.andrewlalis.erme.model.Attribute; import nl.andrewlalis.erme.model.*;
import nl.andrewlalis.erme.model.AttributeType;
import nl.andrewlalis.erme.model.MappingModel;
import nl.andrewlalis.erme.model.Relation;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@ -24,7 +21,7 @@ public class EditorFrame extends JFrame {
model.addRelation(usersRelation); model.addRelation(usersRelation);
Relation tokensRelation = new Relation(model, new Point(50, 120), "Tokens"); Relation tokensRelation = new Relation(model, new Point(50, 120), "Tokens");
tokensRelation.addAttribute(new Attribute(tokensRelation, AttributeType.ID_KEY, "tokenCode")); tokensRelation.addAttribute(new Attribute(tokensRelation, AttributeType.ID_KEY, "tokenCode"));
tokensRelation.addAttribute(new Attribute(tokensRelation, AttributeType.FOREIGN_KEY, "username")); tokensRelation.addAttribute(new ForeignKeyAttribute(tokensRelation,"username", "Users", "username"));
tokensRelation.addAttribute(new Attribute(tokensRelation, AttributeType.PLAIN, "expirationDate")); tokensRelation.addAttribute(new Attribute(tokensRelation, AttributeType.PLAIN, "expirationDate"));
model.addRelation(tokensRelation); model.addRelation(tokensRelation);

View File

@ -25,7 +25,7 @@ public class RelationViewModel implements ViewModel {
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawString(as.getIterator(), bounds.x + PADDING_X, bounds.y + this.getNameBounds(g).height - PADDING_Y); g.drawString(as.getIterator(), bounds.x + PADDING_X, bounds.y + this.getNameBounds(g).height - PADDING_Y);
for (Attribute a : this.relation.getAttributes()) { for (Attribute a : this.relation.getAttributes()) {
new AttributeViewModel(a).draw(g); a.getViewModel().draw(g);
} }
if (this.relation.isSelected()) { if (this.relation.isSelected()) {
g.setColor(Color.BLUE); g.setColor(Color.BLUE);
@ -40,7 +40,7 @@ public class RelationViewModel implements ViewModel {
int totalAttributeWidth = 0; int totalAttributeWidth = 0;
int maxAttributeHeight = 0; int maxAttributeHeight = 0;
for (Attribute a : this.relation.getAttributes()) { for (Attribute a : this.relation.getAttributes()) {
Rectangle attributeBounds = new AttributeViewModel(a).getBounds(g); Rectangle attributeBounds = a.getViewModel().getBounds(g);
totalAttributeWidth += attributeBounds.width; totalAttributeWidth += attributeBounds.width;
maxAttributeHeight = Math.max(maxAttributeHeight, attributeBounds.height); maxAttributeHeight = Math.max(maxAttributeHeight, attributeBounds.height);
} }