• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

umbrello/umbrello

  • sources
  • kde-4.12
  • kdesdk
  • umbrello
  • umbrello
  • codegenerators
  • ruby
rubywriter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * This program is free software; you can redistribute it and/or modify *
3  * it under the terms of the GNU General Public License as published by *
4  * the Free Software Foundation; either version 2 of the License, or *
5  * (at your option) any later version. *
6  * *
7  * copyright (C) 2005 *
8  * Richard Dale <Richard_Dale@tipitina.demon.co.uk> *
9  * copyright (C) 2006-2013 *
10  * Umbrello UML Modeller Authors <umbrello-devel@kde.org> *
11  ***************************************************************************/
12 
13 #include "rubywriter.h"
14 
15 #include "association.h"
16 #include "attribute.h"
17 #include "classifier.h"
18 #include "debug_utils.h"
19 #include "operation.h"
20 #include "umldoc.h"
21 #include "umlattributelist.h"
22 
23 #include <klocale.h>
24 #include <kmessagebox.h>
25 
26 #include <QFile>
27 #include <QRegExp>
28 #include <QTextStream>
29 
30 RubyWriter::RubyWriter()
31 {
32 }
33 
34 RubyWriter::~RubyWriter()
35 {
36 }
37 
42 void RubyWriter::writeClass(UMLClassifier *c)
43 {
44  if (!c) {
45  uDebug()<<"Cannot write class of NULL concept!";
46  return;
47  }
48 
49  UMLClassifierList superclasses = c->getSuperClasses();
50  UMLAssociationList aggregations = c->getAggregations();
51  UMLAssociationList compositions = c->getCompositions();
52 
53  //find an appropriate name for our file
54  fileName_ = findFileName(c, ".rb");
55  if (fileName_.isEmpty()) {
56  emit codeGenerated(c, false);
57  return;
58  }
59 
60  QFile fileh;
61  if (!openFile(fileh, fileName_)) {
62  emit codeGenerated(c, false);
63  return;
64  }
65  QTextStream h(&fileh);
66 
67  className_ = cleanName(c->name());
68 
70  //Start generating the code!!
72 
73  //try to find a heading file (license, coments, etc)
74  QString str;
75 
76  str = getHeadingFile(".rb");
77  if (!str.isEmpty()) {
78  str.replace(QRegExp("%filename%"), fileName_);
79  str.replace(QRegExp("%filepath%"), fileh.fileName());
80  h<<str<<m_endl;
81  }
82 
83  if (forceDoc() || !c->doc().isEmpty()) {
84  QString docStr = c->doc();
85  docStr.replace(QRegExp("\\n"), "\n# ");
86  docStr.remove("@ref ");
87  docStr.replace("@see", "_See_");
88  docStr.replace("@short", "_Summary_");
89  docStr.replace("@author", "_Author_");
90  h<<"#"<<m_endl;
91  h<<"# "<<docStr<<m_endl;
92  h<<"#"<<m_endl<<m_endl;
93  }
94 
95  // write inheritances out
96  UMLClassifier *concept;
97 
98  h<< "class " << cppToRubyType(className_) << (superclasses.count() > 0 ? " < ":"");
99 
100  int i = 0;
101  foreach (concept, superclasses) {
102  if (i == 0) {
103  h << cppToRubyType(concept->name()) << m_endl;
104  } else {
105  // Assume ruby modules that can be mixed in, after the first
106  // superclass name in the list
107  h << m_indentation << "include "<< cppToRubyType(concept->name()) << m_endl;
108  }
109  i++;
110  }
111 
112  h << m_endl;
113 
114  // write comment for sub-section IF needed
115  if (forceDoc() || c->hasAccessorMethods()) {
116  h << m_indentation << "#" << m_endl;
117  h << m_indentation << "# Accessor Methods" << m_endl;
118  h << m_indentation << "#" << m_endl << m_endl;
119 
120  // Accessor methods for attributes
121  writeAttributeMethods(c->getAttributeList(Uml::Visibility::Public), Uml::Visibility::Public, h);
122  writeAttributeMethods(c->getAttributeList(Uml::Visibility::Protected), Uml::Visibility::Protected, h);
123  writeAttributeMethods(c->getAttributeList(Uml::Visibility::Private), Uml::Visibility::Private, h);
124  h << m_endl;
125  }
126 
127  //operations
128  writeOperations(c, h);
129 
130  //finish files
131  h << "end" << m_endl << m_endl;
132 
133  //close files and notfiy we are done
134  fileh.close();
135  emit codeGenerated(c, true);
136 }
137 
143 QString RubyWriter::cppToRubyType(const QString &typeStr)
144 {
145  QString type = cleanName(typeStr);
146  type.remove("const ");
147  type.remove(QRegExp("[*&\\s]"));
148  type.replace(QRegExp("[<>]"), "_");
149  type.replace("QStringList", "Array");
150  type.replace("QString", "String");
151  type.replace("bool", "true|false");
152  type.replace(QRegExp("^(uint|int|ushort|short|ulong|long)$"), "Integer");
153  type.replace(QRegExp("^(float|double)$"), "Float");
154  type.replace(QRegExp("^Q(?=[A-Z])"), "Qt::");
155  type.replace(QRegExp("^K(?!(DE|Parts|IO)"), "KDE::");
156 
157  return type;
158 }
159 
165 QString RubyWriter::cppToRubyName(const QString &nameStr)
166 {
167  QString name = cleanName(nameStr);
168  name.remove(QRegExp("^m_"));
169  name.remove(QRegExp("^[pbn](?=[A-Z])"));
170  name = name.mid(0, 1).toLower() + name.mid(1);
171  return name;
172 }
173 
179 void RubyWriter::writeOperations(UMLClassifier *c, QTextStream &h)
180 {
181  //Lists to store operations sorted by scope
182  UMLOperationList oppub, opprot, oppriv;
183 
184  //sort operations by scope first and see if there are abstract methods
185  UMLOperationList opl(c->getOpList());
186  foreach (UMLOperation *op, opl) {
187  switch(op->visibility()) {
188  case Uml::Visibility::Public:
189  oppub.append(op);
190  break;
191  case Uml::Visibility::Protected:
192  opprot.append(op);
193  break;
194  case Uml::Visibility::Private:
195  oppriv.append(op);
196  break;
197  default:
198  break;
199  }
200  }
201 
202  QString classname(cleanName(c->name()));
203 
204  //write operations to file
205  if (forceSections() || !oppub.isEmpty()) {
206  writeOperations(classname, oppub, Uml::Visibility::Public, h);
207  }
208 
209  if (forceSections() || !opprot.isEmpty()) {
210  writeOperations(classname, opprot, Uml::Visibility::Protected, h);
211  }
212 
213  if (forceSections() || !oppriv.isEmpty()) {
214  writeOperations(classname, oppriv, Uml::Visibility::Private, h);
215  }
216 }
217 
225 void RubyWriter::writeOperations(const QString &classname, const UMLOperationList &opList,
226  Uml::Visibility::Enum permitScope, QTextStream &h)
227 {
228 // UMLOperation *op;
229 // UMLAttribute *at;
230 
231  switch (permitScope) {
232  case Uml::Visibility::Public:
233  h << m_indentation << "public" << m_endl << m_endl;
234  break;
235  case Uml::Visibility::Protected:
236  h << m_indentation << "protected" << m_endl << m_endl;
237  break;
238  case Uml::Visibility::Private:
239  h << m_indentation << "private" << m_endl << m_endl;
240  break;
241  default:
242  break;
243  }
244 
245  foreach (const UMLOperation* op, opList) {
246  QString methodName = cleanName(op->name());
247  QStringList commentedParams;
248 
249  // Skip destructors, and operator methods which
250  // can't be defined in ruby
251  if (methodName.startsWith('~')
252  || methodName == "operator ="
253  || methodName == "operator --"
254  || methodName == "operator ++"
255  || methodName == "operator !=")
256  {
257  continue;
258  }
259 
260  if (methodName == classname) {
261  methodName = "initialize";
262  }
263 
264  methodName.remove("operator ");
265  methodName = methodName.mid(0, 1).toLower() + methodName.mid(1);
266 
267  UMLAttributeList atl = op->getParmList();
268  // Always write out the docs for ruby as the type of the
269  // arguments and return value of the methods is useful
270  bool writeDoc = true;
271 // for (UMLAttribute& at = atl.first(); at; at = atl.next())
272 // writeDoc |= !at->getDoc().isEmpty();
273 
274  if (writeDoc) {
275  h << m_indentation << "#" << m_endl;
276  QString docStr = op->doc();
277 
278  docStr.replace(QRegExp("[\\n\\r]+ *"), m_endl);
279  docStr.replace(QRegExp("[\\n\\r]+\\t*"), m_endl);
280 
281  docStr.replace(" m_", " ");
282  docStr.replace(QRegExp("\\s[npb](?=[A-Z])"), " ");
283  QRegExp re_params("@param (\\w)(\\w*)");
284  int pos = re_params.indexIn(docStr);
285  while (pos != -1) {
286  docStr.replace(re_params.cap(0),
287  QString("@param _") + re_params.cap(1).toLower() + re_params.cap(2) + '_');
288  commentedParams.append(re_params.cap(1).toLower() + re_params.cap(2));
289 
290  pos += re_params.matchedLength() + 3;
291  pos = re_params.indexIn(docStr, pos);
292  }
293 
294  docStr.replace('\n', QString("\n") + m_indentation + "# ");
295 
296  // Write parameter documentation
297  foreach (UMLAttribute* at, atl) {
298  // Only write an individual @param entry if one hasn't been found already
299  // in the main doc comment
300  if (commentedParams.contains(cppToRubyName(at->name())) == 0) {
301  docStr += (m_endl + m_indentation + "# @param _" + cppToRubyName(at->name()) + '_');
302  if (at->doc().isEmpty()) {
303  docStr += (' ' + cppToRubyType(at->getTypeName()));
304  } else {
305  docStr += (' ' + at->doc().replace(QRegExp("[\\n\\r]+[\\t ]*"), m_endl + " "));
306  }
307  }
308  }
309 
310  docStr.remove("@ref ");
311  docStr.replace("@param", "*");
312  docStr.replace("@return", "* _returns_");
313 
314  // All lines after the first '# *' in the doc comment
315  // must be indented correctly. If they aren't a list
316  // item starting with '# *', then indent the text with
317  // three spaces, '# ', to line up with the list item.
318  pos = docStr.indexOf("# *");
319  QRegExp re_linestart("# (?!\\*)");
320  pos = re_linestart.indexIn(docStr, pos);
321  while (pos > 0) {
322  docStr.insert(pos + 1, " ");
323 
324  pos += re_linestart.matchedLength() + 2;
325  pos = re_linestart.indexIn(docStr, pos);
326  }
327 
328  h << m_indentation << "# "<< docStr << m_endl;
329 
330  QString typeStr = cppToRubyType(op->getTypeName());
331  if (!typeStr.isEmpty() && typeStr != "void" && docStr.contains("_returns_") == 0) {
332  h << m_indentation << "# * _returns_ " << typeStr << m_endl;
333  }
334  }
335 
336  h<< m_indentation << "def " + methodName << "(";
337 
338  int j=0;
339  foreach (UMLAttribute* at, atl) {
340  QString nameStr = cppToRubyName(at->name());
341  if (j > 0) {
342  h << ", " << nameStr;
343  } else {
344  h << nameStr;
345  }
346  h << (!(at->getInitialValue().isEmpty()) ?
347  (QString(" = ") + cppToRubyType(at->getInitialValue())) :
348  QString(""));
349  j++;
350  }
351 
352  h <<")" << m_endl;
353 
354  // write body
355  QString sourceCode = op->getSourceCode();
356  if (sourceCode.isEmpty()) { // empty method body
357  h << m_indentation << m_indentation << m_endl;
358  }
359  else {
360  h << formatSourceCode(sourceCode, m_indentation + m_indentation);
361  }
362 
363  h << m_indentation << "end" << m_endl << m_endl;
364 
365  }//end for
366 }
367 
374 void RubyWriter::writeAttributeMethods(UMLAttributeList attribs,
375  Uml::Visibility::Enum visibility, QTextStream &stream)
376 {
377  // return now if NO attributes to work on
378  if (attribs.count() == 0 || visibility == Uml::Visibility::Private)
379  return;
380 
381  UMLAttribute *at;
382  foreach (at, attribs)
383  {
384  QString varName = cppToRubyName(cleanName(at->name()));
385 
386  writeSingleAttributeAccessorMethods(varName, at->doc(), stream);
387  }
388 
389 }
390 
398 void RubyWriter::writeSingleAttributeAccessorMethods(
399  const QString &fieldName,
400  const QString &descr,
401  QTextStream &h)
402 {
403  QString description = descr;
404  description.remove(QRegExp("m_[npb](?=[A-Z])"));
405  description.remove("m_");
406  description.replace('\n', QString("\n") + m_indentation + "# ");
407 
408  if (!description.isEmpty()) {
409  h << m_indentation << "# " << description << m_endl;
410  }
411 
412  h << m_indentation << "attr_accessor :" << fieldName << m_endl << m_endl;
413 
414  return;
415 }
416 
421 Uml::ProgrammingLanguage::Enum RubyWriter::language() const
422 {
423  return Uml::ProgrammingLanguage::Ruby;
424 }
425 
430 QStringList RubyWriter::reservedKeywords() const
431 {
432  static QStringList keywords;
433 
434  if (keywords.isEmpty()) {
435  keywords << "__FILE__"
436  << "__LINE__"
437  << "BEGIN"
438  << "END"
439  << "alias"
440  << "and"
441  << "begin"
442  << "break"
443  << "case"
444  << "class"
445  << "def"
446  << "defined?"
447  << "do"
448  << "else"
449  << "elsif"
450  << "end"
451  << "ensure"
452  << "false"
453  << "for"
454  << "if"
455  << "in"
456  << "module"
457  << "next"
458  << "nil"
459  << "not"
460  << "or"
461  << "redo"
462  << "rescue"
463  << "retry"
464  << "return"
465  << "self"
466  << "super"
467  << "then"
468  << "true"
469  << "undef"
470  << "unless"
471  << "until"
472  << "when"
473  << "while"
474  << "yield";
475  }
476 
477  return keywords;
478 }
479 
480 #include "rubywriter.moc"
UMLCanvasObject::getAggregations
UMLAssociationList getAggregations()
Shorthand for getSpecificAssocs(Uml::at_Aggregation)
Definition: umlcanvasobject.cpp:421
RubyWriter::~RubyWriter
virtual ~RubyWriter()
Definition: rubywriter.cpp:34
Uml::ProgrammingLanguage::Ruby
Definition: basictypes.h:257
UMLClassifier
This class defines the non-graphical information required for a UML Classifier (ie a class or interfa...
Definition: classifier.h:39
SimpleCodeGenerator::className_
QString className_
Definition: simplecodegenerator.h:49
RubyWriter::reservedKeywords
virtual QStringList reservedKeywords() const
Get list of reserved keywords.
Definition: rubywriter.cpp:430
association.h
UMLAttribute::getInitialValue
QString getInitialValue() const
Returns The initial value of the UMLAttribute.
Definition: attribute.cpp:98
Uml::Visibility::Enum
Enum
Definition: basictypes.h:56
UMLObject::visibility
Uml::Visibility::Enum visibility() const
Returns the visibility of the object.
Definition: umlobject.cpp:435
CodeGenerator::openFile
bool openFile(QFile &file, const QString &name)
Opens a file named "name" for writing in the outputDirectory.
Definition: codegenerator.cpp:586
SimpleCodeGenerator::findFileName
QString findFileName(UMLPackage *concept, const QString &ext)
Determine the file name.
Definition: simplecodegenerator.cpp:89
Uml::ProgrammingLanguage::Enum
Enum
Definition: basictypes.h:241
UMLAttribute
This class is used to set up information for an attribute.
Definition: attribute.h:27
UMLAttributeList
This sub-class adds copyInto and clone to the QPtrList base class.
Definition: umlattributelist.h:26
SimpleCodeGenerator::m_indentation
QString m_indentation
Definition: simplecodegenerator.h:74
RubyWriter::RubyWriter
RubyWriter()
Definition: rubywriter.cpp:30
CodeGenerator::getHeadingFile
virtual QString getHeadingFile(const QString &file)
Gets the heading file (as a string) to be inserted at the beginning of the generated file...
Definition: codegenerator.cpp:482
classifier.h
debug_utils.h
description
static const char description[]
Definition: docgenerators/main.cpp:37
Uml::Visibility::Private
Definition: basictypes.h:58
RubyWriter::language
virtual Uml::ProgrammingLanguage::Enum language() const
Returns "Ruby".
Definition: rubywriter.cpp:421
CodeGenerator::forceDoc
bool forceDoc() const
Definition: codegenerator.cpp:841
SimpleCodeGenerator::m_endl
QString m_endl
Definition: simplecodegenerator.h:76
attribute.h
umlattributelist.h
CodeGenerator::codeGenerated
void codeGenerated(UMLClassifier *concept, bool generated)
UMLCanvasObject::getCompositions
UMLAssociationList getCompositions()
Shorthand for getSpecificAssocs(Uml::at_Composition)
Definition: umlcanvasobject.cpp:431
UMLClassifierList
QList< UMLClassifier * > UMLClassifierList
Definition: umlclassifierlist.h:17
uDebug
#define uDebug()
Definition: debug_utils.h:95
CodeGenerator::formatSourceCode
static QString formatSourceCode(const QString &code, const QString &indentation)
Format source code for output in source files by adding the correct indentation to every line of code...
Definition: codegenerator.cpp:803
rubywriter.h
Uml::Visibility::Public
Definition: basictypes.h:57
UMLCanvasObject::getSuperClasses
UMLClassifierList getSuperClasses()
Return a list of the superclasses of this concept.
Definition: umlcanvasobject.cpp:359
UMLClassifier::getAttributeList
UMLAttributeList getAttributeList() const
Returns the attributes for the specified scope.
Definition: classifier.cpp:441
operation.h
umldoc.h
UMLOperation
This class represents an operation in the UML model.
Definition: operation.h:24
RubyWriter::writeClass
virtual void writeClass(UMLClassifier *c)
Call this method to generate C++ code for a UMLClassifier.
Definition: rubywriter.cpp:42
Import_Rose::methodName
void methodName(const QString &m)
Definition: import_rose.cpp:43
UMLOperation::getSourceCode
QString getSourceCode() const
Returns the source code for this operation.
Definition: operation.cpp:440
UMLClassifier::getOpList
UMLOperationList getOpList(bool includeInherited=false, UMLClassifierSet *alreadyTraversed=0)
Return a list of operations for the Classifier.
Definition: classifier.cpp:960
UMLClassifier::hasAccessorMethods
bool hasAccessorMethods()
Return true if this classifier has accessor methods.
Definition: classifier.cpp:1333
UMLObject::name
QString name() const
Returns a copy of m_name.
Definition: umlobject.cpp:185
CodeGenerator::forceSections
bool forceSections() const
Definition: codegenerator.cpp:851
SimpleCodeGenerator::fileName_
QString fileName_
Definition: simplecodegenerator.h:50
CodeGenerator::cleanName
static QString cleanName(const QString &name)
Replaces spaces with underscores and capitalises as defined in m_modname.
Definition: codegenerator.cpp:609
UMLClassifierListItem::getTypeName
virtual QString getTypeName() const
Returns the type name of the UMLClassifierListItem.
Definition: classifierlistitem.cpp:110
Uml::Visibility::Protected
Definition: basictypes.h:59
QList
UMLObject::doc
QString doc() const
Returns the documentation for the object.
Definition: umlobject.cpp:404
UMLOperation::getParmList
UMLAttributeList getParmList() const
Returns a list of parameters.
Definition: operation.cpp:171
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:06:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

umbrello/umbrello

Skip menu "umbrello/umbrello"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal