=head1 NAME
-SQL::Translator::XMI::Parser- Perl class for blah blah blah
+SQL::Translator::XMI::Parser
=cut
my $spec12 = $SPECS->{"1.2"} = {};
$spec12->{class} = {
- name => "class",
- plural => "classes",
+ name => "class",
+ plural => "classes",
+ isRoot => 1,
default_path => '//UML:Class[@xmi.id]',
attrib_data =>
[qw/name visibility isSpecification isRoot isLeaf isAbstract isActive/],
plural => "attributes",
default_path => '//Foundation.Core.Attribute[@xmi.id]',
path_data => [
- {
+ {
name => "name",
path => 'Foundation.Core.ModelElement.name/text()',
},
- {
+ {
name => "visibility",
path => 'Foundation.Core.ModelElement.visibility/@xmi.value',
},
- {
+ {
name => "isSpecification",
path => 'Foundation.Core.ModelElement.isSpecification/@xmi.value',
},
- {
+ {
name => "ownerScope",
path => 'Foundation.Core.Feature.ownerScope/@xmi.value',
},
- {
+ {
name => "initialValue",
path => 'Foundation.Core.Attribute.initialValue/Foundation.Data_Types.Expression/Foundation.Data_Types.Expression.body/text()',
},
- #{
- # name => "datatype",
- # path => 'xmiDeref(Foundation.Core.StructuralFeature.type/Foundation.Core.Classifier)/Foundation.Core.DataType/Foundation.Core.ModelElement.name/text()',
- #},
+ # {
+ # name => "datatype",
+ # path => 'xmiDeref(Foundation.Core.StructuralFeature.type/Foundation.Core.Classifier)/Foundation.Core.DataType/Foundation.Core.ModelElement.name/text()',
+ # },
],
};
foreach ( @{$spec->{kids}} ) {
$_->{get_method} = "get_".$specs->{$_->{class}}{plural};
}
-
+
# Add xmi.id ti all specs. Everything we want at the moment (in both
# versions) has an id. The tags that don't seem to be used for
# structure.
foreach ( values %{$SPECS->{"1.2"}} ) {
my $name = $_->{plural};
no strict "refs";
-
+
# get_ on parser
- *{"get_$name"} = sub {
- #my $me = shift;
- #$me->{xmi_get_}{$name}->($me,@_);
+ my $code = sub {
$_[0]->{xmi_get_}{$name}->(@_);
};
+ *{"get_$name"} = $code;
}
}
my $specs = shift;
my $gets;
foreach ( values %$specs ) {
- # Clone from specs and sort out the lookups into it so we get a
- # self contained spec to use as a proper closure.
+ # Clone from specs so we get a proper closure.
my $spec = dclone($_);
# Add the sub
#warn "Searching for $spec->{plural} using:$xpath\n";
my @nodes = $xp->findnodes($xpath);
+#warn "None.\n" unless @nodes;
return unless @nodes;
for my $node (@nodes) {
+#warn " Found $spec->{name} xmi.id=".$node->getAttribute("xmi.id")." name=".$node->getAttribute("name")."\n";
my $thing = {};
# my $thing = { xpNode => $node };
+ # Have we seen this before? If so just use the ref we have.
+ if ( my $id = $node->getAttribute("xmi.id") ) {
+ if ( my $foo = $me->{model}{things}{$id} ) {
+#warn " Reffing from model **********************\n";
+ push @$things, $foo;
+ next;
+ }
+ }
+
# Get the Tag attributes
foreach ( @{$spec->{attrib_data}} ) {
$thing->{$_} = $node->getAttribute($_);
# Add the path data
foreach ( @{$spec->{path_data}} ) {
-#warn "Searching for $spec->{plural} - $_->{name} using:$_->{path}\n";
+#warn " $spec->{name} - $_->{name} using:$_->{path}\n";
my @nodes = $node->findnodes($_->{path});
$thing->{$_->{name}} = @nodes ? $nodes[0]->getData
: (exists $_->{default} ? $_->{default} : undef);
next unless $filter->($thing);
}
+ # Add anything with an id to the things lookup
+ push @$things, $thing;
+ if ( exists $thing->{"xmi.id"} and defined $thing->{"xmi.id"}
+ and my $id = $thing->{"xmi.id"}
+ ) {
+ $me->{model}{things}{$id} = $thing; }
+
# Kids
#
foreach ( @{$spec->{kids}} ) {
my $data;
my $meth = $_->{get_method};
my $path = $_->{path};
+
+ # Variable subs on the path from thing
+ $path =~ s/\$\{(.*?)\}/$thing->{$1}/g;
$data = $me->$meth( _context => $node, _xpath => $path,
filter => $args{"filter_$_->{name}"} );
}
}
}
+ }
- push @$things, $thing;
+ if ( $spec->{isRoot} ) {
+ push(@{$me->{model}{$spec->{plural}}}, $_) foreach @$things;
}
- return wantarray ? @$things : $things;
+ return $things;
} # /closure sub
} # /mk_get