~ubuntu-branches/ubuntu/utopic/tcm/utopic

« back to all changes in this revision

Viewing changes to src/sd/dv/crdiagram.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2003-07-03 20:08:21 UTC
  • Revision ID: james.westby@ubuntu.com-20030703200821-se4xtqx25e5miczi
Tags: upstream-2.20
ImportĀ upstreamĀ versionĀ 2.20

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
////////////////////////////////////////////////////////////////////////////////
 
2
//
 
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
 
4
// (c) copyright 1995, Vrije Universiteit Amsterdam.
 
5
// Author: Frank Dehne (frank@cs.vu.nl).
 
6
//
 
7
// TCM is free software; you can redistribute it and/or modify
 
8
// it under the terms of the GNU General Public License as published by
 
9
// the Free Software Foundation; either version 2 of the License, or
 
10
// (at your option) any later version.
 
11
//
 
12
// TCM is distributed in the hope that it will be useful,
 
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
// GNU General Public License for more details.
 
16
//
 
17
// You should have received a copy of the GNU General Public License
 
18
// along with TCM; if not, write to the Free Software
 
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
20
// 02111-1307, USA.
 
21
////////////////////////////////////////////////////////////////////////////////
 
22
#include "crgraph.h"
 
23
#include "crwindow.h"
 
24
#include "crviewer.h"
 
25
#include "crchecks.h"
 
26
#include "messagedialog.h"
 
27
#include "grafport.h"
 
28
#include "tripleclassbox.h"
 
29
#include "doubleclassbox.h"
 
30
#include "c1arrow.h"
 
31
#include "c2r2line.h"
 
32
#include "binaryrelationship.h"
 
33
#include "componentfunction.h"
 
34
#include "isarelationship.h"
 
35
#include "modejunction.h"
 
36
#include "emptyedge.h"
 
37
#include "miniellipse.h"
 
38
#include "textbox.h"
 
39
#include "comment.h"
 
40
#include "crdiagram.h"
 
41
#include <limits.h>
 
42
 
 
43
CRDiagram::CRDiagram(Config *c, CRWindow *d, CRViewer *v, CRGraph *g): 
 
44
           ERDiagram(c, d, v, g) {
 
45
        UpdateNodeType(1);
 
46
        UpdateEdgeType(1);
 
47
        crChecks = new CRChecks(this, g);
 
48
}
 
49
 
 
50
CRDiagram::~CRDiagram() {
 
51
        delete crChecks;
 
52
}
 
