Class: Norikra::Field

Inherits:
Object
  • Object
show all
Defined in:
lib/norikra/field.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, type, optional = nil, nullable = false) ⇒ Field

Returns a new instance of Field.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/norikra/field.rb', line 78

def initialize(name, type, optional=nil, nullable=false)
  @name = name.to_s
  @type = self.class.valid_type(type)
  @optional = optional
  @nullable = nullable

  @escaped_name = self.class.escape_name(@name)

  @container_name = @container_type = nil

  @chained_access = !!@name.index('.')
  if @chained_access
    parts = @name.split(/(?<!\.)\./)
    @container_name = parts[0]
    @container_type = parts[1] =~ /^(\$)?\d+$/ ? 'array' : 'hash'
    @optional = true
  end

  define_value_accessor(@name, @chained_access)
end

Instance Attribute Details

#container_nameObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def container_name
  @container_name
end

#container_typeObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def container_type
  @container_type
end

#escaped_nameObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def escaped_name
  @escaped_name
end

#esper_typeObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def esper_type
  @esper_type
end

#nameObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def name
  @name
end

#nullableObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def nullable
  @nullable
end

#optionalObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def optional
  @optional
end

#typeObject

esper types esper.codehaus.org/esper-4.9.0/doc/reference/en-US/html/epl_clauses.html#epl-syntax-datatype string A single character to an unlimited number of characters. boolean A boolean value. integer An integer value (4 byte). long A long value (8 byte). Use the “L” or “l” (lowercase L) suffix. # select 1L as field1, 1l as field2 double A double-precision 64-bit IEEE 754 floating point. # select 1.67 as field1, 167e-2 as field2, 1.67d as field3 float A single-precision 32-bit IEEE 754 floating point. Use the “f” suffix. # select 1.2f as field1, 1.2F as field2 byte A 8-bit signed two’s complement integer. # select 0x10 as field1

norikra types of container hash A single value which is represented as Hash class (ex: parsed json object), and can be nested with hash/array

# select h.value1, h.value2.value3 #<= "h":{"value1":"...","value2":{"value3":"..."}}
Hash key item as "String of Numbers" be escaped with '$$'.
# select h.$$3 #<= "h":{"3":3}

array A single value which is represented as Array class (ex: parsed json array), and can be nested with hash/array

# select h.$0, h.$1.$0.name        #<= "h":["....", [{"name":"value..."}]]

‘integer’ in epser document IS WRONG. If ‘integer’ specified, esper raises this exception: Exception: Nestable type configuration encountered an unexpected property type name ‘integer’ for property ‘status’, expected java.lang.Class or java.util.Map or the name of a previously-declared Map or ObjectArray type Correct type name is ‘int’. see and run ‘junks/esper-test.rb’



38
39
40
# File 'lib/norikra/field.rb', line 38

def type
  @type
end

Class Method Details

.container_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


55
56
57
58
59
60
61
# File 'lib/norikra/field.rb', line 55

def self.container_type?(type)
  case type.to_s.downcase
  when 'hash','array' then true
  else
    false
  end
end

.escape_key_chain(*keys) ⇒ Object



148
149
150
151
152
153
154
# File 'lib/norikra/field.rb', line 148

def self.escape_key_chain(*keys)
  # "hoge", "pos" #=> "hoge$pos"
  # "hoge", 3     #=> "hoge$$3"
  # "hoge", "3"   #=> "hoge$$$3"
  # "hoge", ".pos" #=> "hoge
  regulate_key_chain(keys).join('$')
end

.escape_name(name) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/norikra/field.rb', line 111

def self.escape_name(name)
  # hoge.pos #=> "hoge$pos"
  # hoge.0   #=> "hoge$$0"
  # hoge.$0  #=> "hoge$$0"
  # hoge.$$0 #=> "hoge$$$0"

  # hoge..pos #=> "hoge$_pos"
  # hoge...pos #=> "hoge$__pos"

  parts = name.split(/(?<!\.)\./).map do |part|
    if part =~ /^\d+$/
      '$' + part.to_s
    else
      part.gsub(/[^$_a-zA-Z0-9]/,'_')
    end
  end
  parts.join('$')
end

.esper_type_map(type) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/norikra/field.rb', line 40

def self.esper_type_map(type)
  case type.to_s.downcase
  when 'string' then 'string'
  when 'boolean', 'bool' then 'boolean'
  when 'integer', 'int', 'long' then 'long'
  when 'float', 'double' then 'double'
  when 'hash', 'array'
    raise Norikra::ArgumentError, "#{type} is container field. Don't specify it at open, use it directly."
  when 'byte'
    raise Norikra::ArgumentError, "byte is not supported in Norikra"
  else
    raise Norikra::ArgumentError, "unknown type:#{type}"
  end
end

.regulate_key_chain(keys) ⇒ Object



138
139
140
141
142
143
144
145
146
# File 'lib/norikra/field.rb', line 138

def self.regulate_key_chain(keys)
  keys.map{|key|
    case
    when key.is_a?(Integer) then '$' + key.to_s
    when key.is_a?(String) && key =~ /^[0-9]+$/ then '$$' + key.to_s
    else key.to_s.gsub(/[^$_a-zA-Z0-9]/,'_')
    end
  }
end

