Frontier-RPC

 view release on metacpan or  search on metacpan

lib/Frontier/RPC2.pm  view on Meta::CPAN

###
### XML::Parser callbacks
###

sub die {
    my $expat = shift; my $message = shift;

    die $message
	. "at line " . $expat->current_line
        . " column " . $expat->current_column . "\n";
}

sub init {
    my $expat = shift;

    $expat->{'rpc_state'} = [];
    $expat->{'rpc_container'} = [ [] ];
    $expat->{'rpc_member_name'} = [];
    $expat->{'rpc_type'} = undef;
    $expat->{'rpc_args'} = undef;
}

# FIXME this state machine wouldn't be necessary if we had a DTD.
sub start {
    my $expat = shift; my $tag = shift;

    my $state = $expat->{'rpc_state'}[-1];

    if (!defined $state) {
	if ($tag eq 'methodCall') {
	    $expat->{'rpc_type'} = 'call';
	    push @{ $expat->{'rpc_state'} }, 'want_method_name';
	} elsif ($tag eq 'methodResponse') {
	    push @{ $expat->{'rpc_state'} }, 'method_response';
	} else {
	    Frontier::RPC2::die($expat, "unknown RPC type \`$tag'\n");
	}
    } elsif ($state eq 'want_method_name') {
	Frontier::RPC2::die($expat, "wanted \`methodName' tag, got \`$tag'\n")
	    if ($tag ne 'methodName');
	push @{ $expat->{'rpc_state'} }, 'method_name';
	$expat->{'rpc_text'} = "";
    } elsif ($state eq 'method_response') {
	if ($tag eq 'params') {
	    $expat->{'rpc_type'} = 'response';
	    push @{ $expat->{'rpc_state'} }, 'params';
	} elsif ($tag eq 'fault') {
	    $expat->{'rpc_type'} = 'fault';
	    push @{ $expat->{'rpc_state'} }, 'want_value';
	}
    } elsif ($state eq 'want_params') {
	Frontier::RPC2::die($expat, "wanted \`params' tag, got \`$tag'\n")
	    if ($tag ne 'params');
	push @{ $expat->{'rpc_state'} }, 'params';
    } elsif ($state eq 'params') {
	Frontier::RPC2::die($expat, "wanted \`param' tag, got \`$tag'\n")
	    if ($tag ne 'param');
	push @{ $expat->{'rpc_state'} }, 'want_param_name_or_value';
    } elsif ($state eq 'want_param_name_or_value') {
	if ($tag eq 'value') {
	    $expat->{'may_get_cdata'} = 1;
	    $expat->{'rpc_text'} = "";
	    push @{ $expat->{'rpc_state'} }, 'value';
	} elsif ($tag eq 'name') {
	    push @{ $expat->{'rpc_state'} }, 'param_name';
	} else {	    
	    Frontier::RPC2::die($expat, "wanted \`value' or \`name' tag, got \`$tag'\n");
	}
    } elsif ($state eq 'param_name') {
	Frontier::RPC2::die($expat, "wanted parameter name data, got tag \`$tag'\n");
    } elsif ($state eq 'want_value') {
	Frontier::RPC2::die($expat, "wanted \`value' tag, got \`$tag'\n")
	    if ($tag ne 'value');
	$expat->{'rpc_text'} = "";
	$expat->{'may_get_cdata'} = 1;
	push @{ $expat->{'rpc_state'} }, 'value';
    } elsif ($state eq 'value') {
	$expat->{'may_get_cdata'} = 0;
	if ($tag eq 'array') {
	    push @{ $expat->{'rpc_container'} }, [];
	    push @{ $expat->{'rpc_state'} }, 'want_data';
	} elsif ($tag eq 'struct') {
	    push @{ $expat->{'rpc_container'} }, {};
	    push @{ $expat->{'rpc_member_name'} }, undef;
	    push @{ $expat->{'rpc_state'} }, 'struct';
	} elsif ($scalars{$tag}) {
	    $expat->{'rpc_text'} = "";
	    push @{ $expat->{'rpc_state'} }, 'cdata';
	} else {
	    Frontier::RPC2::die($expat, "wanted a data type, got \`$tag'\n");
	}
    } elsif ($state eq 'want_data') {
	Frontier::RPC2::die($expat, "wanted \`data', got \`$tag'\n")
	    if ($tag ne 'data');
	push @{ $expat->{'rpc_state'} }, 'array';
    } elsif ($state eq 'array') {
	Frontier::RPC2::die($expat, "wanted \`value' tag, got \`$tag'\n")
	    if ($tag ne 'value');
	$expat->{'rpc_text'} = "";
	$expat->{'may_get_cdata'} = 1;
	push @{ $expat->{'rpc_state'} }, 'value';
    } elsif ($state eq 'struct') {
	Frontier::RPC2::die($expat, "wanted \`member' tag, got \`$tag'\n")
	    if ($tag ne 'member');
	push @{ $expat->{'rpc_state'} }, 'want_member_name';
    } elsif ($state eq 'want_member_name') {
	Frontier::RPC2::die($expat, "wanted \`name' tag, got \`$tag'\n")
	    if ($tag ne 'name');
	push @{ $expat->{'rpc_state'} }, 'member_name';
	$expat->{'rpc_text'} = "";
    } elsif ($state eq 'member_name') {
	Frontier::RPC2::die($expat, "wanted data, got tag \`$tag'\n");
    } elsif ($state eq 'cdata') {
	Frontier::RPC2::die($expat, "wanted data, got tag \`$tag'\n");
    } else {
	Frontier::RPC2::die($expat, "internal error, unknown state \`$state'\n");
    }
}

