Class: SafetyPin::Node
- Inherits:
-
Object
- Object
- SafetyPin::Node
- Defined in:
- lib/safety_pin/node.rb
Instance Attribute Summary collapse
-
#j_node ⇒ Object
readonly
Returns the value of attribute j_node.
Class Method Summary collapse
- .build(node_blueprint_or_path_string) ⇒ Object
- .create(node_blueprint_or_path_string) ⇒ Object
- .create_or_update(node_blueprint_or_node_blueprints) ⇒ Object
- .create_parents(path) ⇒ Object
- .exists?(path) ⇒ Boolean
- .find(path) ⇒ Object
- .find_or_create(path, primary_type = nil) ⇒ Object
- .session ⇒ Object
- .update(node_blueprint) ⇒ Object
Instance Method Summary collapse
- #==(other_node) ⇒ Object
- #[](name) ⇒ Object
- #[]=(name, value) ⇒ Object
- #add_mixin(mixin_name) ⇒ Object
- #build(name, node_blueprint = nil) ⇒ Object
- #changed? ⇒ Boolean
- #child(relative_path) ⇒ Object
- #children ⇒ Object
-
#convert_hash_to_node_blueprint(hash) ⇒ Object
Convert a hash (and it’s values recursively) to NodeBlueprints.
-
#create(name, node_blueprint = nil) ⇒ Object
Create and return a child node with a given name.
- #descendants ⇒ Object
- #destroy ⇒ Object
- #find_or_create(name, primary_type = nil) ⇒ Object
- #has_property(name) ⇒ Object
- #has_property?(name) ⇒ Boolean
-
#initialize(j_node) ⇒ Node
constructor
A new instance of Node.
- #inspect ⇒ Object
- #mixin_types ⇒ Object
- #name ⇒ Object
- #new? ⇒ Boolean
- #node_blueprint_for(name, node_blueprint = nil) ⇒ Object
- #parent ⇒ Object
- #path ⇒ Object
- #primary_type ⇒ Object
- #primary_type=(primary_type) ⇒ Object
- #properties ⇒ Object
- #properties=(new_props) ⇒ Object
- #property_is_multi_valued?(property) ⇒ Boolean
- #property_multi_valued?(name) ⇒ Boolean
- #property_single_valued?(name) ⇒ Boolean
- #protected_properties ⇒ Object
- #read_attribute(name) ⇒ Object
- #reload ⇒ Object
- #remove_mixin(mixin_name) ⇒ Object
- #remove_property(name) ⇒ Object
- #replace_property(opts, &block) ⇒ Object
- #retrieve_property_multi_value(property) ⇒ Object
- #retrieve_property_value(property) ⇒ Object
- #retrieve_value(value) ⇒ Object
- #save ⇒ Object
- #session ⇒ Object
- #value_factory ⇒ Object
- #write_attribute(name, value) ⇒ Object
Constructor Details
#initialize(j_node) ⇒ Node
Returns a new instance of Node.
95 96 97 |
# File 'lib/safety_pin/node.rb', line 95 def initialize(j_node) @j_node = j_node end |
Instance Attribute Details
#j_node ⇒ Object (readonly)
Returns the value of attribute j_node.
9 10 11 |
# File 'lib/safety_pin/node.rb', line 9 def j_node @j_node end |
Class Method Details
.build(node_blueprint_or_path_string) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/safety_pin/node.rb', line 31 def self.build(node_blueprint_or_path_string) if node_blueprint_or_path_string.respond_to?(:primary_type, :properties) node_blueprint = node_blueprint_or_path_string else node_blueprint = NodeBlueprint.new(path: node_blueprint_or_path_string) end raise NodeError.new("NodeBlueprint is nil") if node_blueprint.nil? raise NodeError.new("NodeBlueprint has non-absolute path") unless node_blueprint.path.to_s.start_with?("/") raise NodeError.new("Node already exists at path: #{node_blueprint.path}") if Node.exists?(node_blueprint.path) rel_path_to_root_node = node_blueprint.path.to_s[1..-1] node = self.new(session.root_node.add_node(rel_path_to_root_node, node_blueprint.primary_type)) node.properties = node_blueprint.properties node rescue javax.jcr.PathNotFoundException => e raise NodeError.new("Cannot add a new node to a non-existing parent at #{node_blueprint.path}") end |
.create(node_blueprint_or_path_string) ⇒ Object
60 61 62 63 64 |
# File 'lib/safety_pin/node.rb', line 60 def self.create(node_blueprint_or_path_string) node = self.build(node_blueprint_or_path_string) node.save node end |
.create_or_update(node_blueprint_or_node_blueprints) ⇒ Object
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/safety_pin/node.rb', line 84 def self.create_or_update(node_blueprint_or_node_blueprints) node_blueprints = Array(node_blueprint_or_node_blueprints) node_blueprints.map do |node_blueprint| if exists?(node_blueprint.path) update(node_blueprint) else create(node_blueprint) end end end |
.create_parents(path) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/safety_pin/node.rb', line 66 def self.create_parents(path) intermediate_paths = [] current_intermediate_path = Pathname(path) while(current_intermediate_path.to_s != "/") current_intermediate_path = current_intermediate_path.parent intermediate_paths.push(current_intermediate_path) end results = intermediate_paths.reverse.map do |intermediate_path| create(NodeBlueprint.new(:path => intermediate_path.to_s)) unless exists?(intermediate_path) end session.save results end |
.exists?(path) ⇒ Boolean
23 24 25 |
# File 'lib/safety_pin/node.rb', line 23 def self.exists?(path) find(path) != nil end |
.find(path) ⇒ Object
11 12 13 14 15 16 |
# File 'lib/safety_pin/node.rb', line 11 def self.find(path) raise ArgumentError unless path.to_s.start_with?("/") Node.new(session.get_node(path.to_s)) rescue javax.jcr.PathNotFoundException nil end |
.find_or_create(path, primary_type = nil) ⇒ Object
18 19 20 21 |
# File 'lib/safety_pin/node.rb', line 18 def self.find_or_create(path, primary_type = nil) node_blueprint = NodeBlueprint.new(:path => path.to_s, :primary_type => primary_type) find(path) || create(node_blueprint) end |
.session ⇒ Object
27 28 29 |
# File 'lib/safety_pin/node.rb', line 27 def self.session JCR.session end |
.update(node_blueprint) ⇒ Object
51 52 53 54 55 56 57 58 |
# File 'lib/safety_pin/node.rb', line 51 def self.update(node_blueprint) node = find(node_blueprint.path) # raise NodeError.new("Cannot retrieve node for update -- might not exist") if node.nil? node.properties = node_blueprint.properties node.primary_type = node_blueprint.primary_type node.save node end |
Instance Method Details
#==(other_node) ⇒ Object
107 108 109 110 111 |
# File 'lib/safety_pin/node.rb', line 107 def ==(other_node) return false if other_node.nil? return false unless other_node.respond_to?(:path) self.path == other_node.path end |
#[](name) ⇒ Object
262 263 264 |
# File 'lib/safety_pin/node.rb', line 262 def [](name) read_attribute(name) end |
#[]=(name, value) ⇒ Object
266 267 268 |
# File 'lib/safety_pin/node.rb', line 266 def []=(name, value) write_attribute(name, value) end |
#add_mixin(mixin_name) ⇒ Object
361 362 363 |
# File 'lib/safety_pin/node.rb', line 361 def add_mixin(mixin_name) j_node.add_mixin(mixin_name) end |
#build(name, node_blueprint = nil) ⇒ Object
387 388 389 |
# File 'lib/safety_pin/node.rb', line 387 def build(name, node_blueprint = nil) Node.build(node_blueprint_for(name, node_blueprint)) end |
#changed? ⇒ Boolean
270 271 272 |
# File 'lib/safety_pin/node.rb', line 270 def changed? j_node.modified? end |
#child(relative_path) ⇒ Object
130 131 132 133 134 135 |
# File 'lib/safety_pin/node.rb', line 130 def child(relative_path) child_j_node = j_node.get_node(relative_path.to_s) Node.new(child_j_node) rescue javax.jcr.PathNotFoundException nil end |
#children ⇒ Object
118 119 120 121 122 123 124 |
# File 'lib/safety_pin/node.rb', line 118 def children child_nodes = [] j_node.get_nodes.each do |child_j_node| child_nodes << Node.new(child_j_node) end child_nodes end |
#convert_hash_to_node_blueprint(hash) ⇒ Object
Convert a hash (and it’s values recursively) to NodeBlueprints. This is a helper method, allowing a hash to be passed in to Node#properties= when only properties need to be set. One caveat: all node types will default to nt:unstructured.
334 335 336 337 338 339 340 341 |
# File 'lib/safety_pin/node.rb', line 334 def convert_hash_to_node_blueprint(hash) hash.keys.each do |key| if hash[key].is_a? Hash hash[key] = convert_hash_to_node_blueprint(hash[key]) end end NodeBlueprint.new(:path => :no_path, :properties => hash) end |
#create(name, node_blueprint = nil) ⇒ Object
Create and return a child node with a given name
383 384 385 |
# File 'lib/safety_pin/node.rb', line 383 def create(name, node_blueprint = nil) Node.create(node_blueprint_for(name, node_blueprint)) end |
#descendants ⇒ Object
126 127 128 |
# File 'lib/safety_pin/node.rb', line 126 def descendants children.map {|child| [child, child.descendants] }.flatten end |
#destroy ⇒ Object
347 348 349 350 351 352 353 354 355 |
# File 'lib/safety_pin/node.rb', line 347 def destroy path = self.path parent_j_node = j_node.parent j_node.remove parent_j_node.save # raise NodeError.new("Unable to destroy #{path} node") unless self.class.find(path).nil? rescue javax.jcr.RepositoryException => e raise NodeError.new("Unable to destroy #{path} node: #{e.}") end |
#find_or_create(name, primary_type = nil) ⇒ Object
377 378 379 380 |
# File 'lib/safety_pin/node.rb', line 377 def find_or_create(name, primary_type = nil) path = Pathname(self.path) + name self.class.find_or_create(path.to_s, primary_type) end |
#has_property(name) ⇒ Object
423 424 425 |
# File 'lib/safety_pin/node.rb', line 423 def has_property(name) properties.keys.include?(name) end |
#has_property?(name) ⇒ Boolean
202 203 204 |
# File 'lib/safety_pin/node.rb', line 202 def has_property?(name) j_node.has_property(name) end |
#inspect ⇒ Object
427 428 429 |
# File 'lib/safety_pin/node.rb', line 427 def inspect "#<#{self.class} path=#{path}>" end |
#mixin_types ⇒ Object
357 358 359 |
# File 'lib/safety_pin/node.rb', line 357 def mixin_types j_node.mixin_node_types.map(&:name) end |
#name ⇒ Object
137 138 139 |
# File 'lib/safety_pin/node.rb', line 137 def name @name ||= j_node.name end |
#new? ⇒ Boolean
274 275 276 |
# File 'lib/safety_pin/node.rb', line 274 def new? j_node.new? end |
#node_blueprint_for(name, node_blueprint = nil) ⇒ Object
391 392 393 394 395 396 397 398 399 400 |
# File 'lib/safety_pin/node.rb', line 391 def node_blueprint_for(name, node_blueprint = nil) path = Pathname(self.path) + name.to_s unless node_blueprint.nil? properties = node_blueprint.properties primary_type = node_blueprint.primary_type end NodeBlueprint.new(:path => path.to_s, :properties => properties, :primary_type => primary_type) end |
#parent ⇒ Object
113 114 115 116 |
# File 'lib/safety_pin/node.rb', line 113 def parent raise NodeError.new("Root node does not have parent") if path == "/" Node.new(j_node.parent) end |
#path ⇒ Object
99 100 101 |
# File 'lib/safety_pin/node.rb', line 99 def path @path ||= j_node.path end |
#primary_type ⇒ Object
369 370 371 |
# File 'lib/safety_pin/node.rb', line 369 def primary_type self["jcr:primaryType"] end |
#primary_type=(primary_type) ⇒ Object
373 374 375 |
# File 'lib/safety_pin/node.rb', line 373 def primary_type=(primary_type) j_node.set_primary_type(primary_type) end |
#properties ⇒ Object
278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/safety_pin/node.rb', line 278 def properties props = {} prop_iter = j_node.properties while prop_iter.has_next prop = prop_iter.next_property unless prop.definition.protected? prop_name = prop.name props[prop_name] = self[prop_name] end end props end |
#properties=(new_props) ⇒ Object
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/safety_pin/node.rb', line 304 def properties=(new_props) property_names = (properties.keys + new_props.keys).uniq property_names.each do |name| # REFACTOR ME PLZ child_path = Pathname(path.to_s) + name.to_s if new_props[name].is_a? Hash new_props[name] = convert_hash_to_node_blueprint(new_props[name]) end if new_props[name].respond_to?(:node_blueprint?) and new_props[name].node_blueprint? # Handle node blue prints node_blueprint = NodeBlueprint.new(:properties => new_props[name].properties, :path => child_path.to_s, :primary_type => new_props[name].primary_type) if Node.exists?(child_path) Node.update(node_blueprint) else Node.build(node_blueprint) end else # handle everything else self[name] = new_props[name] end end end |
#property_is_multi_valued?(property) ⇒ Boolean
153 154 155 156 157 158 |
# File 'lib/safety_pin/node.rb', line 153 def property_is_multi_valued?(property) property.values true rescue javax.jcr.ValueFormatException false end |
#property_multi_valued?(name) ⇒ Boolean
198 199 200 |
# File 'lib/safety_pin/node.rb', line 198 def property_multi_valued?(name) properties.has_key?(name) and properties[name].is_a?(Array) end |
#property_single_valued?(name) ⇒ Boolean
194 195 196 |
# File 'lib/safety_pin/node.rb', line 194 def property_single_valued?(name) properties.has_key?(name) and !property_multi_valued?(name) end |
#protected_properties ⇒ Object
291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/safety_pin/node.rb', line 291 def protected_properties props = {} prop_iter = j_node.properties while prop_iter.has_next prop = prop_iter.next_property if prop.definition.protected? prop_name = prop.name props[prop_name] = self[prop_name] end end props end |
#read_attribute(name) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/safety_pin/node.rb', line 141 def read_attribute(name) name = name.to_s property = j_node.get_property(name) if property_is_multi_valued?(property) retrieve_property_multi_value(property) else retrieve_property_value(property) end rescue javax.jcr.PathNotFoundException raise NilPropertyError.new("#{name} property not found on node") end |
#reload ⇒ Object
258 259 260 |
# File 'lib/safety_pin/node.rb', line 258 def reload j_node.refresh(false) end |
#remove_mixin(mixin_name) ⇒ Object
365 366 367 |
# File 'lib/safety_pin/node.rb', line 365 def remove_mixin(mixin_name) j_node.remove_mixin(mixin_name) end |
#remove_property(name) ⇒ Object
206 207 208 |
# File 'lib/safety_pin/node.rb', line 206 def remove_property(name) j_node.get_property(name).remove if has_property?(name) end |
#replace_property(opts, &block) ⇒ Object
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
# File 'lib/safety_pin/node.rb', line 402 def replace_property(opts, &block) opts = {recursive: false}.merge(opts) name_pattern = opts.fetch(:name) target_pattern = opts.fetch(:target) replacement_block = block || lambda {|value| opts.fetch(:replacement) } modified = false properties.each do |name, value| if name.match(name_pattern) and value.match(target_pattern) self[name] = replacement_block.call(value) modified = true end end modified_nodes = [] modified_nodes << self if modified modified_nodes << children.map {|child_node| child_node.replace_property(opts) } if opts.fetch(:recursive) modified_nodes.flatten end |
#retrieve_property_multi_value(property) ⇒ Object
160 161 162 |
# File 'lib/safety_pin/node.rb', line 160 def retrieve_property_multi_value(property) property.values.map {|value| retrieve_value(value) } end |
#retrieve_property_value(property) ⇒ Object
164 165 166 |
# File 'lib/safety_pin/node.rb', line 164 def retrieve_property_value(property) retrieve_value(property.value) end |
#retrieve_value(value) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/safety_pin/node.rb', line 168 def retrieve_value(value) property_type = PropertyType.name_from_value(value.type) case property_type when "String" value.string when "Boolean" value.boolean when "Double" value.double when "Long" value.long when "Date" Time.at(value.date.time.time / 1000) when "Name" value.string # Not sure if these should be handled differently when "Binary" value.binary when "Decimal" value.decimal when "Path" Pathname(value.string) else raise PropertyTypeError.new("Unknown property type: #{property_type}") end end |
#save ⇒ Object
248 249 250 251 252 253 254 255 256 |
# File 'lib/safety_pin/node.rb', line 248 def save if new? j_node.parent.save else j_node.save end not changed? end |
#session ⇒ Object
103 104 105 |
# File 'lib/safety_pin/node.rb', line 103 def session @session ||= JCR.session end |
#value_factory ⇒ Object
343 344 345 |
# File 'lib/safety_pin/node.rb', line 343 def value_factory session.value_factory end |
#write_attribute(name, value) ⇒ Object
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 |
# File 'lib/safety_pin/node.rb', line 210 def write_attribute(name, value) raise PropertyError.new("Illegal operation: cannot change jcr:primaryType property") if name == "jcr:primaryType" name = name.to_s if value.nil? remove_property(name) return nil end # when going from multi to single value if property_multi_valued?(name) and !value.is_a?(Array) remove_property(name) end if value.is_a? Array remove_property(name) values = value val_fact = value_factory j_values = [] values.each do |value| j_values << val_fact.create_value(value.to_java) end j_node.set_property(name, j_values.to_java(Java::JavaxJcr::Value)) elsif value.is_a? Time or value.is_a? Date calendar_value = Calendar.instance calendar_value.set_time(value.to_java) j_node.set_property(name, calendar_value) elsif value.is_a?(Symbol) or value.is_a?(Pathname) j_node.set_property(name, value.to_s) else begin j_node.set_property(name, value) rescue NameError raise SafetyPin::PropertyTypeError.new("Property value type of #{value.class} is unsupported") end end end |