53
 
 
54
Thing *CRDiagram::CreateThing(int classNr) {
 
55
        Grafport *g = GetDiagramViewer()->GetGrafport();
 
56
        ShapeView *v = GetDiagramViewer()->GetCurView();
 
57
        CRGraph *cg = (CRGraph *)GetGraph();
 
58
        Thing *thing = 0;
 
59
        // view
 
60
        if (classNr == Code::VIEW)
 
61
                thing = new ShapeView(GetDiagramViewer());
 
62
 
 
63
        // node shapes
 
64
        else if (classNr==Code::TRIPLE_BOX)
 
65
                thing = new TripleClassBox(v, g, 0, 0); 
 
66
        else if (classNr==Code::DOUBLE_BOX)
 
67
                thing = new DoubleClassBox(v, g, 0, 0); 
 
68
        else if (classNr==Code::BOX)
 
69
                thing = new Box(v, g, 0, 0); 
 
70
        else if (classNr == Code::MINI_ELLIPSE) {
 
71
                MiniEllipse *ellipse = new MiniEllipse(v, g, 0, 0);
 
72
                // extra for older diagram versions.
 
73
                ellipse->SetFixedName(False); 
 
74
                thing = ellipse;
 
75
        }
 
76
        else if (classNr==Code::TEXT_BOX)
 
77
                thing = new TextBox(v, g, 0, 0); 
 
78
 
 
79
        // lines
 
80
        else if (classNr==Code::T1_LINE)
 
81
                thing = new C1Arrow(v, g, 0, 0, 0);
 
82
        else if (classNr==Code::T4_LINE || classNr==Code::C2R2_LINE)
 
83
                thing = new C2R2Line(v, g, 0, 0, 0);
 
84
        else if (classNr==Code::LINE)
 
85
                thing = new Line(v, g, 0, 0, 0);
 
86
 
 
87
        // (T1_)ARROW and DOUBLE_ARROW from old file formats.
 
88
        else if (classNr==Code::T1_ARROW)
 
89
                thing = new C1Arrow(v, g, 0, 0, 0);
 
90
        else if (classNr==Code::ARROW) {
 
91
                Line *line = new Line(v, g, 0, 0, 0);
 
92
                line->SetEnd2(LineEnd::FILLED_ARROW);
 
93
                line->SetFixedName(True);
 
94
                thing = line;
 
95
        }
 
96
        else if (classNr==Code::DOUBLE_ARROW) {
 
97
                Line *line = new Line(v, g, 0, 0, 0);
 
98
                line->SetEnd1(LineEnd::FILLED_ARROW);
 
99
                line->SetEnd2(LineEnd::FILLED_ARROW);
 
100
                thing = line;
 
101
        }
 
102
 
 
103
        // nodes
 
104
        else if (classNr==Code::CLASS_NODE)
 
105
                thing = new ClassNode(cg);
 
106
        else if (classNr==Code::TAXONOMY_JUNCTION)
 
107
                thing = new TaxonomyJunction(cg);
 
108
        else if (classNr==Code::MODE_JUNCTION)
 
109
                thing = new ModeJunction(cg);
 
110
        else if (classNr==Code::COMMENT)
 
111
                thing = new Comment(cg);
 
112
 
 
113
        // edges
 
114
        else if (classNr==Code::BINARY_RELATIONSHIP)
 
115
                thing = new BinaryRelationship(cg, 0, 0);
 
116
        else if (classNr==Code::FUNCTION)
 
117
                thing = new Function(cg, 0, 0);
 
118
        else if (classNr==Code::COMPONENT_FUNCTION)
 
119
                thing = new ComponentFunction(cg, 0, 0);
 
120
        else if (classNr==Code::EMPTY_EDGE)
 
121
                thing = new EmptyEdge(cg, 0, 0);
 
122
        else if (classNr==Code::ISA_RELATIONSHIP)
 
123
                thing = new IsaRelationship(cg, 0, 0);
 
124
        else
 
125
                error("%s, line %d: impl error: wrong class number %d\n", 
 
126
                        __FILE__, __LINE__, classNr);
 
127
        return thing;
 
128
}
 
129
 
 
130
Node *CRDiagram::CreateNode(){
 
131
        Node *node = 0;
 
132
        CRGraph *g = (CRGraph *)GetGraph();
 
133
        if (GetNodeType()==Code::MODE_JUNCTION)
 
134
                node = new ModeJunction(g);
 
135
        else if (GetNodeType()==Code::TAXONOMY_JUNCTION)
 
136
                node = new TaxonomyJunction(g);
 
137
        else if (GetNodeType()==Code::CLASS_NODE)
 
138
                node = new ClassNode(g);
 
139
        else if (GetNodeType()==Code::COMMENT)
 
140
                node = new Comment(g);
 
141
        else
 
142
                error( "%s, line %d: impl error: unknown node type\n", 
 
143
                        __FILE__, __LINE__);
 
144
        return node;
 
145
}
 
146
 
 
147
Edge *CRDiagram::CreateEdge(Subject *subj1, Subject *subj2){
 
148
        if (!CheckEdgeConstraints(subj1, subj2))
 
149
                return 0;
 
150
        Edge *edge = 0;
 
151
        CRGraph *g = (CRGraph *)GetGraph();
 
152
        if (GetEdgeType() == Code::EMPTY_EDGE)
 
153
                edge = new EmptyEdge(g, subj1, subj2);
 
154
        else if (GetEdgeType() == Code::FUNCTION)
 
155
                edge = new Function(g, subj1, subj2);
 
156
        else if (GetEdgeType() == Code::BINARY_RELATIONSHIP)
 
157
                edge = new BinaryRelationship(g, subj1, subj2);
 
158
        else if (GetEdgeType() == Code::COMPONENT_FUNCTION)
 
159
                edge = new ComponentFunction(g, subj1, subj2);
 
160
        else if (GetEdgeType() == Code::ISA_RELATIONSHIP)
 
161
                edge = new IsaRelationship(g, subj1, subj2);
 
162
        else
 
163
                error( "%s, line %d: impl error: unknown edge type\n", 
 
164
                        __FILE__, __LINE__);
 
165
 
 
166
        if (GetEdgeType() == Code::EMPTY_EDGE || 
 
167
                GetEdgeType() == Code::ISA_RELATIONSHIP) {
 
168
                if (!CheckIsaLoop(edge) || !CheckTaxonomyCombination(edge)) {
 
169
                        delete edge;
 
170
                        return 0;
 
171
                }
 
172
        }
 
173
        return edge;
 
174
}
 
