use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class JDBCUpdateMonitor method insert.
/**
* Determines if insertion into a given table requires special handling due
* to constraints it may be in. As of now, special cases that may result
* from being in multiple constraints are not supported.
*
* @param table
* The table into which we wish to insert data
* @return Success of the insertion
*/
@Override
public boolean insert(final EntityNode table) {
final DialogOptions dOpts = getDialogOptions(table);
final String lineSep = EasikTools.systemLineSeparator();
// a set of column-value pairs of which we wish to force a specific
// value, leaving the user out
final Set<ColumnEntry> forced = new HashSet<>(10);
// contstraint. Tighten up?
for (final ModelConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> c : table.getConstraints()) {
if (c instanceof SumConstraint) {
// of its foreign key, so remove it from the dialog's selection
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> sp : c.getPaths()) {
if (sp.getDomain() == table) {
// we force the value 0 to avoid out driver to kick back
// an error for having a null fKey
final String columnName = cn.tableFK(sp.getFirstEdge());
dOpts.fKeys.remove(columnName);
forced.add(new ColumnEntry(columnName, "0", new Int()));
break;
}
}
}
if (c instanceof CommutativeDiagram) {
// commute
if (c.getPaths().get(0).getDomain() == table) {
JOptionPane.showMessageDialog(null, "Be sure that the following paths commute:" + lineSep + EasikTools.join(lineSep, c.getPaths()), "Commutative diagram", JOptionPane.INFORMATION_MESSAGE);
try {
return promptAndInsert(table, dOpts, forced);
} catch (SQLException e) {
/*
* if(e instanceof com.mysql.jdbc.exceptions.jdbc4.
* MySQLIntegrityConstraintViolationException){
* //injective property violated
* JOptionPane.showMessageDialog(null, e.getMessage(),
* "Injective property violation",
* JOptionPane.ERROR_MESSAGE); }else{
*/
JOptionPane.showMessageDialog(null, "Not all of the following paths commute -- insert aborted!" + lineSep + EasikTools.join(lineSep, c.getPaths()), "Commutative diagram failure", JOptionPane.ERROR_MESSAGE);
// }
}
}
}
if (c instanceof PullbackConstraint) {
// happens, we want to let the user update the new record
if (((PullbackConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>) c).getTarget() != table) {
final EntityNode pullback = ((PullbackConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>) c).getSource();
try {
// get row count pre-insert
ResultSet result = dbd.executeQuery("SELECT COUNT(*) FROM " + pullback.getName() + " X");
result.next();
final int preRowCount = result.getInt(1);
if (!promptAndInsert(table, dOpts)) {
return false;
}
// get row count post-insert
result = dbd.executeQuery("SELECT COUNT(*) FROM " + pullback.getName() + " X");
result.next();
final int postRowCount = result.getInt(1);
// new row (the one with the highest primary ID)
if (postRowCount > preRowCount) {
result = dbd.executeQuery("SELECT MAX(" + cn.tablePK(pullback) + ") FROM " + pullback.getName() + " X");
result.next();
final int pk = result.getInt(1);
if (JOptionPane.showConfirmDialog(null, "New record in pullback table '" + pullback.getName() + "'. Enter column data?", "Insert column data?", JOptionPane.YES_NO_OPTION) == 0) {
updateRow(pullback, pk);
}
}
return true;
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "Could not execute update. MYSQL Error output:\n" + e.getMessage());
}
}
}
if (c instanceof ProductConstraint) {
// inserting into the product.
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> sp : c.getPaths()) {
if (sp.getCoDomain() == table) {
final EntityNode product = sp.getDomain();
try {
if (!promptAndInsert(table, dOpts)) {
return false;
}
// get the new records from the product. They are
// any record who's fk to our INSERT factor matches
// the primary id of the last insert
ResultSet result = dbd.executeQuery("SELECT MAX(" + cn.tablePK(table) + ") FROM " + table.getName() + " X");
result.next();
final int newPK = result.getInt(1);
result = dbd.executeQuery("SELECT * FROM " + product.getName() + " WHERE " + cn.tableFK(sp.getFirstEdge()) + " = " + newPK);
// get count of new rows as result of INSERT
result.last();
final int newRows = result.getRow();
result.beforeFirst();
if ((newRows > 0) && (JOptionPane.showConfirmDialog(null, newRows + " new rows in product table '" + product.getName() + "'. Insert column data?", "Insert column data?", JOptionPane.YES_NO_OPTION) == 0)) {
while (result.next()) {
updateRow(product, result.getInt(1));
}
}
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
}
return true;
}
}
}
if (c instanceof LimitConstraint) {
// TRIANGLES TODO CF2012 Incomplete
}
}
try {
return promptAndInsert(table, dOpts, forced);
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "Could not execute update. MYSQL Error output:\n" + e.getMessage());
System.err.println(e.getMessage());
return false;
}
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class JDBCUpdateMonitor method updateRow.
/**
* Pops up a row entry dialog for the given table. The default field values
* will be the values stored in the row of the table who's primary ID
* matches the one given. Some cases call for use to restrict the update of
* foreign keys. Those cases are: a) A pullback b) The summands of a sum
* constrain c) The product of a product constraint If the table is in a
* constraint and the user wishes to break it the update is aborted leaving
* the old values in the record. Note: There are currently no checks to
* ensure that pk matches a record in our table.
*
* @param table
* The EntityNode representing the table we wish to update.
* @param pk
* The primary ID of the row whos data will be used to set
* defaults for our row entry dialog.
* @return The Success of the update.
*/
@Override
public boolean updateRow(final EntityNode table, final int pk) {
final DialogOptions dOpts = getDialogOptions(table);
try {
// Remove option to update foreign keys restricted by constraints
for (final ModelConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> c : table.getConstraints()) {
for (final SketchEdge se : table.getOutgoingEdges()) {
if (c.hasEdge(se)) {
dOpts.fKeys.remove(cn.tableFK(se));
}
}
}
// Display dialog for user with defaults as old record values
final RowEntryDialog red = new RowEntryDialog(_theSketch.getFrame(), "Update " + table.getName() + ": " + cn.tablePK(table) + " = " + pk, dOpts.attToType, dOpts.fKeys, DatabaseUtil.getRecord(table, pk));
if (red.isAccepted()) {
final Set<ColumnEntry> input = new LinkedHashSet<>(red.getInput());
// if we do not have any new input, no need to execute an update
if (input.isEmpty()) {
return true;
}
final StringBuilder sb = new StringBuilder("UPDATE " + table.getName() + " SET ");
for (final ColumnEntry ce : input) {
sb.append(dbd.quoteId(ce.getColumnName())).append('=' + "?,");
}
// remove last comma
sb.delete(sb.length() - 1, sb.length());
sb.append(" WHERE ").append(cn.tablePK(table)).append('=').append(pk);
dbd.executePreparedUpdate(sb.toString(), input);
return true;
}
return false;
} catch (SQLException e) {
JOptionPane.showMessageDialog(table.getMModel().getFrame(), "Could not update record: " + e.getMessage());
return false;
}
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class SketchHandler method startElement.
/**
* Overloaded method that is called any time the start of an element is
* found
*
* @param namespace
* @see org.xml.sax.helpers.DefaultHandler
* @param localName
* @see org.xml.sax.helpers.DefaultHandler
* @param qName
* @see org.xml.sax.helpers.DefaultHandler
* @param atts
* @see org.xml.sax.helpers.DefaultHandler
*/
@Override
public void startElement(String namespace, String localName, String qName, Attributes atts) {
_currNode = qName;
if (qName.equals("entity")) {
String name = atts.getValue("name");
int x = Integer.parseInt(atts.getValue("x"));
int y = Integer.parseInt(atts.getValue("y"));
if (_entityNodes.containsKey(name)) {
System.err.println("Duplicate nodes found in XML");
return;
}
_newNode = new EntityNode(name, x, y, _theFrame.getMModel());
_entityNodes.put(name, _newNode);
_curNodeAtts = new LinkedHashMap<>();
} else if (qName.equals("attribute")) {
EasikType type;
// attributeType was created by old Easik versions, and is the SQL
// type signature
// (such as "VARCHAR(255)"). Easik now uses attributeTypeClass,
// containing the
// class name, and any number of extra attributes which
// EasikType.newType() uses to
// recreate the appropriate EasikType object.
String typesig = atts.getValue("attributeType");
if (typesig != null) {
type = EasikType.typeFromSignature(typesig);
} else {
String typename = atts.getValue("attributeTypeClass");
try {
type = EasikType.newType(typename, attributeMap(atts, "attributeType", "attributeTypeClass", "name"));
} catch (ClassNotFoundException e) {
System.err.println("Invalid type found in XML: '" + typename + "' (" + e.getMessage() + ")");
return;
}
}
EntityAttribute<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> myAtt = new EntityAttribute<>(atts.getValue("name"), type, _newNode);
_curNodeAtts.put(atts.getValue("name"), myAtt);
_newNode.addEntityAttribute(myAtt);
} else if (qName.equals("uniqueKey")) {
// New EASIK has noderef, telling us what we refer to. In old easik,
// uniqueKey is under
// the node itself (but as a result, cannot contain edge
// references).
String noderef = atts.getValue("noderef");
if (noderef != null) {
// Restore _newNode and _curNodeAtts, since we're going to need
// them:
_newNode = _entityNodes.get(noderef);
_curNodeAtts = new LinkedHashMap<>();
for (EntityAttribute<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> att : _newNode.getEntityAttributes()) {
_curNodeAtts.put(att.getName(), att);
}
}
_curUniqueKeyName = atts.getValue("name");
_curUniqueKeyElems = new LinkedList<>();
} else if (qName.equals("attref")) {
_curUniqueKeyElems.add(_curNodeAtts.get(atts.getValue("name")));
} else if (qName.equals("edgekeyref")) {
SketchEdge e = _edges.get(atts.getValue("id"));
if (e instanceof UniqueIndexable) {
_curUniqueKeyElems.add((UniqueIndexable) e);
} else {
System.err.println("Encountered an non-unique-indexable <edgekeyref> " + e);
}
} else if (qName.equals("edge")) {
SketchEdge newEdge;
String edgeType = atts.getValue("type");
// injective is an old EASIK attribute:
String injective = atts.getValue("injective");
if (injective != null) {
edgeType = atts.getValue("injective").equals("true") ? "injective" : "normal";
}
EntityNode source = _entityNodes.get(atts.getValue("source"));
EntityNode target = _entityNodes.get(atts.getValue("target"));
String id = atts.getValue("id");
String cascadeAtt = atts.getValue("cascade");
if (cascadeAtt == null) {
// This is from an export before Easik had per-edge cascading
// (in other words, before r583)
// We use the global preferences for cascading
String key = "sql_cascade", def = "restrict";
if (edgeType.equals("partial")) {
key = "sql_cascade_partial";
def = "set_null";
}
cascadeAtt = Easik.getInstance().getSettings().getProperty(key, def);
}
SketchEdge.Cascade cascade = cascadeAtt.equals("set_null") ? SketchEdge.Cascade.SET_NULL : cascadeAtt.equals("cascade") ? SketchEdge.Cascade.CASCADE : SketchEdge.Cascade.RESTRICT;
if (edgeType.equals("injective")) {
newEdge = new InjectiveEdge(source, target, id, cascade);
} else if (edgeType.equals("partial")) {
newEdge = new PartialEdge(source, target, id, cascade);
} else {
newEdge = new NormalEdge(source, target, id, cascade);
}
_edges.put(id, newEdge);
} else if (qName.equals("path")) {
_curPath = new LinkedList<>();
_curPathId = atts.getValue("id");
_curDomain = _entityNodes.get(atts.getValue("domain"));
} else if (qName.equals("edgeref")) {
_curPath.add(_edges.get(atts.getValue("id")));
} else if (// TRIANGLES
qName.equals("sumconstraint") || qName.equals("pullbackconstraint") || qName.equals("productconstraint") || qName.equals("commutativediagram") || qName.equals("equalizerconstraint") || qName.equals("limitconstraint")) // CF2012
{
_curConstraintX = Integer.parseInt(atts.getValue("x"));
_curConstraintY = Integer.parseInt(atts.getValue("y"));
_curConstraintVisible = atts.getValue("isVisible").equals("true");
_curConstraintPaths = new ArrayList<>();
_allConstraintsVisible = atts.getValue("isVisible").equals("true");
} else if (qName.equals("pathref")) {
// This is for compatibility with old versions of Easik (pre-2.0);
// new versions
// put <path> elements directly inside the various constraint
// elements.
_curConstraintPaths.add(_allPaths.get(atts.getValue("id")));
} else if (qName.equals("connectionParam")) {
_connParams.put(atts.getValue("name"), atts.getValue("value"));
} else if (qName.equals("synchronized")) {
// The existance of this tag tells us the sketch is synchronized
_curSketchSync = true;
}
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class EntityNode method getShadowEdges.
/**
* This method returns the edges that will be "shadowed" in this entity for
* allowing various types of constraints. The problem arises when we have
* something like: A -> B -> C, where A is the summand of B, but B has
* to be specified. In this case, the B to C edge will be returned as a
* "shadow" edge. We handle this for other constraint types, too. For a
* good, working, technical example, see the shadowEdges.easik sample
* sketch.
*
* @return a set of edges that will be shadowed by this entity node.
*
* Removing shadow edges completely. Started by Sarah Van der Laan
* continued by Federico Mora because a partial solution is worse
* than all or nothing
*
* public LinkedHashSet<SketchEdge> getShadowEdges() { return
* getShadowEdges(new LinkedHashSet<EntityNode>(5), new
* LinkedHashSet<SketchEdge>(5)); }
*/
// Package-only implementation of the above that breaks recursion by
// ignoring
// shadowed nodes that we already know about.
/**
* @param ignore
* @param constraintEdges
*
* @return
*/
LinkedHashSet<SketchEdge> getShadowEdges(final Collection<EntityNode> ignore, final LinkedHashSet<SketchEdge> constraintEdges) {
// These are the other entity node that we (potentially) need to shadow:
final Collection<EntityNode> shadow = new LinkedHashSet<>(10);
CONSTRAINT: for (final ModelConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> c : getMModel().getConstraints().values()) {
if (c instanceof SumConstraint) {
final SumConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> s = (SumConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>) c;
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> path : s.getPaths()) {
// for this entity, of course):
if (path.getDomain() == this) {
shadow.addAll(path.getEntities());
constraintEdges.addAll(path.getEdges());
continue CONSTRAINT;
}
}
} else if (c instanceof ProductConstraint) {
final ProductConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> p = (ProductConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>) c;
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> path : p.getPaths()) {
// codomains), along each product path
if (path.getCoDomain() == this) {
for (final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> prodPath : p.getPaths()) {
// But we ignore all of the product path edges,
// since they will be automatically generated:
constraintEdges.addAll(prodPath.getEdges());
final Deque<EntityNode> pathNodes = new LinkedList<>();
pathNodes.addAll(prodPath.getEntities());
pathNodes.removeLast();
shadow.addAll(pathNodes);
}
continue CONSTRAINT;
}
}
} else if (c instanceof EqualizerConstraint) {
final EqualizerConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> e = (EqualizerConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>) c;
// injective *edge* doesn't cause that problem).
if (e.getSourceEntity() == this) {
final ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> projection = e.getProjection();
shadow.addAll(projection.getEntities());
// Ignore the projection edge itself:
constraintEdges.addAll(projection.getEdges());
continue CONSTRAINT;
}
} else if (c instanceof PullbackConstraint) {
final PullbackConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> pb = (PullbackConstraint<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>) c;
// WPBEDIT CF2012
for (int i = 0; i < pb.getWidth(); i++) {
ModelPath<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge> proj = pb.getProjectionPath(i);
if (this == proj.getCoDomain()) {
for (int j = 0; j < pb.getWidth(); j++) {
proj = pb.getProjectionPath(j);
Deque<EntityNode> projNodes = new LinkedList<>(proj.getEntities());
projNodes.removeLast();
shadow.addAll(projNodes);
constraintEdges.addAll(proj.getEdges());
}
continue CONSTRAINT;
}
}
} else if (c instanceof LimitConstraint) {
// TRIANGLES TODO CF2012 incomplete
}
}
final LinkedHashSet<SketchEdge> shadowEdges = new LinkedHashSet<>(20);
// All of the ignore entities, plus everything we just found should be
// ignored by any recursion:
final Collection<EntityNode> toIgnore = new LinkedHashSet<>(3);
toIgnore.add(this);
toIgnore.addAll(ignore);
toIgnore.addAll(shadow);
for (final EntityNode node : shadow) {
// it:
if ((node == this) || ignore.contains(node)) {
continue;
}
// Otherwise, shadow its non-partial edges, and all of its shadow
// edges:
shadowEdges.addAll(node.getShadowEdges(toIgnore, constraintEdges));
shadowEdges.addAll(node.getNonPartialEdges());
// Remove edges already
shadowEdges.removeAll(constraintEdges);
// involved in the sum
}
return shadowEdges;
}
use of easik.sketch.util.graph.SketchGraphModel in project fql by CategoricalData.
the class Sketch method initialiseModel.
/**
* When we initialise the sketch, we flush out all the data concerning the
* sketch itself.
*
* This methods serves as a "new sketch" function.
*/
@Override
public void initialiseModel() {
clearSelection();
model = new SketchGraphModel(this);
final GraphLayoutCache glc = new GraphLayoutCache(model, new ModelViewFactory<SketchFrame, SketchGraphModel, Sketch, EntityNode, SketchEdge>());
setModel(model);
setGraphLayoutCache(glc);
_nodes = new LinkedHashMap<>();
_edges = new LinkedHashMap<>();
if (_Frame.getInfoTreeUI() != null) {
// Wipe
_Frame.setInfoTreeUI(new ModelInfoTreeUI<>(_Frame));
// Tree
_Frame.getInfoTreeUI().refreshTree();
}
_docInfo.reset();
_views = new HashMap<>();
_connParams = new HashMap<>();
model.discardUndo();
}
Aggregations