Konstantin Baierer avatar Konstantin Baierer committed b00d670

bugs in typeconstraintwalker fixed, rdfexport/import of models, notes

Comments (0)

Files changed (7)

-* Int and Num are subtypes of Str, not Value!
+
+Fri Feb 24 15:10:35 CET 2012
+----------------------------
+* Just found out toby has written a small schema for perl modules
+  (Module::Install::DOAP) - really useful. Could be foundation for solving
+  the inheritance problem, i.e. have MXS RdfImport recognize a special
+  cpanterms:package_name property and instantiating that instead of the
+  base class specified in isa
+
+Fri Feb 24 05:30:07 CET 2012
+----------------------------
+
+Additionally:
+* Detect attributes that contain a model and export the model
+
+On 02/23/2012 07:49 PM, Kjetil Kjernsmo wrote:
+> On Friday 10. February 2012 16.37.34 Kjetil Kjernsmo wrote:
+>> "what would we do with Moose if 
+>> we got to hack on it for a few days with cabal members to help us?"
+Some ideas off the top of my head:
+
+* How to map Moose TypeConstraints to RDF in a generalized way, i.e.
+  * how to handle multiple statements with the same predicate
+  * how to handle type inheritance (e.g. for an attribute that "isa 
+    =>'My::Plugin'" but should be instantiated as My::Plugin::Specialized
+    depending on some additional data
+  * how to handle rdf:List/rdf:Seq/rdf:Bag etc.
+  * mapping to/from MooseX::Type/subtype
+  * Offering hooks to add application-specific behaviour for Moose<->RDF
+    mapping, e.g. using MooseX::Role::Parametrized.
+
+* A separate MooseX::Types distribution with ready-to-use RDF::Trine
+specific types and coercions
+
+* A role that adds a RDF::Trine::Model to any object, along with some
+delegation methods. This can be useful as a general data container, for
+storing obsolete statements, contextual information.
+
+* A utility role or maybe a MooseX::Singleton that encapsulates
+shortcuts for tedious tasks, at least what RDF::Trine exports (iri,
+literal, statement etc.), one or more solutions for Namespaces
+Management and other stuff that RDF::TrineShortcuts et. al. offer.
+
+* Integrate with MooseX::Storage?
+
+* By introspecting a RDF schema, MooseX::Semantic powered classes can in
+theory be created from scratch or MooseX::Semantic attributes "injected"
+into existing Moose classes. While this works, it requires conventions
+how to do it in a general way.
+
+* Tools for extracting the schema out of a set of MooseX::Class and
+validating it.
+
+* Conventions for exporting any Moose class to RDF, something like
+
+@prefix ns1: <urn:moose:My::Plugin#> .
+@prefix moose: <http://moose.perl.org/onto#> .
+ns1:name a moose:Attribute ;
+    moose:isa "Str";
+    moose:default "ANONYMOUS".
+_:inst123 a <urn:moose:My::Plugin> ;
+         ns1:name "John Doe";
+         ns1:age  26.
+
+* Porting Class::OWL to Moose
+
+* Two modules MooseX::Semantic::NonMoose,
+MooseX::Semantic::NonMooseXSemantic] that make it easy to wrap Non-Moose
+or Moose-but-not-MooseX::Semanic classes (a more specialized version of
+MooseX::NonMoose)
+
+* A way to query all objects of one or more Moose classes using SPARQL
+(some metaclass trickery to track all created objects and convert them
+to RDF/query them on the fly)
+
+
+Cheers,
+Konstantin

lib/MooseX/Semantic/Role/RdfExport.pm

                 push (@{$stash->{uris}}, @{$attr->uri_writer}) if $attr->has_uri_writer;
                 return not $stash->{attr_val};
             },
