module Neo4j
module Core
module Property
# the valid values on a property, and arrays of those.
VALID_PROPERTY_VALUE_CLASSES = Set.new([Array, NilClass, String, Float, TrueClass, FalseClass, Fixnum])
# @return [Hash] all properties plus the id of the node with the key _neo_id
def props
ret = {"_neo_id" => neo_id}
property_keys.each do |key|
ret[key] = get_property(key)
end
ret
end
# Ids are garbage collected over time so they are only guaranteed to be unique during a specific time span:
# if the node is deleted, it's likely that a new node at some point will get the old id. Note:
# this makes node ids brittle as public APIs.
# @return [Fixnum] the unique id of this node.
def neo_id
getId
end
# @param [#to_s] the property we want to check if it exist.
# @return [true false] true if the given key exist as a property.
def property?(key)
has_property?(key.to_s)
end
# Updates this node/relationship's properties by using the provided struct/hash.
# If the option {:strict => true}
is given, any properties present on
# the node but not present in the hash will be removed from the node, except '_neo_id' and '_classname' (defined in Neo4j::Node.protected_keys).
# The option {:protected_keys => array of strings}
is similar to the option, except
# that it allows you to specify which keys will be protected from being updated or deleted.
# If neither the protected nor strict option is given then all properties starting with '_' will never be touched.
#
# @param [Hash, :each_pair] struct_or_hash the key and value to be set
# @param [Hash] options further options defining the context of the update
# @option options [Boolean] :strict any properties present on the node but not present in the hash will be removed from the node if true
# @option options [Array] :protected_keys the keys that never will be touched
# @return self
def update(struct_or_hash, options={})
protected_keys = self.class.protected_keys if options[:strict]
protected_keys ||= options[:protected_keys].map(&:to_s) if options[:protected_keys]
keys_to_delete = props.keys - protected_keys if protected_keys
struct_or_hash.each_pair do |k, value|
key = k.to_s
# do not allow special properties to be mass assigned
if protected_keys
keys_to_delete.delete(key)
next if protected_keys.include?(key)
else
next if key[0..0] == '_'
end
self[key] = value
end
keys_to_delete.each { |key| remove_property(key) } if protected_keys
self
end
def protected_keys
end
# @return the value of the given key or nil if the property does not exist.
def [](key)
return unless property?(key)
val = get_property(key.to_s)
val.class.superclass == ArrayJavaProxy ? val.to_a : val
end
# @param [Object] value the value we want to check if it's a valid neo4j property value
# @return [True, False] A false means it can't be persisted.
def valid_property?(value)
VALID_PROPERTY_VALUE_CLASSES.include?(value.class)
end
# Sets the property of this node.
# Property keys are always strings. Valid property value types are the primitives(String, Fixnum, Float, FalseClass, TrueClass) or array of those primitives.
#
# ==== Gotchas
# * Values in the array must be of the same type.
# * You can *not* delete or add one item in the array (e.g. person.phones.delete('123')) but instead you must create a new array instead.
#
# @param [String, Symbol] key of the property to set
# @param [String,Fixnum,Float,true,false, Array] value to set
def []=(key, value)
raise "Not valid Neo4j Property value #{value.class}, valid: #{VALID_PROPERTY_VALUE_CLASSES.join(', ')}" unless valid_property?(value)
k = key.to_s
if value.nil?
remove_property(k)
elsif (Array === value)
case value[0]
when NilClass
set_property(k, [].to_java(:string))
when String
set_property(k, value.to_java(:string))
when Float
set_property(k, value.to_java(:double))
when FalseClass, TrueClass
set_property(k, value.to_java(:boolean))
when Fixnum
set_property(k, value.to_java(:long))
else
raise "Not allowed to store array with value #{value[0]} type #{value[0].class}"
end
else
set_property(k, value)
end
end
end
end
end