175
 
 
176
NodeShape *CRDiagram::CreateNodeShape(Node *node, int x, int y) {
 
177
        NodeShape *shape = 0;
 
178
        Grafport *g = GetDiagramViewer()->GetGrafport();
 
179
        ShapeView *v = GetDiagramViewer()->GetCurView();
 
180
        if (GetNodeShapeType() == Code::BOX)
 
181
                shape = new Box(v, g, x, y);
 
182
        else if (GetNodeShapeType() == Code::MINI_ELLIPSE) {
 
183
                shape = new MiniEllipse(v, g, x, y);
 
184
                shape->SetFixedName(False);
 
185
        }
 
186
        else if (GetNodeShapeType() == Code::DOUBLE_BOX)
 
187
                shape = new DoubleClassBox(v, g, x, y);
 
188
        else if (GetNodeShapeType() == Code::TEXT_BOX)
 
189
                shape = new TextBox(v, g, x, y);
 
190
        else if (GetNodeShapeType() == Code::TRIPLE_BOX)
 
191
                shape = new TripleClassBox(v, g, x, y);
 
192
        else
 
193
                error( "%s, line %d: impl error: "
 
194
                        "node shape type doesn't exist\n", __FILE__, __LINE__);
 
195
        
 
196
        if (check(shape)) {
 
197
                shape->SetSubject(node);
 
198
                shape->SetTextShape();
 
199
        }
 
200
        return shape;
 
201
}
 
202
 
 
203
Line *CRDiagram::CreateLine(
 
204
                Edge *edge, GShape *from, GShape *to, List<Point *> *l) {
 
205
        Grafport *g = GetDiagramViewer()->GetGrafport();
 
206
        ShapeView *v = GetDiagramViewer()->GetCurView();
 
207
        Line *line = 0;
 
208
        if (GetLineType()== Code::T1_LINE)
 
209
                line = new C1Arrow(v, g, from, to, l, IsCurve());
 
210
        else if (GetLineType()== Code::C2R2_LINE)
 
211
                line = new C2R2Line(v, g, from, to, l, IsCurve());
 
212
        else if (GetLineType()== Code::LINE)
 
213
                line = new Line(v, g, from, to, l, IsCurve());
 
214
        else
 
215
                error( "%s, line %d: impl error: "
 
216
                        "line type does not exist\n", __FILE__, __LINE__);
 
217
        
 
218
        if (check(line)) {
 
219
                line->SetSubject(edge);
 
220
                line->SetTextShape();
 
221
                line->SetEnd1(GetLineEnd1());
 
222
                line->SetEnd2(GetLineEnd2());
 
223
                if (GetEdgeType()==Code::EMPTY_EDGE ||
 
224
                    GetEdgeType()==Code::ISA_RELATIONSHIP)
 
225
                        line->SetFixedName(True);
 
226
                if (GetLineEnd1()==LineEnd::FILLED_ARROW) {
 
227
                        if (edge->GetClassType()==Code::FUNCTION) {
 
228
                                string constr("1");
 
229
                                ((Function *)edge)->SetConstraint(&constr);
 
230
                        }
 
231
                }
 
232
        }
 
233
        return line;
 
234
}
 
