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) ⇒ Object
- .create(node_blueprint) ⇒ 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.
- #destroy ⇒ Object
- #find_or_create(name, primary_type = nil) ⇒ Object
- #has_property(name) ⇒ Object
-
#initialize(j_node) ⇒ Node
constructor
A new instance of Node.
- #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
- #protected_properties ⇒ Object
- #read_attribute(name) ⇒ Object
- #reload ⇒ Object
- #remove_mixin(mixin_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.
89 90 91 |
# File 'lib/safety_pin/node.rb', line 89 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) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/safety_pin/node.rb', line 31 def self.build(node_blueprint) 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) ⇒ Object
54 55 56 57 58 |
# File 'lib/safety_pin/node.rb', line 54 def self.create(node_blueprint) node = self.build(node_blueprint) node.save node end |
.create_or_update(node_blueprint_or_node_blueprints) ⇒ Object
78 79 80 81 82 83 84 85 86 87 |
# File 'lib/safety_pin/node.rb', line 78 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
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/safety_pin/node.rb', line 60 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
45 46 47 48 49 50 51 52 |
# File 'lib/safety_pin/node.rb', line 45 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
101 102 103 104 105 |
# File 'lib/safety_pin/node.rb', line 101 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
223 224 225 |
# File 'lib/safety_pin/node.rb', line 223 def [](name) read_attribute(name) end |
#[]=(name, value) ⇒ Object
227 228 229 |
# File 'lib/safety_pin/node.rb', line 227 def []=(name, value) write_attribute(name, value) end |
#add_mixin(mixin_name) ⇒ Object
322 323 324 |
# File 'lib/safety_pin/node.rb', line 322 def add_mixin(mixin_name) j_node.add_mixin(mixin_name) end |
#build(name, node_blueprint = nil) ⇒ Object
348 349 350 |
# File 'lib/safety_pin/node.rb', line 348 def build(name, node_blueprint = nil) Node.build(node_blueprint_for(name, node_blueprint)) end |
#changed? ⇒ Boolean
231 232 233 |
# File 'lib/safety_pin/node.rb', line 231 def changed? j_node.modified? end |
#child(relative_path) ⇒ Object
120 121 122 123 124 125 |
# File 'lib/safety_pin/node.rb', line 120 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
112 113 114 115 116 117 118 |
# File 'lib/safety_pin/node.rb', line 112 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.
295 296 297 298 299 300 301 302 |
# File 'lib/safety_pin/node.rb', line 295 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
344 345 346 |
# File 'lib/safety_pin/node.rb', line 344 def create(name, node_blueprint = nil) Node.create(node_blueprint_for(name, node_blueprint)) end |
#destroy ⇒ Object
308 309 310 311 312 313 314 315 316 |
# File 'lib/safety_pin/node.rb', line 308 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
338 339 340 341 |
# File 'lib/safety_pin/node.rb', line 338 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
384 385 386 |
# File 'lib/safety_pin/node.rb', line 384 def has_property(name) properties.keys.include?(name) end |
#mixin_types ⇒ Object
318 319 320 |
# File 'lib/safety_pin/node.rb', line 318 def mixin_types j_node.mixin_node_types.map(&:name) end |
#name ⇒ Object
127 128 129 |
# File 'lib/safety_pin/node.rb', line 127 def name @name ||= j_node.name end |
#new? ⇒ Boolean
235 236 237 |
# File 'lib/safety_pin/node.rb', line 235 def new? j_node.new? end |
#node_blueprint_for(name, node_blueprint = nil) ⇒ Object
352 353 354 355 356 357 358 359 360 361 |
# File 'lib/safety_pin/node.rb', line 352 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
107 108 109 110 |
# File 'lib/safety_pin/node.rb', line 107 def parent raise NodeError.new("Root node does not have parent") if path == "/" Node.new(j_node.parent) end |
#path ⇒ Object
93 94 95 |
# File 'lib/safety_pin/node.rb', line 93 def path @path ||= j_node.path end |
#primary_type ⇒ Object
330 331 332 |
# File 'lib/safety_pin/node.rb', line 330 def primary_type self["jcr:primaryType"] end |
#primary_type=(primary_type) ⇒ Object
334 335 336 |
# File 'lib/safety_pin/node.rb', line 334 def primary_type=(primary_type) j_node.set_primary_type(primary_type) end |
#properties ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/safety_pin/node.rb', line 239 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
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/safety_pin/node.rb', line 265 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
143 144 145 146 147 148 |
# File 'lib/safety_pin/node.rb', line 143 def property_is_multi_valued?(property) property.values true rescue javax.jcr.ValueFormatException false end |
#protected_properties ⇒ Object
252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/safety_pin/node.rb', line 252 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
131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/safety_pin/node.rb', line 131 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
219 220 221 |
# File 'lib/safety_pin/node.rb', line 219 def reload j_node.refresh(false) end |
#remove_mixin(mixin_name) ⇒ Object
326 327 328 |
# File 'lib/safety_pin/node.rb', line 326 def remove_mixin(mixin_name) j_node.remove_mixin(mixin_name) end |
#replace_property(opts, &block) ⇒ Object
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/safety_pin/node.rb', line 363 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
150 151 152 |
# File 'lib/safety_pin/node.rb', line 150 def retrieve_property_multi_value(property) property.values.map {|value| retrieve_value(value) } end |
#retrieve_property_value(property) ⇒ Object
154 155 156 |
# File 'lib/safety_pin/node.rb', line 154 def retrieve_property_value(property) retrieve_value(property.value) end |
#retrieve_value(value) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/safety_pin/node.rb', line 158 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 else raise PropertyTypeError.new("Unknown property type: #{property_type}") end end |
#save ⇒ Object
209 210 211 212 213 214 215 216 217 |
# File 'lib/safety_pin/node.rb', line 209 def save if new? j_node.parent.save else j_node.save end not changed? end |
#session ⇒ Object
97 98 99 |
# File 'lib/safety_pin/node.rb', line 97 def session @session ||= JCR.session end |
#value_factory ⇒ Object
304 305 306 |
# File 'lib/safety_pin/node.rb', line 304 def value_factory session.value_factory end |
#write_attribute(name, value) ⇒ Object
178 179 180 181 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 207 |
# File 'lib/safety_pin/node.rb', line 178 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? and not j_node.has_property(name) return nil end if value.is_a? Array 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 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 |