sub end {
    my $expat = shift; my $tag = shift;

    my $state = pop @{ $expat->{'rpc_state'} };

    if ($state eq 'cdata') {
	my $value = $expat->{'rpc_text'};
	if ($tag eq 'base64') {
	    $value = Frontier::RPC2::Base64->new($value);
	} elsif ($tag eq 'boolean') {
	    $value = Frontier::RPC2::Boolean->new($value);
	} elsif ($tag eq 'dateTime.iso8601') {
	    $value = Frontier::RPC2::DateTime::ISO8601->new($value);
	} elsif ($expat->{'use_objects'}) {
	    if ($tag eq 'i4' or $tag eq 'int') {
		$value = Frontier::RPC2::Integer->new($value);
	    } elsif ($tag eq 'float') {
		$value = Frontier::RPC2::Float->new($value);
	    } elsif ($tag eq 'string') {
		$value = Frontier::RPC2::String->new($value);
	    }
	}
	$expat->{'rpc_value'} = $value;
    } elsif ($state eq 'member_name') {
	$expat->{'rpc_member_name'}[-1] = $expat->{'rpc_text'};
	$expat->{'rpc_state'}[-1] = 'want_value';
    } elsif ($state eq 'method_name') {
	$expat->{'rpc_method_name'} = $expat->{'rpc_text'};
	$expat->{'rpc_state'}[-1] = 'want_params';
    } elsif ($state eq 'struct') {
	$expat->{'rpc_value'} = pop @{ $expat->{'rpc_container'} };
	pop @{ $expat->{'rpc_member_name'} };
    } elsif ($state eq 'array') {
	$expat->{'rpc_value'} = pop @{ $expat->{'rpc_container'} };
    } elsif ($state eq 'value') {
	# the rpc_text is a string if no type tags were given
	if ($expat->{'may_get_cdata'}) {
	    $expat->{'may_get_cdata'} = 0;
	    if ($expat->{'use_objects'}) {
		$expat->{'rpc_value'}
		= Frontier::RPC2::String->new($expat->{'rpc_text'});
	    } else {
		$expat->{'rpc_value'} = $expat->{'rpc_text'};
	    }
	}
	my $container = $expat->{'rpc_container'}[-1];
	if (ref($container) eq 'ARRAY') {
	    push @$container, $expat->{'rpc_value'};
	} elsif (ref($container) eq 'HASH') {
	    $container->{ $expat->{'rpc_member_name'}[-1] } = $expat->{'rpc_value'};
	}
    }
}

sub char {
    my $expat = shift; my $text = shift;

    $expat->{'rpc_text'} .= $text;
}

sub proc {
}

sub final {
    my $expat = shift;

    $expat->{'rpc_value'} = pop @{ $expat->{'rpc_container'} };
    
    return {
	value => $expat->{'rpc_value'},
	type => $expat->{'rpc_type'},
	method_name => $expat->{'rpc_method_name'},
    };
}

package Frontier::RPC2::DataType;

sub new {
    my $type = shift; my $value = shift;

    return bless \$value, $type;
}

# `repr' returns the XML representation of this data, which may be
# different [in the future] from what is returned from `value'
sub repr {
    my $self = shift;

    return $$self;
}

# sets or returns the usable value of this data
sub value {
    my $self = shift;
    @_ ? ($$self = shift) : $$self;
}

package Frontier::RPC2::Base64;



( run in 1.826 second using v1.01-cache-2.11-cpan-df04353d9ac )