235
 
 
236
void CRDiagram::UpdateNodeType(int num) {
 
237
        ((DiagramWindow *)GetMainWindow())->SetNodeName(num);
 
238
        switch (num) {
 
239
        case 1: SetNodeType(Code::CLASS_NODE);
 
240
                SetNodeShapeType(Code::BOX);
 
241
                SetNodeLineStyle(LineStyle::SOLID);
 
242
                break;
 
243
        case 2: SetNodeType(Code::CLASS_NODE);
 
244
                SetNodeShapeType(Code::DOUBLE_BOX);
 
245
                SetNodeLineStyle(LineStyle::SOLID);
 
246
                break;
 
247
        case 3: SetNodeType(Code::CLASS_NODE);
 
248
                SetNodeShapeType(Code::TRIPLE_BOX);
 
249
                SetNodeLineStyle(LineStyle::SOLID);
 
250
                break;
 
251
        case 4: SetNodeType(Code::TAXONOMY_JUNCTION);
 
252
                SetNodeShapeType(Code::MINI_ELLIPSE);
 
253
                SetNodeLineStyle(LineStyle::SOLID);
 
254
                break;
 
255
        case 5: SetNodeType(Code::MODE_JUNCTION);
 
256
                SetNodeShapeType(Code::MINI_ELLIPSE);
 
257
                SetNodeLineStyle(LineStyle::DASHED);
 
258
                break;
 
259
        case 6: SetNodeType(Code::COMMENT);
 
260
                SetNodeShapeType(Code::TEXT_BOX);
 
261
                SetNodeLineStyle(LineStyle::INVISIBLE);
 
262
                break;
 
263
        default:
 
264
                error("%s, line %d: impl error: "
 
265
                        "unknown node type selected\n", __FILE__,__LINE__);
 
266
        }
 
267
}
 
268
 
 
269
void CRDiagram::UpdateEdgeType(int num) {
 
270
        ((DiagramWindow *)GetMainWindow())->SetEdgeName(num);
 
271
        switch(num) {
 
272
        case 1: SetEdgeType(Code::BINARY_RELATIONSHIP);
 
273
                SetLineType(Code::C2R2_LINE);
 
274
                SetEdgeLineStyle(LineStyle::SOLID);
 
275
                SetLineEnd1(LineEnd::EMPTY);
 
276
                SetLineEnd2(LineEnd::EMPTY);
 
277
                break;
 
278
        case 2: SetEdgeType(Code::FUNCTION);
 
279
                SetLineType(Code::T1_LINE);
 
280
                SetEdgeLineStyle(LineStyle::SOLID);
 
281
                SetLineEnd1(LineEnd::EMPTY);
 
282
                SetLineEnd2(LineEnd::FILLED_ARROW);
 
283
                break;
 
284
        case 3: SetEdgeType(Code::COMPONENT_FUNCTION);
 
285
                SetLineType(Code::T1_LINE);
 
286
                SetEdgeLineStyle(LineStyle::DASHED);
 
287
                SetLineEnd1(LineEnd::EMPTY);
 
288
                SetLineEnd2(LineEnd::FILLED_ARROW);
 
289
                break;
 
290
        case 4: SetEdgeType(Code::ISA_RELATIONSHIP);
 
291
                SetLineType(Code::LINE);
 
292
                SetEdgeLineStyle(LineStyle::SOLID);
 
293
                SetLineEnd1(LineEnd::EMPTY);
 
294
                SetLineEnd2(LineEnd::FILLED_ARROW);
 
295
                break;
 
296
        case 5: SetEdgeType(Code::EMPTY_EDGE);
 
297
                SetLineType(Code::LINE);
 
298
                SetEdgeLineStyle(LineStyle::SOLID);
 
299
                SetLineEnd1(LineEnd::EMPTY);
 
300
                SetLineEnd2(LineEnd::EMPTY);
 
301
                break;
 
302
        case 6: SetEdgeType(Code::FUNCTION);
 
303
                SetLineType(Code::LINE);
 
304
                SetEdgeLineStyle(LineStyle::SOLID);
 
305
                SetLineEnd1(LineEnd::FILLED_ARROW);
 
306
                SetLineEnd2(LineEnd::FILLED_ARROW);
 
307
                break;
 
308
        default:
 
309
                error("%s, line %d: impl error: "
 
310
                        "unknown edge type selected\n", __FILE__,__LINE__);
 
311
        }
 
312
}
 
