From 43804e57a16f7474e288b8b37c08186bf1383fe1 Mon Sep 17 00:00:00 2001 From: Gabriel Omar Cotelli Date: Wed, 31 Oct 2018 16:56:43 -0300 Subject: [PATCH 1/6] Improved context and test --- .../PetsRESTfulWebServiceSpecification.class.st | 2 +- source/Stargate-Model/HttpRequestContext.class.st | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st b/source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st index 38476de..02c582b 100644 --- a/source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st +++ b/source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st @@ -85,7 +85,7 @@ PetsRESTfulWebServiceSpecification >> getPetRoute [ { #category : #routes } PetsRESTfulWebServiceSpecification >> getPetsRoute [ - ^ RouteSpecification handling: #GET at: '/pets' evaluating: [ :service :httpRequest :context | service getPetsBasedOn: httpRequest within: context ] + ^ RouteSpecification handling: #GET at: self endpoint evaluating: [ :service :httpRequest :context | service getPetsBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } diff --git a/source/Stargate-Model/HttpRequestContext.class.st b/source/Stargate-Model/HttpRequestContext.class.st index 7f75d15..2fb29e9 100644 --- a/source/Stargate-Model/HttpRequestContext.class.st +++ b/source/Stargate-Model/HttpRequestContext.class.st @@ -64,6 +64,12 @@ HttpRequestContext >> initialize [ knownObjects := IdentityDictionary new ] +{ #category : #accessing } +HttpRequestContext >> objectUnder: aConcept [ + + ^ self objectUnder: aConcept ifNone: [ NotFound signal: ('Missing <1s> in the request context' expandMacrosWith: aConcept asString) ] +] + { #category : #accessing } HttpRequestContext >> objectUnder: aConcept ifNone: aBlock [ From abb33b507de3756636546d58deef0873f3c2ba97 Mon Sep 17 00:00:00 2001 From: Gabriel Omar Cotelli Date: Fri, 2 Nov 2018 18:07:54 -0300 Subject: [PATCH 2/6] Made pagination optional Made hypermedia controls optional --- .../PetOrdersRESTfulWebService.class.st | 12 ++++ .../PetsRESTfulWebService.class.st | 12 ++++ .../HypermediaDrivenResourcePolicy.class.st | 33 ++++++++++ .../Stargate-Model/HypermediaPolicy.class.st | 17 +++++ .../NoHypermediaResourcePolicy.class.st | 13 ++++ source/Stargate-Model/PaginationSpec.class.st | 2 +- .../Stargate-Model/RESTfulWebService.class.st | 62 +++++++++---------- .../ResourceIsPaginatedPolicy.class.st | 54 ++++++++++++++++ .../ResourceNotPaginatedPolicy.class.st | 36 +++++++++++ .../ResourcePaginationPolicy.class.st | 23 +++++++ 10 files changed, 232 insertions(+), 32 deletions(-) create mode 100644 source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st create mode 100644 source/Stargate-Model/HypermediaPolicy.class.st create mode 100644 source/Stargate-Model/NoHypermediaResourcePolicy.class.st create mode 100644 source/Stargate-Model/ResourceIsPaginatedPolicy.class.st create mode 100644 source/Stargate-Model/ResourceNotPaginatedPolicy.class.st create mode 100644 source/Stargate-Model/ResourcePaginationPolicy.class.st diff --git a/source/Stargate-Examples/PetOrdersRESTfulWebService.class.st b/source/Stargate-Examples/PetOrdersRESTfulWebService.class.st index eb5f57b..5bafcaf 100644 --- a/source/Stargate-Examples/PetOrdersRESTfulWebService.class.st +++ b/source/Stargate-Examples/PetOrdersRESTfulWebService.class.st @@ -139,6 +139,18 @@ PetOrdersRESTfulWebService >> orders [ ^ orders ] +{ #category : #'private - accessing' } +PetOrdersRESTfulWebService >> provideHypermediaPolicy [ + + ^ HypermediaDrivenResourcePolicy for: self +] + +{ #category : #'private - accessing' } +PetOrdersRESTfulWebService >> providePaginationPolicy [ + + ^ ResourceIsPaginatedPolicy for: self with: self defaultPaginationLimit +] + { #category : #'private - API' } PetOrdersRESTfulWebService >> recordIdAndUpdateTimestampFor: order [ diff --git a/source/Stargate-Examples/PetsRESTfulWebService.class.st b/source/Stargate-Examples/PetsRESTfulWebService.class.st index 68e241f..7ece411 100644 --- a/source/Stargate-Examples/PetsRESTfulWebService.class.st +++ b/source/Stargate-Examples/PetsRESTfulWebService.class.st @@ -152,6 +152,18 @@ PetsRESTfulWebService >> pets [ ^ pets ] +{ #category : #'private - accessing' } +PetsRESTfulWebService >> provideHypermediaPolicy [ + + ^ HypermediaDrivenResourcePolicy for: self +] + +{ #category : #'private - accessing' } +PetsRESTfulWebService >> providePaginationPolicy [ + + ^ ResourceIsPaginatedPolicy for: self with: self defaultPaginationLimit +] + { #category : #'private - state management' } PetsRESTfulWebService >> recordIdAndUpdateTimestampFor: newPet [ diff --git a/source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st b/source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st new file mode 100644 index 0000000..81af726 --- /dev/null +++ b/source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st @@ -0,0 +1,33 @@ +Class { + #name : #HypermediaDrivenResourcePolicy, + #superclass : #HypermediaPolicy, + #instVars : [ + 'resourceController' + ], + #category : #'Stargate-Model-HATEOAS' +} + +{ #category : #'instance creation' } +HypermediaDrivenResourcePolicy class >> for: aResourceController [ + + ^ self new initializeFor: aResourceController +] + +{ #category : #configuring } +HypermediaDrivenResourcePolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ + + context holdAsHypermediaControls: (resourceController paginationPolicy addPaginationControlsTo: {('self' -> httpRequest absoluteUrl)} within: context). + resourceCollection do: [ :resource | context holdAsHypermediaControls: (resourceController mediaControlsFor: resource) forSubresource: resource ] +] + +{ #category : #configuring } +HypermediaDrivenResourcePolicy >> holdResource: resource controlsWithin: context [ + + context holdAsHypermediaControls: (resourceController mediaControlsFor: resource) +] + +{ #category : #initialization } +HypermediaDrivenResourcePolicy >> initializeFor: aResourceController [ + + resourceController := aResourceController +] diff --git a/source/Stargate-Model/HypermediaPolicy.class.st b/source/Stargate-Model/HypermediaPolicy.class.st new file mode 100644 index 0000000..d32d791 --- /dev/null +++ b/source/Stargate-Model/HypermediaPolicy.class.st @@ -0,0 +1,17 @@ +Class { + #name : #HypermediaPolicy, + #superclass : #Object, + #category : #'Stargate-Model-HATEOAS' +} + +{ #category : #configuring } +HypermediaPolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ + + self subclassResponsibility +] + +{ #category : #configuring } +HypermediaPolicy >> holdResource: resource controlsWithin: context [ + + self subclassResponsibility +] diff --git a/source/Stargate-Model/NoHypermediaResourcePolicy.class.st b/source/Stargate-Model/NoHypermediaResourcePolicy.class.st new file mode 100644 index 0000000..a2fe897 --- /dev/null +++ b/source/Stargate-Model/NoHypermediaResourcePolicy.class.st @@ -0,0 +1,13 @@ +Class { + #name : #NoHypermediaResourcePolicy, + #superclass : #HypermediaPolicy, + #category : #'Stargate-Model-HATEOAS' +} + +{ #category : #configuring } +NoHypermediaResourcePolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ +] + +{ #category : #configuring } +NoHypermediaResourcePolicy >> holdResource: resource controlsWithin: context [ +] diff --git a/source/Stargate-Model/PaginationSpec.class.st b/source/Stargate-Model/PaginationSpec.class.st index 8efb35f..d2e2f9f 100644 --- a/source/Stargate-Model/PaginationSpec.class.st +++ b/source/Stargate-Model/PaginationSpec.class.st @@ -8,7 +8,7 @@ Class { 'start', 'limit' ], - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Pagination' } { #category : #'Instance creation' } diff --git a/source/Stargate-Model/RESTfulWebService.class.st b/source/Stargate-Model/RESTfulWebService.class.st index 7185a61..5ab5c6b 100644 --- a/source/Stargate-Model/RESTfulWebService.class.st +++ b/source/Stargate-Model/RESTfulWebService.class.st @@ -11,7 +11,9 @@ Class { #instVars : [ 'mappingRuleSet', 'baseUrlOptional', - 'acceptNegotiator' + 'acceptNegotiator', + 'paginationPolicy', + 'hypermediaPolicy' ], #category : #'Stargate-Model-Services' } @@ -33,12 +35,6 @@ RESTfulWebService >> decode: theRepresentation at: aKey from: sourceMediaType wi do: [ :signal | HTTPClientError signalUnsupportedMediaType: signal messageText ] ] -{ #category : #'private - accessing' } -RESTfulWebService >> defaultPaginationLimit [ - - ^ self subclassResponsibility -] - { #category : #'private - transformations' } RESTfulWebService >> encode: theResource at: aKey to: targetMediaType within: aContext [ @@ -71,12 +67,6 @@ RESTfulWebService >> evaluateQuery: aQueryEvaluationBlock [ do: [ :signal | HTTPClientError signalNotFound: signal messageText ] ] -{ #category : #'private - querying' } -RESTfulWebService >> evaluateQuery: aQueryEvaluationBlock accordingTo: aPaginationSpec [ - - ^ self evaluateQuery: [ aQueryEvaluationBlock cull: aPaginationSpec ] -] - { #category : #'private - API' } RESTfulWebService >> get: aQueryEvaluationBlock asCollectionEncodedUsing: aKey basedOn: anHttpRequest within: aContext [ @@ -85,13 +75,11 @@ RESTfulWebService >> get: aQueryEvaluationBlock asCollectionEncodedUsing: aKey b mediaType := self targetMediaTypeFrom: anHttpRequest. ^ self - handleConflictsIn: [ | resourceCollection encodedResourceCollection response paginationLinks | + handleConflictsIn: [ | resourceCollection encodedResourceCollection response | - resourceCollection := self evaluateQuery: aQueryEvaluationBlock accordingTo: (self paginationFrom: anHttpRequest). - paginationLinks := aContext paginationControls. + resourceCollection := self paginationPolicy evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest. - aContext holdAsHypermediaControls: {('self' -> anHttpRequest absoluteUrl)} , paginationLinks. - resourceCollection do: [ :resource | aContext holdAsHypermediaControls: (self mediaControlsFor: resource) forSubresource: resource ]. + self hypermediaPolicy holdCollection: resourceCollection controlsBasedOn: anHttpRequest within: aContext. encodedResourceCollection := self encode: resourceCollection @@ -99,13 +87,7 @@ RESTfulWebService >> get: aQueryEvaluationBlock asCollectionEncodedUsing: aKey b to: mediaType within: aContext. response := ZnResponse ok: encodedResourceCollection. - paginationLinks - do: [ :assoc | - response - addLink: - ((ZnLink to: assoc value) - rel: assoc key; - yourself) ]. + self paginationPolicy affect: response within: aContext. response ] ] @@ -126,7 +108,7 @@ RESTfulWebService >> get: aQueryEvaluationBlock encodedUsing: aKey basedOn: anHt setEntityTag: etag; yourself ] ]. - aContext holdAsHypermediaControls: (self mediaControlsFor: resource). + self hypermediaPolicy holdResource: resource controlsWithin: aContext. response := ZnResponse ok: (self @@ -146,6 +128,13 @@ RESTfulWebService >> handleConflictsIn: aBlock [ do: [ :signal | HTTPClientError signalConflict: signal messageText ] ] +{ #category : #'private - accessing' } +RESTfulWebService >> hypermediaPolicy [ + + hypermediaPolicy ifNil: [ hypermediaPolicy := self provideHypermediaPolicy ]. + ^ hypermediaPolicy +] + { #category : #'private - accessing' } RESTfulWebService >> ifNoneMatchHeaderPresentIn: anHttpRequest do: aMonadycBlock [ @@ -173,12 +162,23 @@ RESTfulWebService >> mediaControlsFor: result [ ^ {'self' -> (self locationOf: result)} ] -{ #category : #'private - querying' } -RESTfulWebService >> paginationFrom: anHttpRequest [ +{ #category : #'private - accessing' } +RESTfulWebService >> paginationPolicy [ + + paginationPolicy ifNil: [ paginationPolicy := self providePaginationPolicy ]. + ^ paginationPolicy +] + +{ #category : #'private - accessing' } +RESTfulWebService >> provideHypermediaPolicy [ - ^ PaginationSpec - startingAt: (IsInteger parseString: (anHttpRequest at: #start ifAbsent: [ 1 ])) - limitedTo: (IsInteger parseString: (anHttpRequest at: #limit ifAbsent: [ self defaultPaginationLimit ])) + ^ self subclassResponsibility +] + +{ #category : #'private - accessing' } +RESTfulWebService >> providePaginationPolicy [ + + ^ self subclassResponsibility ] { #category : #'private - API' } diff --git a/source/Stargate-Model/ResourceIsPaginatedPolicy.class.st b/source/Stargate-Model/ResourceIsPaginatedPolicy.class.st new file mode 100644 index 0000000..59d3e70 --- /dev/null +++ b/source/Stargate-Model/ResourceIsPaginatedPolicy.class.st @@ -0,0 +1,54 @@ +Class { + #name : #ResourceIsPaginatedPolicy, + #superclass : #ResourcePaginationPolicy, + #instVars : [ + 'resourceController', + 'defaultLimit' + ], + #category : #'Stargate-Model-Pagination' +} + +{ #category : #'instance creation' } +ResourceIsPaginatedPolicy class >> for: aResourceController with: aPaginationLimit [ + + ^ self new initializeFor: aResourceController with: aPaginationLimit +] + +{ #category : #applying } +ResourceIsPaginatedPolicy >> addPaginationControlsTo: mediaControls within: aContext [ + + ^ mediaControls , aContext paginationControls +] + +{ #category : #applying } +ResourceIsPaginatedPolicy >> affect: response within: aContext [ + + aContext paginationControls + do: [ :assoc | + response + addLink: + ((ZnLink to: assoc value) + rel: assoc key; + yourself) ] +] + +{ #category : #applying } +ResourceIsPaginatedPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ + + ^ resourceController evaluateQuery: [ aQueryEvaluationBlock cull: (self paginationFrom: anHttpRequest) ] +] + +{ #category : #'as yet unclassified' } +ResourceIsPaginatedPolicy >> initializeFor: aResourceController with: aPaginationLimit [ + + resourceController := aResourceController. + defaultLimit := aPaginationLimit +] + +{ #category : #private } +ResourceIsPaginatedPolicy >> paginationFrom: anHttpRequest [ + + ^ PaginationSpec + startingAt: (IsInteger parseString: (anHttpRequest at: #start ifAbsent: [ 1 ])) + limitedTo: (IsInteger parseString: (anHttpRequest at: #limit ifAbsent: [ defaultLimit ])) +] diff --git a/source/Stargate-Model/ResourceNotPaginatedPolicy.class.st b/source/Stargate-Model/ResourceNotPaginatedPolicy.class.st new file mode 100644 index 0000000..94db5d2 --- /dev/null +++ b/source/Stargate-Model/ResourceNotPaginatedPolicy.class.st @@ -0,0 +1,36 @@ +Class { + #name : #ResourceNotPaginatedPolicy, + #superclass : #ResourcePaginationPolicy, + #instVars : [ + 'resourceController' + ], + #category : #'Stargate-Model-Pagination' +} + +{ #category : #'instance creation' } +ResourceNotPaginatedPolicy class >> for: aResourceController [ + + ^ self new initializeFor: aResourceController +] + +{ #category : #applying } +ResourceNotPaginatedPolicy >> addPaginationControlsTo: mediaControls within: aContext [ + + ^ mediaControls +] + +{ #category : #applying } +ResourceNotPaginatedPolicy >> affect: response within: aContext [ +] + +{ #category : #applying } +ResourceNotPaginatedPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ + + ^ resourceController evaluateQuery: aQueryEvaluationBlock +] + +{ #category : #'as yet unclassified' } +ResourceNotPaginatedPolicy >> initializeFor: aResourceController [ + + resourceController := aResourceController +] diff --git a/source/Stargate-Model/ResourcePaginationPolicy.class.st b/source/Stargate-Model/ResourcePaginationPolicy.class.st new file mode 100644 index 0000000..62a5bca --- /dev/null +++ b/source/Stargate-Model/ResourcePaginationPolicy.class.st @@ -0,0 +1,23 @@ +Class { + #name : #ResourcePaginationPolicy, + #superclass : #Object, + #category : #'Stargate-Model-Pagination' +} + +{ #category : #applying } +ResourcePaginationPolicy >> addPaginationControlsTo: mediaControls within: aContext [ + + ^ self subclassResponsibility +] + +{ #category : #applying } +ResourcePaginationPolicy >> affect: response within: aContext [ + + self subclassResponsibility +] + +{ #category : #applying } +ResourcePaginationPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ + + self subclassResponsibility +] From 4e046a02412426da9693b250c5517d780d2c8203 Mon Sep 17 00:00:00 2001 From: Gabriel Omar Cotelli Date: Mon, 5 Nov 2018 16:18:31 -0300 Subject: [PATCH 3/6] Several renames --- ...STfulControllerSpecificationTest.class.st} | 8 +- ...> PetOrdersRESTfulControllerTest.class.st} | 60 +++---- .../PetStoreAPITest.class.st | 8 +- ...ESTfulControllerSpecificationTest.class.st | 18 ++ ....st => PetsRESTfulControllerTest.class.st} | 160 +++++++++--------- ...ESTfulWebServiceSpecificationTest.class.st | 18 -- ...st => PetOrdersRESTfulController.class.st} | 48 +++--- ...rsRESTfulControllerSpecification.class.st} | 30 ++-- ...lass.st => PetsRESTfulController.class.st} | 46 ++--- ...tsRESTfulControllerSpecification.class.st} | 32 ++-- ...fulWebServiceAcceptNegotiatorTest.class.st | 2 +- .../ReflectiveRoutesConfiguratorTest.class.st | 2 +- ...=> ResourceRESTfulControllerTest.class.st} | 36 ++-- .../HTTPBasedRESTfulAPI.class.st | 16 +- .../Stargate-Model/HTTPClientError.class.st | 2 +- .../Stargate-Model/HTTPNotAcceptable.class.st | 2 +- ...ESTfulControllerAcceptNegotiator.class.st} | 21 +-- .../ReflectiveMappingRuleSetBuilder.class.st | 8 +- .../ReflectiveRoutesConfigurator.class.st | 6 +- ...ceRESTFulControllerSpecification.class.st} | 10 +- ....st => ResourceRESTfulController.class.st} | 50 +++--- .../Stargate-Model/RouteConfigurator.class.st | 16 +- 22 files changed, 300 insertions(+), 299 deletions(-) rename source/Stargate-Examples-Tests/{PetOrdersRESTfulWebServiceSpecificationTest.class.st => PetOrdersRESTfulControllerSpecificationTest.class.st} (61%) rename source/Stargate-Examples-Tests/{PetOrdersRESTfulWebServiceTest.class.st => PetOrdersRESTfulControllerTest.class.st} (61%) create mode 100644 source/Stargate-Examples-Tests/PetsRESTfulControllerSpecificationTest.class.st rename source/Stargate-Examples-Tests/{PetsRESTfulWebServiceTest.class.st => PetsRESTfulControllerTest.class.st} (64%) delete mode 100644 source/Stargate-Examples-Tests/PetsRESTfulWebServiceSpecificationTest.class.st rename source/Stargate-Examples/{PetOrdersRESTfulWebService.class.st => PetOrdersRESTfulController.class.st} (75%) rename source/Stargate-Examples/{PetOrdersRESTfulWebServiceSpecification.class.st => PetOrdersRESTfulControllerSpecification.class.st} (74%) rename source/Stargate-Examples/{PetsRESTfulWebService.class.st => PetsRESTfulController.class.st} (79%) rename source/Stargate-Examples/{PetsRESTfulWebServiceSpecification.class.st => PetsRESTfulControllerSpecification.class.st} (77%) rename source/Stargate-Model-Tests/{RESTfulWebServiceTest.class.st => ResourceRESTfulControllerTest.class.st} (57%) rename source/Stargate-Model/{RESTfulWebServiceAcceptNegotiator.class.st => RESTfulControllerAcceptNegotiator.class.st} (82%) rename source/Stargate-Model/{RESTFulWebServiceSpecification.class.st => ResourceRESTFulControllerSpecification.class.st} (70%) rename source/Stargate-Model/{RESTfulWebService.class.st => ResourceRESTfulController.class.st} (73%) diff --git a/source/Stargate-Examples-Tests/PetOrdersRESTfulWebServiceSpecificationTest.class.st b/source/Stargate-Examples-Tests/PetOrdersRESTfulControllerSpecificationTest.class.st similarity index 61% rename from source/Stargate-Examples-Tests/PetOrdersRESTfulWebServiceSpecificationTest.class.st rename to source/Stargate-Examples-Tests/PetOrdersRESTfulControllerSpecificationTest.class.st index 9065801..39d4967 100644 --- a/source/Stargate-Examples-Tests/PetOrdersRESTfulWebServiceSpecificationTest.class.st +++ b/source/Stargate-Examples-Tests/PetOrdersRESTfulControllerSpecificationTest.class.st @@ -1,18 +1,18 @@ " -Test Case for PetOrdersRESTfulWebServiceSpecification +Test Case for PetOrdersRESTfulControllerSpecification " Class { - #name : #PetOrdersRESTfulWebServiceSpecificationTest, + #name : #PetOrdersRESTfulControllerSpecificationTest, #superclass : #TestCase, #category : #'Stargate-Examples-Tests' } { #category : #tests } -PetOrdersRESTfulWebServiceSpecificationTest >> testTemplate [ +PetOrdersRESTfulControllerSpecificationTest >> testTemplate [ | spec | - spec := PetOrdersRESTfulWebServiceSpecification new. + spec := PetOrdersRESTfulControllerSpecification new. self assert: spec idTemplate equals: '/orders/'; diff --git a/source/Stargate-Examples-Tests/PetOrdersRESTfulWebServiceTest.class.st b/source/Stargate-Examples-Tests/PetOrdersRESTfulControllerTest.class.st similarity index 61% rename from source/Stargate-Examples-Tests/PetOrdersRESTfulWebServiceTest.class.st rename to source/Stargate-Examples-Tests/PetOrdersRESTfulControllerTest.class.st index b76fa90..1dbf419 100644 --- a/source/Stargate-Examples-Tests/PetOrdersRESTfulWebServiceTest.class.st +++ b/source/Stargate-Examples-Tests/PetOrdersRESTfulControllerTest.class.st @@ -2,72 +2,72 @@ I'm a user stoty test testing the service providing the Pet Order resource, in the classic Pet Store example " Class { - #name : #PetOrdersRESTfulWebServiceTest, - #superclass : #RESTfulWebServiceTest, + #name : #PetOrdersRESTfulControllerTest, + #superclass : #ResourceRESTfulControllerTest, #category : #'Stargate-Examples-Tests' } { #category : #'private - support' } -PetOrdersRESTfulWebServiceTest >> baseUrl [ +PetOrdersRESTfulControllerTest >> baseUrl [ ^ 'https://petstore.example.com' asZnUrl ] { #category : #'private - support' } -PetOrdersRESTfulWebServiceTest >> createOrder [ +PetOrdersRESTfulControllerTest >> createOrder [ - ^ webService createOrderBasedOn: (self requestToCreateOrderFrom: ('{"date":"2018-10-24T18:05:46.418Z","pet":"<1p>"}' expandMacrosWith: self petUrl)) within: self newHttpRequestContext + ^ resourceController createOrderBasedOn: (self requestToCreateOrderFrom: ('{"date":"2018-10-24T18:05:46.418Z","pet":"<1p>"}' expandMacrosWith: self petUrl)) within: self newHttpRequestContext ] { #category : #'private - support' } -PetOrdersRESTfulWebServiceTest >> getFirstOrderAndWithJsonDo: aBlock [ +PetOrdersRESTfulControllerTest >> getFirstOrderAndWithJsonDo: aBlock [ | response | - response := webService getOrderBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: webService specification orderVersion1dot0dot0MediaType) within: self newHttpRequestContext. + response := resourceController getOrderBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: resourceController specification orderVersion1dot0dot0MediaType) within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification orderVersion1dot0dot0MediaType; + assert: response contentType asMediaType equals: resourceController specification orderVersion1dot0dot0MediaType; withJsonFromContentsIn: response do: aBlock ] { #category : #'private - support' } -PetOrdersRESTfulWebServiceTest >> petUrl [ +PetOrdersRESTfulControllerTest >> petUrl [ ^ self baseUrl / 'pets/1' asUrl ] { #category : #'private - support' } -PetOrdersRESTfulWebServiceTest >> requestToCreateOrderFrom: json [ +PetOrdersRESTfulControllerTest >> requestToCreateOrderFrom: json [ - ^ self requestToPOST: json as: webService specification orderVersion1dot0dot0MediaType + ^ self requestToPOST: json as: resourceController specification orderVersion1dot0dot0MediaType ] { #category : #'private - support' } -PetOrdersRESTfulWebServiceTest >> requestToPOST: url identifiedBy: anIdentifier [ +PetOrdersRESTfulControllerTest >> requestToPOST: url identifiedBy: anIdentifier [ ^ TeaRequest fromZnRequest: (ZnRequest post: url) pathParams: {(#identifier -> anIdentifier)} asDictionary ] { #category : #running } -PetOrdersRESTfulWebServiceTest >> setUp [ +PetOrdersRESTfulControllerTest >> setUp [ super setUp. - self setUpWebService. - webService serverUrl: self baseUrl asZnUrl. - self assert: webService orders isEmpty + self setUpResourceController. + resourceController serverUrl: self baseUrl asZnUrl. + self assert: resourceController orders isEmpty ] { #category : #running } -PetOrdersRESTfulWebServiceTest >> setUpWebService [ +PetOrdersRESTfulControllerTest >> setUpResourceController [ - webService := PetOrdersRESTfulWebService new + resourceController := PetOrdersRESTfulController new ] { #category : #tests } -PetOrdersRESTfulWebServiceTest >> testGetCanceledOrder [ +PetOrdersRESTfulControllerTest >> testGetCanceledOrder [ self createOrder; @@ -78,7 +78,7 @@ PetOrdersRESTfulWebServiceTest >> testGetCanceledOrder [ assertUrl: json links self equals: 'https://petstore.example.com/orders/1'; assertUrl: json links cancel equals: 'https://petstore.example.com/orders/1/cancel'; assertUrl: json links complete equals: 'https://petstore.example.com/orders/1/complete'; - assert: (webService cancelOrderBasedOn: (self requestToPOST: json links cancel identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; + assert: (resourceController cancelOrderBasedOn: (self requestToPOST: json links cancel identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; getFirstOrderAndWithJsonDo: [ :json | self assertUrl: json pet equals: self petUrl; @@ -87,7 +87,7 @@ PetOrdersRESTfulWebServiceTest >> testGetCanceledOrder [ ] { #category : #tests } -PetOrdersRESTfulWebServiceTest >> testGetOrderJustCreated [ +PetOrdersRESTfulControllerTest >> testGetOrderJustCreated [ self createOrder; @@ -101,7 +101,7 @@ PetOrdersRESTfulWebServiceTest >> testGetOrderJustCreated [ ] { #category : #tests } -PetOrdersRESTfulWebServiceTest >> testHATEOAS [ +PetOrdersRESTfulControllerTest >> testHATEOAS [ "This case will transition an order from registered to completed to canceled, using the hypermedia controls provided in the response." @@ -115,7 +115,7 @@ PetOrdersRESTfulWebServiceTest >> testHATEOAS [ assertUrl: json links self equals: 'https://petstore.example.com/orders/1'; assertUrl: json links cancel equals: 'https://petstore.example.com/orders/1/cancel'; assertUrl: json links complete equals: 'https://petstore.example.com/orders/1/complete'; - assert: (webService completeOrderBasedOn: (self requestToPOST: json links complete identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; + assert: (resourceController completeOrderBasedOn: (self requestToPOST: json links complete identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; getFirstOrderAndWithJsonDo: [ :json | self assertUrl: json pet equals: self petUrl; @@ -123,7 +123,7 @@ PetOrdersRESTfulWebServiceTest >> testHATEOAS [ assertUrl: json links self equals: 'https://petstore.example.com/orders/1'; assertUrl: json links cancel equals: 'https://petstore.example.com/orders/1/cancel'; assert: json links complete isNil; - assert: (webService cancelOrderBasedOn: (self requestToPOST: json links cancel identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; + assert: (resourceController cancelOrderBasedOn: (self requestToPOST: json links cancel identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; getFirstOrderAndWithJsonDo: [ :json | self assertUrl: json pet equals: self petUrl; @@ -134,7 +134,7 @@ PetOrdersRESTfulWebServiceTest >> testHATEOAS [ ] { #category : #tests } -PetOrdersRESTfulWebServiceTest >> testInvalidStateTransition [ +PetOrdersRESTfulControllerTest >> testInvalidStateTransition [ | completeOrderLink | @@ -143,19 +143,19 @@ PetOrdersRESTfulWebServiceTest >> testInvalidStateTransition [ getFirstOrderAndWithJsonDo: [ :json | self assert: json status equals: 'registered'. completeOrderLink := json links complete. - self assert: (webService cancelOrderBasedOn: (self requestToPOST: json links cancel identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; + self assert: (resourceController cancelOrderBasedOn: (self requestToPOST: json links cancel identifiedBy: 1) within: self newHttpRequestContext) isSuccess ]; getFirstOrderAndWithJsonDo: [ :json | self assert: json status equals: 'canceled'; assert: json links cancel isNil; assert: json links complete isNil ]; - should: [ webService completeOrderBasedOn: (self requestToPOST: completeOrderLink identifiedBy: 1) within: self newHttpRequestContext ] + should: [ resourceController completeOrderBasedOn: (self requestToPOST: completeOrderLink identifiedBy: 1) within: self newHttpRequestContext ] raise: HTTPClientError withExceptionDo: [ :error | self assert: error code equals: 409 ] ] { #category : #tests } -PetOrdersRESTfulWebServiceTest >> testOrderCreation [ +PetOrdersRESTfulControllerTest >> testOrderCreation [ | response | @@ -166,6 +166,6 @@ PetOrdersRESTfulWebServiceTest >> testOrderCreation [ assert: response status equals: 201; assertUrl: response location equals: 'https://petstore.example.com/orders/1'; assert: response hasEntity; - assert: webService orders size equals: 1; - assert: webService orders first pet equals: self petUrl + assert: resourceController orders size equals: 1; + assert: resourceController orders first pet equals: self petUrl ] diff --git a/source/Stargate-Examples-Tests/PetStoreAPITest.class.st b/source/Stargate-Examples-Tests/PetStoreAPITest.class.st index f1e42bb..f672977 100644 --- a/source/Stargate-Examples-Tests/PetStoreAPITest.class.st +++ b/source/Stargate-Examples-Tests/PetStoreAPITest.class.st @@ -38,13 +38,13 @@ PetStoreAPITest >> newClient [ { #category : #private } PetStoreAPITest >> ordersSpec [ - ^ PetOrdersRESTfulWebServiceSpecification new + ^ PetOrdersRESTfulControllerSpecification new ] { #category : #private } PetStoreAPITest >> petsSpec [ - ^ PetsRESTfulWebServiceSpecification new + ^ PetsRESTfulControllerSpecification new ] { #category : #private } @@ -62,8 +62,8 @@ PetStoreAPITest >> setUp [ {(#port -> self port). (#serverUrl -> self baseUrl)} installing: - {PetsRESTfulWebService new. - PetOrdersRESTfulWebService new}. + {PetsRESTfulController new. + PetOrdersRESTfulController new}. api install; diff --git a/source/Stargate-Examples-Tests/PetsRESTfulControllerSpecificationTest.class.st b/source/Stargate-Examples-Tests/PetsRESTfulControllerSpecificationTest.class.st new file mode 100644 index 0000000..c2ab804 --- /dev/null +++ b/source/Stargate-Examples-Tests/PetsRESTfulControllerSpecificationTest.class.st @@ -0,0 +1,18 @@ +" +Test case for PetsRESTfulControllerSpecification +" +Class { + #name : #PetsRESTfulControllerSpecificationTest, + #superclass : #TestCase, + #category : #'Stargate-Examples-Tests' +} + +{ #category : #tests } +PetsRESTfulControllerSpecificationTest >> testTemplate [ + + | spec | + + spec := PetsRESTfulControllerSpecification new. + + self assert: spec idTemplate equals: '/pets/' +] diff --git a/source/Stargate-Examples-Tests/PetsRESTfulWebServiceTest.class.st b/source/Stargate-Examples-Tests/PetsRESTfulControllerTest.class.st similarity index 64% rename from source/Stargate-Examples-Tests/PetsRESTfulWebServiceTest.class.st rename to source/Stargate-Examples-Tests/PetsRESTfulControllerTest.class.st index 2ecb9fe..cd37e22 100644 --- a/source/Stargate-Examples-Tests/PetsRESTfulWebServiceTest.class.st +++ b/source/Stargate-Examples-Tests/PetsRESTfulControllerTest.class.st @@ -2,31 +2,31 @@ I'm a user stoty test testing the service providing the Pet resource, in the classic Pet Store example " Class { - #name : #PetsRESTfulWebServiceTest, - #superclass : #RESTfulWebServiceTest, + #name : #PetsRESTfulControllerTest, + #superclass : #ResourceRESTfulControllerTest, #category : #'Stargate-Examples-Tests' } { #category : #'private - support' } -PetsRESTfulWebServiceTest >> baseUrl [ +PetsRESTfulControllerTest >> baseUrl [ ^ 'https://pets.example.com' asZnUrl ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> createPet [ +PetsRESTfulControllerTest >> createPet [ self assert: - (webService + (resourceController createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext) isSuccess ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> createSixPets [ +PetsRESTfulControllerTest >> createSixPets [ - webService + resourceController createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext; createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Lassie","type":"dog"}') within: self newHttpRequestContext; createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Garfield","type":"cat"}') within: self newHttpRequestContext; @@ -34,27 +34,27 @@ PetsRESTfulWebServiceTest >> createSixPets [ createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Babe","type":"pig"}') within: self newHttpRequestContext; createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Beethoven","type":"dog"}') within: self newHttpRequestContext. - self assert: webService pets size equals: 6 + self assert: resourceController pets size equals: 6 ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> defaultPetMediaType [ +PetsRESTfulControllerTest >> defaultPetMediaType [ - ^ webService specification petVersion1dot0dot0MediaType + ^ resourceController specification petVersion1dot0dot0MediaType ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> entityTagOfPetIdentifiedBy: anIdentifier [ +PetsRESTfulControllerTest >> entityTagOfPetIdentifiedBy: anIdentifier [ | getResponse | - getResponse := webService getPetBasedOn: (self requestToGetResourceIdentifiedBy: anIdentifier accepting: self defaultPetMediaType) within: self newHttpRequestContext. + getResponse := resourceController getPetBasedOn: (self requestToGetResourceIdentifiedBy: anIdentifier accepting: self defaultPetMediaType) within: self newHttpRequestContext. self assert: getResponse isSuccess. ^ getResponse headers at: 'ETag' ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestMissingIfMatchHeaderToUpdatePetIdentifiedBy: anIdentifier nameTo: aName [ +PetsRESTfulControllerTest >> requestMissingIfMatchHeaderToUpdatePetIdentifiedBy: anIdentifier nameTo: aName [ ^ TeaRequest fromZnRequest: @@ -66,19 +66,19 @@ PetsRESTfulWebServiceTest >> requestMissingIfMatchHeaderToUpdatePetIdentifiedBy: ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToCreatePetFrom: json [ +PetsRESTfulControllerTest >> requestToCreatePetFrom: json [ ^ self requestToPOST: json as: self defaultPetMediaType ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToDeletePetIdentifiedBy: anIdentifier [ +PetsRESTfulControllerTest >> requestToDeletePetIdentifiedBy: anIdentifier [ ^ TeaRequest fromZnRequest: (ZnRequest delete: (self urlForResourceIdentifiedBy: anIdentifier)) pathParams: {(#identifier -> anIdentifier)} asDictionary ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToGet: aUrl accepting: anAcceptHeader [ +PetsRESTfulControllerTest >> requestToGet: aUrl accepting: anAcceptHeader [ ^ TeaRequest fromZnRequest: @@ -88,19 +88,19 @@ PetsRESTfulWebServiceTest >> requestToGet: aUrl accepting: anAcceptHeader [ ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToGetPetsAccepting: anAcceptHeader [ +PetsRESTfulControllerTest >> requestToGetPetsAccepting: anAcceptHeader [ ^ self requestToGet: self resourceUrl accepting: anAcceptHeader ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToUpdatePetIdentifiedBy: anIdentifier nameTo: aName [ +PetsRESTfulControllerTest >> requestToUpdatePetIdentifiedBy: anIdentifier nameTo: aName [ ^ self requestToUpdatePetIdentifiedBy: anIdentifier nameTo: aName using: (self entityTagOfPetIdentifiedBy: anIdentifier) ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToUpdatePetIdentifiedBy: anIdentifier nameTo: aName using: anETag [ +PetsRESTfulControllerTest >> requestToUpdatePetIdentifiedBy: anIdentifier nameTo: aName using: anETag [ ^ TeaRequest fromZnRequest: @@ -113,7 +113,7 @@ PetsRESTfulWebServiceTest >> requestToUpdatePetIdentifiedBy: anIdentifier nameTo ] { #category : #'private - support' } -PetsRESTfulWebServiceTest >> requestToUpdatePetIdentifiedBy: anIdentifier statusTo: aStatus [ +PetsRESTfulControllerTest >> requestToUpdatePetIdentifiedBy: anIdentifier statusTo: aStatus [ ^ TeaRequest fromZnRequest: @@ -126,59 +126,59 @@ PetsRESTfulWebServiceTest >> requestToUpdatePetIdentifiedBy: anIdentifier status ] { #category : #running } -PetsRESTfulWebServiceTest >> setUp [ +PetsRESTfulControllerTest >> setUp [ super setUp. - self assert: webService pets isEmpty + self assert: resourceController pets isEmpty ] { #category : #running } -PetsRESTfulWebServiceTest >> setUpWebService [ +PetsRESTfulControllerTest >> setUpResourceController [ - webService := PetsRESTfulWebService new + resourceController := PetsRESTfulController new ] { #category : #'tests - delete' } -PetsRESTfulWebServiceTest >> testCantDeleteInvalidPet [ +PetsRESTfulControllerTest >> testCantDeleteInvalidPet [ self - should: [ webService deletePetBasedOn: (self requestToDeletePetIdentifiedBy: 1) within: self newHttpRequestContext ] + should: [ resourceController deletePetBasedOn: (self requestToDeletePetIdentifiedBy: 1) within: self newHttpRequestContext ] raise: HTTPClientError withExceptionDo: [ :signal | self assert: signal code equals: 404 ] ] { #category : #'tests - update' } -PetsRESTfulWebServiceTest >> testCantUpdatePetIfMissingETag [ +PetsRESTfulControllerTest >> testCantUpdatePetIfMissingETag [ self createPet; - should: [ webService updatePetBasedOn: (self requestMissingIfMatchHeaderToUpdatePetIdentifiedBy: 1 nameTo: 'Mendieta') within: self newHttpRequestContext ] + should: [ resourceController updatePetBasedOn: (self requestMissingIfMatchHeaderToUpdatePetIdentifiedBy: 1 nameTo: 'Mendieta') within: self newHttpRequestContext ] raise: HTTPClientError withExceptionDo: [ :error | self assert: error code equals: 428 ] ] { #category : #'tests - update' } -PetsRESTfulWebServiceTest >> testCantUpdatePetWhenETagNotMatching [ +PetsRESTfulControllerTest >> testCantUpdatePetWhenETagNotMatching [ self createPet; - should: [ webService updatePetBasedOn: (self requestToUpdatePetIdentifiedBy: 1 nameTo: 'Mendieta' using: '"Frula"') within: self newHttpRequestContext ] + should: [ resourceController updatePetBasedOn: (self requestToUpdatePetIdentifiedBy: 1 nameTo: 'Mendieta' using: '"Frula"') within: self newHttpRequestContext ] raise: HTTPClientError withExceptionDo: [ :error | self assert: error code equals: 412 ] ] { #category : #'tests - get collection' } -PetsRESTfulWebServiceTest >> testComplexPagination [ +PetsRESTfulControllerTest >> testComplexPagination [ | response | self createSixPets. "Get the 1st page" - response := webService getPetsBasedOn: (self requestToGet: 'https://pets.example.com/pets?limit=2' accepting: '*/*') within: self newHttpRequestContext. + response := resourceController getPetsBasedOn: (self requestToGet: 'https://pets.example.com/pets?limit=2' accepting: '*/*') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType; + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType; assert: response links size equals: 2; assertUrl: response links first url equals: 'https://pets.example.com/pets?start=3&limit=2'; assert: response links first rel equals: 'next'; @@ -193,11 +193,11 @@ PetsRESTfulWebServiceTest >> testComplexPagination [ assertUrl: json links last equals: 'https://pets.example.com/pets?start=5&limit=2'; assert: json items size equals: 2 ]. "Get the 2nd page" - response := webService getPetsBasedOn: (self requestToGet: 'https://pets.example.com/pets?start=3&limit=2' accepting: '*/*') within: self newHttpRequestContext. + response := resourceController getPetsBasedOn: (self requestToGet: 'https://pets.example.com/pets?start=3&limit=2' accepting: '*/*') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType; + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType; assert: response links size equals: 4; assertUrl: response links first url equals: 'https://pets.example.com/pets?start=1&limit=2'; assert: response links first rel equals: 'first'; @@ -220,13 +220,13 @@ PetsRESTfulWebServiceTest >> testComplexPagination [ ] { #category : #'tests - delete' } -PetsRESTfulWebServiceTest >> testDeletePet [ +PetsRESTfulControllerTest >> testDeletePet [ | response | self createPet. - response := webService deletePetBasedOn: (self requestToDeletePetIdentifiedBy: 1) within: self newHttpRequestContext. + response := resourceController deletePetBasedOn: (self requestToDeletePetIdentifiedBy: 1) within: self newHttpRequestContext. self assert: response isSuccess; @@ -235,13 +235,13 @@ PetsRESTfulWebServiceTest >> testDeletePet [ ] { #category : #'tests - get individual' } -PetsRESTfulWebServiceTest >> testGetNotModifiedWhenValidETag [ +PetsRESTfulControllerTest >> testGetNotModifiedWhenValidETag [ | response | self createPet. - response := webService + response := resourceController getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: self defaultPetMediaType) within: self newHttpRequestContext. @@ -249,7 +249,7 @@ PetsRESTfulWebServiceTest >> testGetNotModifiedWhenValidETag [ assert: response isSuccess; assert: response entityTag equals: '"c051344b8c92c5ed8a2bd0752070c35ed3de3bab"' asETag. - response := webService + response := resourceController getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 @@ -263,15 +263,15 @@ PetsRESTfulWebServiceTest >> testGetNotModifiedWhenValidETag [ ] { #category : #'tests - get individual' } -PetsRESTfulWebServiceTest >> testGetPetJustCreated [ +PetsRESTfulControllerTest >> testGetPetJustCreated [ | response | self - assert: (webService createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext) isSuccess; - assert: webService pets size equals: 1. + assert: (resourceController createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext) isSuccess; + assert: resourceController pets size equals: 1. - response := webService getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: self defaultPetMediaType) within: self newHttpRequestContext. + response := resourceController getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: self defaultPetMediaType) within: self newHttpRequestContext. self assert: response isSuccess; @@ -290,29 +290,29 @@ PetsRESTfulWebServiceTest >> testGetPetJustCreated [ ] { #category : #'tests - get individual' } -PetsRESTfulWebServiceTest >> testGetPetNotFoundShouldFail [ +PetsRESTfulControllerTest >> testGetPetNotFoundShouldFail [ self - should: [ webService getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: '*/*') within: self newHttpRequestContext ] + should: [ resourceController getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: '*/*') within: self newHttpRequestContext ] raise: HTTPClientError withExceptionDo: [ :error | self assert: error code equals: 404 ] ] { #category : #'tests - get individual' } -PetsRESTfulWebServiceTest >> testGetPetSummaryJustCreated [ +PetsRESTfulControllerTest >> testGetPetSummaryJustCreated [ | response | self - assert: (webService createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext) isSuccess; - assert: webService pets size equals: 1. + assert: (resourceController createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext) isSuccess; + assert: resourceController pets size equals: 1. - response := webService getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: webService specification petSummaryVersion1dot0dot0MediaType) within: self newHttpRequestContext. + response := resourceController getPetBasedOn: (self requestToGetResourceIdentifiedBy: 1 accepting: resourceController specification petSummaryVersion1dot0dot0MediaType) within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType; + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType; assert: response entityTag equals: '"1323cdfb8bb0f9011fbd480c5a87c17d05883214"' asETag. self @@ -326,16 +326,16 @@ PetsRESTfulWebServiceTest >> testGetPetSummaryJustCreated [ ] { #category : #'tests - get collection' } -PetsRESTfulWebServiceTest >> testGetPets [ +PetsRESTfulControllerTest >> testGetPets [ | response | - response := webService getPetsBasedOn: (self requestToGetPetsAccepting: '*/*') within: self newHttpRequestContext. + response := resourceController getPetsBasedOn: (self requestToGetPetsAccepting: '*/*') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType. + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType. self withJsonFromContentsIn: response @@ -346,20 +346,20 @@ PetsRESTfulWebServiceTest >> testGetPets [ ] { #category : #'tests - get collection' } -PetsRESTfulWebServiceTest >> testGetPetsNotEmpty [ +PetsRESTfulControllerTest >> testGetPetsNotEmpty [ | response | - webService createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext. + resourceController createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext. - self assert: webService pets notEmpty. + self assert: resourceController pets notEmpty. - response := webService getPetsBasedOn: (self requestToGetPetsAccepting: '*/*') within: self newHttpRequestContext. + response := resourceController getPetsBasedOn: (self requestToGetPetsAccepting: '*/*') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType. + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType. self withJsonFromContentsIn: response @@ -377,18 +377,18 @@ PetsRESTfulWebServiceTest >> testGetPetsNotEmpty [ ] { #category : #'tests - get collection' } -PetsRESTfulWebServiceTest >> testGetPetsWithPagination [ +PetsRESTfulControllerTest >> testGetPetsWithPagination [ | response | self createSixPets. - response := webService getPetsBasedOn: (self requestToGetPetsAccepting: '*/*') within: self newHttpRequestContext. + response := resourceController getPetsBasedOn: (self requestToGetPetsAccepting: '*/*') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType; + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType; assert: response links size equals: 2; assertUrl: response links first url equals: 'https://pets.example.com/pets?start=6&limit=5'; assert: response links first rel equals: 'next'; @@ -404,11 +404,11 @@ PetsRESTfulWebServiceTest >> testGetPetsWithPagination [ assertUrl: json links last equals: 'https://pets.example.com/pets?start=6&limit=5'; assert: json items size equals: 5. - response := webService getPetsBasedOn: (self requestToGet: json links next accepting: response contentType) within: self newHttpRequestContext. + response := resourceController getPetsBasedOn: (self requestToGet: json links next accepting: response contentType) within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; - assert: response contentType asMediaType equals: webService specification petSummaryVersion1dot0dot0MediaType; + assert: response contentType asMediaType equals: resourceController specification petSummaryVersion1dot0dot0MediaType; assert: response links size equals: 2; assertUrl: response links first url equals: 'https://pets.example.com/pets?start=1&limit=5'; assert: response links first rel equals: 'first'; @@ -427,39 +427,39 @@ PetsRESTfulWebServiceTest >> testGetPetsWithPagination [ ] { #category : #'tests - creation' } -PetsRESTfulWebServiceTest >> testPetCreation [ +PetsRESTfulControllerTest >> testPetCreation [ | response | - response := webService createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext. + response := resourceController createPetBasedOn: (self requestToCreatePetFrom: '{"name":"Firulais","type":"dog"}') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 201; assertUrl: response location equals: 'https://pets.example.com/pets/1'; assert: response hasEntity; - assert: webService pets size equals: 1; - assert: webService pets first name equals: 'Firulais' + assert: resourceController pets size equals: 1; + assert: resourceController pets first name equals: 'Firulais' ] { #category : #'tests - update' } -PetsRESTfulWebServiceTest >> testUpdatePetName [ +PetsRESTfulControllerTest >> testUpdatePetName [ | response | self createPet; - assert: webService pets first name equals: 'Firulais'. + assert: resourceController pets first name equals: 'Firulais'. - response := webService updatePetBasedOn: (self requestToUpdatePetIdentifiedBy: 1 nameTo: 'Mendieta') within: self newHttpRequestContext. + response := resourceController updatePetBasedOn: (self requestToUpdatePetIdentifiedBy: 1 nameTo: 'Mendieta') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; assert: response hasEntity; - assert: webService pets size equals: 1; - assert: webService pets first name equals: 'Mendieta'; - assert: webService pets first status equals: 'new'; + assert: resourceController pets size equals: 1; + assert: resourceController pets first name equals: 'Mendieta'; + assert: resourceController pets first status equals: 'new'; withJsonFromContentsIn: response do: [ :json | self @@ -470,23 +470,23 @@ PetsRESTfulWebServiceTest >> testUpdatePetName [ ] { #category : #'tests - update' } -PetsRESTfulWebServiceTest >> testUpdatePetStatus [ +PetsRESTfulControllerTest >> testUpdatePetStatus [ | response | self createPet; - assert: webService pets first status equals: 'new'. + assert: resourceController pets first status equals: 'new'. - response := webService updatePetBasedOn: (self requestToUpdatePetIdentifiedBy: 1 statusTo: 'gone') within: self newHttpRequestContext. + response := resourceController updatePetBasedOn: (self requestToUpdatePetIdentifiedBy: 1 statusTo: 'gone') within: self newHttpRequestContext. self assert: response isSuccess; assert: response status equals: 200; assert: response hasEntity; - assert: webService pets size equals: 1; - assert: webService pets first name equals: 'Firulais'; - assert: webService pets first status equals: 'gone'; + assert: resourceController pets size equals: 1; + assert: resourceController pets first name equals: 'Firulais'; + assert: resourceController pets first status equals: 'gone'; withJsonFromContentsIn: response do: [ :json | self diff --git a/source/Stargate-Examples-Tests/PetsRESTfulWebServiceSpecificationTest.class.st b/source/Stargate-Examples-Tests/PetsRESTfulWebServiceSpecificationTest.class.st deleted file mode 100644 index f604988..0000000 --- a/source/Stargate-Examples-Tests/PetsRESTfulWebServiceSpecificationTest.class.st +++ /dev/null @@ -1,18 +0,0 @@ -" -Test case for PetsRESTfulWebServiceSpecification -" -Class { - #name : #PetsRESTfulWebServiceSpecificationTest, - #superclass : #TestCase, - #category : #'Stargate-Examples-Tests' -} - -{ #category : #tests } -PetsRESTfulWebServiceSpecificationTest >> testTemplate [ - - | spec | - - spec := PetsRESTfulWebServiceSpecification new. - - self assert: spec idTemplate equals: '/pets/' -] diff --git a/source/Stargate-Examples/PetOrdersRESTfulWebService.class.st b/source/Stargate-Examples/PetOrdersRESTfulController.class.st similarity index 75% rename from source/Stargate-Examples/PetOrdersRESTfulWebService.class.st rename to source/Stargate-Examples/PetOrdersRESTfulController.class.st index 5bafcaf..4a85690 100644 --- a/source/Stargate-Examples/PetOrdersRESTfulWebService.class.st +++ b/source/Stargate-Examples/PetOrdersRESTfulController.class.st @@ -2,8 +2,8 @@ I'm an example RESTful Web Service implementing Pet Order resource management " Class { - #name : #PetOrdersRESTfulWebService, - #superclass : #RESTfulWebService, + #name : #PetOrdersRESTfulController, + #superclass : #ResourceRESTfulController, #instVars : [ 'orders', 'nextId', @@ -15,19 +15,19 @@ Class { } { #category : #API } -PetOrdersRESTfulWebService >> cancelOrderBasedOn: anHttpRequest within: aContext [ +PetOrdersRESTfulController >> cancelOrderBasedOn: anHttpRequest within: aContext [ ^ self updateOrderStatusBasedOn: anHttpRequest within: aContext with: [ self updateOrderStatusAt: (self identifierIn: anHttpRequest) to: 'canceled' ] ] { #category : #API } -PetOrdersRESTfulWebService >> completeOrderBasedOn: anHttpRequest within: aContext [ +PetOrdersRESTfulController >> completeOrderBasedOn: anHttpRequest within: aContext [ ^ self updateOrderStatusBasedOn: anHttpRequest within: aContext with: [ self updateOrderStatusToCompletedBasedOn: anHttpRequest ] ] { #category : #API } -PetOrdersRESTfulWebService >> createOrderBasedOn: anHttpRequest within: aContext [ +PetOrdersRESTfulController >> createOrderBasedOn: anHttpRequest within: aContext [ ^ self withCreatedResourceDo: [ :order | @@ -41,13 +41,13 @@ PetOrdersRESTfulWebService >> createOrderBasedOn: anHttpRequest within: aContext ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> defaultPaginationLimit [ +PetOrdersRESTfulController >> defaultPaginationLimit [ ^ 10 ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> entityTagOf: aPetOrder encodedAs: mediaType [ +PetOrdersRESTfulController >> entityTagOf: aPetOrder encodedAs: mediaType [ ^ ZnETag with: @@ -60,7 +60,7 @@ PetOrdersRESTfulWebService >> entityTagOf: aPetOrder encodedAs: mediaType [ ] { #category : #API } -PetOrdersRESTfulWebService >> getOrderBasedOn: anHttpRequest within: aContext [ +PetOrdersRESTfulController >> getOrderBasedOn: anHttpRequest within: aContext [ ^ self get: [ aContext hold: (orderStatus at: (self identifierIn: anHttpRequest)) under: #status. @@ -71,19 +71,19 @@ PetOrdersRESTfulWebService >> getOrderBasedOn: anHttpRequest within: aContext [ ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> identifierIn: anHttpRequest [ +PetOrdersRESTfulController >> identifierIn: anHttpRequest [ ^ anHttpRequest at: #identifier ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> identifierOf: aPetOrder [ +PetOrdersRESTfulController >> identifierOf: aPetOrder [ ^ orderById keyAtValue: aPetOrder ] { #category : #initialization } -PetOrdersRESTfulWebService >> initialize [ +PetOrdersRESTfulController >> initialize [ super initialize. orders := OrderedCollection new. @@ -94,13 +94,13 @@ PetOrdersRESTfulWebService >> initialize [ ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> lastModificationOf: aPetOrder [ +PetOrdersRESTfulController >> lastModificationOf: aPetOrder [ ^ updateTimestamps at: (self identifierOf: aPetOrder) ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> locationOf: aPetOrder [ +PetOrdersRESTfulController >> locationOf: aPetOrder [ | baseUrl | @@ -111,7 +111,7 @@ PetOrdersRESTfulWebService >> locationOf: aPetOrder [ ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> mediaControlsFor: order [ +PetOrdersRESTfulController >> mediaControlsFor: order [ | status | @@ -128,31 +128,31 @@ PetOrdersRESTfulWebService >> mediaControlsFor: order [ ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> orderIdentifiedUsing: anHttpRequest [ +PetOrdersRESTfulController >> orderIdentifiedUsing: anHttpRequest [ ^ orderById at: (self identifierIn: anHttpRequest) ifAbsent: [ ObjectNotFound signal ] ] { #category : #accessing } -PetOrdersRESTfulWebService >> orders [ +PetOrdersRESTfulController >> orders [ ^ orders ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> provideHypermediaPolicy [ +PetOrdersRESTfulController >> provideHypermediaPolicy [ ^ HypermediaDrivenResourcePolicy for: self ] { #category : #'private - accessing' } -PetOrdersRESTfulWebService >> providePaginationPolicy [ +PetOrdersRESTfulController >> providePaginationPolicy [ ^ ResourceIsPaginatedPolicy for: self with: self defaultPaginationLimit ] { #category : #'private - API' } -PetOrdersRESTfulWebService >> recordIdAndUpdateTimestampFor: order [ +PetOrdersRESTfulController >> recordIdAndUpdateTimestampFor: order [ orderById at: nextId put: order. orderStatus at: nextId put: 'registered'. @@ -162,20 +162,20 @@ PetOrdersRESTfulWebService >> recordIdAndUpdateTimestampFor: order [ ] { #category : #specification } -PetOrdersRESTfulWebService >> specification [ +PetOrdersRESTfulController >> specification [ - ^ PetOrdersRESTfulWebServiceSpecification new + ^ PetOrdersRESTfulControllerSpecification new ] { #category : #'private - API' } -PetOrdersRESTfulWebService >> updateOrderStatusAt: id to: aTargetStatus [ +PetOrdersRESTfulController >> updateOrderStatusAt: id to: aTargetStatus [ orderStatus at: id put: aTargetStatus. updateTimestamps at: id put: (updateTimestamps at: id) + 1 ] { #category : #API } -PetOrdersRESTfulWebService >> updateOrderStatusBasedOn: anHttpRequest within: aContext with: anUpdateBlock [ +PetOrdersRESTfulController >> updateOrderStatusBasedOn: anHttpRequest within: aContext with: anUpdateBlock [ | response | @@ -186,7 +186,7 @@ PetOrdersRESTfulWebService >> updateOrderStatusBasedOn: anHttpRequest within: aC ] { #category : #'private - API' } -PetOrdersRESTfulWebService >> updateOrderStatusToCompletedBasedOn: anHttpRequest [ +PetOrdersRESTfulController >> updateOrderStatusToCompletedBasedOn: anHttpRequest [ | orderId | diff --git a/source/Stargate-Examples/PetOrdersRESTfulWebServiceSpecification.class.st b/source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st similarity index 74% rename from source/Stargate-Examples/PetOrdersRESTfulWebServiceSpecification.class.st rename to source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st index 694a05a..8a00a03 100644 --- a/source/Stargate-Examples/PetOrdersRESTfulWebServiceSpecification.class.st +++ b/source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st @@ -2,13 +2,13 @@ I'm an example RESTful Web Service specification implementing Pet Order resource management " Class { - #name : #PetOrdersRESTfulWebServiceSpecification, - #superclass : #RESTFulWebServiceSpecification, + #name : #PetOrdersRESTfulControllerSpecification, + #superclass : #ResourceRESTFulControllerSpecification, #category : #'Stargate-Examples' } { #category : #'mapping rules' } -PetOrdersRESTfulWebServiceSpecification >> addJsonDecoderVersion1dot0dot0MappingIn: aBuilder [ +PetOrdersRESTfulControllerSpecification >> addJsonDecoderVersion1dot0dot0MappingIn: aBuilder [ aBuilder addDefaultRuleToDecode: self orderVersion1dot0dot0MediaType @@ -24,7 +24,7 @@ PetOrdersRESTfulWebServiceSpecification >> addJsonDecoderVersion1dot0dot0Mapping ] { #category : #'mapping rules' } -PetOrdersRESTfulWebServiceSpecification >> addJsonEncoderVersion1dot0dot0MappingIn: aBuilder [ +PetOrdersRESTfulControllerSpecification >> addJsonEncoderVersion1dot0dot0MappingIn: aBuilder [ aBuilder addDefaultRuleToEncode: self orderMappingKey @@ -44,67 +44,67 @@ PetOrdersRESTfulWebServiceSpecification >> addJsonEncoderVersion1dot0dot0Mapping ] { #category : #routes } -PetOrdersRESTfulWebServiceSpecification >> cancelOrderRoute [ +PetOrdersRESTfulControllerSpecification >> cancelOrderRoute [ ^ RouteSpecification handling: #POST at: self cancelTemplate evaluating: [ :service :httpRequest :context | service cancelOrderBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } -PetOrdersRESTfulWebServiceSpecification >> cancelTemplate [ +PetOrdersRESTfulControllerSpecification >> cancelTemplate [ ^ '<1s>/%<<2s>:IsInteger>/cancel' expandMacrosWith: self endpoint with: self identifierKey ] { #category : #routes } -PetOrdersRESTfulWebServiceSpecification >> completeOrderRoute [ +PetOrdersRESTfulControllerSpecification >> completeOrderRoute [ ^ RouteSpecification handling: #POST at: self completeTemplate evaluating: [ :service :httpRequest :context | service completeOrderBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } -PetOrdersRESTfulWebServiceSpecification >> completeTemplate [ +PetOrdersRESTfulControllerSpecification >> completeTemplate [ ^ '<1s>/%<<2s>:IsInteger>/complete' expandMacrosWith: self endpoint with: self identifierKey ] { #category : #routes } -PetOrdersRESTfulWebServiceSpecification >> createOrderRoute [ +PetOrdersRESTfulControllerSpecification >> createOrderRoute [ ^ RouteSpecification handling: #POST at: self endpoint evaluating: [ :service :httpRequest :context | service createOrderBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } -PetOrdersRESTfulWebServiceSpecification >> endpoint [ +PetOrdersRESTfulControllerSpecification >> endpoint [ ^ '/orders' ] { #category : #routes } -PetOrdersRESTfulWebServiceSpecification >> getOrderRoute [ +PetOrdersRESTfulControllerSpecification >> getOrderRoute [ ^ RouteSpecification handling: #GET at: self idTemplate evaluating: [ :service :httpRequest :context | service getOrderBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } -PetOrdersRESTfulWebServiceSpecification >> idTemplate [ +PetOrdersRESTfulControllerSpecification >> idTemplate [ ^ '<1s>/%<<2s>:IsInteger>' expandMacrosWith: self endpoint with: self identifierKey ] { #category : #accessing } -PetOrdersRESTfulWebServiceSpecification >> identifierKey [ +PetOrdersRESTfulControllerSpecification >> identifierKey [ ^ #identifier ] { #category : #accessing } -PetOrdersRESTfulWebServiceSpecification >> orderMappingKey [ +PetOrdersRESTfulControllerSpecification >> orderMappingKey [ ^ #order ] { #category : #accessing } -PetOrdersRESTfulWebServiceSpecification >> orderVersion1dot0dot0MediaType [ +PetOrdersRESTfulControllerSpecification >> orderVersion1dot0dot0MediaType [ ^ 'application/vnd.stargate.order+json;version=1.0.0' asMediaType ] diff --git a/source/Stargate-Examples/PetsRESTfulWebService.class.st b/source/Stargate-Examples/PetsRESTfulController.class.st similarity index 79% rename from source/Stargate-Examples/PetsRESTfulWebService.class.st rename to source/Stargate-Examples/PetsRESTfulController.class.st index 7ece411..6afc280 100644 --- a/source/Stargate-Examples/PetsRESTfulWebService.class.st +++ b/source/Stargate-Examples/PetsRESTfulController.class.st @@ -2,8 +2,8 @@ I'm an example RESTful Web Service implementing Pet resource management " Class { - #name : #PetsRESTfulWebService, - #superclass : #RESTfulWebService, + #name : #PetsRESTfulController, + #superclass : #ResourceRESTfulController, #instVars : [ 'pets', 'nextId', @@ -14,7 +14,7 @@ Class { } { #category : #'private - accessing' } -PetsRESTfulWebService >> addPaginationControlsTo: aContext basedOn: url start: start limit: limit end: end count: total [ +PetsRESTfulController >> addPaginationControlsTo: aContext basedOn: url start: start limit: limit end: end count: total [ start = 1 ifFalse: [ aContext addPaginationControl: 'first' -> (self urlFrom: url startingAt: 1 limitedTo: limit) ]. @@ -27,7 +27,7 @@ PetsRESTfulWebService >> addPaginationControlsTo: aContext basedOn: url start: s ] { #category : #API } -PetsRESTfulWebService >> createPetBasedOn: anHttpRequest within: aContext [ +PetsRESTfulController >> createPetBasedOn: anHttpRequest within: aContext [ ^ self withCreatedResourceDo: [ :resource | @@ -44,13 +44,13 @@ PetsRESTfulWebService >> createPetBasedOn: anHttpRequest within: aContext [ ] { #category : #'private - accessing' } -PetsRESTfulWebService >> defaultPaginationLimit [ +PetsRESTfulController >> defaultPaginationLimit [ ^ 5 ] { #category : #API } -PetsRESTfulWebService >> deletePetBasedOn: anHttpRequest within: aContext [ +PetsRESTfulController >> deletePetBasedOn: anHttpRequest within: aContext [ [ pets remove: (self petIdentifiedUsing: anHttpRequest) ] on: ObjectNotFound @@ -60,7 +60,7 @@ PetsRESTfulWebService >> deletePetBasedOn: anHttpRequest within: aContext [ ] { #category : #'private - accessing' } -PetsRESTfulWebService >> entityTagOf: aPet encodedAs: mediaType [ +PetsRESTfulController >> entityTagOf: aPet encodedAs: mediaType [ ^ ZnETag with: @@ -73,7 +73,7 @@ PetsRESTfulWebService >> entityTagOf: aPet encodedAs: mediaType [ ] { #category : #API } -PetsRESTfulWebService >> getPetBasedOn: anHttpRequest within: aContext [ +PetsRESTfulController >> getPetBasedOn: anHttpRequest within: aContext [ ^ self get: [ self petIdentifiedUsing: anHttpRequest ] @@ -83,7 +83,7 @@ PetsRESTfulWebService >> getPetBasedOn: anHttpRequest within: aContext [ ] { #category : #API } -PetsRESTfulWebService >> getPetsBasedOn: anHttpRequest within: aContext [ +PetsRESTfulController >> getPetsBasedOn: anHttpRequest within: aContext [ ^ self get: [ :pagination | @@ -108,13 +108,13 @@ PetsRESTfulWebService >> getPetsBasedOn: anHttpRequest within: aContext [ ] { #category : #'private - accessing' } -PetsRESTfulWebService >> identifierOf: aPet [ +PetsRESTfulController >> identifierOf: aPet [ ^ petById keyAtValue: aPet ] { #category : #initialization } -PetsRESTfulWebService >> initialize [ +PetsRESTfulController >> initialize [ super initialize. pets := OrderedCollection new. @@ -124,13 +124,13 @@ PetsRESTfulWebService >> initialize [ ] { #category : #'private - accessing' } -PetsRESTfulWebService >> lastModificationOf: aPet [ +PetsRESTfulController >> lastModificationOf: aPet [ ^ updateTimestamps at: (self identifierOf: aPet) ] { #category : #'private - accessing' } -PetsRESTfulWebService >> locationOf: aPet [ +PetsRESTfulController >> locationOf: aPet [ | baseUrl | @@ -141,31 +141,31 @@ PetsRESTfulWebService >> locationOf: aPet [ ] { #category : #'private - accessing' } -PetsRESTfulWebService >> petIdentifiedUsing: anHttpRequest [ +PetsRESTfulController >> petIdentifiedUsing: anHttpRequest [ ^ petById at: (anHttpRequest at: #identifier) ifAbsent: [ ObjectNotFound signal ] ] { #category : #querying } -PetsRESTfulWebService >> pets [ +PetsRESTfulController >> pets [ ^ pets ] { #category : #'private - accessing' } -PetsRESTfulWebService >> provideHypermediaPolicy [ +PetsRESTfulController >> provideHypermediaPolicy [ ^ HypermediaDrivenResourcePolicy for: self ] { #category : #'private - accessing' } -PetsRESTfulWebService >> providePaginationPolicy [ +PetsRESTfulController >> providePaginationPolicy [ ^ ResourceIsPaginatedPolicy for: self with: self defaultPaginationLimit ] { #category : #'private - state management' } -PetsRESTfulWebService >> recordIdAndUpdateTimestampFor: newPet [ +PetsRESTfulController >> recordIdAndUpdateTimestampFor: newPet [ petById at: nextId put: newPet. "I will simulate a timestamp using a fixed version revision, @@ -174,13 +174,13 @@ PetsRESTfulWebService >> recordIdAndUpdateTimestampFor: newPet [ ] { #category : #accessing } -PetsRESTfulWebService >> specification [ +PetsRESTfulController >> specification [ - ^ PetsRESTfulWebServiceSpecification new + ^ PetsRESTfulControllerSpecification new ] { #category : #'private - state management' } -PetsRESTfulWebService >> updatePet: pet with: resource [ +PetsRESTfulController >> updatePet: pet with: resource [ pet synchronizeWith: @@ -192,7 +192,7 @@ PetsRESTfulWebService >> updatePet: pet with: resource [ ] { #category : #API } -PetsRESTfulWebService >> updatePetBasedOn: anHttpRequest within: aContext [ +PetsRESTfulController >> updatePetBasedOn: anHttpRequest within: aContext [ | etag | @@ -216,7 +216,7 @@ PetsRESTfulWebService >> updatePetBasedOn: anHttpRequest within: aContext [ ] { #category : #'private - accessing' } -PetsRESTfulWebService >> urlFrom: url startingAt: start limitedTo: limit [ +PetsRESTfulController >> urlFrom: url startingAt: start limitedTo: limit [ ^ url copy queryAt: 'start' put: start; diff --git a/source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st b/source/Stargate-Examples/PetsRESTfulControllerSpecification.class.st similarity index 77% rename from source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st rename to source/Stargate-Examples/PetsRESTfulControllerSpecification.class.st index 02c582b..1efd8dc 100644 --- a/source/Stargate-Examples/PetsRESTfulWebServiceSpecification.class.st +++ b/source/Stargate-Examples/PetsRESTfulControllerSpecification.class.st @@ -2,20 +2,20 @@ I'm an example RESTful Web Service specification implementing Pet resource management " Class { - #name : #PetsRESTfulWebServiceSpecification, - #superclass : #RESTFulWebServiceSpecification, + #name : #PetsRESTfulControllerSpecification, + #superclass : #ResourceRESTFulControllerSpecification, #category : #'Stargate-Examples' } { #category : #'mapping rules' } -PetsRESTfulWebServiceSpecification >> addJsonDecoderVersion1dot0dot0MappingIn: aBuilder [ +PetsRESTfulControllerSpecification >> addJsonDecoderVersion1dot0dot0MappingIn: aBuilder [ aBuilder addDefaultRuleToDecode: self petVersion1dot0dot0MediaType to: self petMappingKey using: [ :json | NeoJSONObject fromString: json ] ] { #category : #'mapping rules' } -PetsRESTfulWebServiceSpecification >> addJsonEncoderVersion1dot0dot0MappingIn: aBuilder [ +PetsRESTfulControllerSpecification >> addJsonEncoderVersion1dot0dot0MappingIn: aBuilder [ aBuilder addDefaultRuleToEncode: self petMappingKey @@ -59,73 +59,73 @@ PetsRESTfulWebServiceSpecification >> addJsonEncoderVersion1dot0dot0MappingIn: a ] { #category : #routes } -PetsRESTfulWebServiceSpecification >> createPetRoute [ +PetsRESTfulControllerSpecification >> createPetRoute [ ^ RouteSpecification handling: #POST at: self endpoint evaluating: [ :service :httpRequest :context | service createPetBasedOn: httpRequest within: context ] ] { #category : #routes } -PetsRESTfulWebServiceSpecification >> deletePetRoute [ +PetsRESTfulControllerSpecification >> deletePetRoute [ ^ RouteSpecification handling: #DELETE at: self idTemplate evaluating: [ :service :httpRequest :context | service deletePetBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } -PetsRESTfulWebServiceSpecification >> endpoint [ +PetsRESTfulControllerSpecification >> endpoint [ ^ '/pets' ] { #category : #routes } -PetsRESTfulWebServiceSpecification >> getPetRoute [ +PetsRESTfulControllerSpecification >> getPetRoute [ ^ RouteSpecification handling: #GET at: self idTemplate evaluating: [ :service :httpRequest :context | service getPetBasedOn: httpRequest within: context ] ] { #category : #routes } -PetsRESTfulWebServiceSpecification >> getPetsRoute [ +PetsRESTfulControllerSpecification >> getPetsRoute [ ^ RouteSpecification handling: #GET at: self endpoint evaluating: [ :service :httpRequest :context | service getPetsBasedOn: httpRequest within: context ] ] { #category : #'private - accessing' } -PetsRESTfulWebServiceSpecification >> idTemplate [ +PetsRESTfulControllerSpecification >> idTemplate [ ^ '<1s>/%<<2s>:IsInteger>' expandMacrosWith: self endpoint with: self identifierKey ] { #category : #accessing } -PetsRESTfulWebServiceSpecification >> identifierKey [ +PetsRESTfulControllerSpecification >> identifierKey [ ^ #identifier ] { #category : #accessing } -PetsRESTfulWebServiceSpecification >> petMappingKey [ +PetsRESTfulControllerSpecification >> petMappingKey [ ^ #pet ] { #category : #'accessing - media types' } -PetsRESTfulWebServiceSpecification >> petSummaryVersion1dot0dot0MediaType [ +PetsRESTfulControllerSpecification >> petSummaryVersion1dot0dot0MediaType [ ^ 'application/vnd.stargate.pet.summary+json;version=1.0.0' asMediaType ] { #category : #'accessing - media types' } -PetsRESTfulWebServiceSpecification >> petVersion1dot0dot0MediaType [ +PetsRESTfulControllerSpecification >> petVersion1dot0dot0MediaType [ ^ 'application/vnd.stargate.pet+json;version=1.0.0' asMediaType ] { #category : #accessing } -PetsRESTfulWebServiceSpecification >> petsMappingKey [ +PetsRESTfulControllerSpecification >> petsMappingKey [ ^ #pets ] { #category : #routes } -PetsRESTfulWebServiceSpecification >> updatePetRoute [ +PetsRESTfulControllerSpecification >> updatePetRoute [ ^ RouteSpecification handling: #PATCH at: self idTemplate evaluating: [ :service :httpRequest :context | service updatePetBasedOn: httpRequest within: context ] ] diff --git a/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st b/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st index 1327da7..a10c42a 100644 --- a/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st +++ b/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st @@ -19,7 +19,7 @@ RESTfulWebServiceAcceptNegotiatorTest >> assertBestRepresentationFor: anAcceptHe { #category : #'private - accessing' } RESTfulWebServiceAcceptNegotiatorTest >> bestRepresentationFor: anAcceptHeaderContent given: theAvailableMediaTypes [ - ^ (RESTfulWebServiceAcceptNegotiator basedOn: theAvailableMediaTypes) + ^ (RESTfulControllerAcceptNegotiator basedOn: theAvailableMediaTypes) bestRepresentationFor: ((ZnRequest get: '/example' asZnUrl) setAccept: anAcceptHeaderContent; diff --git a/source/Stargate-Model-Tests/ReflectiveRoutesConfiguratorTest.class.st b/source/Stargate-Model-Tests/ReflectiveRoutesConfiguratorTest.class.st index f8a989d..e3dd805 100644 --- a/source/Stargate-Model-Tests/ReflectiveRoutesConfiguratorTest.class.st +++ b/source/Stargate-Model-Tests/ReflectiveRoutesConfiguratorTest.class.st @@ -50,7 +50,7 @@ ReflectiveRoutesConfiguratorTest >> testConfiguringPetsWebServiceRoutes [ teapot := Teapot on. - webService := PetsRESTfulWebService new. + webService := PetsRESTfulController new. (ReflectiveRoutesConfigurator appliedTo: teapot) addRoutesOf: webService. diff --git a/source/Stargate-Model-Tests/RESTfulWebServiceTest.class.st b/source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st similarity index 57% rename from source/Stargate-Model-Tests/RESTfulWebServiceTest.class.st rename to source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st index 2727bde..d7f3c4a 100644 --- a/source/Stargate-Model-Tests/RESTfulWebServiceTest.class.st +++ b/source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st @@ -2,40 +2,40 @@ I'm an abstract Test Case providing facililties to test RESTfulWebServices " Class { - #name : #RESTfulWebServiceTest, + #name : #ResourceRESTfulControllerTest, #superclass : #TestCase, #instVars : [ - 'webService' + 'resourceController' ], #category : #'Stargate-Model-Tests-Services' } { #category : #testing } -RESTfulWebServiceTest class >> isAbstract [ +ResourceRESTfulControllerTest class >> isAbstract [ - ^ self name = #RESTfulWebServiceTest + ^ self name = #ResourceRESTfulControllerTest ] { #category : #'private - asserting' } -RESTfulWebServiceTest >> assertUrl: aStringOrUrl equals: anotherStringOrUrl [ +ResourceRESTfulControllerTest >> assertUrl: aStringOrUrl equals: anotherStringOrUrl [ self assert: aStringOrUrl asZnUrl equals: anotherStringOrUrl asZnUrl ] { #category : #'private - support' } -RESTfulWebServiceTest >> baseUrl [ +ResourceRESTfulControllerTest >> baseUrl [ ^ self subclassResponsibility ] { #category : #'private - support' } -RESTfulWebServiceTest >> newHttpRequestContext [ +ResourceRESTfulControllerTest >> newHttpRequestContext [ ^ HttpRequestContext new ] { #category : #'private - support' } -RESTfulWebServiceTest >> requestToGetResourceIdentifiedBy: anIdentifier accepting: anAcceptHeader [ +ResourceRESTfulControllerTest >> requestToGetResourceIdentifiedBy: anIdentifier accepting: anAcceptHeader [ ^ TeaRequest fromZnRequest: @@ -46,7 +46,7 @@ RESTfulWebServiceTest >> requestToGetResourceIdentifiedBy: anIdentifier acceptin ] { #category : #'private - support' } -RESTfulWebServiceTest >> requestToGetResourceIdentifiedBy: anIdentifier accepting: anAcceptHeader conditionalTo: anETag [ +ResourceRESTfulControllerTest >> requestToGetResourceIdentifiedBy: anIdentifier accepting: anAcceptHeader conditionalTo: anETag [ ^ TeaRequest fromZnRequest: @@ -58,7 +58,7 @@ RESTfulWebServiceTest >> requestToGetResourceIdentifiedBy: anIdentifier acceptin ] { #category : #'private - support' } -RESTfulWebServiceTest >> requestToPOST: content as: aMediaType [ +ResourceRESTfulControllerTest >> requestToPOST: content as: aMediaType [ ^ TeaRequest fromZnRequest: @@ -68,33 +68,33 @@ RESTfulWebServiceTest >> requestToPOST: content as: aMediaType [ ] { #category : #'private - support' } -RESTfulWebServiceTest >> resourceUrl [ +ResourceRESTfulControllerTest >> resourceUrl [ - ^ self baseUrl / webService specification endpoint + ^ self baseUrl / resourceController specification endpoint ] { #category : #running } -RESTfulWebServiceTest >> setUp [ +ResourceRESTfulControllerTest >> setUp [ super setUp. - self setUpWebService. - webService serverUrl: self baseUrl asZnUrl + self setUpResourceController. + resourceController serverUrl: self baseUrl asZnUrl ] { #category : #running } -RESTfulWebServiceTest >> setUpWebService [ +ResourceRESTfulControllerTest >> setUpResourceController [ self subclassResponsibility ] { #category : #'private - support' } -RESTfulWebServiceTest >> urlForResourceIdentifiedBy: anIdentifier [ +ResourceRESTfulControllerTest >> urlForResourceIdentifiedBy: anIdentifier [ ^ self resourceUrl / anIdentifier printString asZnUrl ] { #category : #'private - support' } -RESTfulWebServiceTest >> withJsonFromContentsIn: httpResponse do: aBlock [ +ResourceRESTfulControllerTest >> withJsonFromContentsIn: httpResponse do: aBlock [ aBlock value: (NeoJSONObject fromString: httpResponse contents) ] diff --git a/source/Stargate-Model/HTTPBasedRESTfulAPI.class.st b/source/Stargate-Model/HTTPBasedRESTfulAPI.class.st index b75cec9..91c00ba 100644 --- a/source/Stargate-Model/HTTPBasedRESTfulAPI.class.st +++ b/source/Stargate-Model/HTTPBasedRESTfulAPI.class.st @@ -6,16 +6,16 @@ Class { #superclass : #Object, #instVars : [ 'teapotServer', - 'services' + 'controllers' ], - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Controllers' } { #category : #'instance creation' } -HTTPBasedRESTfulAPI class >> configuredBy: configuration installing: aServicesCollection [ +HTTPBasedRESTfulAPI class >> configuredBy: configuration installing: aRESTfulControllerCollection [ - AssertionChecker enforce: [ aServicesCollection notEmpty ] because: 'An API needs at least to expose one service'. - ^ self new initializeConfiguredBy: configuration installing: aServicesCollection + AssertionChecker enforce: [ aRESTfulControllerCollection notEmpty ] because: 'An API needs at least to expose one resource'. + ^ self new initializeConfiguredBy: configuration installing: aRESTfulControllerCollection ] { #category : #configuring } @@ -60,14 +60,14 @@ HTTPBasedRESTfulAPI >> configureRoutes [ | configurator | configurator := ReflectiveRoutesConfigurator appliedTo: teapotServer. - services do: [ :service | configurator addRoutesOf: service ] + controllers do: [ :controller | configurator addRoutesOf: controller ] ] { #category : #initialization } -HTTPBasedRESTfulAPI >> initializeConfiguredBy: configuration installing: aServicesCollection [ +HTTPBasedRESTfulAPI >> initializeConfiguredBy: configuration installing: aRESTfulControllerCollection [ teapotServer := Teapot configure: configuration. - services := aServicesCollection + controllers := aRESTfulControllerCollection ] { #category : #actions } diff --git a/source/Stargate-Model/HTTPClientError.class.st b/source/Stargate-Model/HTTPClientError.class.st index fe1519f..65c5e04 100644 --- a/source/Stargate-Model/HTTPClientError.class.st +++ b/source/Stargate-Model/HTTPClientError.class.st @@ -4,7 +4,7 @@ I'm an exception expecting to be raised when someone makes an incorrect HTTP req Class { #name : #HTTPClientError, #superclass : #Error, - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Controllers' } { #category : #signaling } diff --git a/source/Stargate-Model/HTTPNotAcceptable.class.st b/source/Stargate-Model/HTTPNotAcceptable.class.st index 3c22961..a55343b 100644 --- a/source/Stargate-Model/HTTPNotAcceptable.class.st +++ b/source/Stargate-Model/HTTPNotAcceptable.class.st @@ -17,7 +17,7 @@ Class { #instVars : [ 'allowedMediaTypes' ], - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Controllers' } { #category : #'instance creation' } diff --git a/source/Stargate-Model/RESTfulWebServiceAcceptNegotiator.class.st b/source/Stargate-Model/RESTfulControllerAcceptNegotiator.class.st similarity index 82% rename from source/Stargate-Model/RESTfulWebServiceAcceptNegotiator.class.st rename to source/Stargate-Model/RESTfulControllerAcceptNegotiator.class.st index 1d14725..3a3ea7c 100644 --- a/source/Stargate-Model/RESTfulWebServiceAcceptNegotiator.class.st +++ b/source/Stargate-Model/RESTfulControllerAcceptNegotiator.class.st @@ -2,22 +2,22 @@ I will provide the best representation (media type) to use for processing an HTTP Request given an available media type list " Class { - #name : #RESTfulWebServiceAcceptNegotiator, + #name : #RESTfulControllerAcceptNegotiator, #superclass : #Object, #instVars : [ 'availableMediaTypes' ], - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Controllers' } { #category : #'instance creation' } -RESTfulWebServiceAcceptNegotiator class >> basedOn: aMediaTypeCollection [ +RESTfulControllerAcceptNegotiator class >> basedOn: aMediaTypeCollection [ ^ self new initializeBasedOn: aMediaTypeCollection ] { #category : #querying } -RESTfulWebServiceAcceptNegotiator >> bestRepresentationFor: anHttpRequest [ +RESTfulControllerAcceptNegotiator >> bestRepresentationFor: anHttpRequest [ "This method returns the best suited representation for the given request" @@ -26,13 +26,13 @@ RESTfulWebServiceAcceptNegotiator >> bestRepresentationFor: anHttpRequest [ ] { #category : #'initialize - release' } -RESTfulWebServiceAcceptNegotiator >> initializeBasedOn: aMediaTypeCollection [ +RESTfulControllerAcceptNegotiator >> initializeBasedOn: aMediaTypeCollection [ availableMediaTypes := aMediaTypeCollection ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiator >> mediaTypesAvailableFor: aMediaType [ +RESTfulControllerAcceptNegotiator >> mediaTypesAvailableFor: aMediaType [ ^ availableMediaTypes select: [ :available | @@ -41,7 +41,7 @@ RESTfulWebServiceAcceptNegotiator >> mediaTypesAvailableFor: aMediaType [ ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiator >> precedenceFor: aMediaType [ +RESTfulControllerAcceptNegotiator >> precedenceFor: aMediaType [ | precedence version versionParts | @@ -57,17 +57,18 @@ RESTfulWebServiceAcceptNegotiator >> precedenceFor: aMediaType [ versionParts := version splitOn: $.. precedence := precedence + versionParts size. versionParts doWithIndex: [ :part :index | precedence := precedence + (part asInteger * (2 raisedTo: 4 - index)) ]. + ^ precedence ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiator >> sortByPrecedence: mediaTypes [ +RESTfulControllerAcceptNegotiator >> sortByPrecedence: mediaTypes [ ^ (mediaTypes sorted: [ :a :b | (self precedenceFor: a) < (self precedenceFor: b) ]) reversed ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiator >> versionIn: acceptable canBeHandledBy: available [ +RESTfulControllerAcceptNegotiator >> versionIn: acceptable canBeHandledBy: available [ | acceptVersion availableVersion acceptVersionParts availableVersionParts | @@ -85,7 +86,7 @@ RESTfulWebServiceAcceptNegotiator >> versionIn: acceptable canBeHandledBy: avail ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiator >> withAcceptableMediaTypesIn: anHttpRequest do: aBlock [ +RESTfulControllerAcceptNegotiator >> withAcceptableMediaTypesIn: anHttpRequest do: aBlock [ | acceptable grouped | diff --git a/source/Stargate-Model/ReflectiveMappingRuleSetBuilder.class.st b/source/Stargate-Model/ReflectiveMappingRuleSetBuilder.class.st index 3989dfa..3ac572a 100644 --- a/source/Stargate-Model/ReflectiveMappingRuleSetBuilder.class.st +++ b/source/Stargate-Model/ReflectiveMappingRuleSetBuilder.class.st @@ -13,9 +13,9 @@ Class { } { #category : #'instance creation' } -ReflectiveMappingRuleSetBuilder class >> for: aWebServiceSpecification [ +ReflectiveMappingRuleSetBuilder class >> for: aResourceRESTfulControllerSpecification [ - ^ self new initializeFor: aWebServiceSpecification + ^ self new initializeFor: aResourceRESTfulControllerSpecification ] { #category : #building } @@ -35,7 +35,7 @@ ReflectiveMappingRuleSetBuilder >> build [ ] { #category : #initialization } -ReflectiveMappingRuleSetBuilder >> initializeFor: aWebServiceSpecification [ +ReflectiveMappingRuleSetBuilder >> initializeFor: aResourceRESTfulControllerSpecification [ - specification := aWebServiceSpecification + specification := aResourceRESTfulControllerSpecification ] diff --git a/source/Stargate-Model/ReflectiveRoutesConfigurator.class.st b/source/Stargate-Model/ReflectiveRoutesConfigurator.class.st index f2942c3..9b39745 100644 --- a/source/Stargate-Model/ReflectiveRoutesConfigurator.class.st +++ b/source/Stargate-Model/ReflectiveRoutesConfigurator.class.st @@ -19,12 +19,12 @@ ReflectiveRoutesConfigurator class >> appliedTo: aTeapot [ ] { #category : #configuring } -ReflectiveRoutesConfigurator >> addRoutesOf: aWebService [ +ReflectiveRoutesConfigurator >> addRoutesOf: aResourceRESTfulController [ | routeConfigurator | - routeConfigurator := RouteConfigurator appliedTo: teapot sendingMessagesTo: aWebService. - aWebService specification routes do: [ :routeSpecification | routeSpecification configureUsing: routeConfigurator ]. + routeConfigurator := RouteConfigurator appliedTo: teapot sendingMessagesTo: aResourceRESTfulController. + aResourceRESTfulController specification routes do: [ :routeSpecification | routeSpecification configureUsing: routeConfigurator ]. routeConfigurator configureCrossOriginSharingRoutes ] diff --git a/source/Stargate-Model/RESTFulWebServiceSpecification.class.st b/source/Stargate-Model/ResourceRESTFulControllerSpecification.class.st similarity index 70% rename from source/Stargate-Model/RESTFulWebServiceSpecification.class.st rename to source/Stargate-Model/ResourceRESTFulControllerSpecification.class.st index 0438824..569bf66 100644 --- a/source/Stargate-Model/RESTFulWebServiceSpecification.class.st +++ b/source/Stargate-Model/ResourceRESTFulControllerSpecification.class.st @@ -5,25 +5,25 @@ I provide the supported mediaTypes for the service to be used during content neg I provide a set of routes to be used to configure Teapot. " Class { - #name : #RESTFulWebServiceSpecification, + #name : #ResourceRESTFulControllerSpecification, #superclass : #Object, - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Controllers' } { #category : #acccessing } -RESTFulWebServiceSpecification >> mappingRuleSet [ +ResourceRESTFulControllerSpecification >> mappingRuleSet [ ^ (ReflectiveMappingRuleSetBuilder for: self) build ] { #category : #acccessing } -RESTFulWebServiceSpecification >> mediaTypes [ +ResourceRESTFulControllerSpecification >> mediaTypes [ ^ (UnaryMessageSendingCollector sendingAllMessagesEndingWith: 'MediaType' to: self) value ] { #category : #acccessing } -RESTFulWebServiceSpecification >> routes [ +ResourceRESTFulControllerSpecification >> routes [ ^ (UnaryMessageSendingCollector sendingAllMessagesEndingWith: 'Route' to: self) value ] diff --git a/source/Stargate-Model/RESTfulWebService.class.st b/source/Stargate-Model/ResourceRESTfulController.class.st similarity index 73% rename from source/Stargate-Model/RESTfulWebService.class.st rename to source/Stargate-Model/ResourceRESTfulController.class.st index 5ab5c6b..f8cbb86 100644 --- a/source/Stargate-Model/RESTfulWebService.class.st +++ b/source/Stargate-Model/ResourceRESTfulController.class.st @@ -6,7 +6,7 @@ I provide a way to encode/decode the resources into the representations produced I also provide standard error handling and templates for processing the differente HTTP verbs. " Class { - #name : #RESTfulWebService, + #name : #ResourceRESTfulController, #superclass : #Object, #instVars : [ 'mappingRuleSet', @@ -15,18 +15,18 @@ Class { 'paginationPolicy', 'hypermediaPolicy' ], - #category : #'Stargate-Model-Services' + #category : #'Stargate-Model-Controllers' } { #category : #'private - asserting' } -RESTfulWebService >> assert: etag matchesEntityTagOf: entity encodedAs: mediaType [ +ResourceRESTfulController >> assert: etag matchesEntityTagOf: entity encodedAs: mediaType [ (etag = (self entityTagOf: entity encodedAs: mediaType)) ifFalse: [ HTTPClientError signalPreconditionFailed ] ] { #category : #'private - transformations' } -RESTfulWebService >> decode: theRepresentation at: aKey from: sourceMediaType within: aContext [ +ResourceRESTfulController >> decode: theRepresentation at: aKey from: sourceMediaType within: aContext [ ^ [ [ (mappingRuleSet ruleToDecode: sourceMediaType to: aKey) applyOn: theRepresentation within: aContext ] on: KeyNotFound , NeoJSONParseError @@ -36,7 +36,7 @@ RESTfulWebService >> decode: theRepresentation at: aKey from: sourceMediaType wi ] { #category : #'private - transformations' } -RESTfulWebService >> encode: theResource at: aKey to: targetMediaType within: aContext [ +ResourceRESTfulController >> encode: theResource at: aKey to: targetMediaType within: aContext [ ^ [ (mappingRuleSet ruleToEncode: aKey to: targetMediaType) applyOn: theResource @@ -46,19 +46,19 @@ RESTfulWebService >> encode: theResource at: aKey to: targetMediaType within: aC ] { #category : #'private - accessing' } -RESTfulWebService >> entityTagOf: resource encodedAs: mediaType [ +ResourceRESTfulController >> entityTagOf: resource encodedAs: mediaType [ self subclassResponsibility ] { #category : #'private - accessing' } -RESTfulWebService >> entityTagToMatchBasedOn: anHttpRequest [ +ResourceRESTfulController >> entityTagToMatchBasedOn: anHttpRequest [ ^ (anHttpRequest headers at: #'If-Match' ifAbsent: [ HTTPClientError signalPreconditionRequired: 'Missing If-Match header.' ]) asETag ] { #category : #'private - querying' } -RESTfulWebService >> evaluateQuery: aQueryEvaluationBlock [ +ResourceRESTfulController >> evaluateQuery: aQueryEvaluationBlock [ ^ [ [ aQueryEvaluationBlock value ] on: TeaNoSuchParam @@ -68,7 +68,7 @@ RESTfulWebService >> evaluateQuery: aQueryEvaluationBlock [ ] { #category : #'private - API' } -RESTfulWebService >> get: aQueryEvaluationBlock asCollectionEncodedUsing: aKey basedOn: anHttpRequest within: aContext [ +ResourceRESTfulController >> get: aQueryEvaluationBlock asCollectionEncodedUsing: aKey basedOn: anHttpRequest within: aContext [ | mediaType | @@ -92,7 +92,7 @@ RESTfulWebService >> get: aQueryEvaluationBlock asCollectionEncodedUsing: aKey b ] { #category : #'private - API' } -RESTfulWebService >> get: aQueryEvaluationBlock encodedUsing: aKey basedOn: anHttpRequest within: aContext [ +ResourceRESTfulController >> get: aQueryEvaluationBlock encodedUsing: aKey basedOn: anHttpRequest within: aContext [ | mediaType resource response | @@ -121,7 +121,7 @@ RESTfulWebService >> get: aQueryEvaluationBlock encodedUsing: aKey basedOn: anHt ] { #category : #'private - transformations' } -RESTfulWebService >> handleConflictsIn: aBlock [ +ResourceRESTfulController >> handleConflictsIn: aBlock [ ^ aBlock on: ConflictingObjectFound @@ -129,84 +129,84 @@ RESTfulWebService >> handleConflictsIn: aBlock [ ] { #category : #'private - accessing' } -RESTfulWebService >> hypermediaPolicy [ +ResourceRESTfulController >> hypermediaPolicy [ hypermediaPolicy ifNil: [ hypermediaPolicy := self provideHypermediaPolicy ]. ^ hypermediaPolicy ] { #category : #'private - accessing' } -RESTfulWebService >> ifNoneMatchHeaderPresentIn: anHttpRequest do: aMonadycBlock [ +ResourceRESTfulController >> ifNoneMatchHeaderPresentIn: anHttpRequest do: aMonadycBlock [ anHttpRequest headers at: #'If-None-Match' ifPresent: [ :ifNoneMatchHeader | aMonadycBlock value: ifNoneMatchHeader asETag ] ] { #category : #initialization } -RESTfulWebService >> initialize [ +ResourceRESTfulController >> initialize [ super initialize. mappingRuleSet := self specification mappingRuleSet. baseUrlOptional := Optional unused. - acceptNegotiator := RESTfulWebServiceAcceptNegotiator basedOn: self specification mediaTypes + acceptNegotiator := RESTfulControllerAcceptNegotiator basedOn: self specification mediaTypes ] { #category : #'private - accessing' } -RESTfulWebService >> locationOf: resource [ +ResourceRESTfulController >> locationOf: resource [ self subclassResponsibility ] { #category : #'private - accessing' } -RESTfulWebService >> mediaControlsFor: result [ +ResourceRESTfulController >> mediaControlsFor: result [ ^ {'self' -> (self locationOf: result)} ] { #category : #'private - accessing' } -RESTfulWebService >> paginationPolicy [ +ResourceRESTfulController >> paginationPolicy [ paginationPolicy ifNil: [ paginationPolicy := self providePaginationPolicy ]. ^ paginationPolicy ] { #category : #'private - accessing' } -RESTfulWebService >> provideHypermediaPolicy [ +ResourceRESTfulController >> provideHypermediaPolicy [ ^ self subclassResponsibility ] { #category : #'private - accessing' } -RESTfulWebService >> providePaginationPolicy [ +ResourceRESTfulController >> providePaginationPolicy [ ^ self subclassResponsibility ] { #category : #'private - API' } -RESTfulWebService >> putEntityTagOf: resource encodedAs: mediaType in: response [ +ResourceRESTfulController >> putEntityTagOf: resource encodedAs: mediaType in: response [ response setEntityTag: (self entityTagOf: resource encodedAs: mediaType) ] { #category : #configuring } -RESTfulWebService >> serverUrl: aServerUrl [ +ResourceRESTfulController >> serverUrl: aServerUrl [ baseUrlOptional := Optional containing: aServerUrl asZnUrl ] { #category : #specification } -RESTfulWebService >> specification [ +ResourceRESTfulController >> specification [ ^ self subclassResponsibility ] { #category : #'private - transformations' } -RESTfulWebService >> targetMediaTypeFrom: anHttpRequest [ +ResourceRESTfulController >> targetMediaTypeFrom: anHttpRequest [ ^ acceptNegotiator bestRepresentationFor: anHttpRequest ] { #category : #'private - API' } -RESTfulWebService >> withCreatedResourceDo: aBlock decodedUsing: aKey basedOn: anHttpRequest within: aContext [ +ResourceRESTfulController >> withCreatedResourceDo: aBlock decodedUsing: aKey basedOn: anHttpRequest within: aContext [ | decodedRepresentation newResource | diff --git a/source/Stargate-Model/RouteConfigurator.class.st b/source/Stargate-Model/RouteConfigurator.class.st index 24298a7..d58d446 100644 --- a/source/Stargate-Model/RouteConfigurator.class.st +++ b/source/Stargate-Model/RouteConfigurator.class.st @@ -8,16 +8,16 @@ Class { #superclass : #Object, #instVars : [ 'teapot', - 'webService', - 'routesAllowingCors' + 'routesAllowingCors', + 'resourceController' ], #category : #'Stargate-Model-Routing' } { #category : #'instance creation' } -RouteConfigurator class >> appliedTo: aTeapot sendingMessagesTo: aWebService [ +RouteConfigurator class >> appliedTo: aTeapot sendingMessagesTo: aResourceRESTfulController [ - ^ self new initializeAppliedTo: aTeapot sendingMessagesTo: aWebService + ^ self new initializeAppliedTo: aTeapot sendingMessagesTo: aResourceRESTfulController ] { #category : #'private - configuring' } @@ -53,14 +53,14 @@ RouteConfigurator >> configureRouteFrom: aRouteSpecification [ perform: ('<1s>:' expandMacrosWith: aRouteSpecification httpMethod) asSymbol with: aRouteSpecification urlTemplate - -> [ :request | aRouteSpecification handler value: webService value: request value: HttpRequestContext new ] + -> [ :request | aRouteSpecification handler value: resourceController value: request value: HttpRequestContext new ] ] { #category : #initialization } -RouteConfigurator >> initializeAppliedTo: aTeapot sendingMessagesTo: aWebService [ +RouteConfigurator >> initializeAppliedTo: aTeapot sendingMessagesTo: aResourceRESTfulController [ teapot := aTeapot. - webService := aWebService. - teapot server serverUrl ifNotNil: [ :url | webService serverUrl: url ]. + resourceController := aResourceRESTfulController. + teapot server serverUrl ifNotNil: [ :url | resourceController serverUrl: url ]. routesAllowingCors := Dictionary new ] From c7d94cc2b1869815bdca72f81d88b4a5a373fd05 Mon Sep 17 00:00:00 2001 From: Gabriel Omar Cotelli Date: Mon, 5 Nov 2018 16:48:28 -0300 Subject: [PATCH 4/6] Added tests --- ...ersRESTfulControllerSpecification.class.st | 2 +- .../HTTPClientErrorTest.class.st | 2 +- .../NoHypermediaResourcePolicyTest.class.st | 22 +++++++++++++ .../PaginationSpecTest.class.st | 2 +- ...fulWebServiceAcceptNegotiatorTest.class.st | 2 +- .../ResourceNotPaginatedPolicyTest.class.st | 31 +++++++++++++++++++ .../ResourceRESTfulControllerTest.class.st | 2 +- 7 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st create mode 100644 source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st diff --git a/source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st b/source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st index 8a00a03..03aa7ed 100644 --- a/source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st +++ b/source/Stargate-Examples/PetOrdersRESTfulControllerSpecification.class.st @@ -38,7 +38,7 @@ PetOrdersRESTfulControllerSpecification >> addJsonEncoderVersion1dot0dot0Mapping do: [ :mapping | mapping mapInstVars; - mapProperty: #status getter: [ :object | context objectUnder: #status ifNone: [ '' ] ] setter: [ :object :value | ]; + mapProperty: #status getter: [ :object | context objectUnder: #status ] setter: [ :object :value | ]; mapHypermediaControlsIn: context ]; nextPut: order ] ] ] diff --git a/source/Stargate-Model-Tests/HTTPClientErrorTest.class.st b/source/Stargate-Model-Tests/HTTPClientErrorTest.class.st index 4ad9014..55bc31e 100644 --- a/source/Stargate-Model-Tests/HTTPClientErrorTest.class.st +++ b/source/Stargate-Model-Tests/HTTPClientErrorTest.class.st @@ -4,7 +4,7 @@ A HTTPClientErrorTest is a test class for testing the behavior of HTTPClientErro Class { #name : #HTTPClientErrorTest, #superclass : #TestCase, - #category : #'Stargate-Model-Tests-Services' + #category : #'Stargate-Model-Tests-Controllers' } { #category : #tests } diff --git a/source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st b/source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st new file mode 100644 index 0000000..8bd1a48 --- /dev/null +++ b/source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st @@ -0,0 +1,22 @@ +" +Unit test +" +Class { + #name : #NoHypermediaResourcePolicyTest, + #superclass : #TestCase, + #category : #'Stargate-Model-Tests-Controllers' +} + +{ #category : #tests } +NoHypermediaResourcePolicyTest >> testBehavior [ + + | policy context | + + context := HttpRequestContext new. + policy := NoHypermediaResourcePolicy new. + policy holdResource: 1 controlsWithin: context. + self assert: context hypermediaControls isEmpty. + + policy holdCollection: #() controlsBasedOn: ZnRequest new within: context. + self assert: context hypermediaControls isEmpty +] diff --git a/source/Stargate-Model-Tests/PaginationSpecTest.class.st b/source/Stargate-Model-Tests/PaginationSpecTest.class.st index b993790..9bf7319 100644 --- a/source/Stargate-Model-Tests/PaginationSpecTest.class.st +++ b/source/Stargate-Model-Tests/PaginationSpecTest.class.st @@ -4,7 +4,7 @@ I'm a Test Case for PaginationSpec Class { #name : #PaginationSpecTest, #superclass : #TestCase, - #category : #'Stargate-Model-Tests-Services' + #category : #'Stargate-Model-Tests-Pagination' } { #category : #tests } diff --git a/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st b/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st index a10c42a..97558ba 100644 --- a/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st +++ b/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st @@ -7,7 +7,7 @@ Class { #instVars : [ 'apiMediaTypes' ], - #category : #'Stargate-Model-Tests-Services' + #category : #'Stargate-Model-Tests-Controllers' } { #category : #'private - asserting' } diff --git a/source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st b/source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st new file mode 100644 index 0000000..d171a76 --- /dev/null +++ b/source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st @@ -0,0 +1,31 @@ +" +Unit Test +" +Class { + #name : #ResourceNotPaginatedPolicyTest, + #superclass : #TestCase, + #category : #'Stargate-Model-Tests-Pagination' +} + +{ #category : #private } +ResourceNotPaginatedPolicyTest >> evaluateQuery: aBlockClosure [ + + ^ aBlockClosure value +] + +{ #category : #tests } +ResourceNotPaginatedPolicyTest >> testBehavior [ + + | policy context controls response | + + context := HttpRequestContext new. + controls := #(). + policy := ResourceNotPaginatedPolicy for: self. + self assert: (policy addPaginationControlsTo: controls within: context) isEmpty. + + response := ZnResponse noContent. + policy affect: response within: context. + self assert: response links isEmpty. + + self assert: (policy evaluateQuery: [ 23 ] basedOn: ZnRequest new) equals: 23 +] diff --git a/source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st b/source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st index d7f3c4a..12176a7 100644 --- a/source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st +++ b/source/Stargate-Model-Tests/ResourceRESTfulControllerTest.class.st @@ -7,7 +7,7 @@ Class { #instVars : [ 'resourceController' ], - #category : #'Stargate-Model-Tests-Services' + #category : #'Stargate-Model-Tests-Controllers' } { #category : #testing } From c919fe0343a96407e92e061a5cc4aa972cfca9c6 Mon Sep 17 00:00:00 2001 From: Gabriel Omar Cotelli Date: Mon, 5 Nov 2018 17:02:03 -0300 Subject: [PATCH 5/6] Removed unused methods --- .../Stargate-Examples/PetOrdersRESTfulController.class.st | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/source/Stargate-Examples/PetOrdersRESTfulController.class.st b/source/Stargate-Examples/PetOrdersRESTfulController.class.st index 4a85690..b0af214 100644 --- a/source/Stargate-Examples/PetOrdersRESTfulController.class.st +++ b/source/Stargate-Examples/PetOrdersRESTfulController.class.st @@ -40,12 +40,6 @@ PetOrdersRESTfulController >> createOrderBasedOn: anHttpRequest within: aContext within: aContext ] -{ #category : #'private - accessing' } -PetOrdersRESTfulController >> defaultPaginationLimit [ - - ^ 10 -] - { #category : #'private - accessing' } PetOrdersRESTfulController >> entityTagOf: aPetOrder encodedAs: mediaType [ @@ -148,7 +142,7 @@ PetOrdersRESTfulController >> provideHypermediaPolicy [ { #category : #'private - accessing' } PetOrdersRESTfulController >> providePaginationPolicy [ - ^ ResourceIsPaginatedPolicy for: self with: self defaultPaginationLimit + ^ ResourceNotPaginatedPolicy for: self ] { #category : #'private - API' } From 598288e8e0db3075540c41035da1111d53e12bda Mon Sep 17 00:00:00 2001 From: Gabriel Omar Cotelli Date: Tue, 6 Nov 2018 10:42:18 -0300 Subject: [PATCH 6/6] Made some renames --- .../PetOrdersRESTfulController.class.st | 4 +- .../PetsRESTfulController.class.st | 4 +- ...rivenRESTfulControllerPolicyTest.class.st} | 6 +-- ...NotPaginateCollectionsPolicyTest.class.st} | 8 ++-- ...ulControllerAcceptNegotiatorTest.class.st} | 20 +++++----- ...diaDrivenRESTfulControllerPolicy.class.st} | 13 ++++--- .../Stargate-Model/HypermediaPolicy.class.st | 3 ++ .../NoHypermediaResourcePolicy.class.st | 13 ------- ...ediaDrivenRESTfulControllerPolicy.class.st | 16 ++++++++ ...lerDoNotPaginateCollectionsPolicy.class.st | 39 +++++++++++++++++++ ...trollerPaginateCollectionsPolicy.class.st} | 21 +++++----- ...RESTfulControllerPaginationPolicy.class.st | 26 +++++++++++++ .../ResourceNotPaginatedPolicy.class.st | 36 ----------------- .../ResourcePaginationPolicy.class.st | 23 ----------- 14 files changed, 125 insertions(+), 107 deletions(-) rename source/Stargate-Model-Tests/{NoHypermediaResourcePolicyTest.class.st => NonHypermediaDrivenRESTfulControllerPolicyTest.class.st} (69%) rename source/Stargate-Model-Tests/{ResourceNotPaginatedPolicyTest.class.st => RESTFullControllerDoNotPaginateCollectionsPolicyTest.class.st} (65%) rename source/Stargate-Model-Tests/{RESTfulWebServiceAcceptNegotiatorTest.class.st => RESTfulControllerAcceptNegotiatorTest.class.st} (88%) rename source/Stargate-Model/{HypermediaDrivenResourcePolicy.class.st => HypermediaDrivenRESTfulControllerPolicy.class.st} (60%) delete mode 100644 source/Stargate-Model/NoHypermediaResourcePolicy.class.st create mode 100644 source/Stargate-Model/NonHypermediaDrivenRESTfulControllerPolicy.class.st create mode 100644 source/Stargate-Model/RESTFullControllerDoNotPaginateCollectionsPolicy.class.st rename source/Stargate-Model/{ResourceIsPaginatedPolicy.class.st => RESTFullControllerPaginateCollectionsPolicy.class.st} (51%) create mode 100644 source/Stargate-Model/RESTfulControllerPaginationPolicy.class.st delete mode 100644 source/Stargate-Model/ResourceNotPaginatedPolicy.class.st delete mode 100644 source/Stargate-Model/ResourcePaginationPolicy.class.st diff --git a/source/Stargate-Examples/PetOrdersRESTfulController.class.st b/source/Stargate-Examples/PetOrdersRESTfulController.class.st index b0af214..d681226 100644 --- a/source/Stargate-Examples/PetOrdersRESTfulController.class.st +++ b/source/Stargate-Examples/PetOrdersRESTfulController.class.st @@ -136,13 +136,13 @@ PetOrdersRESTfulController >> orders [ { #category : #'private - accessing' } PetOrdersRESTfulController >> provideHypermediaPolicy [ - ^ HypermediaDrivenResourcePolicy for: self + ^ HypermediaDrivenRESTfulControllerPolicy for: self ] { #category : #'private - accessing' } PetOrdersRESTfulController >> providePaginationPolicy [ - ^ ResourceNotPaginatedPolicy for: self + ^ RESTFullControllerDoNotPaginateCollectionsPolicy for: self ] { #category : #'private - API' } diff --git a/source/Stargate-Examples/PetsRESTfulController.class.st b/source/Stargate-Examples/PetsRESTfulController.class.st index 6afc280..23ebf02 100644 --- a/source/Stargate-Examples/PetsRESTfulController.class.st +++ b/source/Stargate-Examples/PetsRESTfulController.class.st @@ -155,13 +155,13 @@ PetsRESTfulController >> pets [ { #category : #'private - accessing' } PetsRESTfulController >> provideHypermediaPolicy [ - ^ HypermediaDrivenResourcePolicy for: self + ^ HypermediaDrivenRESTfulControllerPolicy for: self ] { #category : #'private - accessing' } PetsRESTfulController >> providePaginationPolicy [ - ^ ResourceIsPaginatedPolicy for: self with: self defaultPaginationLimit + ^ RESTFullControllerPaginateCollectionsPolicy for: self with: self defaultPaginationLimit ] { #category : #'private - state management' } diff --git a/source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st b/source/Stargate-Model-Tests/NonHypermediaDrivenRESTfulControllerPolicyTest.class.st similarity index 69% rename from source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st rename to source/Stargate-Model-Tests/NonHypermediaDrivenRESTfulControllerPolicyTest.class.st index 8bd1a48..e763bb4 100644 --- a/source/Stargate-Model-Tests/NoHypermediaResourcePolicyTest.class.st +++ b/source/Stargate-Model-Tests/NonHypermediaDrivenRESTfulControllerPolicyTest.class.st @@ -2,18 +2,18 @@ Unit test " Class { - #name : #NoHypermediaResourcePolicyTest, + #name : #NonHypermediaDrivenRESTfulControllerPolicyTest, #superclass : #TestCase, #category : #'Stargate-Model-Tests-Controllers' } { #category : #tests } -NoHypermediaResourcePolicyTest >> testBehavior [ +NonHypermediaDrivenRESTfulControllerPolicyTest >> testBehavior [ | policy context | context := HttpRequestContext new. - policy := NoHypermediaResourcePolicy new. + policy := NonHypermediaDrivenRESTfulControllerPolicy new. policy holdResource: 1 controlsWithin: context. self assert: context hypermediaControls isEmpty. diff --git a/source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st b/source/Stargate-Model-Tests/RESTFullControllerDoNotPaginateCollectionsPolicyTest.class.st similarity index 65% rename from source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st rename to source/Stargate-Model-Tests/RESTFullControllerDoNotPaginateCollectionsPolicyTest.class.st index d171a76..3a2897a 100644 --- a/source/Stargate-Model-Tests/ResourceNotPaginatedPolicyTest.class.st +++ b/source/Stargate-Model-Tests/RESTFullControllerDoNotPaginateCollectionsPolicyTest.class.st @@ -2,25 +2,25 @@ Unit Test " Class { - #name : #ResourceNotPaginatedPolicyTest, + #name : #RESTFullControllerDoNotPaginateCollectionsPolicyTest, #superclass : #TestCase, #category : #'Stargate-Model-Tests-Pagination' } { #category : #private } -ResourceNotPaginatedPolicyTest >> evaluateQuery: aBlockClosure [ +RESTFullControllerDoNotPaginateCollectionsPolicyTest >> evaluateQuery: aBlockClosure [ ^ aBlockClosure value ] { #category : #tests } -ResourceNotPaginatedPolicyTest >> testBehavior [ +RESTFullControllerDoNotPaginateCollectionsPolicyTest >> testBehavior [ | policy context controls response | context := HttpRequestContext new. controls := #(). - policy := ResourceNotPaginatedPolicy for: self. + policy := RESTFullControllerDoNotPaginateCollectionsPolicy for: self. self assert: (policy addPaginationControlsTo: controls within: context) isEmpty. response := ZnResponse noContent. diff --git a/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st b/source/Stargate-Model-Tests/RESTfulControllerAcceptNegotiatorTest.class.st similarity index 88% rename from source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st rename to source/Stargate-Model-Tests/RESTfulControllerAcceptNegotiatorTest.class.st index 97558ba..e189e8b 100644 --- a/source/Stargate-Model-Tests/RESTfulWebServiceAcceptNegotiatorTest.class.st +++ b/source/Stargate-Model-Tests/RESTfulControllerAcceptNegotiatorTest.class.st @@ -2,7 +2,7 @@ I'm a Test Case for AcceptNegotiator " Class { - #name : #RESTfulWebServiceAcceptNegotiatorTest, + #name : #RESTfulControllerAcceptNegotiatorTest, #superclass : #TestCase, #instVars : [ 'apiMediaTypes' @@ -11,13 +11,13 @@ Class { } { #category : #'private - asserting' } -RESTfulWebServiceAcceptNegotiatorTest >> assertBestRepresentationFor: anAcceptHeaderContent given: theAvailableMediaTypes is: aMediaType [ +RESTfulControllerAcceptNegotiatorTest >> assertBestRepresentationFor: anAcceptHeaderContent given: theAvailableMediaTypes is: aMediaType [ self assert: (self bestRepresentationFor: anAcceptHeaderContent given: theAvailableMediaTypes) equals: aMediaType ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiatorTest >> bestRepresentationFor: anAcceptHeaderContent given: theAvailableMediaTypes [ +RESTfulControllerAcceptNegotiatorTest >> bestRepresentationFor: anAcceptHeaderContent given: theAvailableMediaTypes [ ^ (RESTfulControllerAcceptNegotiator basedOn: theAvailableMediaTypes) bestRepresentationFor: @@ -27,19 +27,19 @@ RESTfulWebServiceAcceptNegotiatorTest >> bestRepresentationFor: anAcceptHeaderCo ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiatorTest >> pearAcceptHeader [ +RESTfulControllerAcceptNegotiatorTest >> pearAcceptHeader [ ^ 'text/html,application/xhtml+xml,application/xml;q=0.9,text/*;q=0.7,*/*,image/gif; q=0.8, image/jpeg; q=0.6, image/*' ] { #category : #'private - accessing' } -RESTfulWebServiceAcceptNegotiatorTest >> rfcHeader [ +RESTfulControllerAcceptNegotiatorTest >> rfcHeader [ ^ 'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5' ] { #category : #tests } -RESTfulWebServiceAcceptNegotiatorTest >> setUp [ +RESTfulControllerAcceptNegotiatorTest >> setUp [ super setUp. apiMediaTypes := Array @@ -50,7 +50,7 @@ RESTfulWebServiceAcceptNegotiatorTest >> setUp [ ] { #category : #tests } -RESTfulWebServiceAcceptNegotiatorTest >> testAPIExactMatch [ +RESTfulControllerAcceptNegotiatorTest >> testAPIExactMatch [ self assertBestRepresentationFor: 'application/vnd.stargate.pet+json;version=1.0.0' given: apiMediaTypes is: 'application/vnd.stargate.pet+json;version=1.0.0' asMediaType; @@ -58,7 +58,7 @@ RESTfulWebServiceAcceptNegotiatorTest >> testAPIExactMatch [ ] { #category : #tests } -RESTfulWebServiceAcceptNegotiatorTest >> testMissingVersionSelectsTheNewOne [ +RESTfulControllerAcceptNegotiatorTest >> testMissingVersionSelectsTheNewOne [ self assertBestRepresentationFor: 'application/vnd.stargate.pet+json' given: apiMediaTypes is: 'application/vnd.stargate.pet+json;version=2.0.0' asMediaType; @@ -66,7 +66,7 @@ RESTfulWebServiceAcceptNegotiatorTest >> testMissingVersionSelectsTheNewOne [ ] { #category : #tests } -RESTfulWebServiceAcceptNegotiatorTest >> testRFC2616Sec14 [ +RESTfulControllerAcceptNegotiatorTest >> testRFC2616Sec14 [ self assertBestRepresentationFor: self rfcHeader given: {'text/html;level=1' asMediaType} is: 'text/html;level=1' asMediaType; @@ -78,7 +78,7 @@ RESTfulWebServiceAcceptNegotiatorTest >> testRFC2616Sec14 [ ] { #category : #tests } -RESTfulWebServiceAcceptNegotiatorTest >> testSemanticVersioning [ +RESTfulControllerAcceptNegotiatorTest >> testSemanticVersioning [ self assertBestRepresentationFor: 'application/vnd.stargate.pet+json;version=2' given: apiMediaTypes is: 'application/vnd.stargate.pet+json;version=2.0.0' asMediaType; diff --git a/source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st b/source/Stargate-Model/HypermediaDrivenRESTfulControllerPolicy.class.st similarity index 60% rename from source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st rename to source/Stargate-Model/HypermediaDrivenRESTfulControllerPolicy.class.st index 81af726..1826748 100644 --- a/source/Stargate-Model/HypermediaDrivenResourcePolicy.class.st +++ b/source/Stargate-Model/HypermediaDrivenRESTfulControllerPolicy.class.st @@ -1,5 +1,8 @@ +" +I'm a policy supporting hypermedia-driven RESTful controllers. +" Class { - #name : #HypermediaDrivenResourcePolicy, + #name : #HypermediaDrivenRESTfulControllerPolicy, #superclass : #HypermediaPolicy, #instVars : [ 'resourceController' @@ -8,26 +11,26 @@ Class { } { #category : #'instance creation' } -HypermediaDrivenResourcePolicy class >> for: aResourceController [ +HypermediaDrivenRESTfulControllerPolicy class >> for: aResourceController [ ^ self new initializeFor: aResourceController ] { #category : #configuring } -HypermediaDrivenResourcePolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ +HypermediaDrivenRESTfulControllerPolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ context holdAsHypermediaControls: (resourceController paginationPolicy addPaginationControlsTo: {('self' -> httpRequest absoluteUrl)} within: context). resourceCollection do: [ :resource | context holdAsHypermediaControls: (resourceController mediaControlsFor: resource) forSubresource: resource ] ] { #category : #configuring } -HypermediaDrivenResourcePolicy >> holdResource: resource controlsWithin: context [ +HypermediaDrivenRESTfulControllerPolicy >> holdResource: resource controlsWithin: context [ context holdAsHypermediaControls: (resourceController mediaControlsFor: resource) ] { #category : #initialization } -HypermediaDrivenResourcePolicy >> initializeFor: aResourceController [ +HypermediaDrivenRESTfulControllerPolicy >> initializeFor: aResourceController [ resourceController := aResourceController ] diff --git a/source/Stargate-Model/HypermediaPolicy.class.st b/source/Stargate-Model/HypermediaPolicy.class.st index d32d791..f0a8f6f 100644 --- a/source/Stargate-Model/HypermediaPolicy.class.st +++ b/source/Stargate-Model/HypermediaPolicy.class.st @@ -1,3 +1,6 @@ +" +I'm a policy indicating a RESTful controller if it must support or not an hypermedia driven implementation +" Class { #name : #HypermediaPolicy, #superclass : #Object, diff --git a/source/Stargate-Model/NoHypermediaResourcePolicy.class.st b/source/Stargate-Model/NoHypermediaResourcePolicy.class.st deleted file mode 100644 index a2fe897..0000000 --- a/source/Stargate-Model/NoHypermediaResourcePolicy.class.st +++ /dev/null @@ -1,13 +0,0 @@ -Class { - #name : #NoHypermediaResourcePolicy, - #superclass : #HypermediaPolicy, - #category : #'Stargate-Model-HATEOAS' -} - -{ #category : #configuring } -NoHypermediaResourcePolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ -] - -{ #category : #configuring } -NoHypermediaResourcePolicy >> holdResource: resource controlsWithin: context [ -] diff --git a/source/Stargate-Model/NonHypermediaDrivenRESTfulControllerPolicy.class.st b/source/Stargate-Model/NonHypermediaDrivenRESTfulControllerPolicy.class.st new file mode 100644 index 0000000..d81123e --- /dev/null +++ b/source/Stargate-Model/NonHypermediaDrivenRESTfulControllerPolicy.class.st @@ -0,0 +1,16 @@ +" +I'm a policy non-supporting hypermedia-driven RESTful controllers. +" +Class { + #name : #NonHypermediaDrivenRESTfulControllerPolicy, + #superclass : #HypermediaPolicy, + #category : #'Stargate-Model-HATEOAS' +} + +{ #category : #configuring } +NonHypermediaDrivenRESTfulControllerPolicy >> holdCollection: resourceCollection controlsBasedOn: httpRequest within: context [ +] + +{ #category : #configuring } +NonHypermediaDrivenRESTfulControllerPolicy >> holdResource: resource controlsWithin: context [ +] diff --git a/source/Stargate-Model/RESTFullControllerDoNotPaginateCollectionsPolicy.class.st b/source/Stargate-Model/RESTFullControllerDoNotPaginateCollectionsPolicy.class.st new file mode 100644 index 0000000..3d3ec04 --- /dev/null +++ b/source/Stargate-Model/RESTFullControllerDoNotPaginateCollectionsPolicy.class.st @@ -0,0 +1,39 @@ +" +I'm the policy indicating a RESTful controller to not support pagination of collections related to the controlled resource. +" +Class { + #name : #RESTFullControllerDoNotPaginateCollectionsPolicy, + #superclass : #RESTfulControllerPaginationPolicy, + #instVars : [ + 'resourceController' + ], + #category : #'Stargate-Model-Pagination' +} + +{ #category : #'instance creation' } +RESTFullControllerDoNotPaginateCollectionsPolicy class >> for: aResourceController [ + + ^ self new initializeFor: aResourceController +] + +{ #category : #applying } +RESTFullControllerDoNotPaginateCollectionsPolicy >> addPaginationControlsTo: mediaControls within: aContext [ + + ^ mediaControls +] + +{ #category : #applying } +RESTFullControllerDoNotPaginateCollectionsPolicy >> affect: response within: aContext [ +] + +{ #category : #applying } +RESTFullControllerDoNotPaginateCollectionsPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ + + ^ resourceController evaluateQuery: aQueryEvaluationBlock +] + +{ #category : #initialization } +RESTFullControllerDoNotPaginateCollectionsPolicy >> initializeFor: aResourceController [ + + resourceController := aResourceController +] diff --git a/source/Stargate-Model/ResourceIsPaginatedPolicy.class.st b/source/Stargate-Model/RESTFullControllerPaginateCollectionsPolicy.class.st similarity index 51% rename from source/Stargate-Model/ResourceIsPaginatedPolicy.class.st rename to source/Stargate-Model/RESTFullControllerPaginateCollectionsPolicy.class.st index 59d3e70..b307616 100644 --- a/source/Stargate-Model/ResourceIsPaginatedPolicy.class.st +++ b/source/Stargate-Model/RESTFullControllerPaginateCollectionsPolicy.class.st @@ -1,6 +1,9 @@ +" +I'm the policy indicating a RESTful controller to support pagination of collections related to the controlled resource. +" Class { - #name : #ResourceIsPaginatedPolicy, - #superclass : #ResourcePaginationPolicy, + #name : #RESTFullControllerPaginateCollectionsPolicy, + #superclass : #RESTfulControllerPaginationPolicy, #instVars : [ 'resourceController', 'defaultLimit' @@ -9,19 +12,19 @@ Class { } { #category : #'instance creation' } -ResourceIsPaginatedPolicy class >> for: aResourceController with: aPaginationLimit [ +RESTFullControllerPaginateCollectionsPolicy class >> for: aResourceController with: aPaginationLimit [ ^ self new initializeFor: aResourceController with: aPaginationLimit ] { #category : #applying } -ResourceIsPaginatedPolicy >> addPaginationControlsTo: mediaControls within: aContext [ +RESTFullControllerPaginateCollectionsPolicy >> addPaginationControlsTo: mediaControls within: aContext [ ^ mediaControls , aContext paginationControls ] { #category : #applying } -ResourceIsPaginatedPolicy >> affect: response within: aContext [ +RESTFullControllerPaginateCollectionsPolicy >> affect: response within: aContext [ aContext paginationControls do: [ :assoc | @@ -33,20 +36,20 @@ ResourceIsPaginatedPolicy >> affect: response within: aContext [ ] { #category : #applying } -ResourceIsPaginatedPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ +RESTFullControllerPaginateCollectionsPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ ^ resourceController evaluateQuery: [ aQueryEvaluationBlock cull: (self paginationFrom: anHttpRequest) ] ] -{ #category : #'as yet unclassified' } -ResourceIsPaginatedPolicy >> initializeFor: aResourceController with: aPaginationLimit [ +{ #category : #initialization } +RESTFullControllerPaginateCollectionsPolicy >> initializeFor: aResourceController with: aPaginationLimit [ resourceController := aResourceController. defaultLimit := aPaginationLimit ] { #category : #private } -ResourceIsPaginatedPolicy >> paginationFrom: anHttpRequest [ +RESTFullControllerPaginateCollectionsPolicy >> paginationFrom: anHttpRequest [ ^ PaginationSpec startingAt: (IsInteger parseString: (anHttpRequest at: #start ifAbsent: [ 1 ])) diff --git a/source/Stargate-Model/RESTfulControllerPaginationPolicy.class.st b/source/Stargate-Model/RESTfulControllerPaginationPolicy.class.st new file mode 100644 index 0000000..b67e06e --- /dev/null +++ b/source/Stargate-Model/RESTfulControllerPaginationPolicy.class.st @@ -0,0 +1,26 @@ +" +I'm the policy used to control pagination in a RESTfulController +" +Class { + #name : #RESTfulControllerPaginationPolicy, + #superclass : #Object, + #category : #'Stargate-Model-Pagination' +} + +{ #category : #applying } +RESTfulControllerPaginationPolicy >> addPaginationControlsTo: mediaControls within: aContext [ + + ^ self subclassResponsibility +] + +{ #category : #applying } +RESTfulControllerPaginationPolicy >> affect: response within: aContext [ + + self subclassResponsibility +] + +{ #category : #applying } +RESTfulControllerPaginationPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ + + self subclassResponsibility +] diff --git a/source/Stargate-Model/ResourceNotPaginatedPolicy.class.st b/source/Stargate-Model/ResourceNotPaginatedPolicy.class.st deleted file mode 100644 index 94db5d2..0000000 --- a/source/Stargate-Model/ResourceNotPaginatedPolicy.class.st +++ /dev/null @@ -1,36 +0,0 @@ -Class { - #name : #ResourceNotPaginatedPolicy, - #superclass : #ResourcePaginationPolicy, - #instVars : [ - 'resourceController' - ], - #category : #'Stargate-Model-Pagination' -} - -{ #category : #'instance creation' } -ResourceNotPaginatedPolicy class >> for: aResourceController [ - - ^ self new initializeFor: aResourceController -] - -{ #category : #applying } -ResourceNotPaginatedPolicy >> addPaginationControlsTo: mediaControls within: aContext [ - - ^ mediaControls -] - -{ #category : #applying } -ResourceNotPaginatedPolicy >> affect: response within: aContext [ -] - -{ #category : #applying } -ResourceNotPaginatedPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ - - ^ resourceController evaluateQuery: aQueryEvaluationBlock -] - -{ #category : #'as yet unclassified' } -ResourceNotPaginatedPolicy >> initializeFor: aResourceController [ - - resourceController := aResourceController -] diff --git a/source/Stargate-Model/ResourcePaginationPolicy.class.st b/source/Stargate-Model/ResourcePaginationPolicy.class.st deleted file mode 100644 index 62a5bca..0000000 --- a/source/Stargate-Model/ResourcePaginationPolicy.class.st +++ /dev/null @@ -1,23 +0,0 @@ -Class { - #name : #ResourcePaginationPolicy, - #superclass : #Object, - #category : #'Stargate-Model-Pagination' -} - -{ #category : #applying } -ResourcePaginationPolicy >> addPaginationControlsTo: mediaControls within: aContext [ - - ^ self subclassResponsibility -] - -{ #category : #applying } -ResourcePaginationPolicy >> affect: response within: aContext [ - - self subclassResponsibility -] - -{ #category : #applying } -ResourcePaginationPolicy >> evaluateQuery: aQueryEvaluationBlock basedOn: anHttpRequest [ - - self subclassResponsibility -]