2015-09-03 00:55:04 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# DOC MODULE
|
|
|
|
####################################################################################################################################
|
2015-10-28 11:10:36 +02:00
|
|
|
package BackRestDoc::Common::Doc;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings FATAL => qw(all);
|
|
|
|
use Carp qw(confess);
|
2016-09-06 15:44:50 +02:00
|
|
|
use English '-no_match_vars';
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2018-12-12 20:48:31 +02:00
|
|
|
use Cwd qw(abs_path);
|
2015-09-03 00:55:04 +02:00
|
|
|
use File::Basename qw(dirname);
|
2015-10-28 11:10:36 +02:00
|
|
|
use Scalar::Util qw(blessed);
|
2016-05-24 01:33:02 +02:00
|
|
|
use XML::Checker::Parser;
|
|
|
|
|
2020-03-10 21:12:44 +02:00
|
|
|
use BackRestDoc::Common::Log;
|
|
|
|
use BackRestDoc::Common::String;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# CONSTRUCTOR
|
|
|
|
####################################################################################################################################
|
|
|
|
sub new
|
|
|
|
{
|
|
|
|
my $class = shift; # Class name
|
|
|
|
|
|
|
|
# Create the class hash
|
|
|
|
my $self = {};
|
|
|
|
bless $self, $class;
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
$self->{strClass} = $class;
|
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
(
|
|
|
|
my $strOperation,
|
2015-11-22 23:44:01 +02:00
|
|
|
$self->{strFileName},
|
2017-08-25 22:47:47 +02:00
|
|
|
my $strSgmlSearchPath,
|
2015-09-03 00:55:04 +02:00
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->new', \@_,
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'strFileName', required => false},
|
2017-08-25 22:47:47 +02:00
|
|
|
{name => 'strSgmlSearchPath', required => false},
|
2015-09-03 00:55:04 +02:00
|
|
|
);
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
# Load the doc from a file if one has been defined
|
|
|
|
if (defined($self->{strFileName}))
|
|
|
|
{
|
2017-06-09 23:51:41 +02:00
|
|
|
my $oParser = XML::Checker::Parser->new(ErrorContext => 2, Style => 'Tree');
|
2018-12-12 20:48:31 +02:00
|
|
|
$oParser->set_sgml_search_path(
|
|
|
|
defined($strSgmlSearchPath) ? $strSgmlSearchPath : dirname(dirname(abs_path($0))) . '/doc/xml/dtd');
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2017-06-09 23:51:41 +02:00
|
|
|
my $oTree;
|
2015-11-22 23:44:01 +02:00
|
|
|
|
2017-06-09 23:51:41 +02:00
|
|
|
eval
|
|
|
|
{
|
|
|
|
local $XML::Checker::FAIL = sub
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
2017-06-09 23:51:41 +02:00
|
|
|
my $iCode = shift;
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2017-06-09 23:51:41 +02:00
|
|
|
die XML::Checker::error_string($iCode, @_);
|
2016-09-06 15:44:50 +02:00
|
|
|
};
|
2015-09-03 00:55:04 +02:00
|
|
|
|
2017-06-09 23:51:41 +02:00
|
|
|
$oTree = $oParser->parsefile($self->{strFileName});
|
|
|
|
|
|
|
|
return true;
|
2015-10-28 11:10:36 +02:00
|
|
|
}
|
2017-06-09 23:51:41 +02:00
|
|
|
# Report any error that stopped parsing
|
|
|
|
or do
|
|
|
|
{
|
|
|
|
my $strException = $EVAL_ERROR;
|
|
|
|
$strException =~ s/at \/.*?$//s; # remove module line number
|
|
|
|
die "malformed xml in '$self->{strFileName}':\n" . trim($strException);
|
|
|
|
};
|
|
|
|
|
|
|
|
# Parse and build the doc
|
|
|
|
$self->{oDoc} = $self->build($self->parse(${$oTree}[0], ${$oTree}[1]));
|
2015-10-28 11:10:36 +02:00
|
|
|
}
|
|
|
|
# Else create a blank doc
|
|
|
|
else
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
$self->{oDoc} = {name => 'doc', children => []};
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
$self->{strName} = 'root';
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'self', value => $self}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# parse
|
|
|
|
#
|
|
|
|
# Parse the xml doc into a more usable hash and array structure.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub parse
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName,
|
|
|
|
$oyNode
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->parse', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'strName', trace => true},
|
|
|
|
{name => 'oyNode', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my %oOut;
|
|
|
|
my $iIndex = 0;
|
2015-11-22 23:44:01 +02:00
|
|
|
my $bText = $strName eq 'text' || $strName eq 'li' || $strName eq 'p' || $strName eq 'title' ||
|
2018-12-30 16:40:20 +02:00
|
|
|
$strName eq 'summary' || $strName eq 'table-cell' || $strName eq 'table-column' || $strName eq 'list-item' ||
|
|
|
|
$strName eq 'admonition';
|
2015-09-03 00:55:04 +02:00
|
|
|
|
|
|
|
# Store the node name
|
|
|
|
$oOut{name} = $strName;
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
if (keys(%{$$oyNode[$iIndex]}))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$oOut{param} = $$oyNode[$iIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
$iIndex++;
|
|
|
|
|
|
|
|
# Look for strings and children
|
|
|
|
while (defined($$oyNode[$iIndex]))
|
|
|
|
{
|
|
|
|
# Process string data
|
|
|
|
if (ref(\$$oyNode[$iIndex]) eq 'SCALAR' && $$oyNode[$iIndex] eq '0')
|
|
|
|
{
|
|
|
|
$iIndex++;
|
|
|
|
my $strBuffer = $$oyNode[$iIndex++];
|
|
|
|
|
|
|
|
# Strip tabs, CRs, and LFs
|
|
|
|
$strBuffer =~ s/\t|\r//g;
|
|
|
|
|
|
|
|
# If anything is left
|
|
|
|
if (length($strBuffer) > 0)
|
|
|
|
{
|
|
|
|
# If text node then create array entries for strings
|
|
|
|
if ($bText)
|
|
|
|
{
|
|
|
|
if (!defined($oOut{children}))
|
|
|
|
{
|
|
|
|
$oOut{children} = [];
|
|
|
|
}
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
push(@{$oOut{children}}, $strBuffer);
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
# Don't allow strings mixed with children
|
|
|
|
elsif (length(trim($strBuffer)) > 0)
|
|
|
|
{
|
|
|
|
if (defined($oOut{children}))
|
|
|
|
{
|
|
|
|
confess "text mixed with children in node ${strName} (spaces count)";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($oOut{value}))
|
|
|
|
{
|
|
|
|
confess "value is already defined in node ${strName} - this shouldn't happen";
|
|
|
|
}
|
|
|
|
|
|
|
|
# Don't allow text mixed with
|
|
|
|
$oOut{value} = $strBuffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# Process a child
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (defined($oOut{value}) && $bText)
|
|
|
|
{
|
|
|
|
confess "text mixed with children in node ${strName} before child " . $$oyNode[$iIndex++] . " (spaces count)";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!defined($oOut{children}))
|
|
|
|
{
|
|
|
|
$oOut{children} = [];
|
|
|
|
}
|
|
|
|
|
2016-05-19 16:25:04 +02:00
|
|
|
push(@{$oOut{children}}, $self->parse($$oyNode[$iIndex++], $$oyNode[$iIndex++]));
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'oDoc', value => \%oOut, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# build
|
|
|
|
#
|
|
|
|
# Restructure the doc to make walking it easier.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub build
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oDoc
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->build', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'oDoc', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
# Initialize the node object
|
2015-10-28 11:10:36 +02:00
|
|
|
my $oOut = {name => $$oDoc{name}, children => [], value => $$oDoc{value}};
|
2015-09-03 00:55:04 +02:00
|
|
|
my $strError = "in node $$oDoc{name}";
|
|
|
|
|
|
|
|
# Get all params
|
|
|
|
if (defined($$oDoc{param}))
|
|
|
|
{
|
2016-05-19 16:25:04 +02:00
|
|
|
for my $strParam (keys %{$$oDoc{param}})
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$$oOut{param}{$strParam} = $$oDoc{param}{$strParam};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
if ($$oDoc{name} eq 'p' || $$oDoc{name} eq 'title' || $$oDoc{name} eq 'summary' ||
|
2018-12-30 16:40:20 +02:00
|
|
|
$$oDoc{name} eq 'table-cell' || $$oDoc{name} eq 'table-column' || $$oDoc{name} eq 'list-item' ||
|
|
|
|
$$oDoc{name} eq 'admonition')
|
2015-10-28 11:10:36 +02:00
|
|
|
{
|
|
|
|
$$oOut{field}{text} = $oDoc;
|
|
|
|
}
|
|
|
|
elsif (defined($$oDoc{children}))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
for (my $iIndex = 0; $iIndex < @{$$oDoc{children}}; $iIndex++)
|
|
|
|
{
|
|
|
|
my $oSub = $$oDoc{children}[$iIndex];
|
|
|
|
my $strName = $$oSub{name};
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
if ($strName eq 'text')
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$$oOut{field}{text} = $oSub;
|
|
|
|
}
|
2016-11-17 23:35:11 +02:00
|
|
|
elsif ((defined($$oSub{value}) && !defined($$oSub{param})) && $strName ne 'code-block')
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$$oOut{field}{$strName} = $$oSub{value};
|
|
|
|
}
|
2015-10-28 11:10:36 +02:00
|
|
|
elsif (!defined($$oSub{children}) && !defined($$oSub{value}) && !defined($$oSub{param}))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
$$oOut{field}{$strName} = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-05-19 16:25:04 +02:00
|
|
|
push(@{$$oOut{children}}, $self->build($oSub));
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'oDoc', value => $oOut, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
2016-05-26 15:20:55 +02:00
|
|
|
# nodeGetById
|
2015-09-03 00:55:04 +02:00
|
|
|
#
|
|
|
|
# Return a node by name - error if more than one exists
|
|
|
|
####################################################################################################################################
|
2015-09-08 13:31:24 +02:00
|
|
|
sub nodeGetById
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName,
|
2015-09-08 13:31:24 +02:00
|
|
|
$strId,
|
2015-09-03 00:55:04 +02:00
|
|
|
$bRequired,
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . 'nodeGetById', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'strName', trace => true},
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'strId', required => false, trace => true},
|
|
|
|
{name => 'bRequired', default => true, trace => true}
|
2015-09-03 00:55:04 +02:00
|
|
|
);
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
my $oDoc = $self->{oDoc};
|
2015-09-03 00:55:04 +02:00
|
|
|
my $oNode;
|
|
|
|
|
|
|
|
for (my $iIndex = 0; $iIndex < @{$$oDoc{children}}; $iIndex++)
|
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
if ((defined($strName) && $$oDoc{children}[$iIndex]{name} eq $strName) &&
|
|
|
|
(!defined($strId) || $$oDoc{children}[$iIndex]{param}{id} eq $strId))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
|
|
|
if (!defined($oNode))
|
|
|
|
{
|
|
|
|
$oNode = $$oDoc{children}[$iIndex];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
confess "found more than one child ${strName} in node $$oDoc{name}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!defined($oNode) && $bRequired)
|
|
|
|
{
|
2015-10-28 11:10:36 +02:00
|
|
|
confess "unable to find child ${strName}" . (defined($strId) ? " (${strId})" : '') . " in node $$oDoc{name}";
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'oNodeDoc', value => $self->nodeBless($oNode), trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# nodeGet
|
|
|
|
#
|
|
|
|
# Return a node by name - error if more than one exists
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
return $self->nodeGetById(shift, undef, shift);
|
|
|
|
}
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# nodeTest
|
|
|
|
#
|
|
|
|
# Test that a node exists
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeTest
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
return defined($self->nodeGetById(shift, undef, false));
|
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# nodeAdd
|
|
|
|
#
|
|
|
|
# Add a node to to the current doc's child list
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeAdd
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $strName = shift;
|
|
|
|
my $strValue = shift;
|
|
|
|
my $oParam = shift;
|
|
|
|
my $oField = shift;
|
|
|
|
|
|
|
|
my $oDoc = $self->{oDoc};
|
|
|
|
my $oNode = {name => $strName, value => $strValue, param => $oParam, field => $oField};
|
|
|
|
|
|
|
|
push(@{$$oDoc{children}}, $oNode);
|
|
|
|
|
|
|
|
return $self->nodeBless($oNode);
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# nodeBless
|
|
|
|
#
|
|
|
|
# Make a new Doc object from a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeBless
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oNode
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->nodeBless', \@_,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'oNode', required => false, trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $oDoc;
|
|
|
|
|
|
|
|
if (defined($oNode))
|
|
|
|
{
|
|
|
|
$oDoc = {};
|
|
|
|
bless $oDoc, $self->{strClass};
|
|
|
|
|
|
|
|
$oDoc->{strClass} = $self->{strClass};
|
|
|
|
$oDoc->{strName} = $$oNode{name};
|
|
|
|
$oDoc->{oDoc} = $oNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'oDoc', value => $oDoc, trace => true}
|
2015-09-03 00:55:04 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# nodeList
|
|
|
|
#
|
|
|
|
# Get a list of nodes.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeList
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName,
|
|
|
|
$bRequired,
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->nodeList', \@_,
|
2015-09-03 00:55:04 +02:00
|
|
|
{name => 'strName', required => false, trace => true},
|
|
|
|
{name => 'bRequired', default => true, trace => true},
|
|
|
|
);
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
my $oDoc = $self->{oDoc};
|
2015-09-03 00:55:04 +02:00
|
|
|
my @oyNode;
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
if (defined($$oDoc{children}))
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
for (my $iIndex = 0; $iIndex < @{$$oDoc{children}}; $iIndex++)
|
2015-09-03 00:55:04 +02:00
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
if (!defined($strName) || $$oDoc{children}[$iIndex]{name} eq $strName)
|
|
|
|
{
|
|
|
|
if (ref(\$$oDoc{children}[$iIndex]) eq "SCALAR")
|
|
|
|
{
|
|
|
|
push(@oyNode, $$oDoc{children}[$iIndex]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
push(@oyNode, $self->nodeBless($$oDoc{children}[$iIndex]));
|
|
|
|
}
|
|
|
|
}
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (@oyNode == 0 && $bRequired)
|
|
|
|
{
|
2015-09-08 13:31:24 +02:00
|
|
|
confess 'unable to find ' . (defined($strName) ? "children named '${strName}'" : 'any children') . " in node $$oDoc{name}";
|
2015-09-03 00:55:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'oyNode', value => \@oyNode, trace => true}
|
2015-09-03 00:55:04 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# nodeRemove
|
|
|
|
#
|
|
|
|
# Remove a child node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeRemove
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oChildRemove
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->nodeRemove', \@_,
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'oChildRemove', required => false, trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $bRemove = false;
|
|
|
|
my $oDoc = $self->{oDoc};
|
|
|
|
|
|
|
|
# Error if there are no children
|
|
|
|
if (!defined($$oDoc{children}))
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "node has no children");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (my $iIndex = 0; $iIndex < @{$$oDoc{children}}; $iIndex++)
|
|
|
|
{
|
|
|
|
if ($$oDoc{children}[$iIndex] == $oChildRemove->{oDoc})
|
|
|
|
{
|
|
|
|
splice(@{$$oDoc{children}}, $iIndex, 1);
|
|
|
|
$bRemove = true;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$bRemove)
|
|
|
|
{
|
2017-02-10 17:22:05 +02:00
|
|
|
confess &log(ERROR, "child was not found in node, could not be removed");
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn($strOperation);
|
|
|
|
}
|
|
|
|
|
2017-02-10 17:22:05 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# nodeReplace
|
|
|
|
#
|
|
|
|
# Replace a child node with one or more child nodes.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nodeReplace
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$oChildRemove,
|
|
|
|
$oyChildReplace,
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
|
|
|
__PACKAGE__ . '->nodeReplace', \@_,
|
|
|
|
{name => 'oChildRemove', trace => true},
|
|
|
|
{name => 'oChildReplace', trace => true},
|
|
|
|
);
|
|
|
|
|
|
|
|
my $bReplace = false;
|
|
|
|
my $iReplaceIdx = undef;
|
|
|
|
my $iReplaceTotal = undef;
|
|
|
|
my $oDoc = $self->{oDoc};
|
|
|
|
|
|
|
|
# Error if there are no children
|
|
|
|
if (!defined($$oDoc{children}))
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "node has no children");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (my $iIndex = 0; $iIndex < @{$$oDoc{children}}; $iIndex++)
|
|
|
|
{
|
|
|
|
if ($$oDoc{children}[$iIndex] == $oChildRemove->{oDoc})
|
|
|
|
{
|
|
|
|
splice(@{$$oDoc{children}}, $iIndex, 1);
|
|
|
|
splice(@{$$oDoc{children}}, $iIndex, 0, @{$oyChildReplace});
|
|
|
|
|
|
|
|
$iReplaceIdx = $iIndex;
|
|
|
|
$iReplaceTotal = scalar(@{$oyChildReplace});
|
|
|
|
$bReplace = true;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$bReplace)
|
|
|
|
{
|
|
|
|
confess &log(ERROR, "child was not found in node, could not be replaced");
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'iReplaceIdx', value => $iReplaceIdx, trace => true},
|
|
|
|
{name => 'iReplaceTotal', value => $iReplaceTotal, trace => true},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# nameGet
|
|
|
|
####################################################################################################################################
|
|
|
|
sub nameGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2016-05-26 15:09:42 +02:00
|
|
|
my $strOperation = logDebugParam(__PACKAGE__ . '->nameGet');
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'strName', value => ${$self->{oDoc}}{name}, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# valueGet
|
|
|
|
####################################################################################################################################
|
|
|
|
sub valueGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2016-05-26 15:09:42 +02:00
|
|
|
my $strOperation = logDebugParam(__PACKAGE__ . '->valueGet');
|
2015-09-08 13:31:24 +02:00
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'strValue', value => ${$self->{oDoc}}{value}, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# valueSet
|
|
|
|
####################################################################################################################################
|
|
|
|
sub valueSet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $strValue = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
2016-05-26 15:09:42 +02:00
|
|
|
my $strOperation = logDebugParam(__PACKAGE__ . '->valueSet');
|
2015-10-28 11:10:36 +02:00
|
|
|
|
|
|
|
# Set the value
|
|
|
|
${$self->{oDoc}}{value} = $strValue;
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn($strOperation);
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# paramGet
|
|
|
|
#
|
|
|
|
# Get a parameter from a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub paramGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName,
|
|
|
|
$bRequired,
|
2015-11-22 23:44:01 +02:00
|
|
|
$strDefault,
|
2015-09-08 13:31:24 +02:00
|
|
|
$strType
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->paramGet', \@_,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'strName', trace => true},
|
|
|
|
{name => 'bRequired', default => true, trace => true},
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'strDefault', required => false, trace => true},
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'strType', default => 'param', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $strValue = ${$self->{oDoc}}{$strType}{$strName};
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
if (!defined($strValue))
|
2015-09-08 13:31:24 +02:00
|
|
|
{
|
2015-11-22 23:44:01 +02:00
|
|
|
if ($bRequired)
|
|
|
|
{
|
2016-05-19 23:10:34 +02:00
|
|
|
confess "${strType} '${strName}' is required in node '$self->{strName}'";
|
2015-11-22 23:44:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$strValue = $strDefault;
|
2015-09-08 13:31:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'strValue', value => $strValue, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# paramTest
|
|
|
|
#
|
|
|
|
# Test that a parameter exists or has a certain value.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub paramTest
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName,
|
|
|
|
$strExpectedValue,
|
|
|
|
$strType
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->paramTest', \@_,
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'strName', trace => true},
|
|
|
|
{name => 'strExpectedValue', required => false, trace => true},
|
|
|
|
{name => 'strType', default => 'param', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $bResult = true;
|
|
|
|
my $strValue = $self->paramGet($strName, false, undef, $strType);
|
|
|
|
|
|
|
|
if (!defined($strValue))
|
|
|
|
{
|
|
|
|
$bResult = false;
|
|
|
|
}
|
|
|
|
elsif (defined($strExpectedValue) && $strValue ne $strExpectedValue)
|
|
|
|
{
|
|
|
|
$bResult = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
return logDebugReturn
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
{name => 'bResult', value => $bResult, trace => true}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# paramSet
|
|
|
|
#
|
|
|
|
# Set a parameter in a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub paramSet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
|
|
my
|
|
|
|
(
|
|
|
|
$strOperation,
|
|
|
|
$strName,
|
|
|
|
$strValue,
|
|
|
|
$strType
|
|
|
|
) =
|
|
|
|
logDebugParam
|
|
|
|
(
|
2016-05-26 15:09:42 +02:00
|
|
|
__PACKAGE__ . '->paramSet', \@_,
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'strName', trace => true},
|
2015-11-22 23:44:01 +02:00
|
|
|
{name => 'strValue', required => false, trace => true},
|
2015-09-08 13:31:24 +02:00
|
|
|
{name => 'strType', default => 'param', trace => true}
|
|
|
|
);
|
|
|
|
|
|
|
|
${$self->{oDoc}}{$strType}{$strName} = $strValue;
|
|
|
|
|
|
|
|
# Return from function and log return values if any
|
|
|
|
logDebugReturn($strOperation);
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# fieldGet
|
|
|
|
#
|
|
|
|
# Get a field from a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub fieldGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
return $self->paramGet(shift, shift, shift, 'field');
|
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# fieldTest
|
|
|
|
#
|
|
|
|
# Test if a field exists.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub fieldTest
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
return $self->paramTest(shift, shift, 'field');
|
2015-09-08 13:31:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
####################################################################################################################################
|
|
|
|
# textGet
|
|
|
|
#
|
|
|
|
# Get a field from a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub textGet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
2015-11-22 23:44:01 +02:00
|
|
|
return $self->nodeBless($self->paramGet('text', shift, shift, 'field'));
|
2015-09-08 13:31:24 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 11:10:36 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# textSet
|
|
|
|
#
|
|
|
|
# Get a field from a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub textSet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
my $oText = shift;
|
|
|
|
|
|
|
|
if (blessed($oText) && $oText->isa('BackRestDoc::Common::Doc'))
|
|
|
|
{
|
|
|
|
$oText = $oText->{oDoc};
|
|
|
|
}
|
|
|
|
elsif (ref($oText) ne 'HASH')
|
|
|
|
{
|
|
|
|
$oText = {name => 'text', children => [$oText]};
|
|
|
|
}
|
|
|
|
|
|
|
|
return $self->paramSet('text', $oText, 'field');
|
|
|
|
}
|
|
|
|
|
2015-09-08 13:31:24 +02:00
|
|
|
####################################################################################################################################
|
|
|
|
# fieldSet
|
|
|
|
#
|
|
|
|
# Set a parameter in a node.
|
|
|
|
####################################################################################################################################
|
|
|
|
sub fieldSet
|
|
|
|
{
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
$self->paramSet(shift, shift, 'field');
|
|
|
|
}
|
|
|
|
|
2015-09-03 00:55:04 +02:00
|
|
|
1;
|