gapic-generator 0.6.0 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/gem_templates/entrypoint.erb +1 -0
- data/gem_templates/gemspec.erb +0 -1
- data/lib/gapic/file_formatter.rb +1 -2
- data/lib/gapic/generator/version.rb +1 -1
- data/lib/gapic/{path_template.rb → path_pattern.rb} +9 -8
- data/lib/gapic/path_pattern/parser.rb +146 -0
- data/lib/gapic/path_pattern/pattern.rb +80 -0
- data/lib/gapic/path_pattern/segment.rb +276 -0
- data/lib/gapic/presenters/field_presenter.rb +12 -0
- data/lib/gapic/presenters/gem_presenter.rb +16 -2
- data/lib/gapic/presenters/method_presenter.rb +7 -3
- data/lib/gapic/presenters/resource_presenter.rb +23 -31
- data/lib/gapic/presenters/service_presenter.rb +2 -1
- data/lib/gapic/runner.rb +3 -1
- data/lib/gapic/schema/api.rb +17 -1
- data/lib/gapic/schema/wrappers.rb +24 -20
- data/lib/gapic/uri_template.rb +36 -0
- data/lib/gapic/uri_template/parser.rb +50 -0
- data/lib/google/protobuf/compiler/plugin.pb.rb +5 -1
- data/lib/google/protobuf/descriptor.pb.rb +1 -0
- data/templates/default/gem/gemfile.erb +0 -3
- data/templates/default/gem/readme.erb +1 -1
- data/templates/default/service/client/resource/_doc.erb +1 -1
- data/templates/default/service/client/resource/_multi.erb +4 -0
- data/templates/default/service/test/client.erb +1 -3
- data/templates/default/service/test/client_operations.erb +1 -3
- data/templates/default/service/test/client_paths.erb +1 -3
- data/templates/default/service/test/method/_bidi.erb +10 -2
- data/templates/default/service/test/method/_client.erb +10 -2
- data/templates/default/service/test/method/_normal.erb +6 -0
- data/templates/default/service/test/method/_server.erb +9 -1
- data/templates/default/service/test/method/_setup.erb +2 -2
- metadata +10 -21
- data/lib/gapic/path_template/parser.rb +0 -83
- data/lib/gapic/path_template/segment.rb +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27e2894595efed8561aa48e9059465257267e7f29310a806251bcc6d4d85c63f
|
4
|
+
data.tar.gz: af47f16264074317a8d02e73539208a4b43f565ae346aef480619bc73a6b1203
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eacd1840fadb1236cb5ed7efe7ba254a977529435ee7ddff1fcee7bb900fa847ccc0a3b861098f1292a63f72e82f6065146f1f0a0260b0624dc9a184de3d3389
|
7
|
+
data.tar.gz: 8a93aaef7317b85fc048604b626af4cef13cf90ea2dd785a12180d94d71dbf0bc4ea24a34c828a04825adcfd4ae2b88e4cc3934d41de7de01b3be27f6302aaba
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
# Release History for gapic-generator
|
2
2
|
|
3
|
+
### 0.6.5 / 2020-07-16
|
4
|
+
|
5
|
+
* Examples in auth, rakefile, and readme should pick a non-common service.
|
6
|
+
* Emit a warning if common_services config references a nonexistent service.
|
7
|
+
|
8
|
+
### 0.6.4 / 2020-07-13
|
9
|
+
|
10
|
+
* Fix rubocop warning on a generated multi-path helper if it could take no arguments.
|
11
|
+
* Run the rubocop file formatting step without caching.
|
12
|
+
* Fix an issue where generating a service with no options would fail.
|
13
|
+
|
14
|
+
### 0.6.3 / 2020-06-27
|
15
|
+
|
16
|
+
* Fixes for generated tests for some cases involving proto maps.
|
17
|
+
* Fix a Ruby 2.7 keyword arguments warning in generated tests.
|
18
|
+
* Clean up bundler references in gemspecs and Gemfiles.
|
19
|
+
|
20
|
+
### 0.6.2 / 2020-06-18
|
21
|
+
|
22
|
+
* Support for the proto3_optional
|
23
|
+
* Fixed an issue where tests for the oneof fields were not generating correctly
|
24
|
+
* Removed ruby <2.5 pin for the protobuf dependency since new protobuf supports it again
|
25
|
+
* Generated libraries now depend on gapic-common 0.3
|
26
|
+
|
27
|
+
### 0.6.1 / 2020-06-16
|
28
|
+
|
29
|
+
* Add auto-generated disclaimer to generated tests.
|
30
|
+
* Support shortname and issue tracker URL configs.
|
31
|
+
* Refactors and minor fixes around resource template parsing.
|
32
|
+
|
3
33
|
### 0.6.0 / 2020-06-02
|
4
34
|
|
5
35
|
* Support for clients with generic endpoint and credentials.
|
data/gem_templates/gemspec.erb
CHANGED
@@ -29,7 +29,6 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_dependency "protobuf", "~> 3.8"
|
30
30
|
spec.add_dependency "rubocop", "~> 0.61"
|
31
31
|
|
32
|
-
spec.add_development_dependency "bundler", "~> 2.1"
|
33
32
|
spec.add_development_dependency "minitest", "~> 5.0"
|
34
33
|
spec.add_development_dependency "minitest-focus", "~> 1.0"
|
35
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/lib/gapic/file_formatter.rb
CHANGED
@@ -26,7 +26,6 @@ module Gapic
|
|
26
26
|
##
|
27
27
|
# Create a new file formatter object
|
28
28
|
#
|
29
|
-
# @param path_template [String] The URI path template to be parsed.
|
30
29
|
def initialize configuration, files
|
31
30
|
@configuration = configuration
|
32
31
|
@files = format! configuration, files
|
@@ -40,7 +39,7 @@ module Gapic
|
|
40
39
|
write_file dir, file
|
41
40
|
end
|
42
41
|
|
43
|
-
system "rubocop -x #{dir} -o #{dir}/rubocop.out -c #{configuration}"
|
42
|
+
system "rubocop --cache false -x #{dir} -o #{dir}/rubocop.out -c #{configuration}"
|
44
43
|
|
45
44
|
files.each do |file|
|
46
45
|
read_file dir, file
|
@@ -14,22 +14,23 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
require "gapic/
|
17
|
+
require "gapic/path_pattern/parser"
|
18
18
|
|
19
19
|
module Gapic
|
20
20
|
# TODO: Enter docs
|
21
21
|
# Dooooooooocs!!!
|
22
|
-
module
|
23
|
-
# Parse a URI path
|
22
|
+
module PathPattern
|
23
|
+
# Parse a URI path pattern.
|
24
24
|
#
|
25
|
-
# @see https://
|
25
|
+
# @see https://google.aip.dev/122 AIP-122 Resource names
|
26
|
+
# @see https://google.aip.dev/123 AIP-123 Resource types
|
26
27
|
#
|
27
|
-
# @param
|
28
|
+
# @param path_pattern [String] The URI path template to be parsed.
|
28
29
|
#
|
29
|
-
# @return [
|
30
|
+
# @return [PathPattern::Pattern] The parsed pattern
|
30
31
|
# path template.
|
31
|
-
def self.parse
|
32
|
-
Parser.
|
32
|
+
def self.parse path_pattern
|
33
|
+
Parser.parse path_pattern
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 Google LLC
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
require "gapic/path_pattern/segment"
|
18
|
+
require "gapic/path_pattern/pattern"
|
19
|
+
|
20
|
+
module Gapic
|
21
|
+
module PathPattern
|
22
|
+
##
|
23
|
+
# A path pattern parser.
|
24
|
+
# takes a pattern and transforms it into a collection of parsed segments
|
25
|
+
# @see https://google.aip.dev/122
|
26
|
+
# @see https://google.aip.dev/123
|
27
|
+
#
|
28
|
+
module Parser
|
29
|
+
##
|
30
|
+
# @param path_pattern [String] The path pattern to be parsed
|
31
|
+
# @return [Gapic::PathPattern::Pattern]
|
32
|
+
def self.parse path_pattern
|
33
|
+
remainder = path_pattern.sub(%r{^/}, "").sub(%r{/$}, "")
|
34
|
+
|
35
|
+
segments = []
|
36
|
+
position = 0
|
37
|
+
until remainder.empty?
|
38
|
+
segment, position, remainder = parse_first_segment_with_position remainder, position
|
39
|
+
segments << segment
|
40
|
+
end
|
41
|
+
|
42
|
+
Pattern.new path_pattern, segments
|
43
|
+
end
|
44
|
+
|
45
|
+
# @private
|
46
|
+
def self.parse_first_segment_with_position url_pattern, position
|
47
|
+
# check for the wildcard segment -- either * or **
|
48
|
+
# wildcard segments are positional, so the position counter is used and updated
|
49
|
+
segment, remainder = try_capture_wildcard_segment url_pattern, position
|
50
|
+
return [segment, position + 1, remainder] if segment
|
51
|
+
|
52
|
+
# check for the complex resource id segment, e.g. {foo}-{bar}_{baz}
|
53
|
+
segment, remainder = try_capture_complex_resource_id_segment url_pattern
|
54
|
+
return [segment, position, remainder] if segment
|
55
|
+
|
56
|
+
# check for the simple resource id segment, e.g. {foo} or {foo=some/pattern/*}
|
57
|
+
segment, remainder = try_capture_simple_resource_id_segment url_pattern
|
58
|
+
return [segment, position, remainder] if segment
|
59
|
+
|
60
|
+
# if nothing else fits, it's the collection id segment
|
61
|
+
segment, remainder = capture_collection_id_segment url_pattern
|
62
|
+
[segment, position, remainder]
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Tries to capture the first segment of the pattern as a wildcard segment
|
67
|
+
# The wildcard segment can be either * or **
|
68
|
+
# @private
|
69
|
+
def self.try_capture_wildcard_segment url_pattern, position
|
70
|
+
wildcard_capture_regex = %r{^(?<pattern>\*\*|\*)(?:/|$)}
|
71
|
+
return nil, url_pattern unless wildcard_capture_regex.match? url_pattern
|
72
|
+
|
73
|
+
match = wildcard_capture_regex.match url_pattern
|
74
|
+
|
75
|
+
wildcard_pattern = match[:pattern]
|
76
|
+
|
77
|
+
segment = PositionalSegment.new position, wildcard_pattern
|
78
|
+
remainder = match.post_match
|
79
|
+
[segment, remainder]
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Tries to capture the first segment of the pattern as a complex resource id segment
|
84
|
+
# The pattern for the complex resource id segments is:
|
85
|
+
# {<name_first>}<separator>{<name_second>} etc, e.g. {foo}-{bar}_{baz}
|
86
|
+
# see AIP-4231 Parsing resource names, Complex resource ID path segments
|
87
|
+
# @private
|
88
|
+
def self.try_capture_complex_resource_id_segment url_pattern
|
89
|
+
complex_resource_id_regex =
|
90
|
+
%r/^(?<segment_pattern>{(?<name_first>[^\/}]+?)}(?:(?<separator>[_\-~\.]){(?<name_seq>[^\/}]+?)})+)(?:\/|$)/
|
91
|
+
|
92
|
+
return nil, url_pattern unless complex_resource_id_regex.match? url_pattern
|
93
|
+
|
94
|
+
match = complex_resource_id_regex.match url_pattern
|
95
|
+
segment_pattern = match[:segment_pattern]
|
96
|
+
|
97
|
+
resource_name_regex = %r/{(?<name>[^\/}]+?)}/
|
98
|
+
resource_names = segment_pattern.scan(resource_name_regex).flatten
|
99
|
+
|
100
|
+
segment = ResourceIdSegment.new :complex_resource_id, segment_pattern, resource_names
|
101
|
+
remainder = match.post_match
|
102
|
+
[segment, remainder]
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Tries to capture the first segment of the pattern as a simple resource id segment
|
107
|
+
# The pattern for the simple resource id segments is:
|
108
|
+
# {<name>} or with an optional resource name pattern {<name>=<pattern>}
|
109
|
+
# e.g. {foo} or with an optional pattern, e.g. {foo=**} or {foo=bar}
|
110
|
+
# notably here the pattern between the = and } *can* contain the path separator /
|
111
|
+
# @private
|
112
|
+
def self.try_capture_simple_resource_id_segment url_pattern
|
113
|
+
simple_resource_id_regex =
|
114
|
+
%r/^(?<segment_pattern>{(?<resource_name>[^\/}]+?)(?:=(?<resource_pattern>.+?))?})(?:\/|$)/
|
115
|
+
return nil, url_pattern unless simple_resource_id_regex.match? url_pattern
|
116
|
+
|
117
|
+
match = simple_resource_id_regex.match url_pattern
|
118
|
+
segment_pattern = match[:segment_pattern]
|
119
|
+
|
120
|
+
resource_name = match[:resource_name]
|
121
|
+
resource_pattern = match[:resource_pattern] if match.names.include? "resource_pattern"
|
122
|
+
resource_patterns = resource_pattern.nil? ? [] : [resource_pattern]
|
123
|
+
|
124
|
+
segment = ResourceIdSegment.new :simple_resource_id, segment_pattern, [resource_name], resource_patterns
|
125
|
+
remainder = match.post_match
|
126
|
+
[segment, remainder]
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Captures the first segment of the pattern as a collection id segment
|
131
|
+
# This is used as a catch-all, so the collection id segment can contain anything
|
132
|
+
# except the path separator /
|
133
|
+
# @private
|
134
|
+
def self.capture_collection_id_segment url_pattern
|
135
|
+
collection_id_regex = %r{^(?<collection_name>[^/]+?)(?:/|$)}
|
136
|
+
match = collection_id_regex.match url_pattern
|
137
|
+
|
138
|
+
collection_name = match[:collection_name]
|
139
|
+
|
140
|
+
segment = CollectionIdSegment.new collection_name
|
141
|
+
remainder = match.post_match
|
142
|
+
[segment, remainder]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2020 Google LLC
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
require "gapic/path_pattern/segment"
|
18
|
+
|
19
|
+
module Gapic
|
20
|
+
module PathPattern
|
21
|
+
##
|
22
|
+
# A parsed pattern.
|
23
|
+
# @see https://google.aip.dev/122 AIP-122 Resource names
|
24
|
+
# @see https://google.aip.dev/123 AIP-123 Resource types
|
25
|
+
#
|
26
|
+
# @!attribute [r] path_pattern
|
27
|
+
# @return [String] The path pattern
|
28
|
+
# @!attribute [r] segments
|
29
|
+
# @return [Array<PositionalSegment|ResourceIdSegment|CollectionIdSegment>]
|
30
|
+
# The parsed segments of the path pattern
|
31
|
+
class Pattern
|
32
|
+
attr_reader :path_pattern, :segments
|
33
|
+
|
34
|
+
def initialize path_pattern, segments
|
35
|
+
@path_pattern = path_pattern
|
36
|
+
@segments = segments
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# All argument names from this pattern
|
41
|
+
# @return [Array<String>]
|
42
|
+
def arguments
|
43
|
+
@segments.select(&:provides_arguments?).map(&:arguments).flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Whether pattern contains a positional segment
|
48
|
+
# @return [Boolean]
|
49
|
+
def positional_segments?
|
50
|
+
@segments.any?(&:positional?)
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Whether pattern contains a segment with a nontrivial resource pattern
|
55
|
+
# @return [Boolean]
|
56
|
+
def nontrivial_pattern_segments?
|
57
|
+
@segments.any?(&:nontrivial_resource_pattern?)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# A template of this pattern - all resource id segments are
|
62
|
+
# stripped and replaced by '*'
|
63
|
+
# @return [String]
|
64
|
+
def template
|
65
|
+
@segments.map(&:pattern_template).join("/")
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# A parent template to this pattern or an empty string if a pattern
|
70
|
+
# can not have a parent (too short)
|
71
|
+
# @return [String]
|
72
|
+
def parent_template
|
73
|
+
return nil if segments.length <= 2
|
74
|
+
last_segment = segments.last
|
75
|
+
parent_pattern_segments = last_segment.provides_arguments? ? segments[0...-2] : segments[0...-1]
|
76
|
+
parent_pattern_segments.map(&:pattern_template).join("/")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 Google LLC
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Gapic
|
18
|
+
module PathPattern
|
19
|
+
##
|
20
|
+
# A positional segment in a path pattern.
|
21
|
+
# positional segments have a pattern of wildcards and do not carry a name
|
22
|
+
#
|
23
|
+
# @!attribure [r] type
|
24
|
+
# @return [String] The type of this segment
|
25
|
+
# @!attribute [r] position
|
26
|
+
# @return [Integer] The argument position of this segment i.e.
|
27
|
+
# it's position if we remove all non-positional segments from the pattern
|
28
|
+
# @!attribute [r] pattern
|
29
|
+
# @return [String] The pattern of the segment, for the positional segment it is also
|
30
|
+
# a pattern of its resource
|
31
|
+
class PositionalSegment
|
32
|
+
attr_reader :type, :position, :pattern
|
33
|
+
def initialize position, pattern
|
34
|
+
@type = :positional
|
35
|
+
@position = position
|
36
|
+
@pattern = pattern
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Whether the segment is positional
|
41
|
+
# @return [Boolean]
|
42
|
+
def positional?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Whether the segment provides a resource pattern
|
48
|
+
# @return [Boolean]
|
49
|
+
def resource_pattern?
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Whether the segment provides a nontrivial resource pattern
|
55
|
+
# @return [Boolean]
|
56
|
+
def nontrivial_resource_pattern?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Whether the segment provides arguments
|
62
|
+
# @return [Boolean]
|
63
|
+
def provides_arguments?
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Names of the segment's arguments
|
69
|
+
# @return [Array<String>]
|
70
|
+
def arguments
|
71
|
+
[position.to_s]
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Returns a segment's pattern filled with dummy values
|
76
|
+
# names of the values are generated starting from the index provided
|
77
|
+
# @param start_index [Integer] a starting index for dummy value generation
|
78
|
+
# @return [String] a pattern filled with dummy values
|
79
|
+
def expected_path_for_dummy_values start_index
|
80
|
+
"value#{start_index}"
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Path string for this segment
|
85
|
+
# @return [String]
|
86
|
+
def path_string
|
87
|
+
"\#{#{position}}"
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# A pattern template for this segment
|
92
|
+
# @return [String]
|
93
|
+
def pattern_template
|
94
|
+
pattern
|
95
|
+
end
|
96
|
+
|
97
|
+
# @private
|
98
|
+
def == other
|
99
|
+
return false unless other.is_a? self.class
|
100
|
+
|
101
|
+
(pattern == other.pattern && position == other.position)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# A ResourceId segment in a path pattern.
|
106
|
+
# ResourceId segments can be simple, with one resource name
|
107
|
+
# or complex, with multiple resource names divided by separators
|
108
|
+
#
|
109
|
+
# @!attribure [r] type
|
110
|
+
# @return [String] The type of this segment
|
111
|
+
# @!attribute [r] pattern
|
112
|
+
# @return [String] The pattern of the segment, for the positional segment it is also
|
113
|
+
# a pattern of its resource
|
114
|
+
# @!attribute [r] resource_names
|
115
|
+
# @return [Array<String>] The resource names in this segment
|
116
|
+
# @!attribute [r] resource_patterns
|
117
|
+
# @return [Array<String>] The resource patterns associated with
|
118
|
+
# the resource_names of this segment
|
119
|
+
class ResourceIdSegment
|
120
|
+
attr_reader :type, :pattern, :resource_names, :resource_patterns
|
121
|
+
|
122
|
+
def initialize type, pattern, resource_names, resource_patterns = []
|
123
|
+
@type = type
|
124
|
+
@pattern = pattern
|
125
|
+
@resource_names = resource_names
|
126
|
+
@resource_patterns = resource_patterns
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Whether the segment is positional
|
131
|
+
# @return [Boolean]
|
132
|
+
def positional?
|
133
|
+
false
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Whether the segment provides a resource pattern
|
138
|
+
# @return [Boolean]
|
139
|
+
def resource_pattern?
|
140
|
+
resource_patterns.any?
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Whether the segment provides a nontrivial resource pattern
|
145
|
+
# @return [Boolean]
|
146
|
+
def nontrivial_resource_pattern?
|
147
|
+
resource_patterns.any? { |res_pattern| !res_pattern.match?(/^\*+$/) }
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Whether the segment provides arguments
|
152
|
+
# @return [Boolean]
|
153
|
+
def provides_arguments?
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Names of the segment's arguments
|
159
|
+
# @return [Array<String>]
|
160
|
+
def arguments
|
161
|
+
resource_names
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Returns a segment's pattern filled with dummy values
|
166
|
+
# names of the values are generated starting from the index provided
|
167
|
+
# @param start_index [Integer] a starting index for dummy value generation
|
168
|
+
# @return [String] a pattern filled with dummy values
|
169
|
+
def expected_path_for_dummy_values start_index
|
170
|
+
return "value#{start_index}" if type == :simple_resource_id
|
171
|
+
|
172
|
+
resource_names.each_with_index.reduce pattern do |exp_path, (res_name, index)|
|
173
|
+
exp_path.sub "{#{res_name}}", "value#{start_index + index}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# Path string for this segment
|
179
|
+
# @return [String]
|
180
|
+
def path_string
|
181
|
+
type == :simple_resource_id ? "\#{#{resource_names[0]}}" : pattern.gsub("{", "\#{")
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# A pattern template for this segment
|
186
|
+
# @return [String]
|
187
|
+
def pattern_template
|
188
|
+
"*"
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Initialization helper to create a simple resource without a pattern
|
193
|
+
# @param name [String] resource name
|
194
|
+
# @return [ResourceIdSegment]
|
195
|
+
def self.create_simple name
|
196
|
+
ResourceIdSegment.new :simple_resource_id, "{#{name}}", [name]
|
197
|
+
end
|
198
|
+
|
199
|
+
# @private
|
200
|
+
def == other
|
201
|
+
return false unless other.is_a? self.class
|
202
|
+
|
203
|
+
(type == other.type && pattern == other.pattern &&
|
204
|
+
resource_names == other.resource_names &&
|
205
|
+
resource_patterns == other.resource_patterns)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# A CollectionId segment in a path template.
|
211
|
+
# CollectionId segments are basically string literals
|
212
|
+
#
|
213
|
+
# @!attribure [r] type
|
214
|
+
# @return [String] The type of this segment
|
215
|
+
# @!attribute [r] pattern
|
216
|
+
# @return [String] The pattern of the segment, for the positional segment it is also
|
217
|
+
# a pattern of its resource
|
218
|
+
class CollectionIdSegment
|
219
|
+
attr_reader :type, :pattern
|
220
|
+
|
221
|
+
def initialize pattern
|
222
|
+
@type = :collection_id
|
223
|
+
@pattern = pattern
|
224
|
+
end
|
225
|
+
|
226
|
+
##
|
227
|
+
# Whether the segment is positional
|
228
|
+
# @return [Boolean]
|
229
|
+
def positional?
|
230
|
+
false
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# Whether the segment provides a resource pattern
|
235
|
+
# @return [Boolean]
|
236
|
+
def resource_pattern?
|
237
|
+
false
|
238
|
+
end
|
239
|
+
|
240
|
+
##
|
241
|
+
# Whether the segment provides a nontrivial resource pattern
|
242
|
+
# @return [Boolean]
|
243
|
+
def nontrivial_resource_pattern?
|
244
|
+
false
|
245
|
+
end
|
246
|
+
|
247
|
+
##
|
248
|
+
# Whether the segment provides arguments
|
249
|
+
# @return [Boolean]
|
250
|
+
def provides_arguments?
|
251
|
+
false
|
252
|
+
end
|
253
|
+
|
254
|
+
##
|
255
|
+
# Path string for this segment
|
256
|
+
# @return [String]
|
257
|
+
def path_string
|
258
|
+
pattern
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# A pattern template for this segment
|
263
|
+
# @return [String]
|
264
|
+
def pattern_template
|
265
|
+
pattern
|
266
|
+
end
|
267
|
+
|
268
|
+
# @private
|
269
|
+
def == other
|
270
|
+
return false unless other.is_a? self.class
|
271
|
+
|
272
|
+
(pattern == other.pattern)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|