#
package HTML::WebMake::Metadata;
###########################################################################
use Carp;
use strict;
use HTML::WebMake::Main;
use vars qw{
@ISA %BUILTIN_TYPES $NUM $STR
};
# -------------------------------------------------------------------------
$NUM = 1;
$STR = 2;
%BUILTIN_TYPES = (
'score' => { type => $NUM, default => 50 },
'title' => { type => $STR, default => '(Untitled)' },
'abstract' => { type => $STR, default => '' },
'section' => { type => $STR, default => '' },
'declared' => { type => $NUM, default => 0 },
# some pseudo-metadata types. These are not strictly metadata, but
# they are available through Content::get_metadata().
'url' => { type => $STR, default => '' },
'is_generated' => { type => $NUM, default => 0 },
'mtime' => { type => $NUM, default => 0 },
);
# -------------------------------------------------------------------------
###########################################################################
sub new ($$$$$) {
my $class = shift;
$class = ref($class) || $class;
my ($main) = @_;
my $self = {
'main' => $main,
'metasets' => { },
'metadefaults' => { },
'attrdefaults' => { },
};
bless ($self, $class);
# setup the default set of metadata types
$self->{metasets}->{'def'} = \%BUILTIN_TYPES;
$self;
}
sub dbg { HTML::WebMake::Main::dbg (@_); }
# -------------------------------------------------------------------------
sub get_current_metaset ($)
{
my ($self) = @_;
## CHRIS: FIXME added ->{metaset}, don't know why it's not defined
## when {current_subst} is
if (defined $self->{main}->{current_subst}->{metaset}) {
return $self->{main}->{current_subst}->{metaset};
} elsif (defined $self->{main}->{metaset}) {
return $self->{main}->{metaset};
} else {
return 'def';
}
}
# -------------------------------------------------------------------------
sub get_type ($$)
{
my ($self, $meta) = @_;
croak "no meta defined in get_type" unless defined($meta);
$meta =~ s/::.*$//;
my $set = $self->get_current_metaset();
my $info = $self->{metasets}->{$set}->{$meta};
# default to string type for unknown names of metadata
if (!defined $info) { return $STR; }
return $info->{type};
}
sub get_default_value ($$)
{
my ($self, $meta) = @_;
croak "no meta defined in get_default_value" unless defined($meta);
$meta =~ s/::.*$//;
my $set = $self->get_current_metaset();
my $info = $self->{metasets}->{$set}->{$meta};
if (!defined $info) { return undef; }
return $info->{default};
}
# -------------------------------------------------------------------------
sub convert_to_type ($$$)
{
my ($self, $meta, $val) = @_;
croak "no meta defined in get_type" unless defined($meta);
croak "no val defined in get_type" unless defined($val);
$meta =~ s/::.*$//;
dbg("Metadata->convert_to_type: meta $meta");
my $set = $self->get_current_metaset();
my $info = $self->{metasets}->{$set}->{$meta};
if (!defined $info) { return undef; }
if ($info->{type} == $NUM) {
$val+0; # convert to numeric
} else {
$val;
}
}
# -------------------------------------------------------------------------
sub string_to_sort_sub ($$)
{
my ($self, $sortstring) = @_;
my @substrs = ();
foreach my $item (split (' ', $sortstring)) {
my $aname = '$a';
my $bname = '$b';
# !value means reverse-sort by that value, ie. swap $a and $b.
if ($item =~ s/^!//) { $aname = '$b'; $bname = '$a'; }
my $type = $self->get_type ($item);
if (!defined $type) {
carp "no type defined for metadatum \"$item\"\n";
next;
}
my $cmpstr = '';
if ($type eq $NUM) {
$cmpstr = " <=> ";
} elsif ($type eq $STR) {
$cmpstr = " cmp ";
} else {
die "oops? unknown type $type for $item";
}
push (@substrs , '('. #)
$aname.'->get_metadata(q{'.$item.'})'.$cmpstr.
$bname.'->get_metadata(q{'.$item.'}))');
}
if ($#substrs < 0) {
croak "no usable sort items defined\n";
}
my $substr = 'sub {'.join (' || ', @substrs).'}'; #}
dbg ("string to sort-sub: \"$sortstring\": $substr");
$substr;
}
# -------------------------------------------------------------------------
sub set_metadefault {
my ($self, $name, $value) = @_;
$name = lc $name;
if (defined $value && $value eq '[POP]') {
shift (@{$self->{metadefaults}->{$name}});
} elsif (defined $value) {
if (!defined $self->{metadefaults}->{$name}) {
$self->{metadefaults}->{$name} = [ ];
}
unshift (@{$self->{metadefaults}->{$name}}, $value);
} else {
unshift (@{$self->{metadefaults}->{$name}}, undef);
}
}
# -------------------------------------------------------------------------
sub add_metadefaults {
my ($self, $contobj) = @_;
my ($metaname, $val);
while (($metaname, $val) = each %{$self->{metadefaults}}) {
# dbg ("adding metadefault: \"$metaname\" => \"$val\"");
if (defined $val && defined $val->[0]) {
$contobj->create_extra_metas_if_needed();
$contobj->{extra_metas}->{$metaname} = $val->[0];
}
}
}
# -------------------------------------------------------------------------
sub set_attrdefault {
my ($self, $name, $value) = @_;
$name = lc $name;
if (defined $value && $value eq '[POP]') {
shift (@{$self->{attrdefaults}->{$name}});
} elsif (defined $value) {
if (!defined $self->{attrdefaults}->{$name}) {
$self->{attrdefaults}->{$name} = [ ];
}
unshift (@{$self->{attrdefaults}->{$name}}, $value);
} else {
unshift (@{$self->{attrdefaults}->{$name}}, undef);
}
}
sub get_attrdefault {
my ($self, $name) = @_;
my $ary = $self->{attrdefaults}->{$name};
if (!defined $ary) { return undef; }
$ary->[0];
}
# -------------------------------------------------------------------------
sub parse_metaset {
my ($self, $id, $text, $attrs) = @_;
local ($_);
#
# DC.Title: type=string default="(Untitled)"
#
$self->{metasets}->{$id} = { };
foreach $_ (split (/\n/s, $text)) {
next if /^\s*$/;
if (!/^\s*(\S+):\s+(.*)\s*$/) {
warn "invalid line: $_\n"; next;
}
my $meta = lc $1;
my $attrs = $self->{main}->{util}->parse_xml_tag_attributes
("metaset", $2, "", qw(type default));
my $item;
if ($attrs->{type} eq 'string') {
$item = {
'type' => $STR,
'default' => $attrs->{default},
};
} elsif ($attrs->{type} eq 'numeric') {
$item = {
'type' => $NUM,
'default' => $attrs->{default} + 0,
};
} else {
warn "invalid line, bad type: $_\n"; next;
}
$self->{metasets}->{$id}->{$meta} = $item;
}
}
# -------------------------------------------------------------------------
1;