Commits

Toby Inkster committed 2c382b6 Merge

merge from kb

  • Participants
  • Parent commits 6c03bc1, 81c612c

Comments (0)

Files changed (71)

 syntax: glob
 _build
 **/*.swp
+*.swp
+**/*.swo
+*.swo
+**/*.swn
+*.swn
 blib
 Build
+META.*
 MANIFEST.bak
 MYMETA.json
 MYMETA.yml
 MANIFEST.SKIP
 MANIFEST.SKIP.bak
+**/*.sqlite
+t/temp.t
+t/test.pl
+*.tmp
+Makefile.PL
+
+syntax: regexp
+\bMooseX-Semantic-[\d\.\_]+
+MooseX-Semantic*
+cover_db/
+
+
+48acb79065a2b8b061ac4e020f76a0708a499134 v0.003
+198df73d784bd25c7b153d69dae80c4b103e76c9 0.004
+a5894cd9a038c65983a617478b6a06c2a05f2a11 1232
+a5894cd9a038c65983a617478b6a06c2a05f2a11 1232
+0000000000000000000000000000000000000000 1232
+48acb79065a2b8b061ac4e020f76a0708a499134 0.003
+48acb79065a2b8b061ac4e020f76a0708a499134 v0.003
+0000000000000000000000000000000000000000 v0.003
 use Module::Build;
