1
////////////////////////////////////////////////////////////////////////////////
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
4
// (c) copyright 1997, Vrije Universiteit Amsterdam.
5
// Author: Frank Dehne (frank@cs.vu.nl).
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.
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.
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
21
////////////////////////////////////////////////////////////////////////////////
26
#include "psprocess.h"
27
#include "diagramviewer.h"
30
PSChecks::PSChecks(Diagram *d, Graph *g): DiagramChecks(d, g) { }
32
unsigned PSChecks::CheckRootOperator(PSProcess *p, string &chkbuf) {
34
chkbuf +="* Remark: process '";
35
chkbuf += *p->GetName();
36
chkbuf += "' is considered as the root\n";
38
if ((c = p->GetOperator()) != ' ') {
39
chkbuf +="* Error: root process '";
40
chkbuf += *p->GetName();
41
chkbuf += "' has the illegal operator '";
44
GetDiagram()->SelectSubject(p);
50
unsigned PSChecks::CheckChildPositions(DiagramViewer *dviewer,
51
PSProcess *parent, List<Subject *> *children, string &chkbuf){
53
Shape *pshape = dviewer->GetShape(parent);
54
Point ppos = *pshape->GetPosition();
55
for (children->first(); !children->done(); children->next()) {
56
Subject *child = children->cur();
57
Shape *cshape = dviewer->GetShape(child);
58
Point cpos = *cshape->GetPosition();
59
// child is not lower than the parent.
60
if (cpos.y <= ppos.y) {
61
chkbuf +="* Warning: the process '";
62
chkbuf += *parent->GetName();
63
chkbuf += "' should better be positioned ";
64
chkbuf += "above its child process '";
65
chkbuf += *child->GetName();
67
GetDiagram()->SelectSubject(parent);
68
GetDiagram()->SelectSubject(child);
76
unsigned PSChecks::CheckChildOperators(PSProcess *parent,
77
List<Subject *> *children, string &chkbuf){
79
// There are no children.
80
if (!children->first())
82
else if (*parent->GetName() %= "QUIT") {
83
chkbuf +="* Error: a '";
84
chkbuf += *parent->GetName();
85
chkbuf += "' process should not have children\n";
86
GetDiagram()->SelectSubject(parent);
90
PSProcess *child = (PSProcess *)children->cur();
91
char basis_c = child->GetOperator();
92
if (basis_c == ' ') { // all remaining children should be a 'sequence'.
93
while (children->next()) {
94
child = (PSProcess *)children->cur();
95
char c = child->GetOperator();
98
chkbuf +="* Error: process '";
99
chkbuf += *parent->GetName();
100
chkbuf += "' has a non-single '*'";
101
chkbuf += "(iteration) child\n";
104
chkbuf +="* Error: some children of process '";
105
chkbuf += *parent->GetName();
106
chkbuf +="' have different operators '";
117
else if (basis_c == '*') { // there should be no other children.
118
if (children->next()) {
119
chkbuf +="* Error: process '";
120
chkbuf += *parent->GetName();
121
chkbuf += "' has a non-single '*'";
122
chkbuf += " (iteration) child\n";
126
else if (basis_c == 'o') { // >= 1 remaining children. All children should be choices.
127
if (!children->next()) {
128
chkbuf +="* Error: process '";
129
chkbuf += *parent->GetName();
130
chkbuf += "' has a single 'o' (choice) child\n";
134
for (children->first(); !children->done(); children->next()) {
135
child = (PSProcess *)children->cur();
136
char c = child->GetOperator();
139
chkbuf +="* Error: process '";
140
chkbuf += *parent->GetName();
141
chkbuf += "' has a non-single ";
142
chkbuf += "'*' (iteration) child";
145
chkbuf +="* Error: the ";
146
chkbuf += "children of process '";
147
chkbuf += *parent->GetName();
148
chkbuf += "' have different operators '";
160
else if (basis_c == '?') { // the name is 'POSIT'. The other child is named 'ADMIT'.
161
if (! parent->IsRoot()) {
162
chkbuf +="* Error: non-root process '";
163
chkbuf += *parent->GetName();
164
chkbuf += "' should not have children with a '?'\n";
168
string s = *(child->GetName());
169
if (! (s %= "POSIT")) {
170
chkbuf +="* Error: the first child of process '";
171
chkbuf += *parent->GetName();
172
chkbuf +="' is expected to have as name 'POSIT'\n";
175
else if (!children->next() ||
176
!(*children->cur()->GetName() %= "ADMIT") ||
177
(((PSProcess *)(children->cur()))->GetOperator() != '?')) {
178
chkbuf +="* Error: process '";
179
chkbuf += *parent->GetName();
180
chkbuf += "' is expected to have a second ";
181
chkbuf += "child named 'ADMIT' with a '?'\n";
184
else if (children->next()) {
185
chkbuf +="* Error: process '";
186
chkbuf += *parent->GetName();
187
chkbuf +="' is expected to have exactly two children\n";
191
else if (basis_c == '!') { // the name is [qQ][Uu][Ii][Tt]
192
string s = *(child->GetName());
193
if (! (s %= "QUIT")) {
194
chkbuf +="* Error: the child of process '";
195
chkbuf += *parent->GetName();
196
chkbuf += "' is expected to have name 'QUIT'\n";
199
else if (children->next()) {
200
chkbuf +="* Error: process '";
201
chkbuf += *parent->GetName();
202
chkbuf += "' is expected to have a ";
203
chkbuf += "single child\n";
208
chkbuf +="* Error: process '";
209
chkbuf += *parent->GetName();
210
chkbuf += "' has the illegal operator '";
216
GetDiagram()->SelectSubject(parent);
217
GetDiagram()->SelectSubjects(children);
222
unsigned PSChecks::CheckDoubleProcessNames(string &chkbuf) {
224
int nodetype = Code::PS_PROCESS;
225
List<Subject *> nodes;
226
List<Subject *> doublenodes;
227
List<string> strings_got;
228
GetGraph()->GetNodes(&nodes, nodetype);
229
for (nodes.first(); !nodes.done(); nodes.next()) {
230
PSProcess *proc = (PSProcess *) nodes.cur();
231
const string *s = proc->GetName();
232
if (*s != "" && strings_got.find(*s) == -1) {
234
GetGraph()->GetNodes(&doublenodes, s, nodetype);
235
if (doublenodes.count() > 1) {
236
for (doublenodes.first(); !doublenodes.done();
237
doublenodes.next()) {
238
PSProcess *p = (PSProcess *)doublenodes.cur();
239
// all double names processes should
240
// be leaves (actions).
241
if (!p->IsAction()) {
242
chkbuf += "* Error: ";
243
chkbuf += doublenodes.count();
244
chkbuf += " processes";
245
chkbuf += " are named '";
247
chkbuf += "' but they are not all actions\n";
248
GetDiagram()->SelectSubjects(&doublenodes);