313
 
 
314
bool CRDiagram::SetText(TextShape *t, const string *s) {
 
315
        const string *d = t->GetDescription();
 
316
        Subject *subj = t->GetParent()->GetSubject();
 
317
        if (*d == "Attribute" && subj->GetClassType()==Code::CLASS_NODE)
 
318
                return SetAttribute((ClassNode *)subj, s, t->GetSequence());
 
319
        else if (*d == "Operation" && subj->GetClassType()==Code::CLASS_NODE)
 
320
                return SetOperation((ClassNode *)subj, s, t->GetSequence());
 
321
        else
 
322
                return ERDiagram::SetText(t, s);
 
323
}
 
324
 
 
325
void CRDiagram::MakeErrorMessage(ClassNode *cl, 
 
326
                ClassNode::TextErrType result, 
 
327
                const string *s, string *txt) {
 
328
        *txt = "class '" + *cl->GetName() + "' ";
 
329
        if (result == ClassNode::ATTRIBUTE_EXISTS)
 
330
                *txt += "already has an attribute '" + *s + "'"; 
 
331
        else if (result == ClassNode::OPERATION_EXISTS)
 
332
                *txt += "already has an operation '" + *s + "'"; 
 
333
        else if (result == ClassNode::FUNCTION_EXISTS)
 
334
                *txt += "already has a function '" + *s + "'"; 
 
335
        else if (result == ClassNode::COMPONENT_EXISTS)
 
336
                *txt += "already has a component function '" + *s + "'"; 
 
337
        else if (result == ClassNode::RELATION_EXISTS)
 
338
                *txt += "is already engaged in binary relationship '" + *s + "'"; 
 
339
        else if (result == ClassNode::IMPOSSIBLE_ATTRIBUTE)
 
340
                *txt = "'" + *s + "' wrong syntax\nfor an attribute declaration";
 
341
        else if (result == ClassNode::IMPOSSIBLE_OPERATION)
 
342
                *txt = "'" + *s + "' wrong syntax\nfor an operation declaration";
 
343
}
 
344
 
 
345
bool CRDiagram::SetAttribute(ClassNode *cl, const string *s, unsigned nr) {
 
346
        List<GShape *> shapes;
 
347
        GetDiagramViewer()->GetShapes(cl, &shapes);
 
348
        unsigned m = nr;
 
349
        // split string in different strings (separated by newline).
 
350
        // each string becomes a new attribute.
 
351
        string ss(*s);
 
352
        char *str = (char *)ss.getstr();
 
353
        char *x = strtok(str, "\r");
 
354
        char empty[2] = "";
 
355
        if (x == 0)
 
356
                x = empty;
 
357
        while (x != 0) {
 
358
                string *ns = new string(x);
 
359
                bool update = True;
 
360
                ClassNode::TextErrType result;
 
361
                if (m == nr)
 
362
                        result = cl->SetAttribute(ns, m, True);
 
363
                else { // m != r
 
364
                        result = cl->SetAttribute(ns, m, False);
 
365
                        update = False;
 
366
                }
 
367
                string txt;
 
368
                MakeErrorMessage(cl, result, ns, &txt);
 
369
                if (result != ClassNode::MEMBER_OK) {
 
370
                        ShowDialog(MessageDialog::ERROR, "Error", &txt);
 
371
                        // delete the newly created attributes.
 
372
                        *ns = "";
 
373
                        for (shapes.first(); !shapes.done(); shapes.next()) {
 
374
                                if (shapes.cur()->GetClassType() != Code::BOX) {
 
375
                                        DoubleBox *db = 
 
376
                                                (DoubleBox *)(shapes.cur());
 
377
                                        if (db->NrLabels()-1 == m)
 
378
                                                db->UpdateLabel(ns, m, update);
 
379
                                }
 
380
                        }
 
381
                        delete ns;
 
382
                        return False;
 
383
                }
 
384
                // update the double box shapes.
 
385
                for (shapes.first(); !shapes.done(); shapes.next()) {
 
386
                        if (shapes.cur()->GetClassType() != Code::BOX)
 
387
                                ((DoubleBox *)shapes.cur())->
 
388
                                        UpdateLabel(ns, m, update);
 
389
                }
 
390
                if (!shapes.first()) {
 
391
                        error( "%s, line %d: impl error: "
 
392
                                "shape does not exist!\n", __FILE__, __LINE__);
 
393
                        return False;
 
394
                }
 
395
                m++;
 
396
                x = strtok(0, "\r");
 
397
                delete ns;
 
398
        }
 
399
        return True;
 
400
}
 
