#include "UmlClass.h"
#include "UmlItem.h"
#include "Token.h"
#include "FileIn.h"
#include "UmlAttribute.h"
#include "UmlRelation.h"
#include "UmlOperation.h"
#include "UmlNcRelation.h"
#include "Association.h"
#include "UmlCom.h"
#include "Binding.h"
#include "ClassInstance.h"
UmlItem * UmlClass::container(anItemKind kind, const Token & token, FileIn & in) {
switch (kind) {
case aClass:
case anAttribute:
case aRelation:
case anOperation:
return this;
default:
return parent()->container(kind, token, in );
}
}
void UmlClass::init()
{
declareFct("ownedmember", "uml:Class", &importIt);
declareFct("packagedelement", "uml:Class", &importIt);
declareFct("nestedclassifier", "uml:Class", &importIt);
declareFct("ownedmember", "uml:AssociationClass", &importIt);
declareFct("packagedelement", "uml:AssociationClass", &importIt);
declareFct("nestedclassifier", "uml:AssociationClass", &importIt);
declareFct("ownedmember", "uml:Interface", &importIt);
declareFct("packagedelement", "uml:Interface", &importIt);
declareFct("nestedclassifier", "uml:Interface", &importIt);
declareFct("ownedmember", "uml:Enumeration", &importIt);
declareFct("packagedelement", "uml:Enumeration", &importIt);
declareFct("nestedclassifier", "uml:Enumeration", &importIt);
declareFct("ownedmember", "uml:Actor", &importIt);
declareFct("packagedelement", "uml:Actor", &importIt);
declareFct("nestedclassifier", "uml:Actor", &importIt);
//
declareFct("ownedmember", "uml:PrimitiveType", &importPrimitiveType);
declareFct("packagedelement", "uml:PrimitiveType", &importPrimitiveType);
declareFct("ownedmember", "uml:DataType", &importPrimitiveType);
declareFct("packagedelement", "uml:DataType", &importPrimitiveType);
//
UmlAttribute::init();
UmlRelation::init();
UmlOperation::init();
ClassInstance::init();
}
void UmlClass::importIt(FileIn & in, Token & token, UmlItem * where)
{
where = where->container(aClass, token, in); // can't be null
QCString s = token.valueOf("name");
if (s.isEmpty()) {
static unsigned n = 0;
s.sprintf("anonymous_%u", ++n);
}
UmlClass * cl = create(where, s);
Association * assocclass = 0;
if (cl == 0)
in.error("cannot create classe '" + s +
"' in '" + where->name() + "'");
cl->addItem(token.xmiId(), in);
if (token.xmiType() == "uml:Actor")
cl->set_Stereotype("actor");
else if (token.xmiType() == "uml:Interface")
cl->set_Stereotype("interface");
else if (token.xmiType() == "uml:Enumeration")
cl->set_Stereotype("enum");
else if (token.xmiType() == "uml:AssociationClass") {
assocclass = &Association::get(token.xmiId(), token.valueOf("name"));
assocclass->set_class_association();
}
cl->setVisibility(token.valueOf("visibility"));
if (token.valueOf("isabstract") == "true")
cl->set_isAbstract(TRUE);
if (! token.closed()) {
QCString k = token.what();
const char * kstr = k;
QCString assocclass_ref1;
QCString assocclass_ref2;
while (in.read(), !token.close(kstr)) {
s = token.what();
if ((s == "ownedtemplatesignature") &&
((token.xmiType() == "uml:TemplateSignature") ||
(token.xmiType() == "uml:RedefinableTemplateSignature")))
cl->readFormal(in, token);
else if ((s == "templatebinding") &&
(token.xmiType() == "uml:TemplateBinding")) {
Binding::import(in, token, cl);
}
else if ((assocclass != 0) && (s == "memberend")) {
if (assocclass_ref1.isEmpty())
assocclass_ref1 = token.xmiIdref();
else
assocclass_ref2 = token.xmiIdref();
if (! token.closed())
in.finish(s);
}
else if ((assocclass != 0) &&
(s == "ownedend") &&
(token.xmiType() == "uml:Property"))
assocclass->import(in, token);
else
cl->UmlItem::import(in, token);
}
}
cl->unload(TRUE, FALSE);
}
void UmlClass::readFormal(FileIn & in, Token & token) {
if (! token.closed()) {
signatures[token.xmiId()] = this;
QCString k = token.what();
const char * kstr = k;
unsigned int rank = 0;
while (in.read(), !token.close(kstr)) {
QCString s = token.what();
if (s == "parameter") {
// useless
if (! token.closed())
in.finish(token.what());
}
else if ((s == "ownedparameter") &&
(token.xmiType() == "uml:ClassifierTemplateParameter")) {
QCString idparam = token.xmiId();
QCString pname = token.valueOf("name"); // at least for VP
QCString value;
if (! token.closed()) {
while (in.read(), !token.close("ownedparameter")) {
s = token.what();
if ((s == "ownedparameteredelement") ||
(s == "ownedelement")) {
s = token.valueOf("name");
if (! s.isEmpty())
pname = s;
}
else if (s == "defaultvalue")
value = token.valueOf("value");
if (! token.closed())
in.finish(token.what());
}
}
if (! pname.isEmpty()) {
UmlFormalParameter f(pname, value);
addFormal(rank++, f);
formalsId.append(idparam);
}
}
else if (! token.closed())
in.finish(token.what());
}
}
}
void UmlClass::importPrimitiveType(FileIn & in, Token & token, UmlItem *)
{
QCString id = token.xmiId();
UmlTypeSpec t;
t.explicit_type = token.valueOf("name");
if (FromBouml) {
if (! token.closed()) {
bool dummy;
in.read(); //
in.readWord(FALSE, dummy); // <
in.readWord(FALSE, dummy); // basedOn
t.type = dynamic_cast(All[in.readWord(FALSE, dummy)]);
if (t.type != 0)
// forget modifiers
t.explicit_type = "";
in.readWord(FALSE, dummy); // /
in.readWord(FALSE, dummy); // >
in.read(); //
in.read(); // end of token
}
}
else if (! token.closed())
in.finish(token.what());
if (!id.isEmpty())
PrimitiveTypes[id] = t;
}
void UmlClass::generalizeDependRealize(UmlItem * target, FileIn & in, int context, QCString label) {
static const struct {
aRelationKind rk;
const char * err;
} r[] = {
{ aGeneralisation, "cannot create generalization from '" },
{ aDependency, "cannot create dependency from '" },
{ aRealization, "cannot create realization from '" }
};
UmlItem * rel;
if (target->kind() == aClass)
rel = UmlRelation::create(r[context].rk, this, (UmlClass *) target);
else
rel = UmlNcRelation::create(r[context].rk, this, target);
if (rel == 0)
in.warning(r[context].err + name() + "' to '" + target->name() + "'");
else if (! label.isEmpty())
rel->set_Name(label);
}
void UmlClass::solveGeneralizationDependencyRealization(int context, QCString idref, QCString label) {
QMap::Iterator it = All.find(idref);
if (it == All.end())
UmlCom::trace("relation : unknown target reference '" + idref + "'
");
else {
static const struct {
aRelationKind rk;
const char * err;
} r[] = {
{ aGeneralisation, "cannot create generalization from '" },
{ aDependency, "cannot create dependency from '" },
{ aRealization, "cannot create realization from '" }
};
UmlItem * target = *it;
UmlItem * rel;
if (target->kind() == aClass)
rel = UmlRelation::create(r[context].rk, this, (UmlClass *) target);
else
rel = UmlNcRelation::create(r[context].rk, this, target);
if (rel == 0)
UmlCom::trace(r[context].err + name() + "' to '" + target->name() + "'");
else if (!label.isEmpty())
rel->set_Name(label);
}
}
UmlClass * UmlClass::signature(QCString id)
{
QMap::Iterator iter = signatures.find(id);
return (iter == signatures.end()) ? 0 : *iter;
}
int UmlClass::formalRank(QCString id) {
int r = formalsId.findIndex(id);
if (r == -1)
UmlCom::trace("unknown template formal reference '" + id + "'
");
return r;
}
bool UmlClass::bind(UmlClass * tmpl) {
const QVector ch = children();
unsigned int n = ch.size();
int i;
for (i = 0; i != (int) n; i += 1) {
if ((ch[i]->kind() == aRelation) &&
(((UmlRelation *) ch[i])->roleType() == tmpl)) {
switch (((UmlRelation *) ch[i])->relationKind()) {
case aRealization:
((UmlRelation *) ch[i])->set_Stereotype("bind");
// no break
case aGeneralisation:
return TRUE;
default:
break;
}
}
}
// add realization
UmlRelation * r =
UmlRelation::create(aRealization, this, tmpl);
if (r == 0) {
UmlCom::trace("class reference '" + id() +
"' can't realize class reference '" + tmpl->id() + "'
");
return FALSE;
}
r->set_Stereotype("bind");
return TRUE;
}
int UmlClass::NumberOf;
//associate the class owning the template signature with the signature id
QMap UmlClass::signatures;