odba 1.1.8 → 1.2.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.
data/lib/odba/stub.rb CHANGED
@@ -1,190 +1,203 @@
1
1
  #!/usr/bin/env ruby
2
2
  #-- Stub -- odba -- 29.04.2004 -- hwyss@ywesee.com rwaltert@ywesee.com mwalder@ywesee.com
3
3
 
4
- require 'yaml'
5
- require 'odba/odba_error'
4
+ require "yaml"
5
+ require "odba/odba_error"
6
6
 
7
7
  module ODBA
8
- class Stub # :nodoc: all
9
- attr_accessor :odba_id, :odba_container
10
- def initialize(odba_id, odba_container, receiver)
11
- @odba_id = odba_id
12
- @odba_container = odba_container
13
- @odba_class = receiver.class unless receiver.nil?
8
+ class Stub # :nodoc: all
9
+ attr_accessor :odba_id, :odba_container
10
+ def initialize(odba_id, odba_container, receiver)
11
+ @odba_id = odba_id
12
+ @odba_container = odba_container
13
+ @odba_class = receiver.class unless receiver.nil?
14
14
  @receiver_loaded = true
15
- end
16
- def class
17
- @odba_class ||= odba_instance.class
18
- end
19
- def eql?(other)
20
- @odba_id == other.odba_id || odba_instance.eql?(other)
21
- end
22
- def inspect
23
- "#<ODBA::Stub:#{object_id}##@odba_id @odba_class=#@odba_class @odba_container=#{@odba_container.object_id}##{@odba_container.odba_id}>"
24
- end
25
- def is_a?(klass)
15
+ end
16
+
17
+ def class
18
+ @odba_class ||= odba_instance.class
19
+ end
20
+
21
+ def eql?(other)
22
+ @odba_id == other.odba_id || odba_instance.eql?(other)
23
+ end
24
+
25
+ def inspect
26
+ "#<ODBA::Stub:#{object_id}##{@odba_id} @odba_class=#{@odba_class} @odba_container=#{@odba_container.object_id}##{@odba_container.odba_id}>"
27
+ end
28
+
29
+ def is_a?(klass)
26
30
  klass == Stub || klass == Persistable || klass == @odba_class \
27
- || odba_instance.is_a?(klass)
28
- end
29
- def odba_clear_receiver
30
- @receiver = nil
31
+ || odba_instance.is_a?(klass)
32
+ end
33
+
34
+ def odba_clear_receiver
35
+ @receiver = nil
31
36
  @receiver_loaded = nil
32
- end
37
+ end
38
+
33
39
  def odba_dup
34
40
  odba_isolated_stub
35
41
  end
36
- def odba_isolated_stub
37
- Stub.new(@odba_id, nil, nil)
38
- end
42
+
43
+ def odba_isolated_stub
44
+ Stub.new(@odba_id, nil, nil)
45
+ end
46
+
39
47
  def odba_prefetch?
40
48
  false
41
49
  end
42
- def odba_receiver(name=nil)
43
- if(@receiver && !@receiver_loaded)
50
+
51
+ def odba_receiver(name = nil)
52
+ if @receiver && !@receiver_loaded
44
53
  warn "stub for #{@receiver.class}:#{@odba_id} was saved with receiver"
45
54
  @receiver = nil
46
55
  end
47
- @receiver || begin
48
- #begin
49
- @receiver = ODBA.cache.fetch(@odba_id, @odba_container)
56
+ @receiver || begin
57
+ # begin
58
+ @receiver = ODBA.cache.fetch(@odba_id, @odba_container)
50
59
  @receiver_loaded = true
51
- if(@odba_container)
52
- @odba_container.odba_replace_stubs(@odba_id, @receiver)
60
+ if @odba_container
61
+ @odba_container.odba_replace_stubs(@odba_id, @receiver)
53
62
  else
54
63
  warn "Potential Memory-Leak: stub for #{@receiver.class}##{@odba_id} was saved without container"
