neo4j 1.0.0.beta.20 → 3.0.0.alpha.2
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/CHANGELOG +243 -0
- data/CONTRIBUTORS +12 -0
- data/Gemfile +10 -11
- data/README.md +23 -0
- data/bin/neo4j-jars +33 -0
- data/config/locales/en.yml +5 -0
- data/config/neo4j/config.yml +98 -0
- data/lib/neo4j.rb +28 -68
- data/lib/neo4j/active_node.rb +60 -0
- data/lib/neo4j/active_node/callbacks.rb +41 -0
- data/lib/neo4j/active_node/has_n.rb +138 -0
- data/lib/neo4j/active_node/has_n/decl_rel.rb +236 -0
- data/lib/neo4j/active_node/has_n/nodes.rb +82 -0
- data/lib/neo4j/active_node/identity.rb +28 -0
- data/lib/neo4j/active_node/initialize.rb +24 -0
- data/lib/neo4j/active_node/labels.rb +142 -0
- data/lib/neo4j/active_node/persistence.rb +193 -0
- data/lib/neo4j/active_node/property.rb +41 -0
- data/lib/neo4j/active_node/rels.rb +11 -0
- data/lib/neo4j/active_node/validations.rb +51 -0
- data/lib/neo4j/railtie.rb +40 -0
- data/lib/neo4j/version.rb +1 -1
- data/lib/neo4j/wrapper.rb +25 -0
- data/neo4j.gemspec +25 -15
- metadata +136 -149
- data/README.rdoc +0 -135
- data/lib/generators/neo4j.rb +0 -65
- data/lib/generators/neo4j/model/model_generator.rb +0 -39
- data/lib/generators/neo4j/model/templates/model.erb +0 -7
- data/lib/neo4j/config.rb +0 -153
- data/lib/neo4j/database.rb +0 -56
- data/lib/neo4j/equal.rb +0 -21
- data/lib/neo4j/event_handler.rb +0 -116
- data/lib/neo4j/index/class_methods.rb +0 -62
- data/lib/neo4j/index/index.rb +0 -33
- data/lib/neo4j/index/indexer.rb +0 -312
- data/lib/neo4j/index/indexer_registry.rb +0 -68
- data/lib/neo4j/index/lucene_query.rb +0 -191
- data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/lucene-core-3.0.2.jar +0 -0
- data/lib/neo4j/jars/neo4j-index-1.2-1.2.M03.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar +0 -0
- data/lib/neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar +0 -0
- data/lib/neo4j/load.rb +0 -21
- data/lib/neo4j/mapping/class_methods/init_node.rb +0 -50
- data/lib/neo4j/mapping/class_methods/init_rel.rb +0 -35
- data/lib/neo4j/mapping/class_methods/property.rb +0 -80
- data/lib/neo4j/mapping/class_methods/relationship.rb +0 -90
- data/lib/neo4j/mapping/class_methods/root.rb +0 -31
- data/lib/neo4j/mapping/class_methods/rule.rb +0 -295
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +0 -214
- data/lib/neo4j/mapping/has_n.rb +0 -83
- data/lib/neo4j/mapping/node_mixin.rb +0 -97
- data/lib/neo4j/mapping/relationship_mixin.rb +0 -117
- data/lib/neo4j/model.rb +0 -4
- data/lib/neo4j/neo4j.rb +0 -95
- data/lib/neo4j/node.rb +0 -131
- data/lib/neo4j/node_mixin.rb +0 -4
- data/lib/neo4j/node_relationship.rb +0 -149
- data/lib/neo4j/node_traverser.rb +0 -157
- data/lib/neo4j/property.rb +0 -111
- data/lib/neo4j/rails/finders.rb +0 -121
- data/lib/neo4j/rails/lucene_connection_closer.rb +0 -19
- data/lib/neo4j/rails/mapping/property.rb +0 -35
- data/lib/neo4j/rails/model.rb +0 -324
- data/lib/neo4j/rails/railtie.rb +0 -16
- data/lib/neo4j/rails/transaction.rb +0 -67
- data/lib/neo4j/rails/tx_methods.rb +0 -15
- data/lib/neo4j/rails/validations/non_nil.rb +0 -11
- data/lib/neo4j/rails/validations/uniqueness.rb +0 -31
- data/lib/neo4j/rails/value.rb +0 -124
- data/lib/neo4j/rails/value_properties.rb +0 -29
- data/lib/neo4j/relationship.rb +0 -169
- data/lib/neo4j/relationship_mixin.rb +0 -4
- data/lib/neo4j/relationship_traverser.rb +0 -92
- data/lib/neo4j/to_java.rb +0 -31
- data/lib/neo4j/transaction.rb +0 -68
- data/lib/neo4j/type_converters.rb +0 -98
@@ -1,19 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Rails
|
3
|
-
class LuceneConnectionCloser
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
@app.call(env)
|
10
|
-
ensure
|
11
|
-
Thread.current[:neo4j_lucene_connection].each {|hits| hits.close} if Thread.current[:neo4j_lucene_connection]
|
12
|
-
Thread.current[:neo4j_lucene_connection] = nil
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
Thread.current
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Rails
|
3
|
-
module Mapping
|
4
|
-
module Property
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
def []=(key, value)
|
8
|
-
attribute_will_change!(key.to_s) if self[key.to_s] != value
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
# Handle some additional options for the property
|
14
|
-
#
|
15
|
-
# Set a default - :default => "default"
|
16
|
-
# Prpoerty must be there - :null => false
|
17
|
-
# Property has a length limit - :limit => 128
|
18
|
-
def property(*args)
|
19
|
-
super
|
20
|
-
handle_property_options_for(args.first)
|
21
|
-
end
|
22
|
-
|
23
|
-
protected
|
24
|
-
def handle_property_options_for(property)
|
25
|
-
options = _decl_props[property.to_sym]
|
26
|
-
|
27
|
-
write_inheritable_attribute(:attribute_defaults, property => options[:default]) if options[:default]
|
28
|
-
validates(property, :non_nil => true) if options.has_key?(:null) && options[:null] == false
|
29
|
-
validates(property, :length => { :maximum => options[:limit] }) if options[:limit]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/neo4j/rails/model.rb
DELETED
@@ -1,324 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Rails
|
3
|
-
class Model
|
4
|
-
include Neo4j::NodeMixin
|
5
|
-
|
6
|
-
include ActiveModel::Serializers::Xml
|
7
|
-
include ActiveModel::Validations
|
8
|
-
include ActiveModel::Dirty
|
9
|
-
include ActiveModel::MassAssignmentSecurity
|
10
|
-
|
11
|
-
extend ActiveModel::Naming
|
12
|
-
extend ActiveModel::Callbacks
|
13
|
-
|
14
|
-
include Neo4j::Rails::Validations
|
15
|
-
extend Neo4j::Rails::Validations::ClassMethods
|
16
|
-
|
17
|
-
include Finders # ActiveRecord style find
|
18
|
-
include Mapping::Property # allows some additional options on the #property class method
|
19
|
-
|
20
|
-
extend TxMethods
|
21
|
-
|
22
|
-
class_inheritable_hash :attribute_defaults
|
23
|
-
self.attribute_defaults = {}
|
24
|
-
|
25
|
-
define_model_callbacks :create, :save, :update, :destroy
|
26
|
-
|
27
|
-
class RecordInvalidError < RuntimeError
|
28
|
-
attr_reader :record
|
29
|
-
|
30
|
-
def initialize(record)
|
31
|
-
@record = record
|
32
|
-
super(@record.errors.full_messages.join(", "))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# --------------------------------------
|
37
|
-
# Initialize
|
38
|
-
# --------------------------------------
|
39
|
-
|
40
|
-
def initialize(*)
|
41
|
-
end
|
42
|
-
|
43
|
-
def init_on_create(*args) # :nodoc:
|
44
|
-
super()
|
45
|
-
self.attributes=args[0] if args[0].respond_to?(:each_pair)
|
46
|
-
end
|
47
|
-
|
48
|
-
# --------------------------------------
|
49
|
-
# Identity
|
50
|
-
# --------------------------------------
|
51
|
-
|
52
|
-
def id
|
53
|
-
neo_id.nil? ? nil : neo_id.to_s
|
54
|
-
end
|
55
|
-
|
56
|
-
def to_param
|
57
|
-
persisted? ? neo_id.to_s : nil
|
58
|
-
end
|
59
|
-
|
60
|
-
# Returns an Enumerable of all (primary) key attributes
|
61
|
-
# or nil if model.persisted? is false
|
62
|
-
def to_key
|
63
|
-
persisted? ? [:id] : nil
|
64
|
-
end
|
65
|
-
|
66
|
-
# enables ActiveModel::Dirty and Validation
|
67
|
-
def method_missing(method_id, *args, &block)
|
68
|
-
if !self.class.attribute_methods_generated?
|
69
|
-
self.class.define_attribute_methods(self.class._decl_props.keys)
|
70
|
-
# try again
|
71
|
-
send(method_id, *args, &block)
|
72
|
-
elsif property?(method_id)
|
73
|
-
send(:[], method_id)
|
74
|
-
else
|
75
|
-
super
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def read_attribute_for_validation(key)
|
80
|
-
send(key)
|
81
|
-
end
|
82
|
-
|
83
|
-
def attributes=(values)
|
84
|
-
sanitize_for_mass_assignment(values).each do |k, v|
|
85
|
-
if respond_to?("#{k}=")
|
86
|
-
send("#{k}=", v)
|
87
|
-
else
|
88
|
-
self[k] = v
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
|
94
|
-
# If saving fails because the resource is invalid then false will be returned.
|
95
|
-
def update_attributes(attributes)
|
96
|
-
self.attributes=attributes
|
97
|
-
save
|
98
|
-
end
|
99
|
-
|
100
|
-
def update_attributes!(attributes)
|
101
|
-
self.attributes=attributes
|
102
|
-
save!
|
103
|
-
end
|
104
|
-
|
105
|
-
def update_nested_attributes(rel_type, clazz, has_one, attr, options)
|
106
|
-
allow_destroy, reject_if = [options[:allow_destroy], options[:reject_if]] if options
|
107
|
-
|
108
|
-
if new?
|
109
|
-
# We are updating a node that was created with the 'new' method.
|
110
|
-
# The relationship will only be kept in the Value object.
|
111
|
-
outgoing(rel_type) << clazz.new(attr) unless reject_if?(reject_if, attr) || (allow_destroy && attr[:_destroy] && attr[:_destroy] != '0')
|
112
|
-
else
|
113
|
-
# We have a node that was created with the #create method - has real Neo4j relationships
|
114
|
-
# does it exist ?
|
115
|
-
found = if has_one
|
116
|
-
# id == nil that means we have a has_one relationship
|
117
|
-
outgoing(rel_type).first
|
118
|
-
else
|
119
|
-
# do we have an ID ?
|
120
|
-
id = attr[:id]
|
121
|
-
# this is a has_n relationship, find which one we want to update
|
122
|
-
id && outgoing(rel_type).find { |n| n.id == id }
|
123
|
-
end
|
124
|
-
|
125
|
-
# Check if we want to destroy not found nodes (e.g. {..., :_destroy => '1' } ?
|
126
|
-
destroy = attr[:_destroy] && attr[:_destroy] != '0'
|
127
|
-
|
128
|
-
if found
|
129
|
-
if destroy
|
130
|
-
found.destroy if allow_destroy
|
131
|
-
else
|
132
|
-
found.update_attributes_in_tx(attr) # it already exist, so update that one
|
133
|
-
end
|
134
|
-
elsif !destroy && !reject_if?(reject_if, attr)
|
135
|
-
new_node = clazz.new(attr)
|
136
|
-
saved = new_node.save
|
137
|
-
outgoing(rel_type) << new_node if saved
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def reject_if?(proc_or_symbol, attr)
|
143
|
-
return false if proc_or_symbol.nil?
|
144
|
-
if proc_or_symbol.is_a?(Symbol)
|
145
|
-
meth = method(proc_or_symbol)
|
146
|
-
meth.arity == 0 ? meth.call : meth.call(attr)
|
147
|
-
else
|
148
|
-
proc_or_symbol.call(attr)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def save(*args)
|
153
|
-
_run_save_callbacks do
|
154
|
-
if create_or_update_node(*args)
|
155
|
-
true
|
156
|
-
else
|
157
|
-
# if not valid we should rollback the transaction so that the changes does not take place.
|
158
|
-
# no point failing the transaction if we have created a model with 'new'
|
159
|
-
Neo4j::Rails::Transaction.fail if Neo4j::Rails::Transaction.running? #&& !_java_node.kind_of?(Neo4j::Rails::Value)
|
160
|
-
false
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def create_or_update_node(options = {})
|
166
|
-
options.reverse_merge!({ :validate => true })
|
167
|
-
|
168
|
-
if options[:validate] == false || valid?(:save)
|
169
|
-
if new_record?
|
170
|
-
_run_create_callbacks do
|
171
|
-
if options[:validate] == false || valid?(:create)
|
172
|
-
node = Neo4j::Node.new(props)
|
173
|
-
return false unless _java_node.save_nested(node)
|
174
|
-
init_on_load(node)
|
175
|
-
init_on_create
|
176
|
-
self.created_at = DateTime.now if Neo4j::Config[:timestamps] && respond_to?(:created_at)
|
177
|
-
clear_changes
|
178
|
-
true
|
179
|
-
end
|
180
|
-
end
|
181
|
-
else
|
182
|
-
_run_update_callbacks do
|
183
|
-
if options[:validate] == false || valid?(:update)
|
184
|
-
clear_changes
|
185
|
-
self.updated_at = DateTime.now if Neo4j::Config[:timestamps] && respond_to?(:updated_at)
|
186
|
-
true
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def clear_changes
|
194
|
-
@previously_changed = changes
|
195
|
-
@changed_attributes.clear
|
196
|
-
end
|
197
|
-
|
198
|
-
def reload(options = nil)
|
199
|
-
clear_changes
|
200
|
-
reload_from_database or set_deleted_properties and return self
|
201
|
-
end
|
202
|
-
|
203
|
-
def save!(*args)
|
204
|
-
raise RecordInvalidError.new(self) unless save(*args)
|
205
|
-
end
|
206
|
-
|
207
|
-
# Returns if the record is persisted, i.e. it’s not a new record and it was not destroyed
|
208
|
-
def persisted?
|
209
|
-
!new_record? && !destroyed?
|
210
|
-
end
|
211
|
-
|
212
|
-
def to_model
|
213
|
-
self
|
214
|
-
end
|
215
|
-
|
216
|
-
def new?
|
217
|
-
_java_node.kind_of?(Neo4j::Rails::Value)
|
218
|
-
end
|
219
|
-
|
220
|
-
alias :new_record? :new?
|
221
|
-
|
222
|
-
def ==(other)
|
223
|
-
new? ? self.__id__ == other.__id__ : @_java_node == (other)
|
224
|
-
end
|
225
|
-
|
226
|
-
def del_with_wrapper
|
227
|
-
_run_destroy_callbacks do
|
228
|
-
del_without_wrapper
|
229
|
-
set_deleted_properties
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
alias_method_chain :del, :wrapper
|
234
|
-
alias :destroy :del_with_wrapper
|
235
|
-
|
236
|
-
def destroyed?()
|
237
|
-
@_deleted
|
238
|
-
end
|
239
|
-
|
240
|
-
# TODO: []= shouldn't need to be in a transaction because it shouldn't update the DB. Need to refactor the @_java_node handling stuff if we want that to be the case though
|
241
|
-
tx_methods :destroy, :create_or_update_node, :[]=, :update_attributes, :update_attributes!, :update_nested_attributes
|
242
|
-
|
243
|
-
# --------------------------------------
|
244
|
-
# Class Methods
|
245
|
-
# --------------------------------------
|
246
|
-
|
247
|
-
class << self
|
248
|
-
extend TxMethods
|
249
|
-
|
250
|
-
# returns a value object instead of creating a new node
|
251
|
-
def new(*args)
|
252
|
-
wrapped = self.orig_new
|
253
|
-
value = Neo4j::Rails::Value.new(wrapped)
|
254
|
-
wrapped.init_on_load(value)
|
255
|
-
wrapped.attributes = initial_attributes(*args)
|
256
|
-
wrapped
|
257
|
-
end
|
258
|
-
|
259
|
-
alias_method :_orig_create, :create
|
260
|
-
|
261
|
-
def create(*args)
|
262
|
-
new(*args).tap { |o| o.save }
|
263
|
-
end
|
264
|
-
|
265
|
-
def create!(*args)
|
266
|
-
new(*args).tap { |o| o.save! }
|
267
|
-
end
|
268
|
-
|
269
|
-
def transaction(&block)
|
270
|
-
Neo4j::Rails::Transaction.run do |tx|
|
271
|
-
block.call(tx)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
def accepts_nested_attributes_for(*attr_names)
|
276
|
-
options = attr_names.pop if attr_names[-1].is_a?(Hash)
|
277
|
-
|
278
|
-
attr_names.each do |association_name|
|
279
|
-
rel = self._decl_rels[association_name.to_sym]
|
280
|
-
raise "No relationship declared with has_n or has_one with type #{association_name}" unless rel
|
281
|
-
target_class = rel.target_class
|
282
|
-
raise "Can't use accepts_nested_attributes_for(#{association_name}) since it has not defined which class it has a relationship to, use has_n(#{association_name}).to(MyOtherClass)" unless target_class
|
283
|
-
type = rel.rel_type
|
284
|
-
has_one = rel.has_one?
|
285
|
-
|
286
|
-
send(:define_method, "#{association_name}_attributes=") do |attributes|
|
287
|
-
if has_one
|
288
|
-
update_nested_attributes(type, target_class, true, attributes, options)
|
289
|
-
else
|
290
|
-
if attributes.is_a?(Array)
|
291
|
-
attributes.each do |attr|
|
292
|
-
update_nested_attributes(type, target_class, false, attr, options)
|
293
|
-
end
|
294
|
-
else
|
295
|
-
attributes.each_value do |attr|
|
296
|
-
update_nested_attributes(type, target_class, false, attr, options)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|
303
|
-
|
304
|
-
protected
|
305
|
-
def initial_attributes(*args)
|
306
|
-
args.first.is_a?(Hash) ? args.first.reverse_merge(attribute_defaults) : attribute_defaults
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
private
|
311
|
-
def reload_from_database
|
312
|
-
if reloaded = self.class.load(self.id.to_s)
|
313
|
-
attributes = reloaded.attributes
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
def set_deleted_properties
|
318
|
-
@_deleted = true
|
319
|
-
@_persisted = false
|
320
|
-
@_java_node = Neo4j::Rails::Value.new(self)
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
data/lib/neo4j/rails/railtie.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
class Railtie < ::Rails::Railtie
|
3
|
-
config.neo4j = ActiveSupport::OrderedOptions.new
|
4
|
-
|
5
|
-
initializer "neo4j.tx" do |app|
|
6
|
-
app.config.middleware.use Neo4j::Rails::LuceneConnectionCloser
|
7
|
-
end
|
8
|
-
|
9
|
-
# Starting Neo after :load_config_initializers allows apps to
|
10
|
-
# register migrations in config/initializers
|
11
|
-
initializer "neo4j.start", :after => :load_config_initializers do |app|
|
12
|
-
Neo4j::Config.setup.merge!(app.config.neo4j.to_hash)
|
13
|
-
Neo4j.start
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Rails
|
3
|
-
|
4
|
-
# This method is typically used in an Rails ActionController as a filter method.
|
5
|
-
# It will guarantee that an transaction is create before your action is called,
|
6
|
-
# and that the transaction is finished after your action is called.
|
7
|
-
#
|
8
|
-
# Example:
|
9
|
-
# class MyController < ActionController::Base
|
10
|
-
# around_filter Neo4j::Rails::Transaction, :only => [:edit, :delete]
|
11
|
-
# ...
|
12
|
-
# end
|
13
|
-
class Transaction
|
14
|
-
class << self
|
15
|
-
def new
|
16
|
-
finish if Thread.current[:neo4j_transaction]
|
17
|
-
Thread.current[:neo4j_transaction] = Neo4j::Transaction.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def current
|
21
|
-
Thread.current[:neo4j_transaction]
|
22
|
-
end
|
23
|
-
|
24
|
-
def running?
|
25
|
-
Thread.current[:neo4j_transaction] != nil
|
26
|
-
end
|
27
|
-
|
28
|
-
def fail?
|
29
|
-
Thread.current[:neo4j_transaction_fail] != nil
|
30
|
-
end
|
31
|
-
|
32
|
-
def fail
|
33
|
-
Thread.current[:neo4j_transaction_fail] = true
|
34
|
-
end
|
35
|
-
|
36
|
-
def success
|
37
|
-
Thread.current[:neo4j_transaction_fail] = nil
|
38
|
-
end
|
39
|
-
|
40
|
-
def finish
|
41
|
-
tx = Thread.current[:neo4j_transaction]
|
42
|
-
tx.success unless fail?
|
43
|
-
tx.finish
|
44
|
-
Thread.current[:neo4j_transaction] = nil
|
45
|
-
Thread.current[:neo4j_transaction_fail] = nil
|
46
|
-
end
|
47
|
-
|
48
|
-
def filter(*, &block)
|
49
|
-
run &block
|
50
|
-
end
|
51
|
-
|
52
|
-
def run
|
53
|
-
begin
|
54
|
-
new
|
55
|
-
ret = yield self
|
56
|
-
rescue
|
57
|
-
fail
|
58
|
-
raise
|
59
|
-
ensure
|
60
|
-
finish
|
61
|
-
end
|
62
|
-
ret
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|