X-Git-Url: https://git.auder.net/?a=blobdiff_plain;ds=inline;f=parser.js;h=0d52ee00005bb6889b298d40ee312ab0c68a4956;hb=4ef6cdeda1d92848df61a92f8fa4af20761b99bb;hp=6caf0a9f5a3f0dfdc4f153a5d8e4ffd54dba02df;hpb=006d95a3942660083d2c957afea5338c2de8642d;p=erdiag.git
diff --git a/parser.js b/parser.js
index 6caf0a9..0d52ee0 100644
--- a/parser.js
+++ b/parser.js
@@ -3,11 +3,10 @@ class ErDiags
{
constructor(description)
{
- this.entities = {};
- this.inheritances = [];
- this.associations = [];
+ this.entities = { };
+ this.inheritances = [ ];
+ this.associations = [ ];
this.txt2json(description);
- this.tables = [];
// Cache SVG graphs returned by server (in addition to server cache = good perfs)
this.mcdGraph = "";
this.mldGraph = "";
@@ -26,7 +25,9 @@ class ErDiags
"*": "0,n",
"+": "1,n",
"?": "0,1",
- "1": "1,1"
+ "1": "1,1",
+ "?R": "(0,1)",
+ "1R": "(1,1)",
};
}
@@ -136,7 +137,10 @@ class ErDiags
return inheritance;
}
- // Association (parsed here): { entities: ArrayOf entity names + cardinality, [attributes: ArrayOf {name, [isKey], [type], [qualifiers]}] }
+ // Association (parsed here): {
+ // entities: ArrayOf entity names + cardinality,
+ // [attributes: ArrayOf {name, [isKey], [type], [qualifiers]}]
+ // }
parseAssociation(lines, start, end)
{
let assoce = { };
@@ -192,7 +196,7 @@ class ErDiags
mcdDot += 'rankdir="LR";\n';
// Nodes:
if (mcdStyle == "compact")
- mcdDot += "node [shape=plaintext];\n";
+ mcdDot += 'node [shape=plaintext];\n';
_.shuffle(Object.keys(this.entities)).forEach( name => {
if (mcdStyle == "bubble")
{
@@ -202,7 +206,7 @@ class ErDiags
mcdDot += '];\n';
if (!!this.entities[name].attributes)
{
- _.shuffle(this.entities[name].attributes).forEach( a => {
+ this.entities[name].attributes.forEach( a => {
let label = (a.isKey ? '#' : '') + a.name;
let attrName = name + '_' + a.name;
mcdDot += '"' + attrName + '" [shape=ellipse, label="' + label + '"];\n';
@@ -226,7 +230,7 @@ class ErDiags
mcdDot += '
' + name + ' |
\n';
if (!!this.entities[name].attributes)
{
- _.shuffle(this.entities[name].attributes).forEach( a => {
+ this.entities[name].attributes.forEach( a => {
let label = (a.isKey ? '' : '') + a.name + (a.isKey ? '' : '');
mcdDot += '' + label + ' |
\n';
});
@@ -239,6 +243,10 @@ class ErDiags
});
// Inheritances:
_.shuffle(this.inheritances).forEach( i => {
+ // TODO: node shape = triangle fill yellow. See
+ // https://merise.developpez.com/faq/?page=MCD#CIF-ou-dependance-fonctionnelle-de-A-a-Z
+ // https://merise.developpez.com/faq/?page=MLD#Comment-transformer-un-MCD-en-MLD
+ // https://www.developpez.net/forums/d1088964/general-developpement/alm/modelisation/structure-agregation-l-association-d-association/
_.shuffle(i.children).forEach( c => {
if (Math.random() < 0.5)
mcdDot += '"' + c + '":name -- "' + i.parent;
@@ -248,15 +256,47 @@ class ErDiags
});
});
// Relationships:
+ if (mcdStyle == "compact")
+ mcdDot += 'node [shape=rectangle, style=rounded];\n';
let assoceCounter = 0;
_.shuffle(this.associations).forEach( a => {
let name = !!a.name && a.name.length > 0
? a.name
: '_assoce' + assoceCounter++;
- mcdDot += '"' + name + '" [shape="diamond", style="filled", color="lightgrey", label="' + name + '"';
- if (a.weak)
- mcdDot += ', peripheries=2';
- mcdDot += '];\n';
+ if (mcdStyle == "bubble")
+ {
+ mcdDot += '"' + name + '" [shape="diamond", style="filled", color="lightgrey", label="' + name + '"';
+ if (a.weak)
+ mcdDot += ', peripheries=2';
+ mcdDot += '];\n';
+ if (!!a.attributes)
+ {
+ a.attributes.forEach( attr => {
+ let label = (attr.isKey ? '#' : '') + attr.name;
+ mcdDot += '"' + name + '_' + attr.name + '" [shape=ellipse, label="' + label + '"];\n';
+ let attrName = name + '_' + attr.name;
+ if (Math.random() < 0.5)
+ mcdDot += '"' + attrName + '" -- "' + name + '";\n';
+ else
+ mcdDot += '"' + name + '" -- "' + attrName + '";\n';
+ });
+ }
+ }
+ else
+ {
+ let label = '<' + name + '>';
+ if (!!a.attributes)
+ {
+ a.attributes.forEach( attr => {
+ let attrLabel = (attr.isKey ? '#' : '') + attr.name;
+ label += '\\n' + attrLabel;
+ });
+ }
+ mcdDot += '"' + name + '" [color="lightgrey", label="' + label + '"';
+ if (a.weak)
+ mcdDot += ', peripheries=2';
+ mcdDot += '];\n';
+ }
_.shuffle(a.entities).forEach( e => {
if (Math.random() < 0.5)
mcdDot += '"' + e.name + '":name -- "' + name + '"';
@@ -264,18 +304,6 @@ class ErDiags
mcdDot += '"' + name + '" -- "' + e.name + '":name';
mcdDot += '[label="' + ErDiags.CARDINAL[e.card] + '"];\n';
});
- if (!!a.attributes)
- {
- _.shuffle(a.attributes).forEach( attr => {
- let label = (attr.isKey ? '#' : '') + attr.name;
- mcdDot += '"' + name + '_' + attr.name + '" [shape=ellipse, label="' + label + '"];\n';
- let attrName = name + '_' + attr.name;
- if (Math.random() < 0.5)
- mcdDot += '"' + attrName + '" -- "' + name + '";\n';
- else
- mcdDot += '"' + name + '" -- "' + attrName + '";\n';
- });
- }
});
mcdDot += '}';
console.log(mcdDot);
@@ -295,18 +323,21 @@ class ErDiags
element.innerHTML = this.mcdGraph;
return;
}
- // Build dot graph input
+ // Build dot graph input (assuming foreign keys not already present...)
let mldDot = 'graph {\n';
- // Nodes:
+ // Pass 1: initialize tables
+ let tables = [ ];
Object.keys(this.entities).forEach( name => {
- //mld. ... --> devient table
- // mldDot = ...
+ tables.push({ name: this.entities[name] }); //TODO: should be a (deep) copy
});
- // Relationships:
+ // Pass 2: parse associations, add foreign keys + new tables
this.associations.forEach( a => {
a.entities.forEach( e => { // e.card e.name ...
- // Pass 1 : entites deviennent tables
- // Pass 2 : sur les assoces
+ switch (e.card)
+ {
+ case '?':
+ case '?R': //"weak tables" foreign keys become part of the key
+ // TODO
// multi-arite : sub-loop si 0,1 ou 1,1 : aspiré comme attribut de l'association (phase 1)
// ensuite, que du 0,n ou 1,n : si == 1, OK une table
// si 2 ou + : n tables + 1 pour l'assoce, avec attrs clés étrangères