00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "classifiercodedocument.h"
00019
00020
00021 #include <kdebug.h>
00022 #include <qregexp.h>
00023
00024
00025 #include "association.h"
00026 #include "attribute.h"
00027 #include "operation.h"
00028 #include "classifierlistitem.h"
00029 #include "classifier.h"
00030 #include "codegenerator.h"
00031 #include "uml.h"
00032 #include "umldoc.h"
00033 #include "umlrole.h"
00034 #include "umlattributelist.h"
00035 #include "umloperationlist.h"
00036 #include "codegenerators/codegenfactory.h"
00037
00038
00039
00040
00041 ClassifierCodeDocument::ClassifierCodeDocument ( UMLClassifier * parent )
00042 {
00043 init (parent);
00044 }
00045
00046 ClassifierCodeDocument::~ClassifierCodeDocument ( )
00047 {
00048 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00049 {
00050 CodeClassField * cf = ccflit.current();
00051 delete cf;
00052 }
00053 m_classfieldVector.clear();
00054 }
00055
00056
00057
00058
00059
00060
00061
00062
00063
00066 CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType)
00067 {
00068 CodeClassFieldList list;
00069 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00070 {
00071 CodeClassField * cf = ccflit.current();
00072 if (cf->getClassFieldType() == cfType)
00073 list.append(cf);
00074 }
00075 return list;
00076 }
00077
00080 CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic)
00081 {
00082 CodeClassFieldList list;
00083 list.setAutoDelete(false);
00084 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00085 {
00086 CodeClassField * cf = ccflit.current();
00087 if (cf->getClassFieldType() == cfType && cf->getStatic() == isStatic)
00088 list.append(cf);
00089 }
00090 return list;
00091 }
00092
00095 CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, Uml::Visibility visibility)
00096 {
00097 CodeClassFieldList list;
00098 list.setAutoDelete(false);
00099 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00100 {
00101 CodeClassField * cf = ccflit.current();
00102 if (cf->getClassFieldType() == cfType && cf->getVisibility() == visibility)
00103 list.append(cf);
00104 }
00105 return list;
00106 }
00107
00110 CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic, Uml::Visibility visibility)
00111 {
00112 CodeClassFieldList list;
00113 list.setAutoDelete(false);
00114 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00115 {
00116 CodeClassField * cf = ccflit.current();
00117 if (cf->getClassFieldType() == cfType && cf->getVisibility() == visibility && cf->getStatic() == isStatic )
00118 list.append(cf);
00119 }
00120 return list;
00121 }
00122
00123
00124
00125 bool ClassifierCodeDocument::hasObjectVectorClassFields() {
00126 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00127 {
00128 CodeClassField * cf = ccflit.current();
00129 if(cf->getClassFieldType() != CodeClassField::Attribute)
00130 {
00131 UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject());
00132 QString multi = role->getMultiplicity();
00133 if (
00134 multi.contains(QRegExp("[23456789\\*]")) ||
00135 multi.contains(QRegExp("1\\d"))
00136 )
00137 return true;
00138 }
00139 }
00140 return false;
00141 }
00142
00143 bool ClassifierCodeDocument::hasClassFields() {
00144 if(m_classfieldVector.count() > 0 )
00145 return true;
00146 return false;
00147 }
00148
00152 bool ClassifierCodeDocument::hasAssociationClassFields() {
00153 CodeClassFieldList list = getSpecificClassFields(CodeClassField::Attribute);
00154 return (m_classfieldVector.count() - list.count()) > 0 ? true : false;
00155 }
00156
00160 bool ClassifierCodeDocument::hasAttributeClassFields() {
00161 CodeClassFieldList list = getSpecificClassFields(CodeClassField::Attribute);
00162 return list.count() > 0 ? true : false;
00163 }
00164
00169
00170
00171 bool ClassifierCodeDocument::addCodeClassField ( CodeClassField * add_object ) {
00172 UMLObject * umlobj = add_object->getParentObject();
00173 if(!(m_classFieldMap.contains(umlobj)))
00174 {
00175 m_classfieldVector.append(add_object);
00176 m_classFieldMap.insert(umlobj,add_object);
00177
00178 return true;
00179 }
00180 return false;
00181 }
00182
00183
00184 void ClassifierCodeDocument::addAttributeClassField (UMLClassifierListItem *obj, bool syncToParentIfAdded) {
00185 UMLAttribute *at = (UMLAttribute*)obj;
00186 CodeClassField * cf = CodeGenFactory::newCodeClassField(this, at);
00187 if(cf)
00188 if (addCodeClassField(cf) && syncToParentIfAdded)
00189 updateContent();
00190 }
00191
00195 bool ClassifierCodeDocument::removeCodeClassField ( CodeClassField * remove_object ) {
00196 UMLObject * umlobj = remove_object->getParentObject();
00197 if(m_classFieldMap.contains(umlobj))
00198 {
00199 if (m_classfieldVector.removeRef(remove_object))
00200 {
00201
00202 m_classFieldMap.remove(umlobj);
00203 delete remove_object;
00204 return true;
00205 }
00206 }
00207 return false;
00208 }
00209
00210 void ClassifierCodeDocument::removeAttributeClassField(UMLClassifierListItem *obj)
00211 {
00212 CodeClassField * remove_object = m_classFieldMap[obj];
00213 if(remove_object)
00214 removeCodeClassField(remove_object);
00215 }
00216
00217 void ClassifierCodeDocument::removeAssociationClassField (UMLAssociation *assoc )
00218 {
00219
00220
00221
00222 CodeClassField * remove_object = m_classFieldMap[assoc->getUMLRole(Uml::A)];
00223 if(remove_object)
00224 removeCodeClassField(remove_object);
00225
00226
00227 remove_object = m_classFieldMap[assoc->getUMLRole(Uml::B)];
00228 if(remove_object)
00229 removeCodeClassField(remove_object);
00230
00231 }
00232
00238 CodeClassFieldList * ClassifierCodeDocument::getCodeClassFieldList ( ) {
00239 return &m_classfieldVector;
00240 }
00241
00246 UMLClassifier * ClassifierCodeDocument::getParentClassifier ( ) {
00247 return m_parentclassifier;
00248 }
00249
00253 QPtrList<CodeOperation> ClassifierCodeDocument::getCodeOperations ( ) {
00254
00255 QPtrList<CodeOperation> list;
00256 list.setAutoDelete(false);
00257
00258 TextBlockList * tlist = getTextBlockList();
00259 for (TextBlock *tb = tlist->first(); tb; tb=tlist->next())
00260 {
00261 CodeOperation * cop = dynamic_cast<CodeOperation*>(tb);
00262 if(cop)
00263 list.append(cop);
00264 }
00265 return list;
00266 }
00267
00271 void ClassifierCodeDocument::addOperation (UMLClassifierListItem * o) {
00272 UMLOperation *op = dynamic_cast<UMLOperation*>(o);
00273 if (op == NULL) {
00274 kError() << "ClassifierCodeDocument::addOperation: arg is not a UMLOperation"
00275 << endl;
00276 }
00277 QString tag = CodeOperation::findTag(op);
00278 CodeOperation * codeOp = dynamic_cast<CodeOperation*>(findTextBlockByTag(tag, true));
00279 bool createdNew = false;
00280
00281
00282 if(!codeOp)
00283 {
00284 codeOp = CodeGenFactory::newCodeOperation(this, op);
00285 createdNew = true;
00286 }
00287
00288
00289
00290
00291 if(!addCodeOperation(codeOp))
00292 if(createdNew)
00293 delete codeOp;
00294
00295 }
00296
00300 void ClassifierCodeDocument::removeOperation (UMLClassifierListItem * op ) {
00301
00302 QString tag = CodeOperation::findTag((UMLOperation*)op);
00303 TextBlock *tb = findTextBlockByTag(tag, true);
00304 if(tb)
00305 {
00306 if(removeTextBlock(tb))
00307 delete tb;
00308 else
00309 kError()<<"Cant remove CodeOperation from ClassCodeDocument!"<<endl;
00310
00311 }
00312 else
00313 kError()<<"Cant Find codeOperation for deleted operation!"<<endl;
00314 }
00315
00316
00317
00318
00319 void ClassifierCodeDocument::addCodeClassFieldMethods(CodeClassFieldList &list )
00320 {
00321
00322 for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
00323 {
00324 CodeClassField * field = ccflit.current();
00325 CodeAccessorMethodList list = field->getMethodList();
00326 CodeAccessorMethod * method;
00327 for (CodeAccessorMethodListIt it(list); (method = it.current()) != NULL; ++it)
00328 {
00329
00330
00331
00332
00333
00334
00335
00336
00337 addTextBlock(method);
00338
00339 }
00340
00341 }
00342
00343 }
00344
00345
00346 void ClassifierCodeDocument::declareClassFields (CodeClassFieldList & list ,
00347 CodeGenObjectWithTextBlocks * parent )
00348 {
00349
00350 for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
00351 {
00352 CodeClassField * field = ccflit.current();
00353 CodeClassFieldDeclarationBlock * declBlock = field->getDeclarationCodeBlock();
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 parent->addTextBlock(declBlock);
00371
00372 }
00373 }
00374
00375 bool ClassifierCodeDocument::parentIsClass() {
00376 return (m_parentclassifier->getBaseType() == Uml::ot_Class);
00377 }
00378
00379 bool ClassifierCodeDocument::parentIsInterface() {
00380 return (m_parentclassifier->getBaseType() == Uml::ot_Interface);
00381 }
00382
00388 void ClassifierCodeDocument::init (UMLClassifier * c )
00389 {
00390
00391 m_parentclassifier = c;
00392 m_classfieldVector.setAutoDelete(false);
00393
00394 updateHeader();
00395 syncNamesToParent();
00396
00397
00398
00399 if (parentIsClass()) {
00400 connect(c,SIGNAL(attributeAdded(UMLClassifierListItem*)),this,SLOT(addAttributeClassField(UMLClassifierListItem*)));
00401 connect(c,SIGNAL(attributeRemoved(UMLClassifierListItem*)),this,SLOT(removeAttributeClassField(UMLClassifierListItem*)));
00402 }
00403
00404 connect(c,SIGNAL(sigAssociationEndAdded(UMLAssociation*)),this,SLOT(addAssociationClassField(UMLAssociation*)));
00405 connect(c,SIGNAL(sigAssociationEndRemoved(UMLAssociation*)),this,SLOT(removeAssociationClassField(UMLAssociation*)));
00406 connect(c,SIGNAL(operationAdded(UMLClassifierListItem*)),this,SLOT(addOperation(UMLClassifierListItem*)));
00407 connect(c,SIGNAL(operationRemoved(UMLClassifierListItem*)),this,SLOT(removeOperation(UMLClassifierListItem*)));
00408 connect(c,SIGNAL(modified()),this,SLOT(syncToParent()));
00409
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 void ClassifierCodeDocument::syncNamesToParent( ) {
00428 QString fileName = CodeGenerator::cleanName(getParentClassifier()->getName());
00429 if (!UMLApp::app()->activeLanguageIsCaseSensitive()) {
00430
00431 fileName = fileName.lower();
00432 }
00433 setFileName(fileName);
00434 setPackage(m_parentclassifier->getUMLPackage());
00435 }
00436
00437 void ClassifierCodeDocument::synchronize( ) {
00438
00439 updateHeader();
00440 syncNamesToParent();
00441 updateContent();
00442 syncClassFields();
00443 updateOperations();
00444
00445 }
00446
00447 void ClassifierCodeDocument::syncClassFields( )
00448 {
00449 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00450 {
00451 CodeClassField * cf = ccflit.current();
00452 cf->synchronize();
00453 }
00454 }
00455
00456 void ClassifierCodeDocument::updateOperations( ) {
00457
00458 UMLOperationList opList(getParentClassifier()->getOpList());
00459 for (UMLOperation *op = opList.first(); op; op = opList.next())
00460 {
00461 QString tag = CodeOperation::findTag(op);
00462 CodeOperation * codeOp = dynamic_cast<CodeOperation*>(findTextBlockByTag(tag, true));
00463 bool createdNew = false;
00464
00465 if(!codeOp)
00466 {
00467 codeOp = CodeGenFactory::newCodeOperation(this, op);
00468 createdNew = true;
00469 }
00470
00471
00472
00473
00474 if(!addCodeOperation(codeOp))
00475 if(createdNew)
00476 delete codeOp;
00477
00478
00479 if(!createdNew)
00480 codeOp->syncToParent();
00481 }
00482
00483 }
00484
00485 void ClassifierCodeDocument::syncToParent( ) {
00486 synchronize();
00487 }
00488
00493 void ClassifierCodeDocument::initCodeClassFields ( ) {
00494
00495 UMLClassifier * c = getParentClassifier();
00496
00497 if (parentIsClass()) {
00498 UMLAttributeList alist = c->getAttributeList();
00499 for(UMLAttribute * at = alist.first(); at; at = alist.next())
00500 {
00501 CodeClassField * field = CodeGenFactory::newCodeClassField(this, at);
00502 addCodeClassField(field);
00503 }
00504
00505 }
00506
00507
00508 UMLAssociationList ap = c->getSpecificAssocs(Uml::at_Association);
00509 UMLAssociationList ag = c->getAggregations();
00510 UMLAssociationList ac = c->getCompositions();
00511 UMLAssociationList selfAssoc = c->getSpecificAssocs(Uml::at_Association_Self);
00512
00513 updateAssociationClassFields(ap);
00514 updateAssociationClassFields(ag);
00515 updateAssociationClassFields(ac);
00516 updateAssociationClassFields(selfAssoc);
00517
00518 }
00519
00520 void ClassifierCodeDocument::updateAssociationClassFields ( UMLAssociationList &assocList )
00521 {
00522 CodeClassFieldList list;
00523 for(UMLAssociation * a=assocList.first(); a; a=assocList.next())
00524 addAssociationClassField(a, false);
00525 }
00526
00527 void ClassifierCodeDocument::addAssociationClassField (UMLAssociation * a, bool syncToParentIfAdded)
00528 {
00529
00530 Uml::IDType cid = getParentClassifier()->getID();
00531 bool printRoleA = false, printRoleB = false, shouldSync = false;
00532
00533
00534 if (a->getObjectId(Uml::A) == cid)
00535 printRoleB = true;
00536
00537 if (a->getObjectId(Uml::B) == cid)
00538 printRoleA = true;
00539
00540
00541 if (printRoleB)
00542 {
00543
00544 UMLRole * role = a->getUMLRole(Uml::B);
00545 if(!m_classFieldMap.contains((UMLObject*)role))
00546 {
00547 CodeClassField * classfield = CodeGenFactory::newCodeClassField(this, role);
00548 if( addCodeClassField(classfield))
00549 shouldSync = true;
00550 }
00551 }
00552
00553
00554 if (printRoleA)
00555 {
00556 UMLRole * role = a->getUMLRole(Uml::A);
00557 if(!m_classFieldMap.contains((UMLObject*)role))
00558 {
00559 CodeClassField * classfield = CodeGenFactory::newCodeClassField(this, role);
00560 if( addCodeClassField(classfield))
00561 shouldSync = true;
00562 }
00563 }
00564
00565 if (shouldSync && syncToParentIfAdded)
00566 syncToParent();
00567
00568 }
00569
00573 void ClassifierCodeDocument::setAttributesFromNode ( QDomElement & elem )
00574 {
00575
00576
00577
00578
00579
00580
00581
00582 QDomNode node = elem.firstChild();
00583 QDomElement childElem = node.toElement();
00584 while( !childElem.isNull() ) {
00585 QString tag = childElem.tagName();
00586 if( tag == "classfields" ) {
00587
00588 loadClassFieldsFromXMI(childElem);
00589 break;
00590 }
00591 node = childElem.nextSibling();
00592 childElem= node.toElement();
00593 }
00594
00595
00596
00597 CodeDocument::setAttributesFromNode(elem);
00598
00599 }
00600
00601
00602
00603 CodeClassField *
00604 ClassifierCodeDocument::findCodeClassFieldFromParentID (Uml::IDType id,
00605 int role_id)
00606 {
00607 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00608 {
00609 CodeClassField * cf = ccflit.current();
00610 if(role_id == -1) {
00611 if (STR2ID(cf->getID()) == id)
00612 return cf;
00613 } else {
00614 const Uml::Role_Type r = (Uml::Role_Type)role_id;
00615 UMLRole * role = dynamic_cast<UMLRole *>(cf->getParentObject());
00616 if(role && STR2ID(cf->getID()) == id && role->getRole() == r)
00617 return cf;
00618 }
00619 }
00620
00621
00622 kError() << "Failed to find codeclassfield for parent uml id:"
00623 << ID2STR(id) << " (role id:" << role_id
00624 << ") Do you have a corrupt classifier code document?"
00625 << endl;
00626
00627 return (CodeClassField*) NULL;
00628 }
00629
00630 void ClassifierCodeDocument::loadClassFieldsFromXMI( QDomElement & elem) {
00631
00632 QDomNode node = elem.firstChild();
00633 QDomElement childElem = node.toElement();
00634 while( !childElem.isNull() ) {
00635 QString nodeName = childElem.tagName();
00636 if( nodeName == "codeclassfield")
00637 {
00638 QString id = childElem.attribute("parent_id","-1");
00639 int role_id = childElem.attribute("role_id","-1").toInt();
00640 CodeClassField * cf = findCodeClassFieldFromParentID(STR2ID(id), role_id);
00641 if(cf)
00642 {
00643
00644
00645 m_classFieldMap.remove(cf->getParentObject());
00646
00647
00648 cf->loadFromXMI(childElem);
00649
00650
00651 m_classFieldMap.insert(cf->getParentObject(),cf);
00652
00653 } else
00654 kError()<<" LoadFromXMI: can't load classfield parent_id:"<<id<<" do you have a corrupt savefile?"<<endl;
00655 }
00656 node = childElem.nextSibling();
00657 childElem= node.toElement();
00658 }
00659 }
00660
00664 void ClassifierCodeDocument::saveToXMI ( QDomDocument & doc, QDomElement & root ) {
00665 #if 0
00666
00667 QString strType;
00668 if (getParentClassifier()->getBaseType() == Uml::ot_Datatype) {
00669 strType = getParentClassifier()->getName();
00670
00671
00672 if (getParentGenerator()->isReservedKeyword(strType))
00673 return;
00674 }
00675 #endif
00676 QDomElement docElement = doc.createElement( "classifiercodedocument" );
00677
00678 setAttributesOnNode(doc, docElement);
00679
00680 root.appendChild( docElement );
00681 }
00682
00686 void ClassifierCodeDocument::loadFromXMI ( QDomElement & root ) {
00687
00688
00689 setAttributesFromNode(root);
00690
00691
00692
00693 }
00694
00698 void ClassifierCodeDocument::setAttributesOnNode ( QDomDocument & doc, QDomElement & docElement)
00699 {
00700
00701
00702 CodeDocument::setAttributesOnNode(doc, docElement);
00703
00704
00705 docElement.setAttribute("parent_class", ID2STR(getParentClassifier()->getID()));
00706
00707
00708
00709 QDomElement fieldsElement = doc.createElement( "classfields" );
00710 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00711 {
00712 CodeClassField * field = ccflit.current();
00713 field->saveToXMI(doc, fieldsElement);
00714 }
00715 docElement.appendChild( fieldsElement);
00716
00717 }
00718
00719 TextBlock * ClassifierCodeDocument::findCodeClassFieldTextBlockByTag (const QString &tag)
00720 {
00721
00722 for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
00723 {
00724 CodeClassField * cf = ccflit.current();
00725 CodeClassFieldDeclarationBlock * decl = cf->getDeclarationCodeBlock();
00726 if(decl && decl->getTag() == tag)
00727 return decl;
00728
00729 CodeAccessorMethodList mlist = cf->getMethodList();
00730 CodeAccessorMethod *m;
00731 for (CodeAccessorMethodListIt it(mlist); (m = it.current()) != NULL; ++it)
00732 if(m->getTag() == tag)
00733 return m;
00734 }
00735
00736
00737 return (TextBlock*) NULL;
00738
00739 }
00740
00741
00742 #include "classifiercodedocument.moc"