static void manage_decorators(QTextStream & f, const WrapperStr & decorators, QString indent, BooL & indent_needed) { if (! decorators.isEmpty()) { int index = 0; int index2; while ((index2 = decorators.find("\n", index)) != -1) { if (indent_needed) f << indent; else indent_needed = TRUE; f << decorators.mid(index, index2 + 1 - index); index = index2 + 1; } if (index != (int) decorators.length()) { if (indent_needed) { f << indent; indent_needed = FALSE; } f << decorators.mid(index); } } }
bool UmlClass::isPrimitiveType(Token & token, UmlTypeSpec & ts) { if (token.xmiType() != "uml:PrimitiveType") return FALSE; WrapperStr href = token.valueOf("href"); int index; if (href.isEmpty() || ((index = href.find('#')) == -1)) return FALSE; ts.explicit_type = href.mid(index + 1); if ((CppSettings::type(ts.explicit_type) == ts.explicit_type) && CppSettings::umlType(ts.explicit_type).isEmpty()) { // not defined href = ts.explicit_type.lower(); if (href == "integer") ts.explicit_type = "int"; else if (href == "boolean") ts.explicit_type = "bool"; else if (href == "string") ts.explicit_type = "string"; else if (href == "unlimitednatural") ts.explicit_type = "long"; } return TRUE; }
void UmlItem::write_multiplicity(FileOut & out, WrapperStr s, UmlItem * who) { if (!s.isEmpty()) { WrapperStr min; WrapperStr max; int index = s.find(".."); if (index != -1) { min = s.left(index).stripWhiteSpace(); max = s.mid(index + 2).stripWhiteSpace(); } else min = max = s.stripWhiteSpace(); out.indent(); out << "<lowerValue xmi:type=\"uml:LiteralString\""; out.id_prefix(who, "MULTIPLICITY_L_"); out << " value=\"" << min.operator QString() << "\"/>\n"; out.indent(); out << "<upperValue xmi:type=\"uml:LiteralString\""; out.id_prefix(who, "MULTIPLICITY_U_"); out << " value=\"" << max.operator QString() << "\"/>\n"; } }
bool UmlArtifact::is_imported(WrapperStr path, WrapperStr class_name) { if (imports == 0) { imports = new QHash<WrapperStr, UmlArtifact*>; WrapperStr s = javaSource(); int index = 0; while ((index = s.find("import", index)) != -1) { if ((index == 0) || (s[index - 1] < ' ')) { int index2 = index + 6; while ((s[index2] == ' ') || (s[index2] == '\t')) index2 += 1; if ((index2 != (index + 6)) && ((index = s.find(';', index2)) != -1) && (index != index2)) { WrapperStr p = s.mid(index2, index - index2); imports->insert(p, this); } else index = index2; } else index += 6; } } return ((imports->value(path + '.' + class_name) != 0) || (imports->value(path + ".*") != 0)); }
void UmlItem::replace_alias(WrapperStr & s) { int index = 0; while ((index = s.find("@{", index)) != -1) { int index2 = s.find('}', index + 2); if (index2 == -1) return; UmlBaseItem * obj = this; WrapperStr key = s.mid(index + 2, index2 - index - 2); WrapperStr value; for (;;) { if (obj->propertyValue(key, value)) { s.replace(index, index2 - index + 1, value); index += value.length(); break; } else if ((obj = obj->parent()) == 0) { index = index2 + 1; break; } } } }
static WrapperStr root_relative_if_possible(WrapperStr p) { unsigned rln = RootCDir.length(); return ((p.length() >= rln) && (p.left(rln) == RootCDir)) ? p.mid(rln) : p; }
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 UmlPackage::applyStereotype(FileIn & in, Token & token) { WrapperStr prof_st; Q3ValueList<WrapperStr> base_v; WrapperStr s; if (UmlClass::isAppliedStereotype(token, prof_st, base_v)) { WrapperStr s; Q3ValueList<WrapperStr>::Iterator it_ext; for (it_ext = base_v.begin(); it_ext != base_v.end(); ++it_ext) { WrapperStr s2; if (token.valueOf(*it_ext, s2)) { if (s.isEmpty()) s = s2; else if (s != s2) in.warning("doesn't refer to the same element ('" + s + "' != '" + s2 + "')"); } } if (s.isEmpty()) in.warning("value of 'base_...' is missing"); else { UmlItem * elt = All[s]; if (elt == 0) { if (!FileIn::isBypassedId(s)) in.warning("unknown reference '" + s + "'"); } else { elt->set_Stereotype(prof_st); elt->UmlItem::applyStereotype(); // set properties Q3Dict<WrapperStr> props = elt->properties(); Q3DictIterator<WrapperStr> it(props); while (it.current()) { WrapperStr k = it.currentKey().latin1(); if (token.valueOf(k.mid(k.findRev(':') + 1).lower(), s)) elt->set_PropertyValue(k, s); ++it; } } } if (! token.closed()) in.finish(token.what()); } else in.bypass(token); }
void UmlItem::importExtension(FileIn & in, Token & token, UmlItem * where) { if (! token.closed()) { WrapperStr s = token.valueOf("extender"); if (s.isNull()) s = token.valueOf("xmi:extender"); if (s == "Bouml") { WrapperStr k = token.what(); const char * kstr = k; while (in.read(), !token.close(kstr)) { s = token.what(); if (s == "taggedvalue") // is closed where->set_PropertyValue(token.valueOf("tag"), token.valueOf("value")); else if (s == "stereotype") where->set_Stereotype(token.valueOf("name")); if (! token.closed()) in.finish(token.what()); } } else if (s == "Visual Paradigm for UML") { WrapperStr k = token.what(); const char * kstr = k; while (in.read(), !token.close(kstr)) { s = token.what(); if (s == "appliedstereotype") { s = token.valueOf("xmi:value"); if (s.right(3) == "_id") { s = s.mid(s.find("_") + 1); s = s.left(s.length() - 3).lower(); } where->set_Stereotype(s); } if (! token.closed()) in.finish(token.what()); } } else in.finish(token.what()); } }
void FileOut::define_datatypes(bool uml_20, bool primitive_type, bool gen_extension) { const char * pfix = (primitive_type) ? ((uml_20) ? "<ownedMember xmi:type=\"uml:PrimitiveType\"" : "<packagedElement xmi:type=\"uml:PrimitiveType\"") : ((uml_20) ? "<ownedMember xmi:type=\"uml:DataType\"" : "<packagedElement xmi:type=\"uml:DataType\""); QMap<QString, int>::ConstIterator it; for (it = _datatypes.begin(); it != _datatypes.end(); ++it) { indent(); (*this) << pfix << " xmi:id=\"BOUML_datatype_" << it.value() << "\" name=\""; quote(it.key()); //[jasa] ambiguous call (*this) << "\"/>\n"; } const char * postfix = (uml_20) ? "</ownedMember>\n" : "</packagedElement>\n"; for (it = _modifiedtypes.begin(); it != _modifiedtypes.end(); ++it) { WrapperStr k = it.key(); int index = k.find('_'); indent(); (*this) << pfix << " xmi:id=\"BOUML_basedontype_" << it.value() << "\" name = \""; quote((const char *)k.mid(index + 1)); (*this) << '"'; if (gen_extension) { (*this) << ">\n"; indent(); (*this) << "\t<xmi:Extension extender=\"Bouml\">\n"; indent(); (*this) << "\t\t<basedOn \"BOUML_" << k.left(index).operator QString() << "\"/>\n"; indent(); (*this) << "\t</xmi:Extension>\n"; indent(); (*this) << postfix; } else (*this) << "/>\n"; } }
WrapperStr UmlClass::decl() { WrapperStr result; WrapperStr close_template; UmlArtifact * cp = associatedArtifact(); WrapperStr nasp = ((UmlPackage *) ((cp != 0) ? (UmlItem *) cp : (UmlItem *) this)->package()) ->cppNamespace(); if (!nasp.isEmpty()) { int index = // bypass :: allowing ::a... ((nasp.at(0) == ":") && (nasp != QString("::"))) ? 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 += " } "; } WrapperStr template1; WrapperStr template2; get_template_prefixes(template1, template2); if (!template1.isEmpty()) result += template1.left(template1.length() - 1) + ' '; result += cpp_stereotype() + ' '; return result + name() + ';' + close_template + '\n'; }
bool UmlClass::is_itself(WrapperStr t) { // class is a template class and t is x<...> where x is the class, // t is normalized // return true if t is the class with its formals int index = t.find('<'); t = t.mid(index + 1, t.length() - index - 2); QList<UmlFormalParameter> l = formals(); QList<UmlFormalParameter>::ConstIterator it = l.begin(); WrapperStr t2 = (*it).name(); while ((++it) != l.end()) t2 += ',' + (*it).name(); return (t == t2); }
void UmlItem::importGeneralization(FileIn & in, Token & token, UmlItem * where) { WrapperStr id = token.valueOf("general"); WrapperStr constraint; if (! token.closed()) { WrapperStr k = token.what(); const char * kstr = k; while (in.read(), !token.close(kstr)) { WrapperStr s = token.what(); if (s == "general") { id = token.xmiIdref(); if (id.isEmpty() && !(id = token.valueOf("href")).isEmpty()) { int index = id.find('#'); if (index != -1) id = id.mid(index + 1); } } else if (s == "ownedrule") { constraint = UmlItem::readConstraint(in, token); continue; } if (! token.closed()) in.finish(s); } } if (!id.isEmpty()) { QMap<QString, UmlItem *>::ConstIterator iter = All.find(id); if (iter != All.end()) where->generalizeDependRealize(*iter, in, 0, "", constraint); else Unresolved::addGeneralization(where, id, constraint); } else in.warning("'general' is missing"); }
void UmlOperation::generate_imports(QTextStream & f, WrapperStr & made) { WrapperStr s = pythonDecl(); if (!s.isEmpty()) { UmlArtifact * art = ((UmlClass *) parent())->assocArtifact(); returnType().generate_import(f, art, FALSE, made); int index1 = s.find("${(}"); if (index1 == -1) return; index1 += 4; int index2 = s.find("${)}", index1); if (index2 == -1) return; s = s.mid((unsigned) index1, (unsigned)(index2 - index1)); const QList<UmlParameter> & params = this->params(); QList<UmlParameter>::ConstIterator it; unsigned rank; char ti[16]; strcpy(ti, "${p"); for (it = params.begin(), rank = 0; it != params.end(); ++it, rank += 1) { sprintf(ti + 3, "%u}", rank); if (s.find(ti) != -1) (*it).type.generate_import(f, art, FALSE, made); } } }
void UmlItem::write_default_value(FileOut & out, WrapperStr v, UmlItem * who, int rank) { if (! v.isEmpty()) { if (v[0] == '=') { v = v.mid(1); if (v.isEmpty()) return; } out.indent(); out << "<defaultValue xmi:type=\"uml:LiteralString\""; if (rank == -1) out.id_prefix(who, "VALUE_"); else out.id_prefix(who, "VALUE", rank); out << " value=\""; out.quote((const char *)v); //[jasa] ambiguous call out << "\"/>\n"; } }
bool UmlAttribute::new_one(Class * container, const WrapperStr & name, const WrapperStr & type, const WrapperStr & modifier, const WrapperStr & pretype, const WrapperStr & array, aVisibility visibility, bool staticp, bool constp, bool typenamep, bool mutablep, bool volatilep, const WrapperStr & bitfield, const WrapperStr & value, WrapperStr comment, WrapperStr description #ifdef ROUNDTRIP , bool roundtrip, QList<UmlItem *> & expected_order #endif ) { #ifdef DEBUG_DOUML QLOG_INFO() << "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(WrapperStr("<font face=helvetica><b>cannot add attribute <i>") + name + "</i> in <i>" + WrapperStr(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; WrapperStr typeform; WrapperStr stereotype; if (! pfunc) { typeform = (pretype.isEmpty()) ? WrapperStr("${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); } WrapperStr 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 *)(WrapperStr(" ") + modifier)); if (typeform != "${type}") decl.replace(index, 7, typeform); else if (typespec.type == 0) { WrapperStr t = typespec.explicit_type; int index2 = 0; 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 *)(WrapperStr(" : ") + 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) { 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 (at->visibility() != visibility) { at->set_Visibility(visibility); container->set_updated(); } if (!stereotype.isEmpty()) { WrapperStr 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; }
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; }
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; } } }
bool UmlOperation::get_param(WrapperStr s, int & index, WrapperStr & r, WrapperStr & kname, WrapperStr & ktype, int & rank) { int index0 = index; int level = 0; //const char * p = (const char *) s; r = ""; do { if (index >= (int) s.length()) { if (level != 0) return FALSE; r = s.mid(index0, index - index0).stripWhiteSpace(); if (r.isEmpty()) return FALSE; break; } switch (s[index]) { case ',': if (level == 0) { r = s.mid(index0, index - index0).stripWhiteSpace(); index += 1; if (r.isEmpty()) return FALSE; } break; case '(': case '{': case '[': level += 1; break; case ')': case '}': case ']': if (--level < 0) return FALSE; default: break; } index += 1; } while (r.isEmpty()); int index1; int index2; rank = -1; if (((index1 = r.find("${p")) != -1) && ((index2 = r.find("}", index1 + 3)) != -1)) { kname = r.mid(index1, index2 - index1 + 1); rank = atoi(((const char *) r) + index1 + 3); } else kname = ""; if (((index1 = r.find("${t")) != -1) && ((index2 = r.find("}", index1 + 3)) != -1)) { ktype = r.mid(index1, index2 - index1 + 1); if (rank == -1) rank = atoi(((const char *) r) + index1 + 3); } else if (rank == -1) // too complicated; return FALSE; else ktype = ""; return TRUE; }
void UmlArtifact::generate() { if (! managed) { managed = TRUE; if (stereotype() == "text") { generate_text(); return; } else if (stereotype() != "source") return; package_of_generated_artifact = package(); const WrapperStr hdef = cppHeader(); QLOG_INFO() << "Read header as: " + hdef.operator QString(); const WrapperStr srcdef = cppSource(); if (hdef.isEmpty() && srcdef.isEmpty()) { if (verbose()) UmlCom::trace(WrapperStr("<hr><font face=helvetica>artifact <i>") + name() + "</i> has an empty C++ definition</font><br>"); return; } const WrapperStr & name = UmlArtifact::name(); UmlPackage * pack = package(); WrapperStr h_path = pack->header_path(name); WrapperStr src_path = pack->source_path(name); WrapperStr nasp_start; WrapperStr nasp_end; const char * cnasp = pack->cppNamespace(); WrapperStr nasp = ((cnasp[0] == ':') && (cnasp[1] == ':')) ? cnasp + 2 : cnasp; if (!nasp.isEmpty()) { int index = 0; int index2; WrapperStr closed = "\n} // namespace "; while ((index2 = nasp.find(':', index)) != -1) { WrapperStr na = nasp.mid(index, index2 - index); nasp_start += WrapperStr("namespace ") + na + " {\n\n"; closed += na; nasp_end = closed + "\n" + nasp_end; closed += "::"; nasp.replace(index2, 2, "_"); index = index2 + 1; } nasp_start += WrapperStr("namespace ") + nasp.mid(index) + " {\n\n"; closed += nasp.mid(index); nasp_end = closed + "\n" + nasp_end; } else { WrapperStr s; if (!hdef.isEmpty()) s = " in <i> " + h_path + "</i>"; if (!srcdef.isEmpty()) { if (!hdef.isEmpty()) s += " and <i> " + src_path + "</i>"; else s = " in <i> " + src_path + "</i>"; } UmlCom::message(name); if (verbose()) UmlCom::trace(WrapperStr("<hr><font face=helvetica>Generate code for <i> ") + name + "</i>" + s + "</font><br>"); else set_trace_header(WrapperStr("<font face=helvetica>Generate code for <i> ") + name + "</i>" + s + "</font><br>"); } // get bodies if preserve const Q3PtrVector<UmlClass> & cls = associatedClasses(); if (preserve()) UmlOperation::read_bodies(h_path, src_path); // compute dependencies bool all_in_h = (hdef.find("${all_includes}") != -1); Q3PtrList<CppRefType> dependencies; unsigned n = cls.count(); unsigned index; for (index = 0; index != n; index += 1) cls[index]->compute_dependencies(dependencies, all_in_h); // generate header file WrapperStr h_incl; WrapperStr src_incl; WrapperStr decl; bool incl_computed = FALSE; if (!hdef.isEmpty()) { //headerFile->append("Test DAta"); QLOG_INFO() << "openign file for writing: "; //QTextStream f_h(file.data()); //[lgfreitas] Now QTextStream receives a pointer to a byte array... QSharedPointer<QByteArray> headerFile(new QByteArray()); QTextStream f_h(headerFile.data(), QFile::WriteOnly); f_h.setCodec(QTextCodec::codecForLocale()); //QTextStream f_h(headerFile.data(), QIODevice::WriteOnly); //QString h_copy = QString(hdef.operator QString()); const char * p = hdef; const char * pp = 0; for (;;) { QLOG_INFO() << "At this point P is: " << QString(p); if (*p == 0) { if (pp == 0) break; // comment management done p = pp; pp = 0; if (*p == 0) break; } if (*p == '@') manage_alias(p, f_h); else if (*p != '$') { QTextCodec* codec = QTextCodec::codecForLocale(); //f_h << codec->fromUnicode(*p,1); //p++; f_h << toLocale(p); } else if (!strncmp(p, "${comment}", 10)) manage_comment(p, pp, CppSettings::isGenerateJavadocStyleComment()); else if (!strncmp(p, "${description}", 14)) manage_description(p, pp); else if (!strncmp(p, "${name}", 7)) { p += 7; f_h << name; } else if (!strncmp(p, "${Name}", 7)) { p += 7; //QLOG_INFO() << "Outputting name: " << name; f_h << capitalize(name); } else if (!strncmp(p, "${NAME}", 7)) { p += 7; f_h << name.upper(); } else if (!strncmp(p, "${nAME}", 7)) { p += 7; f_h << name.lower(); } else if (!strncmp(p, "${namespace}", 12)) { p += 12; f_h << nasp; } else if (!strncmp(p, "${NAMESPACE}", 12)) { p += 12; f_h << nasp.upper(); } else if (!strncmp(p, "${includes}", 11) || !strncmp(p, "${all_includes}", 15)) { QLOG_INFO() << "REaDING INCLUDES"; p += (p[2] == 'a') ? 15 : 11; QLOG_INFO() << "Modified p 1 to be" << QString(p); if (!incl_computed) { incl_computed = TRUE; CppRefType::compute(dependencies, hdef.operator QString(), srcdef, h_incl, decl, src_incl, this); QLOG_INFO() << "Modified hdef to be: " << hdef.operator QString(); } QLOG_INFO() << "Modified p 2 to be" << QString(p); if (!h_incl.isEmpty()) { f_h << h_incl; if (*p != '\n') f_h << '\n'; } else if (*p == '\n') p += 1; QLOG_INFO() << "FINISHED INCLUDES"; } else if (!strncmp(p, "${declarations}", 15)) { p += 15; if (!incl_computed) { incl_computed = TRUE; CppRefType::compute(dependencies, hdef.operator QString(), srcdef, h_incl, decl, src_incl, this); } QLOG_INFO() << "DECLS IS: " << decl.operator QString(); if (!decl.isEmpty()) { f_h << decl; if (*p != '\n') f_h << '\n'; } else if (*p == '\n') p += 1; } else if (!strncmp(p, "${namespace_start}", 18)) { p += 18; if (!nasp_start.isEmpty()) f_h << nasp_start; if (*p == '\n') p += 1; } else if (!strncmp(p, "${namespace_end}", 16)) { p += 16; if (!nasp_end.isEmpty()) f_h << nasp_end; if (*p == '\n') p += 1; } else if (!strncmp(p, "${definition}", 13)) { p += 13; for (index = 0; index != n; index += 1) cls[index]->generate_decl(f_h, current_indent(p, hdef.operator QString())); if (*p == '\n') p += 1; } else // strange f_h << toLocale(p); } f_h << '\000'; f_h.flush(); if (must_be_saved(h_path, headerFile->data())) { QLOG_INFO() << "this is essentially what goes to the header file: " << headerFile->size(); write_trace_header(); //FILE * fp_h; QFile file(h_path); if (!file.open(QFile::WriteOnly)) { UmlCom::trace(WrapperStr("<font color=\"red\"><b><i> ") + name + "</i> : cannot open <i> " + h_path + "</i>, edit the <i> generation settings</i> (tab directory) or the <i>" + pack->name() + "</i> C++ directory specification</b></font><br>"); incr_error(); } else { QLOG_INFO() << "this is essentially what goes to the file: " << headerFile->constData(); QTextCodec* codec = QTextCodec::codecForLocale(); QTextStream out(&file); out.setCodec(QTextCodec::codecForLocale()); QString temp(*headerFile.data()); out << codec->toUnicode(temp); //out << *headerFile.data(); out.flush(); } } else { WrapperStr th = get_trace_header(); if (th.isEmpty()) UmlCom::trace(WrapperStr("<br><font face=helvetica><i> ") + h_path + "</i> not modified</font><br>"); else set_trace_header(th + "<font face=helvetica><i> " + h_path + "</i> not modified</font><br>"); } } // generate source file if (!srcdef.isEmpty()) { QSharedPointer<QByteArray> file(new QByteArray()); QTextStream f_src(file.data(), QIODevice::WriteOnly); const char * p = srcdef; const char * pp = 0; for (;;) { if (*p == 0) { if (pp == 0) break; // comment management done p = pp; pp = 0; if (*p == 0) break; } if (*p == '@') manage_alias(p, f_src); else if (*p != '$') f_src << toLocale(p); else if (!strncmp(p, "${comment}", 10)) manage_comment(p, pp, CppSettings::isGenerateJavadocStyleComment()); else if (!strncmp(p, "${description}", 14)) manage_description(p, pp); else if (!strncmp(p, "${name}", 7)) { // for file header p += 7; f_src << name; } else if (!strncmp(p, "${includes}", 11)) { p += 11; if (!incl_computed) { incl_computed = TRUE; CppRefType::compute(dependencies, hdef.operator QString(), srcdef, h_incl, decl, src_incl, this); } if (!src_incl.isEmpty()) { f_src << src_incl; if (*p != '\n') f_src << '\n'; } else if (*p == '\n') p += 1; } else if (!strncmp(p, "${members}", 10)) { p += 10; for (index = 0; index != n; index += 1) cls[index]->generate_def(f_src, current_indent(p, srcdef), FALSE); if (*p == '\n') p += 1; } else if (!strncmp(p, "${namespace_start}", 18)) { p += 18; if (!nasp_start.isEmpty()) f_src << nasp_start; if (*p == '\n') p += 1; } else if (!strncmp(p, "${namespace_end}", 16)) { p += 16; if (!nasp_end.isEmpty()) f_src << nasp_end; if (*p == '\n') p += 1; } else // strange f_src << toLocale(p); } f_src << '\000'; f_src.flush(); if (must_be_saved(src_path, file->data())) { write_trace_header(); FILE * fp_src; if ((fp_src = fopen((const char *) src_path, "wb")) == 0) { write_trace_header(); UmlCom::trace(WrapperStr("<font color=\"red\"><b><i> ") + name + " : </i> cannot open <i> " + src_path + "</i>, edit the <i> generation settings</i> (tab directory) or the <i>" + pack->name() + "</i> C++ directory specification</b></font><br>"); incr_error(); } else { fputs((const char *) file->data(), fp_src); fclose(fp_src); } } else if (get_trace_header().isEmpty()) UmlCom::trace(WrapperStr("<font face=helvetica><i> ") + src_path + "</i> not modified</font><br>"); } } }
bool UmlAttribute::new_one(Class * container, WrapperStr name, aVisibility visibility, bool constp, bool staticp, const WrapperStr & value, WrapperStr comment, WrapperStr description) { #ifdef TRACE QLOG_INFO() << "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(WrapperStr("<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()) { WrapperStr 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; }
WrapperStr capitalize(const WrapperStr & s) { return (s.isEmpty()) ? s : s.left(1).upper() + s.mid(1); }
// 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 UmlOperation::write_cpp_java_params(FileOut & out, WrapperStr decl) { int index1 = decl.find("${(}"); if (index1 == -1) return; int index2 = decl.find("${)}", index1 + 4); if (index2 == -1) return; decl = decl.mid(index1 + 4, index2 - index1 - 4); index1 = 0; const Q3ValueList<UmlParameter> p = params(); WrapperStr sparam; WrapperStr kname; WrapperStr ktype; int rank; while (get_param(decl, index1, sparam, kname, ktype, rank)) { if (rank < (int) p.count()) { const UmlParameter & pa = p[rank]; out.indent(); out << "<ownedParameter xmi:type=\"uml:Parameter\" name=\"" << pa.name << "\" xmi:id=\"BOUML_op_param_" << ++param_id << "\" direction =\""; if (_pk_prefix) out << "pk_"; switch (pa.dir) { case InputOutputDirection: out << "inout\">\n"; break; case OutputDirection: out << "out\">\n"; break; default: out << "in\">\n"; } UmlTypeSpec t = pa.type; if ((t.type != 0) || !(t.explicit_type = (_lang == Cpp) ? CppSettings::type(t.explicit_type) : JavaSettings::type(t.explicit_type)).isEmpty()) { out.indent(); out << "\t<type xmi:type=\"uml:Class\""; write_type(out, t, sparam, kname, ktype); out << "/>\n"; } out.indent(); out << "</ownedParameter>\n"; } } }