401
 
 
402
bool CRDiagram::SetOperation(ClassNode *cl, const string *s, unsigned nr) {
 
403
        List<GShape *> shapes;
 
404
        GetDiagramViewer()->GetShapes(cl, &shapes);
 
405
        string ss(*s);
 
406
        char *str = (char *)ss.getstr();
 
407
        unsigned m = nr;
 
408
        char empty[2] = "";
 
409
        char *x = strtok(str, "\r");
 
410
        if (x == 0)
 
411
                x = empty;
 
412
        while (x != 0) {
 
413
                string *ns = new string(x);
 
414
                bool update = True;
 
415
                ClassNode::TextErrType result;
 
416
                if (m == nr) {
 
417
                        result = cl->SetOperation(ns, m, True);
 
418
                }
 
419
                else { // m != r
 
420
                        result = cl->SetOperation(ns, m, False);
 
421
                        update = False;
 
422
                }
 
423
                string txt;
 
424
                MakeErrorMessage(cl, result, ns, &txt);
 
425
                if (result != ClassNode::MEMBER_OK) {
 
426
                        ShowDialog(MessageDialog::ERROR, "Error", &txt);
 
427
                        // delete the newly created operations.
 
428
                        *ns = "";
 
429
                        for (shapes.first(); !shapes.done(); shapes.next()) {
 
430
                                if (shapes.cur()->GetClassType() == 
 
431
                                                Code::TRIPLE_BOX) {
 
432
                                        TripleBox *tb = 
 
433
                                                (TripleBox *)(shapes.cur());
 
434
                                        if (tb->NrLabels2()-1 == m)
 
435
                                                tb->UpdateLabel2(ns, m, update);
 
436
                                }
 
437
                        }
 
438
                        delete ns;
 
439
                        return False;
 
440
                }
 
441
                // update the triple box shapes.
 
442
                for (shapes.first(); !shapes.done(); shapes.next()) {
 
443
                        if (shapes.cur()->GetClassType() == Code::TRIPLE_BOX) 
 
444
                                ((TripleBox *)shapes.cur())->
 
445
                                        UpdateLabel2(ns, m, update);
 
446
                } 
 
447
                if (!shapes.first()) {
 
448
                        error( "%s, line %d: impl error: "
 
449
                                "shape does not exist!\n", __FILE__, __LINE__);
 
450
                        return False;
 
451
                }
 
452
                m++;
 
453
                x = strtok(0, "\r");
 
454
                delete ns;
 
455
        }
 
456
        return True;
 
457
}
 
