Author: mcbrown
Date: 2008-07-24 12:45:52 +0200 (Thu, 24 Jul 2008)
New Revision: 11343
Log:
Adding in dynamic FAQ support
Added:
trunk/tools/MySQL/DynXML/FAQ.pm
trunk/tools/MySQL/DynXML/FAQParser.pm
Modified:
trunk/tools/MySQL/DynXML/Changelog.pm
trunk/tools/MySQL/DynXMLParse.pm
Modified: trunk/tools/MySQL/DynXML/Changelog.pm
===================================================================
--- trunk/tools/MySQL/DynXML/Changelog.pm 2008-07-24 08:39:02 UTC (rev 11342)
+++ trunk/tools/MySQL/DynXML/Changelog.pm 2008-07-24 10:45:52 UTC (rev 11343)
Changed blocks: 2, Lines Added: 0, Lines Deleted: 2; 579 bytes
@@ -226,7 +226,6 @@
return join('',@lines);
}
-
sub generate_vertitle
{
my ($self,$ver,$options) = @_;
@@ -274,7 +273,6 @@
# print STDERR
Dumper($self->{tdcache}->{$options->{product}}->{versions}->{$ver}),"\n";
-
if (exists($options->{showreldata}) &&
$options->{showreldata} == 1)
{
Added: trunk/tools/MySQL/DynXML/FAQ.pm
===================================================================
--- trunk/tools/MySQL/DynXML/FAQ.pm (rev 0)
+++ trunk/tools/MySQL/DynXML/FAQ.pm 2008-07-24 10:45:52 UTC (rev 11343)
Changed blocks: 1, Lines Added: 229, Lines Deleted: 0; 6678 bytes
@@ -0,0 +1,229 @@
+package MySQL::DynXML::FAQ;
+
+# Load the standard MySQL Libraries
+
+use MySQL;
+
+# Ensure we have enabled error checking
+
+use strict;
+use warnings;
+
+# Load MySQL modules
+
+use MySQL::DynXML::FAQParser;
+
+# Load local modules
+
+use Data::Dumper;
+use IO::String;
+
+sub new
+{
+ my $self = shift;
+ my $class = ref($self) || $self;
+ my $dynxmlcore = shift;
+ my $options = shift;
+
+ return bless {
+ dynxmlcore => $dynxmlcore,
+ options => $options,
+ tdcache => {},
+ versioncache => {},
+ sources => {},
+ dependencyreq => 0,
+ }, $class;
+}
+
+sub force_load_xml
+{
+ my ($self,$product,$options) = @_;
+
+ return($self->load_faq_xml($product,$options));
+}
+
+sub validate
+{
+ my ($self,$options) = @_;
+
+# For faq, the product is the filename, so when validating we can just extract
+# the forward portion
+
+ $options->{product} = $options->{infile};
+ $options->{product} =~ s/\.xml$//g;
+
+ if (!exists($self->{tdcache}->{$options->{product}}))
+ {
+ $self->{tdcache}->{$options->{product}} =
+ $self->load_faq_xml($options->{product},$options);
+ }
+}
+
+sub generate_dependencies
+{
+ my ($self) = @_;
+
+ return('') unless ($self->{dependencyreq});
+
+ my @lines;
+
+ foreach my $file (keys %{$self->{sources}})
+ {
+ push @lines,sprintf('<remark role="dependency" condition="%s"/>',$file);
+ }
+ return(join("\n",@lines));
+}
+
+sub load_faq_xml
+{
+ my ($self,$product,$options) = @_;
+
+ my $sourcedir = $options->{usecustombasedir} || 'faq';
+
+ my $filename = sprintf('%s/%s/%s.xml',
+ $options->{srcdir},
+ $sourcedir,
+ $product);
+ if (!-f $filename)
+ {
+ print STDERR "WARNING: Couldn't load $filename for parsing ($!)\n";
+ return(undef);
+ }
+
+ $self->{sources}->{$filename} = 1;
+
+ my $my_handler = MySQL::DynXML::FAQParser->new();
+
+ XML::Parser::PerlSAX->new->parse(Source => { SystemId => $filename},
+ Handler => $my_handler,
+ );
+
+ # Look for another file and parse it if it exists
+
+ foreach my $counter (1..10)
+ {
+ $filename = sprintf('%s/%s/%s-%d.xml',
+ $options->{srcdir},
+ $sourcedir,
+ $product,
+ $counter);
+
+ if (-f ($filename))
+ {
+ XML::Parser::PerlSAX->new->parse(Source => { SystemId =>
$filename},
+ Handler => $my_handler,
+ );
+ $self->{sources}->{$filename} = 1;
+ }
+ }
+
+ my $returnval = {faqentries => $my_handler->{faqentries},
+ faqentriesbyversion => $my_handler->{faqentriesbyversion},
+ faqentriesbyclass => $my_handler->{faqentriesbyclass},
+ };
+
+ return $returnval;
+}
+
+sub generate
+{
+ my ($self,$options,$item) = @_;
+ $self->{dependencyreq} = 1;
+
+ my ($tableclass) = ($item =~ m/condition="dynamic:(.*?)"/);
+ my ($version,$product,$filter) = ($item =~ m/role="(.*?):(.*?):(.*?)"/);
+
+ if (!exists($self->{tdcache}->{$product}))
+ {
+ $self->{tdcache}->{$product} =
+ $self->load_faq_xml($product,$options);
+ }
+
+ my @md5s = ();
+
+ if (defined($filter) &&
+ $filter ne 'all')
+ {
+ foreach my $md5 (keys
%{$self->{tdcache}->{$product}->{faqentriesbyclass}})
+ {
+ if
(exists($self->{tdcache}->{$product}->{faqentriesbyversion}->{$version}))
+ {
+ print STDERR "Adding a filtered entry for $md5\n";
+ push @md5s,$md5;
+ }
+ }
+ }
+ else
+ {
+ if
(exists($self->{tdcache}->{$product}->{faqentriesbyversion}->{$version}))
+ {
+ push
@md5s,@{$self->{tdcache}->{$product}->{faqentriesbyversion}->{$version}};
+ }
+ }
+
+ if (scalar(@md5s) == 0)
+ {
+ print STDERR ("WARNING: Couldn't find any entries matching version ($version)
and/or filter ($filter)\n");
+ return '';
+ }
+
+ my @sortorder = sort {
$self->{tdcache}->{$product}->{faqentries}->{$a}->{sequence} <=>
+
$self->{tdcache}->{$product}->{faqentries}->{$b}->{sequence} } @md5s;
+
+ my $outfile = IO::String->new();
+
+ print $outfile '<qandaset>';
+
+ foreach my $md5 (@sortorder)
+ {
+
+# If we have an ID, insert it into the qandaentry
+
+ if
(exists($self->{tdcache}->{$product}->{faqentries}->{$md5}->{id})
&&
+
defined($self->{tdcache}->{$product}->{faqentries}->{$md5}->{id}))
+ {
+ printf $outfile ('<qandaentry id="%s-%s-%s">',
+ 'faq',
+ $product,
+
$self->{tdcache}->{$product}->{faqentries}->{$md5}->{id});
+ }
+ else
+ {
+ print $outfile ('<qandaentry>');
+ }
+
+# If we have a version specific entry, output it, otherwise, output the generic one
+
+ if
(exists($self->{tdcache}->{$product}->{faqentries}->{$md5}->{questionbyversion}->{$version})
&&
+
defined($self->{tdcache}->{$product}->{faqentries}->{$md5}->{questionbyversion}->{$version}))
+ {
+ printf $outfile
('<question>%s</question>',$self->{tdcache}->{$product}->{faqentries}->{$md5}->{questionbyversion}->{$version});
+ }
+ else
+ {
+ printf $outfile
('<question>%s</question>',$self->{tdcache}->{$product}->{faqentries}->{$md5}->{question});
+ }
+
+# If we have a version specific entry, output it, otherwise, output the generic one
+
+ if
(exists($self->{tdcache}->{$product}->{faqentries}->{$md5}->{answerbyversion}->{$version})
&&
+
defined($self->{tdcache}->{$product}->{faqentries}->{$md5}->{answerbyversion}->{$version}))
+ {
+ printf $outfile
('<answer>%s</answer>',$self->{tdcache}->{$product}->{faqentries}->{$md5}->{answerbyversion}->{$version});
+ }
+ else
+ {
+ printf $outfile
('<answer>%s</answer>',$self->{tdcache}->{$product}->{faqentries}->{$md5}->{answer});
+ }
+
+ print $outfile '</qandaentry>';
+ }
+
+ print $outfile '</qandaset>';
+
+ $outfile->pos(0);
+ my $string = join('',<$outfile>);
+ return ($string);
+}
+
+1;
Added: trunk/tools/MySQL/DynXML/FAQParser.pm
===================================================================
--- trunk/tools/MySQL/DynXML/FAQParser.pm (rev 0)
+++ trunk/tools/MySQL/DynXML/FAQParser.pm 2008-07-24 10:45:52 UTC (rev 11343)
Changed blocks: 1, Lines Added: 231, Lines Deleted: 0; 6739 bytes
@@ -0,0 +1,231 @@
+package MySQL::DynXML::FAQParser;
+
+# Load the standard MySQL Libraries
+
+use MySQL;
+
+# Ensure we have enabled error checking
+
+use strict;
+use warnings;
+
+# Load local modules
+
+use Digest::MD5 qw(md5_hex);
+use Encode qw(encode_utf8);
+use Data::Dumper;
+
+sub new
+{
+ my $self = shift;
+ my $class = ref($self) || $self;
+
+ return bless {
+ 'faqentriesbyversion' => {},
+ 'faqentriesbyclass' => {},
+ 'faqentries' => {},
+ 'currententry' => {},
+ 'currenttext' => [],
+ 'remapxmldata' => 0,
+ 'savecdata' => 0,
+ 'counter' => 0,
+ 'custom' => {},
+ }, $class;
+}
+
+sub start_element
+{
+ my ($self, $element) = @_;
+
+ if ($element->{Name} eq 'faqentry')
+ {
+ $self->{currententry} = {versions => {},
+ id => undef,
+ sequence => undef,
+ class => undef,
+ subclass => undef,
+ question => {},
+ answer => {},
+ };
+ foreach my $key (qw/id class subclass sequence/)
+ {
+ $self->{currententry}->{$key} = $element->{Attributes}->{$key}
+ if (exists($element->{Attributes}->{$key}) &&
+ defined($element->{Attributes}->{$key}));
+ }
+ }
+
+ if ($element->{Name} eq 'manual')
+ {
+
$self->{currententry}->{versions}->{$element->{Attributes}->{version}} =
1;
+ return;
+ }
+
+ if ($element->{Name} eq 'faqquestion')
+ {
+ $self->{savecdata} = 1;
+ $self->{remapxmldata} = 1;
+ $self->{msgversion} = undef;
+ if (exists($element->{Attributes}->{ver}))
+ {
+ $self->{msgversion} = $element->{Attributes}->{ver};
+ }
+ return;
+ }
+
+ if ($element->{Name} eq 'faqanswer')
+ {
+ $self->{savecdata} = 1;
+ $self->{remapxmldata} = 1;
+ $self->{msgversion} = undef;
+ if (exists($element->{Attributes}->{ver}))
+ {
+ $self->{msgversion} = $element->{Attributes}->{ver};
+ }
+ return;
+ }
+
+ if ($self->{remapxmldata})
+ {
+ push @{$self->{currenttext}},sprintf('<%s',$element->{Name});
+ foreach my $attrib (keys %{$element->{Attributes}})
+ {
+ push @{$self->{currenttext}},sprintf('
%s="%s"',$attrib,$element->{Attributes}->{$attrib});
+ }
+ push @{$self->{currenttext}},'>';
+ }
+}
+
+sub end_element
+{
+ my ($self, $element) = @_;
+
+ if ($element->{Name} eq 'faqentry')
+ {
+ my $md5text = $self->{currententry}->{question} .
$self->{currententry}->{answer} || '';
+
+ foreach my $subver (keys %{$self->{currententry}->{questionbyversion}})
+ {
+ $md5text .= $self->{currententry}->{questionbyversion}->{$subver};
+ }
+
+ foreach my $subver (keys %{$self->{currententry}->{answerbyversion}})
+ {
+ $md5text .= $self->{currententry}->{answerbyversion}->{$subver};
+ }
+
+ $md5text .= join('',keys %{$self->{currententry}->{versions}});
+ $md5text .= $self->{currententry}->{id} || '';
+ $md5text .= $self->{currententry}->{class} || '';
+ $md5text .= $self->{currententry}->{subclass} || '';
+
+ if (length($md5text) == 0)
+ {
+ print STDERR "FATAL: During parsing - no default question/answer or version
specific message\n";
+ print STDERR "Known info:\n",Dumper($self->{currententry}),"\n";
+ exit(1);
+ }
+
+ my $md5 = md5_hex(encode_utf8($md5text));
+ if (exists($self->{faqentries}->{$md5}))
+ {
+ print STDERR "Found another record with the same md5 value - perhaps they
should be merged?\n";
+ print STDERR "Existing record:
",Dumper($self->{logentries}->{$md5}),"\n";
+ print STDERR "New record: ",Dumper($self->{currententry}),"\n";
+ print STDERR "Can't reliably merge these automatically; new entry will
overwrite the old\n";
+ }
+
+ if (!defined($self->{currententry}->{sequence}))
+ {
+ $self->{currententry}->{sequence} = hex(substr($md5,0,7));
+ }
+
+ $self->{faqentries}->{$md5} = $self->{currententry};
+
+ foreach my $version (keys %{$self->{currententry}->{versions}})
+ {
+ push @{$self->{faqentriesbyversion}->{$version}},$md5;
+ }
+
+ my $classtag = undef;
+
+ if (defined($self->{currententry}->{class}))
+ {
+ if (defined($self->{currententry}->{subclass}))
+ {
+ $classtag = sprintf('%s-%s',
+ $self->{currententry}->{class},
+ $self->{currententry}->{subclass});
+ }
+ else
+ {
+ $classtag = $self->{currententry}->{class};
+ }
+ }
+
+ if (defined($classtag))
+ {
+ push @{$self->{faqentriesbyclass}->{$classtag}},$md5;
+ }
+
+ $self->{currententry} = {};
+ }
+
+ if (($element->{Name} eq 'faqquestion') ||
+ ($element->{Name} eq 'faqanswer'))
+ {
+ my $msgtype = $element->{Name};
+ $msgtype =~ s/^faq//g;
+
+ if (exists($self->{msgversion}) && defined($self->{msgversion}))
+ {
+ foreach my $realversion (split(/,/,$self->{msgversion}))
+ {
+
$self->{currententry}->{sprintf('%sbyversion',$msgtype)}->{$realversion} =
join('',@{$self->{currenttext}});
+ }
+ }
+ else
+ {
+ $self->{currententry}->{$msgtype} =
join('',@{$self->{currenttext}});
+ }
+
+ $self->{savecdata} = 0;
+ $self->{remapxmldata} = 0;
+ $self->{currenttext} = [],
+ $self->{msgversion} = undef;
+ return;
+ }
+
+ if ($self->{remapxmldata})
+ {
+ push @{$self->{currenttext}},sprintf('</%s>',$element->{Name});
+ }
+}
+
+
+
+sub characters
+{
+ my ($self, $element) = @_;
+
+ if ($self->{savecdata})
+ {
+ my $rawtext = $element->{Data};
+ $rawtext =~ s/&/&/g;
+ $rawtext =~ s/&([a-z_]);/&$1;/g;
+ $rawtext =~ s/</</g;
+ $rawtext =~ s/>/>/g;
+
+ push @{$self->{currenttext}},$rawtext;
+ }
+}
+
+sub entity_reference
+{
+ my ($self,$element) = @_;
+
+ push @{$self->{currenttext}},sprintf('&%s;',$element->{Name}) if
($self->{savecdata});
+
+}
+
+1;
Modified: trunk/tools/MySQL/DynXMLParse.pm
===================================================================
--- trunk/tools/MySQL/DynXMLParse.pm 2008-07-24 08:39:02 UTC (rev 11342)
+++ trunk/tools/MySQL/DynXMLParse.pm 2008-07-24 10:45:52 UTC (rev 11343)
Changed blocks: 3, Lines Added: 11, Lines Deleted: 0; 1217 bytes
@@ -23,6 +23,7 @@
use MySQL::DynXML::ReservedWords;
use MySQL::DynXML::Changelog;
use MySQL::DynXML::BuildOpts;
+use MySQL::DynXML::FAQ;
# Load the local modules
@@ -46,6 +47,7 @@
changelog => undef,
openbugs => undef,
buildopts => undef,
+ faq => undef,
};
my $dynxml = new MySQL::DynXML($options);
@@ -154,6 +156,15 @@
}
$string = $DynXMLParsers->{changelog}->generate($parser_options,$item);
}
+ elsif ($parser_options->{inserttype} eq 'faq')
+ {
+ if (!exists($DynXMLParsers->{faq}) ||
+ !defined($DynXMLParsers->{faq}))
+ {
+ $DynXMLParsers->{faq} = new
MySQL::DynXML::FAQ($dynxml,$parser_options);
+ }
+ $string = $DynXMLParsers->{faq}->generate($parser_options,$item);
+ }
else
{
print STDERR "$0: WARNING: Dynamic datatype $parser_options->{inserttype}
not recognized\n";
| Thread |
|---|
| • svn commit - mysqldoc@docsrva: r11343 - in trunk/tools/MySQL: . DynXML | mcbrown | 24 Jul |