You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
743 lines
24 KiB
743 lines
24 KiB
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* copyright (C) 2004-2007 *
|
|
* Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
|
|
***************************************************************************/
|
|
|
|
/* This code generated by:
|
|
* Author : thomas
|
|
* Date : Thu Jun 19 2003
|
|
*/
|
|
|
|
// own header
|
|
#include "classifiercodedocument.h"
|
|
|
|
// qt/kde includes
|
|
#include <kdebug.h>
|
|
#include <tqregexp.h>
|
|
|
|
// local includes
|
|
#include "association.h"
|
|
#include "attribute.h"
|
|
#include "operation.h"
|
|
#include "classifierlistitem.h"
|
|
#include "classifier.h"
|
|
#include "codegenerator.h"
|
|
#include "uml.h"
|
|
#include "umldoc.h"
|
|
#include "umlrole.h"
|
|
#include "umlattributelist.h"
|
|
#include "umloperationlist.h"
|
|
#include "codegenerators/codegenfactory.h"
|
|
|
|
// Constructors/Destructors
|
|
//
|
|
|
|
ClassifierCodeDocument::ClassifierCodeDocument ( UMLClassifier * parent )
|
|
{
|
|
init (parent);
|
|
}
|
|
|
|
ClassifierCodeDocument::~ClassifierCodeDocument ( )
|
|
{
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
delete cf;
|
|
}
|
|
m_classfieldVector.clear();
|
|
}
|
|
|
|
//
|
|
// Methods
|
|
//
|
|
|
|
|
|
// Accessor methods
|
|
//
|
|
|
|
/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
|
|
*/
|
|
CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType)
|
|
{
|
|
CodeClassFieldList list;
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
if (cf->getClassFieldType() == cfType)
|
|
list.append(cf);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
|
|
*/
|
|
CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic)
|
|
{
|
|
CodeClassFieldList list;
|
|
list.setAutoDelete(false);
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
if (cf->getClassFieldType() == cfType && cf->getStatic() == isStatic)
|
|
list.append(cf);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
|
|
*/
|
|
CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, Uml::Visibility visibility)
|
|
{
|
|
CodeClassFieldList list;
|
|
list.setAutoDelete(false);
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
if (cf->getClassFieldType() == cfType && cf->getVisibility() == visibility)
|
|
list.append(cf);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/** get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
|
|
*/
|
|
CodeClassFieldList ClassifierCodeDocument::getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic, Uml::Visibility visibility)
|
|
{
|
|
CodeClassFieldList list;
|
|
list.setAutoDelete(false);
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
if (cf->getClassFieldType() == cfType && cf->getVisibility() == visibility && cf->getStatic() == isStatic )
|
|
list.append(cf);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// do we have accessor methods for lists of objects?
|
|
// (as opposed to lists of primitive types like 'int' or 'float', etc)
|
|
bool ClassifierCodeDocument::hasObjectVectorClassFields() {
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
if(cf->getClassFieldType() != CodeClassField::Attribute)
|
|
{
|
|
UMLRole * role = dynamic_cast<UMLRole*>(cf->getParentObject());
|
|
TQString multi = role->getMultiplicity();
|
|
if (
|
|
multi.contains(TQRegExp("[23456789\\*]")) ||
|
|
multi.contains(TQRegExp("1\\d"))
|
|
)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool ClassifierCodeDocument::hasClassFields() {
|
|
if(m_classfieldVector.count() > 0 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Tell if one or more codeclassfields are derived from associations.
|
|
*/
|
|
bool ClassifierCodeDocument::hasAssociationClassFields() {
|
|
CodeClassFieldList list = getSpecificClassFields(CodeClassField::Attribute);
|
|
return (m_classfieldVector.count() - list.count()) > 0 ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Tell if one or more codeclassfields are derived from attributes.
|
|
*/
|
|
bool ClassifierCodeDocument::hasAttributeClassFields() {
|
|
CodeClassFieldList list = getSpecificClassFields(CodeClassField::Attribute);
|
|
return list.count() > 0 ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Add a CodeClassField object to the m_classfieldVector List
|
|
* @return boolean true if successful in adding
|
|
*/
|
|
// We DON'T add methods of the code classfield here because we need to allow
|
|
// the codegenerator writer the liberty to organize their document as they desire.
|
|
bool ClassifierCodeDocument::addCodeClassField ( CodeClassField * add_object ) {
|
|
UMLObject * umlobj = add_object->getParentObject();
|
|
if(!(m_classFieldMap.contains(umlobj)))
|
|
{
|
|
m_classfieldVector.append(add_object);
|
|
m_classFieldMap.insert(umlobj,add_object);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// this is a slot..should only be called from a signal
|
|
void ClassifierCodeDocument::addAttributeClassField (UMLClassifierListItem *obj, bool syncToParentIfAdded) {
|
|
UMLAttribute *at = (UMLAttribute*)obj;
|
|
CodeClassField * cf = CodeGenFactory::newCodeClassField(this, at);
|
|
if(cf)
|
|
if (addCodeClassField(cf) && syncToParentIfAdded)
|
|
updateContent();
|
|
}
|
|
|
|
/**
|
|
* Remove a CodeClassField object from m_classfieldVector List
|
|
*/
|
|
bool ClassifierCodeDocument::removeCodeClassField ( CodeClassField * remove_object ) {
|
|
UMLObject * umlobj = remove_object->getParentObject();
|
|
if(m_classFieldMap.contains(umlobj))
|
|
{
|
|
if (m_classfieldVector.removeRef(remove_object))
|
|
{
|
|
// remove from our classfield map
|
|
m_classFieldMap.remove(umlobj);
|
|
delete remove_object;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ClassifierCodeDocument::removeAttributeClassField(UMLClassifierListItem *obj)
|
|
{
|
|
CodeClassField * remove_object = m_classFieldMap[obj];
|
|
if(remove_object)
|
|
removeCodeClassField(remove_object);
|
|
}
|
|
|
|
void ClassifierCodeDocument::removeAssociationClassField (UMLAssociation *assoc )
|
|
{
|
|
|
|
// the object could be either (or both!) role a or b. We should check
|
|
// both parts of the association.
|
|
CodeClassField * remove_object = m_classFieldMap[assoc->getUMLRole(Uml::A)];
|
|
if(remove_object)
|
|
removeCodeClassField(remove_object);
|
|
|
|
// check role b
|
|
remove_object = m_classFieldMap[assoc->getUMLRole(Uml::B)];
|
|
if(remove_object)
|
|
removeCodeClassField(remove_object);
|
|
|
|
}
|
|
|
|
/**
|
|
* Get the list of CodeClassField objects held by m_classfieldVector
|
|
* @return CodeClassFieldList list of CodeClassField objects held by
|
|
* m_classfieldVector
|
|
*/
|
|
CodeClassFieldList * ClassifierCodeDocument::getCodeClassFieldList ( ) {
|
|
return &m_classfieldVector;
|
|
}
|
|
|
|
/**
|
|
* Get the value of m_parentclassifier
|
|
* @return the value of m_parentclassifier
|
|
*/
|
|
UMLClassifier * ClassifierCodeDocument::getParentClassifier ( ) {
|
|
return m_parentclassifier;
|
|
}
|
|
|
|
/**
|
|
* @return TQPtrList<CodeOperation>
|
|
*/
|
|
TQPtrList<CodeOperation> ClassifierCodeDocument::getCodeOperations ( ) {
|
|
|
|
TQPtrList<CodeOperation> list;
|
|
list.setAutoDelete(false);
|
|
|
|
TextBlockList * tlist = getTextBlockList();
|
|
for (TextBlock *tb = tlist->first(); tb; tb=tlist->next())
|
|
{
|
|
CodeOperation * cop = dynamic_cast<CodeOperation*>(tb);
|
|
if(cop)
|
|
list.append(cop);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* @param o The Operation to add
|
|
*/
|
|
void ClassifierCodeDocument::addOperation (UMLClassifierListItem * o) {
|
|
UMLOperation *op = dynamic_cast<UMLOperation*>(o);
|
|
if (op == NULL) {
|
|
kError() << "ClassifierCodeDocument::addOperation: arg is not a UMLOperation"
|
|
<< endl;
|
|
}
|
|
TQString tag = CodeOperation::findTag(op);
|
|
CodeOperation * codeOp = dynamic_cast<CodeOperation*>(findTextBlockByTag(tag, true));
|
|
bool createdNew = false;
|
|
|
|
// create the block, if it doesn't already exist
|
|
if(!codeOp)
|
|
{
|
|
codeOp = CodeGenFactory::newCodeOperation(this, op);
|
|
createdNew = true;
|
|
}
|
|
|
|
// now try to add it. This may fail because it (or a block with
|
|
// the same tag) is already in the document somewhere. IF we
|
|
// created this new, then we need to delete our object.
|
|
if(!addCodeOperation(codeOp)) // wont add if already present
|
|
if(createdNew)
|
|
delete codeOp;
|
|
|
|
}
|
|
|
|
/**
|
|
* @param op
|
|
*/
|
|
void ClassifierCodeDocument::removeOperation (UMLClassifierListItem * op ) {
|
|
|
|
TQString tag = CodeOperation::findTag((UMLOperation*)op);
|
|
TextBlock *tb = findTextBlockByTag(tag, true);
|
|
if(tb)
|
|
{
|
|
if(removeTextBlock(tb)) // wont add if already present
|
|
delete tb; // delete unused operations
|
|
else
|
|
kError()<<"Cant remove CodeOperation from ClassCodeDocument!"<<endl;
|
|
|
|
}
|
|
else
|
|
kError()<<"Cant Find codeOperation for deleted operation!"<<endl;
|
|
}
|
|
|
|
// Other methods
|
|
//
|
|
|
|
void ClassifierCodeDocument::addCodeClassFieldMethods(CodeClassFieldList &list )
|
|
{
|
|
|
|
for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * field = ccflit.current();
|
|
CodeAccessorMethodList list = field->getMethodList();
|
|
CodeAccessorMethod * method;
|
|
for (CodeAccessorMethodListIt it(list); (method = it.current()) != NULL; ++it)
|
|
{
|
|
/*
|
|
TQString tag = method->getTag();
|
|
if(tag.isEmpty())
|
|
{
|
|
tag = getUniqueTag();
|
|
method->setTag(tag);
|
|
}
|
|
*/
|
|
addTextBlock(method); // wont add if already exists in document, will add a tag if missing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// add declaration blocks for the passed classfields
|
|
void ClassifierCodeDocument::declareClassFields (CodeClassFieldList & list ,
|
|
CodeGenObjectWithTextBlocks * parent )
|
|
{
|
|
|
|
for (CodeClassFieldListIt ccflit(list); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * field = ccflit.current();
|
|
CodeClassFieldDeclarationBlock * declBlock = field->getDeclarationCodeBlock();
|
|
|
|
/*
|
|
// if it has a tag, check
|
|
if(!declBlock->getTag().isEmpty())
|
|
{
|
|
// In C++, because we may shift the declaration to a different parent
|
|
// block for a change in scope, we need to track down any pre-existing
|
|
// location, and remove FIRST before adding to new parent
|
|
CodeGenObjectWithTextBlocks * oldParent = findParentObjectForTaggedTextBlock (declBlock->getTag());
|
|
if(oldParent) {
|
|
if(oldParent != parent)
|
|
oldParent->removeTextBlock(declBlock);
|
|
}
|
|
}
|
|
*/
|
|
|
|
parent->addTextBlock(declBlock); // wont add it IF its already present. Will give it a tag if missing
|
|
|
|
}
|
|
}
|
|
|
|
bool ClassifierCodeDocument::parentIsClass() {
|
|
return (m_parentclassifier->getBaseType() == Uml::ot_Class);
|
|
}
|
|
|
|
bool ClassifierCodeDocument::parentIsInterface() {
|
|
return (m_parentclassifier->getBaseType() == Uml::ot_Interface);
|
|
}
|
|
|
|
/**
|
|
* Init from a UMLClassifier object.
|
|
* @param classifier
|
|
* @param package
|
|
*/
|
|
void ClassifierCodeDocument::init (UMLClassifier * c )
|
|
{
|
|
|
|
m_parentclassifier = c;
|
|
m_classfieldVector.setAutoDelete(false);
|
|
|
|
updateHeader();
|
|
syncNamesToParent();
|
|
// initCodeClassFields(); // cant call here?..newCodeClassField is pure virtual
|
|
|
|
// slots
|
|
if (parentIsClass()) {
|
|
connect(c,TQT_SIGNAL(attributeAdded(UMLClassifierListItem*)),this,TQT_SLOT(addAttributeClassField(UMLClassifierListItem*)));
|
|
connect(c,TQT_SIGNAL(attributeRemoved(UMLClassifierListItem*)),this,TQT_SLOT(removeAttributeClassField(UMLClassifierListItem*)));
|
|
}
|
|
|
|
connect(c,TQT_SIGNAL(sigAssociationEndAdded(UMLAssociation*)),this,TQT_SLOT(addAssociationClassField(UMLAssociation*)));
|
|
connect(c,TQT_SIGNAL(sigAssociationEndRemoved(UMLAssociation*)),this,TQT_SLOT(removeAssociationClassField(UMLAssociation*)));
|
|
connect(c,TQT_SIGNAL(operationAdded(UMLClassifierListItem*)),this,TQT_SLOT(addOperation(UMLClassifierListItem*)));
|
|
connect(c,TQT_SIGNAL(operationRemoved(UMLClassifierListItem*)),this,TQT_SLOT(removeOperation(UMLClassifierListItem*)));
|
|
connect(c,TQT_SIGNAL(modified()),this,TQT_SLOT(syncToParent()));
|
|
|
|
}
|
|
|
|
// IF the classifier object is modified, this will get called.
|
|
// @todo we cannot make this virtual as long as the
|
|
// ClassifierCodeDocument constructor calls it because that gives
|
|
// a call-before-construction error.
|
|
// Example of the problem: CPPSourceCodeDocument reimplementing syncNamesToParent()
|
|
// CPPCodeGenerator::initFromParentDocument()
|
|
// CodeDocument * codeDoc = new CPPSourceCodeDocument(c);
|
|
// CPPSourceCodeDocument::CPPSourceCodeDocument(UMLClassifier * concept)
|
|
// : ClassifierCodeDocument(concept)
|
|
// ClassifierCodeDocument::ClassifierCodeDocument(concept)
|
|
// init(concept);
|
|
// syncNamesToParent();
|
|
// dispatches to CPPSourceCodeDocument::syncNamesToParent()
|
|
// but that object is not yet constructed.
|
|
//
|
|
void ClassifierCodeDocument::syncNamesToParent( ) {
|
|
TQString fileName = CodeGenerator::cleanName(getParentClassifier()->getName());
|
|
if (!UMLApp::app()->activeLanguageIsCaseSensitive()) {
|
|
// @todo let the user decide about mixed case file names (codegen setup menu)
|
|
fileName = fileName.lower();
|
|
}
|
|
setFileName(fileName);
|
|
setPackage(m_parentclassifier->getUMLPackage());
|
|
}
|
|
|
|
void ClassifierCodeDocument::synchronize( ) {
|
|
|
|
updateHeader(); // doing this insures time/date stamp is at the time of this call
|
|
syncNamesToParent();
|
|
updateContent();
|
|
syncClassFields();
|
|
updateOperations();
|
|
|
|
}
|
|
|
|
void ClassifierCodeDocument::syncClassFields( )
|
|
{
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
cf->synchronize();
|
|
}
|
|
}
|
|
|
|
void ClassifierCodeDocument::updateOperations( ) {
|
|
|
|
UMLOperationList opList(getParentClassifier()->getOpList());
|
|
for (UMLOperation *op = opList.first(); op; op = opList.next())
|
|
{
|
|
TQString tag = CodeOperation::findTag(op);
|
|
CodeOperation * codeOp = dynamic_cast<CodeOperation*>(findTextBlockByTag(tag, true));
|
|
bool createdNew = false;
|
|
|
|
if(!codeOp)
|
|
{
|
|
codeOp = CodeGenFactory::newCodeOperation(this, op);
|
|
createdNew = true;
|
|
}
|
|
|
|
// now try to add it. This may fail because it (or a block with
|
|
// the same tag) is already in the document somewhere. IF we
|
|
// created this new, then we need to delete our object.
|
|
if(!addCodeOperation(codeOp)) // wont add if already present
|
|
if(createdNew)
|
|
delete codeOp;
|
|
|
|
// synchronize all non-new operations
|
|
if(!createdNew)
|
|
codeOp->syncToParent();
|
|
}
|
|
|
|
}
|
|
|
|
void ClassifierCodeDocument::syncToParent( ) {
|
|
synchronize();
|
|
}
|
|
|
|
/**
|
|
* add codeclassfields to this classifiercodedocument. IF a codeclassfield
|
|
* already exists, it is not added.
|
|
*/
|
|
void ClassifierCodeDocument::initCodeClassFields ( ) {
|
|
|
|
UMLClassifier * c = getParentClassifier();
|
|
// first, do the code classifields that arise from attributes
|
|
if (parentIsClass()) {
|
|
UMLAttributeList alist = c->getAttributeList();
|
|
for(UMLAttribute * at = alist.first(); at; at = alist.next())
|
|
{
|
|
CodeClassField * field = CodeGenFactory::newCodeClassField(this, at);
|
|
addCodeClassField(field);
|
|
}
|
|
|
|
}
|
|
|
|
// now, do the code classifields that arise from associations
|
|
UMLAssociationList ap = c->getSpecificAssocs(Uml::at_Association);
|
|
UMLAssociationList ag = c->getAggregations();
|
|
UMLAssociationList ac = c->getCompositions();
|
|
UMLAssociationList selfAssoc = c->getSpecificAssocs(Uml::at_Association_Self);
|
|
|
|
updateAssociationClassFields(ap);
|
|
updateAssociationClassFields(ag);
|
|
updateAssociationClassFields(ac);
|
|
updateAssociationClassFields(selfAssoc);
|
|
|
|
}
|
|
|
|
void ClassifierCodeDocument::updateAssociationClassFields ( UMLAssociationList &assocList )
|
|
{
|
|
CodeClassFieldList list;
|
|
for(UMLAssociation * a=assocList.first(); a; a=assocList.next())
|
|
addAssociationClassField(a, false); // syncToParent later
|
|
}
|
|
|
|
void ClassifierCodeDocument::addAssociationClassField (UMLAssociation * a, bool syncToParentIfAdded)
|
|
{
|
|
|
|
Uml::IDType cid = getParentClassifier()->getID(); // so we know who 'we' are
|
|
bool printRoleA = false, printRoleB = false, shouldSync = false;
|
|
// it may seem counter intuitive, but you want to insert the role of the
|
|
// *other* class into *this* class.
|
|
if (a->getObjectId(Uml::A) == cid)
|
|
printRoleB = true;
|
|
|
|
if (a->getObjectId(Uml::B) == cid)
|
|
printRoleA = true;
|
|
|
|
// grab RoleB decl
|
|
if (printRoleB)
|
|
{
|
|
|
|
UMLRole * role = a->getUMLRole(Uml::B);
|
|
if(!m_classFieldMap.contains((UMLObject*)role))
|
|
{
|
|
CodeClassField * classfield = CodeGenFactory::newCodeClassField(this, role);
|
|
if( addCodeClassField(classfield))
|
|
shouldSync = true;
|
|
}
|
|
}
|
|
|
|
// print RoleA decl
|
|
if (printRoleA)
|
|
{
|
|
UMLRole * role = a->getUMLRole(Uml::A);
|
|
if(!m_classFieldMap.contains((UMLObject*)role))
|
|
{
|
|
CodeClassField * classfield = CodeGenFactory::newCodeClassField(this, role);
|
|
if( addCodeClassField(classfield))
|
|
shouldSync = true;
|
|
}
|
|
}
|
|
|
|
if (shouldSync && syncToParentIfAdded)
|
|
syncToParent(); // needed for a slot add
|
|
|
|
}
|
|
|
|
/** set the class attributes of this object from
|
|
* the passed element node.
|
|
*/
|
|
void ClassifierCodeDocument::setAttributesFromNode ( TQDomElement & elem )
|
|
{
|
|
|
|
// NOTE: we DON'T set the parent here as we ONLY get to this point
|
|
// IF the parent codegenerator could find a matching parent classifier
|
|
// that already has a code document.
|
|
|
|
// We FIRST set code class field stuff..check re-linnking with
|
|
// accessor methods by looking for our particular child element
|
|
TQDomNode node = elem.firstChild();
|
|
TQDomElement childElem = node.toElement();
|
|
while( !childElem.isNull() ) {
|
|
TQString tag = childElem.tagName();
|
|
if( tag == "classfields" ) {
|
|
// load classfields
|
|
loadClassFieldsFromXMI(childElem);
|
|
break;
|
|
}
|
|
node = childElem.nextSibling();
|
|
childElem= node.toElement();
|
|
}
|
|
|
|
// call super-class after. THis will populate the text blocks (incl
|
|
// the code accessor methods above) as is appropriate
|
|
CodeDocument::setAttributesFromNode(elem);
|
|
|
|
}
|
|
|
|
// look at all classfields currently in document.. match up
|
|
// by parent object ID and Role ID (needed for self-association CF's)
|
|
CodeClassField *
|
|
ClassifierCodeDocument::findCodeClassFieldFromParentID (Uml::IDType id,
|
|
int role_id)
|
|
{
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
if(role_id == -1) { // attribute-based
|
|
if (STR2ID(cf->getID()) == id)
|
|
return cf;
|
|
} else { // association(role)-based
|
|
const Uml::Role_Type r = (Uml::Role_Type)role_id;
|
|
UMLRole * role = dynamic_cast<UMLRole *>(cf->getParentObject());
|
|
if(role && STR2ID(cf->getID()) == id && role->getRole() == r)
|
|
return cf;
|
|
}
|
|
}
|
|
|
|
// shouldn't happen..
|
|
kError() << "Failed to find codeclassfield for parent uml id:"
|
|
<< ID2STR(id) << " (role id:" << role_id
|
|
<< ") Do you have a corrupt classifier code document?"
|
|
<< endl;
|
|
|
|
return (CodeClassField*) NULL; // not found
|
|
}
|
|
|
|
void ClassifierCodeDocument::loadClassFieldsFromXMI( TQDomElement & elem) {
|
|
|
|
TQDomNode node = elem.firstChild();
|
|
TQDomElement childElem = node.toElement();
|
|
while( !childElem.isNull() ) {
|
|
TQString nodeName = childElem.tagName();
|
|
if( nodeName == "codeclassfield")
|
|
{
|
|
TQString id = childElem.attribute("parent_id","-1");
|
|
int role_id = childElem.attribute("role_id","-1").toInt();
|
|
CodeClassField * cf = findCodeClassFieldFromParentID(STR2ID(id), role_id);
|
|
if(cf)
|
|
{
|
|
// Because we just may change the parent object here,
|
|
// we need to yank it from the map of umlobjects
|
|
m_classFieldMap.remove(cf->getParentObject());
|
|
|
|
// configure from XMI
|
|
cf->loadFromXMI(childElem);
|
|
|
|
// now add back in
|
|
m_classFieldMap.insert(cf->getParentObject(),cf);
|
|
|
|
} else
|
|
kError()<<" LoadFromXMI: can't load classfield parent_id:"<<id<<" do you have a corrupt savefile?"<<endl;
|
|
}
|
|
node = childElem.nextSibling();
|
|
childElem= node.toElement();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save the XMI representation of this object
|
|
*/
|
|
void ClassifierCodeDocument::saveToXMI ( TQDomDocument & doc, TQDomElement & root ) {
|
|
#if 0
|
|
// avoid the creation of primitive data type
|
|
TQString strType;
|
|
if (getParentClassifier()->getBaseType() == Uml::ot_Datatype) {
|
|
strType = getParentClassifier()->getName();
|
|
// lets get the default code generator to check if it is a primitive data type
|
|
// there's a reason to create files for int/boolean and so ?
|
|
if (getParentGenerator()->isReservedKeyword(strType))
|
|
return;
|
|
}
|
|
#endif
|
|
TQDomElement docElement = doc.createElement( "classifiercodedocument" );
|
|
|
|
setAttributesOnNode(doc, docElement);
|
|
|
|
root.appendChild( docElement );
|
|
}
|
|
|
|
/**
|
|
* load params from the appropriate XMI element node.
|
|
*/
|
|
void ClassifierCodeDocument::loadFromXMI ( TQDomElement & root ) {
|
|
|
|
// set attributes/fields
|
|
setAttributesFromNode(root);
|
|
|
|
// now sync our doc, needed?
|
|
// synchronize();
|
|
}
|
|
|
|
/** set attributes of the node that represents this class
|
|
* in the XMI document.
|
|
*/
|
|
void ClassifierCodeDocument::setAttributesOnNode ( TQDomDocument & doc, TQDomElement & docElement)
|
|
{
|
|
|
|
// do super-class first
|
|
CodeDocument::setAttributesOnNode(doc, docElement);
|
|
|
|
// cache local attributes/fields
|
|
docElement.setAttribute("parent_class", ID2STR(getParentClassifier()->getID()));
|
|
|
|
// (code) class fields
|
|
// which we will store in its own separate child node block
|
|
TQDomElement fieldsElement = doc.createElement( "classfields" );
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * field = ccflit.current();
|
|
field->saveToXMI(doc, fieldsElement);
|
|
}
|
|
docElement.appendChild( fieldsElement);
|
|
|
|
}
|
|
|
|
TextBlock * ClassifierCodeDocument::findCodeClassFieldTextBlockByTag (const TQString &tag)
|
|
{
|
|
|
|
for (CodeClassFieldListIt ccflit(m_classfieldVector); ccflit.current(); ++ccflit)
|
|
{
|
|
CodeClassField * cf = ccflit.current();
|
|
CodeClassFieldDeclarationBlock * decl = cf->getDeclarationCodeBlock();
|
|
if(decl && decl->getTag() == tag)
|
|
return decl;
|
|
// well, if not in the decl block, then in the methods perhaps?
|
|
CodeAccessorMethodList mlist = cf->getMethodList();
|
|
CodeAccessorMethod *m;
|
|
for (CodeAccessorMethodListIt it(mlist); (m = it.current()) != NULL; ++it)
|
|
if(m->getTag() == tag)
|
|
return m;
|
|
}
|
|
|
|
// if we get here, we failed.
|
|
return (TextBlock*) NULL;
|
|
|
|
}
|
|
|
|
|
|
#include "classifiercodedocument.moc"
|