Mercurial > pub > Impl
changeset 223:edf011437be8
updated resources schema
author | sergey |
---|---|
date | Tue, 28 Aug 2012 17:29:42 +0400 |
parents | 84a6382b49c8 |
children | e6c050db7d98 |
files | _test/Resources/resources.xsd _test/Resources/sample.xml _test/temp.pl _test/test_transform.pl |
diffstat | 4 files changed, 245 insertions(+), 72 deletions(-) [+] |
line wrap: on
line diff
--- a/_test/Resources/resources.xsd Mon Aug 27 17:28:32 2012 +0400 +++ b/_test/Resources/resources.xsd Tue Aug 28 17:29:42 2012 +0400 @@ -5,17 +5,18 @@ <element name="resources"> <complexType> <sequence> - <element name="root" type="tns:resourceContract" /> - <element name="typeMap" minOccurs="0"> + <element name="root" type="tns:ResourceContract" /> + <element name="contracts" minOccurs="0"> <complexType> <sequence> <element name="contract" maxOccurs="unbounded"> <complexType> <complexContent> - <extension base="tns:resourceContract"> - <sequence></sequence> - <attribute name="type" type="string" use="required"> - </attribute> + <extension base="tns:ResourceContract"> + <all> + <element name="modelType" type="tns:ClassName" /> + </all> + <attribute name="id" type="string" /> </extension> </complexContent> </complexType> @@ -29,7 +30,7 @@ <element name="locator" maxOccurs="unbounded"> <complexType> <complexContent> - <extension base="tns:resourceLocator"> + <extension base="tns:ResourceLocator"> <attribute name="name" type="string" /> </extension> </complexContent> @@ -51,54 +52,74 @@ </element> <!-- abstract types --> - <complexType name="abstractBinding" abstract="true" /> - <complexType name="abstractTransformation" abstract="true" /> - <complexType name="abstractResult" abstract="true" /> + <complexType name="AbstractBinding" abstract="true" /> + <complexType name="AbstractTransformation" abstract="true" /> + <complexType name="AbstractResult" abstract="true" /> - <complexType name="resourceContract"> + <complexType name="ResourceContract"> <sequence> - <group ref="tns:restOperations"></group> - <element name="resource" maxOccurs="unbounded" minOccurs="0"> - <complexType> - <sequence> - <element name="contract" type="tns:resourceContract" /> - </sequence> - <attribute name="name" type="string" /> - </complexType> - </element> + <group ref="tns:RestOperations" /> + <element name="resource" maxOccurs="unbounded" minOccurs="0" + type="tns:ChildResourceContract" /> </sequence> </complexType> - <group name="restOperations"> + <complexType name="ChildResourceContract"> <sequence> - <element name="get" type="tns:operationContract" minOccurs="0" /> - <element name="post" type="tns:operationContract" minOccurs="0" /> - <element name="put" type="tns:operationContract" minOccurs="0" /> - <element name="delete" type="tns:operationContract" + <choice> + <element name="name" type="string" /> + <element name="match" type="string" /> + </choice> + <element name="model" minOccurs="0" type="tns:MethodBinding" /> + <choice> + <element name="contract"> + <complexType> + <attribute name="ref" type="string" use="required" /> + </complexType> + </element> + <sequence> + <group ref="tns:RestOperations" /> + <element name="resource" type="tns:ChildResourceContract" + minOccurs="0" maxOccurs="unbounded" /> + </sequence> + </choice> + </sequence> + + </complexType> + + <group name="RestOperations"> + <sequence> + <element name="get" type="tns:OperationContract" minOccurs="0" /> + <element name="post" type="tns:OperationContract" minOccurs="0" /> + <element name="put" type="tns:OperationContract" minOccurs="0" /> + <element name="delete" type="tns:OperationContract" minOccurs="0" /> </sequence> </group> - <complexType name="operationContract"> - <sequence> - <element name="bind" type="tns:methodBinding" /> - <element name="parameters" type="tns:transformation" - minOccurs="0" /> - <element name="response" type="tns:abstractResult" minOccurs="0" /> - </sequence> + <complexType name="OperationContract"> + <complexContent> + <extension base="tns:MethodBinding"> + <sequence> + <element name="response" type="tns:AbstractResult" + minOccurs="0" /> + </sequence> + </extension> + </complexContent> </complexType> - <complexType name="methodBinding"> + <complexType name="MethodBinding"> <sequence> - <element name="var" type="tns:bindingVariable" minOccurs="0" + <element name="var" type="tns:BindingVariable" minOccurs="0" maxOccurs="unbounded" /> </sequence> - <attribute name="bind" type="string" use="required" /> + <attribute name="expr" type="string" use="required" /> + <attribute name="handler" type="string" /> </complexType> - <complexType name="bindingVariable"> + <complexType name="BindingVariable"> <complexContent> - <extension base="tns:methodBinding"> + <extension base="tns:MethodBinding"> <attribute name="name" type="string" /> </extension> </complexContent> @@ -109,15 +130,15 @@ <attribute name="class" type="string" /> </complexType> - <complexType name="resourceLocator"> + <complexType name="ResourceLocator"> <sequence> - <element name="var" type="tns:bindingVariable" minOccurs="0" + <element name="var" type="tns:BindingVariable" minOccurs="0" maxOccurs="unbounded" /> <element name="template" type="string" /> </sequence> </complexType> - <simpleType name="redirectCodes"> + <simpleType name="RedirectCodes"> <restriction base="string"> <enumeration value="moved-permanently" /> <enumeration value="temporary-redirect" /> @@ -125,20 +146,26 @@ </restriction> </simpleType> - <complexType name="redirectResponse"> + <complexType name="RedirectResponse"> <complexContent> - <extension base="tns:abstractResult"> + <extension base="tns:AbstractResult"> <choice> - <element name="locator" type="tns:resourceLocator" /> + <element name="locator" type="tns:ResourceLocator" /> <element name="locatorRef"> <complexType> <attribute name="ref" type="string" /> </complexType> </element> - <element name="status" type="tns:redirectCodes" minOccurs="0" /> + <element name="status" type="tns:RedirectCodes" minOccurs="0" /> </choice> </extension> </complexContent> </complexType> + <simpleType name="ClassName"> + <restriction base="string"> + <pattern value="\w+(::\w+)*" /> + </restriction> + </simpleType> + </schema> \ No newline at end of file
--- a/_test/Resources/sample.xml Mon Aug 27 17:28:32 2012 +0400 +++ b/_test/Resources/sample.xml Tue Aug 28 17:29:42 2012 +0400 @@ -3,41 +3,56 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://implab.org/schemas/resources resources.xsd "> <root> - <get> - <bind bind="model" /> - </get> + <get expr="model" /> + + <resource> + <name>projects</name> + <model expr="model"/> + <get expr="model.projects" /> + + <post expr="model.CreateProject(project)"> + <var name="project" expr="BindModel()"/> + <response xsi:type="RedirectResponse"> + <locatorRef ref="projects-locator" /> + </response> + </post> - <resource name="projects"> - <contract> - <get> - <bind bind="parent.model.projects" /> - </get> - <post> - <bind bind="parent.model.CreateProject($form)"> - <var name="form" bind="request"/> - </bind> - <response xsi:type="redirectResponse"> - <locatorRef ref="relative-locator"/> - </response> - </post> - </contract> - - <resource match="(\w+)"> - - </resource> + <resource> + <match>(\w+)</match> + <model expr="model.GetProject(resourceId)"/> + + <get expr="model"/> + <put expr="model.update(data)"> + </put> + + <resource> + <name>library</name> + <model expr="model"/> + <get expr="model"/> + </resource> + <resource> + <name>sources</name> + <model expr="model"/> + <get expr="model"/> + </resource> + </resource> </resource> </root> - <typeMap> - </typeMap> + <contracts> + <contract id="project-contract"> + <modelType>Benzin::Model::Project</modelType> + <get/> + </contract> + </contracts> <locators> <locator name="relative-locator"> - <var name="id" bind="model.id" /> - <var name="parent" bind="parent.location" /> + <var name="id" expr="model.id" /> + <var name="parent" expr="parent.location" /> <template>$parent/$id</template> </locator> <locator name="projects-locator"> - <var name="id" bind="model.id" /> - <var name="projects" bind="application.locate('projects')" /> + <var name="id" expr="model.id" /> + <var name="projects" expr="application.locate('projects')" /> <template>$projects/$id</template> </locator> </locators>
--- a/_test/temp.pl Mon Aug 27 17:28:32 2012 +0400 +++ b/_test/temp.pl Tue Aug 28 17:29:42 2012 +0400 @@ -14,7 +14,7 @@ my $reader = $schema->compile( READER => $type, xsi_type => { - pack_type('http://implab.org/schemas/resources','abstractResult') => 'AUTO' + pack_type('http://implab.org/schemas/resources','AbstractResult') => 'AUTO' } );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/_test/test_transform.pl Tue Aug 28 17:29:42 2012 +0400 @@ -0,0 +1,131 @@ +use strict; +package Person; +use IMPL::lang qw(:declare); +use IMPL::declare { + base => [ + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_' + ] +}; + +BEGIN { + public property name => PROP_ALL; + public property age => PROP_ALL; + public property addresses => PROP_ALL | PROP_LIST; +} + +package Address; +use IMPL::lang qw(:declare); +use IMPL::declare { + base => [ + 'IMPL::Object' => undef, + 'IMPL::Object::Autofill' => '@_' + ] +}; + +BEGIN { + public property country => PROP_ALL; + public property city => PROP_ALL; +} + +package main; + +my $data = { + name => 'Peter', + age => '99', + addresses => { + address => [ + { + country => 'Airot', + city => 'Torhiq', + street => 'avenu1' + }, + { + country => 'Olkson', + city => 'Zoxs', + street => 'av2' + } + ] + } +}; + +use Carp qw(confess); + +sub Rule(&) { + my ($block) = @_; + + return sub { + local $_ = shift; + $block->(); + } +} + +sub Inspect($$) { + my ($path,$block) = @_; + my $data = $_; + + foreach my $name (@$path) { + $data = ref $data ? $data->{$name} : undef; + print "$name = $data\n"; + } + + local $_ = $data; + $block->($data); +} + +sub Required(@); + +sub Required(@) { + if(@_) { + Inspect([@_],Rule { Required }); + } else { + confess "required" unless $_; + } +} + +sub Regexp($) { + my $rx = shift; + die "Regular expression doesn't match" unless m/$rx/; +} + +my $validate = Rule { + Required('name'); + + Inspect ['age'] => Rule { + Regexp(qr/^\d+$/); + die "invalid person age" unless $_ > 0 && $_ < 200; + }; + + Inspect ['addresses', 'address'] => Rule { + Required; + foreach(@{$_}) { + Required('street'); + } + } +}; + +$validate->($data); + +my ($person) = + map { + Person->new( + name => $_->{name}, + age => $_->{age}, + addresses => [ + map { + Address->new( + country => $_->{country}, + city => $_->{city} + ) + } as_list( $_->{addresses}{address} ) + ] + ) + } $data; + +use Data::Dumper; +print Dumper($person); + +sub as_list { + return @{ $_[0] } if ref $_[0] eq 'ARRAY'; + return @_; +}