55
- end
56
- @receiver
57
- rescue OdbaError => e
58
- puts "OdbaError"
59
- puts caller[0..10].join("\n")
60
- warn "ODBA::Stub was unable to replace #{@odba_class}##{@odba_id} from #{@odba_container.class}:##{@odba_container.odba_id}. raise OdbaError"
64
+ end
65
+ @receiver
66
+ rescue OdbaError
67
+ puts "OdbaError"
68
+ puts caller[0..10].join("\n")
69
+ warn "ODBA::Stub was unable to replace #{@odba_class}##{@odba_id} from #{@odba_container.class}:##{@odba_container.odba_id}. raise OdbaError"
61
70
  raise OdbaError
62
- end
63
- end
64
- alias :odba_instance :odba_receiver
65
- # A stub always references a Persistable that has
66
- # already been saved.
67
- def odba_unsaved?(snapshot_level=nil)
68
- false
69
- end
70
- def to_yaml_properties
71
- ['@odba_id', '@odba_container']
72
- end
73
- def to_yaml_type
74
- "!ruby/object:ODBA::Stub"
75
- end
76
- def yaml_initialize(tag, val)
77
- if RUBY_VERSION >= '1.9'
78
- val.each { |key, value| instance_variable_set(:"@#{key}", value) }
79
- else
80
- val.each { |key, value| instance_variable_set("@#{key}", value) }
81
71
  end
82
- end
83
- no_override = [
84
- "class", "is_a?", "__id__", "__send__", "inspect",
85
- "eql?", "nil?", "respond_to?", "object_id",
86
- "instance_variables", "instance_variable_get",
87
- "instance_variable_set", "==",
88
- ## methods defined in persistable.rb:Object
89
- "odba_id", "odba_instance", "odba_isolated_stub", "odba_prefetch?",
90
- ## yaml-methods
91
- "to_yaml", "taguri", "to_yaml_style", "to_yaml_type",
92
- "to_yaml_properties", "yaml_initialize",
93
- ]
94
- NO_OVERRIDE = no_override.collect { |name| name.to_sym }
95
- if RUBY_VERSION >= '1.9'
96
- no_override = NO_OVERRIDE
97
- end
98
- override_methods = Object.public_methods - no_override
99
- override_methods.each { |method|
100
- src = (method[-1] == ?=) ? <<-EOW : <<-EOS
72
+ end
73
+ alias_method :odba_instance, :odba_receiver
74
+ # A stub always references a Persistable that has
75
+ # already been saved.
76
+ def odba_unsaved?(snapshot_level = nil)
77
+ false
78
+ end
79
+
80
+ def to_yaml_properties
81
+ ["@odba_id", "@odba_container"]
82
+ end
83
+
84
+ def to_yaml_type
85
+ "!ruby/object:ODBA::Stub"
86
+ end
87
+
88
+ def yaml_initialize(tag, val)
89
+ val.each { |key, value| instance_variable_set(:"@#{key}", value) }
90
+ end
91
+ no_override = [
92
+ "class", "is_a?", "__id__", "__send__", "inspect",
93
+ "eql?", "nil?", "respond_to?", "object_id",
94
+ "instance_variables", "instance_variable_get",
95
+ "instance_variable_set", "==",
96
+ ## methods defined in persistable.rb:Object
97
+ "odba_id", "odba_instance", "odba_isolated_stub", "odba_prefetch?",
98
+ ## yaml-methods
99
+ "to_yaml", "taguri", "to_yaml_style", "to_yaml_type",
100
+ "to_yaml_properties", "yaml_initialize"
101
+ ]
102
+ NO_OVERRIDE = no_override.collect { |name| name.to_sym }
103
+ no_override = NO_OVERRIDE
104
+ override_methods = Object.public_methods - no_override
105
+ override_methods.each { |method|
106
+ src = (method[-1] == "=") ? <<-EOW : <<-EOS
101
107
  def #{method}(args)
102
108
  odba_instance.#{method}(args)
103
109
  end
104
- EOW
110
+ EOW
105
111
  def #{method}(*args)
106
112
  odba_instance.#{method}(*args)
107
113
  end
108
- EOS
109
- eval src
110
- }
111
- def method_missing(meth_symbol, *args, &block)
112
- if(NO_OVERRIDE.include?(meth_symbol))
113
- super
114
- else
115
- odba_instance.send(meth_symbol, *args, &block)
116
- end
117
- end
118
- def respond_to?(msg_id, *args)
119
- case msg_id
120
- when :_dump, :marshal_dump
121
- false
122
- when *NO_OVERRIDE
123
- super
124
- else
125
- odba_instance.respond_to?(msg_id, *args)
126
- end
127
- end
128
- ## FIXME
129
- # implement full hash/array access - separate collection stub?
130
- def [](*args, &block)
131
- if(@odba_class == Hash \
132
- && !ODBA.cache.include?(@odba_id))
133
- ODBA.cache.fetch_collection_element(@odba_id, args.first)
134
- end || method_missing(:[], *args, &block)
135
- end
114
+ EOS
115
+ eval src
116
+ }
117
+ def method_missing(meth_symbol, *args, &block)
118
+ if NO_OVERRIDE.include?(meth_symbol)
119
+ super
120
+ else
121
+ odba_instance.send(meth_symbol, *args, &block)
122
+ end
123
+ end
124
+
125
+ def respond_to?(msg_id, *args)
126
+ case msg_id
127
+ when :_dump, :marshal_dump
128
+ false
129
+ when *NO_OVERRIDE
130
+ super
131
+ else
132
+ odba_instance.respond_to?(msg_id, *args)
133
+ end
134
+ end
135
+
136
+ ## FIXME
137
+ # implement full hash/array access - separate collection stub?
138
+ def [](*args, &block)
139
+ if @odba_class == Hash \
140
+ && !ODBA.cache.include?(@odba_id)
141
+ ODBA.cache.fetch_collection_element(@odba_id, args.first)
142
+ end || method_missing(:[], *args, &block)
143
+ end
144
+
136
145
  def ==(other)
