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.
tdesdk/umbrello/umbrello/assocrules.cpp

387 lines
19 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) 2002-2007 *
* Umbrello UML Modeller Authors <uml-devel@uml.sf.net> *
***************************************************************************/
// own header
#include "assocrules.h"
// qt/kde includes
#include <kdebug.h>
#include <typeinfo>
// local includes
#include "uml.h"
#include "umlview.h"
#include "umlwidget.h"
#include "umlobject.h"
#include "associationwidgetlist.h"
#include "associationwidget.h"
#include "statewidget.h"
#include "activitywidget.h"
#include "forkjoinwidget.h"
using namespace Uml;
AssocRules::AssocRules() {}
AssocRules::~AssocRules() {}
bool allowAssociation( Association_Type/* assocType*/, const std::type_info/* &type*/ )
{
return false;
}
bool AssocRules::allowAssociation( Uml::Association_Type assocType, UMLWidget * widget ) {
Widget_Type widgetType = widget -> getBaseType();
bool bValid = false;
for (int i = 0; i < m_nNumRules; i++) {
if (assocType == m_AssocRules[i].assoc_type) {
if (widgetType == m_AssocRules[i].widgetA_type
|| widgetType == m_AssocRules[i].widgetB_type ) {
bValid = true;
}
}
}
if( !bValid ) {
// Special case: Subsystem realizes interface in component diagram
UMLView *view = UMLApp::app()->getCurrentView();
if (view && view->getType() == dt_Component && widgetType == wt_Package &&
(assocType == at_Generalization || assocType == at_Realization))
bValid = true;
else
return false;
}
AssociationWidgetList list = widget -> getAssocList();
AssociationWidgetListIt it( list );
AssociationWidget * assoc = 0;
switch( assocType ) {
case at_Association:
case at_UniAssociation:
case at_Dependency:
case at_Coll_Message:
case at_Generalization://can have many sub/super types
case at_Aggregation:
case at_Relationship:
case at_Composition:
case at_Containment:
return true;//doesn't matter whats already connected to widget
break;
case at_Association_Self:
return true;// we should really check that connection is to same object
break;
case at_Realization: // one connected to widget only (a or b)
while( ( assoc = it.current() ) ) {
if( assoc -> getAssocType() == at_Realization )
return false;
++it;
}
return true;
break;
case at_State:
{
StateWidget *pState = dynamic_cast<StateWidget*>(widget);
return (pState == NULL || pState->getStateType() != StateWidget::End);
}
break;
case at_Activity:
{
ActivityWidget *pActivity = dynamic_cast<ActivityWidget*>(widget);
return (pActivity == NULL || pActivity->getActivityType() != ActivityWidget::End);
}
break;
case at_Anchor:
return true;
break;
default:
kWarning() << "allowAssociation() on unknown type" << endl;
break;
}
return false;
}
// when we know what we are going to connect both ends of the association to, we can
// use this method.
bool AssocRules::allowAssociation( Uml::Association_Type assocType,
UMLWidget * widgetA, UMLWidget * widgetB,
bool extendedCheck ) {
Widget_Type widgetTypeA = widgetA->getBaseType();
Widget_Type widgetTypeB = widgetB->getBaseType();
bool bValid = false;
for (int i = 0; i < m_nNumRules; i++) {
if (assocType == m_AssocRules[i].assoc_type) {
if( (widgetTypeA == m_AssocRules[i].widgetA_type &&
widgetTypeB == m_AssocRules[i].widgetB_type) ||
(widgetTypeB == m_AssocRules[i].widgetA_type &&
widgetTypeA == m_AssocRules[i].widgetB_type ) )
bValid = true;
}
}
// we can bail here for quick checks, as occur in loading files
// for paste or regular creation operations, we need to go further
if (!extendedCheck) {
return bValid;
}
if (!bValid) {
return false;
}
AssociationWidgetList list = widgetB -> getAssocList();
AssociationWidgetListIt it( list );
AssociationWidget * assoc = 0;
switch( assocType ) {
case at_Association:
case at_Association_Self:
case at_UniAssociation:
case at_Dependency:
case at_Coll_Message:
case at_Aggregation:
case at_Relationship:
return true; // doesn't matter what's already connected to widget
break;
case at_Composition: // can't have mutual composition
case at_Containment: // can't have mutual containment
case at_Generalization://can have many sub/super types but can't sup/sub each
while( ( assoc = it.current() ) ) {
if( ( widgetA == assoc -> getWidget(A) || widgetA == assoc -> getWidget(B) )
&& assoc->getAssocType() == assocType )
return false;
++it;
}
return true;
break;
case at_Realization: // can only connect to abstract (interface) classes
while( ( assoc = it.current() ) ) {
if( ( widgetA == assoc->getWidget(A) || widgetA == assoc->getWidget(B) )
&& assoc->getAssocType() == at_Realization ) {
return false;
}
++it;
}
if (widgetB->getBaseType() == wt_Class) {
return widgetB->getUMLObject()->getAbstract();
} else if (widgetB->getBaseType() == wt_Interface ||
widgetB->getBaseType() == wt_Package) {
return true;
}
break;
case at_State:
{
StateWidget *stateA = dynamic_cast<StateWidget*>(widgetA);
StateWidget *stateB = dynamic_cast<StateWidget*>(widgetB);
if (stateA && stateB) {
if (stateB->getStateType() == StateWidget::Initial)
return false;
if (stateB->getStateType() == StateWidget::End &&
stateA->getStateType() != StateWidget::Normal)
return false;
}
}
return true;
break;
case at_Activity:
{
ActivityWidget *actA = dynamic_cast<ActivityWidget*>(widgetA);
ActivityWidget *actB = dynamic_cast<ActivityWidget*>(widgetB);
// no transitions to initial activity allowed
if (actB && actB->getActivityType() == ActivityWidget::Initial)
return false;
// actType -1 here means "not applicable".
int actTypeA = -1;
if (actA)
actTypeA = actA->getActivityType();
int actTypeB = -1;
if (actB)
actTypeB = actB->getActivityType();
// only from a normal, branch or fork activity to the end
if (actTypeB == ActivityWidget::End &&
actTypeA != ActivityWidget::Normal &&
actTypeA != ActivityWidget::Branch &&
dynamic_cast<ForkJoinWidget*>(widgetA) == NULL) {
return false;
}
// only Forks and Branches can have more than one "outgoing" transition
if (actA != NULL && actTypeA != ActivityWidget::Branch) {
AssociationWidgetList list = widgetA->getAssocList();
for (AssociationWidget* assoc = list.first(); assoc; assoc = list.next()) {
if (assoc->getWidget(A) == widgetA) {
return false;
}
}
}
}
return true;
break;
case at_Anchor:
return true;
break;
default:
kWarning() << "allowAssociation() on unknown type" << endl;
break;
}
return false;
}
bool AssocRules::allowRole( Uml::Association_Type assocType ) {
for( int i = 0; i < m_nNumRules; i++ )
if( assocType == m_AssocRules[ i ].assoc_type )
return m_AssocRules[ i ].role;
return false;
}
bool AssocRules::allowMultiplicity( Uml::Association_Type assocType, Uml::Widget_Type widgetType ) {
for( int i = 0; i < m_nNumRules; i++ )
if( assocType == m_AssocRules[ i ].assoc_type )
if( widgetType == m_AssocRules[ i ].widgetA_type || widgetType == m_AssocRules[ i ].widgetB_type )
return m_AssocRules[ i ].multiplicity;
return false;
}
bool AssocRules::allowSelf( Uml::Association_Type assocType, Uml::Widget_Type widgetType ) {
for( int i = 0; i < m_nNumRules; i++ )
if( assocType == m_AssocRules[ i ].assoc_type )
if( widgetType == m_AssocRules[ i ].widgetA_type || widgetType == m_AssocRules[ i ].widgetB_type )
return m_AssocRules[ i ].self;
return false;
}
Uml::Association_Type AssocRules::isGeneralisationOrRealisation(UMLWidget* widgetA, UMLWidget* widgetB) {
Widget_Type widgetTypeA = widgetA->getBaseType();
Widget_Type widgetTypeB = widgetB->getBaseType();
for (int i = 0; i < m_nNumRules; i++) {
if (m_AssocRules[i].assoc_type == at_Realization &&
widgetTypeA == m_AssocRules[i].widgetA_type &&
widgetTypeB == m_AssocRules[i].widgetB_type) {
return at_Realization;
}
}
return at_Generalization;
}
AssocRules::Assoc_Rule AssocRules::m_AssocRules []= {
// Association widgetA widgetB role multi directional self
//---------------+----------------+----------------+-------+-------+-------+---------
{ at_Association_Self,wt_Class, wt_Class, true, true, true, true },
{ at_Association_Self,wt_Object, wt_Object, true, true, true, true },
{ at_Association_Self,wt_Interface, wt_Interface, true, true, true, true },
{ at_Association, wt_Class, wt_Class, true, true, true, true },
{ at_Association, wt_Object, wt_Object, true, true, true, true },
{ at_Association, wt_Interface, wt_Interface, true, true, true, true },
{ at_Association, wt_Interface, wt_Class, true, true, true, false },
{ at_Association, wt_Class, wt_Interface, true, true, true, false },
{ at_Association, wt_Datatype, wt_Class, true, true, true, false },
{ at_Association, wt_Class, wt_Datatype, true, true, true, false },
{ at_Association, wt_Enum, wt_Class, true, true, true, false },
{ at_Association, wt_Class, wt_Enum, true, true, true, false },
{ at_Association, wt_Actor, wt_UseCase, true, false, false, false },
{ at_Association, wt_UseCase, wt_UseCase, true, false, false, false },
{ at_Association, wt_Actor, wt_Actor, true, false, false, false },
{ at_Association, wt_Actor, wt_UseCase, true, false, false, false },
{ at_Association, wt_Component, wt_Interface, true, false, false, false },
{ at_Association, wt_Interface, wt_Artifact, true, false, false, false },
{ at_Association, wt_Node, wt_Node, true, false, false, false },
{ at_UniAssociation,wt_Class, wt_Class, true, true, true, true },
{ at_UniAssociation,wt_Object, wt_Object, true, true, true, true },
{ at_UniAssociation,wt_Interface, wt_Interface, true, true, true, true },
{ at_UniAssociation,wt_Interface, wt_Class, true, true, true, true },
{ at_UniAssociation,wt_Class, wt_Interface, true, true, true, true },
{ at_UniAssociation,wt_Class, wt_Datatype, true, true, true, true },
{ at_UniAssociation,wt_Class, wt_Enum, true, true, true, true },
{ at_UniAssociation,wt_Actor, wt_Actor, true, false, false, false },
{ at_UniAssociation,wt_UseCase, wt_UseCase, true, false, false, false },
{ at_UniAssociation,wt_UseCase, wt_Actor, true, false, false, false },
{ at_Generalization,wt_Class, wt_Datatype, false, false, false, false },
{ at_Generalization,wt_Class, wt_Class, false, false, false, false },
{ at_Generalization,wt_Interface, wt_Interface, false, false, false, false },
{ at_Generalization,wt_UseCase, wt_UseCase, false, false, false, false },
{ at_Generalization,wt_Actor, wt_Actor, false, false, false, false },
{ at_Generalization,wt_Component, wt_Interface, false, false, false, false },
{ at_Aggregation, wt_Class, wt_Class, true, true, false, true },
{ at_Aggregation, wt_Class, wt_Interface, true, true, false, false },
{ at_Aggregation, wt_Class, wt_Enum, true, true, false, false },
{ at_Aggregation, wt_Class, wt_Datatype, true, true, false, false },
{ at_Dependency, wt_Class, wt_Class, true, false, false, true },
{ at_Dependency, wt_UseCase, wt_UseCase, true, false, false, false },
{ at_Dependency, wt_Actor, wt_Actor, true, false, false, false },
{ at_Dependency, wt_Actor, wt_UseCase, true, false, false, false },
{ at_Dependency, wt_Package, wt_Package, true, true, true, true },
{ at_Dependency, wt_Package, wt_Class, true, true, true, true },
{ at_Dependency, wt_Class, wt_Package, true, true, true, true },
{ at_Dependency, wt_Package, wt_Interface, true, true, true, true },
{ at_Dependency, wt_Interface, wt_Package, true, true, true, true },
{ at_Dependency, wt_Interface, wt_Interface, true, true, true, true },
{ at_Dependency, wt_Interface, wt_Class, true, true, true, true },
{ at_Dependency, wt_Class, wt_Interface, true, true, true, true },
{ at_Dependency, wt_Class, wt_Datatype, true, true, true, true },
{ at_Dependency, wt_Class, wt_Enum, true, true, true, true },
{ at_Dependency, wt_Component, wt_Component, true, true, true, true },
{ at_Dependency, wt_Component, wt_Interface, true, true, true, true },
{ at_Dependency, wt_Component, wt_Artifact, true, false, false, false },
{ at_Dependency, wt_Node, wt_Component, true, false, false, false },
{ at_Realization, wt_Class, wt_Interface, false, false, false, false },
{ at_Realization, wt_Interface, wt_Package, false, false, false, false },
{ at_Realization, wt_Interface, wt_Interface, false, false, false, false },
{ at_Realization, wt_Component, wt_Interface, false, false, false, false },
{ at_Realization, wt_Package, wt_Interface, false, false, false, false },
{ at_Composition, wt_Class, wt_Class, true, true, false, true },
{ at_Composition, wt_Class, wt_Interface, true, true, false, false },
{ at_Composition, wt_Class, wt_Enum, true, true, false, false },
{ at_Composition, wt_Class, wt_Datatype, false, false, false, false },
{ at_Composition, wt_Class, wt_Class, false, false, false, false },
{ at_Containment, wt_Package, wt_Class, false, false, true, false },
{ at_Containment, wt_Package, wt_Interface, false, false, true, false },
{ at_Containment, wt_Package, wt_Enum, false, false, true, false },
{ at_Containment, wt_Package, wt_Package, false, false, true, false },
{ at_Containment, wt_Package, wt_Component, false, false, true, false },
{ at_Containment, wt_Class, wt_Class, false, false, true, false },
{ at_Containment, wt_Class, wt_Interface, false, false, true, false },
{ at_Containment, wt_Class, wt_Enum, false, false, true, false },
{ at_Containment, wt_Interface, wt_Class, false, false, true, false },
{ at_Containment, wt_Interface, wt_Interface, false, false, true, false },
{ at_Containment, wt_Interface, wt_Enum, false, false, true, false },
{ at_Containment, wt_Component, wt_Component, false, false, true, false },
{ at_Containment, wt_Component, wt_Artifact, false, false, true, false },
{ at_Coll_Message, wt_Object, wt_Object, true, false, true, true },
{ at_State, wt_State, wt_State, true, false, true, true },
{ at_State, wt_ForkJoin, wt_State, true, false, true, true },
{ at_State, wt_State, wt_ForkJoin, true, false, true, true },
{ at_Activity, wt_Activity, wt_Activity, true, false, true, true },
{ at_Activity, wt_ForkJoin, wt_Activity, true, false, true, true },
{ at_Activity, wt_Activity, wt_ForkJoin, true, false, true, true },
{ at_Anchor, wt_Class, wt_Note, false, false, false, false },
{ at_Anchor, wt_Package, wt_Note, false, false, false, false },
{ at_Anchor, wt_Interface, wt_Note, false, false, false, false },
{ at_Anchor, wt_Datatype, wt_Note, false, false, false, false },
{ at_Anchor, wt_Enum, wt_Note, false, false, false, false },
{ at_Anchor, wt_Object, wt_Note, false, false, false, false },
{ at_Anchor, wt_Actor, wt_Note, false, false, false, false },
{ at_Anchor, wt_UseCase, wt_Note, false, false, false, false },
{ at_Anchor, wt_Message, wt_Note, false, false, false, false },
{ at_Anchor, wt_State, wt_Note, false, false, false, false },
{ at_Anchor, wt_Activity, wt_Note, false, false, false, false },
{ at_Relationship, wt_Entity, wt_Entity, true, true, true, true },
};
int AssocRules::m_nNumRules = sizeof( m_AssocRules ) / sizeof( AssocRules::Assoc_Rule );