458
 
 
459
void CRDiagram::CheckDocument() {
 
460
        chkbuf = "";
 
461
        unsigned total = 0;
 
462
        // Check that binary relationships are named.
 
463
        total += crChecks->CheckNamelessBinaryRelationships(chkbuf);
 
464
        if (total == 0)
 
465
                total += crChecks->CheckDoubleNamelessEdges(
 
466
                        Code::BINARY_RELATIONSHIP, Code::CLASS_NODE, 
 
467
                        Code::CLASS_NODE, chkbuf);
 
468
        // Check that classes are named.
 
469
        total += crChecks->CheckNamelessNodes(Code::CLASS_NODE, chkbuf);
 
470
        // double nodes can occur after cut-copy-paste
 
471
        total += crChecks->CheckDoubleNodes(Code::CLASS_NODE, chkbuf);
 
472
        // Check that functions and component functions are identifiable.
 
473
        total += crChecks->CheckDoubleNamelessFunctions(
 
474
                Code::CLASS_NODE, Code::CLASS_NODE, chkbuf);
 
475
        // Check that tax. and mode junctions are connected correctly.
 
476
        total += crChecks->CheckJunctionCoherence(
 
477
                Code::TAXONOMY_JUNCTION, Code::ISA_RELATIONSHIP, 
 
478
                Code::EMPTY_EDGE, 2, chkbuf);
 
479
        total += crChecks->CheckJunctionCoherence(
 
480
                Code::MODE_JUNCTION, Code::ISA_RELATIONSHIP, 
 
481
                Code::EMPTY_EDGE, 2, chkbuf);
 
482
        // Check that classes have not 1 comp. function.
 
483
        total += crChecks->CheckCountEdgesFrom(
 
484
                Code::CLASS_NODE, Code::COMPONENT_FUNCTION, 2, INT_MAX, 
 
485
                True, False, chkbuf);
 
486
        // Check that rel. classes are not spec. of classes.
 
487
        total += crChecks->CheckRelationshipIsaClassNode(chkbuf);
 
488
        ReportCheck(total, &chkbuf);
 
489
}
 
490
 
 
491
bool CRDiagram::CheckTaxonomyCombination(Edge *edge) {
 
492
        // checks if adding the edge does not make a static partition 
 
493
        // (with tax.junction) part of a dynamic partition (with modejunction).
 
494
        int eType = edge->GetClassType();
 
495
        Subject *n1 = edge->GetSubject1();
 
496
        Subject *n2 = edge->GetSubject2();
 
497
        int n1Type = n1->GetClassType();
 
498
        int n2Type = n2->GetClassType();
 
499
        bool correct = True;
 
500
        if (eType == Code::EMPTY_EDGE) {
 
501
                Subject *nX = 0;
 
502
                if (n1Type == Code::CLASS_NODE && 
 
503
                    n2Type == Code::MODE_JUNCTION)
 
504
                        nX = n1;
 
505
                else if (n1Type == Code::MODE_JUNCTION && 
 
506
                         n2Type == Code::CLASS_NODE) 
 
507
                        nX = n2;
 
508
                if (nX) {
 
509
                        List<Subject *> edges;
 
510
                        GetGraph()->GetEdges(&edges, Code::ISA_RELATIONSHIP);
 
511
                        for (edges.first(); !edges.done(); edges.next()) {
 
512
                                Edge *e = (Edge *)edges.cur();
 
513
                                if (nX == e->GetSubject2()) {
 
514
                                        int t=e->GetSubject1()->GetClassType();
 
515
                                        if (t == Code::CLASS_NODE || 
 
516
                                                t == Code::TAXONOMY_JUNCTION)
 
517
                                                correct = False;
 
518
                                }
 
519
                        }
 
520
                }
 
521
        }
 
522
        else if (eType == Code::ISA_RELATIONSHIP) {
 
523
                if (n1Type == Code::CLASS_NODE || 
 
524
                    n1Type == Code::TAXONOMY_JUNCTION) {
 
525
                        List<Subject *> edges;
 
526
                        GetGraph()->GetEdges(&edges, Code::EMPTY_EDGE);
 
527
                        for (edges.first(); !edges.done(); edges.next()) {
 
528
                                Edge *e = (Edge *)edges.cur();
 
529
                                if (n2==e->GetSubject1()) {
 
530
                                        if (e->GetSubject2()->GetClassType() == 
 
531
                                            Code::MODE_JUNCTION)
 
532
                                                correct = False;
 
533
                                }
 
534
                                else if (n2==e->GetSubject2()) {
 
535
                                        if (e->GetSubject1()->GetClassType() == 
 
536
                                            Code::MODE_JUNCTION)
 
537
                                                correct = False;
 
538
                                }
 
539
                        } 
 
540
                }
 
541
        }
 
542
        if (!correct) {
 
543
                string txt = "Dynamic specialization (with ModeJunction) cannot "
 
544
                         "be specialized\n into a static specialization "
 
545
                         "(with TaxonomyJunction)";
 
546
                ShowDialog(MessageDialog::ERROR, "Error", &txt);
 
547
        }
 
548
        return correct;
 
549
}