UmlClass * UmlClass::addMetaclass(WrapperStr mclname, const char * mclpath) { UmlPackage * pack = (UmlPackage *) parent()->parent(); // is a package const Q3PtrVector<UmlItem> ch = pack->children(); unsigned n = ch.size(); UmlClass * r = 0; for (unsigned i = 0; i != n; i += 1) { UmlItem * x = ch[i]; if ((x->kind() == aClassView) && !strncmp(x->name(), "meta classes", 12) && ((r = UmlClass::create(x, mclname)) != 0)) break; } if (r == 0) { WrapperStr s = "meta classes"; UmlItem * v = 0; while ((v = UmlClassView::create(pack, s)) == 0) s += "_"; r = UmlClass::create(v, mclname); } r->set_Stereotype("metaclass"); if (mclpath != 0) r->set_PropertyValue("metaclassPath", mclpath); return r; }
bool UmlClass::replaceType(UmlTypeSpec & t, Q3CString & target_id, const Q3CString & ts) { UmlClass * cl = (UmlClass *) findItem(target_id, aClass); bool result = FALSE; if (cl != 0) { int index = 0; const Q3CString & s = cl->name(); unsigned ln1 = s.length(); unsigned ln2 = ts.length(); while ((index = t.explicit_type.find(s, index)) != -1) { if (((index == 0) || isSep(((const char *) t.explicit_type)[index - 1])) && isSep(((const char *) t.explicit_type)[index + (int) ln1])) { t.explicit_type.replace((unsigned) index, ln1, ts); index += ln2; result = TRUE; } else index += 1; } } if (result) { target_id = t.explicit_type; t.explicit_type = 0; t.type = cl; } return result; }
void UmlJunctionPseudoState::generate(UmlClass * machine, UmlClass * anystate, UmlState * state) { // create an operation because a priori shared if (_oper.isEmpty()) _oper.sprintf("_junction%d", ++_rank); UmlClass * cl = state->assocClass(); UmlOperation * junction; if (((junction = (UmlOperation *) cl->getChild(anOperation, _oper)) == 0) && ((junction = UmlBaseOperation::create(cl, _oper)) == 0)) { UmlCom::trace("Error : cannot create operation '" + _oper + "' in class '" + cl->name() + "'<br>"); throw 0; } junction->defaultDef(); junction->setComment("implement a junction, through an operation because shared, internal"); junction->setType("void", "${type}"); junction->addParam(0, InputOutputDirection, "stm", machine); junction->setParams("${t0} & ${p0}"); Q3CString body; const Q3PtrVector<UmlItem> ch = children(); Q3PtrList<UmlTransition> trs; unsigned index; for (index = 0; index != ch.count(); index += 1) if (ch[index]->kind() == aTransition) // theo mandatory trs.append((UmlTransition *) ch[index]); UmlTransition::generate(trs, machine, anystate, state, body, " ", FALSE); junction->set_CppBody(body); }
bool UmlAttribute::new_one(Class * container, Q3CString name, aVisibility visibility, bool constp, bool staticp, const Q3CString & value, Q3CString comment, Q3CString description) { #ifdef TRACE cout << "ATTRIBUTE '" << name << "'\n"; #endif #ifndef REVERSE if (visibility == PrivateVisibility) return TRUE; #endif if (((const char *) name)[0] == '$') name = name.mid(1); UmlClass * cl = container->get_uml(); UmlAttribute * at = UmlBaseAttribute::create(cl, name); if (at == 0) { PhpCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add attribute <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); return FALSE; } #ifdef REVERSE Statistic::one_attribute_more(); #endif if (!comment.isEmpty()) { Q3CString s = (at->phpDecl().find("${description}") != -1) ? description : comment; UmlTypeSpec t; int index; if (! (t.explicit_type = value_of(s, "@var", index)).isEmpty()) { at->set_Type(t); s.replace(index, t.explicit_type.length(), "${type}"); } at->set_Description(s); } if (constp) at->set_isReadOnly(TRUE); if (staticp) at->set_isClassMember(TRUE); if (! value.isEmpty()) at->set_DefaultValue(value); at->set_Visibility(visibility); return TRUE; }
void UmlClass::importInstantiate(File & f) { if (scanning) { f.skipNextForm(); return; } f.read("("); f.read("object"); f.read("Instantiation_Relationship"); Q3CString id; Q3CString ste; Q3CString doc; Q3Dict<Q3CString> prop; Q3CString s2; int k; do { k = f.readDefinitionBeginning(s2, id, ste, doc, prop); } while (id.isEmpty()); for (;;) { if (k == ATOM) { if (s2 == "quidu") break; f.skipNextForm(); k = f.read(s2); } else f.syntaxError(s2); } if (f.read(s2) != STRING) f.syntaxError(s2, "quidu value"); UmlClass * target = (UmlClass *) findItem(s2, aClass); if (target != 0) { UmlRelation * r = UmlRelation::create(aRealization, this, target); if (r == 0) UmlCom::trace("<br>cannot create aRealization from '" + fullName() + "' to '" + target->fullName() + "'"); else { newItem(r, id); if (!ste.isEmpty()) r->set_Stereotype(ste); if (!doc.isEmpty()) r->set_Description(doc); r->setProperties(prop); } } f.skipBlock(); }
void UmlItem::write_stereotyped(FileOut & out) { QMap<QString, Q3PtrList<UmlItem> >::Iterator it; for (it = _stereotypes.begin(); it != _stereotypes.end(); ++it) { const char * st = it.key(); UmlClass * cl = UmlClass::findStereotype(it.key(), TRUE); if (cl != 0) { Q3ValueList<WrapperStr> extended; cl->get_extended(extended); Q3PtrList<UmlItem> & l = it.data(); UmlItem * elt; for (elt = l.first(); elt != 0; elt = l.next()) { out << "\t<" << st; out.id_prefix(elt, "STELT_"); const Q3Dict<WrapperStr> props = elt->properties(); Q3DictIterator<WrapperStr> itp(props); while (itp.current()) { QString k = itp.currentKey(); if (k.contains(':') == 2) { out << " "; out.quote((const char *)k.mid(k.findRev(':') + 1)); //[jasa] ambiguous call out << "=\""; out.quote((const char *)*itp.current()); out << '"'; } ++itp; } Q3ValueList<WrapperStr>::Iterator iter_extended; for (iter_extended = extended.begin(); iter_extended != extended.end(); ++iter_extended) { WrapperStr vr = "base_" + *iter_extended; out.ref(elt, vr); } out << "/>\n"; elt->unload(); } } } }
void UmlClass::generate() { if (! flat) { int n = classes.size(); for (int i = 0; i != n; i += 1) { UmlClass * cl = (UmlClass *)classes.elementAt(i); cl->html(); } } }
bool UmlClass::isAppliedStereotype(Token & tk, WrapperStr & prof_st, Q3ValueList<WrapperStr> & base_v) { static Q3Dict<WrapperStr> stereotypes; static Q3Dict<Q3ValueList<WrapperStr> > bases; WrapperStr s = tk.what(); WrapperStr * st = stereotypes[s]; if (st != 0) { prof_st = *st; base_v = *bases[s]; return TRUE; } base_v.clear(); if (tk.xmiType().isEmpty() && (getFct(tk) == 0)) { int index = s.find(':'); if ((index != -1) && ((index != 3) || ((s.left(3) != "uml") && (s.left(3) != "xmi")))) { UmlClass * cl = findStereotype(s, FALSE); if (cl != 0) { const Q3PtrVector<UmlItem> ch = cl->children(); unsigned n = ch.size(); for (unsigned i = 0; i != n; i += 1) { UmlItem * x = ch[i]; if ((x->kind() == aRelation) && (((UmlRelation *) x)->relationKind() == aDirectionalAssociation) && (((UmlRelation *) x)->roleType()->stereotype() == "metaclass")) base_v.append("base_" + ((UmlRelation *) x)->roleType()->name().lower()); } if (base_v.isEmpty()) base_v.append("base_element"); prof_st = cl->parent()->parent()->name() + ":" + cl->name(); stereotypes.insert(s, new WrapperStr(prof_st)); bases.insert(s, new Q3ValueList<WrapperStr>(base_v)); return TRUE; } } } return FALSE; }
void UmlClass::extend(WrapperStr mcl) { if (parent()->parent()->kind() != aPackage) return; int index = mcl.find('#'); if (index == -1) return; WrapperStr path = mcl.left(index); const char * defltpath0 = "http://schema.omg.org/spec/UML/2.0/uml.xml"; const char * defltpath1 = "http://schema.omg.org/spec/UML/2.1/uml.xml"; bool dflt = ((path == defltpath0) || (path == defltpath1)); mcl = mcl.mid(index + 1); static Q3PtrList<UmlClass> metaclasses; Q3PtrListIterator<UmlClass> it(metaclasses); UmlClass * metacl = UmlClass::get(mcl, 0); WrapperStr s; if ((metacl == 0) || (metacl->stereotype() != "metaclass") || !((dflt) ? (!metacl->propertyValue("metaclassPath", s) || (s == defltpath0) || (s == defltpath1)) : (metacl->propertyValue("metaclassPath", s) && (path == s)))) { metacl = 0; if (dflt) { for (; (metacl = it.current()) != 0; ++it) { if (!strcmp(mcl, metacl->name()) && (!metacl->propertyValue("metaclassPath", s) || (s == defltpath0) || (s == defltpath1))) break; } } else { for (; (metacl = it.current()) != 0; ++it) { if (!strcmp(mcl, metacl->name()) && metacl->propertyValue("metaclassPath", s) && (path == s)) break; } } if (metacl == 0) { metacl = addMetaclass(mcl, (dflt) ? 0 : (const char *)path); //[rageek] different types for ? : metaclasses.append(metacl); } } UmlRelation::create(aDirectionalAssociation, this, metacl); }
void UmlClass::write(QTextOStream & f) { if (isJavaExternal()) { QCString s = javaDecl().stripWhiteSpace(); int index; 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()); f << s; } else { UmlClass * toplevel = this; UmlItem * p; QCString s2; while ((p = toplevel->parent())->kind() == aClass) { toplevel = (UmlClass *) p; s2 = dot + p->name() + s2; } UmlArtifact * cp = toplevel->associatedArtifact(); UmlPackage * pack = (UmlPackage *) ((cp != 0) ? (UmlItem *) cp : (UmlItem *) toplevel)->package(); if (pack != UmlArtifact::generation_package()) { QCString s = pack->javaPackage(); if (! s.isEmpty() && (s != "java.lang") && (s.left(10) != "java.lang.")) { s += s2; if (JavaSettings::isForcePackagePrefixGeneration() || !UmlArtifact::generated_one()->is_imported(s, name())) f << s << '.'; } } else if (! s2.isEmpty()) f << s2.mid(1) << '.'; f << name(); } }
void UmlClass::importIdlConstant(UmlItem * parent, const Q3CString & id, const Q3CString & s, const Q3CString & doc, Q3Dict<Q3CString> & prop) { // use a class to define the constant ! UmlClass * x; if ((x = UmlClass::create(parent, legalName(s))) == 0) { UmlCom::trace("<br>cannot create class '" + s + "' in " + parent->fullName()); throw 0; } newItem(x, id); x->lang = Corba; x->set_Stereotype("constant"); if (!doc.isEmpty()) x->set_Description(doc); Q3CString type; Q3CString value; Q3CString * v; if ((v = prop.find("CORBA/ImplementationType")) != 0) { type = *v; prop.remove("CORBA/ImplementationType"); } if ((v = prop.find("CORBA/ConstValue")) != 0) { if (!v->isEmpty()) value = " = " + *v; prop.remove("CORBA/ConstValue"); } Q3CString d = IdlSettings::constDecl(); int index; if ((index = d.find("${type}")) != -1) d.replace(index, 7, type); if ((index = d.find("${value}")) != -1) d.replace(index, 8, value); x->setProperties(prop); x->set_IdlDecl(d); }
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"); }
UmlClass * UmlClass::auxilarily_typedef(const WrapperStr & base #ifdef REVERSE , bool libp # ifdef ROUNDTRIP , bool container_roundtrip , QList<UmlItem *> & container_expected_order # endif #endif ) { WrapperStr typedef_decl = CppSettings::typedefDecl(); const QVector<UmlItem*>& children = parent()->children(); unsigned n = children.count(); unsigned index; // a typedef with the right definition already exist ? for (index = 0; index != n; index += 1) { if (children[index]->kind() == aClass) { UmlClass * cl = (UmlClass *) children[index]; if ((cl->stereotype() == "typedef") && (cl->cppDecl() == typedef_decl) && (cl->baseType().explicit_type == base)) { #ifdef ROUNDTRIP cl->set_usefull(); if (container_roundtrip) container_expected_order.append(cl); #endif return cl; } } } // must create typedef with a new name for (;;) { static unsigned nty; QString s("typedef%1"); s=s.arg(QString::number(++nty)); for (index = 0; index != n; index += 1) if (children[index]->name() == s) break; if (index == n) { UmlClass * cl = UmlClass::create(parent(), s.toLatin1().constData()); if (cl == 0) { #ifdef REVERSE UmlCom::message(""); CppCatWindow::trace(WrapperStr("<font face=helvetica><b>cannot create class <i>") + s + "</i> under <i>" + parent()->name() + "</b></font><br>"); throw 0; #else QMessageBox::critical(0, "Fatal Error", WrapperStr("<font face=helvetica><b>cannot create class <i>") + s + "</i> under <i>" + parent()->name() + "</b></font><br>"); QApplication::exit(1); #endif } UmlTypeSpec typespec; typespec.explicit_type = base; cl->set_Stereotype("typedef"); cl->set_BaseType(typespec); cl->set_CppDecl(typedef_decl); #ifdef REVERSE if (!libp) cl->need_artifact(Namespace::current()); # ifdef ROUNDTRIP if (container_roundtrip) container_expected_order.append(cl); # endif #endif return cl; } } }
void UmlAttribute::generate_def(QTextOStream & f, Q3CString indent, bool h, Q3CString templates, Q3CString cl_names, Q3CString, Q3CString) { if (isClassMember() && !cppDecl().isEmpty()) { UmlClass * cl = (UmlClass *) parent(); if ((!templates.isEmpty() || ((cl->name().find('<') != -1))) ? h : !h) { const char * p = cppDecl(); const char * pp = 0; while ((*p == ' ') || (*p == '\t')) p += 1; bool re_template = !templates.isEmpty() && insert_template(p, f, indent, templates); if (*p != '#') f << indent; const char * pname = name_spec(p); for (;;) { if (*p == 0) { if (pp == 0) break; // comment management done p = pp; pp = 0; if (re_template) f << templates; if (*p == 0) break; f << indent; } if (*p == '\n') { f << *p++; if (*p && (*p != '#')) f << indent; } else if (*p == '@') manage_alias(p, f); else if (*p != '$') { if (p == pname) f << cl_names << "::"; f << *p++; } else if (!strncmp(p, "${comment}", 10)) { if (!manage_comment(p, pp, CppSettings::isGenerateJavadocStyleComment()) && re_template) f << templates; } else if (!strncmp(p, "${description}", 14)) { if (!manage_description(p, pp) && re_template) f << templates; } else if (!strncmp(p, "${name}", 7)) { if (*pname == '$') f << cl_names << "::"; p += 7; f << name(); } else if (!strncmp(p, "${multiplicity}", 15)) { p += 15; const Q3CString & m = multiplicity(); if (!m.isEmpty() && (*((const char *) m) == '[')) f << m; else f << '[' << m << ']'; } else if (!strncmp(p, "${stereotype}", 13)) { p += 13; f << CppSettings::relationAttributeStereotype(stereotype()); } else if (!strncmp(p, "${value}", 8)) { if (!defaultValue().isEmpty()) { if (need_equal(p, defaultValue())) f << " = "; f << defaultValue(); } p += 8; } else if (!strncmp(p, "${h_value}", 10)) p += 10; else if (!strncmp(p, "${static}", 9)) { p += 9; } else if (!strncmp(p, "${const}", 8)) { p += 8; if (isReadOnly()) f << "const "; } else if (!strncmp(p, "${volatile}", 11)) { p += 11; if (isVolatile()) f << "volatile "; } else if (!strncmp(p, "${mutable}", 10)) { p += 10; } else if (!strncmp(p, "${type}", 7)) { p += 7; UmlClass::write(f, type()); //f << CppSettings::Type(Type().Type()); } else // strange f << *p++; } f << '\n'; } } }
bool UmlAttribute::new_one(Class * container, const WrapperStr & name, UmlTypeSpec typespec, aVisibility visibility, bool staticp, bool finalp, bool transientp, bool volatilep, const WrapperStr & array, const WrapperStr & value, WrapperStr comment, WrapperStr description, WrapperStr annotation #ifdef ROUNDTRIP , bool roundtrip, QList<UmlItem *> & expected_order #endif ) { #ifdef TRACE QLOG_INFO() << "ATTRIBUTE '" << name << "'\n"; #endif if ( #ifdef REVERSE container->from_libp() && ( #endif visibility == PrivateVisibility #ifdef REVERSE ) #endif ) { Lex::finish_line(); Lex::clear_comments(); return TRUE; } UmlClass * cl = container->get_uml(); UmlAttribute * at; #ifdef ROUNDTRIP bool created; if (!roundtrip || ((at = search_attr(container, name)) == 0)) { #endif at = UmlBaseAttribute::create(cl, name); if (at == 0) { JavaCatWindow::trace(WrapperStr("<font face=helvetica><b>cannot add attribute <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); 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); WrapperStr decl = JavaSettings::attributeDecl(""); int index = decl.find("${type}"); if ((index == -1) || (decl.find("${name}") == -1)) { decl = " ${comment}${@}${visibility}${static}${final}${transient}${volatile}${type} ${name}${value};"; index = decl.find("${type}"); } #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() != finalp) { at->set_isReadOnly(finalp); container->set_updated(); } if (at->isJavaTransient() != transientp) { at->set_isJavaTransient(transientp); 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 (!array.isEmpty()) decl.insert(index + 7, "${multiplicity}"); if (neq(at->multiplicity(), array)) { at->set_Multiplicity(array); container->set_updated(); } WrapperStr 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 (nequal(at->javaAnnotations(), annotation)) { at->set_JavaAnnotations(annotation); container->set_updated(); } WrapperStr stereotype; bool force_ste = FALSE; if (cl->stereotype() == "enum") { stereotype = "attribute"; force_ste = TRUE; } else if (typespec.type == 0) { WrapperStr 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}>"); force_ste = TRUE; } } if (at->visibility() != visibility) { at->set_Visibility(visibility); container->set_updated(); } if (neq(at->stereotype(), stereotype)) { WrapperStr jst; if (! at->stereotype().isEmpty()) jst = JavaSettings::relationAttributeStereotype(at->stereotype()); if ((force_ste) ? (jst != stereotype) : (jst == "attribute")) { at->set_Stereotype(stereotype); container->set_updated(); } } if (neq(at->javaDecl(), decl)) { at->set_JavaDecl(decl); container->set_updated(); } if (!at->type().equal(typespec)) { at->set_Type(typespec); 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 (finalp) at->set_isReadOnly(TRUE); if (transientp) at->set_isJavaTransient(TRUE); if (volatilep) at->set_isVolatile(TRUE); if (staticp) at->set_isClassMember(TRUE); if (!array.isEmpty()) { decl.insert(index + 7, "${multiplicity}"); at->set_Multiplicity(array); } if (! value.isEmpty()) at->set_DefaultValue(value); if (! annotation.isEmpty()) at->set_JavaAnnotations(annotation); if ((typespec.type == 0) && (cl->stereotype() != "enum")) { WrapperStr t = typespec.explicit_type; int index2 = 0; if (!t.isEmpty() && (t.at(t.length() - 1) == ">") && ((index2 = t.find('<')) > 0)) { at->set_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}>"); } } at->set_Visibility(visibility); if (cl->stereotype() == "enum") { at->set_JavaDecl(decl); at->set_Stereotype("attribute"); } else if (decl != JavaSettings::attributeDecl("")) at->set_JavaDecl(decl); at->set_Type(typespec); #ifdef ROUNDTRIP if (roundtrip) expected_order.append(at); } #endif return TRUE; }
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(); } }
// from a form 'generic<...C...> var' where C is a class bool UmlRelation::new_one(Class * container, const QCString & name, UmlClass * type, QCString type_def, QCString genericname, aVisibility visibility, bool staticp, bool constp, bool transientp, bool volatilep, const QCString & array, const QCString & value, QCString comment, QCString description, QCString annotation #ifdef ROUNDTRIP , bool roundtrip, QList<UmlItem> & expected_order #endif ) { #ifdef TRACE cout << "RELATION '" << name << "' from '" << cl->Name() << "' to '" << type->Name() << "' array '" << array << "'\n"; #endif if ( #ifdef REVERSE container->from_libp() && #endif (visibility == PrivateVisibility)) { Lex::finish_line(); Lex::clear_comments(); return TRUE; } QCString st = JavaSettings::umlType(genericname); if (st.isEmpty()) st = genericname; UmlClass * cl = container->get_uml(); UmlRelation * rel; #ifdef ROUNDTRIP bool created; if (!roundtrip || ((rel = search_rel(container, name, type, st)) == 0)) { #endif rel = UmlBaseRelation::create(aDirectionalAssociation, cl, type); if (rel == 0) { JavaCatWindow::trace(QCString("<font face=helvetica><b>cannot add relation <i>") + name + "</i> in <i>" + cl->name() + "</i> to <i>" + type->name() + "</i></b></font><br>"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP Statistic::one_relation_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); QCString decl = JavaSettings::relationDecl(array); type_def.replace(0, genericname.length(), "${stereotype}"); decl.replace(decl.find("${type}"), 7, type_def); #ifdef ROUNDTRIP if (roundtrip && !created) { if (rel->visibility() != visibility) { rel->set_Visibility(visibility); 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(); } if (rel->isReadOnly() != constp) { rel->set_isReadOnly(constp); container->set_updated(); } if (rel->isJavaTransient() != transientp) { rel->set_isJavaTransient(transientp); container->set_updated(); } if (rel->isVolatile() != volatilep) { rel->set_isVolatile(volatilep); container->set_updated(); } if (rel->isClassMember() != staticp) { rel->set_isClassMember(staticp); container->set_updated(); } if (neq(rel->multiplicity(), array)) { rel->set_Multiplicity(array); container->set_updated(); } if (neq(rel->defaultValue(), value)) { rel->set_DefaultValue(value); container->set_updated(); } if (nequal(rel->javaAnnotations(), annotation)) { rel->set_JavaAnnotations(annotation); container->set_updated(); } if (neq(rel->stereotype(), st) && (rel->stereotype().isEmpty() || (JavaSettings::relationAttributeStereotype(rel->stereotype()) != st))) { rel->set_Stereotype(st); container->set_updated(); } if (neq(rel->javaDecl(), decl)) { rel->set_JavaDecl(decl); container->set_updated(); } // role name is the right one rel->set_usefull(); expected_order.append(rel); } else { #endif rel->set_Visibility(visibility); if (!comment.isEmpty()) rel->set_Description((decl.find("${description}") != -1) ? description : Lex::simplify_comment(comment)); if (constp) rel->set_isReadOnly(TRUE); if (transientp) rel->set_isJavaTransient(TRUE); if (volatilep) rel->set_isVolatile(TRUE); if (staticp) rel->set_isClassMember(TRUE); if (!array.isEmpty()) rel->set_Multiplicity(array); if (! value.isEmpty()) rel->set_DefaultValue(value); if (! annotation.isEmpty()) rel->set_JavaAnnotations(annotation); rel->set_Stereotype(st); rel->set_JavaDecl(decl); rel->set_RoleName(name); #ifdef ROUNDTRIP if (roundtrip) expected_order.append(rel); } #endif return TRUE; }
void UmlRelation::write_relation_as_attribute(FileOut & out) { UmlRelation * first = side(TRUE); Q3CString s; UmlClass * base; if ((first->parent()->stereotype() == "stereotype") && (first->roleType()->stereotype() == "metaclass")) { if (this != first) return; base = first->roleType(); s = "base_" + base->name(); } else { base = 0; switch (_lang) { case Uml: s = roleName(); break; case Cpp: if (cppDecl().isEmpty()) return; s = true_name(roleName(), cppDecl()); break; default: // Java if (javaDecl().isEmpty()) return; s = true_name(roleName(), javaDecl()); } } out.indent(); out << "<ownedAttribute xmi:type=\"uml:Property\" name=\"" << s << '"'; out.id(this); if (base != 0) out.ref(first, "association", "EXT_"); else { write_visibility(out); write_scope(out); if (isReadOnly()) out << " isReadOnly=\"true\""; if (isDerived()) { out << " isDerived=\"true\""; if (isDerivedUnion()) out << " isDerivedUnion=\"true\""; } if (isOrdered()) out << " isOrdered=\"true\""; if (isUnique()) out << " isUnique=\"true\""; if (first->_assoc_class != 0) out.ref(first->_assoc_class, "association"); else out.ref(first, "association", "ASSOC_"); out << " aggregation=\""; if (this == first) { parent()->memo_relation(this); if (_gen_eclipse) { switch (relationKind()) { case anAggregation: case aDirectionalAggregation: out << "shared"; break; case anAggregationByValue: case aDirectionalAggregationByValue: out << "composite"; break; default: out << "none"; } } else out << "none"; } else if (_gen_eclipse) out << "none"; else { switch (relationKind()) { case anAggregation: case aDirectionalAggregation: out << "shared"; break; case anAggregationByValue: case aDirectionalAggregationByValue: out << "composite"; break; default: out << "none"; } } out << '"'; } out << ">\n"; out.indent(+1); out.indent(); out << "<type xmi:type=\"uml:Class\""; if (base != 0) { if (! base->propertyValue("metaclassPath", s)) s = (_uml_20) ? "http://schema.omg.org/spec/UML/2.0/uml.xml" : "http://schema.omg.org/spec/UML/2.1/uml.xml"; out << " href=\"" << s << '#' << base->name() << '"'; } else out.idref(roleType()); out << "/>\n"; write_multiplicity(out, multiplicity(), this); write_default_value(out, defaultValue(), this); write_constraint(out); write_annotation(out); write_description_properties(out); out.indent(-1); out.indent(); out << "</ownedAttribute>\n"; unload(); }
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 CppRefType::compute(Q3PtrList<CppRefType> & dependencies, const WrapperStr & hdef, const WrapperStr & srcdef, WrapperStr & h_incl, WrapperStr & decl, WrapperStr & src_incl, UmlArtifact * who) { UmlPackage * pack = who->package(); WrapperStr hdir; WrapperStr srcdir; if (CppSettings::isRelativePath()) { WrapperStr empty; hdir = pack->header_path(empty); srcdir = pack->source_path(empty); } else if (CppSettings::isRootRelativePath()) hdir = srcdir = UmlPackage::rootDir(); // aze.cpp includes aze.h src_incl += "#include \""; if (CppSettings::includeWithPath()) src_incl += pack->header_path(who->name(), srcdir); else { src_incl += who->name(); src_incl += '.'; src_incl += CppSettings::headerExtension(); } src_incl += "\"\n"; h_incl = ""; // to not be WrapperStr::null decl = ""; // to not be WrapperStr::null CppRefType * ref; for (ref = dependencies.first(); ref != 0; ref = dependencies.next()) { UmlClass * cl = (ref->type.type) ? ref->type.type : UmlBaseClass::get(ref->type.explicit_type, 0); bool included = ref->included; WrapperStr hform; // form in header WrapperStr srcform; // form in source if (cl == 0) { WrapperStr in = CppSettings::include(ref->type.explicit_type); if (!in.isEmpty()) hform = srcform = in + '\n'; else // doesn't know what it is continue; } else if (cl->isCppExternal()) { QString className = cl->name(); hform = cl->cppDecl(); int index; if ((index = hform.find('\n')) == -1) // wrong form continue; hform = hform.mid(index + 1) + '\n'; for (;;) { if ((index = hform.find("${name}")) != -1) hform.replace(index, 7, cl->name()); else if ((index = hform.find("${Name}")) != -1) hform.replace(index, 7, capitalize(cl->name())); else if ((index = hform.find("${NAME}")) != -1) hform.replace(index, 7, cl->name().upper()); else if ((index = hform.find("${nAME}")) != -1) hform.replace(index, 7, cl->name().lower()); else break; } srcform = hform; } else { QString className = cl->name(); WrapperStr st = cl->cpp_stereotype(); if ((st == "enum") || (st == "typedef")) included = TRUE; UmlArtifact * art = cl->associatedArtifact(); if (art != 0) { if (art == who) // don't include itself continue; if (CppSettings::includeWithPath()) { UmlPackage * p = art->package(); hform = "#include \"" + p->header_path(art->name(), hdir) + "\"\n"; srcform = "#include \"" + p->header_path(art->name(), srcdir) + "\"\n"; } else srcform = hform = "#include \"" + art->name() + '.' + CppSettings::headerExtension() + "\"\n"; } else if (cl->parent()->kind() != aClass) { write_trace_header(); UmlCom::trace(WrapperStr(" <font color=\"red\"><b> class<i> ") + cl->name() + "</i> referenced but does not have associated <i>artifact</i></b></font><br>"); incr_warning(); continue; } } if (included) { // #include must be placed in the header file if ((h_incl.find(hform) == -1) && (hdef.find(hform) == -1)) h_incl += hform; } else if ((cl != 0) && (cl->parent()->kind() != aClass)) { // else too complicated // #include useless in header file, place it in the source file if ((src_incl.find(srcform) == -1) && (h_incl.find(hform) == -1) && (hdef.find(hform) == -1) && (srcdef.find(srcform) == -1)) src_incl += srcform; if (!cl->isCppExternal()) { // header file must contains the declaration hform = cl->decl(); if (decl.find(hform) == -1) decl += hform; if ((cl->associatedArtifact() == 0) && (cl->parent()->kind() != aClass)) { write_trace_header(); UmlCom::trace(WrapperStr(" <font color=\"red\"><b> class<i> ") + cl->name() + "</i> referenced but does not have associated <i>artifact</i></b></font><br>"); incr_warning(); } } } else if (!hform.isEmpty()) { // have the #include form but does not know if it is a class or other, // generate the #include in the header file EXCEPT if the #include is // already in the header/source file to allow to optimize the generated // code if ((src_incl.find(srcform) == -1) && (h_incl.find(hform) == -1) && (hdef.find(hform) == -1) && (srcdef.find(srcform) == -1)) h_incl += hform; } } }
UmlClass * UmlClass::import(File & f, UmlItem * parent, const Q3CString & knd) { Q3CString s; if (f.read(s) != STRING) f.syntaxError(s, "class's name"); Q3CString id; Q3CString ste; Q3CString doc; Q3Dict<Q3CString> prop; Q3CString s2; int k; do { k = f.readDefinitionBeginning(s2, id, ste, doc, prop); } while (id.isEmpty()); if (ste == "CORBAConstant") { // not a class ! if (!scanning) { if (parent->kind() == aClass) UmlAttribute::importIdlConstant((UmlClass *) parent, id, s, doc, prop); else importIdlConstant(parent, id, s, doc, prop); } if (k != ')') f.skipBlock(); return 0; } UmlClass * cl; if (scanning) { if (((cl = UmlBaseClass::create(parent, s)) == 0) && ((cl = UmlBaseClass::create(parent, legalName(s))) == 0)) { UmlCom::trace("<br>cannot create class '" + s + "' in " + parent->fullName()); throw 0; } newItem(cl, id); if (!ste.isEmpty()) { if (ste.left(5) == "CORBA") { if (ste != "CORBAValue") cl->set_Stereotype(ste.mid(5).lower()); } else cl->set_Stereotype(((ste == "Actor") || (ste == "Interface")) ? ste.lower() : ste); } if (!doc.isEmpty()) cl->set_Description(doc); cl->lang = None; } else if ((cl = (UmlClass *) findItem(id, aClass)) == 0) { UmlCom::trace("<br>unknown class '" + s + "' in " + parent->fullName()); throw 0; } Q3CString art_path; for (;;) { switch (k) { case ')': switch (cl->lang) { case Cplusplus: case AnsiCplusplus: case VCplusplus: cl->cplusplus(prop); break; case Oracle8: cl->oracle8(prop); break; case Corba: cl->corba(prop); break; case Java: cl->java(prop); break; default: break; } if (!scanning) { cl->setProperties(prop); cl->unload(TRUE); } return cl; case ATOM: if (s2 == "operations") cl->importOperations(f); else if (s2 == "class_attributes") cl->importAttributes(f); else if (!scanning && ((s2 == "superclasses") || (s2 == "used_nodes") || (s2 == "realized_interfaces"))) cl->importRelations(f); else if (s2 == "nestedClasses") cl->importClasses(f); else if (s2 == "abstract") { if (f.readBool()) cl->set_isAbstract(TRUE); } else if (s2 == "language") cl->lang = f.readLanguage(); else if (s2 == "instantiation_relationship") cl->importInstantiate(f); else if (s2 == "parameters") { if (knd == "Parameterized_Class") cl->importFormals(f); else cl->importActuals(f); } else if (s2 == "module") { if (f.read(art_path) != STRING) f.syntaxError(art_path, "module's name"); } else if (!scanning && (s2 == "quidu")) { f.read(s2); cl->assocArtifact(Artifact::find(s2), art_path); } else f.skipNextForm(); k = f.read(s2); break; default: f.syntaxError(s); } } }
void UmlClass::importRelations(File & f) { Q3CString s; f.read("("); f.read("list"); if (f.read(s) != ATOM) f.syntaxError(s, "an atom"); for (;;) { switch (f.read(s)) { case ')': return; case '(': break; default: f.syntaxError(s); } f.read("object"); if (f.read(s) != ATOM) f.syntaxError(s, "an atom"); aRelationKind rk; Q3CString sr; if (s == "Uses_Relationship") { rk = aDependency; sr = "dependency"; } else if (s == "Inheritance_Relationship") { rk = aGeneralisation; sr = "generalisation"; } else if (s == "Realize_Relationship") { rk = aRealization; sr = "realization"; } else { f.skipBlock(); continue; } // dependency or generalisation Q3CString id; Q3CString ste; Q3CString doc; Q3Dict<Q3CString> prop; Q3CString s2; int k; do { k = f.readDefinitionBeginning(s2, id, ste, doc, prop); } while (id.isEmpty()); Q3CString target_id; aVisibility visibility = PublicVisibility; bool virtual_inheritance = FALSE; bool a_friend = FALSE; for (;;) { if (k == ATOM) { if (s2 == "quidu") { if (f.read(target_id) != STRING) f.syntaxError(target_id, "quidu value"); } else if (s2 == "exportControl") visibility = f.readVisibility(); else if (s2 == "virtual") virtual_inheritance = f.readBool(); else if (s2 == "friend") a_friend = f.readBool(); else f.skipNextForm(); k = f.read(s2); } else if (k == ')') break; else f.syntaxError(s2); } if (target_id.isEmpty()) f.syntaxError("quidu missing"); UmlClass * target = (UmlClass *) findItem(target_id, aClass); if (target != 0) { UmlRelation * r; if (a_friend) { if ((r = UmlRelation::create(rk, target, this)) == 0) { UmlCom::trace("<br>cannot create " + sr + " from '" + target->fullName() + "' to '" + fullName() + "'"); f.skipBlock(); return; } r->set_Stereotype("friend"); } else { if ((r = UmlRelation::create(rk, this, target)) == 0) { UmlCom::trace("<br>cannot create " + sr + " from '" + fullName() + "' to '" + target->fullName() + "'"); f.skipBlock(); return; } if (!ste.isEmpty()) r->set_Stereotype(ste); if (visibility != PublicVisibility) r->set_Visibility(visibility); if (virtual_inheritance) r->set_CppVirtualInheritance(TRUE); } newItem(r, id); if (!doc.isEmpty()) r->set_Description(doc); r->setProperties(prop); } } }
void UmlRelation::generate_def(QTextStream & f, WrapperStr indent, bool h, WrapperStr templates, WrapperStr cl_names, WrapperStr, WrapperStr) { if (isClassMember() && !cppDecl().isEmpty()) { UmlClass * cl = (UmlClass *) parent(); if ((!templates.isEmpty() || (cl->name().find('<') != -1)) ? h : !h) { const char * p = cppDecl(); const char * pp = 0; while ((*p == ' ') || (*p == '\t')) p += 1; bool re_template = !templates.isEmpty() && insert_template(p, f, indent, templates); if (*p != '#') f << indent; const char * pname = name_spec(p); for (;;) { if (*p == 0) { if (pp == 0) break; // comment management done p = pp; pp = 0; if (re_template) f << templates; if (*p == 0) break; if (*p != '#') f << indent; } if (*p == '\n') { f << toLocale(p); if (*p && (*p != '#')) f << indent; } else if (*p == '@') manage_alias(p, f); else if (*p != '$') { if (p == pname) f << cl_names << "::"; f << toLocale(p); } else if (!strncmp(p, "${comment}", 10)) { if (!manage_comment(p, pp, CppSettings::isGenerateJavadocStyleComment()) && re_template) f << templates; } else if (!strncmp(p, "${description}", 14)) { if (!manage_description(p, pp) && re_template) f << templates; } else if (!strncmp(p, "${static}", 9)) { p += 9; } else if (!strncmp(p, "${const}", 8)) { p += 8; if (isReadOnly()) f << "const "; } else if (!strncmp(p, "${volatile}", 11)) { p += 11; if (isVolatile()) f << "volatile "; } else if (!strncmp(p, "${mutable}", 10)) { p += 10; } else if (!strncmp(p, "${type}", 7)) { p += 7; roleType()->write(f); } else if (!strncmp(p, "${name}", 7)) { p += 7; if (*pname == '$') f << cl_names << "::"; 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; const WrapperStr & m = multiplicity(); if (!m.isEmpty() && (*((const char *) m) == '[')) f << m; else f << '[' << m << ']'; } else if (!strncmp(p, "${stereotype}", 13)) { p += 13; f << CppSettings::relationAttributeStereotype(stereotype()); } else if (!strncmp(p, "${value}", 8)) { if (!defaultValue().isEmpty()) { if (need_equal(p, defaultValue())) f << " = "; f << defaultValue(); } p += 8; } else if (!strncmp(p, "${h_value}", 10)) p += 10; else if (!strncmp(p, "${association}", 14)) { p += 14; UmlClass::write(f, association()); } else // strange f << toLocale(p); } f << '\n'; } } }
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); }
// not from a form 'generic<...C...> var' where C is a class bool UmlRelation::new_one(Class * container, const WrapperStr & name, UmlTypeSpec & dest, WrapperStr str_actuals, aVisibility visibility, bool staticp, bool constp, bool transientp, bool volatilep, const WrapperStr & array, const WrapperStr & value, WrapperStr comment, WrapperStr description, WrapperStr annotation #ifdef ROUNDTRIP , bool roundtrip, QList<UmlItem *> & expected_order #endif ) { #ifdef TRACE QLOG_INFO() << "RELATION '" << name << "' from '" << cl->Name() << "' to '" << dest.type->Name() << "' 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(); UmlRelation * rel; #ifdef ROUNDTRIP bool created; if (!roundtrip || ((rel = search_rel(container, name, dest.type, "")) == 0)) { #endif rel = UmlBaseRelation::create(aDirectionalAssociation, cl, dest.type); if (rel == 0) { JavaCatWindow::trace(WrapperStr("<font face=helvetica><b>cannot add relation <i>") + name + "</i> in <i>" + cl->name() + "</i> to <i>" + dest.type->name() + "</i></b></font><br>"); return FALSE; } #ifdef REVERSE # ifndef ROUNDTRIP Statistic::one_relation_more(); # else if (roundtrip) container->set_updated(); created = TRUE; } else created = FALSE; # endif #endif WrapperStr decl = JavaSettings::relationDecl(array); UmlClass::manage_generic(decl, dest, str_actuals, "${type}"); Lex::finish_line(); comment = Lex::get_comments(comment); description = Lex::get_description(description); #ifdef ROUNDTRIP if (roundtrip && !created) { if (rel->visibility() != visibility) { rel->set_Visibility(visibility); 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(); } if (rel->isReadOnly() != constp) { rel->set_isReadOnly(constp); container->set_updated(); } if (rel->isJavaTransient() != transientp) { rel->set_isJavaTransient(transientp); container->set_updated(); } if (rel->isVolatile() != volatilep) { rel->set_isVolatile(volatilep); container->set_updated(); } if (rel->isClassMember() != staticp) { rel->set_isClassMember(staticp); container->set_updated(); } if (neq(rel->multiplicity(), array)) { rel->set_Multiplicity(array); container->set_updated(); } WrapperStr 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(); } if (nequal(rel->javaAnnotations(), annotation)) { rel->set_JavaAnnotations(annotation); container->set_updated(); } if (neq(rel->javaDecl(), decl)) { rel->set_JavaDecl(decl); container->set_updated(); } rel->set_usefull(); expected_order.append(rel); } else { #endif rel->set_Visibility(visibility); if (!comment.isEmpty()) rel->set_Description((decl.find("${description}") != -1) ? description : comment); if (constp) rel->set_isReadOnly(TRUE); if (transientp) rel->set_isJavaTransient(TRUE); if (volatilep) rel->set_isVolatile(TRUE); if (staticp) rel->set_isClassMember(TRUE); if (!array.isEmpty()) rel->set_Multiplicity(array); if (! value.isEmpty()) rel->set_DefaultValue(value); if (! annotation.isEmpty()) rel->set_JavaAnnotations(annotation); rel->set_JavaDecl(decl); rel->set_RoleName(name); #ifdef ROUNDTRIP if (roundtrip) expected_order.append(rel); } #endif return TRUE; }
void UmlClass::importIt(FileIn & in, Token & token, UmlItem * where) { where = where->container(aClass, token, in); // can't be null WrapperStr s = token.valueOf("name"); if (s.isEmpty()) { static unsigned n = 0; s.sprintf("anonymous_%u", ++n); } else s = legalName(s); UmlClass * cl = create(where, s); Association * assocclass = 0; bool stereotype = FALSE; if (cl == 0) in.error("cannot create classe '" + s + "' in '" + where->name() + "'"); cl->addItem(token.xmiId(), in); do where = where->parent(); while (where->kind() != aPackage); if (where->stereotype() == "profile") cl->set_PropertyValue("xmiId", token.xmiId()); 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:Stereotype") { cl->set_Stereotype("stereotype"); NumberOf -= 1; NumberOfStereotype += 1; stereotype = TRUE; } 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.valueOf("isactive") == "true") cl->set_isActive(TRUE); if (! token.closed()) { WrapperStr k = token.what(); const char * kstr = k; WrapperStr assocclass_ref1; WrapperStr 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 if (s == "ownedrule") cl->set_Constraint(UmlItem::readConstraint(in, token)); else if (stereotype && (s == "icon") && (token.xmiType() == "uml:Image")) { WrapperStr path = token.valueOf("location"); if (! path.isEmpty()) cl->set_PropertyValue("stereotypeIconPath", path); if (! token.closed()) in.finish(s); } else cl->UmlItem::import(in, token); } } cl->unload(TRUE, FALSE); }
bool UmlOperation::new_one(Class * container, aVisibility visibility, bool finalp, bool abstractp, bool staticp, Q3CString comment, Q3CString description) { // 'function' was read, it is followed by : // ['&'] name'(' {'array' | <classname>] ['&'] '$'<varname> ['=' <value>]}* ')' '{' ... '}' Q3CString s = Lex::read_word(); bool refp; if (s == "&") { refp = TRUE; s = Lex::read_word(); } else refp = FALSE; if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } Q3CString name = s; #ifdef TRACE QLOG_INFO() <<"OPERATION '" << name << "'\n"; #endif s = Lex::read_word(); if (s != "(") { Lex::syntax_error("'(' expected rather than '" + s + "'"); return FALSE; } UmlClass * cl = container->get_uml(); UmlOperation * op; #ifndef REVERSE if (visibility == PrivateVisibility) op = 0; else #endif { op = UmlBaseOperation::create(cl, name); if (op == 0) { PhpCatWindow::trace(Q3CString("<font face=helvetica><b>cannot add operation <i>") + name + "</i> in <i>" + cl->name() + "</i></b></font><br>"); return FALSE; } #ifdef REVERSE Statistic::one_operation_more(); #endif } Q3CString def; if (op != 0) { op->set_Visibility(visibility); if (staticp) op->set_isClassMember(TRUE); if (finalp) op->set_isPhpFinal(TRUE); def = PhpSettings::operationDef(); int index; if (((index = def.find("${(}")) == -1) || (def.find("${)}", index + 4) == -1) || ((index = def.find("${name}")) == -1) || (def.find("${body}") == -1)) { // use a definition where ${body] is not indented def = " ${comment}${final}${visibility}${abstract}${static}function ${name}${(}${)}\n{\n ${body}}\n"; index = def.find("${name}"); } if (refp) def.insert(index, "&"); if ((name == cl->name()) || (name == "__construct")) { // constructor, remove useless ${} if ((index = def.find("${static}")) != -1) def.remove(index, 9); if ((index = def.find("${final}")) != -1) def.remove(index, 8); if ((index = def.find("${abstract}")) != -1) def.remove(index, 11); } if (abstractp) { op->set_isAbstract(TRUE); def = def.left(def.find("${)}") + 4) + ";"; } } // parameters unsigned rank = 0; UmlParameter param; while (read_param(container, rank, param, def, op == 0)) { if ((op != 0) && ! op->addParameter(rank++, param)) { PhpCatWindow::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 << '\n'; #endif return FALSE; } } s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } // definition if (abstractp || (cl->stereotype() == "interface")) { if (s != ";") { Lex::error_near(s); return FALSE; } #ifdef REVERSE if (op != 0) op->set_PhpBody(0); #endif } else if (s != "{") { Lex::error_near(s); return FALSE; } else { Lex::mark(); // goto the end of the body char c; int level = 1; // '{' already read for (;;) { if ((c = Lex::read_word_bis()) == 0) return FALSE; else if (c == '{') level += 1; else if ((c == '}') && (--level == 0)) break; } #ifdef REVERSE if (op != 0) { Q3CString e = Lex::region(); e.truncate(e.length() - 1); // remove } // remove fist \n if (*((const char *) e) == '\n') e.remove(0, 1); // remove last spaces and tabs int ln = e.length(); while (ln && ((e[ln - 1] == ' ') || (e[ln - 1] == '\t'))) ln -= 1; e.truncate(ln); op->set_PhpBody(e); op->set_PhpContextualBodyIndent(FALSE); } #endif } if ((op != 0) && (def != op->phpDecl())) op->set_PhpDecl(def); Lex::clear_comments(); // params & body comments Lex::finish_line(); if ((op != 0) && !comment.isEmpty()) { s = (def.find("${description}") != -1) ? description : comment; UmlTypeSpec t; int index1; if (! (t.explicit_type = value_of(s, "@return", index1)).isEmpty()) { op->set_ReturnType(t); s.replace(index1, t.explicit_type.length(), "${type}"); } Q3ValueList<UmlParameter> l = op->params(); unsigned nparams = l.count(); if (nparams != 0) { Q3CString varname; int index2; char xn[16]; index1 = 0; rank = 0; while (!((t.explicit_type = value_of(s, "@param", index1, varname, index2)) .isEmpty())) { if (varname.isEmpty() || (varname[0] != '$')) { if (rank < nparams) { UmlParameter & p = l[rank]; p.type = t; op->replaceParameter(rank, p); } } else { varname = varname.mid(1); Q3ValueList<UmlParameter>::Iterator it; for (it = l.begin(), rank = 0; it != l.end(); ++it, rank += 1) { if ((*it).name == varname) { (*it).type = t; op->replaceParameter(rank, *it); sprintf(xn, "${p%d}", rank); s.replace(index2, varname.length() + 1, xn); break; } } } sprintf(xn, "${t%d}", rank++); s.replace(index1, t.explicit_type.length(), xn); } } op->set_Description(s); } return TRUE; }