Q3CString UmlClassMember::true_name(Q3CString decl) { int index = decl.find("${name}", 0); //[rageek] Removed CS=FALSE param - rethink this, case sensitive if (index == -1) // too complicated, return the Uml one return name(); int begin = index; while ((begin != 0) && identChar(decl[begin - 1])) begin -= 1; int sup = index + 7; while (identChar(decl[sup])) sup += 1; Q3CString r = decl.mid(begin, index - begin); Q3CString k = decl.mid(index + 2, 4); if (k == "name") r += name(); else if (k == "Name") r += name().left(1).upper() + name().mid(1); else // NAME r += name().upper(); r += decl.mid(index + 7, sup - index - 7); return r; }
Q3CString UmlClass::decl() { Q3CString result; Q3CString close_template; UmlArtifact * cp = associatedArtifact(); Q3CString nasp = ((UmlPackage *) ((cp != 0) ? (UmlItem *) cp : (UmlItem *) this)->package()) ->cppNamespace(); if (! nasp.isEmpty()) { int index = // bypass :: allowing ::a... ((nasp.at(0) == ':') && (nasp != "::")) ? 2 : 0; int index2 = 0; while ((index2 = nasp.find("::", index)) != -1) { result += "namespace " + nasp.mid(index, index2 - index) + " { "; close_template += " } "; index = index2 + 2; } result += "namespace " + nasp.mid(index) + " { "; close_template += " } "; } Q3CString template1; Q3CString template2; get_template_prefixes(template1, template2); if (!template1.isEmpty()) result += template1.left(template1.length() - 1) + ' '; result += cpp_stereotype() + ' '; return result + name() + ';' + close_template + '\n'; }
static void manage_decorators(QTextOStream & f, const Q3CString & 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 UmlArtifact::is_imported(Q3CString path, Q3CString class_name) { if (imports == 0) { imports = new Q3AsciiDict<UmlArtifact>(17); Q3CString 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)) { Q3CString p = s.mid(index2, index - index2); imports->insert(p, this); } else index = index2; } else index += 6; } } return ((imports->find(path + '.' + class_name) != 0) || (imports->find(path + ".*") != 0)); }
void UmlItem::write_multiplicity(FileOut & out, Q3CString s, UmlItem * who) { if (!s.isEmpty()) { Q3CString min; Q3CString 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 << "\"/>\n"; out.indent(); out << "<upperValue xmi:type=\"uml:LiteralString\""; out.id_prefix(who, "MULTIPLICITY_U_"); out << " value=\"" << max << "\"/>\n"; } }
void UmlRelation::write_relation(FileOut & out) { // note : it is the first side if (_assoc_class != 0) // generated in the association class return; const char * k = (_uml_20) ? "ownedElement" : "packagedElement"; out.indent(); out << '<' << k << " xmi:type=\"uml:Association\""; out.id_prefix(this, "ASSOC_"); Q3CString s = name(); int i1 = s.find("("); int i2 = s.findRev(")"); if ((i1 != -1) && (i2 != -1) && (i2 > i1) && (s[i1+1] != '<') && (s[i2-1] != '>')) { s = s.mid(i1 + 1, i2 - i1 - 1); if (!s.isEmpty()) { out << " name=\""; out.quote((const char*)s);//[jasa] ambiguous call out << '"'; } } write_visibility(out); out << ">\n"; write_ends(out); out.indent(); out << "</" << k << ">\n"; }
void UmlItem::replace_alias(Q3CString & s) { int index = 0; while ((index = s.find("@{", index)) != -1) { int index2 = s.find('}', index + 2); if (index2 == -1) return; UmlBaseItem * obj = this; Q3CString key = s.mid(index + 2, index2 - index - 2); Q3CString 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; } } } }
void tst_Q3CString::mid() { Q3CString a; a="ABCDEFGHIEfGEFG"; // 15 chars QCOMPARE(a.mid(3,3),(Q3CString)"DEF"); QCOMPARE(a.mid(0,0),(Q3CString)""); QVERIFY(a.mid(9999).isNull()); QVERIFY(a.mid(9999,1).isNull()); Q3CString n; QVERIFY(n.mid(3,3).isNull()); QVERIFY(n.mid(0,0).isNull()); QVERIFY(n.mid(9999,0).isNull()); QVERIFY(n.mid(9999,1).isNull()); }
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 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<Q3CString, int>::ConstIterator it; for (it = _datatypes.begin(); it != _datatypes.end(); ++it) { indent(); (*this) << pfix << " xmi:id=\"BOUML_datatype_" << it.data() << "\" name=\""; quote((const char*)it.key());//[jasa] ambiguous call (*this) << "\"/>\n"; } const char * postfix = (uml_20) ? "</ownedMember>\n" : "</packagedElement>\n"; for (it = _modifiedtypes.begin(); it != _modifiedtypes.end(); ++it) { Q3CString k = it.key(); int index = k.find('_'); indent(); (*this) << pfix << " xmi:id=\"BOUML_basedontype_" << it.data() << "\" 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) << "\"/>\n"; indent(); (*this) << "\t</xmi:Extension>\n"; indent(); (*this) << postfix; } else (*this) << "/>\n"; } }
Q3CString UmlOperation::compute_name(Q3CString s) { if (!s.isEmpty()) { UmlClassMember * m = getOf(); if ((m != 0) || ((m = setOf()) != 0)) { Q3CString n = (m->kind() == aRelation) ? ((UmlRelation *) m)->roleName() : m->name(); int index; if ((index = s.find("${name}")) != -1) return s.left(index) + n + s.mid(index + 7); else if ((index = s.find("${Name}")) != -1) return s.left(index) + n.left(1).upper() + n.mid(1) + s.mid(index + 7); else if ((index = s.find("${NAME}")) != -1) return s.left(index) + n.upper() + s.mid(index + 7); else return s; } } return name(); }
void UmlItem::write_default_value(FileOut & out, Q3CString 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"; } }
void UmlOperation::generate_imports(QTextOStream & f, Q3CString & made) { Q3CString 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 Q3ValueList<UmlParameter> & params = this->params(); Q3ValueListConstIterator<UmlParameter> 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); } } }
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); } } }
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 ClassContainer::compute_type(Q3CString type, UmlTypeSpec & typespec, Q3CString & typeform, bool get_first_template_actual, const Q3ValueList<FormalParameterList> & tmplts) { typespec.type = 0; typespec.explicit_type = 0; if (!strncmp((const char *) type, "struct ", 7) || !strncmp((const char *) type, "union ", 6) || !strncmp((const char *) type, "enum ", 5)) { typespec.explicit_type = "<complex type>"; typeform = type; return; } int index; if (get_first_template_actual && ((index = type.find('<')) != -1)) { type = Lex::normalize(type); index = type.find('<'); const char * p = type; if (strncmp(p + index + 1, "const ", 6) == 0) index += 6; // look at each actual in <> unsigned level = 1; int index2; Q3CString tf1; Q3CString t1; for (;;) { // earch for the current arg end for (index2 = index + 1; p[index2]; index2 += 1) { char c = p[index2]; if ((c == ',') || (c == '*') || (c == '[') || (c == '&')) { if (level == 1) break; } else if (c == '<') level += 1; else if ((c == '>') && (--level == 0)) break; } if (p[index2]) { Q3CString tf = type.left(index + 1) + typeform + type.mid(index2); Q3CString t = type.mid(index + 1, index2 - index - 1).stripWhiteSpace(); #ifdef DEBUG_BOUML cout << "typeform '" << tf << "' type '" << t << "'\n"; #endif UmlTypeSpec ts; Q3CString normalized = Lex::normalize(t); if (!find_type(normalized, ts) && (Namespace::current().isEmpty() || (normalized.at(0) == ':') || !find_type("::" + normalized, ts))) { if (get_first_template_actual) { get_first_template_actual = FALSE; tf1 = tf; t1 = t; } index = index2; } else { // find a class typeform = tf; type = t; typespec.type = ts.type; break; } } else if (!get_first_template_actual) { // has first actual typeform = tf1; type = t1; break; } else { typespec.explicit_type = type; return; } } } if (! tmplts.isEmpty()) { Q3ValueList<FormalParameterList>::ConstIterator it1; for (it1 = tmplts.begin(); it1 != tmplts.end(); ++it1) { FormalParameterList::ConstIterator it2; for (it2 = (*it1).begin(); it2 != (*it1).end(); ++it2) { if ((*it2).name() == type) { typespec.type = 0; typespec.explicit_type = type; return; } } } } Q3CString normalized; if (typespec.type == 0) { normalized = Lex::normalize(type); if (!find_type(normalized, typespec) && (Namespace::current().isEmpty() || (normalized.at(0) == ':') || !find_type("::" + normalized, typespec))) { typespec.explicit_type = CppSettings::umlType(type); if (typespec.explicit_type.isEmpty()) { // search for equivalent forms if (type == "long int") typespec.explicit_type = CppSettings::umlType("long"); else if (type == "long") typespec.explicit_type = CppSettings::umlType("long int"); else if (type == "unsigned long int") typespec.explicit_type = CppSettings::umlType("unsigned long"); else if (type == "unsigned long") typespec.explicit_type = CppSettings::umlType("unsigned long int"); else if (type == "unsigned") typespec.explicit_type = CppSettings::umlType("unsigned int"); else if (type == "unsigned int") typespec.explicit_type = CppSettings::umlType("unsigned"); else if ((type == "signed") || (type == "signed int")) typespec.explicit_type = CppSettings::umlType("int"); } if (typespec.explicit_type.isEmpty()) { typespec.explicit_type = type; /* if (!Lex::identifierp(type, TRUE)) typespec.explicit_type = type; else { Q3CString t = type; while ((index = t.find(':')) == 0) t = t.mid(1); ClassContainer * cc = Package::unknown(); while (index != -1) { if ((cc = cc->declare_if_needed(t.left(index))) == 0) { typespec.explicit_type = type; return; } while (t[index] == ':') index += 1; t = t.mid(index); index = t.find(':'); } if (((cc = cc->declare_if_needed(t)) == 0) || ((typespec.type = ((Class *) cc)->get_uml()) == 0)) typespec.explicit_type = type; }*/ } typespec.type = 0; } } if ((typespec.type != 0) && !typespec.type->formals().isEmpty() && (type.at(type.length() - 1) == '>') && (!typespec.type->inside_its_definition() || !typespec.type->is_itself((normalized.isEmpty()) ? Lex::normalize(type) : normalized))) { typespec.type = 0; typespec.explicit_type = type; } }
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); }
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; }
Q3CString capitalize(const Q3CString & s) { return (s.isEmpty()) ? s : s.left(1).upper() + s.mid(1); }
void UmlArtifact::generate() { if (! managed) { managed = TRUE; if (stereotype() == "text") { generate_text(); return; } else if (stereotype() != "source") return; package_of_generated_artifact = package(); const Q3CString def = idlSource(); if (def.isEmpty()) return; const Q3CString & name = this->name(); UmlPackage * pack = package(); Q3CString path = pack->path(name); Q3CString mod_start; Q3CString mod_end; Q3CString mod = pack->idlModule(); if (! mod.isEmpty()) { int index = 0; int index2; Q3CString closed = "\n}; // module "; while ((index2 = mod.find(':', index)) != -1) { Q3CString mo = mod.mid(index, index2 - index); mod_start += Q3CString("module ") + mo + " {\n\n"; closed += mo; mod_end = closed + "\n" + mod_end; closed += "::"; mod.replace(index2, 2, "_"); index = index2 + 1; } mod_start += Q3CString("module ") + mod.mid(index) + " {\n\n"; closed += mod.mid(index); mod_end = closed + "\n" + mod_end; } UmlCom::message(name); if (verbose()) UmlCom::trace(Q3CString("<hr><font face=helvetica>Generate code for <i> ") + name + "</i> in <i>" + path + "</i></font><br>"); else set_trace_header(Q3CString("<font face=helvetica>Generate code for <i> ") + name + "</i> in <i>" + path + "</i></font><br>"); #if 0 // compute dependencies Q3PtrList<CppRefType> dependencies; #endif const Q3PtrVector<UmlClass> & cls = associatedClasses(); unsigned n = cls.count(); unsigned index; #if 0 for (index = 0; index != n; index += 1) cls[index]->compute_dependencies(dependencies); #endif // generate source file QByteArray file; QTextOStream f(&file); const char * p = def; 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); else if (*p != '$') f << *p++; else if (!strncmp(p, "${comment}", 10)) manage_comment(p, pp); else if (!strncmp(p, "${description}", 14)) manage_description(p, pp); else if (!strncmp(p, "${name}", 7)) { p += 7; f << name; } else if (!strncmp(p, "${Name}", 7)) { p += 7; f << capitalize(name); } else if (!strncmp(p, "${NAME}", 7)) { p += 7; f << name.upper(); } else if (!strncmp(p, "${nAME}", 7)) { p += 7; f << name.lower(); } else if (!strncmp(p, "${module}", 9)) { p += 9; f << mod; } else if (!strncmp(p, "${MODULE}", 9)) { p += 9; f << mod.upper(); } else if (!strncmp(p, "${includes}", 11)) { p += 11; /*if (!incl_computed) { incl_computed = TRUE; CppRefType::compute(dependencies, hdef, srcdef, h_incl, decl, incl, this); } if (!incl.isEmpty()) { f << incl; if (*p != '\n') f << '\n'; } else*/ if (*p == '\n') p += 1; } else if (!strncmp(p, "${definition}", 13)) { p += 13; for (index = 0; index != n; index += 1) cls[index]->generate(f); if (*p == '\n') p += 1; } else if (!strncmp(p, "${module_start}", 15)) { p += 15; if (!mod_start.isEmpty()) f << mod_start; if (*p == '\n') p += 1; } else if (!strncmp(p, "${module_end}", 13)) { p += 13; if (!mod_end.isEmpty()) f << mod_end; if (*p == '\n') p += 1; } else // strange f << *p++; } f << '\000'; if (must_be_saved(path, file)) { write_trace_header(); FILE * fp; if ((fp = fopen((const char *) path, "wb")) == 0) { write_trace_header(); UmlCom::trace(Q3CString("<font color=\"red\"><b><i> ") + name + " : </i> cannot open <i> " + path + "</i>, edit the <i> generation settings</i> (tab directory) or the <i>" + pack->name() + "</i> Idl directory specification</b></font><br>"); incr_error(); } else { fputs((const char *) file, fp); fclose(fp); } } else if (get_trace_header().isEmpty()) UmlCom::trace(Q3CString("<font face=helvetica><i> ") + path + "</i> not modified</font><br>"); } }
bool UmlOperation::read_param(Class * container, unsigned rank, UmlParameter & param, Q3CString & def, bool bypass) { #ifdef TRACE QLOG_INFO() <<"UmlOperation::manage_param " << rank << "\n"; #endif Q3CString s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else if (s == ")") return FALSE; #ifdef TRACE QLOG_INFO() <<"commence par " << s << '\n'; #endif param.type.type = 0; param.type.explicit_type = 0; param.dir = InputOutputDirection; bool arrayp = FALSE; if (s == "array") { arrayp = TRUE; s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } } else if ((((const char *) s)[0] != '&') && (((const char *) s)[0] != '$')) { // a type container->compute_type(s, param.type, 0); s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } } bool refp; if (s == "&") { refp = TRUE; s = Lex::read_word(); if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } } else refp = FALSE; if (((const char *) s)[0] != '$') { Lex::syntax_error("invalid parameter name : " + s); return FALSE; } if (! bypass) { Q3CString n_close = Q3CString().setNum(rank) + "}"; param.name = s.mid(1); s = (rank == 0) ? "" : ", "; if (arrayp) s += "array "; else if ((param.type.type != 0) || !param.type.explicit_type.isEmpty()) { s += "${t" + n_close + " "; } if (refp) s += "& "; s += "${p" + n_close + "${v" + n_close; def.insert(def.find("${)}"), // cannot be -1 (const char *)s); } s = Lex::read_word(); if (s == "=") { Lex::mark(); s = skip_expr(0); param.default_value = Lex::region(); param.default_value.truncate(param.default_value.length() - s.length()); if (*((const char *) param.default_value) == ' ') param.default_value = param.default_value.mid(1); } else if (s.isEmpty()) { Lex::premature_eof(); return FALSE; } else param.default_value = 0; if (s == ")") Lex::unread_word(s); return TRUE; }