Q3CString UmlClass::decl() { Q3CString result; Q3CString close_template; UmlArtifact * cp = associatedArtifact(); Q3CString nasp = ((UmlPackage *) ((cp != 0) ? (UmlItem *) cp : (UmlItem *) this)->package()) ->cppNamespace(); if (! nasp.isEmpty()) { int index = // bypass :: allowing ::a... ((nasp.at(0) == ':') && (nasp != "::")) ? 2 : 0; int index2 = 0; while ((index2 = nasp.find("::", index)) != -1) { result += "namespace " + nasp.mid(index, index2 - index) + " { "; close_template += " } "; index = index2 + 2; } result += "namespace " + nasp.mid(index) + " { "; close_template += " } "; } Q3CString template1; Q3CString template2; get_template_prefixes(template1, template2); if (!template1.isEmpty()) result += template1.left(template1.length() - 1) + ' '; result += cpp_stereotype() + ' '; return result + name() + ';' + close_template + '\n'; }
void UmlClass::write(QTextOStream & f, const UmlTypeSpec & t, bool with_formals, BooL * is_template) { if (t.type != 0) t.type->write(f, with_formals, is_template); else { Q3CString s = CppSettings::type(t.explicit_type); f << s; if (is_template != 0) *is_template = (!s.isEmpty() && (s.at(s.length() - 1) == '>')); } }
bool UmlOperation::new_one(Class * container, const Q3CString & name, const Q3ValueList<FormalParameterList> & tmplts, const Q3CString & oper_templ, UmlTypeSpec & type, Q3CString str_actuals, UmlClass * first_actual_class, Q3CString type_def, aVisibility visibility, bool finalp, bool abstractp, bool staticp, bool nativep, bool strictfp, bool synchronizedp, const Q3CString & array, Q3CString comment, Q3CString description, Q3CString annotation #ifdef ROUNDTRIP , bool roundtrip, Q3PtrList<UmlItem> & expected_order #endif ) { // the "(" was read #ifdef TRACE QLOG_INFO() <<"OPERATION '" << name << "'\n"; #endif UmlClass * cl = container->get_uml(); UmlOperation * op; #ifdef ROUNDTRIP bool may_roundtrip = roundtrip && (!container->from_libp() || (visibility != PrivateVisibility)); UmlTypeSpec return_type; Q3ValueList<UmlParameter> params; Q3ValueList<UmlTypeSpec> exceptions; Q3CString body; if (may_roundtrip) #else if ( # ifdef REVERSE container->from_libp() && # endif (visibility == PrivateVisibility)) #endif op = 0; else { op = UmlBaseOperation::create(cl, name); if (op == 0) { JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); return FALSE; } #ifndef ROUNDTRIP # if defined(REVERSE) Statistic::one_operation_more(); # endif #endif } Q3CString def; #ifdef ROUNDTRIP if (may_roundtrip || (op != 0)) { #else if (op != 0) { op->set_Visibility(visibility); if (staticp) op->set_isClassMember(TRUE); if (abstractp) op->set_isAbstract(TRUE); if (finalp) op->set_isJavaFinal(TRUE); if (synchronizedp) op->set_isJavaSynchronized(TRUE); if (! annotation.isEmpty()) op->set_JavaAnnotations(annotation); #endif def = JavaSettings::operationDef(); int index; if (((index = def.find("${(}")) == -1) || ((index = def.find("${)}", index + 4)) == -1) || ((index = def.find("${throws}", index + 4)) == -1) || (def.find("${body}", index + 9) == -1) || ((index = def.find("${type}")) == -1)) { // use a definition where ${body] is not indented def = " ${comment}${@}${visibility}${final}${static}${abstract}${synchronized}${type} ${name}${(}${)}${throws}${staticnl}{\n${body}}\n"; index = def.find("${type}"); } if (!array.isEmpty()) def.insert(index + 7, (const char *)array); if (nativep) { def.insert(index, "native "); index += 7; // no body int index2 = def.find("${throws}", index+7); if (index2 != -1) { def.resize(index2 + 12); def[index2 + 9] = ';'; def[index2 + 10] = '\n'; } } if (strictfp) { def.insert(index, "strictfp "); index += 9; } if (! oper_templ.isEmpty()) def.insert(index, (const char *)(oper_templ + " ")); if (name == cl->name()) { // constructor, remove useless ${} if ((index = def.find("${static}")) != -1) def.remove(index, 9); if ((index = def.find("${type}")) != -1) def.remove(index, (((const char *) def)[index + 7] == ' ') ? 8 : 7); if ((index = def.find("${final}")) != -1) def.remove(index, 8); if ((index = def.find("${abstract}")) != -1) def.remove(index, 11); } if (type.type != 0) { UmlClass::manage_generic(def, type, str_actuals, "${type}"); #ifdef ROUNDTRIP return_type = type; #else op->set_ReturnType(type); #endif } else if (first_actual_class != 0) { #ifndef ROUNDTRIP UmlTypeSpec return_type; #endif return_type.type = first_actual_class; def.replace(def.find("${type}"), 7, type_def); #ifndef ROUNDTRIP op->set_ReturnType(return_type); #endif } else if (!type.explicit_type.isEmpty()) { // not a contructor #ifdef ROUNDTRIP return_type = type; #else op->set_ReturnType(type); #endif } } // parameters unsigned rank = 0; UmlParameter param; #ifdef ROUNDTRIP if (may_roundtrip) while (read_param(container, rank++, tmplts, param, def, FALSE)) params.append(param); else #endif while (read_param(container, rank, tmplts, param, def, op == 0)) { if ((op != 0) && ! op->addParameter(rank, param)) { JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add param <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); # ifdef TRACE QLOG_INFO() <<"ERROR cannot add param '" << param.name << "' type '" << param.type.Type() << '\n'; # endif return FALSE; } rank += 1; } Q3CString s = Lex::read_word(); if (!s.isEmpty() && (*((const char *) s) == '[')) { #ifdef ROUNDTRIP if (may_roundtrip) #else if (op != 0) #endif // do not place it at the same place def.insert(def.find("${type}") + 7, (const char *)s); s = Lex::read_word(); } if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } if (s == "throws") { // throws rank = 0; for (;;) { if ((s = Lex::read_word()).isEmpty()) { Lex::premature_eof(); return FALSE; } #ifdef ROUNDTRIP if (may_roundtrip) { UmlTypeSpec typespec; container->compute_type(s, typespec, tmplts); exceptions.append(typespec); } else #endif if (op != 0) { UmlTypeSpec typespec; container->compute_type(s, typespec, tmplts); if (! op->addException(rank++, typespec)) { # ifdef TRACE QLOG_INFO() <<"cannot add exception " << s << '\n'; # endif return FALSE; } } if (((s = Lex::read_word()) == "{") || (s == ";")) break; if (s != ",") { Lex::error_near(s, " ',' expected"); return FALSE; } } } // definition if (abstractp || nativep || (cl->stereotype() == "interface") || (cl->stereotype() == "@interface")) { if ((s == "default") && (cl->stereotype() == "@interface")) { int index = def.find("${)}"); Lex::mark(); s = Lex::read_word(); if (s == "{") { int level = 1; char c; for (;;) { if ((c = Lex::read_word_bis()) == 0) return FALSE; else if (c == '{') level += 1; else if ((c == '}') && (--level == 0)) break; } s = Lex::region(); } def.insert(index + 4, (const char *)(" default" + s)); s = Lex::read_word(); } if (s != ";") { Lex::error_near(s, " ';' expected"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP if ((op != 0) && !container->from_libp()) op->set_JavaBody(0); # endif #endif } else if (s != "{") { Lex::error_near(s, " '{' expected"); return FALSE; } else { Lex::mark(); // goto the end of the body #ifndef ROUNDTRIP Q3CString body; #endif int level = 1; // '{' already read char c; for (;;) { if ((c = Lex::read_word_bis()) == 0) return FALSE; else if (c == '{') level += 1; else if ((c == '}') && (--level == 0)) break; } #ifdef REVERSE if ( # ifdef ROUNDTRIP may_roundtrip || (op != 0) # else (op != 0) && !container->from_libp() # endif ) { body = Lex::region(); body.truncate(body.length() - 1); // remove } // remove fist \n if (*((const char *) body) == '\n') body.remove(0, 1); // remove last spaces and tabs int ln = body.length(); while (ln && ((body[ln - 1] == ' ') || (body[ln - 1] == '\t'))) ln -= 1; body.truncate(ln); if (!body.isEmpty() && (body[ln - 1] != '\n')) body += "\n"; # ifndef ROUNDTRIP op->set_JavaBody(body); op->set_JavaContextualBodyIndent(FALSE); # endif } #endif } #ifdef ROUNDTRIP if (may_roundtrip) { if (((op = already_exist_from_id(container, body)) != 0) || ((op = already_exist(container, name, params)) != 0)) { // update already existing operation op->set_usefull(); { // remove \r in case of preserve body Q3CString current_body = op->javaBody(); int index = 0; while ((index = current_body.find('\r', index)) != -1) current_body.remove(index, 1); if (nequal(current_body, body)) { container->set_updated(); op->set_JavaBody(body); op->set_JavaContextualBodyIndent(FALSE); } } if (op->visibility() != visibility) { container->set_updated(); op->set_Visibility(visibility); } if (op->isClassMember() != staticp) { container->set_updated(); op->set_isClassMember(staticp); } if (op->isAbstract() != abstractp) { container->set_updated(); op->set_isAbstract(abstractp); } if (op->isJavaFinal() != finalp) { container->set_updated(); op->set_isJavaFinal(finalp); } if (op->isJavaSynchronized() != synchronizedp) { container->set_updated(); op->set_isJavaSynchronized(synchronizedp); } if (nequal(op->javaAnnotations(), annotation)) { container->set_updated(); op->set_JavaAnnotations(annotation); } if (!op->returnType().equal(return_type)) { container->set_updated(); op->set_ReturnType(return_type); } Q3ValueList<UmlParameter>::Iterator itp1; const Q3ValueList<UmlParameter> old_params = op->params(); Q3ValueList<UmlParameter>::ConstIterator itp2; for (rank = 0, itp1 = params.begin(), itp2 = old_params.begin(); (itp1 != params.end()) && (itp2 != old_params.end()); ++itp1, ++itp2, rank += 1) { UmlParameter & p1 = *itp1; const UmlParameter & p2 = *itp2; if ((p1.name != p2.name) || nequal(p1.default_value, p2.default_value) || !p1.type.equal(p2.type)) { if (p1.dir != InputDirection) p1.dir = p2.dir; op->replaceParameter(rank, p1); container->set_updated(); } else if ((p1.dir == InputDirection) && (p2.dir != InputDirection)) { op->replaceParameter(rank, p1); container->set_updated(); } } if (itp1 != params.end()) { // have missing params container->set_updated(); do { op->addParameter(rank, *itp1); itp1++; rank += 1; } while (itp1 != params.end()); } else if (itp2 != old_params.end()) { // have extra params container->set_updated(); do { op->removeParameter(rank); itp2++; } while (itp2 != old_params.end()); } Q3ValueList<UmlTypeSpec>::ConstIterator ite1; const Q3ValueList<UmlTypeSpec> old_exceptions = op->exceptions(); Q3ValueList<UmlTypeSpec>::ConstIterator ite2; for (rank = 0, ite1 = exceptions.begin(), ite2 = old_exceptions.begin(); (ite1 != exceptions.end()) && (ite2 != old_exceptions.end()); ++ite1, ++ite2, rank += 1) { const UmlTypeSpec & e1 = *ite1; if (!e1.equal(*ite2)) { op->replaceException(rank, e1); container->set_updated(); } } if (ite1 != exceptions.end()) { // have missing exceptions container->set_updated(); do { op->addException(rank, *ite1); ite1++; rank += 1; } while (ite1 != exceptions.end()); } else if (ite2 != old_exceptions.end()) { // have extra exceptions container->set_updated(); do { op->removeException(rank); ite2++; } while (ite2 != old_exceptions.end()); } if (neq(def, op->javaDecl())) { container->set_updated(); op->set_JavaDecl(def); } Lex::clear_comments(); // params & body comments Lex::finish_line(); if (def.find("${description}") != -1) { if (nequal(op->description(), description)) { container->set_updated(); op->set_Description(description); } } else if (nequal(op->description(), Lex::simplify_comment(comment))) { op->set_Description(comment); // comment was set container->set_updated(); } expected_order.append(op); return TRUE; } // operation doesn't yet exist container->set_updated(); op = UmlBaseOperation::create(cl, name); if (op == 0) { JavaCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); throw 0; } expected_order.append(op); Q3ValueList<UmlParameter>::ConstIterator itp; for (rank = 0, itp = params.begin(); itp != params.end(); ++itp) op->addParameter(rank++, *itp); Q3ValueList<UmlTypeSpec>::ConstIterator ite; for (rank = 0, ite = exceptions.begin(); ite != exceptions.end(); ++ite) op->addException(rank++, *ite); } if (op != 0) { op->set_JavaContextualBodyIndent(FALSE); op->set_Visibility(visibility); if (staticp) op->set_isClassMember(TRUE); if (abstractp) op->set_isAbstract(TRUE); if (finalp) op->set_isJavaFinal(TRUE); if (synchronizedp) op->set_isJavaSynchronized(TRUE); if (! annotation.isEmpty()) op->set_JavaAnnotations(annotation); op->set_JavaBody(body); op->set_ReturnType(return_type); if (def != JavaSettings::operationDef()) op->set_JavaDecl(def); } #else if ((op != 0) && (def != JavaSettings::operationDef())) op->set_JavaDecl(def); #endif Lex::clear_comments(); // params & body comments Lex::finish_line(); if (!comment.isEmpty()) if (op != 0) op->set_Description((def.find("${description}") != -1) ? description : Lex::simplify_comment(comment)); return TRUE; } bool UmlOperation::read_param(Class * container, unsigned rank, const Q3ValueList<FormalParameterList> & tmplts, UmlParameter & param, Q3CString & def, bool bypass) { #ifdef TRACE QLOG_INFO() <<"UmlOperation::manage_param " << rank << "\n"; #endif bool finalp = FALSE; bool in = FALSE; bool ellipsis = FALSE; Q3CString array; bool type_read = FALSE; Q3ValueList<UmlTypeSpec> actuals; Q3CString str_actuals; Q3CString annotation; param.name = param.default_value = 0; Q3CString s = Lex::read_word(); #ifdef TRACE QLOG_INFO() <<"commence par " << s << '\n'; #endif if (s == ")") return FALSE; for (;;) { if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else if (s == "final") finalp = TRUE; else if ((s == "void") || (s == "byte") || (s == "char") || (s == "short") || (s == "int") || (s == "long") || (s == "float") || (s == "double")) { if (type_read) { Lex::error_near(s); return FALSE; } param.type.type = 0; param.type.explicit_type = s; type_read = TRUE; in = TRUE; } else if ((s == ")") || (s == ",")) { if (param.name.isEmpty() && !type_read) { Lex::error_near(s); return FALSE; } if (s == ")") Lex::unread_word(s); if (! bypass) { param.dir = (finalp || in) ? InputDirection : InputOutputDirection; Q3CString s; if (rank != 0) s = ", "; if (! annotation.isEmpty()) s += annotation + " "; if (finalp) s += "final "; if ((param.type.type != 0) && !param.type.explicit_type.isEmpty()) s += param.type.explicit_type; else { s += "${t"; s += Q3CString().setNum(rank); s += "}"; if (param.type.type != 0) s += str_actuals; } s += array; s += (ellipsis) ? " ... ${p": " ${p"; s += Q3CString().setNum(rank); s += "}"; def.insert(def.find("${)}"), // cannot be -1 (const char *)s); } return TRUE; } else if (Lex::identifierp(s)) { if (!type_read) { while (s.at(s.length() - 1) == '.') { // type on several lines, managed in this case Q3CString s2 = Lex::read_word(); if (Lex::identifierp(s2)) s += s2; else { Lex::error_near(s, " identifier expected"); return FALSE; } } #ifdef TRACE QLOG_INFO() <<"type = '" << s << "...'\n"; #endif if (! bypass) { Q3CString dummy; container->read_type(param.type, 0, tmplts, 0, str_actuals, s, 0, dummy, dummy); if (param.type.explicit_type == "String") // at least for it ! in = TRUE; } else Lex::bypass_type(s); type_read = TRUE; } else if (param.name.isEmpty()) { if (s == "...") ellipsis = TRUE; else { param.name = s; #ifdef TRACE QLOG_INFO() <<"name = '" << param.name << "'\n"; #endif } } else { Lex::error_near(s); #ifdef TRACE QLOG_INFO() <<"ERROR '" << s << "' alors qu a deja le type et le nom '" << param.name << "'\n"; #endif return FALSE; } } else if (*((const char *) s) == '@') annotation = s; else if (*((const char *) s) == '[') { in = FALSE; array = s; } else { Lex::error_near(s); #ifdef TRACE QLOG_INFO() <<"ERROR : '" << s << "'\n"; #endif return FALSE; } s = Lex::read_word(); } }
bool UmlAttribute::new_one(Class * container, const Q3CString & name, const Q3CString & type, const Q3CString & modifier, const Q3CString & pretype, const Q3CString & array, aVisibility visibility, bool staticp, bool constp, bool typenamep, bool mutablep, bool volatilep, const Q3CString & bitfield, const Q3CString & value, Q3CString comment, Q3CString description #ifdef ROUNDTRIP , bool roundtrip, Q3PtrList<UmlItem> & expected_order #endif ) { #ifdef DEBUG_BOUML cout << "ATTRIBUTE '" << name << "' type '" << type << "' modifier '" << modifier << "' array '" << array << "'\n"; #endif if ( #ifdef REVERSE container->from_libp() && #endif (visibility == PrivateVisibility)) { Lex::finish_line(); Lex::clear_comments(); return TRUE; } UmlClass * cl = container->get_uml(); UmlAttribute * at; #ifdef ROUNDTRIP bool created; if (!roundtrip || ((at = search_attr(cl, name)) == 0)) { #endif at = UmlBaseAttribute::create(cl, name); if (at == 0) { UmlCom::trace(Q3CString("<font face=helvetica><b>cannot add attribute <i>") + name + "</i> in <i>" + Q3CString(cl->name()) + "</i></b></font><br><hr>"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP Statistic::one_attribute_more(); # else if (roundtrip) container->set_updated(); created = TRUE; } else created = FALSE; # endif #endif Lex::finish_line(); comment = Lex::get_comments(comment); description = Lex::get_description(description); bool pfunc = (type.find('$') != -1); UmlTypeSpec typespec; Q3CString typeform; Q3CString stereotype; if (! pfunc) { typeform = (pretype.isEmpty()) ? Q3CString("${type}") : pretype + " ${type}"; container->compute_type(type, typespec, typeform); } else { typespec.explicit_type = type.simplifyWhiteSpace(); int index = typespec.explicit_type.find("${name}"); if (index != -1) typespec.explicit_type.remove(index, 7); } Q3CString decl = CppSettings::attributeDecl(""); int index = decl.find("${type}"); if ((index == -1) || (decl.find("${const}") == -1) || (decl.find("${name}") == -1) || (decl.find("${mutable}") == -1) || (decl.find("${volatile}") == -1) || (decl.find(';') == -1)) { decl = " ${comment}${static}${mutable}${volatile}${const}${type} ${name}${value};"; index = decl.find("${type}"); } if (pfunc) decl.replace(index, decl.find("${name}") + 7 - index, type); else { if (!modifier.isEmpty()) decl.insert(index + 7, (const char*)(Q3CString(" ") + modifier)); if (typeform != "${type}") decl.replace(index, 7, typeform); else if (typespec.type == 0) { Q3CString t = typespec.explicit_type; int index2; if (!t.isEmpty() && (t.at(t.length() - 1) == '>') && ((index2 = t.find('<')) > 0)) { stereotype = t.left(index2); typespec.explicit_type = // may be a,b ... t.mid(index2 + 1, t.length() - 2 - index2); decl.replace(index, 7, "${stereotype}<${type}>"); } } if (!array.isEmpty()) decl.insert(decl.find("${name}") + 7, "${multiplicity}"); if (!bitfield.isEmpty()) decl.insert(decl.find(';'), (const char *)(Q3CString(" : ") + bitfield)); } if (typenamep) { int index = decl.find("${const}") + 8; // find cannot return -1 int index2 = decl.find("${mutable}") + 10; // find cannot return -1 int index3 = decl.find("${volatile}") + 11; // find cannot return -1 if (index2 > index) index = index2; if (index3 > index) index = index3; decl.insert(index, "typename "); } if (!value.isEmpty() && ((index = decl.find("${value}")) != -1)) decl.insert(index + 2, "h_"); #ifdef ROUNDTRIP if (roundtrip && !created) { if (decl.find("${description}") != -1) { if (nequal(at->description(), description)) { at->set_Description(description); container->set_updated(); } } else if (nequal(at->description(), Lex::simplify_comment(comment))) { at->set_Description(comment); // comment was set container->set_updated(); } if (at->isReadOnly() != constp) { at->set_isReadOnly(constp); container->set_updated(); } if (at->isCppMutable() != mutablep) { at->set_isCppMutable(mutablep); container->set_updated(); } if (at->isVolatile() != volatilep) { at->set_isVolatile(volatilep); container->set_updated(); } if (at->isClassMember() != staticp) { at->set_isClassMember(staticp); container->set_updated(); } if (neq(at->multiplicity(), array)) { at->set_Multiplicity(array); container->set_updated(); } if (!staticp) { Q3CString v = at->defaultValue(); if (!v.isEmpty() && (((const char *) v)[0] == '=')) v = v.mid(1); if (nequal(v, value)) { at->set_DefaultValue(value); container->set_updated(); } } if (at->visibility() != visibility) { at->set_Visibility(visibility); container->set_updated(); } if (!stereotype.isEmpty()) { Q3CString cppst; if (!at->stereotype().isEmpty()) cppst = CppSettings::relationAttributeStereotype(at->stereotype()); if (cppst != stereotype) { at->set_Stereotype(stereotype); container->set_updated(); } } if (!at->type().equal(typespec)) { at->set_Type(typespec); container->set_updated(); } if (neq(at->cppDecl(), decl)) { at->set_CppDecl(decl); container->set_updated(); } at->set_usefull(); expected_order.append(at); } else { #endif if (!comment.isEmpty()) at->set_Description((decl.find("${description}") != -1) ? description : Lex::simplify_comment(comment)); if (constp) at->set_isReadOnly(TRUE); if (mutablep) at->set_isCppMutable(TRUE); if (volatilep) at->set_isVolatile(TRUE); if (staticp) at->set_isClassMember(TRUE); if (!array.isEmpty()) at->set_Multiplicity(array); if (! value.isEmpty()) at->set_DefaultValue(value); at->set_Visibility(visibility); if (! stereotype.isEmpty()) at->set_Stereotype(stereotype); at->set_Type(typespec); at->set_CppDecl(decl); #ifdef ROUNDTRIP if (roundtrip) expected_order.append(at); } #endif return TRUE; }
void UmlRelation::generate(QTextOStream & f, const Q3CString & cl_stereotype, Q3CString indent) { switch (relationKind()) { case aDependency: case aGeneralisation: case aRealization: break; default: if (!javaDecl().isEmpty()) { if (cl_stereotype == "enum_pattern") { write_trace_header(); UmlCom::trace(" <font color=\"red\"><b>an <i>enum_pattern</i> cannot have relation</b></font><br>"); incr_warning(); return; } const char * p = javaDecl(); const char * pp = 0; Q3CString s; while ((*p == ' ') || (*p == '\t')) indent += *p++; f << indent; for (;;) { if (*p == 0) { if (pp == 0) break; // comment management done p = pp; pp = 0; if (*p == 0) break; f << indent; } if (*p == '\n') { f << *p++; if (*p) f << indent; } else if (*p == '@') manage_alias(p, f); else if (*p != '$') f << *p++; else if (!strncmp(p, "${comment}", 10)) manage_comment(p, pp, JavaSettings::isGenerateJavadocStyleComment()); else if (!strncmp(p, "${description}", 14)) manage_description(p, pp); else if (!strncmp(p, "${visibility}", 13)) { p += 13; generate_visibility(f, cl_stereotype); } else if (!strncmp(p, "${static}", 9)) { p += 9; if (isClassMember()) f << "static "; } else if (!strncmp(p, "${final}", 8)) { p += 8; if (isReadOnly()) f << "final "; } else if (!strncmp(p, "${transient}", 12)) { p += 12; if (isJavaTransient()) f << "transient "; } else if (!strncmp(p, "${volatile}", 11)) { p += 11; if (isVolatile()) f << "volatile "; } else if (!strncmp(p, "${type}", 7)) { p += 7; roleType()->write(f); } else if (!strncmp(p, "${stereotype}", 13)) { p += 13; f << JavaSettings::relationAttributeStereotype(stereotype()); } else if (!strncmp(p, "${name}", 7)) { p += 7; f << roleName(); } else if (!strncmp(p, "${inverse_name}", 15)) { p += 15; switch (relationKind()) { case anAssociation: case anAggregation: case anAggregationByValue: f << side(side(TRUE) != this)->roleName(); default: break; } } else if (!strncmp(p, "${multiplicity}", 15)) { p += 15; Q3CString m = multiplicity(); if (*m != '[') f << "[]"; else { for (unsigned index = 0; index != m.length(); index += 1) { switch (m.at(index)) { case '[': f << '['; break; case ']': f << ']'; default: break; } } } } else if (!strncmp(p, "${value}", 8)) { if (!defaultValue().isEmpty()) { if (need_equal(p, defaultValue())) f << " = "; f << defaultValue(); } p += 8; } else if (!strncmp(p, "${association}", 14)) { p += 14; UmlClass::write(f, association()); } else if (!strncmp(p, "${@}", 4)) { p += 4; if (pp != 0) f << "${@}"; else if (! javaAnnotations().isEmpty()) { pp =p; p = javaAnnotations(); } } else // strange f << *p++; } f << '\n'; } } }
void ClassContainer::compute_type(Q3CString type, UmlTypeSpec & typespec, Q3CString & typeform, bool get_first_template_actual, const Q3ValueList<FormalParameterList> & tmplts) { typespec.type = 0; typespec.explicit_type = 0; if (!strncmp((const char *) type, "struct ", 7) || !strncmp((const char *) type, "union ", 6) || !strncmp((const char *) type, "enum ", 5)) { typespec.explicit_type = "<complex type>"; typeform = type; return; } int index; if (get_first_template_actual && ((index = type.find('<')) != -1)) { type = Lex::normalize(type); index = type.find('<'); const char * p = type; if (strncmp(p + index + 1, "const ", 6) == 0) index += 6; // look at each actual in <> unsigned level = 1; int index2; Q3CString tf1; Q3CString t1; for (;;) { // earch for the current arg end for (index2 = index + 1; p[index2]; index2 += 1) { char c = p[index2]; if ((c == ',') || (c == '*') || (c == '[') || (c == '&')) { if (level == 1) break; } else if (c == '<') level += 1; else if ((c == '>') && (--level == 0)) break; } if (p[index2]) { Q3CString tf = type.left(index + 1) + typeform + type.mid(index2); Q3CString t = type.mid(index + 1, index2 - index - 1).stripWhiteSpace(); #ifdef DEBUG_BOUML cout << "typeform '" << tf << "' type '" << t << "'\n"; #endif UmlTypeSpec ts; Q3CString normalized = Lex::normalize(t); if (!find_type(normalized, ts) && (Namespace::current().isEmpty() || (normalized.at(0) == ':') || !find_type("::" + normalized, ts))) { if (get_first_template_actual) { get_first_template_actual = FALSE; tf1 = tf; t1 = t; } index = index2; } else { // find a class typeform = tf; type = t; typespec.type = ts.type; break; } } else if (!get_first_template_actual) { // has first actual typeform = tf1; type = t1; break; } else { typespec.explicit_type = type; return; } } } if (! tmplts.isEmpty()) { Q3ValueList<FormalParameterList>::ConstIterator it1; for (it1 = tmplts.begin(); it1 != tmplts.end(); ++it1) { FormalParameterList::ConstIterator it2; for (it2 = (*it1).begin(); it2 != (*it1).end(); ++it2) { if ((*it2).name() == type) { typespec.type = 0; typespec.explicit_type = type; return; } } } } Q3CString normalized; if (typespec.type == 0) { normalized = Lex::normalize(type); if (!find_type(normalized, typespec) && (Namespace::current().isEmpty() || (normalized.at(0) == ':') || !find_type("::" + normalized, typespec))) { typespec.explicit_type = CppSettings::umlType(type); if (typespec.explicit_type.isEmpty()) { // search for equivalent forms if (type == "long int") typespec.explicit_type = CppSettings::umlType("long"); else if (type == "long") typespec.explicit_type = CppSettings::umlType("long int"); else if (type == "unsigned long int") typespec.explicit_type = CppSettings::umlType("unsigned long"); else if (type == "unsigned long") typespec.explicit_type = CppSettings::umlType("unsigned long int"); else if (type == "unsigned") typespec.explicit_type = CppSettings::umlType("unsigned int"); else if (type == "unsigned int") typespec.explicit_type = CppSettings::umlType("unsigned"); else if ((type == "signed") || (type == "signed int")) typespec.explicit_type = CppSettings::umlType("int"); } if (typespec.explicit_type.isEmpty()) { typespec.explicit_type = type; /* if (!Lex::identifierp(type, TRUE)) typespec.explicit_type = type; else { Q3CString t = type; while ((index = t.find(':')) == 0) t = t.mid(1); ClassContainer * cc = Package::unknown(); while (index != -1) { if ((cc = cc->declare_if_needed(t.left(index))) == 0) { typespec.explicit_type = type; return; } while (t[index] == ':') index += 1; t = t.mid(index); index = t.find(':'); } if (((cc = cc->declare_if_needed(t)) == 0) || ((typespec.type = ((Class *) cc)->get_uml()) == 0)) typespec.explicit_type = type; }*/ } typespec.type = 0; } } if ((typespec.type != 0) && !typespec.type->formals().isEmpty() && (type.at(type.length() - 1) == '>') && (!typespec.type->inside_its_definition() || !typespec.type->is_itself((normalized.isEmpty()) ? Lex::normalize(type) : normalized))) { typespec.type = 0; typespec.explicit_type = type; } }
Q3CString Lex::normalize(const Q3CString & s) { int index = s.find('<'); if (index == -1) return s; Q3CString r; const char * p = s; index = 0; for (;;) { char c = *p++; switch (c) { case 0: return r; case '<': if (!r.isEmpty() && (r.at(r.length() - 1) == ' ')) r.truncate(r.length() - 1); r += '<'; break; case '>': if (!r.isEmpty() && (r.at(r.length() - 1) == '>')) r += " >"; else r += '>'; break; case '/': if (*p == '/') { // comment p += 1; do p += 1; while (*p && (*p != '\n')); } else if (*p == '*') { /* comment */ p += 1; do p += 1; while (*p && ((*p != '*') || (p[1] != '/'))); p += 2; } else { if (!r.isEmpty() && (r.at(r.length() - 1) == ' ')) r.truncate(r.length() - 1); } break; case '#': do { if (*++p == '\\') p += 2; else if ((*p == '/') && (p[1] == '*')) { /* comment */ p += 1; do p += 1; while (*p && ((*p != '*') || (p[1] != '/'))); p += 2; } } while (*p && (*p != '\n')); break; case '"': if (!r.isEmpty() && (r.at(r.length() - 1) == '"') && (p[-2] != '"')) r += ' '; do { if (*++p == '\\') p += 2; } while (*p && (*p != '"')); break; case '\'': if (!r.isEmpty() && (r.at(r.length() - 1) == ' ')) r.truncate(r.length() - 1); do { if (*++p == '\\') p += 2; } while (*p && (*p != '\'')); break; case ':': if (!r.isEmpty() && (p[-2] <= ' ')) r += " :"; else r += ':'; break; default: if (c > ' ') { if (::identifierp(c)) { if (!r.isEmpty() && ::identifierp(r.at(r.length() - 1))) r += ' '; r += c; while ((*p == ':') || ::identifierp(*p)) r += *p++; } else r += c; } } } return r; }
void UmlClass::write(QTextOStream & f, bool with_formals, BooL * is_template, const Q3ValueList<UmlActualParameter> & actuals) { if (context.findRef(this) == -1) { if (parent()->kind() == aClass) { if (context.findRef((UmlClass *) parent()) == -1) { // parent cannot have formals, but may have actuals ((UmlClass *) parent())->write(f, FALSE, 0, actuals); f << "::"; } } else { UmlArtifact * cp = associatedArtifact(); Q3CString nasp = ((UmlPackage *) ((cp != 0) ? (UmlItem *) cp : (UmlItem *) this)->package()) ->cppNamespace(); if (CppSettings::isForceNamespacePrefixGeneration() || (nasp != UmlArtifact::generation_package()->cppNamespace())) f << nasp << "::"; } } Q3CString s; if (isCppExternal()) { s = cppDecl(); int index = s.find('\n'); s = (index == -1) ? s.stripWhiteSpace() : s.left(index).stripWhiteSpace(); if ((index = s.find("${name}")) != -1) s.replace(index, 7, name()); else if ((index = s.find("${Name}")) != -1) s.replace(index, 7, capitalize(name())); else if ((index = s.find("${NAME}")) != -1) s.replace(index, 7, name().upper()); else if ((index = s.find("${nAME}")) != -1) s.replace(index, 7, name().lower()); } else s = name(); // true_name if (! s.isEmpty()){ f << s; if (is_template != 0) *is_template = (s.at(s.length() - 1) == '>'); } else if (is_template != 0) *is_template = FALSE; if (with_formals) { Q3ValueList<UmlFormalParameter> formals = this->formals(); if (! formals.isEmpty()) { const char * sep = "<"; Q3ValueList<UmlFormalParameter>::ConstIterator it; for (it = formals.begin(); it != formals.end(); ++it) { f << sep << (*it).name(); sep = ", "; } f << '>'; if (is_template != 0) *is_template = TRUE; } } else if (!actuals.isEmpty()) { Q3ValueList<UmlActualParameter>::ConstIterator ita; BooL need_space = FALSE; bool used = FALSE; for (ita = actuals.begin(); ita != actuals.end(); ++ita) { if ((*ita).superClass() == this) { used = TRUE; (*ita).generate(f, need_space); } } if (used) { if (need_space) f << " >"; else f << '>'; if (is_template != 0) *is_template = TRUE; } } }