Problem
In Enterprise Architect 7.1.834 in the code generation templates it is possible to print all the parent packages that a class belongs to in the scope of the File template?
The reason this is needed is to generate multi-include guards compliant with my companies coding standard
What doesn't work
I have tried both:
%list="Namespace__Notes" #separator="-"%
and
%packageName%
The output of both only prints the top-level parent package (Package1) but I would like to see:
Package1-Package2-Package3
Has anyone found a way to do this?
Namepace__Notes
Namepace__Notes is a custom template with Namepace type, the contents are ar follows
%PI=""%
%packageName%
[Edit] Dirty Solution
My current (dirty) solution is to mangle the file-path. Am I missing something?
The code:
$l_backslash = %REPLACE("\z","z","")%
$filepath = %filePath%
$upper_filepath = %TO_UPPER($filepath)%
$upper_package_as_path = $l_backslash + %TO_UPPER(packageName)% + $l_backslash
$upper_package_base_len = %LENGTH(packageName)%
$package_path_pos = %FIND($upper_filepath,$upper_package_as_path)%
%if $package_path_pos != "-1" and $package_path_pos != "0"%
$upper_filepath = %MID($upper_filepath,$package_path_pos)%
%endIf%
$file_define = "_" + $upper_filepath + "__"
$file_define = %REPLACE($file_define,".","_")%
$file_define = %REPLACE($file_define,$l_backslash,"_")%
$file_define = %REPLACE($file_define,"/","_")%
$body += "/**************************************************************************//**"
$body += "\n * \file " + %fileName%
$body += "\n *"
$body += "\n * \brief " + %elemType% + " " + %className% + " header file"
$body += "\n *"
$body += "\n * \author " + %classAuthor ? value : "<unknown>"%
$body += "\n *"
$body += "\n *****************************************************************************/"
$body += "\n"
$body += "\n#ifndef " + $file_define
$body += "\n#define " + $file_define
$body += "\n"
%packagePath% gives you the dot-separated package hierarchy, while %classQualName% yields the ::-separated class hierarchy (for inner classes).
This is for the current version, I don't know whether these macros were present as far back as 7.1. You should seriously consider upgrading, as the current version is 9.3 and EA is backwards-compatible wrt project contents.
In EA 10 %packagePath% also gives only top level package in File template
[Edit] Another dirty and partial solution.
I'v made a new custom templates, Namespace__fullName:
$prevName = %list="Namespace__fullName"%
%if $prevName != ""%
%packageName%::$prevName
%else%
%packageName%
%endIf%
;
and Class__fullQualName:
%list="Namespace__fullName"%::%classQualName%
This will work in simple cases when the source file contains only 1 class (possibly with nested items) and, therefore, only 1 namespaces hierarchy.
In my code, I want to view all data from a CSV in table form, but it only displays the last line. How about lines 1 and 2? Here's the data:
1,HF6,08-Oct-08,34:22:13,df,jhj,fh,fh,ffgh,gh,g,rt,ffgsaf,asdf,dd,yoawa,DWP,tester,Pattern
2,hf35,08-Oct-08,34:12:13,dg,jh,fh,fgh,fgh,gh,gfh,re,fsaf,asdf,dd,yokogawa,DWP,DWP,Pattern
3,hf35,08-Oct-08,31:22:03,dg,jh,fh,fgh,gh,gh,gh,rte,ffgsaf,asdf,dfffd,yokogawa,DWP,DWP,ghh
Here's the code:
#! /usr/bin/perl
print "Content-type:text/html\r\n\r\n";
use CGI qw(:standard);
use strict;
use warnings;
my $line;
my $file;
my ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$f10,$f11,$f12,$f13,$f14,$f15,$f16,$f17,$f18,$f19);
$file='MyFile.txt';
open(F,$file)||die("Could not open $file");
while ($line=<F>)
{
($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$f10,$f11,$f12,$f13,$f14,$f15,$f16,$f17,$f18,$f19)= split ',',$line;
}
close(F);
print "<HTML>";
print "<head>";
print "<body bgcolor='#4682B4'>";
print "<title>FUSION SHIFT REPORT</title>";
print "<div align='left'>";
print "<TABLE CELLPADDING='1' CELLSPACING='1' BORDER='1' bordercolor=black width='100%'>";
print "<TR>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>RECORD No.</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>TESTER No.</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>DATE</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>TIME</td>";
print "<td width='11%'bgcolor='#00ff00'><font size='2'>DEVICE NAME</td>";
print "<td bgcolor='#00ff00'><font size='2'>TEST PROGRAM</td>";
print "<td bgcolor='#00ff00'><font size='2'>DEVICE FAMILY</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>SMSLOT</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>DIE LOT</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>LOADBOARD</td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>TESTER </td>";
print "<td width='12%'bgcolor='#00ff00'><font size='2'>SERIAL NUMBER</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>TESTER CONFIG</td>";
print "<td width='11%'bgcolor='#00ff00'><font size='2'>SMSLOT</td>";
print "<td bgcolor='#00ff00'><font size='2'>PACKAGE</td>";
print "<td bgcolor='#00ff00'><font size='2'>SOCKET</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 1</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 2</td>";
print "<td width='13%'bgcolor='#00ff00'><font size='2'>ROOT CAUSE 3</td>";
print "</tr>";
print "<TR>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f1</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f2</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f3</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f4</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f5</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f6</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f7</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f8</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f9</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f10</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f11</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f12</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f13</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f14</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f15</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f16</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f17</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f18</TD>";
print "<TD bgcolor='#ADD8E6'><font size='2'>$f19</TD>";
print "</tr>";
print "</TABLE>";
print "</body>";
print "<html>";
You need to output the table rows inside the while loop, as that's where you are reading the lines.
So change the code so that it
outputs table headers
reads the file line by line outputting table rows
outputs table footer
Here's how your loop might look if a little simplified...
while ($line=<F>)
{
print "<tr>";
my #cells= split ',',$line;
foreach my $cell (#cells)
{
print "<td>$cell</td>";
}
print "</tr>";
}
HTML::Template would make your life a lot easier. Here's my go with a cut-down template.
#!/usr/local/bin/perl
use strict;
use warnings;
use HTML::Template;
my #table;
while (my $line = <DATA>){
chomp $line;
my #row = map{{cell => $_}} split(/,/, $line);
push #table, {row => \#row};
}
my $tmpl = HTML::Template->new(scalarref => \get_tmpl());
$tmpl->param(table => \#table);
print $tmpl->output;
sub get_tmpl{
return <<TMPL
<html>
<TMPL_LOOP table>
<tr>
<TMPL_LOOP row>
<td><TMPL_VAR cell></td></TMPL_LOOP>
</tr></TMPL_LOOP>
</html>
TMPL
}
__DATA__
1,HF6,08-Oct-08,34:22:13,df,jhj,fh,fh,ffgh,gh,g,rt,ffgsaf,asdf,dd,yoawa,DWP,tester,Pattern
2,hf35,08-Oct-08,34:12:13,dg,jh,fh,fgh,fgh,gh,gfh,re,fsaf,asdf,dd,yokogawa,DWP,DWP,Pattern
3,hf35,08-Oct-08,31:22:03,dg,jh,fh,fgh,gh,gh,gh,rte,ffgsaf,asdf,dfffd,yokogawa,DWP,DWP,ghh
$f1,$f2,$f3,$f4
Any time you see code like that alarm bells should go off. Use an array.
Allow me to demonstrate with a smaller example.
my $f;
while ($line = <F>) {
$f = $line;
}
print $f;
The above code will read every line of the file F, assigning each line to the variable $f. Each time it assigns a new line, the previous line is overwritten. When it reaches the end of the file, it prints out the value of $f once.
my $f;
while ($line = <F>) {
$f = $line;
print $f;
}
The above code has the print inside the loop, so the print will run for each line of the input. You will want to make a similar modification to your code to get the output you expect.
The reason you were only seeing the last line was that you ran the print's after reading the entire file and discarding each line when the next was read.
To be honest, there's various things wrong with that code. I'll mention a couple and address those in the code snippet below.
Don't parse CSV data yourself (the split). Use Text::CSV or -- if you need better performance -- Text::CSV_XS.
Your HTML is invalid. You don't close all tags and in particular, title should be in head, but not body.
You should use a templating module for inserting tabular data into a web page. Examples: HTML::Template or Template Toolkit.
At the very least, use functions to abstract out the redundant code.
Better yet, use the fact that the formatting of the data is also data. That's why it should be treated as such.
If you ever find that you're declaring lots of variables with numbers attached ($f1,$f2,...), you really want an array: #fields = split /,/, $line;
use strict;
use warnings;
use CGI qw();
use Text::CSV;
my $cgi = CGI->new();
print $cgi->header();
my $file ='MyFile.txt';
# should really use a templating module from CPAN,
# but let's take it step by step.
# Any of the following would fit nicely:
# - Template.pm (Template Toolkit)
# - HTML::Template, etc.
my $startHtml = <<'HERE';
<html>
<head> <title>FUSION SHIFT REPORT</title> </head>
<body bgcolor="#4682B4">
<div align="left">
<table cellpadding="1" cellspacing="1" border="1" bordercolor="black" width="100%">
HERE
my $endHtml = <<'HERE';
</table>
</body>
<html>
HERE
my #columns = (
{ name => 'RECORD No.', width => 12 },
{ name => 'TESTER No.', width => 12 },
{ name => 'DATE', width => 12 },
{ name => 'TIME', width => 13 },
{ name => 'DEVICE NAME', width => 11 },
{ name => 'TEST PROGRAM' },
{ name => 'DEVICE FAMILY' },
{ name => 'SMSLOT', width => 13 },
{ name => 'DIE LOT', width => 13 },
{ name => 'LOADBOARD', width => 12 },
{ name => 'TESTER', width => 12 },
{ name => 'SERIAL NUMBER', width => 12 },
{ name => 'TESTER CONFIG', width => 13 },
{ name => 'SMSLOT', width => 11 },
{ name => 'PACKAGE' },
{ name => 'SOCKET' },
{ name => 'ROOT CAUSE 1', width => 13 },
{ name => 'ROOT CAUSE 2', width => 13 },
{ name => 'ROOT CAUSE 3', width => 13 },
);
my $csv = Text::CSV->new();
open my $fh, '<', $file
or die "Could not open file '$file': $!"; # should generate a HTML error here
# print header
print $startHtml;
print_table_header(\#columns);
while (defined(my $line = <$fh>)) {
$csv->parse($line);
# watch out: This may be "tainted" data!
my #fields = $csv->fields();
#fields = #fields[0..$#columns] if #fields > #columns;
print_table_line(\#fields);
}
close $fh;
print $endHtml;
sub print_table_header {
my $columns = shift;
print "<tr>\n";
foreach my $column (#$columns) {
my $widthStr = (defined($column->{width}) ? ' width="'.$column->{width}.'"' : '');
my $colName = $column->{name};
print qq{<td$widthStr bgcolor="#00FF00"><font size="2">$colName</font></td>\n};
}
print "</tr>\n";
}
sub print_table_line {
my $fields = shift;
print "<tr>\n";
foreach my $field (#$fields) {
print qq{<td bgcolor=\"#ADD8E6\"><font size="2">$field</font></td>\n};
}
print "</tr>\n";
}
Please close your <font> tags. Just because the browser will handle their lack doesn't mean they're not valuable to include.
This isn't the most robust solution, matter of fact is has some pretty nasty failures if you have commas inside values, but it did the job for me:
(CSV data is in a variable called $content)
$content =~ s#\n#</td></tr><tr><td>#g;
$content =~ s#,#</td><td>#g;
$content = "<table><tr><td>$content</td></tr></table>";