icss-activesupport-4 0.4.0
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 +7 -0
- data/.document +5 -0
- data/.rspec +3 -0
- data/.watchr +52 -0
- data/CHANGELOG.md +38 -0
- data/Gemfile +22 -0
- data/LICENSE.textile +20 -0
- data/README.md +298 -0
- data/Rakefile +39 -0
- data/TODO.md +44 -0
- data/VERSION +1 -0
- data/examples/avro_examples/BulkData.avpr +21 -0
- data/examples/avro_examples/complicated.icss.yaml +159 -0
- data/examples/avro_examples/interop.avsc +32 -0
- data/examples/avro_examples/mail.avpr +20 -0
- data/examples/avro_examples/namespace.avpr +28 -0
- data/examples/avro_examples/org/apache/avro/ipc/HandshakeRequest.avsc +11 -0
- data/examples/avro_examples/org/apache/avro/ipc/HandshakeResponse.avsc +15 -0
- data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avdl +64 -0
- data/examples/avro_examples/org/apache/avro/ipc/trace/avroTrace.avpr +82 -0
- data/examples/avro_examples/org/apache/avro/mapred/tether/InputProtocol.avpr +59 -0
- data/examples/avro_examples/org/apache/avro/mapred/tether/OutputProtocol.avpr +75 -0
- data/examples/avro_examples/simple.avpr +70 -0
- data/examples/avro_examples/weather.avsc +9 -0
- data/examples/bnc.icss.yaml +70 -0
- data/examples/chronic.icss.yaml +115 -0
- data/examples/license.icss.yaml +7 -0
- data/examples/source1.icss.yaml +4 -0
- data/examples/source2.icss.yaml +4 -0
- data/examples/test_icss.yaml +67 -0
- data/icss.gemspec +168 -0
- data/icss_specification.textile +393 -0
- data/lib/icss.rb +53 -0
- data/lib/icss/core_types.rb +20 -0
- data/lib/icss/error.rb +4 -0
- data/lib/icss/init.rb +3 -0
- data/lib/icss/message.rb +133 -0
- data/lib/icss/message/message_sample.rb +144 -0
- data/lib/icss/protocol.rb +199 -0
- data/lib/icss/protocol/code_asset.rb +18 -0
- data/lib/icss/protocol/data_asset.rb +23 -0
- data/lib/icss/protocol/license.rb +41 -0
- data/lib/icss/protocol/source.rb +37 -0
- data/lib/icss/protocol/target.rb +68 -0
- data/lib/icss/receiver_model.rb +24 -0
- data/lib/icss/receiver_model/active_model_shim.rb +36 -0
- data/lib/icss/receiver_model/acts_as_catalog.rb +174 -0
- data/lib/icss/receiver_model/acts_as_hash.rb +177 -0
- data/lib/icss/receiver_model/acts_as_loadable.rb +47 -0
- data/lib/icss/receiver_model/acts_as_tuple.rb +100 -0
- data/lib/icss/receiver_model/locale/en.yml +27 -0
- data/lib/icss/receiver_model/to_geo_json.rb +19 -0
- data/lib/icss/receiver_model/tree_merge.rb +34 -0
- data/lib/icss/receiver_model/validations.rb +31 -0
- data/lib/icss/serialization.rb +51 -0
- data/lib/icss/serialization/zaml.rb +442 -0
- data/lib/icss/type.rb +168 -0
- data/lib/icss/type/base_type.rb +0 -0
- data/lib/icss/type/named_type.rb +185 -0
- data/lib/icss/type/record_field.rb +77 -0
- data/lib/icss/type/record_model.rb +49 -0
- data/lib/icss/type/record_schema.rb +54 -0
- data/lib/icss/type/record_type.rb +325 -0
- data/lib/icss/type/simple_types.rb +71 -0
- data/lib/icss/type/structured_schema.rb +288 -0
- data/lib/icss/type/type_factory.rb +144 -0
- data/lib/icss/type/union_schema.rb +41 -0
- data/lib/icss/view_helper.rb +65 -0
- data/notes/named_array.md +32 -0
- data/notes/on_include_vs_extend_etc.rb +176 -0
- data/notes/technical_details.md +278 -0
- data/spec/core_types_spec.rb +119 -0
- data/spec/fixtures/zaml_complex_hash.yaml +35 -0
- data/spec/icss_spec.rb +90 -0
- data/spec/message/message_sample_spec.rb +4 -0
- data/spec/message_spec.rb +139 -0
- data/spec/protocol/license_spec.rb +67 -0
- data/spec/protocol/protocol_catalog_spec.rb +48 -0
- data/spec/protocol/protocol_validations_spec.rb +176 -0
- data/spec/protocol/source_spec.rb +65 -0
- data/spec/protocol_spec.rb +170 -0
- data/spec/receiver_model_spec.rb +115 -0
- data/spec/serialization/zaml_spec.rb +82 -0
- data/spec/serialization/zaml_test.rb +473 -0
- data/spec/serialization_spec.rb +63 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/icss_test_helper.rb +67 -0
- data/spec/support/load_example_protocols.rb +17 -0
- data/spec/type/base_type_spec.rb +0 -0
- data/spec/type/named_type_spec.rb +75 -0
- data/spec/type/record_field_spec.rb +44 -0
- data/spec/type/record_model_spec.rb +206 -0
- data/spec/type/record_schema_spec.rb +161 -0
- data/spec/type/record_type_spec.rb +155 -0
- data/spec/type/simple_types_spec.rb +121 -0
- data/spec/type/structured_schema_spec.rb +300 -0
- data/spec/type/type_catalog_spec.rb +44 -0
- data/spec/type/type_factory_spec.rb +93 -0
- data/spec/type/union_schema_spec.rb +0 -0
- data/spec/type_spec.rb +63 -0
- metadata +304 -0
data/lib/icss/type.rb
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
module Icss
|
|
2
|
+
module Meta
|
|
3
|
+
module Type
|
|
4
|
+
include Icss::ReceiverModel::ActsAsCatalog
|
|
5
|
+
def self.catalog_sections
|
|
6
|
+
::Icss::Meta::Protocol.catalog_sections
|
|
7
|
+
end
|
|
8
|
+
def self.receive(hsh)
|
|
9
|
+
::Icss::Meta::Protocol.receive(hsh)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# Predefining the namespaces here makes inclusion-order less brittle.
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
# full definitions in type/simple_types.rb
|
|
19
|
+
class ::Boolean < ::BasicObject ; end
|
|
20
|
+
class ::Long < ::Integer ; end
|
|
21
|
+
class ::Double < ::Float ; end
|
|
22
|
+
class ::Binary < ::String ; end
|
|
23
|
+
|
|
24
|
+
# patron saint of Simple Types (Structured Text)
|
|
25
|
+
module St ; end
|
|
26
|
+
# pasture wherein graze MeasurementUnits
|
|
27
|
+
module Mu ; end
|
|
28
|
+
# stand in the place where you are
|
|
29
|
+
module Business ; end
|
|
30
|
+
#
|
|
31
|
+
module Culture ; end
|
|
32
|
+
# we gots the whhole worl innour hans
|
|
33
|
+
module Encyclopedic ; end
|
|
34
|
+
# Eventfully, Tom phoned the caterer.
|
|
35
|
+
module Ev ; end
|
|
36
|
+
#
|
|
37
|
+
module Geo ; end
|
|
38
|
+
# Relatively speaking, this is where links and relations go
|
|
39
|
+
module Rel ; end
|
|
40
|
+
# I don't want to sell anything, buy anything, or process anything as a career.
|
|
41
|
+
# I don't want to sell anything bought or processed, or buy anything sold or processed, or process
|
|
42
|
+
# anything sold, bought, or processed, or repair anything sold, bought, or processed.
|
|
43
|
+
# You know, as a career, I don't want to do that.
|
|
44
|
+
module Prod ; end
|
|
45
|
+
#
|
|
46
|
+
module Social ; end
|
|
47
|
+
# Oh what a tangled web we weave when first we practice to receive
|
|
48
|
+
module Web ; end
|
|
49
|
+
# Raw records, for use by data mungers
|
|
50
|
+
module Raw ; end
|
|
51
|
+
|
|
52
|
+
# Buffalo Buffalo buffalo Buffalo Buffalo Buffalo buffalo.
|
|
53
|
+
module Meta
|
|
54
|
+
# full definitions in type/structured_schema.rb and type/union_schema.rb
|
|
55
|
+
class NamedSchema ; end
|
|
56
|
+
class SimpleSchema < NamedSchema ; end
|
|
57
|
+
class UnionSchema < NamedSchema ; end
|
|
58
|
+
class RecordSchema < SimpleSchema ; end
|
|
59
|
+
class ErrorSchema < RecordSchema ; end
|
|
60
|
+
#
|
|
61
|
+
class StructuredSchema < NamedSchema ; end
|
|
62
|
+
class HashSchema < StructuredSchema ; end
|
|
63
|
+
class ArraySchema < StructuredSchema ; end
|
|
64
|
+
class FixedSchema < StructuredSchema ; end
|
|
65
|
+
class EnumSchema < StructuredSchema ; end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
::Icss::SIMPLE_TYPES = {} unless defined?( ::Icss::SIMPLE_TYPES )
|
|
69
|
+
::Icss::FACTORY_TYPES = {} unless defined?( ::Icss::FACTORY_TYPES )
|
|
70
|
+
::Icss::STRUCTURED_SCHEMAS = {} unless defined?( ::Icss::STRUCTURED_SCHEMAS )
|
|
71
|
+
::Icss::UNION_SCHEMAS = {} unless defined?( ::Icss::UNION_SCHEMAS )
|
|
72
|
+
|
|
73
|
+
unless defined?(::Icss::AVRO_TYPES)
|
|
74
|
+
::Icss::AVRO_TYPES = {
|
|
75
|
+
:null => ::NilClass,
|
|
76
|
+
:boolean => ::Boolean,
|
|
77
|
+
:int => ::Integer,
|
|
78
|
+
:long => ::Long,
|
|
79
|
+
:float => ::Float,
|
|
80
|
+
:double => ::Double,
|
|
81
|
+
:string => ::String,
|
|
82
|
+
:bytes => ::Binary,
|
|
83
|
+
}.freeze
|
|
84
|
+
end
|
|
85
|
+
::Icss::SIMPLE_TYPES.merge!(::Icss::AVRO_TYPES)
|
|
86
|
+
|
|
87
|
+
::Icss::SIMPLE_TYPES.merge!({
|
|
88
|
+
:binary => ::Binary,
|
|
89
|
+
:symbol => ::Symbol,
|
|
90
|
+
:time => ::Time,
|
|
91
|
+
:integer => ::Integer,
|
|
92
|
+
:numeric => ::Numeric,
|
|
93
|
+
:regexp => ::Regexp,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
::Icss::STRUCTURED_SCHEMAS.merge!({
|
|
97
|
+
:simple => Icss::Meta::SimpleSchema,
|
|
98
|
+
:record => Icss::Meta::RecordSchema,
|
|
99
|
+
:error => Icss::Meta::ErrorSchema,
|
|
100
|
+
:map => Icss::Meta::HashSchema,
|
|
101
|
+
:hash => Icss::Meta::HashSchema,
|
|
102
|
+
Hash => Icss::Meta::HashSchema,
|
|
103
|
+
:array => Icss::Meta::ArraySchema,
|
|
104
|
+
Array => Icss::Meta::ArraySchema,
|
|
105
|
+
:fixed => Icss::Meta::FixedSchema,
|
|
106
|
+
:enum => Icss::Meta::EnumSchema,
|
|
107
|
+
})
|
|
108
|
+
::Icss::UNION_SCHEMAS.merge!({
|
|
109
|
+
:union => Icss::Meta::UnionSchema,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
module Meta
|
|
113
|
+
module Type
|
|
114
|
+
#:nodoc:
|
|
115
|
+
NORMAL_NAMED_CONSTANT_RE = /\A[\w\:\.]+\z/ unless defined?(NORMAL_NAMED_CONSTANT_RE)
|
|
116
|
+
|
|
117
|
+
# Turns a type name into its dotted (avro-style) name, regardless of its
|
|
118
|
+
# current form.
|
|
119
|
+
#
|
|
120
|
+
# @example
|
|
121
|
+
# Icss::Meta::Type.fullname_for(Icss::This::That::TheOther) # 'this.that.the_other'
|
|
122
|
+
# Icss::Meta::Type.fullname_for("Icss::This::That::TheOther") # 'this.that.the_other'
|
|
123
|
+
# Icss::Meta::Type.fullname_for('this.that.the_other') # 'this.that.the_other'
|
|
124
|
+
#
|
|
125
|
+
def self.fullname_for(klass_name)
|
|
126
|
+
return nil unless klass_name.present? && (klass_name.to_s =~ NORMAL_NAMED_CONSTANT_RE)
|
|
127
|
+
klass_name.to_s.gsub(/^:*Icss::/, '').underscore.gsub(%r{/},".")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Converts a type name to its ruby (camel-cased) form. Works on class,
|
|
131
|
+
# name of class, or dotted (avro-style) namespace.name. Names will have
|
|
132
|
+
# an 'Icss::' prefix.
|
|
133
|
+
#
|
|
134
|
+
# @example
|
|
135
|
+
# Icss::Meta::Type.fullname_for('this.that.the_other') # "Icss::This::That::TheOther"
|
|
136
|
+
# Icss::Meta::Type.fullname_for(Icss::This::That::TheOther) # "Icss::This::That::TheOther"
|
|
137
|
+
# Icss::Meta::Type.fullname_for("Icss::This::That::TheOther") # "Icss::This::That::TheOther"
|
|
138
|
+
#
|
|
139
|
+
def self.klassname_for(obj)
|
|
140
|
+
return nil unless obj.present? && (obj.to_s =~ NORMAL_NAMED_CONSTANT_RE)
|
|
141
|
+
nm = obj.to_s.gsub(/^:*Icss:+/, '').
|
|
142
|
+
gsub(%r{::},'.').
|
|
143
|
+
split('.').map(&:camelize).join('::')
|
|
144
|
+
"::Icss::#{nm}"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.schema_for(obj)
|
|
148
|
+
case
|
|
149
|
+
when obj.respond_to?(:to_schema) then obj.to_schema
|
|
150
|
+
when str = fullname_for(obj) then str.to_sym
|
|
151
|
+
else nil ; end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# true if class is among the defined primitive types:
|
|
155
|
+
# null boolean integer long float double string binary
|
|
156
|
+
# and so forth
|
|
157
|
+
#
|
|
158
|
+
# note this takes no account of inheritance -- only the types specifically
|
|
159
|
+
# listed in Icss::SIMPLE_TYPES are simple
|
|
160
|
+
def self.simple?(tt) ::Icss::SIMPLE_TYPES.has_value?(tt) ; end
|
|
161
|
+
|
|
162
|
+
def self.union?(tt) false ; end
|
|
163
|
+
|
|
164
|
+
def self.record?(tt) false ; end
|
|
165
|
+
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
module Icss
|
|
2
|
+
module Meta
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# Record, Error, Enum and Fixed are named types. Each has a fullname that is
|
|
6
|
+
# composed of two parts; a name and a namespace. Equality of names is
|
|
7
|
+
# defined on the fullname.
|
|
8
|
+
#
|
|
9
|
+
# The name portion of a fullname, and record field names, must:
|
|
10
|
+
#
|
|
11
|
+
# * start with [A-Za-z_]
|
|
12
|
+
# * subsequently contain only [A-Za-z0-9_]
|
|
13
|
+
# * A namespace is a dot-separated sequence of such names.
|
|
14
|
+
#
|
|
15
|
+
# References to previously defined names are as in the latter two cases above:
|
|
16
|
+
# if they contain a dot they are a fullname, if they do not contain a dot, the
|
|
17
|
+
# namespace is the namespace of the enclosing definition.
|
|
18
|
+
#
|
|
19
|
+
# Simple type names have no namespace and their names may not be defined in
|
|
20
|
+
# any namespace. A schema may only contain multiple definitions of a
|
|
21
|
+
# fullname if the definitions are equivalent.
|
|
22
|
+
#
|
|
23
|
+
module NamedType
|
|
24
|
+
def doc() "" end
|
|
25
|
+
def doc=(str)
|
|
26
|
+
singleton_class.class_eval do
|
|
27
|
+
remove_possible_method(:doc)
|
|
28
|
+
define_method(:doc){ str }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
#
|
|
32
|
+
def fullname
|
|
33
|
+
::Icss::Meta::Type.fullname_for(self.name)
|
|
34
|
+
end
|
|
35
|
+
def basename
|
|
36
|
+
@basename ||= fullname.to_s.gsub(/.*[\.]/, "")
|
|
37
|
+
end
|
|
38
|
+
def namespace
|
|
39
|
+
@namespace ||= fullname.to_s.include?('.') ? fullname.to_s.gsub(/\.[^\.]+\z/so, '') : ''
|
|
40
|
+
end
|
|
41
|
+
def pathname
|
|
42
|
+
fullname.to_s.gsub(/\./, '/')
|
|
43
|
+
end
|
|
44
|
+
#
|
|
45
|
+
def to_schema
|
|
46
|
+
if respond_to?(:_schema) then return _schema.to_hash ; end
|
|
47
|
+
{
|
|
48
|
+
:name => fullname,
|
|
49
|
+
# :namespace => namespace,
|
|
50
|
+
:doc => doc,
|
|
51
|
+
}.compact_blank
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def is_core?
|
|
55
|
+
respond_to?(:_schema) && _schema.is_core?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# ---------------------------------------------------------------------------
|
|
59
|
+
#
|
|
60
|
+
# Type Factory methods
|
|
61
|
+
#
|
|
62
|
+
|
|
63
|
+
#
|
|
64
|
+
# Returns the metamodel -- a module extending the type, on which all the
|
|
65
|
+
# accessors and receive methods are inscribed. (This allows you to call
|
|
66
|
+
# +super()+ from within receive_foo)
|
|
67
|
+
#
|
|
68
|
+
def metamodel
|
|
69
|
+
return @metamodel if @metamodel
|
|
70
|
+
@metamodel = Icss::Meta::NamedType.get_meta_module(self.to_s)
|
|
71
|
+
self.class_eval{ include(@metamodel) }
|
|
72
|
+
@metamodel
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
#
|
|
76
|
+
# Manufactures klass and metamodel
|
|
77
|
+
#
|
|
78
|
+
# for type science.astronomy.ufo_sighting, we synthesize
|
|
79
|
+
# * a module, ::Icss::Meta::Science::Astronomy::UfoSightingType
|
|
80
|
+
# * a class, ::Icss::Science::Astronomy::UfoSighting
|
|
81
|
+
#
|
|
82
|
+
# If no superklass is given, Icss::Entity is used.
|
|
83
|
+
def self.make(fullname, superklass)
|
|
84
|
+
klass = get_model_klass(fullname, superklass)
|
|
85
|
+
metamodel = get_meta_module(klass.to_s)
|
|
86
|
+
klass.class_eval{ extend(::Icss::Meta::NamedType) }
|
|
87
|
+
klass.class_eval{ include(metamodel) }
|
|
88
|
+
[klass, metamodel]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
protected
|
|
92
|
+
|
|
93
|
+
def define_metamodel_method(meth_name, visibility=:public, &blk)
|
|
94
|
+
metamodel.class_eval do
|
|
95
|
+
define_method(meth_name, &blk) unless method_defined?(meth_name)
|
|
96
|
+
case visibility
|
|
97
|
+
when :protected then protected meth_name
|
|
98
|
+
when :private then private meth_name
|
|
99
|
+
when :public then public meth_name
|
|
100
|
+
else raise ArgumentError, "visibility must be :public, :private or :protected"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns the klass for the given scope and name, starting with '::Icss'
|
|
106
|
+
# and creating all necessary parents along the way. Note that if the given
|
|
107
|
+
# class or its parent scopes already exist, they're trusted to be correct
|
|
108
|
+
# -- we don't do any error checking as to their type or superclass.
|
|
109
|
+
#
|
|
110
|
+
# @example
|
|
111
|
+
# Icss::Meta::Type.get_model_klass('this.that.the_other')
|
|
112
|
+
# # Icss::This::That::TheOther
|
|
113
|
+
#
|
|
114
|
+
# @param scope_names [Array of String]
|
|
115
|
+
# @param superklass [Class] - the superclass to use if the class doesn't exist.
|
|
116
|
+
def self.get_model_klass(fn, superklass)
|
|
117
|
+
fullname = Icss::Meta::Type.fullname_for(fn)
|
|
118
|
+
return Class.new(superklass) if fullname.nil?
|
|
119
|
+
#
|
|
120
|
+
scope_names = scope_names_for(fullname)
|
|
121
|
+
klass_name = scope_names.pop
|
|
122
|
+
parent_module = get_nested_module(%w[Icss] + scope_names)
|
|
123
|
+
|
|
124
|
+
# const_defined?(klass, inherit), const_get(klass, inherit)
|
|
125
|
+
# inherit = false makes these methods be scoped to parent_module instead of universally
|
|
126
|
+
if parent_module.const_defined?(klass_name, false)
|
|
127
|
+
klass = parent_module.const_get(klass_name, false)
|
|
128
|
+
# #{superklass.object_id}: #{klass.ancestors.map{|o| [o, o.object_id] }}
|
|
129
|
+
unless klass.ancestors.include?(superklass)
|
|
130
|
+
warn "+++++++++++++++++++++++++++++++ Superclass and is_a? mismatch for #{klass.inspect} (doesn't inherit from #{superklass.inspect})"
|
|
131
|
+
# p [klass_name, klass, Icss::Thing.object_id, ::Icss::Thing.object_id, Icss.const_get(:Thing).object_id,]
|
|
132
|
+
# p klass .ancestors.flatten.map{|t| [t, t.object_id]}
|
|
133
|
+
# p Icss::Thing.ancestors.flatten.map{|t| [t, t.object_id]}
|
|
134
|
+
end
|
|
135
|
+
klass
|
|
136
|
+
else
|
|
137
|
+
parent_module.const_set(klass_name, Class.new(superklass))
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Returns the meta-module for the given scope and name, starting with
|
|
142
|
+
# '::Icss::Meta' and creating all necessary parents along the way.
|
|
143
|
+
#
|
|
144
|
+
# @example
|
|
145
|
+
# Icss::Meta::TypeFactory.get_meta_module(["This", "That"], "TheOther")
|
|
146
|
+
# # Icss::Meta::This::That::TheOtherModel
|
|
147
|
+
def self.get_meta_module(fullname)
|
|
148
|
+
fullname = Icss::Meta::Type.fullname_for(fullname)
|
|
149
|
+
return Module.new if fullname.nil?
|
|
150
|
+
#
|
|
151
|
+
scope_names = scope_names_for(fullname)
|
|
152
|
+
scope_names[-1] += "Model"
|
|
153
|
+
get_nested_module(%w[Icss Meta] + scope_names)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Turns a dotted namespace.name into camelized rubylike names for a class
|
|
157
|
+
# @example
|
|
158
|
+
# scope_names_for('this.that.the_other')
|
|
159
|
+
# # ["This", "That", "TheOther"]
|
|
160
|
+
def self.scope_names_for(fullname)
|
|
161
|
+
fullname.split('.').map(&:camelize)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Returns a module for the given scope names, rooted always at Object (so
|
|
165
|
+
# implicity with '::').
|
|
166
|
+
# @example
|
|
167
|
+
# get_nested_module(["This", "That", "TheOther"])
|
|
168
|
+
# # This::That::TheOther
|
|
169
|
+
def self.get_nested_module(scope_names)
|
|
170
|
+
scope_names.inject(Object) do |parent_module, module_name|
|
|
171
|
+
|
|
172
|
+
# const_defined?(klass, inherit), const_get(klass, inherit)
|
|
173
|
+
# inherit = false makes these methods be scoped to parent_module instead of universally
|
|
174
|
+
if parent_module.const_defined?(module_name, false)
|
|
175
|
+
parent_module.const_get(module_name, false)
|
|
176
|
+
else
|
|
177
|
+
parent_module.const_set(module_name.to_sym, Module.new)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module Icss
|
|
2
|
+
module Meta
|
|
3
|
+
|
|
4
|
+
class RecordField
|
|
5
|
+
include Icss::Meta::RecordModel
|
|
6
|
+
include Icss::ReceiverModel::ActsAsHash
|
|
7
|
+
include Gorillib::Hashlike
|
|
8
|
+
include Gorillib::Hashlike::Keys
|
|
9
|
+
include Icss::ReceiverModel
|
|
10
|
+
include Icss::ReceiverModel::ActiveModelShim
|
|
11
|
+
remove_possible_method(:type)
|
|
12
|
+
|
|
13
|
+
ALLOWED_ORDERS = %w[ascending descending ignore].freeze unless defined?(ALLOWED_ORDERS)
|
|
14
|
+
|
|
15
|
+
field :name, Symbol, :required => true
|
|
16
|
+
field :type, Icss::Meta::TypeFactory, :required => true
|
|
17
|
+
field :doc, String
|
|
18
|
+
field :default, Icss::Meta::IdenticalFactory
|
|
19
|
+
field :replace, Hash
|
|
20
|
+
field :required, Boolean
|
|
21
|
+
field :aliases, Array, :items => Symbol
|
|
22
|
+
field :order, String, :validates => { :inclusion => { :in => ALLOWED_ORDERS } }
|
|
23
|
+
field :accessor, Symbol
|
|
24
|
+
field :receiver, Symbol
|
|
25
|
+
field :validates, Hash
|
|
26
|
+
rcvr_remaining :_extra_params
|
|
27
|
+
attr_accessor :parent
|
|
28
|
+
|
|
29
|
+
# FIXME: cruft
|
|
30
|
+
field :indexed_on, Symbol
|
|
31
|
+
field :identifier, Boolean, :doc => 'indicates the field is suitable for use'
|
|
32
|
+
|
|
33
|
+
after_receive(:warnings) do |hsh|
|
|
34
|
+
# warn "Extra params given to field #{self}: #{_extra_params.inspect}" if _extra_params.present?
|
|
35
|
+
warn "Validation failed for field #{self}: #{errors.inspect}" if respond_to?(:errors) && (not valid?)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# track recursion of type references
|
|
39
|
+
after_receive(:am_i_a_reference) do |hsh|
|
|
40
|
+
hsh = hsh.symbolize_keys
|
|
41
|
+
nonreference_klasses = [::Icss::Meta::ArrayType, ::Icss::Meta::HashType, ::Icss::Meta::EnumType, ::Icss::Meta::FixedType]
|
|
42
|
+
|
|
43
|
+
@is_reference = (hsh[:type].is_a?(String) || hsh[:type].is_a?(Symbol) || (hsh[:type].is_a?(Class) && nonreference_klasses.none?{|klass| hsh[:type].is_a?(klass) }))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# is the field a reference to a named type (true), or an inline schema (false)?
|
|
47
|
+
def is_reference?() @is_reference ; end
|
|
48
|
+
|
|
49
|
+
def to_hash()
|
|
50
|
+
hsh = super
|
|
51
|
+
hsh = hsh.merge({ :type => (is_reference? ? type.fullname : Type.schema_for(type)) })
|
|
52
|
+
hsh.delete(:_extra_params)
|
|
53
|
+
hsh
|
|
54
|
+
end
|
|
55
|
+
def to_schema
|
|
56
|
+
to_hash
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Hack hack -- makes it so fields go thru the receiver door when merged in RecordType
|
|
60
|
+
def merge(hsh)
|
|
61
|
+
dup.receive!(hsh)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Order is defined by the avro spec
|
|
65
|
+
def order() @order || 'ascending' ; end
|
|
66
|
+
def order_direction() case order when 'ascending' then 1 when 'descending' then -1 else 0 ; end ; end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
module RecordType
|
|
70
|
+
protected
|
|
71
|
+
# create new field_schema as a RecordField object, not Hash
|
|
72
|
+
def make_field_schema
|
|
73
|
+
RecordField.new
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Icss
|
|
2
|
+
module Meta
|
|
3
|
+
|
|
4
|
+
module RecordModel
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(Icss::Meta::RecordType)
|
|
7
|
+
base.metamodel
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# modify object in place with new typecast values.
|
|
12
|
+
#
|
|
13
|
+
def receive!(hsh={})
|
|
14
|
+
raise ArgumentError, "Can't receive (it isn't hashlike): {#{hsh.inspect}}" unless hsh.respond_to?(:[]) && hsh.respond_to?(:has_key?)
|
|
15
|
+
self.class.send(:_rcvr_methods).each do |attr, meth|
|
|
16
|
+
if hsh.has_key?(attr) then val = hsh[attr]
|
|
17
|
+
elsif hsh.has_key?(attr.to_s) then val = hsh[attr.to_s]
|
|
18
|
+
else next ; end
|
|
19
|
+
self.send(meth, val)
|
|
20
|
+
end
|
|
21
|
+
run_after_receivers(hsh)
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# true if the attr is a receiver variable and it has been set
|
|
26
|
+
def attr_set?(attr)
|
|
27
|
+
self.class.has_field?(attr) && self.instance_variable_defined?("@#{attr}")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def unset!(attr)
|
|
31
|
+
self.send(:remove_instance_variable, "@#{attr}") if self.instance_variable_defined?("@#{attr}")
|
|
32
|
+
end
|
|
33
|
+
protected :unset!
|
|
34
|
+
|
|
35
|
+
protected
|
|
36
|
+
|
|
37
|
+
def run_after_receivers(hsh)
|
|
38
|
+
self.class.after_receivers.each do |after_hook_name, after_hook|
|
|
39
|
+
self.instance_exec(hsh, &after_hook)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _set_field_val(field_name, val)
|
|
44
|
+
self.instance_variable_set("@#{field_name}", val)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|