137
146
  @odba_id == other.odba_id || odba_instance == other
138
147
  end
139
- end
148
+ end
140
149
  end
141
150
 
142
151
  class Array # :nodoc: all
143
- alias :_odba_amp :&
144
- def &(stub)
145
- self._odba_amp(stub.odba_instance)
146
- end
147
- alias :_odba_plus :+
148
- def +(stub)
149
- self._odba_plus(stub.odba_instance)
150
- end
151
- alias :_odba_minus :-
152
- def -(stub)
153
- self._odba_minus(stub.odba_instance)
154
- end
155
- alias :_odba_weight :<=>
156
- def <=>(stub)
157
- self._odba_weight(stub.odba_instance)
158
- end
159
- alias :_odba_equal? :==
160
- def ==(stub)
161
- self._odba_equal?(stub.odba_instance)
162
- end
163
- alias :_odba_union :|
164
- def |(stub)
165
- self._odba_union(stub.odba_instance)
166
- end
167
- ['concat', 'replace', 'include?'].each { |method|
168
- #['concat', 'replace'].each { |method|
169
- eval <<-EOS
170
- alias :_odba_#{method} :#{method}
171
- def #{method}(stub)
172
- self._odba_#{method}(stub.odba_instance)
173
- end
174
- EOS
175
- }
152
+ alias_method :_odba_amp, :&
153
+ def &(other)
154
+ _odba_amp(other.odba_instance)
155
+ end
156
+ alias_method :_odba_plus, :+
157
+ def +(other)
158
+ _odba_plus(other.odba_instance)
159
+ end
160
+ alias_method :_odba_minus, :-
161
+ def -(other)
162
+ _odba_minus(other.odba_instance)
163
+ end
164
+ alias_method :_odba_weight, :<=>
165
+ def <=>(other)
166
+ _odba_weight(other.odba_instance)
167
+ end
168
+ alias_method :_odba_equal?, :==
169
+ def ==(other)
170
+ _odba_equal?(other.odba_instance)
171
+ end
172
+ alias_method :_odba_union, :|
173
+ def |(other)
174
+ _odba_union(other.odba_instance)
175
+ end
176
+ # Workaround to avoid the following problem
177
+ # Formatter SimpleCov::Formatter::HTMLFormatter failed with ArgumentError: wrong number of arguments (given 2, expected 1
178
+ more_methods = ["replace", "include?"]
179
+ more_methods << "concat" unless defined?(SimpleCov)
180
+ more_methods.each do |method|
181
+ eval %(
182
+ alias :_odba_#{method} :#{method}
183
+ def #{method}(stub)
184
+ self._odba_#{method}(stub.odba_instance)
185
+ end
186
+ )
187
+ end
176
188
  end
