00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "operation.h"
00014
00015
00016 #include <qregexp.h>
00017 #include <kdebug.h>
00018 #include <klocale.h>
00019
00020
00021 #include "attribute.h"
00022 #include "classifier.h"
00023 #include "uml.h"
00024 #include "umldoc.h"
00025 #include "uniqueid.h"
00026 #include "dialogs/umloperationdialog.h"
00027
00028 UMLOperation::UMLOperation(const UMLClassifier *parent, const QString& name,
00029 Uml::IDType id, Uml::Visibility s, UMLObject *rt)
00030 : UMLClassifierListItem(parent, name, id)
00031 {
00032 if (rt)
00033 m_returnId = UniqueID::gen();
00034 else
00035 m_returnId = Uml::id_None;
00036 m_pSecondary = rt;
00037 m_Vis = s;
00038 m_BaseType = Uml::ot_Operation;
00039 m_bConst = false;
00040 }
00041
00042 UMLOperation::UMLOperation(const UMLClassifier * parent)
00043 : UMLClassifierListItem (parent)
00044 {
00045 m_BaseType = Uml::ot_Operation;
00046 m_bConst = false;
00047 }
00048
00049 UMLOperation::~UMLOperation() {
00050 }
00051
00052 void UMLOperation::setType(UMLObject *type) {
00053 UMLClassifierListItem::setType(type);
00054 if (m_returnId == Uml::id_None)
00055 m_returnId = UniqueID::gen();
00056 }
00057
00058 void UMLOperation::moveParmLeft(UMLAttribute * a) {
00059 if (a == NULL) {
00060 kDebug() << "UMLOperation::moveParmLeft called on NULL attribute"
00061 << endl;
00062 return;
00063 }
00064 kDebug() << "UMLOperation::moveParmLeft(" << a->getName() << ") called"
00065 << endl;
00066 disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
00067 int idx;
00068 if ( (idx=m_List.find( a )) == -1 ) {
00069 kDebug() << "Error move parm left " << a->getName() << endl;
00070 return;
00071 }
00072 if ( idx == 0 )
00073 return;
00074 m_List.remove( a );
00075 m_List.insert( idx-1, a );
00076 }
00077
00078 void UMLOperation::moveParmRight(UMLAttribute * a) {
00079 if (a == NULL) {
00080 kDebug() << "UMLOperation::moveParmRight called on NULL attribute"
00081 << endl;
00082 return;
00083 }
00084 kDebug() << "UMLOperation::moveParmRight(" << a->getName() << ") called"
00085 << endl;
00086 disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
00087 int idx;
00088 if ( (idx=m_List.find( a )) == -1 ) {
00089 kDebug() << "Error move parm right " << a->getName() << endl;
00090 return;
00091 }
00092 int count = m_List.count();
00093 if ( idx == count-1 )
00094 return;
00095 m_List.remove( a );
00096 m_List.insert( idx+1, a );
00097 }
00098
00099 void UMLOperation::removeParm(UMLAttribute * a, bool emitModifiedSignal ) {
00100 if (a == NULL) {
00101 kDebug() << "UMLOperation::removeParm called on NULL attribute"
00102 << endl;
00103 return;
00104 }
00105 kDebug() << "UMLOperation::removeParm(" << a->getName() << ") called"
00106 << endl;
00107 disconnect(a,SIGNAL(modified()),this,SIGNAL(modified()));
00108 if(!m_List.remove(a))
00109 kDebug() << "Error removing parm " << a->getName() << endl;
00110
00111 if (emitModifiedSignal)
00112 emit modified();
00113 }
00114
00115 UMLAttribute* UMLOperation::findParm(const QString &name) {
00116 UMLAttribute * obj=0;
00117 for (obj = m_List.first(); obj; obj = m_List.next()) {
00118 if (obj->getName() == name)
00119 return obj;
00120 }
00121 return 0;
00122 }
00123
00124 QString UMLOperation::toString(Uml::Signature_Type sig) {
00125 QString s = "";
00126
00127 if(sig == Uml::st_ShowSig || sig == Uml::st_NoSig)
00128 s = m_Vis.toString(true) + ' ';
00129
00130 s += getName();
00131 Uml::Programming_Language pl = UMLApp::app()->getActiveLanguage();
00132 bool parameterlessOpNeedsParentheses = (pl != Uml::pl_Pascal && pl != Uml::pl_Ada);
00133
00134 if (sig == Uml::st_NoSig || sig == Uml::st_NoSigNoVis) {
00135 if (parameterlessOpNeedsParentheses)
00136 s.append("()");
00137 return s;
00138 }
00139 int last = m_List.count();
00140 if (last) {
00141 s.append("(");
00142 int i = 0;
00143 for (UMLAttribute *param = m_List.first(); param; param = m_List.next()) {
00144 i++;
00145 s.append(param->toString(Uml::st_SigNoVis));
00146 if (i < last)
00147 s.append(", ");
00148 }
00149 s.append(")");
00150 } else if (parameterlessOpNeedsParentheses) {
00151 s.append("()");
00152 }
00153 UMLClassifier *ownParent = static_cast<UMLClassifier*>(parent());
00154 QString returnType;
00155 UMLClassifier *retType = UMLClassifierListItem::getType();
00156 if (retType) {
00157 UMLPackage *retVisibility = retType->getUMLPackage();
00158 if (retVisibility != ownParent && retVisibility != ownParent->getUMLPackage())
00159 returnType = retType->getFullyQualifiedName();
00160 else
00161 returnType = retType->getName();
00162 }
00163 if (returnType.length() > 0 && returnType != "void") {
00164 s.append(" : ");
00165
00166 if (returnType.startsWith("virtual ")) {
00167 s += returnType.mid(8);
00168 } else {
00169 s += returnType;
00170 }
00171 }
00172 return s;
00173 }
00174
00175 void UMLOperation::addParm(UMLAttribute *parameter, int position) {
00176 if( position >= 0 && position <= (int)m_List.count() )
00177 m_List.insert(position,parameter);
00178 else
00179 m_List.append( parameter );
00180 UMLObject::emitModified();
00181 connect(parameter,SIGNAL(modified()),this,SIGNAL(modified()));
00182 }
00183
00184 QString UMLOperation::getUniqueParameterName() {
00185 QString currentName = i18n("new_parameter");
00186 QString name = currentName;
00187 for (int number = 1; findParm(name); number++) {
00188 name = currentName + '_' + QString::number(number);
00189 }
00190 return name;
00191 }
00192
00193 bool UMLOperation::operator==( UMLOperation & rhs ) {
00194 if( this == &rhs )
00195 return true;
00196
00197 if( !UMLObject::operator==( rhs ) )
00198 return false;
00199
00200 if( getTypeName() != rhs.getTypeName() )
00201 return false;
00202
00203 if( m_List.count() != rhs.m_List.count() )
00204 return false;
00205
00206 if(!(m_List == rhs.m_List))
00207 return false;
00208
00209 return true;
00210 }
00211
00212 void UMLOperation::copyInto(UMLOperation *rhs) const
00213 {
00214 UMLClassifierListItem::copyInto(rhs);
00215
00216 m_List.copyInto(&(rhs->m_List));
00217 }
00218
00219 UMLObject* UMLOperation::clone() const
00220 {
00221
00222 UMLOperation *clone = new UMLOperation( static_cast<UMLClassifier*>(parent()) );
00223 copyInto(clone);
00224
00225 return clone;
00226 }
00227
00228 bool UMLOperation::resolveRef() {
00229 bool overallSuccess = UMLObject::resolveRef();
00230
00231 for (UMLAttributeListIt ait(m_List); ait.current(); ++ait) {
00232 UMLAttribute *pAtt = ait.current();
00233 if (! pAtt->resolveRef())
00234 overallSuccess = false;
00235 }
00236 return overallSuccess;
00237 }
00238
00239 bool UMLOperation::isConstructorOperation() {
00240
00241
00242 QString strConstructor ("constructor");
00243 if (getStereotype() == strConstructor)
00244 return true;
00245
00246 UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
00247 QString cName = c->getName();
00248 QString opName = getName();
00249
00250
00251 return (cName == opName);
00252 }
00253
00254 bool UMLOperation::isDestructorOperation() {
00255 if (getStereotype() == "destructor")
00256 return true;
00257 UMLClassifier * c = static_cast<UMLClassifier*>(this->parent());
00258
00259 QString cName = c->getName();
00260 QString opName = getName();
00261
00262
00263
00264 if (! opName.startsWith("~"))
00265 return false;
00266 opName.remove( QRegExp("^~\\s*") );
00267 return (cName == opName);
00268 }
00269
00270 bool UMLOperation::isLifeOperation() {
00271 return (isConstructorOperation() || isDestructorOperation());
00272 }
00273
00274 void UMLOperation::setConst(bool b) {
00275 m_bConst = b;
00276 }
00277
00278 bool UMLOperation::getConst() const {
00279 return m_bConst;
00280 }
00281
00282 bool UMLOperation::showPropertiesDialog(QWidget* parent) {
00283 UMLOperationDialog dialog(parent, this);
00284 return dialog.exec();
00285 }
00286
00287 void UMLOperation::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
00288 QDomElement operationElement = UMLObject::save("UML:Operation", qDoc);
00289 operationElement.setAttribute( "isQuery", m_bConst ? "true" : "false" );
00290 QDomElement featureElement = qDoc.createElement( "UML:BehavioralFeature.parameter" );
00291 if (m_pSecondary) {
00292 QDomElement retElement = qDoc.createElement("UML:Parameter");
00293 if (m_returnId == Uml::id_None) {
00294 kDebug() << "UMLOperation::saveToXMI(" << m_Name
00295 << "): m_returnId is not set, setting it now." << endl;
00296 m_returnId = UniqueID::gen();
00297 }
00298 retElement.setAttribute( "xmi.id", ID2STR(m_returnId) );
00299 retElement.setAttribute( "type", ID2STR(m_pSecondary->getID()) );
00300 retElement.setAttribute( "kind", "return" );
00301 featureElement.appendChild( retElement );
00302 } else {
00303 kDebug() << "UMLOperation::saveToXMI: m_SecondaryId is "
00304 << m_SecondaryId << endl;
00305 }
00306
00307 UMLAttribute* pAtt = 0;
00308 for( pAtt = m_List.first(); pAtt != 0; pAtt = m_List.next() ) {
00309 QDomElement attElement = pAtt->UMLObject::save("UML:Parameter", qDoc);
00310 UMLClassifier *attrType = pAtt->getType();
00311 if (attrType) {
00312 attElement.setAttribute( "type", ID2STR(attrType->getID()) );
00313 } else {
00314 attElement.setAttribute( "type", pAtt -> getTypeName() );
00315 }
00316 attElement.setAttribute( "value", pAtt -> getInitialValue() );
00317
00318 Uml::Parameter_Direction kind = pAtt->getParmKind();
00319 if (kind == Uml::pd_Out)
00320 attElement.setAttribute("kind", "out");
00321 else if (kind == Uml::pd_InOut)
00322 attElement.setAttribute("kind", "inout");
00323
00324
00325 featureElement.appendChild( attElement );
00326 }
00327 if (featureElement.hasChildNodes())
00328 operationElement.appendChild( featureElement );
00329 qElement.appendChild( operationElement );
00330 }
00331
00332 bool UMLOperation::load( QDomElement & element ) {
00333 m_SecondaryId = element.attribute( "type", "" );
00334 QString isQuery = element.attribute( "isQuery", "" );
00335 if (!isQuery.isEmpty()) {
00336
00337
00338 m_bConst = (isQuery == "true");
00339 }
00340 QDomNode node = element.firstChild();
00341 if (node.isComment())
00342 node = node.nextSibling();
00343 QDomElement attElement = node.toElement();
00344 while( !attElement.isNull() ) {
00345 QString tag = attElement.tagName();
00346 if (Uml::tagEq(tag, "BehavioralFeature.parameter")) {
00347 if (! load(attElement))
00348 return false;
00349 } else if (Uml::tagEq(tag, "Parameter")) {
00350 QString kind = attElement.attribute("kind", "");
00351 if (kind.isEmpty()) {
00352
00353 for (QDomNode n = attElement.firstChild(); !n.isNull(); n = n.nextSibling()) {
00354 if (n.isComment())
00355 continue;
00356 QDomElement tempElement = n.toElement();
00357 QString tag = tempElement.tagName();
00358 if (!Uml::tagEq(tag, "kind"))
00359 continue;
00360 kind = tempElement.attribute( "xmi.value", "" );
00361 break;
00362 }
00363 if (kind.isEmpty()) {
00364
00365
00366 kind = "in";
00367 }
00368 }
00369 if (kind == "return") {
00370 QString returnId = attElement.attribute("xmi.id", "");
00371 if (!returnId.isEmpty())
00372 m_returnId = STR2ID(returnId);
00373 m_SecondaryId = attElement.attribute( "type", "" );
00374 if (m_SecondaryId.isEmpty()) {
00375
00376 QDomNode node = attElement.firstChild();
00377 while (!node.isNull()) {
00378 if (node.isComment()) {
00379 node = node.nextSibling();
00380 continue;
00381 }
00382 QDomElement tempElement = node.toElement();
00383 QString tag = tempElement.tagName();
00384 if (!Uml::tagEq(tag, "type")) {
00385 node = node.nextSibling();
00386 continue;
00387 }
00388 m_SecondaryId = tempElement.attribute( "xmi.id", "" );
00389 if (m_SecondaryId.isEmpty())
00390 m_SecondaryId = tempElement.attribute( "xmi.idref", "" );
00391 if (m_SecondaryId.isEmpty()) {
00392 QDomNode inner = node.firstChild();
00393 QDomElement tmpElem = inner.toElement();
00394 m_SecondaryId = tmpElem.attribute( "xmi.id", "" );
00395 if (m_SecondaryId.isEmpty())
00396 m_SecondaryId = tmpElem.attribute( "xmi.idref", "" );
00397 }
00398 break;
00399 }
00400 if (m_SecondaryId.isEmpty()) {
00401 kError() << "UMLOperation::load(" << m_Name << "): "
00402 << "cannot find return type." << endl;
00403 }
00404 }
00405
00406 m_pSecondary = NULL;
00407 } else {
00408 UMLAttribute * pAtt = new UMLAttribute( this );
00409 if( !pAtt->loadFromXMI(attElement) ) {
00410 delete pAtt;
00411 return false;
00412 }
00413 if (kind == "out")
00414 pAtt->setParmKind(Uml::pd_Out);
00415 else if (kind == "inout")
00416 pAtt->setParmKind(Uml::pd_InOut);
00417 else
00418 pAtt->setParmKind(Uml::pd_In);
00419 m_List.append( pAtt );
00420 }
00421 }
00422 node = node.nextSibling();
00423 if (node.isComment())
00424 node = node.nextSibling();
00425 attElement = node.toElement();
00426 }
00427 return true;
00428 }
00429
00430
00431 #include "operation.moc"