module Neo4j # = Neo4j Identity Map # # Ensures that each object gets loaded only once by keeping every loaded # object in a map. Looks up objects using the map when referring to them. # # More information on Identity Map pattern: # http://www.martinfowler.com/eaaCatalog/identityMap.html # # == Configuration # # In order to enable IdentityMap, set config.neo4j.identity_map = true # in your config/application.rb file. If used outside rails, set Neo4j::Config[:identity_map] = true. # # IdentityMap is disabled by default and still in development (i.e. use it with care). # module IdentityMap class << self def enabled=(flag) Thread.current[:neo4j_identity_map] = flag end def enabled Thread.current[:neo4j_identity_map] == true end alias enabled? enabled def node_repository Thread.current[:node_identity_map] ||= java.util.HashMap.new end def rel_repository Thread.current[:rel_identity_map] ||= java.util.HashMap.new end def repository_for(neo_entity) return nil unless enabled? if neo_entity.class == Neo4j::Node node_repository elsif neo_entity.class == Neo4j::Relationship rel_repository else nil end end def use old, self.enabled = enabled, true yield if block_given? ensure self.enabled = old clear end def without old, self.enabled = enabled, false yield if block_given? ensure self.enabled = old end def get(neo_entity) r = repository_for(neo_entity) r && r.get(neo_entity.neo_id) end def add(neo_entity, wrapped_entity) r = repository_for(neo_entity) r && r.put(neo_entity.neo_id, wrapped_entity) end def remove(neo_entity) r = repository_for(neo_entity) r && r.remove(neo_entity.neo_id) end def remove_node_by_id(node_id) node_repository.remove(node_id) end def remove_rel_by_id(rel_id) rel_repository.remove(rel_id) end def clear node_repository.clear rel_repository.clear end def on_after_commit(*) clear end def on_neo4j_started(db) if !Neo4j::Config[:identity_map] && !enabled db.event_handler.remove(self) end end end end end Neo4j.unstarted_db.event_handler.add(Neo4j::IdentityMap)