DS::Target - target of rows.


DSlib documentation Contained in the DSlib distribution.

Index


Code Index:

NAME

Top

DS::Target - target of rows.

DESCRIPTION

Top

This class is the target of rows. It can be bound to any DS::Source, which will send rows to it. Unless you are into writing complicated classes, you will probably never need to inherit directly from this class.

SUPER CLASSES

Top

None.

METHODS

Top

new( $class, $in_type, $source )

Constructor. Instantiates an object of class $class, taking the type $in_type, attached to the source $source. Besides $class, any of the parameters can be left out.

receive_row( $row )

Triggers processing of $row. This method calls process with $row, and then passes the result to pass_row.

attach_source( $source )

Attaches $source as source. This method also validates data types by calling validate_source_type, throwing an exception if the validation fails.

source( $source )

Accessor for source. This method sets the source of this object and triggers type checking.

validate_source_type( $source_type )

Validates source type. If the $source_type is not valid, it returns false, true otherwise. By default, this method ensures that the ingoing type of this object contains no fields not specified in $source_type. Override if you need more complex checking.

in_type( $type )

Accessor for ingoing type.

SEE ALSO

Top

DS::Transformer, DS::Source.

AUTHOR

Top

Written by Michael Zedeler.


DSlib documentation Contained in the DSlib distribution.

#!perl

# ########################################################################## #
# Title:         Data stream sink
# Creation date: 2007-03-05
# Author:        Michael Zedeler
# Description:   Receives data from data stream
# File:          $Source: /data/cvs/lib/DSlib/lib/DS/Target.pm,v $
# Repository:    kronhjorten
# State:         $State: Exp $
# Documentation: inline
# Recepient:     -
# #TODO Sources should not by default be constructed with an explicit typespec, since this may be derived from the data source
# ########################################################################## #

package DS::Target;

use strict;
use Carp qw{ croak cluck confess carp };
use Carp::Assert;

our ($VERSION) = $DS::VERSION;
our ($REVISION) = '$Revision: 1.2 $' =~ /(\d+\.\d+)/;


sub new {
    my( $class, $source_type, $source ) = @_;

    my $self = {};
    bless $self, $class;
    
    if( defined( $source_type ) ) {
        $self->in_type( $source_type );
    }
    
    if( defined( $source ) ) {
        $self->attach_source( $source );
    }
    
    return $self;
}

# Receives row - invoked by source.
sub receive_row {
    confess("This method is abstract. Don't call it. Override it.");
}

sub attach_source {
    my( $self, $source ) = @_;
    
    my $result;
    
    assert( $source, '$source should be defined' );
    assert( $source->isa('DS::Source'), "ref(\$source) = " . ref( $source ) . " != DS::Source" );
    
    # First break link with old source, if any
    if( $self->{source} ) {
        $self->{source}->{target} = undef;
    }
    if( $self->source( $source ) ) {
        $source->target( $self );
        $result = 1;
    }
    return $result;
}

# This is a primarily private method
# Important caveat: this method is just a field accessor method.
# Maintaining consistent links with source is handled by attach_source
sub source {
    my( $self, $source ) = @_;

    my $result;
    if( $source ) {
        assert($source->isa('DS::Source'));
        if( my $source_type = $source->out_type ) {
            if( not $self->validate_source_type( $source_type ) ) {
                my $target_fields = join(", ", keys %{$self->in_type->{fields}});
                my $source_fields = join(", ", keys %{$source_type->{fields}});
                croak("Validation of source ($source with fields $source_fields) for me ($self with fields $target_fields) failed.");
            } #TODO Consider throwing a type incompatibility exception here
        } else {
            cluck("Type checking of stream from $source to $self skipped because source has no outgoing type specification.");
        }
        $self->{source} = $source;
        $result = 1;
    } else {
        $result = $self->{source};
    }
    return $result;        
}

sub validate_source_type {
    my( $self, $source_type ) = @_;
    my $result = 1;
    # We accept if the sender of data are passing more fields to us, than we require
    if( $self->in_type ) {
        $result = $source_type->contains( $self->in_type );
    } else {
        cluck("Type checking of stream to $self skipped because $self has no ingoing type specification.");
    }
    return $result;
}

sub in_type {
    my( $self, $type ) = @_;

    my $result;
    if( defined( $type ) ) {
        assert($type->isa('DS::TypeSpec'));
        $self->{in_type} = $type;
    } else {
        $result = $self->{in_type};
    }
    return $result;        
}

1;

__END__