view lib/IMPL/Web/View/Metadata/ObjectMeta.pm @ 417:3ed0c58e9da3 ref20150831

working on di container, tests
author cin
date Mon, 02 Nov 2015 01:56:53 +0300
parents c6e90e02dd17
children
line wrap: on
line source

package IMPL::Web::View::Metadata::ObjectMeta;
use strict;

use IMPL::lang;
use IMPL::Const qw(:prop :access);
use IMPL::declare {
	require => {
		Exception => 'IMPL::Exception',
		ArgException => '-IMPL::InvalidArgumentException',
		OpException => '-IMPL::InvalidOperationException',
		PropertyInfo => 'IMPL::Class::PropertyInfo',
		AbstractObject => '-IMPL::Object::Abstract'
	},
	base => [
		'IMPL::Web::View::Metadata::BaseMeta' => sub {
			my ($model,$type,$args) = @_;
			$type ||= typeof($model);
			return ($model,$type,$args);
		}
	],
	props => [
		isMultiple => PROP_RO,
		holdingType => PROP_RO
	]
};

use constant {
	Meta => __PACKAGE__
};

sub CTOR {
	my ($this,$model,$type,$args) = @_;
	
	$type = $this->modelType;
	
	$args->{isMultiple} ||= $type && $type eq 'ARRAY';
	
	if ($args) {
		$this->$_($args->{$_}) foreach grep $args->{$_}, qw(isMultiple holdingType);
	}
}

sub PopulateProperties {
	my ($this) = @_;
	
	my %seen;
	my @props;
	
	my $modelType = $this->modelType;  

	if ( isclass($modelType,AbstractObject) ) {
		foreach my $pi (
			$this->modelType->GetMeta(
				PropertyInfo,
				sub { not($seen{$_}++) and $_->access == ACCESS_PUBLIC },
				1
			)
		) {
			my $pv = $this->model && $pi->getter->($this->model);
			my $pt;
			
			my %args = (name => $pi->name);
			if ($pi->isList) {
				$pt = 'ARRAY';
				$args{isMultiple} = 1;
				$args{holdingType} = $pi->type;
			} else {
				$pt = $pi->type;
			}
			
			push @props, Meta->new($pv, $pt, \%args);
		}
	} elsif ( $modelType && $modelType eq 'HASH' ) {
		while ( my ($k,$v) = each %{$this->model || {}} ) {
			push @props, Meta->new($v,undef,{name => $k});
		}
	}
	
	return \@props;
}

sub GetItems {
	my ($this) = @_;
	
	die OpException->new("The operation must be performed on the container")
		unless $this->isMultiple;
		
	my $i = 0;
	
	return [
		map $this->_GetItemMeta($_,$i++), @{$this->model || []}
	];
}

sub GetItem {
	my ($this,$index) = @_;
	
	die OpException->new("The operation must be performed on the container")
		unless $this->isMultiple;
		
	my $item = @{$this->model || []}[$index];
	
	return $this->_GetItemMeta($item,$index);
}

sub _GetItemMeta {
	my ($this,$item,$index) = @_;
	
	return Meta->new(
		$item,
		$this->holdingType,
		{
			name => $index,
			container => $this
		}
	);
}

sub GetMetadataForModel {
	my ($self,$model,$args) = @_;
	
	$args ||= {};
	
	return $self->new(
		$model,
		delete $args->{modelType},
		$args
	)
}

1;

__END__