1 package SQL::Translator::Parser::XML::XMI::Rational;
3 # -------------------------------------------------------------------
4 # $Id: Rational.pm,v 1.6 2003-10-06 15:43:41 grommit Exp $
5 # -------------------------------------------------------------------
6 # Copyright (C) 2003 Mark Addison <mark.addison@itn.co.uk>,
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License as
10 # published by the Free Software Foundation; version 2.
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 # -------------------------------------------------------------------
25 SQL::Translator::Parser::XML::XMI::Rational - Create Schema using Rational's UML
26 Data Modeling Profile.
32 use vars qw[ $DEBUG $VERSION @EXPORT_OK ];
33 $VERSION = sprintf "%d.%02d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/;
34 $DEBUG = 0 unless defined $DEBUG;
36 use base qw(Exporter);
37 @EXPORT_OK = qw(parse);
39 use SQL::Translator::Parser::XML::XMI;
40 use SQL::Translator::Utils 'debug';
42 # Set the parg for the conversion sub then use the XMI parser
44 my ( $translator ) = @_;
45 local $DEBUG = $translator->debug;
46 my $pargs = $translator->parser_args;
47 $pargs->{classes2schema} = \&classes2schema;
48 return SQL::Translator::Parser::XML::XMI::parse(@_);
53 return grep {$_->{kind} ne "return"} @$params;
57 my ($schema, $classes) = @_;
59 foreach my $class (@$classes) {
60 next unless $class->{stereotype} eq "Table";
63 debug "Adding class: $class->{name}";
64 my $table = $schema->add_table( name => $class->{name} )
65 or die "Schema Error: ".$schema->error;
68 # Fields from Class attributes
70 foreach my $attr ( @{$class->{attributes}} ) {
71 next unless $attr->{stereotype} eq "Column"
72 or $attr->{stereotype} eq "PK"
73 or $attr->{stereotype} eq "FK"
74 or $attr->{stereotype} eq "PFK";
77 $attr->{stereotype} eq "PK" or $attr->{stereotype} eq "PFK"
80 name => $attr->{name},
81 data_type => $attr->{datatype},
82 is_primary_key => $ispk,
84 $data{default_value} = $attr->{initialValue}
85 if exists $attr->{initialValue};
86 $data{data_type} = $attr->{_map_taggedValues}{dataType}{dataValue}
88 $data{size} = $attr->{_map_taggedValues}{size}{dataValue};
89 $data{is_nullable}=$attr->{_map_taggedValues}{nullable}{dataValue};
91 my $field = $table->add_field( %data ) or die $schema->error;
92 $table->primary_key( $field->name ) if $data{'is_primary_key'};
96 # Constraints and indexes from Operations
98 foreach my $op ( @{$class->{operations}} ) {
99 next unless my $stereo = $op->{stereotype};
100 my @fields = map {$_->{name}} grep {$_->{kind} ne "return"} @{$op->{parameters}};
107 # Work out type and any other data
108 if ( $stereo eq "Unique" ) {
109 $data{type} = "UNIQUE";
111 elsif ( $stereo eq "PK" ) {
112 $data{type} = "PRIMARY_KEY";
114 # Work out the ref table
115 elsif ( $stereo eq "FK" ) {
116 $data{type} = "FOREIGN_KEY";
117 _add_fkey_refs($class,$op,\%data);
120 # Add the constraint or index
122 $table->add_constraint( %data ) or die $schema->error;
124 elsif ( $stereo eq "Index" ) {
125 $data{type} = "NORMAL";
126 $table->add_index( %data ) or die $schema->error;
136 my ($class,$op,$data) = @_;
138 # Find the association ends
139 my ($end) = grep { $_->{name} eq $op->{name} } @{$class->{associationEnds}};
142 my ($refop) = grep { $_->{name} eq $end->{otherEnd}{name} }
143 @{$end->{otherEnd}{participant}{operations}};
144 return unless $refop;
146 $data->{reference_table} = $end->{otherEnd}{participant}{name};
147 $data->{reference_fields} = [ map("$_->{name}", _parameters_in($refop->{parameters})) ];
151 1; #---------------------------------------------------------------------------
160 use SQL::Translator::Parser::XML::XMI;
162 my $translator = SQL::Translator->new(
163 from => 'XML-XMI-Rational',
165 filename => 'schema.xmi',
170 print $obj->translate;
174 Translates Schema described using Rational Software's UML Data Modeling Profile.
175 Finding good information on this profile seems to be very difficult so this
176 is based on a vague white paper and notes in vendors docs!
178 Below is a summary of what this parser thinks the profile looks like.
180 B<Tables> Are classes marked with <<Table>> stereotype.
182 B<Fields> Attributes stereotyped with <<Column>> or one of the key stereotypes.
183 Additional info is added using tagged values of C<dataType>, C<size> and
184 C<nullable>. Default value is given using normal UML default value for the
187 B<Keys> Key fields are marked with <<PK>>, <<FK>> or <<PFK>>. Note that this is
188 really to make it obvious on the diagram, you must still add the constraints.
189 (This parser will also automatically add the constraint for single field pkeys
190 for attributes marked with PK but I think this is out of spec.)
192 B<Constraints> Stereotyped operations, with the names of the parameters
193 indicating which fields it applies to. Can use <<PK>>, <<FK>>, <<Unique>> or
196 B<Relationships> You can model the relationships in the diagram and have the
197 translator add the foreign key constraints for you. The forign keys are defined
198 as <<FK>> operations as show above. To show which table they point to join the
199 class to the taget classwith an association where the role names are the names
200 of the constraints to join.
204 +------------------------------------------------------+
207 +------------------------------------------------------+
208 | <<PK>> fooID { dataType=INT size=10 nullable=0 } |
209 | <<Column>> name { dataType=VARCHAR size=255 } |
210 | <<Column>> description { dataType=TEXT } |
211 +------------------------------------------------------+
212 | <<PK>> pkcon( fooID ) |
213 | <<Unique>> con2( name ) |
214 +------------------------------------------------------+
223 +------------------------------------------------------+
226 +------------------------------------------------------+
227 | <<PK>> barID { dataType=INT size=10 nullable=0 } |
228 | <<FK>> fooID { dataType=INT size=10 nullable=0 } |
229 | <<Column>> name { dataType=VARCHAR size=255 } |
230 +------------------------------------------------------+
231 | <<PK>> pkcon( barID ) |
232 | <<FK>> fkcon( fooID ) |
233 +------------------------------------------------------+
236 fooID INT(10) NOT NULL,
244 barID INT(10) NOT NULL,
245 fooID INT(10) NOT NULL,
248 FOREIGN KEY fkcon (fooID) REFERENCES Foo (fooID)
257 The Rational profile also defines ways to model stuff above tables such as the
262 Mark D. Addison E<lt>mark.addison@itn.co.ukE<gt>.
266 perl(1), SQL::Translator::Parser::XML::XMI