189
+
177
190
  class Hash # :nodoc: all
178
- alias :_odba_equal? :==
179
- def ==(stub)
180
- self._odba_equal?(stub.odba_instance)
181
- end
182
- ['merge', 'merge!', 'replace'].each { |method|
183
- eval <<-EOS
184
- alias :_odba_#{method} :#{method}
185
- def #{method}(stub)
186
- self._odba_#{method}(stub.odba_instance)
187
- end
188
- EOS
189
- }
191
+ alias_method :_odba_equal?, :==
192
+ def ==(other)
193
+ _odba_equal?(other.odba_instance)
194
+ end
195
+ ["merge", "merge!", "replace"].each { |method|
196
+ eval %(
197
+ alias :_odba_#{method} :#{method}
198
+ def #{method}(stub)
199
+ self._odba_#{method}(stub.odba_instance)
200
+ end
201
+ )
202
+ }
190
203
  end
data/lib/odba/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  class Odba
4
- VERSION = '1.1.8'
4
+ VERSION = '1.2.0'
5
5
  end
data/lib/odba.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'odba/persistable'
4
- require 'odba/storage'
5
- require 'odba/cache'
6
- require 'odba/stub'
7
- require 'odba/marshal'
8
- require 'odba/cache_entry'
9
- require 'odba/odba_error'
10
- require 'odba/index'
11
- require 'odba/odba'
3
+ require "odba/persistable"
4
+ require "odba/storage"
5
+ require "odba/cache"
6
+ require "odba/stub"
7
+ require "odba/marshal"
8
+ require "odba/cache_entry"
9
+ require "odba/odba_error"
10
+ require "odba/index"
11
+ require "odba/odba"
data/odba.gemspec CHANGED
@@ -9,19 +9,24 @@ Gem::Specification.new do |spec|
9
9
  spec.description = "Object Database Access"
10
10
  spec.summary = "Ruby Software for ODDB.org Memory Management"
11
11
  spec.homepage = "https://github.com/zdavatz/odba"
12
+ spec.metadata["changelog_uri"] = spec.homepage + "/blob/master/History.md"
12
13
  spec.license = "GPL-v2"
13
14
  spec.files = `git ls-files -z`.split("\x0")
14
15
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
16
  spec.require_paths = ["lib"]
17
+ spec.required_ruby_version = ">= 3.2"
16
18
 
19
+ spec.add_dependency 'observer'
20
+ spec.add_dependency 'drb'
21
+ spec.add_dependency 'stringio'
17
22
  spec.add_development_dependency 'ydbi', '>=0.5.7'
18
23
  spec.add_development_dependency 'ydbd-pg','>=0.5.7'
19
24
 
20
25
  spec.add_development_dependency "bundler"
21
26
  spec.add_development_dependency "rake"
22
27
  spec.add_development_dependency "rspec"
23
- spec.add_development_dependency "flexmock"
24
- spec.add_development_dependency "minitest"
28
+ spec.add_development_dependency "flexmock", "2.4.0" # Version 3.0.1 leads to many errors. Do not know why?
25
29
  spec.add_development_dependency "test-unit"
26
- spec.add_development_dependency "debug_inspector"
30
+ spec.add_development_dependency "debug"
31
+ spec.add_development_dependency "simplecov"
27
32
  end
