umbrello API Documentation

assocrules.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
00007  *                                                                         *
00008  *   copyright (C) 2002-2007                                               *
00009  *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
00010  ***************************************************************************/
00011 
00012 // own header
00013 #include "assocrules.h"
00014 
00015 // qt/kde includes
00016 #include <kdebug.h>
00017 #include <typeinfo>
00018 
00019 // local includes
00020 #include "uml.h"
00021 #include "umlview.h"
00022 #include "umlwidget.h"
00023 #include "umlobject.h"
00024 #include "associationwidgetlist.h"
00025 #include "associationwidget.h"
00026 #include "statewidget.h"
00027 #include "activitywidget.h"
00028 #include "forkjoinwidget.h"
00029 
00030 
00031 using namespace Uml;
00032 
00033 AssocRules::AssocRules() {}
00034 
00035 AssocRules::~AssocRules() {}
00036 
00037 bool allowAssociation( Association_Type/* assocType*/, const std::type_info/* &type*/ )
00038 {
00039     return false;
00040 
00041 }
00042 
00043 bool AssocRules::allowAssociation( Association_Type assocType, UMLWidget * widget ) {
00044     Widget_Type widgetType = widget -> getBaseType();
00045     bool bValid = false;
00046     for (int i = 0; i < m_nNumRules; i++) {
00047         if (assocType == m_AssocRules[i].assoc_type) {
00048             if (widgetType == m_AssocRules[i].widgetA_type
00049                     || widgetType == m_AssocRules[i].widgetB_type ) {
00050                 bValid =  true;
00051             }
00052         }
00053     }
00054     if( !bValid ) {
00055         // Special case: Subsystem realizes interface in component diagram
00056         UMLView *view = UMLApp::app()->getCurrentView();
00057         if (view && view->getType() == dt_Component && widgetType == wt_Package &&
00058             (assocType == at_Generalization || assocType == at_Realization))
00059             bValid = true;
00060         else
00061             return false;
00062     }
00063     AssociationWidgetList list = widget -> getAssocList();
00064     AssociationWidgetListIt it( list );
00065     AssociationWidget * assoc = 0;
00066     switch( assocType ) {
00067     case at_Association:
00068     case at_UniAssociation:
00069     case at_Dependency:
00070     case at_Coll_Message:
00071     case at_Generalization://can have many sub/super types
00072     case at_Aggregation:
00073     case at_Relationship:
00074     case at_Composition:
00075     case at_Containment:
00076         return true;//doesn't matter whats already connected to widget
00077         break;
00078 
00079     case at_Association_Self:
00080         return true;// we should really check that connection is to same object
00081         break;
00082 
00083     case at_Realization:  // one connected to widget only (a or b)
00084         while( ( assoc = it.current() ) ) {
00085             if( assoc -> getAssocType() == at_Realization )
00086                 return false;
00087             ++it;
00088         }
00089         return true;
00090         break;
00091 
00092     case at_State:
00093         {
00094             StateWidget *pState = dynamic_cast<StateWidget*>(widget);
00095             return (pState == NULL || pState->getStateType() != StateWidget::End);
00096         }
00097         break;
00098 
00099     case at_Activity:
00100         {
00101             ActivityWidget *pActivity = dynamic_cast<ActivityWidget*>(widget);
00102             return (pActivity == NULL || pActivity->getActivityType() != ActivityWidget::End);
00103         }
00104         break;
00105 
00106     case at_Anchor:
00107         return true;
00108         break;
00109     default:
00110         kWarning() << "allowAssociation() on unknown type" << endl;
00111         break;
00112     }
00113     return false;
00114 }
00115 
00116 // when we know what we are going to connect both ends of the association to, we can
00117 // use this method.
00118 bool AssocRules::allowAssociation( Association_Type assocType,
00119                                    UMLWidget * widgetA, UMLWidget * widgetB,
00120                                    bool extendedCheck ) {
00121     Widget_Type widgetTypeA = widgetA->getBaseType();
00122     Widget_Type widgetTypeB = widgetB->getBaseType();
00123     bool bValid = false;
00124     for (int i = 0; i < m_nNumRules; i++) {
00125         if (assocType == m_AssocRules[i].assoc_type) {
00126             if( (widgetTypeA == m_AssocRules[i].widgetA_type &&
00127                     widgetTypeB == m_AssocRules[i].widgetB_type) ||
00128                     (widgetTypeB == m_AssocRules[i].widgetA_type &&
00129                      widgetTypeA == m_AssocRules[i].widgetB_type ) )
00130                 bValid = true;
00131         }
00132     }
00133     // we can bail here for quick checks, as occur in loading files
00134     // for paste or regular creation operations, we need to go further
00135     if (!extendedCheck) {
00136         return bValid;
00137     }
00138 
00139     if (!bValid) {
00140         return false;
00141     }
00142     AssociationWidgetList list = widgetB -> getAssocList();
00143     AssociationWidgetListIt it( list );
00144     AssociationWidget * assoc = 0;
00145     switch( assocType ) {
00146     case at_Association:
00147     case at_Association_Self:
00148     case at_UniAssociation:
00149     case at_Dependency:
00150     case at_Coll_Message:
00151     case at_Aggregation:
00152     case at_Relationship:
00153         return true;  // doesn't matter what's already connected to widget
00154         break;
00155 
00156     case at_Composition:   // can't have mutual composition
00157     case at_Containment:   // can't have mutual containment
00158     case at_Generalization://can have many sub/super types but can't sup/sub each
00159         while( ( assoc = it.current() ) ) {
00160             if( ( widgetA == assoc -> getWidget(A) || widgetA == assoc -> getWidget(B) )
00161                     && assoc->getAssocType() == assocType )
00162                 return false;
00163             ++it;
00164         }
00165         return true;
00166         break;
00167 
00168     case at_Realization: // can only connect to abstract (interface) classes
00169         while( ( assoc = it.current() ) ) {
00170             if( ( widgetA == assoc->getWidget(A) || widgetA == assoc->getWidget(B) )
00171                     && assoc->getAssocType() == at_Realization ) {
00172                 return false;
00173             }
00174             ++it;
00175         }
00176         if (widgetB->getBaseType() == wt_Class) {
00177             return widgetB->getUMLObject()->getAbstract();
00178         } else if (widgetB->getBaseType() == wt_Interface ||
00179                    widgetB->getBaseType() == wt_Package) {
00180             return true;
00181         }
00182         break;
00183 
00184     case at_State:
00185         {
00186             StateWidget *stateA = dynamic_cast<StateWidget*>(widgetA);
00187             StateWidget *stateB = dynamic_cast<StateWidget*>(widgetB);
00188             if (stateA && stateB) {
00189                 if (stateB->getStateType() == StateWidget::Initial)
00190                     return false;
00191                 if (stateB->getStateType() == StateWidget::End &&
00192                     stateA->getStateType() != StateWidget::Normal)
00193                     return false;
00194             }
00195         }
00196         return true;
00197         break;
00198 
00199     case at_Activity:
00200         {
00201             ActivityWidget *actA = dynamic_cast<ActivityWidget*>(widgetA);
00202             ActivityWidget *actB = dynamic_cast<ActivityWidget*>(widgetB);
00203             // no transitions to initial activity allowed
00204             if (actB && actB->getActivityType() == ActivityWidget::Initial)
00205                 return false;
00206             // actType -1 here means "not applicable".
00207             int actTypeA = -1;
00208             if (actA)
00209                 actTypeA = actA->getActivityType();
00210             int actTypeB = -1;
00211             if (actB)
00212                 actTypeB = actB->getActivityType();
00213             // only from a normal, branch or fork activity to the end
00214             if (actTypeB == ActivityWidget::End &&
00215                 actTypeA != ActivityWidget::Normal &&
00216                 actTypeA != ActivityWidget::Branch &&
00217                 dynamic_cast<ForkJoinWidget*>(widgetA) == NULL) {
00218                 return false;
00219             }
00220             // only Forks and Branches can have more than one "outgoing" transition
00221             if (actA != NULL && actTypeA != ActivityWidget::Branch) {
00222                 AssociationWidgetList list = widgetA->getAssocList();
00223                 for (AssociationWidget* assoc = list.first(); assoc; assoc = list.next()) {
00224                     if (assoc->getWidget(A) == widgetA) {
00225                         return false;
00226                     }
00227                 }
00228             }
00229         }
00230         return true;
00231         break;
00232 
00233     case at_Anchor:
00234         return true;
00235         break;
00236 
00237     default:
00238         kWarning() << "allowAssociation() on unknown type" << endl;
00239         break;
00240     }
00241     return false;
00242 }
00243 
00244 bool AssocRules::allowRole( Association_Type assocType ) {
00245     for( int i = 0; i < m_nNumRules; i++ )
00246         if( assocType == m_AssocRules[ i ].assoc_type )
00247             return m_AssocRules[ i ].role;
00248     return false;
00249 }
00250 
00251 bool AssocRules::allowMultiplicity( Association_Type assocType, Widget_Type widgetType ) {
00252     for( int i = 0; i < m_nNumRules; i++ )
00253         if( assocType == m_AssocRules[ i ].assoc_type )
00254             if( widgetType == m_AssocRules[ i ].widgetA_type || widgetType == m_AssocRules[ i ].widgetB_type )
00255                 return m_AssocRules[ i ].multiplicity;
00256     return false;
00257 }
00258 
00259 bool AssocRules::allowSelf( Association_Type assocType, Widget_Type widgetType ) {
00260     for( int i = 0; i < m_nNumRules; i++ )
00261         if( assocType == m_AssocRules[ i ].assoc_type )
00262             if( widgetType == m_AssocRules[ i ].widgetA_type || widgetType == m_AssocRules[ i ].widgetB_type )
00263                 return m_AssocRules[ i ].self;
00264 
00265     return false;
00266 }
00267 
00268 Association_Type AssocRules::isGeneralisationOrRealisation(UMLWidget* widgetA, UMLWidget* widgetB) {
00269     Widget_Type widgetTypeA = widgetA->getBaseType();
00270     Widget_Type widgetTypeB = widgetB->getBaseType();
00271     for (int i = 0; i < m_nNumRules; i++) {
00272         if (m_AssocRules[i].assoc_type == at_Realization &&
00273                 widgetTypeA == m_AssocRules[i].widgetA_type &&
00274                 widgetTypeB == m_AssocRules[i].widgetB_type) {
00275             return at_Realization;
00276         }
00277     }
00278     return at_Generalization;
00279 }
00280 
00281 AssocRules::Assoc_Rule AssocRules::m_AssocRules []= {
00282     //  Association     widgetA         widgetB         role    multi   directional  self
00283     //---------------+----------------+----------------+-------+-------+-------+---------
00284     { at_Association_Self,wt_Class,     wt_Class,       true,   true,   true,   true  },
00285     { at_Association_Self,wt_Object,    wt_Object,      true,   true,   true,   true  },
00286     { at_Association_Self,wt_Interface, wt_Interface,   true,   true,   true,   true  },
00287     { at_Association,   wt_Class,       wt_Class,       true,   true,   true,   true },
00288     { at_Association,   wt_Object,      wt_Object,      true,   true,   true,   true },
00289     { at_Association,   wt_Interface,   wt_Interface,   true,   true,   true,   true },
00290     { at_Association,   wt_Interface,   wt_Class,       true,   true,   true,   false },
00291     { at_Association,   wt_Class,       wt_Interface,   true,   true,   true,   false },
00292     { at_Association,   wt_Datatype,    wt_Class,       true,   true,   true,   false },
00293     { at_Association,   wt_Class,       wt_Datatype,    true,   true,   true,   false },
00294     { at_Association,   wt_Enum,        wt_Class,       true,   true,   true,   false },
00295     { at_Association,   wt_Class,       wt_Enum,        true,   true,   true,   false },
00296     { at_Association,   wt_Actor,       wt_UseCase,     true,   false,  false,  false },
00297     { at_Association,   wt_UseCase,     wt_UseCase,     true,   false,  false,  false },
00298     { at_Association,   wt_Actor,       wt_Actor,       true,   false,  false,  false },
00299     { at_Association,   wt_Actor,       wt_UseCase,     true,   false,  false,  false },
00300     { at_Association,   wt_Component,   wt_Interface,   true,   false,  false,  false },
00301     { at_Association,   wt_Interface,   wt_Artifact,    true,   false,  false,  false },
00302     { at_Association,   wt_Node,        wt_Node,        true,   false,  false,  false },
00303     { at_UniAssociation,wt_Class,       wt_Class,       true,   true,   true,   true  },
00304     { at_UniAssociation,wt_Object,      wt_Object,      true,   true,   true,   true  },
00305     { at_UniAssociation,wt_Interface,   wt_Interface,   true,   true,   true,   true  },
00306     { at_UniAssociation,wt_Interface,   wt_Class,       true,   true,   true,   true  },
00307     { at_UniAssociation,wt_Class,       wt_Interface,   true,   true,   true,   true  },
00308     { at_UniAssociation,wt_Class,       wt_Datatype,    true,   true,   true,   true  },
00309     { at_UniAssociation,wt_Class,       wt_Enum,        true,   true,   true,   true  },
00310     { at_UniAssociation,wt_Actor,       wt_Actor,       true,   false,  false,  false },
00311     { at_UniAssociation,wt_UseCase,     wt_UseCase,     true,   false,  false,  false },
00312     { at_UniAssociation,wt_UseCase,     wt_Actor,       true,   false,  false,  false },
00313     { at_Generalization,wt_Class,       wt_Datatype,    false,  false,  false,  false },
00314     { at_Generalization,wt_Class,       wt_Class,       false,  false,  false,  false },
00315     { at_Generalization,wt_Interface,   wt_Interface,   false,  false,  false,  false },
00316     { at_Generalization,wt_UseCase,     wt_UseCase,     false,  false,  false,  false },
00317     { at_Generalization,wt_Actor,       wt_Actor,       false,  false,  false,  false },
00318     { at_Generalization,wt_Component,   wt_Interface,   false,  false,  false,  false },
00319     { at_Aggregation,   wt_Class,       wt_Class,       true,   true,   false,  true  },
00320     { at_Aggregation,   wt_Class,       wt_Interface,   true,   true,   false,  false },
00321     { at_Aggregation,   wt_Class,       wt_Enum,        true,   true,   false,  false },
00322     { at_Aggregation,   wt_Class,       wt_Datatype,    true,   true,   false,  false },
00323     { at_Dependency,    wt_Class,       wt_Class,       true,   false,  false,  true },
00324     { at_Dependency,    wt_UseCase,     wt_UseCase,     true,   false,  false,  false },
00325     { at_Dependency,    wt_Actor,       wt_Actor,       true,   false,  false,  false },
00326     { at_Dependency,    wt_Actor,       wt_UseCase,     true,   false,  false,  false },
00327     { at_Dependency,    wt_Package,     wt_Package,     true,   true,   true,   true  },
00328     { at_Dependency,    wt_Package,     wt_Class,       true,   true,   true,   true  },
00329     { at_Dependency,    wt_Class,       wt_Package,     true,   true,   true,   true  },
00330     { at_Dependency,    wt_Package,     wt_Interface,   true,   true,   true,   true  },
00331     { at_Dependency,    wt_Interface,   wt_Package,     true,   true,   true,   true  },
00332     { at_Dependency,    wt_Interface,   wt_Interface,   true,   true,   true,   true  },
00333     { at_Dependency,    wt_Interface,   wt_Class,       true,   true,   true,   true  },
00334     { at_Dependency,    wt_Class,       wt_Interface,   true,   true,   true,   true  },
00335     { at_Dependency,    wt_Class,       wt_Datatype,    true,   true,   true,   true  },
00336     { at_Dependency,    wt_Class,       wt_Enum,        true,   true,   true,   true  },
00337     { at_Dependency,    wt_Component,   wt_Component,   true,   true,   true,   true  },
00338     { at_Dependency,    wt_Component,   wt_Interface,   true,   true,   true,   true  },
00339     { at_Dependency,    wt_Component,   wt_Artifact,    true,   false,  false,  false },
00340     { at_Dependency,    wt_Node,        wt_Component,   true,   false,  false,  false },
00341     { at_Realization,   wt_Class,       wt_Interface,   false,  false,  false,  false },
00342     { at_Realization,   wt_Interface,   wt_Package,     false,  false,  false,  false },
00343     { at_Realization,   wt_Interface,   wt_Interface,   false,  false,  false,  false },
00344     { at_Realization,   wt_Component,   wt_Interface,   false,  false,  false,  false },
00345     { at_Realization,   wt_Package,     wt_Interface,   false,  false,  false,  false },
00346     { at_Composition,   wt_Class,       wt_Class,       true,   true,   false,  true  },
00347     { at_Composition,   wt_Class,       wt_Interface,   true,   true,   false,  false },
00348     { at_Composition,   wt_Class,       wt_Enum,        true,   true,   false,  false },
00349     { at_Composition,   wt_Class,       wt_Datatype,    false,  false,  false,  false },
00350     { at_Composition,   wt_Class,       wt_Class,       false,  false,  false,  false },
00351     { at_Containment,   wt_Package,     wt_Class,       false,  false,  true,   false },
00352     { at_Containment,   wt_Package,     wt_Interface,   false,  false,  true,   false },
00353     { at_Containment,   wt_Package,     wt_Enum,        false,  false,  true,   false },
00354     { at_Containment,   wt_Package,     wt_Package,     false,  false,  true,   false },
00355     { at_Containment,   wt_Package,     wt_Component,   false,  false,  true,   false },
00356     { at_Containment,   wt_Class,       wt_Class,       false,  false,  true,   false },
00357     { at_Containment,   wt_Class,       wt_Interface,   false,  false,  true,   false },
00358     { at_Containment,   wt_Class,       wt_Enum,        false,  false,  true,   false },
00359     { at_Containment,   wt_Interface,   wt_Class,       false,  false,  true,   false },
00360     { at_Containment,   wt_Interface,   wt_Interface,   false,  false,  true,   false },
00361     { at_Containment,   wt_Interface,   wt_Enum,        false,  false,  true,   false },
00362     { at_Containment,   wt_Component,   wt_Component,   false,  false,  true,   false },
00363     { at_Containment,   wt_Component,   wt_Artifact,    false,  false,  true,   false },
00364     { at_Coll_Message,  wt_Object,      wt_Object,      true,   false,  true,   true  },
00365     { at_State,         wt_State,       wt_State,       true,   false,  true,   true  },
00366     { at_State,         wt_ForkJoin,    wt_State,       true,   false,  true,   true  },
00367     { at_State,         wt_State,       wt_ForkJoin,    true,   false,  true,   true  },
00368     { at_Activity,      wt_Activity,    wt_Activity,    true,   false,  true,   true  },
00369     { at_Activity,      wt_ForkJoin,    wt_Activity,    true,   false,  true,   true  },
00370     { at_Activity,      wt_Activity,    wt_ForkJoin,    true,   false,  true,   true  },
00371     { at_Anchor,        wt_Class,       wt_Note,        false,  false,  false,  false },
00372     { at_Anchor,        wt_Package,     wt_Note,        false,  false,  false,  false },
00373     { at_Anchor,        wt_Interface,   wt_Note,        false,  false,  false,  false },
00374     { at_Anchor,        wt_Datatype,    wt_Note,        false,  false,  false,  false },
00375     { at_Anchor,        wt_Enum,        wt_Note,        false,  false,  false,  false },
00376     { at_Anchor,        wt_Object,      wt_Note,        false,  false,  false,  false },
00377     { at_Anchor,        wt_Actor,       wt_Note,        false,  false,  false,  false },
00378     { at_Anchor,        wt_UseCase,     wt_Note,        false,  false,  false,  false },
00379     { at_Anchor,        wt_Message,     wt_Note,        false,  false,  false,  false },
00380     { at_Anchor,        wt_State,       wt_Note,        false,  false,  false,  false },
00381     { at_Anchor,        wt_Activity,    wt_Note,        false,  false,  false,  false },
00382     { at_Relationship,  wt_Entity,      wt_Entity,      true,   true,   true,   true  },
00383 };
00384 
00385 int AssocRules::m_nNumRules = sizeof( m_AssocRules ) / sizeof( AssocRules::Assoc_Rule );
00386 
KDE Logo
This file is part of the documentation for umbrello Version 3.1.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Jun 26 08:07:54 2007 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003