void UMLAttribute::setTemplateParams(const QString& templateParam, UMLClassifierList &templateParamList) { if (templateParam.isEmpty()) return; QString type = templateParam.simplifyWhiteSpace(); int start = type.find(QChar('<')); if (start >= 0 ) { int end = start; int count = 1; int len = type.length(); while (count != 0 && ++end < len) { QChar c = type.at(end); if (c == QChar('<')) { count++; } if (c == QChar('>')) { count--; } } if (count != 0) { //The template is ill-formated, let's quit return; } setTemplateParams(type.mid(start + 1, end - start - 1), templateParamList); setTemplateParams(type.left(start) + type.right(len - end - 1), templateParamList); } else { QStringList paramsList = QStringList::split(QChar(','), type); for ( QStringList::Iterator it = paramsList.begin(); it != paramsList.end(); ++it ) { QString param = *it; if (!param.isEmpty()) { UMLDoc *pDoc = UMLApp::app()->getDocument(); UMLObject* obj = pDoc->findUMLObject(param); if (obj == NULL ) { obj = pDoc->findUMLObject(param.remove(QChar(' '))); } if (obj != NULL ) { //We want to list only the params that already exist in this document //If the param doesnt't already exist, we couldn't draw an association anyway UMLClassifier* tmpClassifier = static_cast<UMLClassifier*>(obj); if (templateParamList.findRef(tmpClassifier) == -1) { templateParamList.append(tmpClassifier); } } } } } }
/** * Sets the classes Package. * DEPRECATED - use SetUMLPackage instead. * * @param _name The classes Package name. */ void UMLObject::setPackage(const QString &_name) { UMLObject *pkgObj = NULL; if (!_name.isEmpty()) { UMLDoc* umldoc = UMLApp::app()->document(); pkgObj = umldoc->findUMLObject(_name); if (pkgObj == NULL) { uDebug() << "creating UMLPackage " << _name << " for " << m_name; pkgObj = Import_Utils::createUMLObject(ot_Package, _name); } else { const ObjectType ot = pkgObj->baseType(); if (ot != ot_Package && ot != ot_Folder && ot != ot_Component) { uError() << m_name << ": " << "existing " << _name << " is not a container"; // This should not happen - if it does, there may be further problems. // A container name should not overlap with another name in the same scope. pkgObj = Import_Utils::createUMLObject(ot_Package, _name); } } } setUMLPackage(static_cast<UMLPackage *>(pkgObj)); }
/** * Resolve referenced objects (if any.) * Needs to be called after all UML objects are loaded from file. * This needs to be done after all model objects are loaded because * some of the xmi.id's might be forward references, i.e. they may * identify model objects which were not yet loaded at the point of * reference. * The default implementation attempts resolution of the m_SecondaryId. * * @return True for success. */ bool UMLObject::resolveRef() { if (m_pSecondary || (m_SecondaryId.isEmpty() && m_SecondaryFallback.isEmpty())) { maybeSignalObjectCreated(); return true; } #ifdef VERBOSE_DEBUGGING uDebug() << m_name << ": m_SecondaryId is " << m_SecondaryId; #endif UMLDoc *pDoc = UMLApp::app()->document(); // In the new, XMI standard compliant save format, // the type is the xmi.id of a UMLClassifier. if (! m_SecondaryId.isEmpty()) { m_pSecondary = pDoc->findObjectById(Uml::ID::fromString(m_SecondaryId)); if (m_pSecondary != NULL) { if (m_pSecondary->baseType() == ot_Stereotype) { m_pStereotype = dynamic_cast<UMLStereotype*>(m_pSecondary.data()); m_pStereotype->incrRefCount(); m_pSecondary = NULL; } m_SecondaryId = QString(); maybeSignalObjectCreated(); return true; } if (m_SecondaryFallback.isEmpty()) { uDebug() << "object with xmi.id=" << m_SecondaryId << " not found, setting to undef"; UMLFolder *datatypes = pDoc->datatypeFolder(); m_pSecondary = Object_Factory::createUMLObject(ot_Datatype, QLatin1String("undef"), datatypes, false); return true; } } if (m_SecondaryFallback.isEmpty()) { uError() << m_name << ": cannot find type with id " << m_SecondaryId; return false; } #ifdef VERBOSE_DEBUGGING uDebug() << m_name << ": could not resolve secondary ID " << m_SecondaryId << ", using secondary fallback " << m_SecondaryFallback; #endif m_SecondaryId = m_SecondaryFallback; // Assume we're dealing with the older Umbrello format where // the type name was saved in the "type" attribute rather // than the xmi.id of the model object of the attribute type. m_pSecondary = pDoc->findUMLObject(m_SecondaryId, ot_UMLObject, this); if (m_pSecondary) { m_SecondaryId = QString(); maybeSignalObjectCreated(); return true; } // Work around Object_Factory::createUMLObject()'s incapability // of on-the-fly scope creation: if (m_SecondaryId.contains(QLatin1String("::"))) { // TODO: Merge Import_Utils::createUMLObject() into Object_Factory::createUMLObject() m_pSecondary = Import_Utils::createUMLObject(ot_UMLObject, m_SecondaryId, m_pUMLPackage); if (m_pSecondary) { if (Import_Utils::newUMLObjectWasCreated()) { maybeSignalObjectCreated(); qApp->processEvents(); uDebug() << "Import_Utils::createUMLObject() created a new type for " << m_SecondaryId; } else { uDebug() << "Import_Utils::createUMLObject() returned an existing type for " << m_SecondaryId; } m_SecondaryId = QString(); return true; } uError() << "Import_Utils::createUMLObject() failed to create a new type for " << m_SecondaryId; return false; } uDebug() << "Creating new type for " << m_SecondaryId; // This is very C++ specific - we rely on some '*' or // '&' to decide it's a ref type. Plus, we don't recognize // typedefs of ref types. bool isReferenceType = (m_SecondaryId.contains(QLatin1Char('*')) || m_SecondaryId.contains(QLatin1Char('&'))); ObjectType ot = ot_Class; if (isReferenceType) { ot = ot_Datatype; } else { if (Model_Utils::isCommonDataType(m_SecondaryId)) ot = ot_Datatype; } m_pSecondary = Object_Factory::createUMLObject(ot, m_SecondaryId, NULL); if (m_pSecondary == NULL) return false; m_SecondaryId = QString(); maybeSignalObjectCreated(); //qApp->processEvents(); return true; }
/** * Implement abstract operation from NativeImportBase. */ bool AdaImport::parseStmt() { const int srcLength = m_source.count(); QString keyword = m_source[m_srcIndex]; UMLDoc *umldoc = UMLApp::app()->document(); //uDebug() << '"' << keyword << '"'; if (keyword == QLatin1String("with")) { if (m_inGenericFormalPart) { // mapping of generic formal subprograms or packages is not yet implemented return false; } while (++m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(";")) { QStringList components = m_source[m_srcIndex].toLower().split(QLatin1Char('.')); const QString& prefix = components.first(); if (prefix == QLatin1String("system") || prefix == QLatin1String("ada") || prefix == QLatin1String("gnat") || prefix == QLatin1String("interfaces") || prefix == QLatin1String("text_io") || prefix == QLatin1String("unchecked_conversion") || prefix == QLatin1String("unchecked_deallocation")) { if (advance() != QLatin1String(",")) break; continue; } parseStems(components); if (advance() != QLatin1String(",")) break; } return true; } if (keyword == QLatin1String("generic")) { m_inGenericFormalPart = true; return true; } if (keyword == QLatin1String("package")) { const QString& name = advance(); QStringList parentPkgs = name.toLower().split(QLatin1Char('.')); parentPkgs.pop_back(); // exclude the current package parseStems(parentPkgs); UMLObject *ns = NULL; if (advance() == QLatin1String("is")) { ns = Import_Utils::createUMLObject(UMLObject::ot_Package, name, currentScope(), m_comment); if (m_source[m_srcIndex + 1] == QLatin1String("new")) { m_srcIndex++; QString pkgName = advance(); UMLObject *gp = Import_Utils::createUMLObject(UMLObject::ot_Package, pkgName, currentScope()); gp->setStereotype(QLatin1String("generic")); // Add binding from instantiator to instantiatee UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, ns, gp); assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical)); assoc->setStereotype(QLatin1String("bind")); // Work around missing display of stereotype in AssociationWidget: assoc->setName(assoc->stereotype(true)); umldoc->addAssociation(assoc); skipStmt(); } else { pushScope(static_cast<UMLPackage*>(ns)); } } else if (m_source[m_srcIndex] == QLatin1String("renames")) { m_renaming[name] = advance(); } else { uError() << "unexpected: " << m_source[m_srcIndex]; skipStmt(QLatin1String("is")); } if (m_inGenericFormalPart) { if (ns) ns->setStereotype(QLatin1String("generic")); m_inGenericFormalPart = false; } return true; } if (m_inGenericFormalPart) return false; // skip generic formal parameter (not yet implemented) if (keyword == QLatin1String("subtype")) { QString name = advance(); advance(); // "is" QString base = expand(advance()); base.remove(QLatin1String("Standard."), Qt::CaseInsensitive); UMLObject *type = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope()); if (type == NULL) { type = Import_Utils::createUMLObject(UMLObject::ot_Datatype, base, currentScope()); } UMLObject *subtype = Import_Utils::createUMLObject(type->baseType(), name, currentScope(), m_comment); UMLAssociation *assoc = new UMLAssociation(Uml::AssociationType::Dependency, subtype, type); assoc->setUMLPackage(umldoc->rootFolder(Uml::ModelType::Logical)); assoc->setStereotype(QLatin1String("subtype")); // Work around missing display of stereotype in AssociationWidget: assoc->setName(assoc->stereotype(true)); umldoc->addAssociation(assoc); skipStmt(); return true; } if (keyword == QLatin1String("type")) { QString name = advance(); QString next = advance(); if (next == QLatin1String("(")) { uDebug() << name << ": discriminant handling is not yet implemented"; // @todo Find out how to map discriminated record to UML. // For now, we just create a pro forma empty record. Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(), m_comment, QLatin1String("record")); skipStmt(QLatin1String("end")); if ((next = advance()) == QLatin1String("case")) m_srcIndex += 2; // skip "case" ";" skipStmt(); return true; } if (next == QLatin1String(";")) { // forward declaration Import_Utils::createUMLObject(UMLObject::ot_Class, name, currentScope(), m_comment); return true; } if (next != QLatin1String("is")) { uError() << "expecting \"is\""; return false; } next = advance(); if (next == QLatin1String("(")) { // enum type UMLObject *ns = Import_Utils::createUMLObject(UMLObject::ot_Enum, name, currentScope(), m_comment); UMLEnum *enumType = static_cast<UMLEnum*>(ns); while ((next = advance()) != QLatin1String(")")) { Import_Utils::addEnumLiteral(enumType, next, m_comment); m_comment.clear(); if (advance() != QLatin1String(",")) break; } skipStmt(); return true; } bool isTaggedType = false; if (next == QLatin1String("abstract")) { m_isAbstract = true; next = advance(); } if (next == QLatin1String("tagged")) { isTaggedType = true; next = advance(); } if (next == QLatin1String("limited") || next == QLatin1String("task") || next == QLatin1String("protected") || next == QLatin1String("synchronized")) { next = advance(); // we can't (yet?) represent that } if (next == QLatin1String("private") || next == QLatin1String("interface") || next == QLatin1String("record") || (next == QLatin1String("null") && m_source[m_srcIndex+1] == QLatin1String("record"))) { UMLObject::ObjectType t = (next == QLatin1String("interface") ? UMLObject::ot_Interface : UMLObject::ot_Class); UMLObject *ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment); if (t == UMLObject::ot_Interface) { while ((next = advance()) == QLatin1String("and")) { UMLClassifier *klass = static_cast<UMLClassifier*>(ns); QString base = expand(advance()); UMLObject *p = Import_Utils::createUMLObject(UMLObject::ot_Interface, base, currentScope()); UMLClassifier *parent = static_cast<UMLClassifier*>(p); Import_Utils::createGeneralization(klass, parent); } } else { ns->setAbstract(m_isAbstract); } m_isAbstract = false; if (isTaggedType) { if (! m_classesDefinedInThisScope.contains(ns)) m_classesDefinedInThisScope.append(ns); } else { ns->setStereotype(QLatin1String("record")); } if (next == QLatin1String("record")) m_klass = static_cast<UMLClassifier*>(ns); else skipStmt(); return true; } if (next == QLatin1String("new")) { QString base = expand(advance()); QStringList baseInterfaces; while ((next = advance()) == QLatin1String("and")) { baseInterfaces.append(expand(advance())); } const bool isExtension = (next == QLatin1String("with")); UMLObject::ObjectType t; if (isExtension || m_isAbstract) { t = UMLObject::ot_Class; } else { base.remove(QLatin1String("Standard."), Qt::CaseInsensitive); UMLObject *known = umldoc->findUMLObject(base, UMLObject::ot_UMLObject, currentScope()); t = (known ? known->baseType() : UMLObject::ot_Datatype); } UMLObject *ns = Import_Utils::createUMLObject(t, base, NULL); UMLClassifier *parent = static_cast<UMLClassifier*>(ns); ns = Import_Utils::createUMLObject(t, name, currentScope(), m_comment); if (isExtension) { next = advance(); if (next == QLatin1String("null") || next == QLatin1String("record")) { UMLClassifier *klass = static_cast<UMLClassifier*>(ns); Import_Utils::createGeneralization(klass, parent); if (next == QLatin1String("record")) { // Set the m_klass for attributes. m_klass = klass; } if (baseInterfaces.count()) { t = UMLObject::ot_Interface; QStringList::Iterator end(baseInterfaces.end()); for (QStringList::Iterator bi(baseInterfaces.begin()); bi != end; ++bi) { ns = Import_Utils::createUMLObject(t, *bi, currentScope()); parent = static_cast<UMLClassifier*>(ns); Import_Utils::createGeneralization(klass, parent); } } } } skipStmt(); return true; } // Datatypes: TO BE DONE return false; } if (keyword == QLatin1String("private")) { m_currentAccess = Uml::Visibility::Private; return true; } if (keyword == QLatin1String("end")) { if (m_klass) { if (advance() != QLatin1String("record")) { uError() << "end: expecting \"record\" at " << m_source[m_srcIndex]; } m_klass = NULL; } else if (scopeIndex()) { if (advance() != QLatin1String(";")) { QString scopeName = currentScope()->fullyQualifiedName(); if (scopeName.toLower() != m_source[m_srcIndex].toLower()) uError() << "end: expecting " << scopeName << ", found " << m_source[m_srcIndex]; } popScope(); m_currentAccess = Uml::Visibility::Public; // @todo make a stack for this } else { uError() << "importAda: too many \"end\""; } skipStmt(); return true; } // subprogram if (keyword == QLatin1String("not")) keyword = advance(); if (keyword == QLatin1String("overriding")) keyword = advance(); if (keyword == QLatin1String("function") || keyword == QLatin1String("procedure")) { const QString& name = advance(); QString returnType; if (advance() != QLatin1String("(")) { // Unlike an Ada package, a UML package does not support // subprograms. // In order to map those, we would need to create a UML // class with stereotype <<utility>> for the Ada package. uDebug() << "ignoring parameterless " << keyword << " " << name; skipStmt(); return true; } UMLClassifier *klass = NULL; UMLOperation *op = NULL; const uint MAX_PARNAMES = 16; while (m_srcIndex < srcLength && m_source[m_srcIndex] != QLatin1String(")")) { QString parName[MAX_PARNAMES]; uint parNameCount = 0; do { if (parNameCount >= MAX_PARNAMES) { uError() << "MAX_PARNAMES is exceeded at " << name; break; } parName[parNameCount++] = advance(); } while (advance() == QLatin1String(",")); if (m_source[m_srcIndex] != QLatin1String(":")) { uError() << "importAda: expecting ':'"; skipStmt(); break; } const QString &direction = advance(); QString typeName; Uml::ParameterDirection::Enum dir = Uml::ParameterDirection::In; if (direction == QLatin1String("access")) { // Oops, we have to improvise here because there // is no such thing as "access" in UML. // So we use the next best thing, "inout". // Better ideas, anyone? dir = Uml::ParameterDirection::InOut; typeName = advance(); } else if (direction == QLatin1String("in")) { if (m_source[m_srcIndex + 1] == QLatin1String("out")) { dir = Uml::ParameterDirection::InOut; m_srcIndex++; } typeName = advance(); } else if (direction == QLatin1String("out")) { dir = Uml::ParameterDirection::Out; typeName = advance(); } else { typeName = direction; // In Ada, the default direction is "in" } typeName.remove(QLatin1String("Standard."), Qt::CaseInsensitive); typeName = expand(typeName); if (op == NULL) { // In Ada, the first parameter indicates the class. UMLObject *type = Import_Utils::createUMLObject(UMLObject::ot_Class, typeName, currentScope()); UMLObject::ObjectType t = type->baseType(); if ((t != UMLObject::ot_Interface && (t != UMLObject::ot_Class || type->stereotype() == QLatin1String("record"))) || !m_classesDefinedInThisScope.contains(type)) { // Not an instance bound method - we cannot represent it. skipStmt(QLatin1String(")")); break; } klass = static_cast<UMLClassifier*>(type); op = Import_Utils::makeOperation(klass, name); // The controlling parameter is suppressed. parNameCount--; if (parNameCount) { for (uint i = 0; i < parNameCount; ++i) { parName[i] = parName[i + 1]; } } } for (uint i = 0; i < parNameCount; ++i) { UMLAttribute *att = Import_Utils::addMethodParameter(op, typeName, parName[i]); att->setParmKind(dir); } if (advance() != QLatin1String(";")) break; } if (keyword == QLatin1String("function")) { if (advance() != QLatin1String("return")) { if (klass) uError() << "importAda: expecting \"return\" at function " << name; return false; } returnType = expand(advance()); returnType.remove(QLatin1String("Standard."), Qt::CaseInsensitive); } bool isAbstract = false; if (advance() == QLatin1String("is") && advance() == QLatin1String("abstract")) isAbstract = true; if (klass != NULL && op != NULL) Import_Utils::insertMethod(klass, op, m_currentAccess, returnType, false, isAbstract, false, false, m_comment); skipStmt(); return true; } if (keyword == QLatin1String("task") || keyword == QLatin1String("protected")) { // Can task and protected objects/types be mapped to UML? QString name = advance(); if (name == QLatin1String("type")) { name = advance(); } QString next = advance(); if (next == QLatin1String("(")) { skipStmt(QLatin1String(")")); // skip discriminant next = advance(); } if (next == QLatin1String("is")) skipStmt(QLatin1String("end")); skipStmt(); return true; } if (keyword == QLatin1String("for")) { // rep spec QString typeName = advance(); QString next = advance(); if (next == QLatin1String("'")) { advance(); // skip qualifier next = advance(); } if (next == QLatin1String("use")) { if (advance() == QLatin1String("record")) skipStmt(QLatin1String("end")); } else { uError() << "importAda: expecting \"use\" at rep spec of " << typeName; } skipStmt(); return true; } // At this point we're only interested in attribute declarations. if (m_klass == NULL || keyword == QLatin1String("null")) { skipStmt(); return true; } const QString& name = keyword; if (advance() != QLatin1String(":")) { uError() << "adaImport: expecting \":\" at " << name << " " << m_source[m_srcIndex]; skipStmt(); return true; } QString nextToken = advance(); if (nextToken == QLatin1String("aliased")) nextToken = advance(); QString typeName = expand(nextToken); QString initialValue; if (advance() == QLatin1String(":=")) { initialValue = advance(); QString token; while ((token = advance()) != QLatin1String(";")) { initialValue.append(QLatin1Char(' ') + token); } } UMLObject *o = Import_Utils::insertAttribute(m_klass, m_currentAccess, name, typeName, m_comment); if (o) { UMLAttribute *attr = static_cast<UMLAttribute*>(o); attr->setInitialValue(initialValue); } skipStmt(); return true; }
/** * Returns the UML Object if found, or null otherwise. * @param name name of the uml object * @param parentPkg parent package * @return null or the uml objecct */ UMLObject* JavaImport::findObject(const QString& name, UMLPackage *parentPkg) { UMLDoc *umldoc = UMLApp::app()->document(); UMLObject * o = umldoc->findUMLObject(name, UMLObject::ot_UMLObject , parentPkg); return o; }
/** * Checks if changes are valid and applies them if they are, * else returns false */ bool UMLEntityAttributeDialog::apply() { QString name = m_pNameLE->text(); if (name.isEmpty()) { KMessageBox::error(this, i18n("You have entered an invalid entity attribute name."), i18n("Entity Attribute Name Invalid"), 0); m_pNameLE->setText(m_pEntityAttribute->name()); return false; } UMLClassifier * pConcept = dynamic_cast<UMLClassifier *>(m_pEntityAttribute->parent()); UMLObject *o = pConcept->findChildObject(name); if (o && o != m_pEntityAttribute) { KMessageBox::error(this, i18n("The entity attribute name you have chosen is already being used in this operation."), i18n("Entity Attribute Name Not Unique"), 0); m_pNameLE->setText(m_pEntityAttribute->name()); return false; } m_pEntityAttribute->setName(name); m_pEntityAttribute->setInitialValue(m_pInitialLE->text()); m_stereotypeWidget->apply(); m_pEntityAttribute->setValues(m_pValuesLE->text()); m_pEntityAttribute->setAttributes(m_pAttributesCB->currentText()); m_pEntityAttribute->setAutoIncrement(m_pAutoIncrementCB->isChecked()); m_pEntityAttribute->setNull(m_pNullCB->isChecked()); /* if (m_pPublicRB->isChecked()) { m_pEntityAttribute->setIndexType(UMLEntityAttribute::Primary); } else if (m_pProtectedRB->isChecked()) { m_pEntityAttribute->setIndexType(UMLEntityAttribute::Unique); } else */ if (m_pPrivateRB->isChecked()) { m_pEntityAttribute->setIndexType(UMLEntityAttribute::Index); } else { m_pEntityAttribute->setIndexType(UMLEntityAttribute::None); } QString typeName = m_pTypeCB->currentText(); UMLDoc *pDoc = UMLApp::app()->document(); UMLClassifierList dataTypes = pDoc->datatypes(); foreach (UMLClassifier* dat, dataTypes) { if (typeName == dat->name()) { m_pEntityAttribute->setType(dat); return true; } } UMLObject *obj = pDoc->findUMLObject(typeName); UMLClassifier *classifier = dynamic_cast<UMLClassifier*>(obj); if (classifier == NULL) { // If it's obviously a pointer type (C++) then create a datatype. // Else we don't know what it is so as a compromise create a class. UMLObject::ObjectType ot = (typeName.contains(QChar::fromLatin1('*')) ? UMLObject::ot_Datatype : UMLObject::ot_Class); obj = Object_Factory::createUMLObject(ot, typeName); if (obj == NULL) return false; classifier = static_cast<UMLClassifier*>(obj); } m_pEntityAttribute->setType(classifier); return true; }