+            model => sub {
+                my ($attr, $stash) = @_;
+                my $iter = $stash->{attr_val}->as_stream;
+                while (my $stmt = $iter->next) {
+                    $model->add_statement($stmt);
+                }
+            },
             literal => sub {
                 my ($attr, $stash) = @_;
                 $self->_export_one_scalar( $model, $stash->{attr_val}, $_, $attr->rdf_lang, $attr->rdf_datatype, $opts{context})
     my $self = shift;
     my ($model,  $single_val, $rel, $context) = @_;
     if (blessed $single_val) {
-        if ($single_val->does('MooseX::Semantic::Role::RdfExport')) {
+        # warn Dumper ref $single_val;
+        if (ref $single_val eq 'RDF::Trine::Node::Resource' ) {
+            $model->add_statement(RDF::Trine::Statement->new(
+                    $self->rdf_about,
+                    $rel,
+                    $single_val,
+                ),
+                $context,
+            );
+        }
+        elsif ($single_val->does('MooseX::Semantic::Role::RdfExport')) {
             #
             # Here's the recursion
             #
             $single_val->export_to_model($model);
             $model->add_statement(RDF::Trine::Statement->new(
-                $self->rdf_about,
-                $rel,
-                $single_val->rdf_about
-            ),
-            $context,
-        );
+                    $self->rdf_about,
+                    $rel,
+                    $single_val->rdf_about
+                ),
+                $context,
+            );
         } else {
             warn "Can't export this object since it doesn't MooseX::Semantic::Role::RdfExport";
         }

lib/MooseX/Semantic/Role/RdfImport.pm

     # warn Dumper [$unfinished_resources->elements];
     # warn Dumper $resource;
     unless ($instance_class) {
-        warn Dumper $model;
-        warn Dumper $cls;
-        warn Dumper $resource;
-        die "DEATH";
+        die "Can't instantiate $resource / $cls. Did you forget to load the type for this attribute TODO?";
+        # warn Dumper $model;
+        # warn Dumper $cls;
+        # warn Dumper $resource;
+        # die "DEATH";
     }
     if (! $instance_class->does('MooseX::Semantic::Role::Resource')) {
         warn "Resource $resource can't be instantiated as $instance_class ($instance_class doesn't MooseX::Semantic::Role::Resource)";

lib/MooseX/Semantic/Test/ModelContainingPerson.pm

+package MooseX::Semantic::Test::ModelContainingPerson;
+use Moose;
+# use MooseX::Semantic::
+
+with qw(
+    MooseX::Semantic::Role::RdfExport
+);
+
+has data_bucket => (
+    traits => ['Semantic'],
+    is => 'rw',
+    isa => 'RDF::Trine::Model',
+    default => sub { RDF::Trine::Model->temporary_model },
+    uri => 'DUMMY'
+);
+
+
+1;

lib/MooseX/Semantic/Types.pm

     TrineBlank
     TrineResource 
     ArrayOfTrineResources
+    HashOfTrineResources
     TrineNode
     ArrayOfTrineNodes
+    HashOfTrineNodes
     TrineLiteral
     TrineBlankOrUndef 
     ArrayOfTrineLiterals
+    HashOfTrineLiterals
     CPAN_URI
     UriStr
     TrineModel
 
 class_type TrineResource, { class => 'RDF::Trine::Node::Resource' };
 subtype ArrayOfTrineResources, as ArrayRef[TrineResource];
+subtype HashOfTrineResources, as HashRef[TrineResource];
 class_type TrineBlank, { class => 'RDF::Trine::Node::Blank' };
 subtype TrineBlankOrUndef, as Maybe[TrineBlank];
 class_type TrineLiteral, { class => 'RDF::Trine::Node::Literal' };
 subtype ArrayOfTrineLiterals, as ArrayRef[TrineLiteral];
+subtype HashOfTrineLiterals, as HashRef[TrineLiteral];
 subtype TrineNode, as Object, where {$_->isa('RDF::Trine::Node::Blank') || $_->isa('RDF::Trine::Node::Resource')};
 subtype ArrayOfTrineNodes, as ArrayRef[TrineNode];
+subtype HashOfTrineNodes, as HashRef[TrineNode];
 subtype UriStr, as Str;
 class_type TrineModel, { class => 'RDF::Trine::Model' };
 class_type TrineStore, { class => 'RDF::Trine::Store' };

lib/MooseX/Semantic/Util/TypeConstraintWalker.pm

     elsif ($type_ref =~ m'^Moose::Meta::(?:Attribute|Class)') {
         $type_constraint = $attr_or_type_constraint->type_constraint;
     }
-    elsif ($type_ref =~ m'^Moose::Meta::TypeConstraint') {
+    elsif ($type_ref =~ m'^(?:Moose::Meta::TypeConstraint|MooseX::Types::TypeDecorator)') {
         $type_constraint = $attr_or_type_constraint;
     }
     else {
 sub _find_parent_type_for_type_constraint {
     my ($self, $type_constraint, $needle, %opts) = @_;
     # warn Dumper $type_constraint->name;
-    # warn Dumper $needle;
+    warn Dumper $needle;
     $opts{max_depth} = 9999 unless defined $opts{max_depth};
     $opts{max_width} = 9999 unless defined $opts{max_width};
     $opts{current_depth} = 0 unless $opts{current_depth};
 sub _walk_attributes{
     my ($self, $cb_opts, $cb_selector) = @_;
     my $cb;
-    for (qw(before literal resource literal_in_array resource_in_array)) { 
+    for (qw(before literal resource literal_in_array resource_in_array model)) { 
         $cb->{$_} = defined $cb_opts->{$_} ? $cb_opts->{$_} : sub {}
     }
     ATTR:
         {
             $callback_name = 'literal';
         }
-        elsif ($self->_find_parent_type($attr->type_constraint, 'Object')
-            || $self->_find_parent_type($attr->type_constraint, 'ClassName'))
+        elsif ($self->_find_parent_type($attr_type, 'Object')
+            || $self->_find_parent_type($attr_type, 'ClassName'))
         {
             $callback_name = 'resource';
+            if ($attr_type =~ /^RDF::Trine::Model/) {
+                $callback_name = 'model';
+            }
         }
         elsif ($self->_find_parent_type($attr->type_constraint, 'ArrayRef')) {
             if ( ! $attr_type->can('type_parameter')
                 $callback_name = 'resource_in_array';
             }
         }
+        else {
+            warn Dumper $attr_type->has_parent;
+            # warn Dumper $attr_type->parent;
+            warn Dumper ref $attr_type;
+            warn Dumper $self->_find_parent_type($attr_type, 'Object');
+            warn "Can't handle this attribute: $attr_name";
+        }
         $cb->{$callback_name}->($attr, $stash, @_);
     }
 }

t/rdf_export/basic.t

 use Test::More tests=>10;
 use Test::Moose;
-use RDF::Trine qw(blank);
+use RDF::Trine qw(blank literal iri statement);
 use Data::Dumper;
 use MooseX::Semantic::Test::Person;
 use File::Temp qw( tempfile );
     print $p->export_to_string(format=>'turtle');
 }
 
+sub model_export {
+    {
+        package My::Model::Person;
+        use Moose;
+        with qw(MooseX::Semantic::Role::RdfExport);
+        has bucket => (
+            traits => ['Semantic'],
+            is => 'rw',
+            isa => 'RDF::Trine::Model',
+            uri => 'http://xmlns.com/foaf/0.1/dataBucket',
+            uri_writer => ['http://myont.org/onto#name'],
+        );
+    }
+    my $dummy_model = RDF::Trine::Model->temporary_model;
+    $dummy_model->add_statement(statement(
+        iri('Someone'),
+        iri('is'),
+        literal('bored'),
+    ));
+    my $p = My::Model::Person->new(
+        rdf_about => 'http://myont.org/data/John',
+        bucket      => $dummy_model
+    );
+    print $p->export_to_string(format=>'turtle');
+}
+
 &basic_export;
 &basic_blank_node;
 &basic_to_turtle;
+&model_export;
 # done_testing;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.