| UMMF documentation | Contained in the UMMF distribution. |
UMMF::XForm::FoldMultipleInheritance - Inlines multiple inheritance bodies.
use UMMF::XForm::FoldMultipleInheritance; my $xform = UMMF::XForm::FoldMultipleInheritance->new(); $model = $xform->apply_Model($model);
This transform is useful for converting a Model containing multiple inheritance to a Model using single inheritance by creating Interfaces for classes that are inherited from in multiple inheritance context and inlining Features and Operations from the multiple inheritance Classifiers.
None exported.
Kurt Stephens, kstephens@users.sourceforge.net 2003/05/04
$Revision: 1.8 $
| UMMF documentation | Contained in the UMMF distribution. |
package UMMF::XForm::FoldMultipleInheritance; use 5.6.1; use strict; use warnings; our $AUTHOR = q{ kstephens@users.sourceforge.net 2003/05/04 }; our $VERSION = do { my @r = (q$Revision: 1.8 $ =~ /\d+/g); sprintf "%d." . "%03d" x $#r, @r };
####################################################################### use base qw(UMMF::XForm); ####################################################################### use UMMF::Core::Util qw(:all); use Carp qw(confess); use UMMF::XForm::ClassInterface; ####################################################################### sub initialize { my ($self) = @_; $self->SUPER::initialize; $self->{'verbose'} ||= 0; $self; } ####################################################################### sub apply_Model { my ($self, $model) = @_; my $x1 = UMMF::XForm::ClassInterface ->new( 'verbose' => $self->{'verbose'}, 'config_enabled_force' => 1, ); # Do Class => Interface production. $model = $x1->apply_Model($model); # Get mappings of production. my $iface = $x1->{'iface'}; my $icls = $x1->{'icls'}; print STDERR "* Pass 1:\n" if $self->{'verbose'} > 0; # For each Class that has more than one Generalization: # 1. Leave the first Generalization (to reduce code bloat). # 2. Remove the remaining Generalizations. # 3. Create Abstraction to analogous generated Interface from # each remaining Generalization. # 4. Copy Features and Assocations from all remaining Generalizations and # their Generalization parents, avoiding all Classifiers that are Generalizations # of the first Generalization. my (@op); for my $cls ( Namespace_class($model) ) { my @gen = $cls->generalization; next unless @gen > 1; # Leave the first Generalization and all its Generalization parents # out of the traversal. my $keep = (shift @gen)->parent; my @avoid = ( $keep, GeneralizableElement_generalization_parent_all($keep), ); # Remove extra generalizations. my @copy_op; my @abs_op; my $op = [ $cls, $keep, \@avoid, [ @gen ], \@abs_op, \@copy_op ]; push(@op, $op); # Map to actual Classifier. @gen = map($_->parent, @gen); # $DB::single = 1; # Create Abstractions to the new Interfaces. # Select only defined Interfaces of the Generalization parent. { my %visit; my @x = @gen; while ( @x ) { my $x = pop @x; next if $visit{$x} ++; push(@x, map($_->parent, $x->generalization)); for my $abs ( $iface->{$x}, map($_->supplier, grep($_->isaAbstraction, $x->clientDependency) ) ) { push(@abs_op, $abs) if $abs && ! grep($_ eq $abs, @abs_op); } } } # Start visiting others, except all Classes already covered # by first Generalization. { my %visit = ( map(($_ => 1), @avoid) ); while ( @gen ) { my $scls = pop(@gen); next if $visit{$scls} ++; push(@gen, map($_->parent, $scls->generalization)); # What to do. push(@copy_op, [ $scls, [ $scls->feature ], [ $scls->association ] ]); } } } # Apply Model deltas now. for my $x ( @op ) { my ($cls, $keep, $avoid, $gen, $abs, $copy) = @$x; print STDERR "Classifier '", $cls->name, "' :\n" if $self->{'verbose'} > 0; print STDERR " Keeping Generalization => ", $keep->name, "\n" if $self->{'verbose'} > 0; if ( @$gen ) { print STDERR " Removing Generalizations : ", join(', ', map($_->parent->name, @$gen)), "\n" if $self->{'verbose'} > 0; $cls->remove_generalization(@$gen); } if ( @$abs ) { print STDERR " Adding Abstractions : ", join(', ', map($_->name, @$abs)), "\n" if $self->{'verbose'} > 0; for my $iface ( @$abs ) { my $factory = $cls->__factory; $factory->create('Abstraction', 'namespace' => $cls->namespace, 'supplier' => [ $iface ], 'client' => [ $cls ], ); } } print STDERR " Avoiding Features from ", join(', ', map($_->name, @$avoid)), "\n" if $self->{'verbose'} > 0; $self->{'assoc_copied'} = { }; for my $y ( @$copy ) { my ($scls, $features, $assocs) = @$y; $self->copy_Classifier_Feature($cls, $scls, $features); $self->copy_Classifier_AssociationEnd($cls, $scls, $assocs); } } # Replace all Class type usages with Interfaces. $x1->{'verbose'} = 9; $model = $x1->pass_4($model); $model; } ####################################################################### 1; ####################################################################### ### Keep these comments at end of file: kstephens@users.sourceforge.net 2003/04/06 ### ### Local Variables: ### ### mode:perl ### ### perl-indent-level:2 ### ### perl-continued-statement-offset:0 ### ### perl-brace-offset:0 ### ### perl-label-offset:0 ### ### End: ###