bool UmlRelation::new_friend(Class * container, UmlClass * to, Q3PtrList<UmlItem> & expected_order) { UmlClass * from = container->get_uml(); #ifdef DEBUG_BOUML cout << "FRIEND from '" << from->name() << "' to '" << to->name() << "'\n"; #endif const Q3PtrVector<UmlItem> & ch = from->children(); UmlItem ** v = ch.data(); UmlItem ** const vsup = v + ch.size(); for (;v != vsup; v += 1) { if (((*v)->kind() == aRelation) && (((UmlRelation *) *v)->relationKind() == aDependency) && (((UmlRelation *) *v)->roleType() == to) && !neq((*v)->stereotype(), "friend")) { expected_order.append(*v); ((UmlRelation *) *v)->set_usefull(); return TRUE; } } // relation not found UmlRelation * rel = UmlBaseRelation::create(aDependency, from, to); if (rel == 0) { UmlCom::trace(Q3CString("<font face=helvetica><b>cannot add friend relation in <i>") + from->name() + "</i> to <i>" + to->name() + "</i></b></font><br><hr><br>"); return FALSE; } expected_order.append(rel); container->set_updated(); rel->set_CppDecl("Generated"); return rel->set_Stereotype("friend"); }
bool UmlRelation::new_friend(UmlClass * from, UmlClass * to) { #ifdef DEBUG_BOUML cout << "FRIEND from '" << from->name() << "' to '" << to->name() << "'\n"; #endif UmlRelation * rel = UmlBaseRelation::create(aDependency, from, to); if (rel == 0) { UmlCom::trace(Q3CString("<font face=helvetica><b>cannot add friend relation in <i>") + from->name() + "</i> to <i>" + to->name() + "</i></b></font><br><hr><br>"); return FALSE; } #ifndef ROUNDTRIP Statistic::one_relation_more(); #endif rel->set_CppDecl("Generated"); return rel->set_Stereotype("friend"); }
bool UmlRelation::new_one(Class * container, const Q3CString & name, UmlClass * dest, const Q3CString & modifier, const Q3CString & pretype, const Q3CString & array, const Q3CString & typeform, aVisibility visibility, bool staticp, bool constp, bool mutablep, bool volatilep, const Q3CString & value, Q3CString comment, Q3CString description #ifdef ROUNDTRIP , bool roundtrip, Q3PtrList<UmlItem> & expected_order #endif ) { #ifdef DEBUG_BOUML cout << "RELATION '" << name << "' from '" << cl->name() << "' to '" << dest->name() << "' modifier '" << modifier << "' array '" << array << "' typeform '" << typeform << "'\n"; #endif if ( #ifdef REVERSE container->from_libp() && #endif (visibility == PrivateVisibility)) { Lex::finish_line(); Lex::clear_comments(); return TRUE; } UmlClass * cl = container->get_uml(); UmlRelation * rel; #ifdef ROUNDTRIP if (roundtrip && ((rel = search_rel(container, name, dest, "")) != 0)) { rel->set_usefull(); expected_order.append(rel); } else { #endif rel = UmlBaseRelation::create((modifier.isEmpty() && ((typeform == "${type}") || (typeform[typeform.find("${type}") + 7] != '*'))) ? aDirectionalAggregationByValue : aDirectionalAssociation, cl, dest); if (rel == 0) { UmlCom::trace(Q3CString("<font face=helvetica><b>cannot add relation <i>") + name + "</i> in <i>" + cl->name() + "</i> to <i>" + dest->name() + "</i></b></font><br><hr>"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP Statistic::one_relation_more(); # else if (roundtrip) { expected_order.append(rel); container->set_updated(); roundtrip = FALSE; } } # endif #endif Lex::finish_line(); comment = Lex::get_comments(comment); description = Lex::get_description(description); #ifdef ROUNDTRIP if (roundtrip) { if (rel->visibility() != visibility) { rel->set_Visibility(visibility); container->set_updated(); } if (rel->isReadOnly() != constp) { rel->set_isReadOnly(constp); container->set_updated(); } if (rel->isClassMember() != staticp) { rel->set_isClassMember(staticp); container->set_updated(); } if (rel->isCppMutable() != mutablep) { rel->set_isCppMutable(mutablep); container->set_updated(); } if (rel->isVolatile() != volatilep) { rel->set_isVolatile(volatilep); container->set_updated(); } } else { #endif rel->set_Visibility(visibility); if (constp) rel->set_isReadOnly(TRUE); if (staticp) rel->set_isClassMember(TRUE); if (mutablep) rel->set_isCppMutable(TRUE); if (volatilep) rel->set_isVolatile(TRUE); #ifdef ROUNDTRIP } #endif Q3CString decl; if (typeform != "${type}") { // array & modified are empty, pretype is empty ? decl = CppSettings::relationDecl(TRUE, "*"); int index = typeform.find("<"); // cannot be -1 Q3CString st = typeform.left(index); Q3CString st_uml = CppSettings::umlType(st); #ifdef ROUNDTRIP if (roundtrip) { if (st_uml.isEmpty()) st_uml = st; if (neq(rel->stereotype(), st_uml)) { rel->set_Stereotype(st_uml); container->set_updated(); } } else #endif rel->set_Stereotype((st_uml.isEmpty()) ? st : st_uml); int index2; if ((index2 = decl.find("<${type}>")) == -1) { decl = " ${comment}${static}${mutable}${volatile}${const}${stereotype}<${type}> ${name}${value};"; index2 = decl.find("<${type}>"); } decl.replace(index2, 9, typeform.mid(index)); } else { if (!array.isEmpty()) { #ifdef ROUNDTRIP if (roundtrip) { if (neq(rel->multiplicity(), array)) { rel->set_Multiplicity(array); container->set_updated(); } } else #endif rel->set_Multiplicity(array); } decl = CppSettings::relationDecl(modifier != "*", array); int index; if (!pretype.isEmpty() && ((index = decl.find("${type}")) != 0)) decl.insert(index,(const char*)( pretype + " ")); if ((modifier == "&") && ((index = decl.find("${type}")) != 0)) decl.insert(index + 7, " &"); } if (! value.isEmpty()) { int index = decl.find("${value}"); if (index != -1) decl.insert(index + 2, "h_"); #ifdef ROUNDTRIP if (roundtrip) { if (!staticp) { Q3CString v = rel->defaultValue(); if (!v.isEmpty() && (((const char *) v)[0] == '=')) v = v.mid(1); if (nequal(v, value)) { rel->set_DefaultValue(value); container->set_updated(); } } } else #endif rel->set_DefaultValue(value); } #ifdef ROUNDTRIP if (roundtrip) { if (neq(rel->cppDecl(), decl)) { rel->set_CppDecl(decl); container->set_updated(); } if (decl.find("${description}") != -1) { if (nequal(rel->description(), description)) { rel->set_Description(description); container->set_updated(); } } else if (nequal(rel->description(), Lex::simplify_comment(comment))) { rel->set_Description(comment); // comment was set container->set_updated(); } // role name is the right one return TRUE; } #endif rel->set_CppDecl(decl); if (!comment.isEmpty()) rel->set_Description((decl.find("${description") != -1) ? description : Lex::simplify_comment(comment)); return rel->set_RoleName(name); }
void UmlRelation::set_unidir() { UmlRelation * r1 = side(TRUE); UmlRelation * r2 = (r1 != this) ? this : side(FALSE); if (r1->isReadOnly() || r2->isReadOnly()) { UmlCom::trace(Q3CString("<font face=helvetica>in <i>") + Q3CString(Lex::filename().toAscii().constData()) + "</i> line " + Q3CString().setNum(Lex::line_number()) + " <b>cannot remove relation between classes <i>" + roleType()->name() + "</i> and <i>" + parent()->name() + "</i> because one is read only</b></font><br>"); throw 0; } aRelationKind k; switch (relationKind()) { case anAssociation: k = aDirectionalAssociation; break; case anAggregation: k = aDirectionalAggregation; break; default: k = aDirectionalAggregationByValue; } if (this == r1) set_rel_kind(k); else { UmlRelation * rel = UmlBaseRelation::create(aDirectionalAssociation, (UmlClass *) parent(), roleType()); Q3CString role = roleName(); rel->moveAfter(this); rel->set_Visibility(visibility()); if (!description().isEmpty()) rel->set_Description(description()); if (isReadOnly()) rel->set_isReadOnly(TRUE); if (isVolatile()) rel->set_isVolatile(TRUE); if (isClassMember()) rel->set_isClassMember(TRUE); if (!multiplicity().isEmpty()) rel->set_Multiplicity(multiplicity()); if (!defaultValue().isEmpty()) rel->set_DefaultValue(defaultValue()); if (!stereotype().isEmpty()) rel->set_Stereotype(stereotype()); rel->set_CppDecl(cppDecl()); rel->set_CppVisibility(cppVisibility()); if (cppVirtualInheritance()) rel->set_CppVirtualInheritance(TRUE); if (isCppMutable()) rel->set_isCppMutable(TRUE); UmlOperation * op; UmlOperation * oper; if (((op = getOperation()) != 0) && rel->addGetOperation() && ((oper = rel->getOperation()) != 0)) copy(op, oper); if (((op = setOperation()) != 0) && rel->addSetOperation() && ((oper = rel->getOperation()) != 0)) copy(op, oper); r1->deleteIt(); r2->deleteIt(); rel->set_RoleName(role); } }
bool UmlClass::manage_inherit(ClassContainer * container, const QList<FormalParameterList> & tmplts #ifdef REVERSE , bool libp # ifdef ROUNDTRIP , bool roundtrip, QList<UmlItem *> & expected_order , bool container_roundtrip, QList<UmlItem *> & container_expected_order # endif #endif ) { #ifdef DEBUG_DOUML QLOG_INFO() << name() << "->manage_inherit()\n"; #endif WrapperStr s = Lex::read_word(TRUE); while (s != "{") { #ifdef DEBUG_DOUML QLOG_INFO() << "Class::manage_inherit, visibility : " << s << '\n'; #endif bool is_virtual; if (s == "virtual") { is_virtual = TRUE; s = Lex::read_word(TRUE); } else is_virtual = FALSE; aVisibility v; if (s == "public") { v = PublicVisibility; s = Lex::read_word(TRUE); } else if (s == "protected") { v = ProtectedVisibility; s = Lex::read_word(TRUE); } else if (s == "private") { v = PrivateVisibility; s = Lex::read_word(TRUE); } else v = PrivateVisibility; if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } #ifdef DEBUG_DOUML QLOG_INFO() << "UmlClass::manage_inherit, mother : " << s << '\n'; #endif WrapperStr mother_name = s; UmlTypeSpec mother; WrapperStr typeform; UmlRelation * rel = 0; #ifdef ROUNDTRIP bool is_new = TRUE; #endif container->compute_type(s, mother, typeform); s = Lex::read_word(); if (s == "<") { Lex::mark(); // goes up to the corresponding '>' WrapperStr after_gt; Lex::finish_template(after_gt); s = Lex::read_word(TRUE); if (*s == ':') { // inherits 'T<...>::...' // don't try to solve, use a typedef named 'Type_<n>' based on T<...>::... // creating this typedef if it doesn't yet exist mother_name += "<" + Lex::region(); mother.type = 0; // made below s = Lex::read_word(); } else if (mother.type == 0) { mother_name += "<" + after_gt; } else { // inherits T<...> #ifdef ROUNDTRIP is_new = !roundtrip || ((rel = search_for_inherit(mother.type)) == 0); #endif mother_name += "<" + after_gt; Lex::come_back(); // must add inheritance before setting actuals if ( #ifdef ROUNDTRIP is_new && ( #endif (rel = UmlBaseRelation::create(aRealization, this, mother.type)) == 0 #ifdef ROUNDTRIP ) #endif ) { Lex::warn("cannot inherit <font color =\"red\">" + Lex::quote(mother_name) + " </font>"); #ifdef DEBUG_DOUML QLOG_INFO() << "cannot create <|---\n"; #endif return FALSE; } else if (!get_actuals(mother.type, container, tmplts #ifdef ROUNDTRIP , !is_new #endif )) return FALSE; #ifdef ROUNDTRIP if (! is_new) { if (neq(rel->stereotype(), "bind")) { rel->set_Stereotype("bind"); the_class->set_updated(); } } else #endif rel->set_Stereotype("bind"); s = Lex::read_word(); } } if (mother.type == 0) { mother.type = auxilarily_typedef(mother_name #ifdef REVERSE , libp # ifdef ROUNDTRIP , container_roundtrip , container_expected_order # endif #endif ); if (mother.type == 0) return FALSE; } #ifdef ROUNDTRIP if (rel == 0) is_new = !roundtrip || ((rel = search_for_inherit(mother.type)) == 0); #endif if ((rel == 0) && ((rel = UmlBaseRelation::create(aGeneralisation, this, mother.type)) == 0)) { Lex::warn("cannot inherit <font color =\"red\">" + Lex::quote(mother_name) + " </font>"); #ifdef DEBUG_DOUML QLOG_INFO() << "cannot create <|---\n"; #endif return FALSE; } #ifdef ROUNDTRIP expected_order.append(rel); if (!is_new) { rel->set_usefull(); if (neq(rel->cppDecl(), "${type}")) { rel->set_CppDecl("${type}"); the_class->set_updated(); } if (rel->visibility() != v) { rel->set_Visibility(v); the_class->set_updated(); } if (is_virtual != rel->cppVirtualInheritance()) { rel->set_CppVirtualInheritance(is_virtual); the_class->set_updated(); } } else { #elif defined(REVERSE) Statistic::one_relation_more(); #endif rel->set_CppDecl("${type}"); rel->set_Visibility(v); if (is_virtual) rel->set_CppVirtualInheritance(TRUE); #ifdef ROUNDTRIP } #endif if (s == ",") s = Lex::read_word(); } Lex::unread_word(); // '{' return TRUE; }