data/test/example.rb ADDED
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.dirname(__FILE__)
3
+ $: << File.expand_path("../lib/", File.dirname(__FILE__))
4
+ require "odba"
5
+ require "odba/connection_pool"
6
+
7
+ class User
8
+ attr_accessor :first_name, :last_name
9
+ include ODBA::Persistable
10
+ def initialize(first_name, last_name)
11
+ @first_name = first_name
12
+ @last_name = last_name
13
+ end
14
+
15
+ def to_s
16
+ "#{@first_name} #{@last_name}"
17
+ end
18
+ end
19
+
20
+ class Example
21
+ def self.db_setup
22
+ # connect default storage manager to a relational database on
23
+ # our localhost using port 5435 with a user odba_test and an empty password
24
+ ODBA.storage.dbi = ODBA::ConnectionPool.new("DBI:Pg:dbname=odba_test;host=127.0.0.1;port=5432", "odba_test", "")
25
+ ODBA.cache.setup
26
+ end
27
+
28
+ def self.show_last_added_user
29
+ res = ODBA.storage.dbi.select_all("Select count(*) from object;").first.first
30
+ odba_id = ODBA.storage.dbi.select_one("select odba_id from object order by odba_id desc limit 1;")
31
+ puts "show_last_added_user: We have #{res} objects. Highest odba_id is #{odba_id}"
32
+ first = ODBA.storage.dbi.select_one("select odba_id, name, prefetchable, extent, content from object order by odba_id desc limit 1;")
33
+ puts " DB-content is #{first}"
34
+ puts " Fetched object for odba_id #{odba_id} is #{ODBA.cache.fetch(odba_id.first)}"
35
+ end
36
+ end
37
+
38
+ Example.db_setup
39
+ composer = User.new("Ludwig", "Van Beethoven")
40
+ composer.odba_store
41
+ Example.show_last_added_user
42
+ painter = User.new("Vincent", "Van Gogh")
43
+ painter.odba_store
44
+ scientist = User.new("Albert", "Einstein")
45
+ scientist.odba_store
46
+ Example.show_last_added_user
47
+
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ $: << File.dirname(__FILE__)
2
+ $: << File.expand_path("../lib/", File.dirname(__FILE__))
3
+ require "test/unit"
4
+ require "flexmock/test_unit"
5
+ require 'simplecov'
6
+ SimpleCov.start 'test_frameworks'
data/test/suite.rb ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # TestSuite -- yus -- 02.06.2006 -- rwaltert@ywesee.com
3
+ require_relative "helper"
4
+
5
+ Dir.foreach(File.dirname(__FILE__)) { |file|
6
+ require file if /^test_.*\.rb$/o.match?(file)
7
+ }
data/test/test_array.rb CHANGED
@@ -1,48 +1,46 @@
1
1
  #!/usr/bin/env ruby
2
2
  # TestArray -- odba -- 30.01.2007 -- hwyss@ywesee.com
3
-
4
- $: << File.dirname(__FILE__)
5
- $: << File.expand_path('../lib', File.dirname(__FILE__))
6
-
7
- require 'minitest/autorun'
8
- require 'flexmock/test_unit'
9
- require 'flexmock'
10
- require 'odba/persistable'
11
- require 'odba/stub'
12
- require 'odba/odba'
3
+ require_relative "helper"
4
+ require "odba/persistable"
5
+ require "odba/stub"
6
+ require "odba/odba"
13
7
 
14
8
  module ODBA
15
- class TestArray < Minitest::Test
16
- include FlexMock::TestCase
9
+ class TestArray < Test::Unit::TestCase
17
10
  class ODBAContainerInArrayInArray
18
- include ODBA::Persistable
19
- attr_accessor :non_replaceable, :replaceable, :array, :odba_id
11
+ include ODBA::Persistable
12
+ attr_accessor :non_replaceable, :replaceable, :array, :odba_id
20
13
  end
14
+
21
15
  class ContainerInArray
22
16
  attr_accessor :content
23
17
  end
18
+
24
19
  def setup
25
- @array = Array.new
20
+ @array = []
26
21
  ODBA.storage = flexmock("storage")
27
22
  ODBA.marshaller = flexmock("marshaller_array")
28
23
  ODBA.cache = flexmock("cache")
29
24
  end
25
+
30
26
  def teardown
31
27
  ODBA.storage = nil
32
28
  ODBA.marshaller = nil
33
29
  ODBA.cache = nil
34
- load = File.expand_path(File.join(File.dirname(__FILE__), '../lib/odba/storage.rb'))
30
+ File.expand_path(File.join(File.dirname(__FILE__), "../lib/odba/storage.rb"))
35
31
  super
36
32
  end
33
+
37
34
  def test_odba_cut_connection
38
35
  remove_obj = Object
