eco-helpers 0.6.17 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +19 -0
- data/.yardopts +2 -2
- data/Gemfile +6 -0
- data/Rakefile +27 -0
- data/eco-helpers.gemspec +9 -6
- data/lib/eco/api.rb +2 -1
- data/lib/eco/api/common/people.rb +1 -1
- data/lib/eco/api/common/people/base_parser.rb +31 -1
- data/lib/eco/api/common/people/default_parsers.rb +5 -1
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +37 -0
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +0 -1
- data/lib/eco/api/common/people/entries.rb +14 -18
- data/lib/eco/api/common/people/entry_factory.rb +97 -9
- data/lib/eco/api/common/people/person_entry.rb +147 -206
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +212 -0
- data/lib/eco/api/common/people/person_factory.rb +10 -12
- data/lib/eco/api/common/people/person_parser.rb +97 -37
- data/lib/eco/api/common/session/base_session.rb +1 -2
- data/lib/eco/api/common/session/file_manager.rb +1 -1
- data/lib/eco/api/organization.rb +2 -1
- data/lib/eco/api/organization/people.rb +54 -22
- data/lib/eco/api/organization/person_schemas.rb +54 -0
- data/lib/eco/api/organization/policy_groups.rb +5 -9
- data/lib/eco/api/organization/{presets.rb → presets_factory.rb} +1 -1
- data/lib/eco/api/policies.rb +10 -0
- data/lib/eco/api/policies/base_policy.rb +14 -0
- data/lib/eco/api/policies/policy.rb +20 -0
- data/lib/eco/api/policies/used_policies.rb +37 -0
- data/lib/eco/api/session.rb +36 -34
- data/lib/eco/api/session/batch.rb +94 -44
- data/lib/eco/api/session/batch_job.rb +108 -48
- data/lib/eco/api/session/batch_jobs.rb +4 -5
- data/lib/eco/api/session/batch_status.rb +70 -11
- data/lib/eco/api/session/config.rb +22 -5
- data/lib/eco/api/session/config/files.rb +10 -1
- data/lib/eco/api/session/config/people.rb +18 -5
- data/lib/eco/api/session/config/policies.rb +29 -0
- data/lib/eco/api/session/config/use_cases.rb +3 -7
- data/lib/eco/api/session/job_groups.rb +9 -10
- data/lib/eco/api/usecases.rb +2 -1
- data/lib/eco/api/usecases/base_case.rb +7 -2
- data/lib/eco/api/usecases/default_cases/change_email_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/create_case.rb +2 -1
- data/lib/eco/api/usecases/default_cases/create_details_case.rb +3 -1
- data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/hris_case.rb +20 -13
- data/lib/eco/api/usecases/default_cases/new_email_case.rb +3 -1
- data/lib/eco/api/usecases/default_cases/new_id_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/recover_db_case.rb +9 -5
- data/lib/eco/api/usecases/default_cases/remove_account_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +4 -2
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +2 -2
- data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +2 -2
- data/lib/eco/api/usecases/default_cases/update_case.rb +16 -2
- data/lib/eco/api/usecases/default_cases/update_details_case.rb +3 -1
- data/lib/eco/api/usecases/default_cases/upsert_case.rb +25 -3
- data/lib/eco/api/usecases/use_case.rb +23 -140
- data/lib/eco/api/usecases/use_case_chain.rb +95 -0
- data/lib/eco/api/usecases/use_case_io.rb +117 -0
- data/lib/eco/api/usecases/use_group.rb +25 -5
- data/lib/eco/common/base_cli_backup.rb +1 -0
- data/lib/eco/language/models.rb +1 -1
- data/lib/eco/language/models/collection.rb +42 -31
- data/lib/eco/language/models/parser_serializer.rb +68 -0
- data/lib/eco/version.rb +1 -1
- metadata +93 -38
- data/lib/eco/api/common/people/types.rb +0 -47
- data/lib/eco/api/usecases/case_data.rb +0 -13
- data/lib/eco/language/models/attribute_parser.rb +0 -38
- data/lib/eco/lexic/dictionary.rb +0 -33
- data/lib/eco/lexic/dictionary/dictionary.txt +0 -355484
- data/lib/eco/lexic/dictionary/tags.json +0 -38
@@ -0,0 +1,212 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Common
|
4
|
+
module People
|
5
|
+
|
6
|
+
# @attr_reader core_attrs [Array<String>] core attributes that are present in the person entry.
|
7
|
+
# @attr_reader details_attrs [Array<String>] schema details attributes that are present in the person entry.
|
8
|
+
# @attr_reader account_attrs [Array<String>] account attributes that are present in the person entry.
|
9
|
+
# @attr_reader all_attrs [Array<String>] all the attrs that are present in the person entry.
|
10
|
+
# @attr_reader internal_attrs [Array<String>] all the internally named attributes that the person entry has.
|
11
|
+
# @attr_reader aliased_attrs [Array<String>] only those internal attributes present in the person entry that have an internal/external name mapping.
|
12
|
+
# @attr_reader direct_attrs [Array<String>] only those internal attributes present in the person entry that do **not** have an internal/external name mapping.
|
13
|
+
class PersonEntryAttributeMapper
|
14
|
+
@@cached_warnings = {}
|
15
|
+
|
16
|
+
attr_reader :core_attrs, :details_attrs, :account_attrs, :all_attrs
|
17
|
+
attr_reader :internal_attrs, :aliased_attrs, :direct_attrs
|
18
|
+
|
19
|
+
# Helper class tied to `PersonEntry` that allows to track which attributes of a person entry are present
|
20
|
+
# and how they should be mapped between internal and external names if applicable.
|
21
|
+
# This class is meant to help in providing a common interface to access entries of source data that come in different formats.
|
22
|
+
# @note
|
23
|
+
# - if `data` is a `Person` object, its behaviour is `serialise`.
|
24
|
+
# - if `data` is **not** a `Person` object, it does a `parse`.
|
25
|
+
# - currently **in rework**, so there may be subtle differences that make it temporarily unstable (yet it is reliable).
|
26
|
+
# @param data [Hash, Person] `Person` object to be serialized or hashed entry (`CSV::Row` is accepted).
|
27
|
+
# @param person_parser [Common::People::PersonParser] parser/serializer of person attributes (it contains a set of attribute parsers).
|
28
|
+
# @param attr_map [Eco::Data::Mapper] mapper to translate attribute names from _external_ to _internal_ names and _vice versa_.
|
29
|
+
# @param logger [Common::Session::Logger, ::Logger] object to manage logs.
|
30
|
+
def initialize(data, person_parser:, attr_map:, logger: ::Logger.new(IO::NULL))
|
31
|
+
raise "Constructor needs a PersonParser. Given: #{parser}" if !person_parser.is_a?(Eco::API::Common::People::PersonParser)
|
32
|
+
raise "Expecting Mapper object. Given: #{attr_map}" if attr_map && !attr_map.is_a?(Eco::Data::Mapper)
|
33
|
+
|
34
|
+
@source = data
|
35
|
+
@person_parser = person_parser
|
36
|
+
@attr_map = attr_map
|
37
|
+
@logger = logger
|
38
|
+
|
39
|
+
if parsing?
|
40
|
+
@external_entry = data
|
41
|
+
init_attr_trackers
|
42
|
+
else # SERIALIZING
|
43
|
+
@person = data
|
44
|
+
@internal_attrs = @person_parser.all_attrs
|
45
|
+
end
|
46
|
+
|
47
|
+
@core_attrs = @person_parser.target_attrs_core(@internal_attrs)
|
48
|
+
@details_attrs = @person_parser.target_attrs_details(@internal_attrs)
|
49
|
+
@account_attrs = @person_parser.target_attrs_account(@internal_attrs)
|
50
|
+
@all_attrs = @core_attrs | @account_attrs | @details_attrs
|
51
|
+
end
|
52
|
+
|
53
|
+
# To know if currently the object is in parse or serialize mode.
|
54
|
+
# @return [Boolean] returns `true` if we are **parsing**, `false` otherwise.
|
55
|
+
def parsing?
|
56
|
+
!@source.is_a?(Ecoportal::API::Internal::Person)
|
57
|
+
end
|
58
|
+
|
59
|
+
# To know if currently the object is in parse or serialize mode.
|
60
|
+
# @return [Boolean] returns `true` if we are **serializing**, `false` otherwise.
|
61
|
+
def serializing?
|
62
|
+
!parsing?
|
63
|
+
end
|
64
|
+
|
65
|
+
# If there **no** `mapper` defined for the object, it mirrors `value`.
|
66
|
+
# If there is a `mapper` defined for the object:
|
67
|
+
# 1. if the `value` exists as external, translates it into an internal one.
|
68
|
+
# 2. if it doesn't exist, returns `nil`.
|
69
|
+
# @note
|
70
|
+
# 1. the **scope of attributes** is based on all the attributes recognized by the person parser.
|
71
|
+
# 2. the attributes recognized by the person parser are those of of the `Person` model (where details attributes depend on the `schema`).
|
72
|
+
# @param value [String, Array<String>] value(s) to be translated into internal names.
|
73
|
+
# @return [String, nil, Array<String] the internal name(s) of `value`.
|
74
|
+
def to_internal(value)
|
75
|
+
return value if !@attr_map
|
76
|
+
attr = value
|
77
|
+
case value
|
78
|
+
when Array
|
79
|
+
return value.map do |v|
|
80
|
+
to_internal(v)
|
81
|
+
end.compact
|
82
|
+
when String
|
83
|
+
case
|
84
|
+
when @attr_map.external?(value)
|
85
|
+
attr = @attr_map.to_internal(value)
|
86
|
+
when @attr_map.external?(value.strip)
|
87
|
+
unless cached_warning("external", "spaces", value)
|
88
|
+
logger.warn("The external person field name '#{value}' contains additional spaces in the reference file")
|
89
|
+
end
|
90
|
+
attr = @attr_map.to_internal(value.strip)
|
91
|
+
when @attr_map.internal?(value) || @attr_map.internal?(value.strip) || @attr_map.internal?(value.strip.downcase)
|
92
|
+
unless cached_warning("external", "reversed", value)
|
93
|
+
logger.warn("The mapper [external, internal] attribute names may be declared reversedly for EXTERNAL attribute: '#{value}'")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
return nil unless @person_parser.all_attrs.include?(attr)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Serializing helper also used to do a reverse mapping when parsing:
|
102
|
+
# - as there could be _internal attributes_ that shared _external attributes_,
|
103
|
+
# - when parsing, you use this helper to recognize the source _external attribute_ of each _internal_ one.
|
104
|
+
# If there **no** `mapper` defined for the object, it mirrors `value`.
|
105
|
+
# If there is a `mapper` defined for the object:
|
106
|
+
# 1. if the `value` exists as _internal-, translates it into an _external_ one.
|
107
|
+
# 2. if it doesn't exist, returns `nil`.
|
108
|
+
# @note
|
109
|
+
# 1. the **scope of attributes** is based on all the attributes defined in the current entry.
|
110
|
+
# 2. the attributes recognized by the person parser are those of of the `Person` model (where details attributes depend on the `schema`).
|
111
|
+
# @param value [String, Array<String>] value(s) to be translated or aliased into external ones.
|
112
|
+
# @return [String, nil, Array<String] the external name(s) of `value`.
|
113
|
+
def to_external(value)
|
114
|
+
return value if !@attr_map
|
115
|
+
attr = value
|
116
|
+
case value
|
117
|
+
when Array
|
118
|
+
return value.map do |v|
|
119
|
+
to_external(v)
|
120
|
+
end.compact
|
121
|
+
when String
|
122
|
+
case
|
123
|
+
when @attr_map.internal?(value)
|
124
|
+
attr = @attr_map.to_external(value)
|
125
|
+
when @attr_map.internal?(value.strip)
|
126
|
+
unless cached_warning("internal", "spaces", value)
|
127
|
+
logger.warn("The internal person field name '#{value}' contains additional spaces in the reference file")
|
128
|
+
end
|
129
|
+
attr = @attr_map.to_external(value.strip)
|
130
|
+
when @attr_map.external?(value) || @attr_map.external?(value.strip) || @attr_map.external?(value.strip.downcase)
|
131
|
+
unless cached_warning("internal", "reversed", value)
|
132
|
+
logger.warn("The mapper [external, internal] attribute names may be declared reversedly for INTERNAL attribute: '#{value}'")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
return nil unless !@external_entry || attributes(@external_entry).include?(attr)
|
138
|
+
attr
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# when parsing:
|
144
|
+
def init_attr_trackers
|
145
|
+
# internal <-> external attributes
|
146
|
+
int_aliased = @person_parser.all_attrs.select { |attr| to_external(attr) }
|
147
|
+
ext_alias = int_aliased.map { |attr| to_external(attr) }
|
148
|
+
|
149
|
+
# virtual attrs (non native internal attr that require aliasing):
|
150
|
+
ext_vi_aliased = attributes(@external_entry).select do |attr|
|
151
|
+
!ext_alias.include?(attr) && @attr_map&.external?(attr)
|
152
|
+
end
|
153
|
+
|
154
|
+
# internal name of external attrs that are not native internal attrs
|
155
|
+
int_vi_aliased = ext_vi_aliased.map do |attr|
|
156
|
+
# to_internal(attr) can't be used here, becauase virtual fields would get filtered out,
|
157
|
+
# as they are not recognized by @parser.all_attrs.include?(attr)
|
158
|
+
@attr_map.to_internal(attr)
|
159
|
+
end.compact
|
160
|
+
|
161
|
+
@aliased_attrs = int_aliased + int_vi_aliased
|
162
|
+
|
163
|
+
int_unlinked = @person_parser.undefined_attrs.select { |attr| !to_external(attr) }
|
164
|
+
# those with parser or alias:
|
165
|
+
int_linked = @person_parser.all_attrs - int_unlinked
|
166
|
+
|
167
|
+
ext_aliased = ext_alias + ext_vi_aliased
|
168
|
+
# those that are direct external to internal:
|
169
|
+
ext_direct = attributes(@external_entry) - ext_aliased
|
170
|
+
# to avoid collisions between internal names:
|
171
|
+
@direct_attrs = ext_direct - int_linked
|
172
|
+
@internal_attrs = @aliased_attrs | @direct_attrs
|
173
|
+
end
|
174
|
+
|
175
|
+
def attributes(value)
|
176
|
+
case value
|
177
|
+
when CSV::Row
|
178
|
+
value&.headers
|
179
|
+
when Hash
|
180
|
+
value&.keys
|
181
|
+
when PersonEntry
|
182
|
+
@person_parser.target_attrs_core
|
183
|
+
else
|
184
|
+
[]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# LOGGER
|
189
|
+
def logger
|
190
|
+
@logger || ::Logger.new(IO::NULL)
|
191
|
+
end
|
192
|
+
|
193
|
+
def cached_warning(*args)
|
194
|
+
unless exists = !!@@cached_warnings.dig(*args)
|
195
|
+
args.reduce(@@cached_warnings) do |cache, level|
|
196
|
+
cache[level] = {} if !cache.key?(level)
|
197
|
+
cache[level]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
exists
|
201
|
+
end
|
202
|
+
|
203
|
+
def fatal(msg)
|
204
|
+
logger.fatal(msg)
|
205
|
+
exit
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -4,8 +4,6 @@ module Eco
|
|
4
4
|
module People
|
5
5
|
class PersonFactory
|
6
6
|
|
7
|
-
include Common::People
|
8
|
-
|
9
7
|
attr_reader :schema_attrs
|
10
8
|
|
11
9
|
def initialize(person: {}, schema: {}, account: {}, modifier: Common::People::PersonModifier.new)
|
@@ -43,9 +41,9 @@ module Eco
|
|
43
41
|
|
44
42
|
def klass
|
45
43
|
if @modifier.external?
|
46
|
-
|
44
|
+
Ecoportal::API::V1::Person
|
47
45
|
else
|
48
|
-
|
46
|
+
Ecoportal::API::Internal::Person
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -69,10 +67,10 @@ module Eco
|
|
69
67
|
end
|
70
68
|
|
71
69
|
def person_hash(person)
|
72
|
-
case
|
73
|
-
when
|
70
|
+
case person
|
71
|
+
when Ecoportal::API::V1::Person
|
74
72
|
JSON.parse(person.doc.to_json)
|
75
|
-
when
|
73
|
+
when Hash
|
76
74
|
JSON.parse(person.to_json)
|
77
75
|
else
|
78
76
|
{}
|
@@ -80,12 +78,12 @@ module Eco
|
|
80
78
|
end
|
81
79
|
|
82
80
|
def details_hash(details)
|
83
|
-
case
|
84
|
-
when
|
81
|
+
case details
|
82
|
+
when Ecoportal::API::V1::PersonDetails
|
85
83
|
doc = JSON.parse(details.doc.to_json)
|
86
|
-
when
|
84
|
+
when Ecoportal::API::V1::PersonSchema
|
87
85
|
doc =JSON.parse(details.doc.to_json)
|
88
|
-
when
|
86
|
+
when Hash
|
89
87
|
doc = JSON.parse(details.to_json)
|
90
88
|
doc = doc["details"] if doc.key?("details")
|
91
89
|
else
|
@@ -97,7 +95,7 @@ module Eco
|
|
97
95
|
|
98
96
|
def account_hash(account)
|
99
97
|
case
|
100
|
-
when account.is_a?(
|
98
|
+
when account.is_a?(Ecoportal::API::Internal::Account)
|
101
99
|
JSON.parse(account.doc.to_json)
|
102
100
|
when account.is_a?(Hash)
|
103
101
|
doc = JSON.parse(account.to_json)
|
@@ -2,17 +2,35 @@ module Eco
|
|
2
2
|
module API
|
3
3
|
module Common
|
4
4
|
module People
|
5
|
+
|
6
|
+
# Class to define/group a set of parsers/serializers.
|
7
|
+
#
|
8
|
+
# @attr_reader schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
|
9
|
+
# @attr_reader details_attrs [Array<String>] internal names of schema details attributes.
|
10
|
+
# @attr_reader all_attrs [Array<String>] all the internal name attributes, including _core_, _account_ and _details_.
|
5
11
|
class PersonParser
|
6
12
|
CORE_ATTRS = ["id", "external_id", "email", "name", "supervisor_id"]
|
7
13
|
ACCOUNT_ATTRS = ["policy_group_ids", "filter_tags", "default_tag"]
|
8
14
|
TYPE = [:select, :text, :date, :number, :phone_number, :boolean, :multiple]
|
15
|
+
FORMAT = [:csv, :xml, :json]
|
9
16
|
|
10
17
|
attr_reader :schema
|
11
18
|
attr_reader :details_attrs, :all_attrs
|
12
19
|
attr_reader :defined_attrs
|
13
20
|
|
14
|
-
|
15
|
-
|
21
|
+
# @example Example of usage:
|
22
|
+
# person_parser = PersonParser.new(schema: schema)
|
23
|
+
# person_parser.define_attribute("example") do |parser|
|
24
|
+
# parser.def_parser do |str, deps|
|
25
|
+
# i = value.to_i rescue 0
|
26
|
+
# i +=5 if deps.dig(:sum_5)
|
27
|
+
# i
|
28
|
+
# end.def_serializer do |value|
|
29
|
+
# value.to_s
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# @param schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
|
33
|
+
def initialize(schema: nil)
|
16
34
|
raise "Constructor needs a PersonSchema. Given: #{schema}" if schema && !schema.is_a?(Ecoportal::API::V1::PersonSchema)
|
17
35
|
@details_attrs = []
|
18
36
|
@parsers = {}
|
@@ -23,49 +41,66 @@ module Eco
|
|
23
41
|
end
|
24
42
|
|
25
43
|
@all_attrs = CORE_ATTRS + ACCOUNT_ATTRS + @details_attrs
|
26
|
-
#init_default_parsers if @schema
|
27
44
|
end
|
28
45
|
|
46
|
+
# Lists all defined attributes, types and formats.
|
47
|
+
# @return [Array<String>] the list of defined parsers/serializers.
|
48
|
+
def list_defined
|
49
|
+
@parsers.keys
|
50
|
+
end
|
51
|
+
|
52
|
+
# Scopes `source_attrs` using the _**core** attributes_.
|
53
|
+
# @note use this helper to know which among your attributes are **core** ones.
|
54
|
+
# @param source_attrs [Array<String>]
|
55
|
+
# @return [Array<String>] the scoped **core** attributes, if `source_attrs` is not `nil`. All the _core attributes_, otherwise.
|
29
56
|
def target_attrs_core(source_attrs = nil)
|
30
57
|
return CORE_ATTRS if !source_attrs
|
31
58
|
scoped_attrs(source_attrs, CORE_ATTRS)
|
32
59
|
end
|
33
60
|
|
61
|
+
# Scopes `source_attrs` using the schema _**details** attributes_.
|
62
|
+
# @note use this helper to know which among your attributes are schema **details** ones.
|
63
|
+
# @param source_attrs [Array<String>]
|
64
|
+
# @return [Array<String>] the scoped **details** attributes, if `source_attrs` is not `nil`. All the _details attributes_, otherwise.
|
34
65
|
def target_attrs_details(source_attrs = nil)
|
35
66
|
return @details_attrs if ! source_attrs
|
36
67
|
scoped_attrs(source_attrs, @details_attrs)
|
37
68
|
end
|
38
69
|
|
70
|
+
# Scopes `source_attrs` using the schema _**account** attributes_.
|
71
|
+
# @note use this helper to know which among your attributes are **account** ones.
|
72
|
+
# @param source_attrs [Array<String>]
|
73
|
+
# @return [Array<String>] the scoped **account** attributes, if `source_attrs` is not `nil`. All the _account attributes_, otherwise.
|
39
74
|
def target_attrs_account(source_attrs = nil)
|
40
75
|
return ACCOUNT_ATTRS if !source_attrs
|
41
76
|
scoped_attrs(source_attrs, ACCOUNT_ATTRS)
|
42
77
|
end
|
43
78
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def list
|
49
|
-
@parsers.keys
|
50
|
-
end
|
51
|
-
|
79
|
+
# Returns a list of all the internal attributes of the model that have a parser defined.
|
80
|
+
# @note it excludes any parser that is not in the model, such as type parsers (i.e. ``:boolean`, ``:multiple`)
|
81
|
+
# @return [Array<String>] list of all attribute defined parsers.
|
52
82
|
def defined_attrs
|
83
|
+
defined = @parsers.keys
|
53
84
|
defined - (defined - all_attrs)
|
54
85
|
end
|
55
86
|
|
87
|
+
# Returns a list of all the internal attributes of the model that do **not** have a parser defined.
|
88
|
+
# @note it excludes any parser that is **not** in the model, such as type parsers (i.e. :boolean, :multiple)
|
89
|
+
# @return [Array<String>] list of all attributes without a defined parser.
|
56
90
|
def undefined_attrs
|
57
91
|
all_attrs - defined_attrs
|
58
92
|
end
|
59
93
|
|
94
|
+
# @param attr [String] internal name of an attribute.
|
95
|
+
# @return [Boolean] `true` if the attribute `attr` has parser defined, and `false` otherwise.
|
60
96
|
def defined?(attr)
|
61
|
-
|
97
|
+
@parsers.key?(attr)
|
62
98
|
end
|
63
99
|
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
|
68
|
-
# merges parser overriding self for exisint parsers
|
100
|
+
# Helper to **merge** a set of parsers of another `PersonParser` into the current object.
|
101
|
+
# @note if there are parsers with same name, it **overrides** the ones of the current object with them.
|
102
|
+
# @param parser [Eco::API::Common::People::PersonParser] a `PersonParser` containing defined parsers.
|
103
|
+
# @return [Eco::API::Common::People::PersonParser] the current object (to ease chainig).
|
69
104
|
def merge(parser)
|
70
105
|
return self if !parser
|
71
106
|
raise "Expected a PersonParser object. Given #{parser}" if !parser.is_a?(PersonParser)
|
@@ -73,16 +108,51 @@ module Eco
|
|
73
108
|
self
|
74
109
|
end
|
75
110
|
|
76
|
-
|
77
|
-
|
111
|
+
|
112
|
+
# Helper to define and associate a parser/serializer to a type or attribute.
|
113
|
+
# @raise [Exception] if trying to define a parser/serializer for:
|
114
|
+
# - an unkown attribute (`String`)
|
115
|
+
# - an unrecognized type or format (`Symbol`)
|
116
|
+
# @param attr [String] type (`Symbol`) or attribute (`String`) to define the parser/serializer to.
|
117
|
+
# @param dependencies [Hash] dependencies to be used when calling the parser/serializer.
|
118
|
+
# @yield [parser] the definition of the parser.
|
119
|
+
# @yieldparam parser [Eco::Language::Models::ParserSerializer] parser to define.
|
120
|
+
# @return [Eco::API::Common::People::PersonParser] the current object (to ease chainig).
|
121
|
+
def define_attribute(attr, dependencies: {}, &definition)
|
122
|
+
if !valid?(attr)
|
123
|
+
msg = "The attribute '#{attr_to_str(attr)}' is not part of core, account or target schema, or does not match any type: #{@details_attrs}"
|
124
|
+
raise msg
|
125
|
+
end
|
126
|
+
|
127
|
+
Eco::Language::Models::ParserSerializer.new(attr, dependencies: dependencies).tap do |parser|
|
128
|
+
@parsers[attr] = parser
|
129
|
+
definition.call(parser)
|
130
|
+
end
|
131
|
+
|
78
132
|
self
|
79
133
|
end
|
80
134
|
|
135
|
+
# Call to parser `source` value of attribute or type `attr` into an internal valid value.
|
136
|
+
# @note dependencies introduced on `parse` call will be merged with those defined during the
|
137
|
+
# initialization of the parser `attr`.
|
138
|
+
# @raise [Exception] if there is **no** parser for attribute or type `attr`.
|
139
|
+
# @param attr [String] target attribute or type to **parse**.
|
140
|
+
# @param source [Any] source value to be parsed.
|
141
|
+
# @param deps [Hash] key-value pairs of call dependencies.
|
142
|
+
# @return [Any] a valid internal value.
|
81
143
|
def parse(attr, source, deps: {})
|
82
144
|
raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr)
|
83
145
|
@parsers[attr].parse(source, dependencies: deps)
|
84
146
|
end
|
85
147
|
|
148
|
+
# Call to serialise `object` value of attribute or type `attr` into an external valid value.
|
149
|
+
# @note dependencies introduced on `serialise` call will be merged with those defined during the
|
150
|
+
# initialization of the parser/serialiser `attr`.
|
151
|
+
# @raise [Exception] if there is **no** serialiser for attribute or type `attr`.
|
152
|
+
# @param attr [String] target attribute or type to **serialize**.
|
153
|
+
# @param object [Any] object value to be serialized.
|
154
|
+
# @param deps [Hash] key-value pairs of call dependencies.
|
155
|
+
# @return a valid external value.
|
86
156
|
def serialize(attr, object, deps: {})
|
87
157
|
raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr)
|
88
158
|
@parsers[attr].serialize(object, dependencies: deps)
|
@@ -90,6 +160,7 @@ module Eco
|
|
90
160
|
|
91
161
|
protected
|
92
162
|
|
163
|
+
# @return [Hash] attr-parser pairs with all the defined type and attribute parsers/serializers.
|
93
164
|
def hash
|
94
165
|
@parsers
|
95
166
|
end
|
@@ -102,35 +173,24 @@ module Eco
|
|
102
173
|
(source_attrs + parsed_attrs) & (direct_attrs + parsed_attrs)
|
103
174
|
end
|
104
175
|
|
105
|
-
def
|
106
|
-
|
107
|
-
str_attr = (attr.is_a?(Symbol) ? ":" : "") + attr.to_s
|
108
|
-
msg = "The attribute '#{str_attr}' is not part of core, account or target schema, or does not match any type: #{@details_attrs}"
|
109
|
-
raise msg
|
110
|
-
end
|
111
|
-
parser = Eco::Language::Models::AttributeParser.new(attr, dependencies: dependencies)
|
112
|
-
#yield(parser)
|
113
|
-
definition.call(parser)
|
114
|
-
parser
|
176
|
+
def attr_to_str(attr)
|
177
|
+
attr.is_a?(Symbol)? ":#{attr.to_s}" : "#{attr.to_s}"
|
115
178
|
end
|
116
179
|
|
117
180
|
def valid?(attr)
|
118
|
-
(attr
|
119
|
-
(attr.is_a?(String) && (!@schema || valid_attr?(attr)))
|
181
|
+
valid_attr?(attr) || valid_type?(attr) || valid_format?(attr)
|
120
182
|
end
|
121
183
|
|
122
184
|
def valid_attr?(attr)
|
123
|
-
@all_attrs.include?(attr)
|
185
|
+
attr.is_a?(String) && (!@schema || @all_attrs.include?(attr))
|
124
186
|
end
|
125
187
|
|
126
188
|
def valid_type?(attr)
|
127
|
-
TYPE.include?(attr)
|
189
|
+
attr.is_a?(Symbol) && TYPE.include?(attr)
|
128
190
|
end
|
129
191
|
|
130
|
-
def
|
131
|
-
|
132
|
-
value = [].push(value) unless value.is_a?(Array)
|
133
|
-
value
|
192
|
+
def valid_format?(attr)
|
193
|
+
attr.is_a?(Symbol) && FORMAT.include?(attr)
|
134
194
|
end
|
135
195
|
|
136
196
|
end
|