예제 #1
0
bool UmlArtifact::set_roundtrip_expected()
{
    if ((stereotype() != "source") || cppSource().isEmpty())
        return TRUE;

    const Q3PtrVector<UmlClass> & cls = associatedClasses();

    if (cls.isEmpty()) {
        if ((name() == "main") && cppHeader().isEmpty())
            main_art = this;
        else
            return TRUE;
    }

    has_roundtrip_expected = TRUE;
    roundtrip_expected = TRUE;
    useless = TRUE;
    fully_updated = TRUE;
    ((UmlPackage *) parent()->parent())->get_package()->own(this);

    UmlClass ** v = cls.data();
    UmlClass ** vsup = v + cls.size();
    bool result = isWritable();

    for (; v != vsup; v += 1)
        result &= (*v)->set_roundtrip_expected();

    return result;
}
예제 #2
0
void UmlArtifact::write(FileOut & out)
{
    const char * k = (_uml_20) ? "ownedMember" : "packagedElement";

    out.indent();
    out << "<" << k << " xmi:type=\"uml:Artifact\"";
    out.id(this);
    out << " name=\"";
    out.quote((const char *)name()); //[jasa] ambiguous call
    out << "\">\n";
    out.indent(+1);

    write_description_properties(out);

    const Q3PtrVector<UmlItem> ch = children();
    unsigned i;
    unsigned n = ch.size();
    unsigned rank = 0;

    for (i = 0; i != n; i += 1) {
        UmlItem * x = ch[i];

        if ((x->kind() == aNcRelation) &&
            (x->stereotype() == "manifest") &&
            (((UmlNcRelation *) x)->relationKind() == aDependency))
            write_manifest(out, ((UmlNcRelation *) x)->target(), "dependency", ++rank);
        else
            ch[i]->write(out);
    }

    if (stereotype() == "source") {
        const Q3PtrVector<UmlClass> & cls = associatedClasses();

        n = cls.size();

        for (i = 0; i != n; i += 1)
            write_manifest(out, cls[i], "source", ++rank);
    }
    else {
        const Q3PtrVector<UmlArtifact> & arts = associatedArtifacts();

        n = arts.size();

        for (i = 0; i != n; i += 1)
            write_manifest(out, arts[i], 0, ++rank);
    }

    out.indent(-1);
    out.indent();
    out << "</" << k << ">\n";

    unload();

}
예제 #3
0
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>");
  }
}
예제 #4
0
void UmlArtifact::generate()
{
    if (! managed) {
        managed = TRUE;

        if (stereotype() == "text") {
            generate_text();
            return;
        }
        else if (stereotype() != "source")
            return;

        package_of_generated_artifact = package();
        current = this;

        const WrapperStr filedef = javaSource();

        if (filedef.isEmpty())
            return;

        const WrapperStr & name = this->name();
        WrapperStr path = package_of_generated_artifact->file_path(name);

        UmlCom::message(name);

        if (verbose())
            UmlCom::trace(WrapperStr("<hr><font face=helvetica>Generate code for <i> ")
                          + name + "</i> in " + path + "</i></font><br>");
        else
            set_trace_header(WrapperStr("<font face=helvetica>Generate code for <i> ")
                             + name + "</i> in " + path + "</i></font><br>");

        // get bodies if preserve
        const QVector<UmlClass*> & cls = associatedClasses();

        if (preserve())
            UmlOperation::read_bodies(path);

        // generate file

        unsigned n = cls.count();
        unsigned index;
        WrapperStr incl;
        QSharedPointer<QByteArray> headerFile(new QByteArray());
        QTextStream f(headerFile.data(), QIODevice::WriteOnly);
        const char * p = filedef;
        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, JavaSettings::isGenerateJavadocStyleComment());
            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, "${imports}", 10)) {
                WrapperStr indent = current_indent(p, filedef);

                for (index = 0; index != n; index += 1)
                    cls[index]->generate_import(f, indent);

                p += 10;

                if (*p == '\n')
                    p += 1;
            }
            else if (!strncmp(p, "${package}", 10)) {
                p += 10;

                const WrapperStr & package = package_of_generated_artifact->javaPackage();

                if (!package.isEmpty())
                    f << "package " << package << ";\n\n";

                if (*p == '\n')
                    p += 1;
            }
            else if (!strncmp(p, "${definition}", 13)) {
                WrapperStr indent = current_indent(p, filedef);

                for (index = 0; index != n; index += 1)
                    cls[index]->generate(f, indent);

                p += 13;

                if (*p == '\n')
                    p += 1;
            }
            else
                // strange
                f << *p++;
        }

        f << '\000';
        f.flush();

        if (must_be_saved(path, headerFile->data())) {
            write_trace_header();

            FILE * fp;

            if ((fp = fopen((const char *) path, "wb")) == 0) {
                write_trace_header();
                UmlCom::trace(WrapperStr("<font color=\"red\"><b><i> ")
                              + name + "</i> : cannot open <i> "
                              + path + "</i>, edit the <i> generation settings</i> (tab directory) or the <i>"
                              + package_of_generated_artifact->name()
                              + "</i> Java directory specification</b></font><br>");
                incr_error();
            }
            else {
                fputs((const char *) headerFile->data(), fp);
                fclose(fp);
            }
        }
        else if (get_trace_header().isEmpty())
            UmlCom::trace(WrapperStr("<font face=helvetica><i> ")
                          + path + "</i> not modified</font><br>");

        if (imports != 0) {
            delete imports;
            imports = 0;
        }
    }
}
예제 #5
0
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>");
        }
    }
}
예제 #6
0
void UmlArtifact::generate()
{
    if (! managed) {
        managed = TRUE;

        if (stereotype() == "text") {
            generate_text();
            return;
        }
        else if (stereotype() != "source")
            return;

        package_of_generated_artifact = package();
        current = this;

        const WrapperStr filedef = pythonSource();

        if (filedef.isEmpty())
            return;

        const WrapperStr & name = this->name();
        WrapperStr path = package_of_generated_artifact->file_path(name);

        UmlCom::message(name);

        if (verbose())
            UmlCom::trace(WrapperStr("<hr><font face=helvetica>Generate code for <i> ")
                          + name + "</i> in " + path + "</i></font><br>");
        else
            set_trace_header(WrapperStr("<font face=helvetica>Generate code for <i> ")
                             + name + "</i> in " + path + "</i></font><br>");

        // get bodies if preserve
        const QVector<UmlClass*> & cls = associatedClasses();

        if (preserve())
            UmlOperation::read_bodies(path);

        // generate file

        WrapperStr indent;
        BooL indent_needed;
        unsigned n = cls.count();
        unsigned index;
        QByteArray file;
        // note : QTextStream(FILE *) does not work under windows
        QTextStream f(&file);
        const char * p = filedef;
        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 == '@') {
                indent_needed = FALSE;
                manage_alias(p, f, indent, indent_needed);
            }
            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, "${definition}", 13)) {
                indent_needed = TRUE;

                for (index = 0; index != n; index += 1)
                    cls[index]->generate(f, indent, indent_needed);

                p += 13;

                if (*p == '\n')
                    p += 1;
            }
            else if (!strncmp(p, "${import}", 9)) {
                imports = "";
                generate_imports(f, imports);

                for (index = 0; index != n; index += 1)
                    cls[index]->generate_imports(f, imports);

                p += 9;
            }
            else
                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(WrapperStr("<font color=\"red\"><b><i> ")
                              + name + "</i> : cannot open <i> "
                              + path + "</i>, edit the <i> generation settings</i> (tab directory) or the <i>"
                              + package_of_generated_artifact->name()
                              + "</i> Python directory specification</b></font><br>");
                incr_error();
            }
            else {
                fputs((const char *) file, fp);
                fclose(fp);
            }
        }
        else if (get_trace_header().isEmpty())
            UmlCom::trace(WrapperStr("<font face=helvetica><i> ")
                          + path + "</i> not modified</font><br>");
    }
}