summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Bread/Board.pm60
-rw-r--r--t/010_container.t102
2 files changed, 158 insertions, 4 deletions
diff --git a/lib/Bread/Board.pm b/lib/Bread/Board.pm
index aba64df..d1d6385 100644
--- a/lib/Bread/Board.pm
+++ b/lib/Bread/Board.pm
@@ -1,9 +1,11 @@
use v6;
+class Bread::Board::Container {...}
class Bread::Board::Dependency {...}
role Bread::Board::Service {
has Str $.name;
+ has Bread::Board::Container $.parent is rw = Bread::Board::Container;
# XXX not sure how to make these optional - specifying the types here
# makes it fail when the parameters aren't passed
@@ -16,10 +18,11 @@ role Bread::Board::Service {
method new (*%params is copy) {
if %params.<dependencies> {
my $deps = {};
- for %params.<dependencies>.keys -> $dep {
- $deps.{$dep} = Bread::Board::Dependency.new(
- service => %params.<dependencies>.{$dep},
- );
+ for %params.<dependencies>.keys -> $name {
+ my $dep = %params.<dependencies>.{$name};
+ $deps.{$name} = $dep.isa(Bread::Board::Dependency)
+ ?? $dep
+ !! Bread::Board::Dependency.new(service => $dep);
}
%params.<dependencies> = $deps;
}
@@ -121,3 +124,52 @@ class Bread::Board::Literal does Bread::Board::Service {
return $.value;
}
}
+
+class Bread::Board::Container {
+ has Str $.name;
+ has Bread::Board::Container $.parent is rw = Bread::Board::Container;
+ # XXX again, as above
+ # has Hash of Bread::Board::Container $.sub_containers = {};
+ # has Hash of Bread::Board::Service $.services = {};
+ has $.sub_containers = {};
+ has $.services = {};
+
+ # XXX again, as above
+ method new (*%params is copy) {
+ if %params.<sub_containers>.isa(Array) {
+ %params.<sub_containers> = %params.<sub_containers>.map(-> $c { $c.name => $c }).hash;
+ }
+ if %params.<services>.isa(Array) {
+ %params.<services> = %params.<services>.map(-> $c { $c.name => $c }).hash;
+ }
+ my $container = callwith(|%params);
+ if %params.<sub_containers>:exists {
+ for %params.<sub_containers>.values -> $c {
+ $c.parent = $container;
+ }
+ }
+ if %params.<services>:exists {
+ for %params.<services>.values -> $c {
+ $c.parent = $container;
+ }
+ }
+ return $container;
+ }
+
+ method add_sub_container (Bread::Board::Container $c) {
+ $.sub_containers.{$c.name} = $c;
+ $c.parent = self;
+ }
+
+ method get_sub_container (Str $name) {
+ return $.sub_containers.{$name};
+ }
+
+ method has_services {
+ return $.services > 0;
+ }
+
+ method get_service (Str $name) {
+ return $.services.{$name};
+ }
+}
diff --git a/t/010_container.t b/t/010_container.t
new file mode 100644
index 0000000..379950a
--- /dev/null
+++ b/t/010_container.t
@@ -0,0 +1,102 @@
+use v6;
+use Test;
+
+use Bread::Board;
+
+sub does_ok(Mu $var, Mu $type, $msg = ("The object does '" ~ $type.perl ~ "'")) {
+ ok($var.does($type), $msg);
+}
+
+class MyApp::Schema {}
+class MyApp::View::TT {}
+
+my $c = Bread::Board::Container.new(name => '/');
+isa_ok($c, Bread::Board::Container);
+
+$c.add_sub_container(
+ Bread::Board::Container.new(
+ name => 'Application',
+ sub_containers => [
+ Bread::Board::Container.new(
+ name => 'Model',
+ services => [
+ Bread::Board::Literal.new(name => 'dsn', value => ''),
+ Bread::Board::ConstructorInjection.new(
+ name => 'schema',
+ class => MyApp::Schema,
+ dependencies => {
+ dsn => Bread::Board::Dependency.new(
+ service_path => '../dsn',
+ ),
+ user => Bread::Board::Literal.new(
+ name => 'user',
+ value => '',
+ ),
+ pass => Bread::Board::Literal.new(
+ name => 'pass',
+ value => '',
+ ),
+ },
+ ),
+ ],
+ ),
+ Bread::Board::Container.new(
+ name => 'View',
+ services => [
+ Bread::Board::ConstructorInjection.new(
+ name => 'TT',
+ class => MyApp::View::TT,
+ dependencies => {
+ tt_include_path => Bread::Board::Literal.new(
+ name => 'include_path',
+ value => [],
+ ),
+ },
+ ),
+ ],
+ ),
+ Bread::Board::Container.new(
+ name => 'Controller',
+ ),
+ ],
+ ),
+);
+
+my $app = $c.get_sub_container('Application');
+isa_ok($app, Bread::Board::Container);
+
+is($app.name, 'Application');
+
+{
+ my $controller = $app.get_sub_container('Controller');
+ isa_ok($controller, Bread::Board::Container);
+ is($controller.name, 'Controller');
+ is($controller.parent, $app);
+ ok(!$controller.has_services);
+}
+
+{
+ my $view = $app.get_sub_container('View');
+ isa_ok($view, Bread::Board::Container);
+ is($view.name, 'View');
+ is($view.parent, $app);
+ ok($view.has_services);
+
+ my $service = $view.get_service('TT');
+ does_ok($service, Bread::Board::Service);
+ is($service.parent, $view);
+}
+
+{
+ my $model = $app.get_sub_container('Model');
+ isa_ok($model, Bread::Board::Container);
+ is($model.name, 'Model');
+ is($model.parent, $app);
+ ok($model.has_services);
+
+ my $service = $model.get_service('schema');
+ does_ok($service, Bread::Board::Service);
+ is($service.parent, $model);
+}
+
+done;