39
36
  remove_obj.extend(ODBA::Persistable)
40
- remove_obj.instance_variable_set('@odba_id', 2)
41
- receiver = ODBA::Stub.new(2,self, remove_obj)
42
- array = Array.new
37
+ remove_obj.instance_variable_set(:@odba_id, 2)
38
+ receiver = ODBA::Stub.new(2, self, remove_obj)
39
+ array = []
43
40
  array.push(receiver)
44
41
  assert_equal(0, array.odba_cut_connection(remove_obj).size)
45
42
  end
43
+
46
44
  def test_odba_unsaved_neighbors_array
47
45
  rep1 = ODBAContainerInArrayInArray.new
48
46
  rep2 = ODBAContainerInArrayInArray.new
@@ -51,47 +49,53 @@ module ODBA
51
49
  result = @array.odba_unsaved_neighbors(1)
52
50
  assert_equal([rep1, rep2], result)
53
51
  end
52
+
54
53
  def test_array_replacement
55
- replacement = flexmock('replacement')
56
- replacement2 = flexmock('replacement2')
57
- stub = flexmock('stub')
58
- stub2 = flexmock('stub2')
59
- foo = flexmock("foo")
54
+ replacement = flexmock("replacement")
55
+ replacement2 = flexmock("replacement2")
56
+ stub = flexmock("stub")
57
+ stub2 = flexmock("stub2")
58
+ flexmock("foo")
60
59
  @array.push(stub)
61
60
  @array.push(stub2)
62
- @array.odba_restore([[0,replacement], [1,replacement2]])
61
+ @array.odba_restore([[0, replacement], [1, replacement2]])
63
62
  assert_equal(replacement, @array[0])
64
63
  assert_equal(replacement2, @array[1])
65
64
  end
65
+
66
66
  def test_odba_replace_persistables_array
67
67
  replaceable = flexmock("replaceable")
68
68
  replaceable2 = flexmock("replaceable2")
69
69
  @array.push(replaceable)
70
70
  @array.push(replaceable2)
71
71
  @array.odba_replace_persistables
72
- #size is 0 because we store empty array in the db
72
+ # size is 0 because we store empty array in the db
73
73
  # content of the array is in the collection table
74
74
  assert_equal(0, @array.size)
75
75
  end
76
+
76
77
  def test_odba_unsaved_array_true
77
78
  val = flexmock("val")
78
- @array.instance_variable_set("@odba_persistent", true)
79
+ @array.instance_variable_set(:@odba_persistent, true)
79
80
  @array.push(val)
80
81
  val.should_receive(:is_a?).and_return { |klass| true }
81
82
  val.should_receive(:odba_unsaved?).and_return { true }
82
83
  assert_equal(true, @array.odba_unsaved?)
83
84
  end
85
+
84
86
  def test_odba_collection
85
- @array.push('foo', 'bar')
86
- assert_equal([[0,'foo'], [1, 'bar']], @array.odba_collection)
87
+ @array.push("foo", "bar")
88
+ assert_equal([[0, "foo"], [1, "bar"]], @array.odba_collection)
87
89
  end
90
+
88
91
  def test_odba_replace
89
- modified = ['foo']
92
+ modified = ["foo"]
90
93
  reloaded = modified.dup
91
- modified.push('bar')
94
+ modified.push("bar")
92
95
  modified.odba_replace!(reloaded)
93
96
  assert_equal(reloaded, modified)
94
97
  end
98
+
95
99
  def test_odba_target_ids
96
100
  o = ODBAContainerInArrayInArray.new
97
101
  o.odba_id = 1
@@ -100,9 +104,10 @@ module ODBA
100
104
  q = ODBAContainerInArrayInArray.new
101
105
  q.odba_id = 3
102
106
  @array.push(p, q)
103
- @array.instance_variable_set('@foo', o)
104
- assert_equal([1,2,3], @array.odba_target_ids)
107
+ @array.instance_variable_set(:@foo, o)
108
+ assert_equal([1, 2, 3], @array.odba_target_ids)
105
109
  end
110
+
106
111
  def test_stubize
107
112
  item = ODBAContainerInArrayInArray.new
108
113
  @array.push(item)