.unescape_name(name) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/norikra/field.rb', line 130

def self.unescape_name(name)
  if name.index('$')
    name.split(/(?<!\$)\$/).join('.')
  else
    name
  end
end

.valid_type(type) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/norikra/field.rb', line 63

def self.valid_type(type)
  case type.to_s.downcase
  when 'string' then 'string'
  when 'boolean', 'bool' then 'boolean'
  when 'integer', 'int', 'long' then 'integer'
  when 'float', 'double' then 'float'
  when 'hash' then 'hash'
  when 'array' then 'array'
  when 'byte'
    raise Norikra::ArgumentError, "byte is not supported in Norikra"
  else
    raise Norikra::ArgumentError, "invalid field type '#{type}'"
  end
end

Instance Method Details

#==(other) ⇒ Object



168
169
170
# File 'lib/norikra/field.rb', line 168

def ==(other)
  self.name == other.name && self.type == other.type && self.optional == other.optional && self.nullable == other.nullable
end

#chained_access?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/norikra/field.rb', line 99

def chained_access?
  @chained_access
end

#container_field?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/norikra/field.rb', line 103

def container_field?
  self.class.container_type?(@type)
end

#define_value_accessor(name, chained) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/norikra/field.rb', line 208

def define_value_accessor(name, chained)
  # "fieldname" -> def value(event) ; event["fieldname"] ; end
  # "fieldname.key1" -> def value(event) ; event["fieldname"]["key1"] ; end
  # "fieldname.key1.$$2" -> def value(event) ; event["fieldname"]["key1"]["2"] ; end
  # "fieldname.2" -> def value(event) ; event["fieldname"][2] ; end
  # "fieldname.$2" -> def value(event) ; event["fieldname"][2] ; end

  unless chained
    @accessors = [name]
    self.instance_eval do
      def value(event)
        event[@accessors.first]
      end
    end
    return
  end

  @accessors = name.split(/(?<!\.)\./).map do |part|
    case part
    when /^\d+$/ then part.to_i
    when /^\$(\d+)$/ then $1.to_i
    when /^\$\$(\d+)$/ then $1.to_s
    else part
    end
  end
  self.instance_eval do
    def safe_fetch(v, accessor)
      unless accessor.is_a?(String) || accessor.is_a?(Fixnum)
        raise ::ArgumentError, "container_accessor must be a String or Interger, but #{accessor.class.to_s}"
      end
      if v.is_a?(Hash)
        # v[accessor] || v[accessor.to_s]
        if v.has_key?(accessor)
          v[accessor]
        elsif v.has_key?(accessor.to_s)
          v[accessor.to_s]
        elsif accessor.is_a?(String)
          val = v.keys.reduce(nil) do |r, key|
            if key.is_a?(String)
              r || ( key.gsub(/[^$_a-zA-Z0-9]/, '_') == accessor.to_s ? v[key] : nil )
            else
              r
            end
          end
          val # valid value or nil
        else # v does not have key "#{accessor}" and accessor is Fixnum
          nil
        end
      elsif v.is_a?(Array)
        if accessor.is_a?(Fixnum)
          v[accessor]
        else # String -> Hash expected
          nil
        end
      else # non-container value
        nil
      end
    end
    def value(event)
      @accessors.reduce(event){|e,a| safe_fetch(e, a)}
    end
  end
end

#dup(optional = nil) ⇒ Object



164
165
166
# File 'lib/norikra/field.rb', line 164

def dup(optional=nil)
  self.class.new(@name, @type, optional.nil? ? @optional : optional, @nullable)
end

#format(value, element_path = nil) ⇒ Object

def value(event) # by define_value_accessor



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/norikra/field.rb', line 182

def format(value, element_path=nil) #element_path ex: 'fname.fchild', 'fname.$0', 'f.fchild.$2'
  return nil if value.nil? || value.is_a?(Hash) || value.is_a?(Array)

  case @type
  when 'string'  then value.to_s.force_encoding('UTF-8')
  when 'boolean'
    if value.is_a?(TrueClass) || value.is_a?(FalseClass)
      value
    elsif value.is_a?(String)
      if value =~ /^(true|false)$/i
        value.downcase == 'true'
      else
        !!value
      end
    else
      !!value
    end
  when 'integer' then value.to_i
  when 'float' then value.to_f
  when 'hash', 'array'
    raise RuntimeError, "container field not permitted to access directly, maybe BUG. name:#{@name},type:#{@type}"
  else
    raise RuntimeError, "unknown field type (in format), maybe BUG. name:#{@name},type:#{@type}"
  end
end

#nullable?Boolean

Returns:

  • (Boolean)


176
177
178
# File 'lib/norikra/field.rb', line 176

def nullable?
  @nullable
end

#optional?Boolean

used outside of FieldSet

Returns:

  • (Boolean)


172
173
174
# File 'lib/norikra/field.rb', line 172

def optional? # used outside of FieldSet
  @optional
end

#to_hash(sym = false) ⇒ Object



156
157
158
159
160
161
162
# File 'lib/norikra/field.rb', line 156

def to_hash(sym=false)
  if sym
    {name: @name, type: @type, optional: @optional, nullable: @nullable}
  else
    {'name' => @name, 'type' => @type, 'optional' => @optional, 'nullable' => @nullable}
  end
end