-my $build = Module::Build->new(
+# http://odyniec.net/blog/2011/11/github-friendly-readme-files-with-extutils-makemaker-and-module-build/
+my $class = Module::Build->subclass(
+    class => 'My::Builder',
+    code => q{
+        sub ACTION_docs {
+            use Pod::Readme;
+            use Pod::Select;
+ 
+            my $self = shift;
+ 
+            unlink 'README.pod';
+            unlink 'README';
+            podselect({ -output => 'README.pod' },
+                'lib/MooseX/Semantic.pm');
+ 
+            my $parser = Pod::Readme->new();
+            $parser->parse_from_file('README.pod', 'README');
+            warn "Built README";
+ 
+            return $self->SUPER::ACTION_docs;
+        }
+    }
+);
+my $build = $class->new(
     module_name => 'MooseX::Semantic',
+    license => 'perl',
     dist_abstract => 'Semantic extensions to Moose',
-    dist_author => 'konstantin baierer',
+    dist_author => 'konstantin baierer <kba@cpan.org>',
+    dist_version_from   => 'lib/MooseX/Semantic.pm',
     license     => 'perl',
     requires    => {
         'Moose' => '2.0',
         'RDF::Trine' => '0.136',
         'Data::UUID' => '1.217',
         'Try::Tiny' => '0.09',
+        'File::Path' => 0,
+        'File::Temp' => 0,,
+        'File::Slurp' => '9999.19',
+        'MooseX::Role::Parameterized' => 0,
         'RDF::RDFa::Parser' => '1.096',
+        'Module::Load' => '0.18',
         'namespace::clean' => 0,
         'MooseX::Types' => '0.30',
         'MooseX::Types::URI' => '0.03',
         'MooseX::ClassAttribute' => '0.26',
-        'MooseX::Unique' => '0.005',
-        'LWP::UserAgent' => 0,
+        # 'MooseX::Unique' => '0.005',
         'LWP::UserAgent' => 0,
         'Scalar::Util' => 0,
-        'Set::Object' => 1.28,
+        'Set::Object' => '1.28',
         'URI' => 0,
+        'Data::Printer' => 0,
+        'RDF::NS' => '20111124',
+        'MooseX::HasDefaults' => '0.03',
 
         # 'perl'          => '5.6.1',
         # 'Some::Module'  => '1.23',
         # 'Other::Module' => '>= 1.2, != 1.5, < 2.0',
     },
+    build_requires => {
+        'String::Diff' => 0,
+        'Carp::Always' => 0,
+        'Data::Printer' => 0,
+        'Devel::PartialDump' => 0,
+        'Term::ANSIColor' => 0,
+        'RDF::Endpoint' => '0.04',
+        'SUPER' => 0,
+        'YAML::XS' => 0,
+        'LWP::Protocol::PSGI' => 0,
+        'Pod::Readme' => 0,
+        'Pod::Select' => 0,
+        'RDF::Trine::Serializer::SparqlUpdate' => '0.0002',
+    },
+    configure_requires => {
+        'Pod::Readme' => 0,
+        'Pod::Select' => 0,
+        'Module::Build' => 0.38,
+    },
+    create_makefile_pl => 'traditional',
+    recursive_test_files => 1,
 );
 $build->create_build_script;
+0.004   2012-03-31
+    * fixed some tests
+    * missing requirements
+0.003   2012-03-27
+    * Handling of models as attribute isa
+    * Role for Named Graphs
+    * Convenience Role for Import&Export&RdfType
+    * Basic support for MooseX::Types typedecorators in TypeConstraintWalker
+0.002   2011-12-27
+    * Fix build errors (missing dependencies)
+0.001   2011-12-23
+    * Initial release
 Build.PL
+Changes
 lib/Moose/Meta/Attribute/Custom/Trait/Semantic.pm
 lib/MooseX/Semantic.pm
 lib/MooseX/Semantic/Meta/Attribute/Trait.pm
+lib/MooseX/Semantic/Role/Graph.pm
+lib/MooseX/Semantic/Role/PortableResource.pm
+lib/MooseX/Semantic/Role/RdfBackend.pm
 lib/MooseX/Semantic/Role/RdfExport.pm
 lib/MooseX/Semantic/Role/RdfImport.pm
 lib/MooseX/Semantic/Role/RdfImportAll.pm
+lib/MooseX/Semantic/Role/RdfObsolescence.pm
+lib/MooseX/Semantic/Role/RdfSchemaImport.pm
 lib/MooseX/Semantic/Role/Resource.pm
 lib/MooseX/Semantic/Role/WithRdfType.pm
+lib/MooseX/Semantic/Test.pm
+lib/MooseX/Semantic/Test/BackendPerson.pm
+lib/MooseX/Semantic/Test/MetaPerson.pm
+lib/MooseX/Semantic/Test/ModelContainingPerson.pm
 lib/MooseX/Semantic/Test/Person.pm
 lib/MooseX/Semantic/Test/StrictPerson.pm
 lib/MooseX/Semantic/Types.pm
+lib/MooseX/Semantic/Util/SchemaExport.pm
+lib/MooseX/Semantic/Util/SchemaImport.pm
+lib/MooseX/Semantic/Util/SchemaImport/Attribute.pm
+lib/MooseX/Semantic/Util/SchemaImport/Class.pm
 lib/MooseX/Semantic/Util/TypeConstraintWalker.pm
 lib/MooseX/Semantic/Util/ValueHeuristics.pm
+Makefile.PL
 MANIFEST			This list of files
+META.json
+META.yml
+par-package.sh
+README
+README.pod
+t/closure.t
+t/config/rdf_endpoint.yaml
 t/data/blank_node_01.ttl
 t/data/multiple_persons.ttl
+t/data/ontologies/foaf.rdf
+t/data/ontologies/nfo_data.rdfs
+t/data/person_moose_definition.ttl
 t/data/symmetrical_property.ttl
 t/data/toby_inkster.ttl
+t/rdf_backend/role_rdfbackend.t
+t/rdf_export/basic.t
+t/rdf_export/graph.t
+t/rdf_export/rdf_endpoint.t
+t/rdf_export/to_hash.t
+t/rdf_import/blank_node.t
+t/rdf_import/import_all.t
+t/rdf_import/import_all_from_web.t
+t/rdf_import/import_from_string.t
+t/rdf_import/rdf_import.t
+t/rdf_import/rdf_import_all_synopsis.t
+t/rdf_import/subtyped.t
+t/rdf_resource.t
 t/rdf_type.t
-t/role_rdfexport.t
-t/role_rdfimport.t
-t/role_rdfimport_blank_node.t
-t/role_rdfimportall.t
+t/role_obsolescence.t
 t/role_withrdftype.t
-t/trait.t
-t/types_uri.t
-t/util_walker.t
+t/sparql_serializer.t
+t/temp.t
+t/test.pl
+t/trait_semantic/trait.t
+t/util/coercions.t
+t/util/schema_export.t
+t/util/schema_import/dynamic_class.t
+t/util/schema_import/from_foaf.t
+t/util/schema_import/from_moose_ttl.t
+t/util/util_walker.t
+TODO
+NAME
+    MooseX::Semantic - Adding RDF semantics to the Moose framework
+
+DESCRIPTION
+    MooseX::Semantic is a set of modules that adds a semantic layer to
+    Moose-powered objects. Moose classes that consume the various roles
+    MooseX::Semantic offers are interoperable with the RDF::Trine RDF
+    framework.
+
+DOCUMENTATION OVERVIEW
+    MooseX::Semantic can be used on multiple levels of integration into RDF.
+
+  Basic semantics
+    For basic semantic additions, the following roles are necessary:
+
+    MooseX::Semantic::Meta::Attribute::Trait
+        Add URIs, datatype and language to your attributes, turning them
+        into RDF properties.
+
+    MooseX::Semantic::Role::WithRdfType
+        Adds a class attribute `rdf_type' representing the RDF is-a
+        relationship.
+
+    MooseX::Semantic::Role::Resource
+        Adds an 'rdf_about' attribute to Moose objects turning them into RDF
+        resources.
+
+  From Moose to RDF and back
+    The following classes make round-tripping to/from RDF/Moose possible:
+
+    MooseX::Semantic::Role::RdfExport
+        Role for exporting a Moose object to RDF, including serialization
+        and exporting to SPARQL/U endpoints.
+
+    MooseX::Semantic::Role::RdfImport
+        Creating instances of MooseX::Semantic-flavored Moose classes from
+        RDF data.
+
+    MooseX::Semantic::Role::RdfImportAll
+        Bulk import of multiple RDF resources.
+
+  Persistence
+    These modules make MooseX::Semantic-enabled classes storable in a
+    RDF::Trine::Store and handle statement obsolescence.
+
+    MooseX::Semantic::Role::RdfBackend
+        Assignment a RDF::Trine::Store object to a class, so objects of the
+        class can be stored and re-imported from that store.
+
+    MooseX::Semantic::Role::RdfObsolescence
+        Role that keeps track of changes within an object's set of
+        statements and helps keeping the statements accurate.
+
+  Schema introspection
+    MooseX::Semantic::Util::SchemaExport
+        Extract the schema/ontology that a MooseX::Semantic class
+        represents.
+
+    MooseX::Semantic::Util::SchemaImport
+        Dynamically adding MooseX::Semantic::Meta::Attribute::Trait-enabled
+        attributes to existing classes or creating MooseX::Semantic classes
+        directly from a schema such as FOAF.
+
+  Utility Modules
+    MooseX::Semantic::Types
+        Defines subtypes and coercions for various RDF-related data
+        structures
+
+    MooseX::Semantic::Util::TypeConstraintWalker
+        Convenient way to loop through the attributes of a Moose class with
+        regards to their RDF semantics.
+
+TODO BUGS
+    Documentation is lacking, the tests would be a good starting point right
+    now.
+
+    Context isn't properly handled right now.
+
+    Performance hasn't been considered yet.
+
+    Schema introspection without at least RDFS reasoning can only get you so
+    far.
+
+    Recursive import is buggy.
+
+AUTHOR
+    Konstantin Baierer (<kba@cpan.org>)
+    Toby Inkster (<tobyink@cpan.org>)
+
+SEE ALSO
+    RDF::Trine
+
+LICENSE
+    This module is free software; you can redistribute it and/or modify it
+    under the same terms as Perl itself. See perldoc perlartistic.
+
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+=head1 NAME
+
+MooseX::Semantic - Adding RDF semantics to the Moose framework
+
+=head1 DESCRIPTION
+
+MooseX::Semantic is a set of modules that adds a semantic layer to
+L<Moose|Moose>-powered objects. Moose classes that consume the various roles
+MooseX::Semantic offers are interoperable with the L<RDF::Trine|RDF::Trine> RDF
+framework.
+
+=head1 DOCUMENTATION OVERVIEW
+
+MooseX::Semantic can be used on multiple levels of integration into RDF.
+
+=head2 Basic semantics
+
+For basic semantic additions, the following roles are necessary:
+
+=over 4
+
+=item L<MooseX::Semantic::Meta::Attribute::Trait>
+
+Add URIs, datatype and language to your attributes, turning them into RDF
+properties.
+
+=item L<MooseX::Semantic::Role::WithRdfType>
+
+Adds a class attribute C<rdf_type> representing the RDF is-a relationship.
+
+=item L<MooseX::Semantic::Role::Resource> 
+
+Adds an 'rdf_about' attribute to Moose objects turning them into RDF resources.
+
+=back
+
+=head2 From Moose to RDF and back
+
+The following classes make round-tripping to/from RDF/Moose possible:
+
+=over 4
+
+=item L<MooseX::Semantic::Role::RdfExport>
+
+Role for exporting a Moose object to RDF, including serialization and exporting
+to SPARQL/U endpoints.
+
+=item L<MooseX::Semantic::Role::RdfImport>
+
+Creating instances of MooseX::Semantic-flavored Moose classes from RDF data.
+
+=item L<MooseX::Semantic::Role::RdfImportAll>
+
+Bulk import of multiple RDF resources.
+
+=back
+
+=head2 Persistence
+
+These modules make MooseX::Semantic-enabled classes storable in a
+L<RDF::Trine::Store> and handle statement obsolescence.
+
+=over 4
+
+=item L<MooseX::Semantic::Role::RdfBackend>
+
+Assignment a L<RDF::Trine::Store> object to a class, so objects of the class
+can be stored and re-imported from that store.
+
+=item L<MooseX::Semantic::Role::RdfObsolescence>
+
+Role that keeps track of changes within an object's set of statements and helps
+keeping the statements accurate.
+
+=back
+
+=head2 Schema introspection
+
+=over 4
+
+=item L<MooseX::Semantic::Util::SchemaExport>
+
+Extract the schema/ontology that a MooseX::Semantic class represents.
+
+=item L<MooseX::Semantic::Util::SchemaImport>
+
+Dynamically adding L<MooseX::Semantic::Meta::Attribute::Trait>-enabled
+attributes to existing classes or creating MooseX::Semantic classes directly
+from a schema such as FOAF.
+
+=back
+
+=head2 Utility Modules
+
+=over 4 
+
+=item L<MooseX::Semantic::Types>
+
+Defines subtypes and coercions for various RDF-related data structures
+
+=item L<MooseX::Semantic::Util::TypeConstraintWalker>
+
+Convenient way to loop through the attributes of a Moose class with regards
+to their RDF semantics.
+
+=back
+
+=head1 TODO BUGS
+
+Documentation is lacking, the tests would be a good starting point right now.
+
+Context isn't properly handled right now.
+
+Performance hasn't been considered yet.
+
+Schema introspection without at least RDFS reasoning can only get you so far.
+
+Recursive import is buggy.
+
+=head1 AUTHOR
+
+=over 4
+
+=item Konstantin Baierer (<kba@cpan.org>)
+
+=item Toby Inkster (<tobyink@cpan.org>)
+
+=back
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<RDF::Trine>
+
+=back
+
+=head1 LICENSE
+
+This module is free software; you can redistribute it and/or modify it under
+the same terms as Perl itself. See perldoc perlartistic.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.
-* Int and Num are subtypes of Str, not Value!
+Tue Mar 27 02:57:43 CEST 2012
+-----------------------------
+* A meta-attribute 'inverse' to specify that $self->rdf_about should be the
+  object of a statement, not it's subject.
+* A Moose class for all that is known about $self->rdf_about across named
+  graphs/contexts and with '$self->rdf_about' as subject or object
+
+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/Moose/Meta/Attribute/Custom/Trait/Semantic.pm

 package Moose::Meta::Attribute::Custom::Trait::Semantic;
 use Moose::Role;
 sub register_implementation {'MooseX::Semantic::Meta::Attribute::Trait'};
+
+=head2 NAME
+
+Moose::Meta::Attribute::Custom::Trait::Semantic - Semantic Moose attributes
+
+=head1 DESCRIPTION
+
+See L<MooseX::Semantic::Meta::Attribute::Trait> for documentation.
+
+=cut
+
 1;

lib/MooseX/Semantic.pm

-#=======================================================================
-#         FILE:  Semantic.pm
-#  DESCRIPTION:  
-#       AUTHOR:  Konstantin Baierer (kba), konstantin.baierer@gmail.com
-#      CREATED:  11/22/2011 11:33:47 PM
-#    COPYRIGHT:  Artistic License 2.0
-#=======================================================================
 package MooseX::Semantic;
-# use Moose;
-our $VERSION = '0.001';
-
+BEGIN { $MooseX::Semantic::AUTHORITY = 'cpan:KBA'; }
+BEGIN { $MooseX::Semantic::VERSION = '0.004'; }
 
 1;
+
+# perlpod
+
+=head1 NAME
+
+MooseX::Semantic - Adding RDF semantics to the Moose framework
+
+=head1 DESCRIPTION
+
+MooseX::Semantic is a set of modules that adds a semantic layer to
+L<Moose|Moose>-powered objects. Moose classes that consume the various roles
+MooseX::Semantic offers are interoperable with the L<RDF::Trine|RDF::Trine> RDF
+framework.
+
+=head1 DOCUMENTATION OVERVIEW
+
+MooseX::Semantic can be used on multiple levels of integration into RDF.
+
+=head2 Basic semantics
+
+For basic semantic additions, the following roles are necessary:
+
+=over 4
+
+=item L<MooseX::Semantic::Meta::Attribute::Trait>
+
+Add URIs, datatype and language to your attributes, turning them into RDF
+properties.
+
+=item L<MooseX::Semantic::Role::WithRdfType>
+
+Adds a class attribute C<rdf_type> representing the RDF is-a relationship.
+
+=item L<MooseX::Semantic::Role::Resource> 
+
+Adds an 'rdf_about' attribute to Moose objects turning them into RDF resources.
+
+=back
+
+=head2 From Moose to RDF and back
+
+The following classes make round-tripping to/from RDF/Moose possible:
+
+=over 4
+
+=item L<MooseX::Semantic::Role::RdfExport>
+
+Role for exporting a Moose object to RDF, including serialization and exporting
+to SPARQL/U endpoints.
+
+=item L<MooseX::Semantic::Role::RdfImport>
+
+Creating instances of MooseX::Semantic-flavored Moose classes from RDF data.
+
+=item L<MooseX::Semantic::Role::RdfImportAll>
+
+Bulk import of multiple RDF resources.
+
+=back
+
+=head2 Persistence
+
+These modules make MooseX::Semantic-enabled classes storable in a
+L<RDF::Trine::Store> and handle statement obsolescence.
+
+=over 4
+
+=item L<MooseX::Semantic::Role::RdfBackend>
+
+Assignment a L<RDF::Trine::Store> object to a class, so objects of the class
+can be stored and re-imported from that store.
+
+=item L<MooseX::Semantic::Role::RdfObsolescence>
+
+Role that keeps track of changes within an object's set of statements and helps
+keeping the statements accurate.
+
+=back
+
+=head2 Schema introspection
+
+=over 4
+
+=item L<MooseX::Semantic::Util::SchemaExport>
+
+Extract the schema/ontology that a MooseX::Semantic class represents.
+
+=item L<MooseX::Semantic::Util::SchemaImport>
+
+Dynamically adding L<MooseX::Semantic::Meta::Attribute::Trait>-enabled
+attributes to existing classes or creating MooseX::Semantic classes directly
+from a schema such as FOAF.
+
+=back
+
+=head2 Utility Modules
+
+=over 4 
+
+=item L<MooseX::Semantic::Types>
+
+Defines subtypes and coercions for various RDF-related data structures
+
+=item L<MooseX::Semantic::Util::TypeConstraintWalker>
+
+Convenient way to loop through the attributes of a Moose class with regards
+to their RDF semantics.
+
+=back
+
+=head1 TODO BUGS
+
+Documentation is lacking, the tests would be a good starting point right now.
+
+Context isn't properly handled right now.
+
+Performance hasn't been considered yet.
+
+Schema introspection without at least RDFS reasoning can only get you so far.
+
+Recursive import is buggy.
+
+=head1 AUTHOR
+
+=over 4
+
+=item Konstantin Baierer (<kba@cpan.org>)
+
+=item Toby Inkster (<tobyink@cpan.org>)
+
+=back
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<RDF::Trine>
+
+=back
+
+=head1 LICENSE
+
+This module is free software; you can redistribute it and/or modify it under
+the same terms as Perl itself. See perldoc perlartistic.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE.

lib/MooseX/Semantic/Meta/Attribute/Trait.pm

 package MooseX::Semantic::Meta::Attribute::Trait;
 use Moose::Role;
 use MooseX::Semantic::Types qw(TrineResource ArrayOfTrineResources);
+use Data::Dumper;
+with ( 'MooseX::HasDefaults::Meta::IsRW' );
+=head1 NAME
 
-use Data::Dumper;
+MooseX::Semantic::Meta::Attribute::Trait - Attribute trait for semantic attributes
+
+=head1 SYNOPSIS
+
+    package My::Model::Person;
+    use RDF::Trine::Namespace qw(foaf xsd);
+
+    has name => (
+        traits => ['Semantic'],
+        is => 'rw',
+        isa => 'Str',
+        uri => $foaf->name,
+        rdf_datatype => $xsd->string,
+    );
+
+    has knows => (
+        traits => ['Semantic'],
+        is => 'rw',
+        isa => 'My::Model::Person',
+        uri => $foaf->knows,
+    );
+
+=cut
+
+=head1 DESCRIPTION
+
+Attributes that apply the C<Semantic> trait can be extended using the attributes listed below.
+
+By default, all Semantic attributes are read-write, i.e. C<is => 'rw'>.
+
+=head1 ATTRIBUTES
+
+=cut
+
+=head2 uri
+
+The URI of the property this attribute represents.
+
+=cut
 
 has uri => (
     is => 'rw',
     predicate => 'has_uri',
 );
 
+=head2 uri_reader
+
+Additional URIs for this attribute that are checked when objects of this class
+are imported from RDF using the MooseX::Semantic::Role::RdfImport role.
+
+=cut
+
 has uri_reader => (
     traits => ['Array'],
     is => 'rw',
     }
 );
 
+=head2 uri_writer
+
+Additional URIs for this attribute that generate additional statements when
+this object is converted to RDF.
+
+=cut
+
 has uri_writer => (
     traits => ['Array'],
     is => 'rw',
     }
 );
 
+=head2 rdf_datatype
+
+RDF datatype for this resource. 
+
+Makes sense only when the attribute in question is of a literal type, i.e.
+C<Str>, C<Num> or descendants thereof.
+
+=cut
+
 has rdf_datatype => (
     is => 'rw',
     # XXX Maybe leave this Uri
     predicate => 'has_rdf_datatype',
 );
 
+=head2 rdf_lang
+
+RDF language for this resource. 
+
+Makes sense only when the attribute in question is of a literal type, i.e.
+C<Str>, C<Bool>, C<Num> or descendants thereof.
+
+=cut
+
 has rdf_lang => (
     is => 'rw',
     isa => 'Str',
     predicate => 'has_rdf_lang',
 );
 
+# has rdfs_comment => (
+#     # XXX this might blow up terribly, depending on how attributes are built (inf. recursion)
+#     # XXX indeed it does. should be moved to a 'Semantic::Extended' trait or something
+#     traits => ['Semantic'],
+#     is => 'rw',
+#     isa => 'Str',
+#     predicate => 'has_rdfs_comment',
+# );
+
+=head2 rdf_formatter
+
+CodeRef of a function for coercing the value to a RDF literal. Defaults to the identity function.
+
+=cut
+
+has rdf_formatter => (
+    is => 'rw',
+    isa => 'CodeRef',
+    predicate => 'has_rdf_formatter',
+    # default => sub { sub{ return $_[0] }},
+);
+
+=head2 rdf_parser
+
+CodeRef of a function for parsing the literal value before importing this statement. Defaults to the identity function.
+
+=cut
+
+has rdf_parser => (
+    is => 'rw',
+    isa => 'CodeRef',
+    default => sub {sub{ return $_[0] }},
+);
+
+has 'is' => (
+    is => 'rw',
+    default => 'rw',
+);
+
 1;
+=head1 AUTHOR
+
+Konstantin Baierer (<kba@cpan.org>)
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<MooseX::Semantic|MooseX::Semantic>
+
+=back
+
+=cut
+
+=head1 LICENCE AND COPYRIGHT
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See perldoc perlartistic.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+

lib/MooseX/Semantic/Role/Graph.pm

+package MooseX::Semantic::Role::Graph;
+use Moose::Role;
+use MooseX::Semantic::Types qw(TrineModel TrineLiteral TrineNode TrineResource );
+use RDF::Trine qw(iri literal statement);
+use Data::Dumper;
+
+with qw(
+    MooseX::Semantic::Role::Resource
+);
+
+=head1 NAME
+
+MooseX::Semantic::Role::Graph - Role for Moose objects that represent named graphs
+
+=cut
+
+=head2 
+
+=head2 SYNOPSIS
+
+    package GraphPackage;
+    use Moose;
+    with qw( MooseX::Semantic::Role::Graph MooseX::Semantic::Role::RdfExport );
+    has 'timestamp' => (
+        traits => ['Semantic'],
+        is => 'rw',
+        default => '1234',
+        uri => 'dc:date',
+    );
+    package main;
+    my $g = GraphPackage->new;
+    $g->rdf_graph->add_statement(statement iri('A'), iri('B'), iri('C') );
+
+=cut
+
+=head2 ATTRIBUTES
+
+=head3 rdf_graph
+
+The model this graph represents
+
+=cut
+
+has rdf_graph => (
+    traits => ['Semantic'],
+    is => 'rw',
+    isa => TrineModel,
+    coerce => 1,
+    default => sub { TrineModel->coerce },
+    uri => 'http://moosex-semantic.org/onto#rdf_graph',
+    # lazy => 1,
+    handles => [qw(
+        add_statement
+        get_statements
+    )],
+);
+
+=head2 METHODS
+
+=head3 From RDF::Trine::Model
+
+=over 4
+
+=item add_statement
+
+=item get_statements
+
+=back
+
+=head3 add_statement_smartly
+
+More DWIMmy version of RDF::Trine::Model->add_statmeent
+
+WARNING: Don't use this
+
+=cut
+
+sub add_statement_smartly {
+    my $self = shift;
+    my @args = @_;
+
+    $args[0] = TrineResource->coerce($args[0]);
+    $args[1] = TrineResource->coerce($args[1]);
+    $args[2] = TrineLiteral->coerce($args[2]);
+    return $self->rdf_graph->add_statement(statement(@args));
+}
+
+
+1;

lib/MooseX/Semantic/Role/PortableResource.pm

+package MooseX::Semantic::Role::PortableResource;
+use Moose::Role;
+with qw(
+    MooseX::Semantic::Role::Resource
+    MooseX::Semantic::Role::RdfExport
+    MooseX::Semantic::Role::RdfImport
+    MooseX::Semantic::Role::WithRdfType
+);
+
+1;

lib/MooseX/Semantic/Role/RdfBackend.pm

+package MooseX::Semantic::Role::RdfBackend;
+use  Moose::Role;
+use MooseX::ClassAttribute;
+use MooseX::Semantic::Types qw(ArrayOfTrineResources TrineStore);
+use Data::Dumper;
+# use MooseX::Role::Parameterized;
+
+with (
+    # Class role
+    'MooseX::Semantic::Role::WithRdfType',
+    'MooseX::Semantic::Role::Resource',
+);
+
+
+=head1 NAME
+
+MooseX::Semantic::Role::RdfBackend - Associate a class with a RDF::Trine::Store
+
+=head1 SYNOPSIS
+
+    # My/Model/Person.pm
+    package My::Model::Person;
+    use Moose;
+    with qw(MooseX::Semantic::Role::RdfBackend);
+    __PACKAGE__->rdf_store({
+        storetype => 'DBI',
+        name => 'semantic_moose',
+        dsn => 'dbi:SQLite:dbname=t/data/semantic_moose.sqlite',
+        username => 'FAKE',
+        password => 'FAKE',
+    });
+    ...
+
+    # your script
+    my $p = My::Model::Person->new( rdf_about => 'http://mydomain.org/data/John' );
+    $p->store();
+    my $x = My::Model::Person->new_from_store( 'http://mydomain.org/data/John' );
+    print $x->rdf_about     # prints "<http://mydomain.org/data/John>"
+
+
+=head1 DESCRIPTION
+
+=cut
+
+=head1 CLASS ATTRIBUTES
+
+=head2 rdf_store
+
+Reference to a lazily built RDF::Trine::Store object. Can be instantiated with everything
+that L<RDF::Trine::Store's|RDF::Trine::Store> C<new> method accepts, i.e. a DSN-like string,
+a hash reference of options or a blessed object.
+
+=cut
+
+class_has rdf_store => (
+    is => 'rw',
+    lazy => 1,
+    coerce => 1,
+    isa => TrineStore,
+    default => sub { TrineStore->coerce; }, # XXX is this really what we want by default - a volatile store?
+);
+
+=head1 METHODS
+
+=head2 new_from_store
+
+C<new_from_store( $uri )>
+
+Searches the RDF store for a resource C<$uri> and tries to instantiate an object
+using the C<new_from_model> method of L<MooseX::Semantic::Role::RdfImport>.
+
+=cut
+
+sub new_from_store {
+    my ($cls, $uri) = @_;
+    my $model = RDF::Trine::Model->new( $cls->rdf_store );
+    return $cls->new_from_model( $model, $uri );
+}
+
+=head2 store
+
+Exports an instance to RDF into the model underlying the RDF store.
+
+=cut
+
+sub store {
+    my ($inst) = @_;
+    my $model = RDF::Trine::Model->new( $inst->rdf_store );
+    $inst->export_to_model( $model );
+}
+
+=head1 CONSUMED ROLES
+
+=over 4
+
+=item L<MooseX::Semantic::Role::Resource>
+
+=item L<MooseX::Semantic::Role::WithRdfType>
+
+=item L<MooseX::Semantic::Role::RdfImport>
+
+=item L<MooseX::Semantic::Role::RdfExport>
+
+=back
+
+=cut
+
+1;
+
+=head1 AUTHOR
+
+Konstantin Baierer (<kba@cpan.org>)
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<MooseX::Semantic|MooseX::Semantic>
+
+=item L<RDF::Trine::Store|RDF::Trine::Store>
+
+=back
+
+=cut
+
+=head1 LICENCE AND COPYRIGHT
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See perldoc perlartistic.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+

lib/MooseX/Semantic/Role/RdfExport.pm

 package MooseX::Semantic::Role::RdfExport;
 use Moose::Role;
-use RDF::Trine;
+use RDF::Trine::Serializer::SparqlUpdate;
+use RDF::Trine qw(iri);
+use RDF::Trine::Namespace qw(rdf);
 use LWP::UserAgent;
 use HTTP::Headers;
 use HTTP::Request;
 use Scalar::Util qw(blessed);
-use MooseX::Semantic::Types qw(Uri TrineLiteral);
+use MooseX::Semantic::Types qw(TrineLiteral);
 use Data::Dumper;
 
 with (
     'MooseX::Semantic::Util::TypeConstraintWalker',
 );
 
+=head1 NAME
+
+MooseX::Semantic::Role::RdfExport - Role for exporting Moose objects to RDF
+
+=head1 SYNOPSIS
+
+    package My::Model::Person;
+    use Moose;
+    with qw(MooseX::Semantic::Role::RdfExport);
+    has name => (
+        traits => ['Semantic'],
+        is => 'rw',
+        isa => 'Str',
+        uri => 'http://xmlns.com/foaf/0.1/name',
+        uri_writer => ['http://myont.org/onto#name'],
+    );
+    package main;
+    my $p = My::Model::Person->new(
+        rdf_about => 'http://myont.org/data/John',
+        name      => 'John'
+    );
+    print $p->export_to_string(format=>'turtle');
+    # <http://myont.org/data/John> <http://myont.org/onto#name>     "John"^^<http://www.w3.org/2001/XMLSchema#string> ;
+    #                              <http://xmlns.com/foaf/0.1/name> "John"^^<http://www.w3.org/2001/XMLSchema#string> .
+
+=cut
+
 has _user_agent => (
     is   => 'rw',
     isa  => 'LWP::UserAgent',
     );
 }
 
+=head1 METHODS
+
+=cut
+
+=head2 export_to_model
+
+C<export_to_model($model, %opts)>
+
+Exports the object to RDF in model C<$model>. 
+
+For C<%opts> see L<EXPORT OPTIONS> below.
+
+=cut
+
 sub export_to_model {
     my $self = shift;
-    my ($model) = @_;
+    my ($model, %opts) = @_;
     unless ($model) {
+        # warn "No model supplied, create temporary model";
         $model = RDF::Trine::Model->temporary_model;
     }
 
+    # BUG investigate TODO
+    $opts{context} = $self->rdf_about if ($self->does('MooseX::Semantic::Role::Graph')) ;
+
+    # TODO should be moved to MooseX::Semantic::Role::WithRdfType
     # rdf:type
-    my $RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
-    for my $this_type (@{ $self->rdf_type }) {
-        # warn Dumper $self;
-        # warn Dumper $self->as_trine_node;
-        $model->add_statement(RDF::Trine::Statement->new(
-            $self->as_trine_node,
-            RDF::Trine::Node::Resource->new( $RDF_TYPE ),
-            RDF::Trine::Node::Resource->new( $this_type ),
-        ));
-    }
-    ATTR:
-    for my $attr_name ($self->meta->get_attribute_list) {
-        my $attr = $self->meta->get_attribute($attr_name);
-        my $attr_type = $attr->type_constraint;
-        my $val = $self->$attr_name;
-        next unless ($val);
-        # warn $val;
-        next unless ($attr->does('MooseX::Semantic::Meta::Attribute::Trait'));
-        # XXX if an attribute has no type constraint, just skip it for now. would
-        # need heuristics otherwise, maybe later.
-        next unless ($attr->type_constraint);
-        my @uris_to_export;
-        # TODO what's uri_writer supposed to do? Replace uri or add to it?
-        push (@uris_to_export, $attr->uri) if $attr->has_uri;
-        push (@uris_to_export, @{$attr->uri_writer}) if $attr->has_uri_writer;
-        for my $uri (@uris_to_export) {
-            if ($self->_find_parent_type($attr->type_constraint, 'Value')) {
-                $self->_export_one_scalar($val, $uri, $model, $attr->rdf_lang, $attr->rdf_datatype);
-            }
-            elsif ($self->_find_parent_type($attr->type_constraint, 'Object')) {
-                $self->_export_one_object($val, $uri, $model);
-            }
-            elsif ($self->_find_parent_type($attr->type_constraint, 'ArrayRef')) {
-
-                # XXX TODO if an array isn't constrainted on its elements continue, heuristics needed
-                # next unless $attr->type_constraint->can('type_parameter');
-
-                # my $subtype = $attr->type_constraint->type_parameter;
-                if ( ! $attr_type->can('type_parameter')
-                    || $attr_type->type_parameter eq 'Str'
-                    || $self->_find_parent_type( $attr_type->type_parameter, 'Num' )
-                    || $self->_find_parent_type( $attr_type->type_parameter, 'Bool' ))
-                {
-                    for ( @{$val} ) {
-                        $self->_export_one_scalar( $_, $uri, $model, $attr->rdf_lang, $attr->rdf_datatype );
-                    }
-                }
-                elsif ( $self->_find_parent_type( $attr_type->type_parameter, 'Object' ) 
-                   || $self->_find_parent_type( $attr_type->type_parameter, 'ClassName' ) ) {
-                    for (@{$val}) {
-                        $self->_export_one_object($_, $uri, $model);
-                    }
-                }
-            }
-            else {
-                # TODO
-                warn "Unimplemented for ref " . ref($val);
-                next ATTR;
-            }
+    if ($self->does('MooseX::Semantic::Role::WithRdfType')){
+        for my $this_type (@{ $self->rdf_type }) {
+            $model->add_statement(RDF::Trine::Statement->new(
+                $self->rdf_about,
+                $rdf->type,
+                $this_type,
+            ),
+            $opts{context},
+            );
         }
     }
+    $self->_walk_attributes({
+            before => sub {
+                my ($attr, $stash) = @_;
+                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) {
+                    # warn Dumper $stmt;
+                    if ($self->does('MooseX::Semantic::Role::Graph')) {
+                        $stmt->[3] = $self->rdf_about;
+                    }
+                    $model->add_statement($stmt);
+                }
+            },
+            literal => sub {
+                my ($attr, $stash) = @_;
+                my $val = $stash->{attr_val};
+                if ($attr->has_rdf_formatter) {
+                    $val = $attr->rdf_formatter->( $val );
+                }
+                $self->_export_one_scalar( $model, $val, $_, $attr->rdf_lang, $attr->rdf_datatype, $opts{context})
+                    for (@{ $stash->{uris} });
+            },
+            resource => sub {
+                my ($attr, $stash) = @_;
+                $self->_export_one_object($model, $stash->{attr_val}, $_, $opts{context})
+                    for (@{ $stash->{uris} });
+            },
+            literal_in_array => sub {
+                my ($attr, $stash) = @_;
+                for my $subval ( @{$stash->{attr_val}} ) {
+                    if ($attr->has_rdf_formatter) {
+                        $subval = $attr->rdf_formatter->( $subval );
+                    }
+                    $self->_export_one_scalar($model, $subval, $_, $attr->rdf_lang, $attr->rdf_datatype, $opts{context} )
+                        for (@{ $stash->{uris} });
+                }
+            },
+            resource_in_array => sub {
+                my ($attr, $stash) = @_;
+                for my $subval ( @{$stash->{attr_val}} ) {
+                    $self->_export_one_object($model, $subval, $_, $opts{context})
+                    for (@{ $stash->{uris} });
+                }
+            },
+    });
     return $model;
 }
 
 sub _export_one_object {
-    my ($self, $single_val, $rel, $model) = @_;
+    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->as_trine_node,
-                RDF::Trine::Node::Resource->new($rel),
-                $single_val->as_trine_node
-            ));
+                    $self->rdf_about,
+                    $rel,
+                    $single_val->rdf_about
+                ),
+                $context,
+            );
         } else {
             warn "Can't export this object since it doesn't MooseX::Semantic::Role::RdfExport";
         }
     }
     else {
-        confess 'Trying to export unblessed reference like an object';
+        confess "Trying to export unblessed reference like an object: $single_val";
     }
 }
 sub _export_one_scalar {
-    my ($self, $val, $rel, $model, $lang, $datatype) = @_;
+    my $self = shift;
+    my ($model,  $val, $rel, $lang, $datatype, $context) = @_;
+    # warn Dumper \@_;
     my $lit;
     if ($lang) {
         $lit = RDF::Trine::Node::Literal->new($val, $lang);
         $lit = TrineLiteral->coerce($val);
     }
     $model->add_statement(RDF::Trine::Statement->new(
-        $self->as_trine_node,
-        RDF::Trine::Node::Resource->new($rel),
+        $self->rdf_about,
+        $rel,
         $lit,
-    ));
+    ),
+    $context,
+    );
 }
 
 sub _get_serializer{
     my $self = shift;
     my (%opts) = @_;
-    my $format =  $opts{format} || 'turtle';
+    # warn Dumper keys %opts;
+    my $format =  $opts{format} || 'nquads';
     my $options = $opts{serializer_opts} || {};
     my $serializer = RDF::Trine::Serializer->new($format, %{$options} );
     return $serializer;
 }
 
+=head2 export_to_string
+
+C<export_to_string( %opts )>
+
+For C<%opts>, see L<EXPORT OPTIONS> below.
+
+=cut
+
 sub export_to_string {
     my ($self, %opts) = @_;
-    my $model = $self->export_to_model($opts{model});
-    return $self->_get_serializer(%opts)->serialize_model_to_string($model); 
+    # HACK HACK HACK
+    my $context = $opts{context} || 0;
+    my $model = $self->export_to_model($opts{model}, context => $opts{context});
+    # my $iter = $model->get_statements;
+    # while ($_ = $iter->next) {
+    #     warn Dumper [
+    #         $_->subject->uri,
+    #         $_->predicate->uri,
+    #         $_->object->as_string,
+    #     ];
+    # }
+    my $serializer = $self->_get_serializer(%opts)->serialize_model_to_string($model); 
 }
+
+=head2 export_to_file
+
+TODO
+
+=cut
+
 sub export_to_file {
     my ($self, $fh, %opts) = @_;
     if (! ref $fh) {
         warn "can't open file for ref type " . ref $fh;
         return;
     }
-    my $model = $self->export_to_model($opts{model});
+    my $model = $self->export_to_model($opts{model}, context => $opts{context});
     # TODO prove that data was actually written out to $fh
     # and return undef otherwise
     $self->_get_serializer(%opts)->serialize_model_to_file($fh, $model); 
     return 1;
 }
 
+=head2 export_to_web
+
+TODO
+
+=cut
+
 sub export_to_web {
     my ($self, $method, $uri, %opts) = @_;
     confess "Method must be PUT or POST" unless $method =~ /^(PUT|POST)$/;
     
     ### XXX: It would be handy if there were an application/sparql-update
     ###      serializer for Trine.
+    ### kb Tue Nov 29 03:55:55 CET 2011
+    #   started sparqlu_insert serializer
     my $ser = $self->_get_serializer(%opts);
     my ($type) = $ser->media_types;
     
-    my $req = HTTP::Request->new($method => $uri);
+    my $req = HTTP::Request->new(POST => $uri);
     $req->header(Content_Type => $type);
-    $req->header(From => $opts{http_from}) if exists $opts{http_from};
-    
-    my $model = $self->export_to_model($opts{model});
+    my $model = $self->export_to_model($opts{model}, %opts);
     $req->content( $ser->serialize_model_to_string($model) );
     
     my $res = $self->_user_agent->request($req);
     $res->is_success or
         confess("<%s> HTTP %d Error: %s", $uri, $res->code, $res->message);
+    return $res;
 }
 
+=head2 export_to_hash
+
+TODO
+
+=cut
+
+sub export_to_hash {
+    # warn Dumper [@_];<>;
+    my ($self, %opts) = @_;
+    my $self_hash = {};
+    $opts{max_recursion} //= 0;
+    $opts{hash_key} //= 'Moose';
+    $self_hash->{rdf_about} = $self->rdf_about->uri;
+    $self->_walk_attributes({
+        # skip empty attributes;
+        before => sub {
+            my ($attr, $stash) = @_;
+            push (@{$stash->{uris}}, @{$attr->uri_writer}) if $attr->has_uri_writer;
+            return not $stash->{attr_val};
+        },
+        literal => sub {
+            my ($attr, $stash) = @_;
+            $self->_attr_to_hash( $self_hash, $attr, $stash->{attr_val}, %opts);
+        },
+        model => sub {
+            my ($attr, $stash) = @_;
+            $self_hash->{$attr->name} = $self->{$attr->name}->as_hashref;
+        },
+        resource => sub {
+            my ($attr, $stash) = @_;
+            my $self_hash_value = $self->export_to_hash( $stash->{attr_val}, %opts );
+            $self_hash_value = [ map {$_->export_to_hash(%opts)} @{ $stash->{attr_val} } ];
+        }
+        ,
+        literal_in_array => sub {
+            my ($attr, $stash) = @_;
+            $self->_attr_to_hash( $self_hash, $attr, $stash->{attr_val}, %opts);
+        },
+        resource_in_array => sub {
+            my ($attr, $stash) = @_;
+            my $self_hash_value;
+            if ($opts{max_recursion}-- > 0) {
+                $self_hash_value = [ map {$_->export_to_hash(%opts)} @{ $stash->{attr_val} } ];
+            }
+            else {
+                $self_hash_value = [ map {{rdf_about => $_->rdf_about->uri_value}} @{ $stash->{attr_val} } ];
+            }
+            $self->_attr_to_hash( $self_hash, $attr, $self_hash_value, %opts);
+        },
+    });
+    # # TODO
+    #     if ($opts{hash_key} && $opts{hash_key} eq 'rdf_about') {
+    #     }
+    return $self_hash;
+}
+
+=head2 rdf_serialize
+
+TODO
+
+=cut
+
+sub rdf_serialize {
+    my $self = shift;
+    my $content_type = shift;
+    my %opts = @_;
+    my $temp_model = RDF::Trine::Model->temporary_model;
+    my $content_type_mapping = {
+        'application/json' => sub {$self->export_to_hash(%opts)},
+        'application/rdf+xml' => sub {$self->export_to_string(%opts, model => $temp_model, format=>'rdfxml')},
+    };
+    if (my $coderef = $content_type_mapping->{$content_type}) {
+        return $coderef->();
+    }
+    else {
+        warn "Unknown content type '$content_type'";
+    }
+    return;
+}
+
+=head1 EXPORT OPTIONS
+
+=over 4
+
+=item format
+
+Format string to be passed to L<RDF::Trine::Parser>, e.g. C<turtle> or C<rdfxml>. Defaults to C<nquads>.
+
+=item serializer_opts
+
+Additional options for the L<RDF::Trine::Serializer> to be used.
+
+=item context
+
+
+Optional URI of the named graph this export should be exported into.
+
+
+=back
+
+=cut
+
 
 1;
+=head1 AUTHOR
+
+Konstantin Baierer (<kba@cpan.org>)
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<MooseX::Semantic|MooseX::Semantic>
+
+=back
+
+=cut
+
+=head1 LICENCE AND COPYRIGHT
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See perldoc perlartistic.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+

lib/MooseX/Semantic/Role/RdfImport.pm

 package MooseX::Semantic::Role::RdfImport;
 use Moose::Role;
-use RDF::Trine;
+use RDF::Trine qw(statement);
 use Data::Dumper;
-use MooseX::Semantic::Types qw(TrineResource);
+use MooseX::Semantic::Types qw(TrineResource TrineModel);
 use Set::Object;
 use namespace::autoclean;
+use Log::Log4perl;
+my $logger = Log::Log4perl->get_logger(__PACKAGE__);
 
 with(
     'MooseX::Semantic::Role::Resource',
     'MooseX::Semantic::Util::ValueHeuristics',
 );
 
+=head1 NAME
+
+MooseX::Semantic::Role::RdfImport - Role for classes instantiable from RDF
+
+=head1 SYNOPSIS
+
+    package My::Model::Person;
+    use Moose;
+    with qw(MooseX::Semantic::Role::RdfImport);
+    has name => (
+        traits => ['Semantic'],
+        is => 'rw',
+        isa => 'Str',
+        uri => 'http://xmlns.com/foaf/0.1/name',
+        uri_reader => ['http://myont.org/onto#name'],
+    );
+
+    package main;
+    my $base_uri = 'http://myont.org/data/';
+    my $rdf_in_turtle = '
+        <http://myont.org/data/Lenny> <http://xmlns.com/foaf/0.1/name> "Lenny" .
+        <http://myont.org/data/Carl> <http://myont.org/onto#name> "Carl" .
+    ';
+    my $model = RDF::Trine::Model->temporary_model;
+    RDF::Trine::Parser::Turtle->parse_into_model($base_uri, $rdf_in_turtle, $model);
+    my $lenny = My::Model::Person->new_from_model($model, 'http://myont.org/data/Lenny');
+    my $carl = My::Model::Person->new_from_model($model, 'http://myont.org/data/Carl');
+    print $lenny->name;     # 'Lenny'
+    print $carl->name;      # 'Carl'
+
+=cut 
+
+=head1 METHODS
+
+=cut
+
+
+=head2 new_from_model( $model, $uri )
+
+Creates a new object from resource C<$uri> in C<$model>. 
+
+This loops through all  attributes with trait
+L<MooseX::Semantic::Meta::Attribute::Trait> and searches C<$model> for all
+statements about C<$uri> with the attribute's C<uri> or any of the
+C<uri_reader> attributes as property. For every match, the appropriate key in
+the instantiation hash is set to the value found. 
+
+When the object of a statement represents a resource ... TODO
+
+When all attributes have been walked, the class is instantiated with the
+instantiation hash and the newly-created object is returned.
+
+=cut
 sub new_from_model {
     my ( $cls, $model, $uri, $unfinished_resources ) = @_;
 
     return $resource_obj;
 }
 
+sub new_from_string {
+    my ($cls, $model_string, $uri, %opts) = @_;
+    $opts{format} //= 'nquads';
+    $opts{base_uri} //= 'urn:none:';
+    my $model = RDF::Trine::Model->temporary_model;
+    my $parser = RDF::Trine::Parser->new($opts{format});
+    $parser->parse_into_model($opts{base_uri}, $model_string, $model);
+    return $cls->new_from_model($model, $uri);
+}
+
+=head2 get_instance_hash
+
+Creates a hash of attribute/value pairs that can be passed to $cls->new
+
+=cut
+
+sub get_instance_hash {
+    my ( $cls, $model, $uri, $unfinished_resources ) = @_;
+
+    my $resource = TrineResource->coerce( $uri );
+    $unfinished_resources = Set::Object->new unless $unfinished_resources;
+    $unfinished_resources->insert( $resource );
+    my $inst_hash        = $cls->_build_instance_hash($resource, $model, $unfinished_resources);
+    $inst_hash->{rdf_about} = $resource;
+
+    return $inst_hash;
+}
+
 sub _build_instance_hash {
     my $cls = shift;
     my ($resource, $model, $unfinished_resources) = @_;
+    $resource = TrineResource->coerce( $resource );
 
     # callback for the type hierarchy walking to find
     # the first thing that's a class and a Resource
         my $c = shift;
         $c->can('does') && $c->does('MooseX::Semantic::Role::Resource');
     };
+
     my $inst_hash = {};
-    ATTR_LOOP:
-    for my $attr_name ( $cls->meta->get_attribute_list ) {
-        my $attr      = $cls->meta->get_attribute($attr_name);
-        my $attr_type = $attr->type_constraint;
-        next unless ( $attr->does('MooseX::Semantic::Meta::Attribute::Trait') );
+    $cls->_walk_attributes({
+        before => sub {
+            my ($attr, $stash) = @_;
 
-        my @rels_to_check;
-        push( @rels_to_check, $attr->uri )             if $attr->has_uri;
-        push( @rels_to_check, @{ $attr->uri_reader } ) if $attr->has_uri_reader;
-        next ATTR_LOOP unless @rels_to_check;
+            # add import uris
+            push (@{$stash->{uris}}, @{$attr->uri_reader}) if $attr->has_uri_reader;
 
-        my @values = $model->objects_for_predicate_list($resource, @rels_to_check);
-        my @literal_values = map {$_->literal_value} grep { $_->is_literal } @values;
-        next ATTR_LOOP unless @values;
+            # skip attribute we can't import to (lack of uri)
+            return 1 unless scalar $stash->{uris};
 
-        # Attribute has scalar type
-        if ( $attr_type eq 'Str'
-            || $cls->_find_parent_type( $attr_type, 'Num' )
-            || $cls->_find_parent_type( $attr_type, 'Bool' ))
-        {
-            # XXX Information gets lost here if multiple statements
-            # match a particular scalar attribute. Only the last one
-            # will be set!
-            if ( ! @literal_values) {
-                warn "Scalar attribute but no Literal Rdf nodes.";
-                next ATTR_LOOP;
-            } elsif ( scalar @literal_values > 1 ) {
-                warn "Ignored ". (scalar(@literal_values) - 1) . " values for scalar attribute $attr_name.";
+
+            # warn Dumper $stash->{uris};
+            if ($stash->{uris}->[0] && $stash->{uris}->[0]->as_string eq '<http://moosex-semantic.org/onto#rdf_graph>') {
+                $stash->{statement_iterator} = $model->get_statements(undef,undef,undef,$resource);
             }
-            $inst_hash->{$attr_name} = $literal_values[0];
+            else {
+                # retrieve nodes from model
+                my @nodes = $model->objects_for_predicate_list($resource, @{ $stash->{uris} });
+
+                # skip attribute if no values are to be set
+                return 1 unless scalar @nodes;
+
+                # stash nodes away for other callbacks
+                $stash->{nodes} = \@nodes;
+                $stash->{literal_nodes} = [ map {$_->literal_value} grep { $_->is_literal } @nodes ];
+            }
+
+            # *Don't* skip this attribute
+            return undef;
+        },
+        literal => sub {
+            my ($attr, $stash) = @_;
+            return unless $stash->{literal_nodes}->[0];
+            $inst_hash->{$attr->name} = $stash->{literal_nodes}->[0];
+        },
+        literal_in_array => sub {
+            my ($attr, $stash) = @_;
+            return unless $stash->{literal_nodes}->[0];
+            $inst_hash->{$attr->name} = $stash->{literal_nodes};
+        },
+        model => sub {
+            my ($attr, $stash) = @_;
+
+            # support for MooseX::Semantic::Role::Graph
+            # push (@{$stash->{rdf_graph} = $) if $attr->name eq 'rdf_graph';
+            # warn Dumper $resource;
+            # warn Dumper "I LIVE";
+            my $graph_model = TrineModel->coerce;
+            # while (my $stmt = $model->get_statements(undef,undef,undef)) {
+            # warn Dumper $stash;
+            while (my $stmt = $stash->{statement_iterator}->next){
+                # warn Dumper $stmt;
+                $graph_model->add_statement(statement( $stmt->[0], $stmt->[1], $stmt->[2] ));
+            }
+            # warn Dumper $inst_hash;
+            $inst_hash->{$attr->name} = $graph_model;
+        },
+        resource => sub {
+            my ($attr, $stash) = @_;
+            my $attr_type_cls = $cls->_find_parent_type( $attr, $does_resource );
+            my $recursive_inst_hash = $cls->_instantiate_one_object(
+                $model, $stash->{nodes}->[0], $attr_type_cls, $unfinished_resources
+            );
+            if ($recursive_inst_hash) {
+                $inst_hash->{$attr->name} = $recursive_inst_hash;
+            }
+        },
+        resource_in_array => sub {
+            my ($attr, $stash) = @_;
+            my $subtype_cls = $cls->_find_parent_type( $attr, $does_resource, look_vertically => 1 );
+            $inst_hash->{$attr->name} = [
+                grep { defined $_ }
+                map { $cls->_instantiate_one_object(
+                    $model, $_, $subtype_cls, $unfinished_resources 
+                ) } @{ $stash->{nodes} }
+            ];
         }
 
-        # Attribute is a class name or something subtyped from a class name
-        elsif ( $cls->_find_parent_type( $attr_type, 'Object' )
-                || $cls->_find_parent_type( $attr_type, 'ClassName' )) {
-
-            my $attr_type_cls = $cls->_find_parent_type( $attr_type, $does_resource, undef );
-            my $recursive_inst_hash = $cls->_instantiate_one_object(
-                $model, $values[0], $attr_type_cls, $unfinished_resources
-            );
-            if ($recursive_inst_hash) {
-                $inst_hash->{$attr_name} = $recursive_inst_hash;
-            }
-        }
-
-        # Attribute has arrayref type
-        elsif ( $cls->_find_parent_type( $attr_type, 'ArrayRef' ) ) {
-
-            # initialize empty array
-            $inst_hash->{$attr_name} = [] unless $inst_hash->{$attr_name};
-
-            # if it's either an unparametrized ArrayRef or an ArrayRef[nodeue]
-            # see Moose::Meta::TypeConstraint::Parameterizable
-            # TODO this is a bit shoddy, what if we have something like ArrayRefOfSomethings
-            # which is (one level higher) ArrayRef[Something] and Something->does('...')
-            # should make _find_parent_type more flexible
-            if ( ! $attr_type->can('type_parameter')
-                || $attr_type->type_parameter eq 'Str'
-                || $cls->_find_parent_type( $attr_type->type_parameter, 'Num' )
-                || $cls->_find_parent_type( $attr_type->type_parameter, 'Bool' ))
-            {
-                $inst_hash->{$attr_name} = [@literal_values];
-            }
-            elsif ( $cls->_find_parent_type( $attr_type->type_parameter, 'Object' ) 
-                || $cls->_find_parent_type( $attr_type->type_parameter, 'ClassName' ) ) {
-
-                my $subtype_cls = $cls->_find_parent_type( $attr_type, $does_resource, 1 );
-                $inst_hash->{$attr_name} = [
-                    grep { defined $_ }
-                        map { $cls->_instantiate_one_object(
-                            $model, $_, $subtype_cls, $unfinished_resources 
-                        ) } @values
-                ];
-            }
-        }
-        else {
-            warn "Unimplemented for type " . $attr_type;
-            next ATTR_LOOP;
-        }
-    }
+    });
     return $inst_hash;
 }
 
+=head2 C<new_from_web( $uri )>
+
+Retrieves the remote graph C<$uri> using
+L<RDF::Trine::Parser's|RDF::Trine::Parser> C<parse_url_into_model> method and
+tries to create a new instance from the statements found. 
+
+=cut
+
 sub new_from_web {
     my $cls = shift;
     my ($uri) = @_;
 
-    # my $rdfa = RDF::RDFa::Parser->new_from_url($uri);
-    # my $model = $rdfa->graph;
     my $model = RDF::Trine::Model->temporary_model;
     RDF::Trine::Parser->parse_url_into_model( $uri, $model );
     return $cls->new_from_model( $model, $uri );
 sub _instantiate_one_object {
     my ($cls, $model, $resource, $instance_class, $unfinished_resources) = @_;
     # warn Dumper [$unfinished_resources->elements];
+    # warn Dumper $resource;
+    unless ($instance_class) {
+        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)";
         return;
 }
 
 1;
+=head1 AUTHOR
+
+Konstantin Baierer (<kba@cpan.org>)
+
+=head1 SEE ALSO
+
+=over 4
+
+=item L<MooseX::Semantic|MooseX::Semantic>
+
+=back
+
+=cut
+
+=head1 LICENCE AND COPYRIGHT
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See perldoc perlartistic.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+

lib/MooseX/Semantic/Role/RdfImportAll.pm

 use namespace::autoclean;
 
 use RDF::Trine::Namespace qw/rdf/;
+use MooseX::Semantic::Types qw(ArrayOfTrineResources);
 use Try::Tiny;
 
 use Data::Dumper;
 
 with( 'MooseX::Semantic::Role::RdfImport' );
 
+=head1 NAME
+
+MooseX::Semantic::Role::RdfImportAll - Import all resources from a RDF source
+
+=head1 SYNOPSIS