# class GxG::Database::Database

`Database` class proper

### Public Class Methods

element_table_by_index(the_index=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 97
    def self.element_table_by_index(the_index=0)
      (::GxG::Database::Database::element_tables().keys[(the_index)] || :unspecified)
    end

element_table_for_instance(the_instance=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 101
    def self.element_table_for_instance(the_instance=nil)
      # Review : rewrite - in use
      result = :unspecified
      #
      table = ::GxG::Database::Database::element_tables()
      table.keys.each do |the_key|
        unless the_key == :unspecified
          if the_instance.is_any?(table[(the_key)])
            result = the_key
            break
          end
        end
      end
      #
      result
    end

element_table_index(the_key=:unspecified) click to toggle source

    # File lib/gxg/gxg_database.rb, line 93
    def self.element_table_index(the_key=:unspecified)
      (::GxG::Database::Database::element_tables().keys.index(the_key.to_sym) || 0)
    end

element_tables() click to toggle source

    # File lib/gxg/gxg_database.rb, line 74
    def self.element_tables()
      {
        :unspecified => nil,
        :element_boolean => [::TrueClass, ::FalseClass, ::NilClass],
        :element_integer => [::Integer],
        :element_float => [::Float],
        :element_bigdecimal => [::BigDecimal],
        :element_datetime => [::DateTime],
        :element_text => [::String],
        :element_binary => [::GxG::ByteArray],
        :element_array => [::Array],
        :element_hash => [::Hash]
      }
    end

new(connection = nil, options={}) click to toggle source
Calls superclass method

    # File lib/gxg/gxg_database.rb, line 5111
    def initialize(connection = nil, options={})
      # TODO: require :credential (access privs)
      super()
      @credential = nil
      @url = options[:url]
      @base_permissions = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
      #
      if connection.is_a?(::Sequel::Database)
        @connector = connection
        #
        @active = false
        unless open?()
          raise Exception, "Unable to connect with the database"
        end
        #
        @scheme = @url.scheme.to_s.to_sym
        case @scheme
        when :sqlite, :sqlite3
          @connector.run("PRAGMA page_size=65536")
          @connector.run("PRAGMA max_page_count=281474976710656")
          @connector.run("PRAGMA encoding='UTF-8'")
        when :mysql, :mysql2
          @connector.run("SET GLOBAL max_allowed_packet=17825792;")
          @connector.run("SET NAMES 'utf8' COLLATE 'utf8_general_ci';")
          @connector.run("SET collation_connection = 'utf8_general_ci';")
        when :postgres
          # place holder
        end
      else
        raise Exception, "Invalid db connection"
      end
      # characterize basic effective permissions
      begin
        formatted = db_formatted?()
        @base_permissions[:read] = true
        @base_permissions[:execute] = true
      rescue Exception => the_error
        formatted = false
        raise Exception, "Lack read permissions to the database"
      end
      #
      unless options[:read_only]
        if formatted
          begin
            dbid = @connector[:text_page].insert()
          rescue Exception => the_error
            dbid = nil
          end
          if dbid.is_a?(::Integer)
            @connector[:text_page].filter({:dbid => (dbid)}).delete
            @base_permissions[:write] = true
            @base_permissions[:create] = true
            @base_permissions[:destroy] = true
            @base_permissions[:rename] = true
            @base_permissions[:move] = true
          end
        else
          begin
            test_table_name = ::GxG::uuid_generate().gsub("-","")
            while (@connector.table_exists?(test_table_name.to_sym)) do
              test_table_name = ::GxG::uuid_generate().gsub("-","")
            end
            @connector.create_table(test_table_name.to_sym) do
              primary_key :dbid
            end
            @connector.drop_table(test_table_name.to_sym)
            @base_permissions[:write] = true
            @base_permissions[:create] = true
            @base_permissions[:destroy] = true
            @base_permissions[:rename] = true
            @base_permissions[:move] = true
          rescue Exception => the_error
            # Read-only Database
          end
        end
      end
      #
      @base_permissions.freeze
      #
      unless formatted
        if @base_permissions[:write]
          db_format
          unless db_formatted?()
            @active = false
            raise Exception, "Unable to format the database for use"
          end
        else
          raise Exception, "Unable to format a read-only database"
        end
      end
      #
      @authority = nil
      @db_list = []
      if options[:authority].is_a?(::GxG::Database::Database)
        @authority = options[:authority]
        @authority.db_register(self)
      end
      #
      unless @authority
        unless self.group_exist?("Administrators")
          if @base_permissions[:write]
            if self.user_id_available?("root")
              self.user_create("root","password")
              temp_cred = self.user_credential("root","password")
              temp_group = self.group_create({:title => "Administrators", :default_role => {:title => "Members"}})
              self.role_add_user(temp_group[:default_role],temp_cred)
              #
              dev_group = self.group_create({:title => "Developers", :default_role => {:title => "Members"}})
              dsn_group = self.group_create({:title => "Designers", :default_role => {:title => "Members"}})
              #
              self[:system_credentials] = {:administrator => temp_cred, :administrators => temp_group[:default_role], :developers => dev_group[:default_role], :designers => dsn_group[:default_role]}
              self[:permission_policy] = [{:event => :extend, :credential => :any, :action => {:extend_permissions => temp_group[:default_role]}}]
              #
            end
            if self.user_id_available?("public")
              self.user_create("public","password", "00000000-0000-4000-0000-000000000000")
            end
          end
        end
      end
      #
      permission_policy_load
      self
    end

valid_field_classes() click to toggle source

    # File lib/gxg/gxg_database.rb, line 89
    def self.valid_field_classes()
      [::TrueClass, ::FalseClass, ::NilClass, ::Integer, ::Float, ::BigDecimal, ::DateTime, ::String, ::GxG::ByteArray]
    end

### Public Instance Methods

[](setting_key=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3500
    def [](setting_key=nil)
      result = nil
      begin
        if self.alive?()
          if self.open?()
            record = @connector[:settings].filter({:title => setting_key.to_s}).first
            if record
              content = ""
              @connector[:text_page].select(:content).where({:parent_uuid => record[:uuid].to_s}).order(:ordinal).each do |entry|
                content << entry[:content]
              end
              if content.size > 0
                result = content.unserialize()
              end
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:setting_key => setting_key}})
      end
      result
    end

[]=(setting_key=nil, object=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3527
    def []=(setting_key=nil, object=nil)
      result = object
      begin
        if self.alive?()
          if self.open?()
            unless self.db_permissions()[:write]
              raise Exception, "Unable to write to database"
            end
            unless setting_key.is_a?(::Symbol)
              raise ArgumentError, "You must supply a setting key as a Symbol"
            end
            unless setting_key.to_s.size > 0
              raise ArgumentError, "You must supply a setting key whose length is greater than zero"
            end
            record = @connector[:settings].filter({:title => setting_key.to_s}).first
            unless record
              new_uuid = ::GxG::uuid_generate().to_s
              while (@connector[:settings].filter({:uuid => (new_uuid)}).count > 0 or @connector[:formats].filter({:uuid => (new_uuid)}).count > 0 or @connector[:element_text].filter({:uuid => (new_uuid)}).count > 0)
                new_uuid = ::GxG::uuid_generate().to_s
              end
              @connector[:settings].insert({:title => setting_key.to_s, :uuid => new_uuid.to_s})
              record = @connector[:settings].filter({:uuid => (new_uuid)}).first
            end
            if record
              @connector[:settings].filter({:dbid => (record[:dbid])}).update({:version => (record[:version] + 0.0001)})
              content = object.serialize()
              old_segments = []
              @connector[:text_page].select(:dbid).where({:parent_uuid => record[:uuid].to_s}).order(:ordinal).each do |entry|
                old_segments << entry[:dbid]
              end
              if content.size == 0
                if old_segments.size > 0
                  @connector[:text_page].filter({:parent_uuid => record[:uuid].to_s}).delete
                end
              else
                new_segments = ::GxG::apportioned_ranges(content.size, 4096)
                if old_segments.size > new_segments.size
                  the_count = old_segments.size
                else
                  the_count = new_segments.size
                end
                manifest = []
                (0..(the_count - 1)).each do |the_ordinal|
                  if new_segments[(the_ordinal)] and old_segments[(the_ordinal)]
                    #overwrite with new segment range
                    manifest << {:operation => :overwrite, :dbid => (old_segments[(the_ordinal)]), :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                  else
                    if new_segments[(the_ordinal)]
                      # create new segment at this ordinal
                      manifest << {:operation => :create, :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                    else
                      # delete old segment
                      manifest << {:operation => :delete, :dbid => (old_segments[(the_ordinal)])}
                    end
                  end
                end
                manifest.each do |action|
                  case action[:operation]
                  when :overwrite
                    @connector[:text_page].filter({:dbid => (action[:dbid])}).update({:ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
                  when :create
                    @connector[:text_page].insert({:parent_uuid => (record[:uuid]), :ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
                  when :delete
                    @connector[:text_page].filter({:dbid => (action[:dbid])}).delete
                  end
                end
                #
              end
            else
              raise Exception, "Internal Error - could not retrieve setting record: #{setting_key.inspect}"
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:setting => setting_key, :object => object}})
      end
      result
    end

assign_element_permission(table=:unspecified, dbid=0, credential=nil, permissions={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1502
    def assign_element_permission(table=:unspecified, dbid=0, credential=nil, permissions={})
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless dbid.is_a?(::Integer)
          raise ArgumentError, "dbid must be specified with a Integer"
        end
        unless permissions.is_a?(::Hash)
          raise ArgumentError, "permissions must be specified with a Hash"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
        end
        if table.is_a?(::Integer)
          table = ::GxG::Database::Database::element_table_by_index(table)
        end
        # Review : change in permission policy
        # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
        if [:element_array, :element_hash].include?(table)
          record = @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)}).first
          if record
            # update
            the_update = {:execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
            [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
              if record[(the_permission)] == 1
                the_update[(the_permission)] = 1
              end
            end
            [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
              if permissions[(the_permission)].is_a?(::TrueClass)
                the_update[(the_permission)] = 1
              end
              if permissions[(the_permission)].is_a?(::FalseClass)
                the_update[(the_permission)] = 0
              end
            end
            the_update[:version] = record[:version] + 0.0001
            @connector[:permissions].filter({:dbid => (record[:dbid])}).update(the_update)
          else
            # create
            new_record = {:credential => (credential.to_s), :element_table => (table.to_s), :elementid => (dbid), :execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
            [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
              if permissions[(the_permission)]
                new_record[(the_permission)] = 1
              end
            end
            @connector[:permissions].insert(new_record)
          end
          result = true
        else
          raise ArgumentError, "Invalid table specified"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :credential => (credential), :permissions => (permissions)}})
      end
      result
    end

byte_size_by_uuid(the_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2514
    def byte_size_by_uuid(the_uuid=nil)
      result = 0
      begin
        if self.alive?
          if self.open?
            found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
            if found
              result += self.element_byte_size(:element_hash,(found[:dbid]))
            else
              found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
              if found
                result += self.element_byte_size(:element_array,(found[:dbid]))
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:uuid => (the_uuid)}})
      end
      result
    end

clear_all_element_locks() click to toggle source

Utility methods

    # File lib/gxg/gxg_database.rb, line 5086
    def clear_all_element_locks()
      # for when boo-boos happen
      if self.open?()
        if self.db_permissions()[:write]
          @connector[:element_locks].filter({}).delete
        end
      end
    end

clone() click to toggle source

    # File lib/gxg/gxg_database.rb, line 5107
    def clone()
      initialize_clone
    end

close() click to toggle source

    # File lib/gxg/gxg_database.rb, line 415
    def close()
      # place holder for now.
      if @authority
        @authority.db_unregister(self)
      end
    end

connector() click to toggle source

    # File lib/gxg/gxg_database.rb, line 422
    def connector()
      @connector
    end

create_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1767
    def create_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false})
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless file_id.is_a?(::String)
          raise ArgumentError, "file_id must be specified with a String"
        end
        unless permission.is_a?(::Hash)
          raise ArgumentError, "permission must be specified with a Hash"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
        end
        #
        record = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).first
        if record
          update = true
          dbid = record.delete(:dbid)
        else
          update = false
          dbid = nil
          record = {:file_id => file_id.to_s, :credential => credential.to_s, :execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
        end
        permission.keys.each do |the_permission_key|
          if permission[(the_permission_key)] == true
            record[(the_permission_key)] = 1
          else
            record[(the_permission_key)] = 0
          end
        end
        if update == true
          @connector[:file_permissions].filter({:dbid => dbid}).update(record)
        else
          @connector[:file_permissions].insert(record)
        end
        result = true
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
      end
      result
    end

db_format(format_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 297
    def db_format(format_options={})
      # MySql stuff:
      # ALTER TABLE tbl_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;
      # See: https://dev.mysql.com/doc/refman/5.0/en/table-size-limit.html
      result = true
      #
      begin
        if @connector.is_a?(::Sequel::Database)
          case @scheme
          when :sqlite
            @connector.run("PRAGMA page_size=65536")
            @connector.run("PRAGMA max_page_count=281474976710656")
            @connector.run("PRAGMA encoding='UTF-8'")
          when :mysql, :mysql2
            @connector.run("SET GLOBAL max_allowed_packet = 17825792;")
            @connector.run("SET NAMES 'utf8' COLLATE 'utf8_general_ci';")
            @connector.run("SET collation_connection = 'utf8_general_ci';")
          when :postgres
            # place holder
          end
          migration = db_migration()
          migration.keys.each do |the_table|
            unless @connector.table_exists?(the_table)
                @connector.create_table(the_table) do
                primary_key :dbid
              end
            end
            used_bytes = 0
            #
            existing_columns = @connector[(the_table)].columns
            migration[(the_table)].keys.each do |the_column|
              used_bytes += (migration[(the_table)][(the_column)][:bytes]).to_i
              if existing_columns.include?(the_column)
                # TODO: figure out a way to inspect columns for attributes -> detailed verification
              else
                # collation for mysql
                if @scheme == :mysql
                  # Note: might have to specify :collate first, use -> {:collate => ""}.merge(migration[(the_table)][(the_column)][:options])
                  if migration[(the_table)][(the_column)][:type] == :varchar
                    # migration[(the_table)][(the_column)][:options] = {:collate => "utf8_general_ci"}.merge(migration[(the_table)][(the_column)][:options])
                    migration[(the_table)][(the_column)][:options][:collate] = "utf8_general_ci"
                  end
                  if migration[(the_table)][(the_column)][:type] == :blob
                    # migration[(the_table)][(the_column)][:options] = {:collate => "binary"}.merge(migration[(the_table)][(the_column)][:options])
                    # Note: MySQL 5 doesn't like putting collation on blobs! (blows up)
                    # migration[(the_table)][(the_column)][:options][:collate] = "binary"
                  end
                else
                end
                # do the deed
                @connector.add_column((the_table), (the_column), (migration[(the_table)][(the_column)][:type]), (migration[(the_table)][(the_column)][:options]))
                #
              end
            end
            #
            if @scheme == :mysql
              @connector.run("ALTER TABLE #{the_table.to_s} MAX_ROWS=18446744073709551616 AVG_ROW_LENGTH=#{used_bytes.to_s};")
            end
            #
          end
        else
          raise Exception, "Invalid db connection"
        end
      rescue Exception => the_error
        result = false
        log_error({:error => the_error, :parameters => format_options})
      end
      #
      result
    end

db_formatted?() click to toggle source

    # File lib/gxg/gxg_database.rb, line 368
    def db_formatted?()
      result = true
      #
      begin
        if @connector.is_a?(::Sequel::Database)
          migration = db_migration()
          migration.keys.each do |the_table|
            unless @connector.table_exists?(the_table)
              result = false
              break
            end
            #columns
            existing_columns = @connector[(the_table)].columns
            migration[(the_table)].keys.each do |the_column|
              unless existing_columns.include?(the_column)
                result = false
                break
              end
            end
            #
            unless (result)
              break
            end
          end
        else
          raise Exception, "Invalid db connection"
        end
      rescue Exception => the_error
        result = false
        log_error({:error => the_error, :parameters => nil})
      end
      #
      result
    end

db_list() click to toggle source

    # File lib/gxg/gxg_database.rb, line 455
    def db_list()
      result = []
      @db_list.each do |the_db|
        result << the_db
      end
      result
    end

db_migration() click to toggle source

    # File lib/gxg/gxg_database.rb, line 118
    def db_migration()
      # Review : Consider adding support for a ::Symbol class as well. (ease-of-use implications later)
      # Internal mapping of the database format
      # Datatypes - See: http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html
      # Column Options - See: http://sequel.jeremyevans.net/rdoc/classes/Sequel/Database.html#method-i-add_column
      # See also : http://ruby-doc.org/core-2.2.0/Array.html#method-i-pack
      {
        :element_text => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
          },
        :text_page => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :content => {:type => :varchar, :options => {:size => 4099, :default => "", :null => false}, :bytes => 4099}
          },
        :element_binary => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :format => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
          },
        :binary_page => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :content => {:type => :blob, :options => {:size => 65536}, :bytes => 65536}
          },
        :element_array => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :constraint => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :title => {:type => :varchar, :options => {:size => 259, :null => false, :default => "Untitled"}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
          },
        :array_elements => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :element => {:type => :varchar, :options => {:size => 259, :default => "element_boolean", :null => false}, :bytes => 259},
          :element_boolean => {:type => :integer, :options => {:size => 1, :default => -1}, :bytes => ([ -1 ].pack('l!').length)},
          :element_integer => {:type => :integer, :options => {}, :bytes => ([ -1 ].pack('l!').length)},
          :element_float => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :element_bigdecimal => {:type => :numeric, :options => {:default => ::BigDecimal.new("0.0")}, :bytes => 256},
          :element_datetime => {:type => :datetime, :options => {}, :bytes => 16},
          :time_offset => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :time_prior => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :time_after => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :element_text => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :element_text_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_binary_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_array_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_hash_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40}
        },
        :element_hash => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :format => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :title => {:type => :varchar, :options => {:size => 259, :null => false, :default => "Untitled"}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
          },
        :hash_properties => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :property => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :ordinal => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :element => {:type => :varchar, :options => {:size => 259, :default => "element_boolean", :null => false}, :bytes => 259},
          :element_boolean => {:type => :integer, :options => {:size => 1, :default => -1}, :bytes => ([ -1 ].pack('l!').length)},
          :element_integer => {:type => :integer, :options => {}, :bytes => ([ -1 ].pack('l!').length)},
          :element_float => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :element_bigdecimal => {:type => :numeric, :options => {:default => ::BigDecimal.new("0.0")}, :bytes => 256},
          :element_datetime => {:type => :datetime, :options => {}, :bytes => 16},
          :time_offset => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :time_prior => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :time_after => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :length => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :element_text => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :element_text_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_binary_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_array_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_hash_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40}
        },
        :element_locks => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :type => {:type => :varchar, :options => {:size => 40,:default => "", :null => false}, :bytes => 40},
          :reservation => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :credential => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :element_table => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :elementid => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
        },
        :trash => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :element_table => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :elementid => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)}
        },
        :users => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :user_id => {:type => :varchar, :options => {:size => 259, :null => false, :default => ""}, :bytes => 259},
          :password_hash => {:type => :varchar, :options => {:size => 259, :null => false, :default => ""}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        },
        :roles => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :group_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :seo => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        },
        :user_roles => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :user_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :role_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        },
        :groups => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :parent_uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :default_role => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :seo => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        },
        :permissions => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :credential => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :execute => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :rename => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :move => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :destroy => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :create => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :write => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :read => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :element_table => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :elementid => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        },
        :file_permissions => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :file_id => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :credential => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :execute => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :rename => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :move => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :destroy => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :create => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :write => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :read => {:type => :integer, :options => {:default => 0}, :bytes => ([ -1 ].pack('l!').length)},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        },
        :formats => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :type => {:type => :varchar, :options => {:size => 40, :null => false, :default => "structure"}, :bytes => 40},
          :ufs => {:type => :varchar, :options => {:size => 4099, :default => "", :null => false}, :bytes => 4099},
          :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)},
          :mime_types => {:type => :varchar, :options => {:size => 4099, :default => "", :null => false}, :bytes => 4099}
        },
        :settings => {
          :dbid => {:type => :integer, :options => {:unique => true, :primary_key => true, :auto_increment => true}, :bytes => ([ -1 ].pack('l!').length)},
          :uuid => {:type => :varchar, :options => {:size => 40, :default => "", :null => false}, :bytes => 40},
          :title => {:type => :varchar, :options => {:size => 259, :default => "", :null => false}, :bytes => 259},
          :version => {:type => :float, :options => {:default => 0.0}, :bytes => ([ 0.1 ].pack('d').length)}
        }
      }
    end

db_permissions() click to toggle source

Permission Handling methods

    # File lib/gxg/gxg_database.rb, line 435
    def db_permissions
      @base_permissions.clone
    end

db_register(the_db) click to toggle source

Authority support

    # File lib/gxg/gxg_database.rb, line 439
    def db_register(the_db)
      if the_db.is_a?(::GxG::Database::Database)
        unless @db_list.find_index(the_db)
          @db_list << the_db
        end
      end
    end

db_unregister(the_db) click to toggle source

    # File lib/gxg/gxg_database.rb, line 447
    def db_unregister(the_db)
      if the_db.is_a?(::GxG::Database::Database)
        if @db_list.find_index(the_db)
          @db_list.delete_at(@db_list.find_index(the_db))
        end
      end
    end

destroy_by_uuid(credential=nil, the_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2457
    def destroy_by_uuid(credential=nil, the_uuid=nil)
      # Review : rewrite - in use
      # element_destroy(credential=nil,table=:unspecified,dbid=0, options={})
      # .effective_uuid_permission(data["location"].to_s.to_sym,@credential)
      result = false
      begin
        if self.alive?
          if self.open?
            if self.db_permissions()[:destroy] == true
              if ::GxG::valid_uuid?(credential)
                found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
                if found
                  self.element_destroy(credential, :element_hash,(found[:dbid]))
                  result = true
                else
                  found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
                  if found
                    self.element_destroy(credential, :element_array,(found[:dbid]))
                    result = true
                  end
                end
              else
                raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:credential => (credential), :uuid => (the_uuid)}})
      end
      result
    end

destroy_vfs_permission(file_id=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1861
    def destroy_vfs_permission(file_id=nil, credential=nil)
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless file_id.is_a?(::String)
          raise ArgumentError, "file_id must be specified with a String"
        end
        # ### Review : make more efficient
        if credential
          unless ::GxG::valid_uuid?(credential)
            raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
          end
          record = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).first
          if record
            @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).delete
          end
        else
          record = @connector[:file_permissions].filter({:file_id => file_id.to_s}).first
          if record
            @connector[:file_permissions].filter({:file_id => file_id.to_s}).delete
          end
        end
        result = true
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
      end
      result
    end

dup()
Alias for: initialize_clone
effective_element_permission(table=:unspecified, dbid=0, credential=nil) click to toggle source

DB Objects

    # File lib/gxg/gxg_database.rb, line 1895
    def effective_element_permission(table=:unspecified, dbid=0, credential=nil)
      result = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless dbid.is_a?(::Integer)
          raise ArgumentError, "dbid must be specified with a Integer"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
        end
        if table.is_a?(::Integer)
          table = ::GxG::Database::Database::element_table_by_index(table)
        end
        # Review : change in permission policy
        # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
        if [:element_array, :element_hash].include?(table)
          # is credential a user or role?
          raw_permissions = []
          # Include PUBLIC credential
          credentials = ["00000000-0000-4000-0000-000000000000"]
          #
          if self.user_exist?(credential)
            credentials << credential
            role_list = self.user_roles(credential)
            role_list.each do |entry|
              credentials << entry[:credential]
            end
            #
          else
            if self.role_exist?(credential)
              credentials << credential
            else
              raise ArgumentError, "Invalid credential.  It is neither a user nor a role UUID"
            end
          end
          credentials.each do |entry|
            manifest = @connector[:permissions].filter({:credential => (entry.to_s), :element_table => (table.to_s), :elementid => (dbid)})
            manifest.each do |record|
              new_permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
              [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
                if record[(the_permission)] == 1
                  new_permission[(the_permission)] = true
                end
              end
              raw_permissions << new_permission
            end
          end
          permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
          raw_permissions.each do |entry|
            [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
              if entry[(the_permission)]
                permission[(the_permission)] = true
              end
            end
          end
          db_limits = self.db_permissions()
          [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
            if db_limits[(the_permission)] and permission[(the_permission)]
              result[(the_permission)] = true
            end
          end
          #
        else
          raise ArgumentError, "Invalid table specified"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :credential => (credential)}})
      end
      result
    end

effective_uuid_permission(uuid=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1971
    def  effective_uuid_permission(uuid=nil, credential=nil)
      result = nil
      begin
        if self.alive?
          if self.open?
            address = nil
            record = @connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
            if record
              address = {:database => self, :table => :element_hash, :dbid => (record[:dbid])}
            else
              record = @connector[:element_array].filter({:uuid => (uuid.to_s)}).first
              if record
                address = {:database => self, :table => :element_array, :dbid => (record[:dbid])}
              end
            end
            if address
              result = self.effective_element_permission(address[:table], address[:dbid], credential)
            else
              # ### Review : Experimental Code - attempt to seemlessly integrate dbs of different roles into in-memory structures.
              already_checked = [(self)]
              ::GxG::DB[:roles].each_pair do |the_db_role, the_database|
                unless already_checked.include?(the_database)
                  record = the_database.connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
                  if record
                    address = {:database => the_database, :table => :element_hash, :dbid => (record[:dbid])}
                    result = the_database.effective_element_permission(address[:table], address[:dbid], credential)
                    break
                  else
                    record = the_database.connector[:element_array].filter({:uuid => (uuid.to_s)}).first
                    if record
                      address = {:database => the_database, :table => :element_array, :dbid => (record[:dbid])}
                      result = the_database.effective_element_permission(address[:table], address[:dbid], credential)
                      break
                    end
                  end
                  already_checked << the_database
                end
              end
              #
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:uuid => (uuid), :credential => (credential)}})
      end
      result
    end

effective_vfs_permission(file_id=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1710
    def effective_vfs_permission(file_id=nil, credential=nil)
      result = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless file_id.is_a?(::String)
          raise ArgumentError, "file_id must be specified with a String"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
        end
        # ### VFS Permissions
        raw_permissions = []
        credentials = ["00000000-0000-4000-0000-000000000000"]
        if self.user_exist?(credential)
          credentials << credential
          role_list = self.user_roles(credential)
          role_list.each do |entry|
            credentials << entry[:credential]
          end
          #
        else
          if self.role_exist?(credential)
            credentials << credential
          else
            raise ArgumentError, "Invalid credential.  It is neither a user nor a role UUID"
          end
        end
        credentials.each do |entry|
          manifest = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => (entry.to_s)})
          manifest.each do |record|
            new_permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}
            [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
              if record[(the_permission)] == 1
                new_permission[(the_permission)] = true
              end
            end
            raw_permissions << new_permission
          end
        end
        raw_permissions.each do |entry|
          [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
            if entry[(the_permission)]
              result[(the_permission)] = true
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
      end
      result
    end

element_byte_size(table=:unspecified, dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2490
    def element_byte_size(table=:unspecified, dbid=0)
      #
      result = 0
      begin
        if self.alive?
          if self.open?
            migration = self.db_migration()
            elements = self.element_manifest(table, dbid, true)
            elements.each do |entry|
              table_definition = migration[(entry[:table])]
              if table_definition
                table_definition.keys.each do |the_field|
                  result += table_definition[(the_field)][:bytes].to_i
                end
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid)}})
      end
      result
    end

element_create(the_table=:unspecified, the_record=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2090
    def element_create(the_table=:unspecified, the_record=nil)
      # Review : rewrite - in use
      result = nil
      begin
        unless the_table.is_a?(::Symbol)
          raise ArgumentError, "You MUST provide the table specifier as a Symbol."
        end
        unless the_record.is_a?(::Hash)
          raise ArgumentError, "You MUST provide a record in the form of a Hash."
        end
        if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :text_page, :element_binary, :binary_page, :element_array, :element_hash].include?(the_table)
          # Review : UTF8 fix
          begin
            result = @connector[(the_table)].insert(the_record)
          rescue Exception
            if the_table == :text_page
              the_record[:content] = the_record[:content].encode64
            end
            result = @connector[(the_table)].insert(the_record)
          end
        else
          raise ArgumentError, "The table specified is unknown - Check your code."
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (the_table), :record => (the_record)}})
      end
      result
    end

element_destroy(credential=nil,table=:unspecified,dbid=0, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2401
    def element_destroy(credential=nil,table=:unspecified,dbid=0, options={})
      # Review : rewrite for new arch.
      # Review : rewrite - in use
      result = false
      begin
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              # if credential has :destroy permission on this element?
              if ::GxG::valid_uuid?(credential)
                if [:persisted_array, :persisted_hash].include?(table.to_s.to_sym)
                  go_ahead = self.effective_element_permission(table, dbid, credential)[:destroy]
                else
                  go_ahead = true
                end
                # xxx Quick fix : BETA: clean all this up!
                if go_ahead
                  # Review : DB overhaul / rewrite - allow delete if object has write lock in place? I think not. (return false)
                  # Note: BETA - bring back read-locks? it was 9x slower with them ... not sure.
                  elements = self.element_manifest(table, dbid, false)
                  elements.each do |entry|
                    #
                    unless self.element_in_trash?(entry[:table], entry[:dbid])
                      @connector[:trash].insert({:element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                    end
                    #
                    #if @connector[:element_locks].filter({:type => "read", :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count > 0
                      # put in trash
                      #unless self.element_in_trash?(entry[:table], entry[:dbid])
                        #@connector[:trash].insert({:element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                      #end
                    #else
                      # delete now
                      #manifest = self.element_manifest(entry[:table], entry[:dbid], true)
                      #manifest.each do |item|
                        #@connector[:permissions].filter({:element_table => (item[:table].to_s), :elementid => (item[:dbid])}).delete
                        #@connector[(item[:table])].filter({:dbid => item[:dbid]}).delete
                      #end
                    #end
                  end
                  result = true
                else
                  raise Exception, "You do not have permission to destory this element"
                end
              else
                raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:credential => (credential), :table => (table), :dbid => (dbid)}})
      end
      result
    end

element_exists?(the_table=:unspecified, the_dbid=0) click to toggle source

Data Handling methods

    # File lib/gxg/gxg_database.rb, line 2024
    def element_exists?(the_table=:unspecified, the_dbid=0)
      result = false
      if the_table.is_a?(::Integer)
        the_table = ::GxG::Database::Database::element_table_by_index(the_table)
      end
      if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(the_table)
        begin
          record = @connector[(the_table)].select(:dbid).where({:dbid => (the_dbid)}).first
          if record
            result = true
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:table => (the_table), :dbid => (the_dbid)}})
        end
      end
      result
    end

element_in_trash?(table=:unspecified, dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3021
    def element_in_trash?(table=:unspecified, dbid=0)
      result = false
      begin
        if self.alive?
          if self.open?
            if @connector[:trash].filter({:element_table => table.to_s, :elementid => dbid}).count > 0
              result = true
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid)}})
      end
      result
    end

element_in_use?(db_table=:unspecified, dbid = 0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2211
    def element_in_use?(db_table=:unspecified, dbid = 0)
      # Review : rewrite - in use for now.
      # Review : rewrite - todo (alter to reflect the new architecture : perhaps limit to structures only)
      unless db_table.is_any?(::Integer, ::Symbol)
        raise ArgumentError, "Table needs to be specified as a Symbol, or a table code Integer"
      end
      unless dbid.is_a?(::Integer)
        raise ArgumentError, "Record ID needs to be specified with an Integer"
      end
      result = false
      begin
        if db_table == :element_hash || db_table == :element_array
          # Review : make more efficient in later revs of this.
          the_record = @connector[(db_table)].filter({:dbid => (dbid)}).select(:uuid).first
          if the_record
            if @connector[:hash_properties].filter({:element_hash_uuid => the_record[:uuid]}).count > 0 || @connector[:array_elements].filter({:element_array_uuid => the_record[:uuid]}).count > 0
              result = true
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table_code => (db_table), :dbid => (dbid)}})
      end
      result
    end

element_manifest(the_table=:unspecified, the_dbid=0, everything=false) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2263
    def element_manifest(the_table=:unspecified, the_dbid=0, everything=false)
      # Review : rewrite - in use
      # returns an Array of tables and dbid pairs and sub-item pairs if they exist
      result = []
      #
      begin
        unless the_dbid > 0
          raise ArgumentError, "dbid specified must be greater than zero"
        end
        case the_table
        when :element_text
          the_record = @connector[:element_text].select(:uuid, :dbid).where({:dbid => (the_dbid)}).first
          if the_record
            result << {:table => :element_text, :dbid => the_record[:dbid]}
            if everything
              the_pages = @connector[:text_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
              the_pages.each do |entry|
                result << {:table => :text_page, :dbid => entry[:dbid]}
              end
            end
          end
        when :element_binary
          the_record = @connector[:element_binary].select(:uuid, :dbid).where({:dbid => (the_dbid)}).first
          if the_record
            result << {:table => :element_binary, :dbid => the_record[:dbid]}
            if everything
              the_pages = @connector[:binary_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
              the_pages.each do |entry|
                result << {:table => :binary_page, :dbid => entry[:dbid]}
              end
            end
          end
        when :element_array, :element_hash
          record_db = [{:table => the_table, :dbid => the_dbid}]
          while record_db.size > 0 do
            item = record_db.shift
            case item[:table]
            when :element_text
              the_record = @connector[:element_text].select(:uuid, :dbid).where({:dbid => item[:dbid]}).first
              if the_record
                result << {:table => :element_text, :dbid => the_record[:dbid]}
                if everything
                  the_pages = @connector[:text_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
                  the_pages.each do |entry|
                    result << {:table => :text_page, :dbid => entry[:dbid]}
                  end
                end
              end
            when :element_binary
              the_record = @connector[:element_binary].select(:uuid, :dbid).where({:dbid => item[:dbid]}).first
              if the_record
                result << {:table => :element_binary, :dbid => the_record[:dbid]}
                if everything
                  the_pages = @connector[:binary_page].select(:dbid, :ordinal).where({:parent_uuid => (the_record[:uuid])}).order(:ordinal)
                  the_pages.each do |entry|
                    result << {:table => :binary_page, :dbid => entry[:dbid]}
                  end
                end
              end
            when :element_array
              result << {:table => item[:table], :dbid => item[:dbid]}
              array_record = @connector[:element_array].select(:uuid).where({:dbid => item[:dbid]}).first
              if array_record
                @connector[:array_elements].filter({:parent_uuid => (array_record[:uuid])}).order(:ordinal).each do |entry|
                  if entry[:element_text_uuid].size > 0
                    the_temp_record = @connector[:element_text].select(:dbid).where({:uuid => entry[:element_text_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_text, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  if entry[:element_binary_uuid].size > 0
                    the_temp_record = @connector[:element_binary].select(:dbid).where({:uuid => entry[:element_binary_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_binary, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  if entry[:element_array_uuid].size > 0
                    the_temp_record = @connector[:element_array].select(:dbid).where({:uuid => entry[:element_array_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_array, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  if entry[:element_hash_uuid].size > 0
                    the_temp_record = @connector[:element_hash].select(:dbid).where({:uuid => entry[:element_hash_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_hash, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  result << {:table => :array_elements, :dbid => entry[:dbid]}
                end
              end
            when :element_hash
              result << {:table => item[:table], :dbid => item[:dbid]}
              hash_record = @connector[:element_hash].select(:uuid).where({:dbid => item[:dbid]}).first
              if hash_record
                @connector[:hash_properties].filter({:parent_uuid => (hash_record[:uuid])}).order(:ordinal).each do |entry|
                  if entry[:element_text_uuid].size > 0
                    the_temp_record = @connector[:element_text].select(:dbid).where({:uuid => entry[:element_text_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_text, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  if entry[:element_binary_uuid].size > 0
                    the_temp_record = @connector[:element_binary].select(:dbid).where({:uuid => entry[:element_binary_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_binary, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  if entry[:element_array_uuid].size > 0
                    the_temp_record = @connector[:element_array].select(:dbid).where({:uuid => entry[:element_array_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_array, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  if entry[:element_hash_uuid].size > 0
                    the_temp_record = @connector[:element_hash].select(:dbid).where({:uuid => entry[:element_hash_uuid]}).first
                    if the_temp_record
                      record_db << {:table => :element_hash, :dbid => the_temp_record[:dbid]}
                    end
                  end
                  result << {:table => :hash_properties, :dbid => entry[:dbid]}
                end
              end
            else
              the_record = @connector[(item[:table])].select(:dbid).where({:dbid => (item[:dbid])}).first
              if the_record
                result << {:table => item[:table], :dbid => item[:dbid]}
              end
            end
          end
          #
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (the_table), :dbid => (the_dbid)}})
      end
      result
    end

element_parent_address(the_table=:unspecified, the_dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2237
    def element_parent_address(the_table=:unspecified, the_dbid=0)
      result = nil
      if self.element_in_use?(the_table,the_dbid)
        begin
          link = @connector[:hash_links].select(:parent_uuid).where({:element => (::GxG::Database::Database::element_table_index(the_table)), :elementid => (the_dbid)}).first
          if link
            record = @connector[:element_hash].select(:dbid).where({:uuid => link[:parent_uuid]}).first
            if record
              result = {:table => :element_hash, :dbid => (record[:dbid])}
            end
          else
            link = @connector[:array_links].select(:parent_uuid).where({:element => (::GxG::Database::Database::element_table_index(the_table)), :elementid => (the_dbid)}).first
            if link
              record = @connector[:element_array].select(:dbid).where({:uuid => link[:parent_uuid]}).first
              if record
                result = {:table => :element_array, :dbid => (record[:dbid])}
              end
            end
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:table => (the_table), :dbid => (the_dbid)}})
        end
      end
      result
    end

element_permissions(table=:unspecified, dbid=0, options={}) click to toggle source

Raw Permission Handling methods

    # File lib/gxg/gxg_database.rb, line 1345
    def element_permissions(table=:unspecified, dbid=0, options={})
      result = []
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless dbid.is_a?(::Integer)
          raise ArgumentError, "dbid must be specified with a Integer"
        end
        unless options.is_a?(::Hash)
          raise ArgumentError, "options must be specified with a Hash"
        end
        credential = options[:credential]
        if credential
          unless ::GxG::valid_uuid?(credential)
            raise ArgumentError, "This option requires a valid credential UUID (as a String or Symbol)"
          end
        end
        if table.is_a?(::Integer)
          table = ::GxG::Database::Database::element_table_by_index(table)
        end
        # Review : change in permission policy
        # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
        if [:element_array, :element_hash].include?(table)
          if credential
            list = @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)})
          else
            list = @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid)})
          end
          list.each do |record|
            # [:execute, :rename, :move, :destroy, :create, :write, :read]
            entry = {:credential => (record[:credential].to_sym), :table => (record[:element_table].to_sym), :dbid => (record[:elementid]), :permissions => {}}
            [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
              if record[(the_permission)] == 1
                entry[:permissions][(the_permission)] = true
              else
                entry[:permissions][(the_permission)] = false
              end
            end
            result << entry
          end
        else
          raise ArgumentError, "Invalid table specified"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :options => (options)}})
      end
      result
    end

element_permissions_by_uuid(the_uuid=nil,options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1458
    def element_permissions_by_uuid(the_uuid=nil,options={})
      result = []
      begin
        if self.alive?
          if self.open?
            found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
            if found
              result = self.element_permissions_manifest(:element_hash,(found[:dbid]),options)
            else
              found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
              if found
                result = self.element_permissions_manifest(:element_array,(found[:dbid]),options)
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:uuid => (the_uuid)}})
      end
      result
    end

element_permissions_manifest(table=:unspecified, dbid=0, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1431
    def element_permissions_manifest(table=:unspecified, dbid=0, options={})
      result = []
      self.element_permissions(table,dbid,options).each do |entry|
        the_record = {:credential => nil, :permissions => {}, :details => {}}
        #
        the_record[:credential] = entry[:credential]
        the_record[:permissions] = entry[:permissions]
        if self.role_exist?(entry[:credential])
          role = self.role_fetch({:uuid => entry[:credential].to_s})
          group = self.group_fetch({:uuid => role[:group_uuid].to_s})
          the_record[:details][:role_title] = role[:title]
          the_record[:details][:group] = group[:uuid].to_s.to_sym
          the_record[:details][:group_title] = group[:title]
        else
          if self.user_exist?(entry[:credential])
            user = self.user_fetch({:uuid => entry[:credential].to_s})
            the_record[:details][:user_title] = user[:user_id]
          else
            log_warn("Invalid User Credential Detected: #{entry[:credential].to_s.to_sym.inspect}")
            the_record[:details][:user_title] = "Invalid User Credential #{entry[:credential].to_s.to_sym.inspect} !"
          end
        end
        result << the_record
      end
      result
    end

element_recover(table=:unspecified, dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3037
    def element_recover(table=:unspecified, dbid=0)
      # recover an element from the trash
      result = false
      begin
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              unless [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
                raise ArgumentError, "Invalid table specified"
              end
              unless dbid > 0
                raise ArgumentError, "dbid must be greater than zero"
              end
              if self.element_in_trash?(table, dbid)
                scrub_list = []
                manifest = self.element_manifest(table, dbid)
                manifest.each do |entry|
                  if @connector[:trash].filter({:element_table => (entry[:table].to_s), :elementid => (entry[:dbid])}).count > 0
                    record = @connector[:trash].select(:dbid).where({:element_table => (entry[:table].to_s), :elementid => (entry[:dbid])}).first
                    if record
                      scrub_list << record[:dbid]
                    end
                  end
                end
                scrub_list.each do |entry|
                  @connector[:trash].filter({:dbid => entry}).delete
                end
                result = true
              else
                # it was never in the trash, so mission accomplished
                result = true
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid)}})
      end
      result
    end

element_retrieve(the_table=:unspecified, the_filter={}, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2042
    def element_retrieve(the_table=:unspecified, the_filter={}, options={})
      result = []
      begin
        if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :text_page, :element_binary,:binary_page, :element_array, :element_hash].include?(the_table)
          #
          if the_filter.is_a?(::Hash)
            if options[:order]
              raw_result = @connector[(the_table)].filter(the_filter).order(options[:order])
            else
              raw_result = @connector[(the_table)].filter(the_filter)
            end
            # Review : UTF-8 Encoding Error Fix
            if options[:single_record] == true
              result = raw_result.first
              # utf8 fix
              if the_table == :text_page
                if result[:content].is_a?(::String)
                  if result[:content].base64?
                    result[:content] = result[:content].decode64
                  end
                end
              end
              #
            else
              # utf8 fix
              raw_result.each do |the_record|
                if the_record[:content].is_a?(::String)
                  if the_record[:content].base64?
                    the_record[:content] = the_record[:content].decode64
                  end
                end
                result << the_record
              end
              # result = raw_result
            end
            #
          else
            raise ArguementError, "You MUST provide a record selection filter as a Hash. "
          end
        else
          raise ArgumentError, "The table specified is unknown - Check your code."
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => the_table, :filter => the_filter, :options => options}})
      end
      result
    end

element_update(the_table=:unspecified, the_filter={}, the_record=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2119
    def element_update(the_table=:unspecified, the_filter={}, the_record=nil)
      result = false
      begin
        unless the_table.is_a?(::Symbol)
          raise ArgumentError, "You MUST provide the table specifier as a Symbol."
        end
        unless the_filter.is_a?(::Hash)
          raise ArgumentError, "You MUST provide a selection filter in the form of a Hash."
        end
        unless the_record.is_a?(::Hash)
          raise ArgumentError, "You MUST provide a record in the form of a Hash."
        end
        if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :text_page, :element_binary, :binary_page, :element_array, :element_hash].include?(the_table)
          # Review : shim to eliminate UTF-8 encoding errors
          begin
            @connector[(the_table)].filter(the_filter).update(the_record)
          rescue Exception
            if the_table == :text_page
              the_record[:content] = the_record[:content].encode64
            end
            @connector[(the_table)].filter(the_filter).update(the_record)
          end
          result = true
        else
          raise ArgumentError, "The table specified is unknown - Check your code."
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => the_table, :filter => the_filter, :record => the_record}})
      end
      result
    end

empty_trash() click to toggle source

    # File lib/gxg/gxg_database.rb, line 2986
    def empty_trash()
      result = false
      begin
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              scrub_list = []
              @connector[:trash].filter({}).each do |entry|
                the_table = entry[:element_table].to_sym
                the_dbid = entry[:elementid]
                if @connector[:element_locks].filter({:type => "write", :element_table => the_table.to_s, :elementid => the_dbid}).count == 0
                  # delete full manifest
                  manifest = self.element_manifest(the_table, the_dbid, true)
                  manifest.each do |item|
                    @connector[:permissions].filter({:element_table => (item[:table].to_s), :elementid => (item[:dbid])}).delete
                    @connector[(item[:table])].filter({:dbid => item[:dbid]}).delete
                  end
                  scrub_list << entry[:dbid]
                end
              end
              scrub_list.each do |entry|
                @connector[:trash].filter({:dbid => entry}).delete
              end
              if @connector[:trash].filter({}).count == 0
                result = true
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error})
      end
      result
    end

enforce_permission_policy(event={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3679
    def enforce_permission_policy(event={})
      # Event format: enforce_permission_policy({:action => :extend, :credential => nil, :source => nil, :destination => nil})
      # Rule format: {:event => :create, :credential => :any, :action => {:extend_permissions => nil}}
      the_policy = self.permission_policy()
      result = false
      begin
        if self.alive?()
          if self.open?()
            actions = []
            the_policy.each do |rule|
              if event[:action] == rule[:event]
                if rule[:credential] == event[:credential] || rule[:credential] == :any
                  actions << rule[:action]
                end
              end
            end
            actions.each do |action|
              case action.keys[0]
              when :extend_permissions
                if action[:use_permission].is_a?(::Hash)
                  use_permission = action[:use_permission]
                else
                  use_permission = nil
                end
                credential = event[:credential]
                unless ::GxG::valid_uuid?(credential)
                  raise ArgumentError, "You MUST provide a valid UUID as :credential."
                end
                new_credential = action[:extend_permissions]
                source = event[:source]
                unless source.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
                  raise ArgumentError, "You MUST provide a persisted object as :source."
                end
                unless source.db_address
                  raise Exception, "You provided a Deactivated object as :source."
                end
                destination = event[:destination]
                unless destination.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
                  raise ArgumentError, "You MUST provide a persisted object as :source."
                end
                unless destination.db_address
                  raise Exception, "You provided a Deactivated object as :destination."
                end
                #
                permissions = self.element_permissions(source.db_address()[:table],source.db_address()[:dbid])
                permission_db = []
                if [:persisted_array, :persisted_hash].include?(destination.db_address()[:table])
                  search_db = [{:table => destination.db_address()[:table], :dbid => destination.db_address()[:dbid]}]
                  permission_db << {:table => destination.db_address()[:table], :dbid => destination.db_address()[:dbid]}
                  while search_db.size > 0 do
                    entry = search_db.shift
                    self.element_manifest(entry[:table],entry[:dbid],false).each do |item|
                      if [:persisted_array, :persisted_hash].include?(item[:table])
                        search_db << item
                        permission_db << item
                      end
                    end
                  end
                  permission_db.each do |the_reference|
                    permissions.each do |record|
                      self.assign_element_permission(the_reference[:table],the_reference[:dbid], credential, record[:permissions])
                      if use_permission
                        self.assign_element_permission(the_reference[:table],the_reference[:dbid], new_credential, use_permission)
                      else
                        self.assign_element_permission(the_reference[:table],the_reference[:dbid], new_credential, record[:permissions])
                      end
                    end
                  end
                  # destination.search do |the_value, the_selector, the_container|
                  #   if [:persisted_array, :persisted_hash].include?(the_value.db_address()[:table])
                  #     permission_db << {:table => the_value.db_address()[:table], :dbid => the_value.db_address()[:dbid]}
                  #   end
                  # end
                  #
                end
                # permission_db << {:table => destination.db_address()[:table], :dbid => destination.db_address()[:dbid]}
                # if destination.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
                #   destination.search do |the_value, the_selector, the_container|
                #     permission_db << {:table => the_value.db_address()[:table], :dbid => the_value.db_address()[:dbid]}
                #   end
                # end
                # permission_db.each do |item|
                #   self.element_manifest(item[:table],item[:dbid],false).each do |entry|
                #     permissions.each do |record|
                #       self.assign_element_permission(entry[:table],entry[:dbid], credential, record[:permissions])
                #       if use_permission
                #         self.assign_element_permission(entry[:table],entry[:dbid], new_credential, use_permission)
                #       else
                #         self.assign_element_permission(entry[:table],entry[:dbid], new_credential, record[:permissions])
                #       end
                #     end
                #   end
                # end
                #
              end
            end
            result = true
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:event => event}})
      end
      result
    end

extend_element_permissions(source_table=:unspecified, source_dbid=0, dest_table=:unspecified, dest_dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1565
    def extend_element_permissions(source_table=:unspecified, source_dbid=0, dest_table=:unspecified, dest_dbid=0)
      permissions = self.element_permissions(source_table, source_dbid)
      permissions.each do |entry|
        if [:persisted_array, :persisted_hash].include?(dest_table)
          self.assign_element_permission(dest_table, dest_dbid, entry[:credential], entry[:permissions])
        end
      end
    end

format_create(format_record=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3244
    def format_create(format_record=nil)
      result = false
      begin
        if self.alive?()
          if self.open?
            unless self.db_permissions()[:write]
              raise Exception, "Unable to write to database"
            end
            if format_record.is_a?(::Hash)
              unless ::GxG::valid_uuid?(format_record[:uuid])
                raise Exception, "Invalid UUID passed for the format"
              end
              unless format_record[:type].is_any?([::String, ::Symbol])
                raise Exception, "You must pass the format_record[:type] as a String or Symbol"
              end
              unless format_record[:ufs].is_any?([::String, ::Symbol])
                raise Exception, "You must pass the format_record[:ufs] as a String or Symbol"
              end
              unless format_record[:title].is_a?(::String)
                raise Exception, "You must pass the format_record[:title] as a String"
              end
              unless format_record[:version].is_a?(::Float)
                raise Exception, "You must pass the format_record[:version] as a Float"
              end
              unless format_record[:mime_types].is_any?(::String, ::Array)
                raise Exception, "You must pass the format_record[:mime_types] as a String"
              end
              unless format_record[:content].is_a?(::Hash)
                raise Exception, "You must pass the format_record[:content] as a Hash"
              end
              unless self.persistable?(format_record[:content])
                raise Exception, "You must pass the format_record[:content] as a Hash of persistable elements"
              end
              if (@connector[:settings].filter({:uuid => format_record[:uuid].to_s}).count == 0 and @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).count == 0 and @connector[:element_text].filter({:uuid => format_record[:uuid].to_s}).count == 0)
                new_record = {:uuid => (format_record[:uuid].to_s)}
                new_record[:type] = format_record[:type].to_s
                new_record[:ufs] = format_record[:ufs].to_s
                new_record[:title] = format_record[:title].to_s[0..256]
                new_record[:version] = format_record[:version]
                if format_record[:mime_types].is_a?(::Array)
                  the_mimes = format_record[:mime_types].join(",").to_s[0..4096]
                else
                  the_mimes = format_record[:mime_types].to_s[0..4096]
                end
                new_record[:mime_types] = the_mimes
                content = format_record[:content].gxg_export.to_json.encode64
                new_dbid = @connector[:formats].insert(new_record)
                if content.size > 0
                  ::GxG::apportioned_ranges(content.size, 4096).each_with_index do |portion, ordinal|
                    @connector[:text_page].insert({:parent_uuid => (new_record[:uuid].to_s), :ordinal => (ordinal), :length => (content[(portion)].size), :content => (content[(portion)])})
                  end
                end
                if new_dbid
                  result = true
                end
              else
                raise Exception, "That format UUID is already in use, please generate another"
              end
              #
            else
              raise ArgumentError, "You must supply a valid format record as a Hash"
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:format_record => (format_record)}})
      end
      result
    end

format_destroy(search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3452
    def format_destroy(search_options={})
      result = false
      begin
        if self.alive?()
          if self.open?
            unless self.db_permissions()[:write]
              raise Exception, "Unable to write to database"
            end
            format_stub = self.format_list(search_options).first
            if format_stub
              @connector[:formats].filter({:uuid => (format_stub[:uuid].to_s)}).delete
              if @connector[:text_page].filter({:parent_uuid => (format_stub[:uuid].to_s)}).count > 0
                @connector[:text_page].filter({:parent_uuid => (format_stub[:uuid].to_s)}).delete
              end
              result = true
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
      end
      result
    end

format_list(search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3112
    def format_list(search_options={})
      result = []
      begin
        if self.alive?
          if self.open?
            unless search_options.is_a?(::Hash)
              raise ArgumentError, "You must specify search options as a Hash"
            end
            the_filter = {}
            if search_options[:uuid]
              the_filter[:uuid] = search_options[:uuid].to_s
            end
            if search_options[:type]
              the_filter[:type] = search_options[:type].to_s
            end
            if search_options[:ufs]
              the_filter[:ufs] = search_options[:ufs].to_s[0..4096]
            end
            if search_options[:title]
              the_filter[:title] = search_options[:title].to_s[0..256]
            end
            if search_options[:version].is_a?(::Float)
              the_filter[:version] = search_options[:version]
            end
            mime_type = search_options[:mime_type].to_s
            if mime_type.size > 0
              @connector[:formats].filter(the_filter).where(::Sequel.like(:mime_types, ("%" + mime_type + "%"))).order(::Sequel[:version].desc).each do |entry|
                result << {:uuid => entry[:uuid].to_sym, :type => entry[:type].to_sym, :ufs => entry[:ufs].to_sym, :title => entry[:title], :version => entry[:version]}
              end
            else
              @connector[:formats].filter(the_filter).order(::Sequel[:version].desc).each do |entry|
                result << {:uuid => entry[:uuid].to_sym, :type => entry[:type].to_sym, :ufs => entry[:ufs].to_sym, :title => entry[:title], :version => entry[:version]}
              end
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
      end
      result
    end

format_load(search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3158
    def format_load(search_options={})
      result = nil
      begin
        if self.alive?()
          if self.open?
            format_stub = self.format_list(search_options).first
            if format_stub
              format_record = @connector[:formats].filter({:uuid => (format_stub[:uuid].to_s)}).first
              if format_record
                content = ""
                @connector[:text_page].filter({:parent_uuid => (format_stub[:uuid].to_s)}).order(:ordinal).each do |entry|
                  content << entry[:content]
                end
                format_record.delete(:dbid)
                format_record[:ufs] = format_stub[:ufs]
                format_record[:type] = format_stub[:type]
                if content.size > 0
                  if content.base64?
                    content = content.decode64
                  end
                  if content.json?
                    content = ::JSON::parse(content.to_s, {:symbolize_names => true})
                  end
                  if content[:type]
                    content = ::Hash.gxg_import(content)
                  end
                  format_record[:content] = content
                else
                  format_record[:content] = nil
                end
                #
                if format_record[:mime_types].size > 0
                  if format_record[:mime_types].include?(",")
                    format_record[:mime_types] = format_record[:mime_types].split(",")
                  else
                    format_record[:mime_types] = [(format_record[:mime_types])]
                  end
                end
                #
                result = format_record
              end
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
      end
      result
    end

format_template(type=:structure) click to toggle source

Format handing methods

    # File lib/gxg/gxg_database.rb, line 3078
    def format_template(type=:structure)
      result = nil
      begin
        if self.alive?
          if self.open?
            unless type.is_any?(::String, ::Symbol)
              raise ArgumentError, "You must supply a type as a String or Symbol:  :structure or :binary"
            end
            the_uuid = ::GxG::uuid_generate()
            while (@connector[:formats].filter({:uuid => (the_uuid)}).count > 0 or @connector[:element_text].filter({:uuid => (the_uuid)}).count > 0)
              the_uuid = ::GxG::uuid_generate()
            end
            result = {:uuid => (the_uuid.to_sym), :type => (type.to_s), :ufs => "unspecified", :title => "", :version => 0.0, :mime_types => [], :content => nil}
            case type
            when :structure
              result[:content] = {}
            when :binary
              result[:content] = {:sample_size => 0, :recognition => "", :import => "", :export => ""}
            else
              raise Exception, "Invalid format type specified: #{type.inspect}.  Use :structure or :binary"
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        result = nil
        log_error({:error => the_error, :parameters => {:type => (type)}})
      end
      result
    end

format_update(format_record=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3318
    def format_update(format_record=nil)
      format_record = format_record.clone
      result = false
      begin
        if self.alive?()
          if self.open?
            unless self.db_permissions()[:write]
              raise Exception, "Unable to write to database"
            end
            if format_record.is_a?(::Hash)
              unless ::GxG::valid_uuid?(format_record[:uuid])
                raise Exception, "Invalid UUID passed for the format"
              end
              record = @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).first
              if record
                format_update = {}
                record.keys.each do |the_key|
                  if [:type, :ufs, :title, :version, :mime_types].include?(the_key)
                    case the_key
                    when :type
                      unless format_record[:type].is_any?(::String, ::Symbol)
                        raise Exception, "You must pass the format_record[:type] as a String or Symbol"
                      end
                    when :ufs
                      unless format_record[:ufs].is_any?(::String, ::Symbol)
                        raise Exception, "You must pass the format_record[:ufs] as a String or Symbol"
                      end
                    when :title
                      unless format_record[:title].is_a?(::String)
                        raise Exception, "You must pass the format_record[:title] as a String"
                      end
                    when :version
                      unless format_record[:version].is_a?(::Float)
                        raise Exception, "You must pass the format_record[:version] as a Float"
                      end
                    when :mime_types
                      unless format_record[:mime_types].is_any?(::String, ::Array)
                        raise Exception, "You must pass the format_record[:mime_types] as a String"
                      end
                    end
                    #
                    if the_key == :mime_types
                      if format_record[:mime_types].is_a?(::Array)
                        the_mimes = format_record[:mime_types].join(",").to_s[0..4096]
                      else
                        the_mimes = format_record[:mime_types].to_s[0..4096]
                      end
                      format_record[:mime_types] = the_mimes
                    end
                    #
                    if format_record[(the_key)] != record[(the_key)]
                      format_update[(the_key)] = format_record[(the_key)]
                    end
                  end
                end
                if format_update.keys.size > 0
                  # FIXME: :type and :ufs are being passed as a Symbols, but DB requires them to be a strings:
                  if format_update[:type].is_a?(::Symbol)
                    format_update[:type] = format_update[:type].to_s
                  end
                  if format_update[:ufs].is_a?(::Symbol)
                    format_update[:ufs] = format_update[:ufs].to_s
                  end
                  @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).update(format_update)
                end
                if format_record[:content].is_a?(::Hash)
                  unless self.persistable?(format_record[:content])
                    raise Exception, "You must pass the format_record[:content] as a Hash of persistable elements"
                  end
                  old_segments = []
                  content = format_record[:content].gxg_export.to_json.encode64
                  @connector[:text_page].select(:dbid).where({:parent_uuid => format_record[:uuid].to_s}).order(:ordinal).each do |entry|
                    old_segments << entry[:dbid]
                  end
                  if content.size == 0
                    if old_segments.size > 0
                      @connector[:text_page].filter({:parent_uuid => format_record[:uuid].to_s}).delete
                    end
                  else
                    new_segments = ::GxG::apportioned_ranges(content.size, 4096)
                    if old_segments.size > new_segments.size
                      the_count = old_segments.size
                    else
                      the_count = new_segments.size
                    end
                    manifest = []
                    (0..(the_count - 1)).each do |the_ordinal|
                      if new_segments[(the_ordinal)] and old_segments[(the_ordinal)]
                        #overwrite with new segment range
                        manifest << {:operation => :overwrite, :dbid => (old_segments[(the_ordinal)]), :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                      else
                        if new_segments[(the_ordinal)]
                          # create new segment at this ordinal
                          manifest << {:operation => :create, :ordinal => (the_ordinal), :portion => (new_segments[(the_ordinal)])}
                        else
                          # delete old segment
                          manifest << {:operation => :delete, :dbid => (old_segments[(the_ordinal)])}
                        end
                      end
                    end
                    manifest.each do |action|
                      case action[:operation]
                      when :overwrite
                        @connector[:text_page].filter({:dbid => (action[:dbid])}).update({:ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
                      when :create
                        @connector[:text_page].insert({:parent_uuid => (record[:uuid]), :ordinal => (action[:ordinal]), :length => (content[(action[:portion])].size), :content => (content[(action[:portion])])})
                      when :delete
                        @connector[:text_page].filter({:dbid => (action[:dbid])}).delete
                      end
                    end
                    @connector[:formats].filter({:uuid => format_record[:uuid].to_s}).update({:version => (format_record[:version].to_f + 0.00001)})
                    #
                  end
                end
                #
                result = true
              else
                result = self.format_create(format_record)
              end
            else
              raise ArgumentError, "You must supply a valid format record as a Hash"
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:format_record => (format_record)}})
      end
      result
    end

group_create(options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1177
    def group_create(options={})
      result = nil
      if @authority
        result = @authority.group_create(options)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                unless options.is_a?(::Hash)
                  raise ArgumentError, "Options must be passed as a Hash"
                end
                #
                title = (options[:title] || "Untitled Group")
                seo = (options[:seo] || title.downcase.gsub(" ", "_"))
                if options[:default_role].is_a?(::Hash)
                  role_title = (options[:default_role][:title] || (title + " Members"))
                  role_seo = (options[:default_role][:seo] || role_title.downcase.gsub(" ", "_"))
                else
                  role_title = (title + " Members")
                  role_seo = role_title.downcase.gsub(" ", "_")
                end
                #
                the_uuid = ::GxG::uuid_generate()
                while (@connector[:groups].filter({:uuid => (the_uuid.to_s)}).count > 0)
                  the_uuid = ::GxG::uuid_generate()
                end
                @connector[:groups].insert({:uuid => (the_uuid.to_s), :title => (title.to_s), :seo => (seo.to_s)})
                role_uuid = self.role_create(the_uuid, role_title, role_seo)
                if role_uuid
                  @connector[:groups].filter({:uuid => (the_uuid.to_s)}).update({:default_role => (role_uuid.to_s)})
                  result = {:group => the_uuid.to_sym, :default_role => role_uuid.to_sym}
                else
                  @connector[:groups].filter({:uuid => (the_uuid.to_s)}).delete
                  raise Exception, "Could not create default role for group.  Aborting."
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:options => (options)}})
              end
            end
          end
        end
      end
      result
    end

group_credential(details={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1308
    def group_credential(details={})
      result = nil
      if @authority
        result = @authority.group_credential(details)
      else
        begin
          unless self.alive?
            raise Exception, "Database inactive"
          end
          unless self.open?
            raise Exception, "Database not available"
          end
          unless details.is_any?(::Hash, ::GxG::Database::PersistedHash)
            raise ArgumentError, "group and role specifiers must be provided within a Hash or PeristedHash"
          end
          #
          if details[:group].is_a?(::String)
            group_record = self.group_fetch({:title => details[:group]})
            if group_record
              role_title_specified = (details[:role] || (group_record[:title].to_s + " Members")).to_s
              group_roles = self.group_roles(group_record[:uuid].to_sym)
              group_roles.each do |role_profile|
                if role_profile[:title] == role_title_specified
                  result = role_profile[:uuid].to_s.to_sym
                  break
                end
              end
            end
          end
          #
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:details => (details)}})
        end
      end
      result
    end

group_delete(group_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1275
    def group_delete(group_uuid=nil)
      result = false
      if @authority
        result = @authority.group_delete(group_uuid)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(group_uuid)
                  record = @connector[:groups].filter({:uuid => (group_uuid.to_s)}).first
                  if record
                    @connector[:groups].filter({:uuid => (group_uuid.to_s)}).update({:default_role => "__role_deleted__"})
                    role_list = @connector[:roles].select(:uuid).where({:group_uuid => (group_uuid.to_s)})
                    role_list.each do |role|
                      self.role_destroy(role[:uuid].to_sym)
                    end
                    @connector[:groups].filter({:uuid => (group_uuid.to_s)}).delete
                  end
                  result = true
                else
                  raise ArgumentError, "You must specify a valid group UUID (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:group_uuid => (group_uuid)}})
              end
            end
          end
        end
      end
      result
    end

group_exist?(the_specifier=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1090
    def group_exist?(the_specifier=nil)
      result = nil
      if @authority
        result = @authority.group_exist?(the_specifier)
      else
        if self.alive?
          if self.open?
            if GxG::valid_uuid?(the_specifier)
              # uuid search
              the_filter = {:uuid => the_specifier.to_s}
            else
              # title search
              the_filter = {:title => the_specifier.to_s}
            end
            if @connector[:groups].filter(the_filter).count > 0
              result = true
            end
          end
        end
      end
      result
    end

group_fetch(search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1113
    def group_fetch(search_options={})
      result = nil
      if @authority
        result = @authority.group_fetch(search_options)
      else
        if self.alive?
          if self.open?
            begin
              record = @connector[:groups].filter(search_options).first
              if record
                result = record
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:options => (search_options)}})
            end
          end
        end
      end
      result
    end

group_manifest() click to toggle source

    # File lib/gxg/gxg_database.rb, line 1134
    def group_manifest()
      result = {}
      if @authority
        result = @authority.group_manifest()
      else
        if self.alive?
          if self.open?
            # intitialize result tree
            @connector[:groups].filter({:parent_uuid => ""}).each do |the_group|
              # dbid, uuid, parent_uuid, default_role, seo, title, version
              result[(the_group[:uuid].to_s.to_sym)] = {:title => the_group[:title], :seo => the_group[:seo], :version => the_group[:version], :groups => {}, :roles => {}}
            end
            # flesh out tree
            build_list = result.keys
            while build_list.size > 0 do
              group_uuid = build_list.shift
              if group_uuid
                the_group = nil
                result.search do |item, selector, container|
                  if selector == group_uuid
                    the_group = item
                    break
                  end
                end
                if the_group
                  @connector[:groups].filter({:parent_uuid => group_uuid.to_s}).each do |subgroup|
                    the_group[:groups][(subgroup[:uuid].to_s.to_sym)] = {:title => subgroup[:title], :seo => subgroup[:seo], :version => subgroup[:version], :groups => {}, :roles => {}}
                    build_list << subgroup[:uuid].to_s.to_sym
                  end
                  @connector[:roles].filter({:group_uuid => group_uuid.to_s}).each do |the_role|
                    the_group[:roles][(the_role[:uuid].to_s.to_sym)] = {:title => the_role[:title], :seo => the_role[:seo], :version => the_role[:version]}
                  end
                end
                #
              end
            end
            #
          end
        end
      end
      result
    end

group_roles(group_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1076
    def group_roles(group_uuid=nil)
      result = []
      if @authority
          result = @authority.group_roles(group_uuid)
      else
          if ::GxG::valid_uuid?(group_uuid)
              @connector[:roles].filter(:group_uuid => group_uuid).each do |the_entry|
                  result << {:role => (the_entry[:title]), :uuid => (the_entry[:uuid])}
              end
          end
      end
      result
    end

group_update(group_uuid=nil, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1223
    def group_update(group_uuid=nil, options={})
      result = false
      if @authority
        result = @authority.group_update(group_uuid, options)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(group_uuid)
                  unless options.is_a?(::Hash)
                    raise ArgumentError, "Options must be passed as a Hash"
                  end
                  title = options[:title]
                  seo = options[:seo]
                  if title.is_a?(::String) or seo.is_a?(::String) or ::GxG::valid_uuid?(options[:default_role]) or ::GxG::valid_uuid?(options[:parent_uuid])
                    the_update = {}
                    if title
                      the_update[:title] = title.to_s[0..255]
                    end
                    if seo
                      the_update[:seo] = seo.to_s[0..255]
                    end
                    if options[:default_role]
                      the_update[:default_role] = options[:default_role].to_s[0..36]
                    end
                    if options[:parent_uuid]
                      the_update[:parent_uuid] = options[:parent_uuid].to_s[0..36]
                    end
                    record = @connector[:groups].select(:version).where({:uuid => (group_uuid.to_s)}).first
                    if record
                      the_update[:version] = (record[:version] + 0.0001)
                    else
                      log_warn("Could not update version for group #{group_uuid}")
                    end
                    @connector[:groups].filter({:uuid => (group_uuid.to_s)}).update(the_update)
                    # Review : BE SURE to also update the title of the default "<group-title> Members" role.
                    result = true
                  end
                else
                  raise ArgumentError, "You must specify a valid group UUID (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:group_uuid => (group_uuid), :options => (options)}})
              end
            end
          end
        end
      end
      result
    end

import(credential=nil, the_record=nil) click to toggle source

Import methods (deprecated in favor of sychronize_records)

    # File lib/gxg/gxg_database.rb, line 3788
    def import(credential=nil, the_record=nil)
      #
      result = nil
      if self.alive?
        if self.open?
          if self.db_permissions()[:write]
            cleanup_manifest = []
            begin
              unless ::GxG::valid_uuid?(credential)
                raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
              end
              if the_record.is_a?(::Hash)
                case the_record[:type]
                when :element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime
                  new_dbid = @connector[(the_record[:type])].insert({:version => (the_record[:version]), :content => (the_record[:content])})
                  self.assign_element_permission((the_record[:type]), (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                  result = {:table => (the_record[:table]), :dbid => (new_dbid)}
                when :element_text
                  the_uuid = ::GxG::uuid_generate()
                  while (@connector[:element_text].filter({:uuid => the_uuid}).count > 0)
                    the_uuid = ::GxG::uuid_generate()
                  end
                  new_dbid = @connector[:element_text].insert({:uuid => (the_uuid), :version => (the_record[:version]), :length => (the_record[:content].size)})
                  cleanup_manifest << {:table => :element_text, :dbid => (new_dbid)}
                  ::GxG::apportioned_ranges(the_record[:content].size, 4096).each_with_index do |the_range,the_ordinal|
                    @connector[:text_page].insert({:parent_uuid => (the_uuid), :ordinal => (the_ordinal), :length => (the_record[:content][(the_range)].size), :content => (the_record[:content][(the_range)])})
                  end
                  self.assign_element_permission((the_record[:type]), (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                  result = {:table => :element_text, :dbid => (new_dbid)}
                when :element_binary
                  the_uuid = ::GxG::uuid_generate()
                  while (@connector[:element_binary].filter({:uuid => the_uuid}).count > 0)
                    the_uuid = ::GxG::uuid_generate()
                  end
                  new_dbid = @connector[:element_binary].insert({:uuid => (the_uuid), :version => (the_record[:version]), :length => (the_record[:content].size)})
                  cleanup_manifest << {:table => :element_binary, :dbid => (new_dbid)}
                  ::GxG::apportioned_ranges(the_record[:content].size, 65536).each_with_index do |the_range,the_ordinal|
                    @connector[:binary_page].insert({:parent_uuid => (the_uuid), :ordinal => (the_ordinal), :length => (the_record[:content].data()[(the_range)].size), :content => (the_record[:content].data()[(the_range)])})
                  end
                  self.assign_element_permission((the_record[:type]), (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                  result = {:table => :element_binary, :dbid => (new_dbid)}
                when :element_array
                  # {:type => :element_array, :uuid => @uuid, :title => @title, :version => @version, :content => []}
                  existing = @connector[(the_record[:type])].select(:dbid, :version).where({:uuid => the_record[:uuid].to_s}).first
                  if existing
                    if the_record[:version] > existing[:version]
                      unless self.element_destroy(credential, :element_array, existing[:dbid])
                        raise Exception, "Error replacing array element - Aborting"
                      end
                      existing = nil
                    else
                      log_warn("Import record is older than existing one - Skipping")
                      new_dbid = existing[:dbid]
                    end
                  end
                  unless existing
                    new_dbid = @connector[(the_record[:type])].insert({:uuid => (the_record[:uuid].to_s), :title => (the_record[:title]), :version => (the_record[:version])})
                    cleanup_manifest << {:table => :element_array, :dbid => (new_dbid)}
                    self.assign_element_permission(:element_array, (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                    the_record[:content].each_with_index do |element, indexer|
                      new_address = self.import(credential, (element))
                      if new_address
                        cleanup_manifest << new_address
                        @connector[:array_links].insert({:parent_uuid => (the_record[:uuid].to_s), :ordinal => (indexer), :element => (::GxG::Database::Database::element_table_index(new_address[:table])), :elementid => new_address[:dbid]})
                      else
                        raise Exception, "Error processing the import record - Aborting"
                      end
                    end
                  end
                  result = {:table => :element_array, :dbid => (new_dbid)}
                when :element_hash
                  # {:type => :element_hash, :uuid => @uuid, :title => @title, :version => @version, :format => @format, :content => {}}
                  existing = @connector[(the_record[:type])].select(:dbid, :version).where({:uuid => the_record[:uuid].to_s}).first
                  if existing
                    if the_record[:version] > existing[:version]
                      unless self.element_destroy(credential, :element_hash, existing[:dbid])
                        raise Exception, "Error replacing hash element - Aborting"
                      end
                      existing = nil
                    else
                      log_warn("Import record is older than existing one - Skipping")
                      new_dbid = existing[:dbid]
                    end
                  end
                  unless existing
                    new_dbid = @connector[(the_record[:type])].insert({:uuid => (the_record[:uuid].to_s), :title => (the_record[:title]), :version => (the_record[:version]), :format => (the_record[:format].to_s)})
                    cleanup_manifest << {:table => :element_hash, :dbid => (new_dbid)}
                    self.assign_element_permission(:element_hash, (new_dbid), credential, {:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                    the_record[:content].keys.each_with_index do |the_key, indexer|
                      new_address = self.import(credential, (the_record[:content][(the_key)]))
                      if new_address
                        cleanup_manifest << new_address
                        @connector[:hash_links].insert({:parent_uuid => (the_record[:uuid].to_s), :property => (the_key.to_s), :ordinal => (indexer), :element => (::GxG::Database::Database::element_table_index(new_address[:table])), :elementid => new_address[:dbid]})
                      else
                        raise Exception, "Error processing the import record - Aborting"
                      end
                    end
                  end
                  result = {:table => :element_hash, :dbid => (new_dbid)}
                else
                  raise ArgumentError, "Invalid table specified"
                end
              else
                raise ArgumentError, "You must supply an import record as a Hash"
              end
            rescue Exception => the_error
              # clean up
              cleanup_manifest.each do |entry|
                self.element_destroy(credential, entry[:table], entry[:dbid])
              end
              log_error({:error => the_error, :parameters => {:the_record => (the_record)}})
            end
          else
            log_warn("Cannot import records into a read-only Database - Aborting")
          end
        end
      end
      result
    end

initialize_clone() click to toggle source

Comm objects cannot be cloned - returns nil

    # File lib/gxg/gxg_database.rb, line 5102
    def initialize_clone
      nil
    end

Also aliased as: initialize_dup, dup
initialize_dup()
Alias for: initialize_clone
inspect() click to toggle source

    # File lib/gxg/gxg_database.rb, line 431
    def inspect()
      "<Database: #{this().to_uri()}>"
    end

iterative_persist(old_root=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2558
    def iterative_persist(old_root=nil, credential=nil)
      # New PersistedArray, or PersistedHash interface:
      # mount element: {:database => <database>, :uuid => <uuid>, :credential => <uuid>, :delegate => nil/<uuid>, :parent => nil/<an-object>}
      # create element: {:database => <database>, :credential => <uuid>, :delegate => nil/<uuid>, :parent => nil/<an-object>}
      #
      result = nil
      begin
        # db open?
        # write permissions on db?
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You MUST provide a valid UUID as a credential."
        end
        unless old_root.is_any?(::Array, ::Hash)
          raise ArgumentError, "You MUST provide either an Array or a Hash."
        end
        unless self.persistable?(old_root)
          raise ArgumentError, "The object you are attempting to persist contains a non-persistable item."
        end
        if old_root.is_a?(::Array)
          original_partner = ::GxG::Database::PersistedArray.new({:database => self, :credential => credential})
          original_partner.get_reservation()
          self.enforce_permission_policy({:action => :extend, :credential => credential, :source => original_partner, :destination => original_partner})
          #
        end
        if old_root.is_a?(::Hash)
          original_partner = ::GxG::Database::PersistedHash.new({:database => self, :credential => credential})
          original_partner.get_reservation()
          self.enforce_permission_policy({:action => :extend, :credential => credential, :source => original_partner, :destination => original_partner})
        end
        if old_root.is_any?(::GxG::Database::PersistedArray, ::GxG::Database::PersistedHash)
          # TODO: support subsuming already persisted objects.
        end
        paring_data = [{:parent => nil, :parent_selector => nil, :object => old_root, :partner => original_partner}]
        children_of = Proc.new do |the_parent=nil|
          list = []
          paring_data.each do |node|
            if node[:parent].object_id == the_parent.object_id
              list << node
            end
          end
          list
        end
        #
        parent_of = Proc.new do |the_parent=nil|
          output = nil
          paring_data.each do |entry|
            if entry[:object].object_id == the_parent.object_id
              output = entry
            end
          end
          output
        end
        find_partner = Proc.new do |the_object|
          found_partner = nil
          paring_data.each do |the_record|
            if the_record.is_a?(::Hash)
              if the_record[:object].object_id == the_object.object_id
                found_partner = the_record[:partner]
                break
              end
            end
          end
          found_partner
        end
        # build paring data:
        delegate_permission = nil
        old_root.search do |the_value, the_selector, the_container|
          if the_value.is_a?(::Array)
            paring_data << {:parent => the_container, :parent_selector => the_selector, :object => the_value, :partner => ::GxG::Database::PersistedArray.new({:database => self, :credential => credential})}
          else
            if the_value.is_a?(::Hash)
              paring_data << {:parent => the_container, :parent_selector => the_selector, :object => the_value, :partner => ::GxG::Database::PersistedHash.new({:database => self, :credential => credential})}
            else
              paring_data << {:parent => the_container, :parent_selector => the_selector, :object => the_value, :partner => the_value}
            end
          end
        end
        # Assign objects to structure in order by parent / parent_selector
        link_db = [(paring_data[0])]
        while link_db.size > 0
          entry = link_db.shift
          if entry.is_a?(::Hash)
            if entry[:object].is_any?(::Array, ::Hash)
              # get children and assign
              children = children_of.call(entry[:object])
              children.each do |child|
                entry[:partner][(child[:parent_selector])] = child[:partner]
                if child[:partner].is_any?(::GxG::Database::PersistedArray, ::GxG::Database::PersistedHash)
                  link_db << child
                end
              end
            end
          end
        end
        result = original_partner
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:object => old_root, :credential => credential}})
      end
      result
    end

new_structure_from_format(credential=nil, search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 3212
    def new_structure_from_format(credential=nil, search_options={})
      result = nil
      begin
        if self.alive?()
          if self.open?
            unless ::GxG::valid_uuid?(credential)
              raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
            end
            format = self.format_load(search_options)
            if format
              # TODO: add support for :binary formats.
              unless format[:type] == :structure
                raise Exception, "Only formats of type :structure are supported"
              end
              result = self.try_persist(format[:content], credential)
              if result.is_a?(::GxG::Database::PersistedHash)
                result.set_format(format[:uuid].to_sym)
                @connector[:element_hash].filter({:uuid => result.uuid.to_s}).update({:format => format[:uuid].to_s})
              end
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:search_options => (search_options)}})
      end
      result
    end

open?() click to toggle source

    # File lib/gxg/gxg_database.rb, line 403
    def open?()
      begin
        @connector.synchronize do |connection|
          @active = @connector.valid_connection?(connection)
        end
      rescue => the_error
        @active = false
        log_error({:error => the_error, :parameters => nil})
      end
      @active
    end

permission_policy() click to toggle source

Permission policy support:

    # File lib/gxg/gxg_database.rb, line 3611
    def permission_policy()
      result = nil
      begin
        if self.alive?()
          if self.open?()
            if @authority
              result = @authority.permission_policy()
            else
              result = @permission_policy
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {}})
      end
      result
    end

permission_policy_load() click to toggle source

    # File lib/gxg/gxg_database.rb, line 3633
    def permission_policy_load()
      result = false
      begin
        if self.alive?()
          if self.open?()
            if @authority
              result = @authority.permission_policy_load()
            else
              @permission_policy = (self[:permission_policy] || [])
              result = true
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {}})
      end
      result
    end

permission_policy_save() click to toggle source

    # File lib/gxg/gxg_database.rb, line 3656
    def permission_policy_save()
      result = false
      begin
        if self.alive?()
          if self.open?()
            if @authority
              result = @authority.permission_policy_save()
            else
              self[:permission_policy] = (@permission_policy || [])
              result = true
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {}})
      end
      result
    end

persistable?(the_object) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2536
    def persistable?(the_object)
      result = true
      unless the_object.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
        if the_object.is_any?(::Hash, ::Array)
          the_object.search do |item, selector, container|
            if result
              if ::GxG::Database::Database::element_table_for_instance(item) == :unspecified
                result = false
                break
              end
            end
            nil
          end
        else
          if ::GxG::Database::Database::element_table_for_instance(the_object) == :unspecified
            result = false
          end
        end
      end
      result
    end

release_element_locks(reservation_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2878
    def release_element_locks(reservation_uuid=nil)
      result = false
      begin
        if self.alive?
          if self.open?
            unless ::GxG::valid_uuid?(reservation_uuid)
              raise ArgumentError, "You must supply a valid reservation UUID (as a String or Symbol) to release locks"
            end
            if self.db_permissions()[:write]
              @connector[:element_locks].filter({:reservation => reservation_uuid.to_s}).delete
            end
            # on read-only db, no reservation was made so mission accomplished
            result = true
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:reservation => (reservation_uuid)}})
      end
      result
    end

remove_element_permissions(table=:unspecified, dbid=0, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1574
    def remove_element_permissions(table=:unspecified, dbid=0, options={})
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless dbid.is_a?(::Integer)
          raise ArgumentError, "dbid must be specified with a Integer"
        end
        unless options.is_a?(::Hash)
          raise ArgumentError, "permissions must be specified with a Hash"
        end
        credential = options[:credential]
        if credential
          unless ::GxG::valid_uuid?(credential)
            raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
          end
        end
        if table.is_a?(::Integer)
          table = ::GxG::Database::Database::element_table_by_index(table)
        end
        # Review : change in permission policy
        # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
        if [:element_array, :element_hash].include?(table)
          if credential
            @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)}).delete
          else
            @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid)}).delete
          end
          result = true
        else
          raise ArgumentError, "Invalid table specified"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :options => (options)}})
      end
      result
    end

reservation_add_element(reservation_uuid=nil, table=:unspecified, dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2903
    def reservation_add_element(reservation_uuid=nil, table=:unspecified, dbid=0)
      result = false
      #
      begin
        if self.alive?
          if self.open?
            unless ::GxG::valid_uuid?(reservation_uuid)
              raise ArgumentError, "You must supply a valid reservation UUID (as a String or Symbol) to add an element to the reserve locks"
            end
            record = @connector[:element_locks].select(:type, :reservation, :credential).where({:reservation => reservation_uuid.to_s}).first
            if record
              type = record[:type].to_sym
              credential = record[:credential].to_sym
              manifest = self.element_manifest(table, dbid, false)
              if type == :write
                if self.db_permissions()[:write]
                  #
                  manifest.each do |entry|
                    if @connector[:element_locks].filter({:type => (type.to_s), :reservation => reservation_uuid.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count == 0
                      @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                    end
                  end
                  result = true
                end
              else
                # read
                if self.db_permissions()[:write]
                  #
                  manifest.each do |entry|
                    @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                  end
                  result = true
                end
              end
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:reservation => (reservation_uuid)}})
      end
      #
      result
    end

reservation_remove_element(reservation_uuid=nil, table=:unspecified, dbid=0) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2951
    def reservation_remove_element(reservation_uuid=nil, table=:unspecified, dbid=0)
      result = false
      #
      begin
        if self.alive?
          if self.open?
            unless ::GxG::valid_uuid?(reservation_uuid)
              raise ArgumentError, "You must supply a valid reservation UUID (as a String or Symbol) to remove element from reserve locks"
            end
            record = @connector[:element_locks].select(:reservation).where({:reservation => reservation_uuid.to_s}).first
            if record
              manifest = self.element_manifest(table, dbid, false)
              if self.db_permissions()[:write]
                #
                manifest.each do |entry|
                  if @connector[:element_locks].filter({:reservation => reservation_uuid.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count > 0
                    @connector[:element_locks].filter({:reservation => reservation_uuid.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).delete
                  end
                end
                result = true
              end
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:reservation => (reservation_uuid)}})
      end
      #
      result
    end

reserve_element_locks(credential=nil, manifest=[], type=:read) click to toggle source

Element Write-Lock Handling methods

    # File lib/gxg/gxg_database.rb, line 2816
    def reserve_element_locks(credential=nil, manifest=[], type=:read)
      result = nil
      begin
        if self.alive?
          if self.open?
            unless ::GxG::valid_uuid?(credential)
              raise ArgumentError, "You must supply a valid credential UUID to reserve locks"
            end
            unless manifest.is_a?(::Array)
              raise ArguementError, "You must supply an Array of tables and record ids to reserve for writing"
            end
            unless [:write, :read].include?(type)
              raise ArgumentError, "You must specify a type of reservation: either :write or :read are supported"
            end
            if manifest.size > 0
              reservation_uuid = ::GxG::uuid_generate()
              while @connector[:element_locks].filter({:reservation => (reservation_uuid.to_s)}).count > 0
                reservation_uuid = ::GxG::uuid_generate()
              end
              if type == :write
                if self.db_permissions()[:write]
                  # Write-lock must be unique to the elements
                  manifest.each do |entry|
                    if @connector[:element_locks].filter({:type => (type.to_s), :element_table => entry[:table].to_s, :elementid => entry[:dbid]}).count > 0
                      self.release_element_locks(reservation_uuid)
                      # raise Exception, "A reservation already exists for element #{entry[:table]}:#{entry[:dbid]}"
                      # Note - just silently fail and return Nil - no reservation for you.
                      break
                    else
                      @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                    end
                  end
                  # if write-reservation was made
                  if @connector[:element_locks].filter({:reservation => reservation_uuid.to_s}).count > 0
                    result = reservation_uuid.to_sym
                  end
                end
              else
                # Read-lock reservation - can share elements
                if self.db_permissions()[:write]
                  manifest.each do |entry|
                    @connector[:element_locks].insert({:type => (type.to_s), :reservation => reservation_uuid.to_s, :credential => credential.to_s, :element_table => entry[:table].to_s, :elementid => entry[:dbid]})
                    #
                  end
                end
                # Note - on a read-only db it will act as though it has a read-reservation since no deletions can be made.
                result = reservation_uuid.to_sym
              end
            end
            #
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:credential => (credential), :manifest => (manifest), :type => (type)}})
      end
      result
    end

retrieve_by_address(the_address={}, credential=nil, delegate=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2687
    def retrieve_by_address(the_address={}, credential=nil, delegate=nil)
      result = nil
      begin
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
        end
        if self.alive?
          if self.open?
            address = {}
            if the_address[:database]
              unless the_address[:database] == self
                raise ArgumentError, "Database mismatch.  Call this method on database #{the_address[:database].inspect}"
              end
              address[:database] = the_address[:database]
            else
              address[:database] = self
            end
            unless ((the_address[:table]) and (the_address[:dbid].is_a?(::Integer)))
              raise ArgumentError, "Invalid database address: #{the_address.inspect}"
            end
            if the_address[:table].is_a?(::Integer)
              address[:table] = ::GxG::Database::Database::element_table_by_index(the_address[:table])
            else
              address[:table] = the_address[:table]
            end
            address[:dbid] = the_address[:dbid]
            unless self.element_in_trash?(address[:table], address[:dbid])
              if [:persisted_array, :persisted_hash].include?(address[:table])
                the_permission = address[:database].effective_element_permission(address[:table], address[:dbid], credential)
              else
                the_permission = {:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => true}
              end
              # Review ????
              # puts "Effective Permission: #{the_permission.inspect} for #{address[:table].inspect},#{address[:dbid].inspect}"
              if the_permission[:read] == true
                case address[:table]
                when :element_array
                  record = address[:database].connector()[(address[:table].to_s.to_sym)].select(:uuid).where({:dbid => (address[:dbid])}).first
                  if record
                    result = ::GxG::Database::PersistedArray.new({:database => (address[:database]), :uuid => (record[:uuid].to_sym), :credential => (credential), :delegate => (delegate)})
                  else
                    raise Exception, "Unable to retrieve PersistedArray"
                  end
                when :element_hash
                  record = address[:database].connector()[:element_hash].select(:uuid, :format).where({:dbid => (address[:dbid])}).first
                  if record
                    result = ::GxG::Database::PersistedHash.new({:database => (address[:database]), :uuid => (record[:uuid].to_sym), :credential => (credential), :delegate => (delegate)})
                    if result
                      if record[:format].to_s.size > 0
                        result.set_format(record[:format].to_sym)
                      end
                    end
                  else
                    raise Exception, "Unable to retrieve PersistedHash"
                  end
                else
                  raise Exception, "Invalid table specifier: #{address[:table].inspect}"
                end
              else
                # At this point the idea is that if you don't have permissions to read it, you never see it
                # raise Exception, "You don't have permission to retrieve this element"
              end
              #
            end
            #
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:address => (the_address), :credential => (credential), :delegate => (delegate)}})
      end
      result
    end

retrieve_by_uuid(uuid=nil, credential=nil, delegate=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2764
    def retrieve_by_uuid(uuid=nil, credential=nil, delegate=nil)
      result = nil
      begin
        if self.alive?
          if self.open?
            address = nil
            record = @connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
            if record
              address = {:database => self, :table => :element_hash, :dbid => (record[:dbid])}
            else
              record = @connector[:element_array].filter({:uuid => (uuid.to_s)}).first
              if record
                address = {:database => self, :table => :element_array, :dbid => (record[:dbid])}
              end
            end
            if address
              result = self.retrieve_by_address(address, credential, delegate)
            else
              # ### Review : Experimental Code - attempt to seemlessly integrate dbs of different roles into in-memory structures.
              already_checked = [(self)]
              ::GxG::DB[:roles].each_pair do |the_db_role, the_database|
                unless already_checked.include?(the_database)
                  record = the_database.connector[:element_hash].filter({:uuid => (uuid.to_s)}).first
                  if record
                    address = {:database => the_database, :table => :element_hash, :dbid => (record[:dbid])}
                    result = the_database.retrieve_by_address(address, credential, delegate)
                    break
                  else
                    record = the_database.connector[:element_array].filter({:uuid => (uuid.to_s)}).first
                    if record
                      address = {:database => the_database, :table => :element_array, :dbid => (record[:dbid])}
                      result = the_database.retrieve_by_address(address, credential, delegate)
                      break
                    end
                  end
                  already_checked << the_database
                end
              end
              #
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Database not available (defunct)"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:uuid => (uuid), :credential => (credential), :delegate => (delegate)}})
      end
      result
    end

revoke_element_permissions(table=:unspecified, dbid=0, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1398
    def revoke_element_permissions(table=:unspecified, dbid=0, credential=nil)
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless dbid.is_a?(::Integer)
          raise ArgumentError, "dbid must be specified with a Integer"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "This option requires a valid credential UUID (as a String or Symbol)"
        end
        if table.is_a?(::Integer)
          table = ::GxG::Database::Database::element_table_by_index(table)
        end
        # Review : change in permission policy
        # if [:element_boolean, :element_integer, :element_float, :element_bigdecimal, :element_datetime, :element_text, :element_binary, :element_array, :element_hash].include?(table)
        if [:element_array, :element_hash].include?(table)
          @connector[:permissions].filter({:element_table => (table.to_s), :elementid => (dbid), :credential => (credential.to_s)}).delete
          result = true
        else
          raise ArgumentError, "Invalid table specified"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:table => (table), :dbid => (dbid), :options => (options)}})
      end
      result
    end

revoke_permissions_by_uuid(the_uuid=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1480
    def revoke_permissions_by_uuid(the_uuid=nil, credential=nil)
      result = []
      begin
        if self.alive?
          if self.open?
            found = @connector[:element_hash].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
            if found
              result = self.revoke_element_permissions(:element_hash,(found[:dbid]),credential)
            else
              found = @connector[:element_array].select(:dbid, :uuid).filter({:uuid => the_uuid.to_s}).first
              if found
                result = self.revoke_element_permissions(:element_array,(found[:dbid]),credential)
              end
            end
          end
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:uuid => (the_uuid)}})
      end
      result
    end

role_add_user(role_uuid=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 930
    def role_add_user(role_uuid=nil, credential=nil)
      result = false
      if @authority
        result = @authority.role_add_user(role_uuid, credential)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(role_uuid)
                  if ::GxG::valid_uuid?(credential)
                    if @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).count == 0
                      @connector[:user_roles].insert({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)})
                    end
                    result = true
                  else
                    raise ArgumentError, "You must specify a valid user credential UUID (as a String or Symbol)"
                  end
                else
                  raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :credential => (credential)}})
              end
            end
          end
        end
      end
      result
    end

role_create(group_uuid=nil, title="", seo="") click to toggle source

    # File lib/gxg/gxg_database.rb, line 808
    def role_create(group_uuid=nil, title="", seo="")
      result = nil
      if @authority
        result = @authority.role_create(title,seo)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(group_uuid)
                  #
                  if title.to_s.size <= 256
                    #
                    if title.to_s.size == 0
                      title = "Member"
                    end
                    unless seo.to_s.size <= 256
                      raise ArgumentError, "Oversized SEO attempted (256 Character Limit): #{seo}"
                    end
                    if seo.to_s.size == 0
                      seo = title.downcase.gsub(" ","_")[0..255]
                    end
                    the_uuid = ::GxG::uuid_generate()
                    while (@connector[:roles].filter({:uuid => (the_uuid.to_s)}).count > 0)
                      the_uuid = ::GxG::uuid_generate()
                    end
                    @connector[:roles].insert({:uuid => (the_uuid.to_s), :group_uuid => (group_uuid.to_s), :title => (title.to_s), :seo => (seo.to_s)})
                    result = the_uuid.to_sym
                  else
                    raise ArgumentError, "Oversized title attempted (256 Character Limit): #{title}"
                  end
                else
                  raise ArgumentError, "You must specify a valid group UUID to link to (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:group_uuid => (group_uuid), :title => (title), :seo => (seo)}})
              end
            end
          end
        end
      end
      result
    end

role_destroy(role_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 888
    def role_destroy(role_uuid=nil)
      result = false
      if @authority
        result = @authority.role_destroy(role_uuid)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(role_uuid)
                  # cannot destroy if still linked as group's default role
                  record = @connector[:roles].filter({:uuid => (role_uuid.to_s)}).first
                  if record
                    group_record = @connector[:groups].filter({:uuid => (record[:group_uuid].to_s)}).first
                    if group_record
                      if role_uuid.to_s != group_record[:default_role].to_s
                        the_list = self.db_list()
                        the_list << (self)
                        the_list.each do |the_db|
                          the_db.connector()[:permissions].filter({:credential => (role_uuid.to_s)}).delete
                          the_db.connector()[:user_roles].filter({:role_uuid => (role_uuid.to_s)}).delete
                        end
                        @connector[:roles].filter({:uuid => (role_uuid.to_s)}).delete
                        result = true
                      else
                        log_warn("You cannot destroy a group's default role")
                      end
                    end
                  end
                else
                  raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid)}})
              end
            end
          end
        end
      end
      result
    end

role_exist?(credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 792
    def role_exist?(credential=nil)
      result = nil
      if @authority
        result = @authority.role_exist?(credential)
      else
        if self.alive?
          if self.open?
            if @connector[:roles].filter({:uuid => (credential.to_s)}).count > 0
              result = true
            end
          end
        end
      end
      result
    end

role_fetch(search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1062
    def role_fetch(search_options={})
      result = nil
      if @authority
        result = @authority.role_fetch(search_options)
      else
        if self.alive?
          if self.open?
            result = @connector[:roles].filter(search_options).first
          end
        end
      end
      result
    end

role_group(role_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1040
    def role_group(role_uuid=nil)
      result = nil
      if @authority
        result = @authority.role_group(role_uuid)
      else
        if self.alive?
          if self.open?
            if GxG::valid_uuid?(role_uuid)
              record = @connector[:roles].filter({:uuid => (role_uuid.to_s)}).first
              if record
                group = self.group_fetch({:uuid => record[:group_uuid].to_s})
                if group
                  result = group
                end
              end
            end
          end
        end
      end
      result
    end

role_member?(role_uuid=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 992
    def role_member?(role_uuid=nil, credential=nil)
      result = false
      if @authority
        result = @authority.role_member?(role_uuid, credential)
      else
        if self.alive?
          if self.open?
            begin
              if ::GxG::valid_uuid?(role_uuid)
                if ::GxG::valid_uuid?(credential)
                  if @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).count > 0
                    result = true
                  end
                else
                  raise ArgumentError, "You must specify a valid user credential UUID (as a String or Symbol)"
                end
              else
                raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :credential => (credential)}})
            end
          end
        end
      end
      result
    end

role_members(role_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1020
    def role_members(role_uuid=nil)
      result = []
      if @authority
        result = @authority.role_members(role_uuid)
      else
        if self.alive?
          if self.open?
            if GxG::valid_uuid?(role_uuid)
              @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s)}).each do |the_record|
                unless result.include?(the_record[:user_uuid].to_s.to_sym)
                  result << the_record[:user_uuid].to_s.to_sym
                end
              end
            end
          end
        end
      end
      result
    end

role_remove_user(role_uuid=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 961
    def role_remove_user(role_uuid=nil, credential=nil)
      result = false
      if @authority
        result = @authority.role_remove_user(role_uuid, credential)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(role_uuid)
                  if ::GxG::valid_uuid?(credential)
                    if @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).count > 0
                      @connector[:user_roles].filter({:role_uuid => (role_uuid.to_s), :user_uuid => (credential.to_s)}).delete
                    end
                    result = true
                  else
                    raise ArgumentError, "You must specify a valid user credential UUID (as a String or Symbol)"
                  end
                else
                  raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :credential => (credential)}})
              end
            end
          end
        end
      end
      result
    end

role_update(role_uuid=nil, data={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 852
    def role_update(role_uuid=nil, data={})
      # data: :title, :seo
      result = false
      if @authority
        result = @authority.role_update(role_uuid,data)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                unless data.is_a?(::Hash)
                  raise Exception, "Update data must be passed in a Hash"
                end
                if ::GxG::valid_uuid?(role_uuid)
                  the_title = (data[:title] || "Member")
                  the_seo = (data[:seo] || the_title.downcase.gsub(" ", "_"))
                  record = @connector[:roles].filter({:uuid => (role_uuid.to_s)}).first
                  if record
                    @connector[:roles].filter({:uuid => (role_uuid.to_s)}).update({:title => (the_title), :seo => (the_seo), :version => (record[:version] + 0.0001)})
                    result = true
                  else
                    raise Exception, "Attempted to update a non-existent role: #{role_uuid}"
                  end
                else
                  raise ArgumentError, "You must specify a valid role UUID (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:role_uuid => (role_uuid), :data => (data)}})
              end
            end
          end
        end
      end
      result
    end

search_database(credential=nil, criteria={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 4468
    def search_database(credential=nil, criteria={})
      # Usage: search_database(credential, {:ufs => "the.ufs.code", :properties => [{:the_property => {:equals => value}}]})
      #
      # criteria[:properties] :
      # For all
      # {:property_name => {:equals => value}}
      # For :element_integer, :element_float, :element_bigdecimal
      # {:property_name => {:greater_than => value, :greater_or_equal => value, :less_than => value, :less_or_equal => value}}
      # For :element_datetime, Note: if you pass text as a date ::Chronic will be used to parse it.
      # {:property_name => {:at => value, :before => value, :at_or_before => value, :after => value, :at_or_after => value, :between => <range-value>}
      # For Text, Binary
      # {:property_name => {:include => value}}
      #
      # criteria[:element] :
      # similar to criteria[:property] except that the entire table for the type is searched and no property dereferencing needed.
      #
      result = []
      criterium = []
      criteria_error = false
      unless criteria.is_a?(::Hash)
        criteria_error = true
      end
      unless criteria_error
        common_criteria = criteria.clone
        properties = (common_criteria.delete(:properties) || [])
        unless properties.is_a?(::Array)
          criteria_error = true
        end
        elements = (common_criteria.delete(:elements) || [])
        unless elements.is_a?(::Array)
          criteria_error = true
        end
      end
      #
      unless criteria_error
        if properties.size > 0 && elements.size > 0
          criteria_error = true
          log_warn("You MUST select EITHER :properites OR :elements, not both.")
        end
      end
      #
      unless criteria_error
        # Prepare criterium
        if common_criteria[:select].is_a?(::Array)
          unless common_criteria[:select].include?(:uuid)
            common_criteria[:select] << :uuid
          end
        else
          common_criteria[:select] = [:uuid]
        end
        #
        if common_criteria[:ufs]
          criterium << {:ufs => common_criteria[:ufs]}
        end
        if common_criteria[:format]
          criterium << {:format => common_criteria[:format]}
        end
        #
        if properties.size > 0
          properties.each do |the_property_search|
            criterium << ((common_criteria.clone).merge({:property => the_property_search}))
          end
        end
        if elements.size > 0
          elements.each do |the_element_search|
            criterium << ((common_criteria.clone).merge({:element => the_element_search}))
          end
        end
      end
      #
      result_sets = []
      # if properties.size == 0 && elements.size == 0
      #   result_sets << self.uuid_list(credential, criteria)
      # else
        criterium.each do |the_criteria|
          result_sets << self.uuid_list(credential, the_criteria)
        end
      # end
      scores = {}
      result_sets.each do |the_result|
        the_result.each do |the_answer|
          if scores.keys.include?(the_answer[:uuid])
            scores[(the_answer[:uuid])] = (scores[(the_answer[:uuid])] + 1)
          else
            scores[(the_answer[:uuid])] = 1
          end
        end
      end
      scores.keys.each do |the_uuid|
        if scores[(the_uuid)] == result_sets.size
          result_sets[0].each do |the_record|
            if the_record[:uuid] == the_uuid
              result << the_record
              break
            end
          end
        end
      end
      #
      result
    end

serialize() click to toggle source

### Various methods Comm objects cannot be serialized - return encoded nil

    # File lib/gxg/gxg_database.rb, line 5097
    def serialize()
      "marshal:BAgw"
    end

setting_keys() click to toggle source

Settings methods

    # File lib/gxg/gxg_database.rb, line 3480
    def setting_keys()
      result = []
      begin
        if self.alive?()
          if self.open?()
            @connector[:settings].all.each do |the_entry|
              result << the_entry[:title].to_sym
            end
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:setting_key => setting_key}})
      end
      result
    end

structural_link(the_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2165
    def structural_link(the_uuid=nil)
      # Review : rewrite - in use
      result = nil
      if ::GxG::valid_uuid?(the_uuid)
        search_queue = [(self)]
        ::GxG::DB[:roles].each_pair do |the_role, the_database|
          unless search_queue.include?(the_database)
            search_queue << the_database
          end
        end
        search_queue.each do |the_database|
          found = the_database.connector()[:hash_properties].filter({:element_hash_uuid => the_uuid.to_s}).first
          if found
            result = {:database => the_database, :table => :hash_properties, :dbid => found[:dbid]}
            break
          end
          found = the_database.connector()[:hash_properties].filter({:element_array_uuid => the_uuid.to_s}).first
          if found
            result = {:database => the_database, :table => :hash_properties, :dbid => found[:dbid]}
            break
          end
          found = the_database.connector()[:array_elements].filter({:element_hash_uuid => the_uuid.to_s}).first
          if found
            result = {:database => the_database, :table => :hash_properties, :dbid => found[:dbid]}
            break
          end
          found = the_database.connector()[:array_elements].filter({:element_array_uuid => the_uuid.to_s}).first
          if found
            result = {:database => the_database, :table => :hash_properties, :dbid => found[:dbid]}
            break
          end
        end
      end
      result
    end

structure_attached?(the_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2201
    def structure_attached?(the_uuid=nil)
      # Review : rewrite - in use
      result = false
      record = self.structural_link(the_uuid)
      if record
        result = true
      end
      result
    end

structure_detach(the_uuid=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2151
    def structure_detach(the_uuid=nil)
      if ::GxG::valid_uuid?(the_uuid)
        record = self.structural_link(the_uuid)
        if record
          record[:database].connector()[(record[:table])].filter({:dbid => record[:dbid]}).update({:element => "element_boolean", :element_boolean => -1, :element_hash_uuid => "", :element_array_uuid => ""})
          true
        else
          false
        end
      else
        false
      end
    end

sync_export(credential=nil, uuid_list=[], options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 5029
    def sync_export(credential=nil, uuid_list=[], options={})
      result = {:formats => {}, :records => []}
      if uuid_list.is_any?(::Array, ::GxG::Database::PersistedArray)
        uuid_list.each do |the_reference|
          the_uuid = the_reference
          if ::GxG::valid_uuid?(the_uuid)
            the_object = self.retrieve_by_uuid(the_uuid, credential)
            if the_object
              object_record = the_object.export()
              object_record.search do |item,selector,container|
                if selector == :format || selector == :constraint
                  if item.to_s.size > 0
                    format_uuid = item
                    unless result[:formats][(format_uuid.to_s.to_sym)].is_a?(::Hash)
                      format_sample = self.format_load({:uuid => format_uuid.to_s.to_sym})
                      format_sample[:content] = format_sample[:content].gxg_export()
                      result[:formats][(format_uuid.to_s.to_sym)] = format_sample
                    end
                  end
                end
              end
              result[:records] << object_record
              #
            end
          end
        end
      end
      result
    end

sync_import(credential=nil, the_records={:formats => {}, :records => []}, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 5059
    def sync_import(credential=nil, the_records={:formats => {}, :records => []}, options={})
      result = false
      #
      if the_records.is_a?(::Hash)
        if the_records[:formats].is_a?(::Hash)
          op_frame = {:operation => :merge_format, :data => []}
          the_records[:formats].each_pair do |the_uuid, the_format_record|
            # gxg_import format content prior to sync update op
            the_format_record[:content] = ::Hash.gxg_import(the_format_record[:content])
            op_frame[:data] << the_format_record
          end
          if op_frame[:data].size > 0
            self.synchronize_records([(op_frame)],credential)
          end
        end
        #
        if the_records[:records].is_a?(::Array)
          if the_records[:records].size > 0
            self.synchronize_records([{:operation => :merge, :data => the_records[:records]}],credential)
            result = true
          end
        end
      end
      #
      result
    end

synchronize_records(the_records=[], credential=nil, options={}) click to toggle source

Synchronize records: (and supports)

    # File lib/gxg/gxg_database.rb, line 4571
    def synchronize_records(the_records=[], credential=nil, options={})
      # Review : rewrite for new architecture.
      result = {:status => :completed}
      #
      total_records_processed = 0
      total_formats_processed = 0
      # List of format uuids needed from the OTHER database to complete the sync.
      formats_needed = []
      # List of format records we are sharing.
      formats_provided = []
      # records on THIS database that are higher version than submitted version.
      updates_provided = []
      # In case something goes horribly wrong:
      clean_up_list = []
      #
      begin
        if self.alive?
          if self.open?
            unless ::GxG::valid_uuid?(credential)
              raise ArgumentError, "You MUST provide a valid UUID as credential."
            end
            #
            if the_records.is_a?(::String)
              if the_records.base64?
                the_records = the_records.decode64
              end
              if the_records.json?
                the_records = ::JSON.parse(the_records,{:symbolize_names => true})
              end
            end
            if the_records.is_a?(::Hash)
              the_records = [(the_records)]
            end
            unless the_records.is_a?(::Array)
              raise ArgumentError, "You MUST provide: Base64, JSON, Hash, or Array of operation Hashes."
            end
            # Process each operation in the_records, data is inline under :data key.
            the_records.each do |the_operation|
              if the_operation.is_a?(::Hash)
                if [:merge, :delete, :fetch, :merge_format, :delete_format, :formats_provided, :formats_needed].include?(the_operation[:operation])
                  #
                  case the_operation[:operation]
                  when :merge
                    unless self.db_permissions()[:write]
                      raise Exception, "Attempted to alter a read-only database."
                    end
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if entry[:format]
                        unless self.format_list({:uuid => (entry[:format])}).size > 0
                          raise Exception, "Attempted to merge with unknown :format #{entry[:format].inspect}. Synchronize formats first, then records."
                        end
                      end
                      # fetch existing:
                      # if existing - compare versions - if greater provide, if lesser update, else add to db.
                      queue = [(entry)]
                      while queue.size > 0 do
                        record = queue.shift
                        if ::GxG::valid_uuid?(record[:uuid])
                          formatting = {:format => nil, :constraint => nil}
                          existing = self.retrieve_by_uuid(record[:uuid], credential)
                          unless existing
                            # Note: since there is no way to create a Persisted Object with a given UUID, this method is used to create the object: object will be updated later.
                            unless @connector[(record[:type].to_s.downcase.to_sym)].filter({:uuid => record[:uuid].to_s}).count > 0
                              # This prevents no-element-retrieved-due-to-permission issue causing an 'add duplicate uuid object' situation:
                              dbid = @connector[(record[:type].to_s.downcase.to_sym)].insert({:uuid => record[:uuid].to_s, :title => "Merged Persisted Object"})
                              self.assign_element_permission(record[:type].to_s.downcase.to_sym,dbid,credential,{:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                              #
                            end
                            existing = self.retrieve_by_uuid(record[:uuid], credential)
                          end
                          if existing
                            # ### Compare versions
                            if existing.version > record[:version]
                              action = :provide
                            else
                              if existing.version < record[:version]
                                action = :update
                              else
                                action = :ignore
                              end
                            end
                            # ### Take Action
                            case action
                            when :provide
                              updates_provided << {:operation => :merge, :data => [(existing.export())]}
                              existing.deactivate
                              total_records_processed += 1
                            when :update
                              # ### Prelude
                              if record[:format].to_s.size > 0
                                formatting[:format] = record[:format].to_s
                              end
                              if record[:constraint].to_s.size > 0
                                formatting[:constraint] = record[:constraint].to_s
                              end
                              clean_up_list << existing
                              existing.get_reservation()
                              unless existing.write_permission?() && existing.write_reserved?()
                                raise Exception, "Failed to secure write permission and write reservation for this credential."
                              end
                              existing.title = (record[:title])
                              # ### Update Elements
                              if record[:content].is_a?(::Hash)
                                # Review : What to do / how to handle formatted existing Hashes??
                                record[:content].each_pair do |property, element_record|
                                  if element_record[:uuid]
                                    # ### Element is Hash or Array
                                    element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                    unless element
                                      # ### Create blank element record and retrieve
                                      # Note: since there is no way to create a Persisted Object with a given UUID, this method is used to create the object: object will be updated later.
                                      unless @connector[(element_record[:type].to_s.downcase.to_sym)].filter({:uuid => element_record[:uuid].to_s}).count > 0
                                        # This prevents no-element-retrieved-due-to-permission issue causing an 'add duplicate uuid object' situation:
                                        dbid = @connector[(element_record[:type].to_s.downcase.to_sym)].insert({:uuid => element_record[:uuid].to_s, :title => "Merged Persisted Object"})
                                        self.assign_element_permission(element_record[:type].to_s.downcase.to_sym,dbid,credential,{:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                                        #
                                      end
                                      element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                    end
                                    if element
                                      # ### Ensure Element Linking
                                      # Review : Warning - absence of a :write permission can bugger this up.
                                      clean_up_list << element
                                      element.get_reservation()
                                      unless element.write_permission?() && element.write_reserved?()
                                        raise Exception, "Failed to secure write permission and write reservation for this credential."
                                      end
                                      existing[(property)] = element
                                      # element.deactivate ??
                                    end
                                    # Note: return to processing queue to set its elements
                                    queue << element_record
                                  else
                                    # ### Base Element
                                    unless existing.version(property) > element_record[:version]
                                      the_content = nil
                                      case element_record[:type].to_s.downcase.to_sym
                                      when :element_boolean, :element_integer, :element_float
                                        the_content = element_record[:content]
                                      when :element_bigdecimal
                                        the_content = ::BigDecimal.new(element_record[:content].to_s)
                                      when :element_datetime
                                        the_content = ::DateTime::parse(element_record[:content].to_s)
                                      when :element_text
                                        the_content = element_record[:content].to_s
                                      when :element_binary
                                        the_content = ::GxG::ByteArray.new(element_record[:content].to_s.decode64)
                                      end
                                      existing[(property)] = the_content
                                    end
                                  end
                                end
                              else
                                if record[:content].is_a?(::Array)
                                  record[:content].each_with_index do |element_record, indexer|
                                    if element_record[:uuid]
                                      # ### Element is Hash or Array
                                      element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                      unless element
                                        # ### Create blank element record and retrieve
                                        # Note: since there is no way to create a Persisted Object with a given UUID, this method is used to create the object: object will be updated later.
                                        unless @connector[(element_record[:type].to_s.downcase.to_sym)].filter({:uuid => element_record[:uuid].to_s}).count > 0
                                          # This prevents no-element-retrieved-due-to-permission issue causing an 'add duplicate uuid object' situation:
                                          dbid = @connector[(element_record[:type].to_s.downcase.to_sym)].insert({:uuid => element_record[:uuid].to_s, :title => "Merged Persisted Object"})
                                          self.assign_element_permission(element_record[:type].to_s.downcase.to_sym,dbid,credential,{:execute => false, :rename => true, :move => true, :destroy => true, :create => true, :write => true, :read => true})
                                          #
                                        end
                                        element = self.retrieve_by_uuid(element_record[:uuid], credential)
                                      end
                                      if element
                                        # ### Ensure Element Linking
                                        # Review : Warning - absence of a :write permission can bugger this up.
                                        clean_up_list << element
                                        element.get_reservation()
                                        unless element.write_permission?() && element.write_reserved?()
                                          raise Exception, "Failed to secure write permission and write reservation for this credential."
                                        end
                                        existing[(indexer)] = element
                                        # element.deactivate ??
                                      end
                                      # Note: return to processing queue to set its elements
                                      queue << element_record
                                    else
                                      # ### Base Element
                                      unless existing.version(indexer) > element_record[:version]
                                        the_content = nil
                                        case element_record[:type].to_s.downcase.to_sym
                                        when :element_boolean, :element_integer, :element_float
                                          the_content = element_record[:content]
                                        when :element_bigdecimal
                                          the_content = ::BigDecimal.new(element_record[:content].to_s)
                                        when :element_datetime
                                          the_content = ::DateTime::parse(element_record[:content].to_s)
                                        when :element_text
                                          the_content = element_record[:content].to_s
                                        when :element_binary
                                          the_content = ::GxG::ByteArray.new(element_record[:content].to_s.decode64)
                                        end
                                        existing[(indexer)] = the_content
                                      end
                                    end
                                    #
                                  end
                                end
                              end
                              # ### Set Fromatting / Constraints
                              if existing.is_a?(::GxG::Database::PersistedHash)
                                if formatting[:format].to_s.size > 0
                                  existing.format = (formatting[:format])
                                end
                              end
                              if existing.is_a?(::GxG::Database::PersistedArray)
                                if formatting[:constraint].to_s.size > 0
                                  existing.constraint = (formatting[:constraint])
                                end
                              end
                              # ### Conclude Existing
                              existing.version = (record[:version])
                              existing.save
                              existing.deactivate
                              total_records_processed += 1
                            end
                          end
                        end
                      end
                      #
                    end
                  when :delete
                    unless self.db_permissions()[:write]
                      raise Exception, "Attempted to alter a read-only database."
                    end
                    #
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if ::GxG::valid_uuid?(entry[:uuid])
                        existing = self.retrieve_by_uuid(entry[:uuid].to_sym, credential)
                        if existing
                          the_address = existing.db_address()
                          existing.deactivate
                          if self.element_destroy(credential,the_address[:table],the_address[:dbid])
                            total_records_processed += 1
                          else
                            log_warn("Record #{entry[:uuid].inspect} was not deleted.")
                          end
                        else
                          log_warn("Record #{entry[:uuid].inspect} was not found.")
                        end
                      else
                        log_warn("Invalid UUID specifier (ignoring): #{entry[:uuid].inspect}")
                      end
                    end
                    #
                  when :fetch
                    # wrap export record in a :merge operation and add to updates_provided.
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if ::GxG::valid_uuid?(entry[:uuid])
                        existing = self.retrieve_by_uuid(entry[:uuid].to_sym, credential)
                        if existing
                          updates_provided << {:operation => :merge, :data => [(existing.export())]}
                          existing.deactivate
                          total_records_processed += 1
                        else
                          log_warn("Record #{entry[:uuid].inspect} was not found.")
                        end
                      else
                        log_warn("Invalid UUID specifier (ignoring): #{entry[:uuid].inspect}")
                      end
                    end
                    #
                  when :merge_format
                    unless self.db_permissions()[:write]
                      raise Exception, "Attempted to alter a read-only database."
                    end
                    # add format record if missing - check for existing, and provide if ours is newer.
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if ::GxG::valid_uuid?(entry[:uuid])
                        existing = self.format_load({:uuid => entry[:uuid].to_sym})
                        if existing.is_a?(::Hash)
                          if existing[:version] < entry[:version]
                            if self.format_update(entry)
                              total_formats_processed += 1
                            else
                              log_warn("Could not update Format #{entry[:uuid].inspect}")
                            end
                          end
                          if existing[:version] > entry[:version]
                            unless formats_provided.include?(existing)
                              formats_provided << existing
                              total_formats_processed += 1
                            end
                          end
                        else
                          if self.format_create(entry)
                            total_formats_processed += 1
                          else
                            log_warn("Could not create Format #{entry[:uuid].inspect}")
                          end
                        end
                      else
                        log_warn("Invalid Format specifier (ignoring): #{entry[:uuid].inspect}")
                      end
                    end
                  when :delete_format
                    unless self.db_permissions()[:write]
                      raise Exception, "Attempted to alter a read-only database."
                    end
                    # If the format is in use, log_warn that you're ignoring the directive.
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if ::GxG::valid_uuid?(entry[:uuid])
                        if @connector[:element_hash].filter({:format => entry[:uuid].to_s}).count == 0 && @connector[:element_array].filter({:constraint => entry[:uuid].to_s}).count == 0
                          # Not in use, safe to delete
                          if self.format_destroy({:uuid => entry[:uuid].to_sym})
                            total_formats_processed += 1
                          end
                        else
                          log_warn("Format #{entry[:uuid].inspect} in use (ignorning).")
                        end
                      else
                        log_warn("Invalid format specifier on :delete directive (ignorning): #{entry[:uuid].inspect}")
                      end
                    end
                  when :formats_provided
                    unless self.db_permissions()[:write]
                      raise Exception, "Attempted to alter a read-only database."
                    end
                    # compare uuids against db-installed formats and add to formats_needed if missing.
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if ::GxG::valid_uuid?(entry[:uuid])
                        if self.format_list({:uuid => (entry[:uuid])}).size == 0
                          record = {:uuid => (entry[:uuid].to_sym)}
                          unless formats_needed.include?(record)
                            formats_needed << record
                            total_formats_processed += 1
                          end
                        end
                      else
                        log_warn("Invalid Format specifier (ignoring): #{entry[:uuid].inspect}")
                      end
                    end
                  when :formats_needed
                    # Gather up existing format records to share.
                    manifest = []
                    if the_operation[:data].is_a?(::Array)
                      manifest = the_operation[:data]
                    else
                      if the_operation[:data].is_a?(::Hash)
                        manifest = [(the_operation[:data])]
                      else
                        log_warn("Invalid record sepecifier or manifiest (ignoring): #{the_operation[:data].inspect}")
                      end
                    end
                    manifest.each do |entry|
                      if ::GxG::valid_uuid?(entry[:uuid])
                        existing = self.format_load({:uuid => entry[:uuid].to_sym})
                        if existing.is_a?(::Hash)
                          unless formats_provided.include?(existing)
                            formats_provided << existing
                            total_formats_processed += 1
                          end
                        end
                      else
                        log_warn("Invalid Format specifier (ignoring): #{entry[:uuid].inspect}")
                      end
                    end
                    #
                  end
                else
                  log_warn("Invalid operation (ignoring): #{the_operation[:operation].inspect}")
                end
              else
                raise Exception, "Invalid formatted operation passed (MUST be a Hash): #{the_operation.inspect}"
              end
            end
            #
          else
            raise Exception, "Database not available."
          end
        else
          raise Exception, "Attempted to access a defunct database."
        end
      rescue Exception => the_error
        clean_up_list.each do |the_object|
          if the_object.alive?
            the_object.release_reservation()
            the_object.deactivate()
          end
        end
        result[:status] = :failed
        #log_error({:error => the_error, :parameters => {:records => (the_records), :options => (options)}})
        log_error({:error => the_error, :parameters => {}})
      end
      result[:formats_needed] = formats_needed
      result[:formats_provided] = formats_provided
      result[:record_updates] = updates_provided
      result[:records_processed] = total_records_processed
      result[:formats_processed] = total_formats_processed
      result
    end

to_uri() click to toggle source

    # File lib/gxg/gxg_database.rb, line 427
    def to_uri()
      ::URI.parse(@url.to_s)
    end

try_persist(the_object=nil, credential=nil, options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 2659
    def try_persist(the_object=nil, credential=nil, options={})
      result = nil
      if the_object.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::PersistedArray)
        result = the_object
      else
        begin
          unless ::GxG::valid_uuid?(credential)
            raise ArgumentError, "You must supply a credential (36 character limit) as a String or Symbol"
          end
          unless options.is_a?(::Hash)
            raise ArgumentError, "You must supply persisting options as a Hash"
          end
          table = ::GxG::Database::Database::element_table_for_instance(the_object)
          if table == :unspecified
            raise ArgumentError, "You provided an object that cannot be persisted."
          end
          if [:element_hash, :element_array].include?(table)
            result = self.iterative_persist(the_object, credential)
          else
            result = the_object
          end
        rescue Exception => the_error
          log_error({:error => the_error, :parameters => {:object => the_object, :credential => credential, :options => options}})
        end
      end
      result
    end

update_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1814
    def update_vfs_permission(file_id=nil, credential=nil, permission={:execute => false, :rename => false, :move => false, :destroy => false, :create => false, :write => false, :read => false})
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless file_id.is_a?(::String)
          raise ArgumentError, "file_id must be specified with a String"
        end
        unless permission.is_a?(::Hash)
          raise ArgumentError, "permission must be specified with a Hash"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
        end
        #
        record = @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).first
        if record
          update = true
          dbid = record.delete(:dbid)
        else
          update = false
          dbid = nil
          record = {:file_id => file_id.to_s, :credential => credential.to_s, :execute => 0, :rename => 0, :move => 0, :destroy => 0, :create => 0, :write => 0, :read => 0}
        end
        permission.keys.each do |the_permission_key|
          if permission[(the_permission_key)] == true
            record[(the_permission_key)] = 1
          else
            record[(the_permission_key)] = 0
          end
        end
        if update == true
          @connector[:file_permissions].filter({:dbid => dbid}).update(record)
        else
          @connector[:file_permissions].insert(record)
        end
        result = true
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
      end
      result
    end

user_create(the_user_id="", the_password="", use_credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 581
    def user_create(the_user_id="", the_password="", use_credential=nil)
      result = false
      if @authority
        result = @authority.user_create(the_user_id, the_password)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if the_user_id.to_s.size <= 256
                  if the_password.to_s.size > 0
                    if self.user_id_available?(the_user_id)
                      if ::GxG::valid_uuid?(use_credential)
                        the_uuid = use_credential.to_s
                        if (@connector[:users].filter({:uuid => (the_uuid.to_s)}).count > 0)
                          raise Exception, "That credential UUID is already in use"
                        end
                      else
                        the_uuid = ::GxG::uuid_generate()
                        while (@connector[:users].filter({:uuid => (the_uuid.to_s)}).count > 0)
                          the_uuid = ::GxG::uuid_generate()
                        end
                      end
                      salt = ::SecureRandom.base64(24)
                      pbkdf2 = ::OpenSSL::PKCS5::pbkdf2_hmac_sha1(the_password, salt, 1000, 24)
                      the_pass_hash = [salt, ::Base64.strict_encode64(pbkdf2)].join("\t")
                      @connector[:users].insert({:uuid => (the_uuid), :user_id => (the_user_id.to_s), :password_hash => (the_pass_hash)})
                      result = true
                    else
                      raise Exception, "UserID not available: #{the_user_id}"
                    end
                  else
                    raise ArgumentError, "Empty password not supported"
                  end
                else
                  raise ArgumentError, "Oversized UserID attempted: #{the_user_id}"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
              end
            end
          end
        end
      end
      result
    end

user_credential(the_user_id="", the_password="") click to toggle source

    # File lib/gxg/gxg_database.rb, line 543
    def user_credential(the_user_id="", the_password="")
      result = nil
      if @authority
        result = @authority.user_credential(the_user_id, the_password)
      else
        if self.alive?
          if self.open?
            begin
              if the_user_id.to_s.size <= 256
                if the_password.to_s.size > 0
                  record = @connector[:users].select(:uuid, :user_id, :password_hash).where({:user_id => (the_user_id.to_s)}).first
                  if record
                    salt = record[:password_hash].split("\t")[0].to_s
                    pbkdf2 = ::Base64.decode64(record[:password_hash].split("\t")[1].to_s)
                    tester = ::OpenSSL::PKCS5::pbkdf2_hmac_sha1(the_password.to_s, salt, 1000, pbkdf2.length)
                    if pbkdf2 == tester
                      result = record[:uuid].to_sym
                    else
                      log_warn("Password attempt invalid for #{the_user_id}")
                    end
                  else
                    raise Exception, "UserID not found: #{the_user_id}"
                  end
                else
                  raise Exception, "Empty password not supported"
                end
              else
                raise Exception, "Oversized UserID attempted: #{the_user_id}"
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
            end
          end
        end
      end
      result
    end

user_destroy(credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 707
    def user_destroy(credential=nil)
      result = false
      if @authority
        result = @authority.user_destroy(credential)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(credential)
                  if @connector[:users].filter({:uuid => (credential.to_s)}).count > 0
                    the_list = self.db_list()
                    the_list << (self)
                    the_list.each do |the_db|
                      the_db.connector()[:permissions].filter({:credential => (credential.to_s)}).delete
                      the_db.connector()[:user_roles].filter({:user_uuid => (credential.to_s)}).delete
                    end
                    @connector[:users].filter({:uuid => (credential.to_s)}).delete
                    result = true
                  end
                else
                  raise ArgumentError, "Invalid credential argument: #{credential}"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:credential => credential}})
              end
            end
          end
        end
      end
      result
    end

user_exist?(the_user_id) click to toggle source

    # File lib/gxg/gxg_database.rb, line 513
    def user_exist?(the_user_id)
      result = false
      if @authority
        result = @authority.user_exist?(the_user_id)
      else
        if self.alive?
          if self.open?
            begin
              if ::GxG::valid_uuid?(the_user_id)
                if @connector[:users].filter({:uuid => (the_user_id.to_s)}).count > 0
                  result = true
                end
              else
                if the_user_id.to_s.size <= 256
                  if @connector[:users].filter({:user_id => (the_user_id.to_s)}).count > 0
                    result = true
                  end
                else
                  raise ArgumentError, "Oversized UserID attempted: #{the_user_id}"
                end
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
            end
          end
        end
      end
      result
    end

user_fetch(search_options={}) click to toggle source

    # File lib/gxg/gxg_database.rb, line 740
    def user_fetch(search_options={})
      result = nil
      if @authority
        result = @authority.user_fetch(search_options)
      else
        if self.alive?
          if self.open?
            begin
              result = @connector[:users].filter(search_options).first
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:credential => (credential)}})
            end
          end
        end
      end
      result
    end

user_id_available?(the_user_id) click to toggle source

    # File lib/gxg/gxg_database.rb, line 489
    def user_id_available?(the_user_id)
      result = false
      if @authority
        result = @authority.user_id_available?(the_user_id)
      else
        if self.alive?
          if self.open?
            begin
              if the_user_id.to_s.size <= 256
                if @connector[:users].filter({:user_id => (the_user_id.to_s)}).count == 0
                  result = true
                end
              else
                raise ArgumentError, "Oversized UserID attempted: #{the_user_id}"
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:user_id => the_user_id}})
            end
          end
        end
      end
      result
    end

user_manifest(include_password=false) click to toggle source

User, Role, and Group methods

    # File lib/gxg/gxg_database.rb, line 464
    def user_manifest(include_password=false)
      result = []
      if @authority
        result = @authority.user_manifest(include_password)
      else
        if self.alive?
          if self.open?
            begin
              if include_password == true
                dataset = @connector[:users].select(:uuid, :user_id, :password_hash, :version).all
              else
                dataset = @connector[:users].select(:uuid, :user_id, :version).all
              end
              dataset.each do |entry|
                result << entry
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {}})
            end
          end
        end
      end
      result
    end

user_roles(credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 758
    def user_roles(credential=nil)
      result = []
      if @authority
        result = @authority.user_roles(credential)
      else
        if self.alive?
          if self.open?
            begin
              if ::GxG::valid_uuid?(credential)
                memberships = @connector[:user_roles].select(:role_uuid).where({:user_uuid => (credential.to_s)})
                pull_list = []
                memberships.each do |record|
                  unless pull_list.find_index(record[:role_uuid].to_sym)
                    pull_list << record[:role_uuid].to_sym
                  end
                end
                pull_list.each do |role_uuid|
                  record = @connector[:roles].filter({:uuid => (role_uuid.to_s)})
                  if record
                    result << {:credential => (role_uuid), :title => (record[:title]), :seo => (record[:seo])}
                  end
                end
              else
                raise ArgumentError, "You must supply a valid user credential (as a String or Symbol)"
              end
            rescue Exception => the_error
              log_error({:error => the_error, :parameters => {:credential => (credential)}})
            end
          end
        end
      end
      result
    end

user_set_password(credential=nil, old_password="", new_password="") click to toggle source

    # File lib/gxg/gxg_database.rb, line 662
    def user_set_password(credential=nil, old_password="", new_password="")
      result = false
      if @authority
        result = @authority.user_set_password(credential, old_password, new_password)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(credential)
                  if new_password.to_s.size > 0
                    if @connector[:users].filter({:uuid => (credential.to_s)}).count > 0
                      record = @connector[:users].filter({:uuid => (credential.to_s)}).first
                      if record
                        if self.user_credential(record[:user_id], old_password).to_s == credential.to_s
                          salt = ::SecureRandom.base64(24)
                          pbkdf2 = ::OpenSSL::PKCS5::pbkdf2_hmac_sha1(new_password, salt, 1000, 24)
                          the_pass_hash = [salt, ::Base64.strict_encode64(pbkdf2)].join("\t")
                          @connector[:users].filter({:uuid => (credential.to_s)}).update({:password_hash => (the_pass_hash), :version => (record[:version] + 0.0001)})
                          result = true
                        else
                          log_warn("Invalid password change attempted for #{credential}")
                        end
                      else
                        raise Exception, "Could not retrieve user record: #{credential}"
                      end
                    else
                      raise Exception, "No user with that credential exists"
                    end
                  else
                    raise ArgumentError, "Empty password not supported"
                  end
                else
                  raise ArgumentError, "Invalid credential argument: #{credential}"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:credential => credential}})
              end
            end
          end
        end
      end
      result
    end

user_update(credential=nil, user_id=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 628
    def user_update(credential=nil, user_id=nil)
      result = false
      if @authority
        result = @authority.user_update(credential, user_id)
      else
        if self.alive?
          if self.open?
            if self.db_permissions()[:write]
              begin
                if ::GxG::valid_uuid?(credential)
                  if self.user_id_available?(user_id.to_s)
                    record = @connector[:users].filter({:uuid => (credential.to_s)}).first
                    if record
                      @connector[:users].filter({:uuid => (credential.to_s)}).update({:user_id => (user_id), :version => (record[:version] + 0.0001)})
                      result = true
                    else
                      raise Exception, "User record not found"
                    end
                  else
                    log_warn("UserID is not available: #{user_id.to_s}")
                  end
                else
                  raise ArgumentError, "You must supply a valid user credential (as a String or Symbol)"
                end
              rescue Exception => the_error
                log_error({:error => the_error, :parameters => {:credential => credential, :user_id => user_id}})
              end
            end
          end
        end
      end
      result
    end

uuid_list(credential=nil, criteria={}) click to toggle source

Search function method

    # File lib/gxg/gxg_database.rb, line 3908
    def uuid_list(credential=nil, criteria={})
      # will return an array of all structures the credential has (at least) read access to
      result = []
      begin
        if self.alive?
          if self.open?
            unless ::GxG::valid_uuid?(credential)
              raise ArgumentError, "You must supply a valid credential UUID (as a String or Symbol)"
            end
            unless criteria.is_a?(::Hash)
              raise ArgumentError, "You must supply a search criteria as a Hash"
            end
            hash_criteria = {}
            array_criteria = {}
            # Limit, Offset, and Page selection
            if criteria[:limit].is_a?(::Integer)
              limit = criteria[:limit]
            else
              limit = nil
            end
            if criteria[:offset].is_a?(::Integer)
              offset = criteria[:offset]
            else
              offset = 0
            end
            if criteria[:page].is_a?(::Integer)
              page = criteria[:page]
              unless limit
                limit = 100
              end
              offset = ((page * limit) - 1)
            else
              page = nil
            end
            # UUID, Title, and Format searches
            if ::GxG::valid_uuid?(criteria[:uuid])
              hash_criteria[:uuid] = criteria[:uuid].to_s
              array_criteria[:uuid] = criteria[:uuid].to_s
            end
            if criteria[:title].is_a?(::String)
              hash_criteria[:title] = criteria[:title].to_s[0..256]
              array_criteria[:title] = criteria[:title].to_s[0..256]
            end
            if criteria[:format].is_any?([::String, ::Symbol])
              if ::GxG::valid_uuid?(criteria[:format])
                format_list = self.format_list({:uuid => criteria[:format].to_sym})
                unless format_list.size > 0
                  raise ArgumentError, "Format not found: #{criteria[:format].inspect}"
                end
                hash_criteria[:format] = criteria[:format].to_s
              end
            end
            if criteria[:ufs].is_any?(::String, ::Symbol)
              if criteria[:ufs_version].is_a?(::Float)
                format_list = self.format_list({:ufs => criteria[:ufs].to_sym, :version => criteria[:ufs_version]})
              else
                format_list = self.format_list({:ufs => criteria[:ufs].to_sym})
              end
              unless format_list.size > 0
                if criteria[:ufs_version].is_a?(::Float)
                  raise ArgumentError, "Format not found: #{criteria[:ufs].inspect}, Version: #{criteria[:ufs_version].inspect}"
                else
                  raise ArgumentError, "Format not found: #{criteria[:ufs].inspect}"
                end
              end
              hash_criteria[:format] = format_list[0][:uuid].to_s
            end
            # Output column selection: (very very basic at first)
            selectables = [:uuid, :title, :version]
            selected = []
            if criteria[:select].is_any?(::Symbol, ::Array)
              if criteria[:select].is_a?(::Array)
                criteria[:select].each do |the_column_symbol|
                  if selectables.include?(the_column_symbol)
                    selected << the_column_symbol
                  end
                end
              else
                if selectables.include?(criteria[:select])
                  selected << criteria[:select]
                end
              end
            end
            if selected.size == 0
              selected << :uuid
            end
            #
            reduce_to_datetime = Proc.new do |the_value|
              the_result = nil
              db_content = nil
              if the_value.is_a?(::String)
                if the_value.include?("between")
                  the_times = the_value.split("between")[1].split("and")
                  the_times[0] = ::Chronic.parse(the_times[0])
                  the_times[1] = ::Chronic.parse(the_times[1])
                  if the_times[0].is_a?(::Time) && the_times[1].is_a?(::Time)
                    db_content = ((the_times[0].to_datetime)..(the_times[1].to_datetime))
                  else
                    raise Exception, "Unable to understand your time specification text: #{the_value.inspect}"
                  end
                else
                  if the_value.valid_time? || the_value.valid_date? || the_value.valid_datetime_nolocale? || the_value.valid_datetime?
                    db_content = ::DateTime::parse(the_value)
                  else
                    the_times = ::Chronic.parse(the_value)
                    if the_times.is_a?(::Time)
                      db_content = the_times.to_datetime
                    else
                      raise Exception, "Unable to understand your time specification text: #{the_value.inspect}"
                    end
                  end
                end
              end
              if the_value.is_a?(::Range)
                the_times = [(the_value.first), (the_value.last)]
                if the_times[0].is_a?(::Time)
                  the_times[0] = the_times[0].to_datetime
                end
                if the_times[0].is_a?(::Date)
                  the_times[0] = ::DateTime::parse(the_times[0].to_s)
                end
                if the_times[1].is_a?(::Time)
                  the_times[1] = the_times[1].to_datetime
                end
                if the_times[1].is_a?(::Date)
                  the_times[1] = ::DateTime::parse(the_times[1].to_s)
                end
                the_times = ((the_times[0])..(the_times[1]))
                if the_times.first.is_a?(::DateTime) && the_value.last.is_a?(::DateTime)
                  db_content = the_times
                else
                  raise Exception, "Invalid Range of dates, use DateTime objects in the Range: #{the_value.inspect}"
                end
              end
              if the_value.is_any?(::Time, ::Date)
                db_content = ::DateTime::parse(the_value.to_s)
              end
              if the_value.is_a?(::DateTime)
                db_content = the_value
              end
              if db_content
                result = db_content
              else
                raise Exception, "Unable to reduce to a DateTime with this input: #{the_value.inspect}"
              end
              the_result
            end
            #
            db_content_value = Proc.new do |the_value|
              the_result = nil
              the_table = ::GxG::Database::Database::element_table_for_instance(the_value)
              if the_table == :unspecified
                raise Exception, "Invalid value passed as persistable: #{the_value.inspect}"
              else
                db_content = nil
                case the_table
                when :element_boolean
                  if the_value.is_a?(::TrueClass)
                    db_content = 1
                  else
                    if the_value.is_a?(::FalseClass)
                      db_content = 0
                    else
                      db_content = -1
                    end
                  end
                when :element_binary
                  db_content = ""
                  the_value.each do |the_byte|
                    db_content << the_byte.to_s(base=16)
                  end
                when :element_text
                  if the_value.valid_time? || the_value.valid_date? || the_value.valid_datetime_nolocale? || the_value.valid_datetime?
                    db_content = reduce_to_datetime.call(the_value)
                  else
                    db_content = the_value
                  end
                else
                  db_content = the_value
                end
                if db_content
                  the_result = db_content
                else
                  raise Exception, "Could not cast the value to something useful: #{the_value.inspect}"
                end
              end
              the_result
            end
            #
            find_property_records = Proc.new do |a_selector, a_container|
              a_result = []
              a_container.each do |item|
                if item[(a_selector)]
                  a_result << item
                end
              end
              a_result
            end
            find_element_records = Proc.new do |a_selector, a_container|
              a_result = []
              a_container.each do |item|
                if item[(a_selector)]
                  a_result << item
                end
              end
              a_result
            end
            found_list = []
            # criteria[:property] :
            # For all
            # {:property_name => {:equals => value}}
            # For :element_integer, :element_float, :element_bigdecimal
            # {:property_name => {:greater_than => value, :greater_or_equal => value, :less_than => value, :less_or_equal => value}}
            # For :element_datetime, Note: if you pass text as a date ::Chronic will be used to parse it.
            # {:property_name => {:at => value, :before => value, :at_or_before => value, :after => value, :at_or_after => value, :between => <range-value>}
            # For Text, Binary
            # {:property_name => {:include => value}}
            #
            # criteria[:element] :
            # similar to criteria[:property] except that the entire table for the type is searched and no property dereferencing needed.
            #
            if criteria[:property] || criteria[:element]
              # Expansion
              # Text Search: @connector[:text_page].where(::Sequel.like(:content,'%#{search_text}%'))
              # Binary Search: @connector[:binary_page].where(::Sequel.like(:content,'%#{byte_sequence}%'))
              # self.element_parent_address(the_table=:unspecified, the_dbid=0)
              if criteria[:property].is_a?(::Hash)
                # Only ONE property key can be compared (TODO: expand to multiple keys)
                property_matches = []
                last_key = nil
                #
                criteria[:property].keys.each do |property_key|
                  # compare each key's value to qualify the parent object:
                  # {:html => {:include => "\n"}}
                  comparison_op = criteria[:property][(property_key)].keys[0].to_sym
                  if criteria[:property][(property_key)][(comparison_op)].is_any?(::String, ::Range) && [:at, :before, :after, :at_or_before, :at_or_after, :between].include?(comparison_op)
                    comparison_value = reduce_to_datetime.call(criteria[:property][(property_key)][(comparison_op)])
                    table_test = ::GxG::Database::Database::element_table_for_instance(comparison_value)
                  else
                    table_test = ::GxG::Database::Database::element_table_for_instance(criteria[:property][(property_key)][(comparison_op)])
                    comparison_value = db_content_value.call(criteria[:property][(property_key)][(comparison_op)])
                  end
                  #
                  if [:element_hash, :element_array].include?(table_test)
                    # Only properties with base elements can be compared - not structures (TODO: expand this)
                    log_warn("Attempted to compare a structure as a property value (not supported, ignoring).")
                    next
                  end
                  # Review : rewrite - adapt to new arch.
                  match_uuid_list = []
                  # comparison_value
                  @connector[:hash_properties].filter({:property => property_key.to_s}).each do |entry|
                    element_value = nil
                    case entry[:element]
                    when "element_boolean"
                      case entry[:element_boolean]
                      when -1
                        element_value = nil
                      when 0
                        element_value = false
                      when 1
                        element_value = nil
                      end
                    when "element_integer"
                      element_value = entry[:element_integer]
                    when "element_float"
                      element_value = entry[:element_float]
                    when "element_bigdecimal"
                      element_value = ::BigDecimal.new(entry[:element_bigdecimal].to_s)
                    when "element_datetime"
                      element_value = entry[:element_datetime]
                    when "element_text"
                      if entry[:element_text_uuid].to_s.size > 0
                        # Review: issue with Base64: decode64 mangles non-base64 text but does it w/o error now.
                        element_value = ""
                        @connector[:text_page].filter({:uuid => entry[:element_text_uuid].to_s}).order(:ordinal).each do |text_page|
                          element_value << text_page[:content]
                        end
                      else
                        element_value = entry[:element_text]
                      end
                    when "element_binary"
                      element_value = ::GxG::ByteArray.new
                      @connector[:binary_page].filter({:uuid => entry[:element_binary_uuid].to_s}).order(:ordinal).each do |binary_page|
                        element_value << binary_page[:content]
                      end
                    end
                    #
                    begin
                      case comparison_op
                      when :equals, :at
                        if element_value == comparison_value
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :greater_than, :after
                        if element_value > comparison_value
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :greater_or_equal, :at_or_after
                        if element_value >= comparison_value
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :less_than, :before
                        if element_value < comparison_value
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :less_or_equal, :at_or_before
                        if element_value <= comparison_value
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :between
                        if comparison_value.include?(element_value)
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :include
                        if element_value.to_s.include?(comparison_value.to_s)
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      when :match
                        if element_value.to_s.match(comparison_value)
                          match_uuid_list << entry[:parent_uuid].to_sym
                        end
                      end
                    rescue Exception => cast_error
                      # Probably a type casting error (comparison of dissimilar types)
                      next
                    end
                  end
                  #
                  match_uuid_list.each do |the_matched_uuid|
                    # Add to main found list
                    parent_record = @connector[:element_hash].select(:uuid, :version, :title).where({:uuid => the_matched_uuid.to_s}).first
                    if parent_record
                      new_record = {}
                      selected.each do |the_selected_key|
                        if parent_record.keys.include?(the_selected_key)
                          new_record[(the_selected_key)] = parent_record[(the_selected_key)]
                          if ::GxG::valid_uuid?(new_record[(the_selected_key)])
                            new_record[(the_selected_key)] = new_record[(the_selected_key)].to_sym
                          end
                        end
                      end
                      unless found_list.include?(new_record)
                        found_list << new_record
                      end
                    end
                  end
                  #
                  if last_key != property_key
                    last_key = property_key
                  end
                  #
                end
                #
              else
                if criteria[:element].is_a?(::Array)
                  criteria[:element].each_with_index do |the_element, element_index|
                    comparison_op = criteria[:element][(element_index)].keys[0].to_sym
                    if criteria[:element][(element_index)][(comparison_op)].is_any?(::String, ::Range) && [:at, :before, :after, :at_or_before, :at_or_after, :between].include?(comparison_op)
                      comparison_value = reduce_to_datetime.call(criteria[:element][(element_index)][(comparison_op)])
                      element_table = ::GxG::Database::Database::element_table_for_instance(comparison_value)
                    else
                      element_table = ::GxG::Database::Database::element_table_for_instance(criteria[:element][(element_index)][(comparison_op)])
                      comparison_value = db_content_value.call(criteria[:element][(element_index)][(comparison_op)])
                    end
                    # Structural comparison not supported.
                    if [:element_hash, :element_array].include?(element_table)
                      log_warn("Attempted to compare a structure as an element (not supported, ignoring).")
                      next
                    end
                    match_uuid_list = []
                    # comparison_value
                    @connector[:array_elements].filter({:element => element_table.to_s}).each do |entry|
                      element_value = nil
                      case entry[:element]
                      when "element_boolean"
                        case entry[:element_boolean]
                        when -1
                          element_value = nil
                        when 0
                          element_value = false
                        when 1
                          element_value = nil
                        end
                      when "element_integer"
                        element_value = entry[:element_integer]
                      when "element_float"
                        element_value = entry[:element_float]
                      when "element_bigdecimal"
                        element_value = ::BigDecimal.new(entry[:element_bigdecimal].to_s)
                      when "element_datetime"
                        element_value = entry[:element_datetime]
                      when "element_text"
                        if entry[:element_text_uuid].to_s.size > 0
                          # Review: issue with Base64: decode64 mangles non-base64 text but does it w/o error now.
                          element_value = ""
                          @connector[:text_page].filter({:uuid => entry[:element_text_uuid].to_s}).order(:ordinal).each do |text_page|
                            element_value << text_page[:content]
                          end
                        else
                          element_value = entry[:element_text]
                        end
                      when "element_binary"
                        element_value = ::GxG::ByteArray.new
                        @connector[:binary_page].filter({:uuid => entry[:element_binary_uuid].to_s}).order(:ordinal).each do |binary_page|
                          element_value << binary_page[:content]
                        end
                      end
                      #
                      begin
                        case comparison_op
                        when :equals, :at
                          if element_value == comparison_value
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :greater_than, :after
                          if element_value > comparison_value
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :greater_or_equal, :at_or_after
                          if element_value >= comparison_value
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :less_than, :before
                          if element_value < comparison_value
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :less_or_equal, :at_or_before
                          if element_value <= comparison_value
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :between
                          if comparison_value.include?(element_value)
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :include
                          if element_value.to_s.include?(comparison_value.to_s)
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        when :match
                          if element_value.to_s.match(comparison_value)
                            match_uuid_list << entry[:parent_uuid].to_sym
                          end
                        end
                      rescue Exception => cast_error
                        # Probably a type casting error (comparison of dissimilar types)
                        next
                      end
                      # end - comparison loop
                    end
                    #
                    match_uuid_list.each do |the_matched_uuid|
                      # Add to main found list
                      parent_record = @connector[:element_array].select(:uuid, :version, :title).where({:uuid => the_matched_uuid.to_s}).first
                      if parent_record
                        new_record = {}
                        selected.each do |the_selected_key|
                          if parent_record.keys.include?(the_selected_key)
                            new_record[(the_selected_key)] = parent_record[(the_selected_key)]
                            if ::GxG::valid_uuid?(new_record[(the_selected_key)])
                              new_record[(the_selected_key)] = new_record[(the_selected_key)].to_sym
                            end
                          end
                        end
                        unless found_list.include?(new_record)
                          found_list << new_record
                        end
                      end
                    end
                    #
                    # unless last_index == element_index
                    #   last_index = element_index
                    # end
                  end
                  #
                else
                  # Criteria Expansion Here
                end
              end
            else
              @connector[:element_hash].filter(hash_criteria).each do |entry|
                new_record = {}
                selected.each do |the_key|
                  if ::GxG::valid_uuid?(entry[(the_key)])
                    new_record[(the_key)] = entry[(the_key)].to_sym
                  else
                    new_record[(the_key)] = entry[(the_key)]
                  end
                end
                found_list << new_record
              end
              #
              unless hash_criteria[:format]
                @connector[:element_array].filter(array_criteria).each do |entry|
                  new_record = {}
                  selected.each do |the_key|
                    if ::GxG::valid_uuid?(entry[(the_key)])
                      new_record[(the_key)] = entry[(the_key)].to_sym
                    else
                      new_record[(the_key)] = entry[(the_key)]
                    end
                  end
                  found_list << new_record
                end
              end
            end
            #
            # Sorting Options Here: (Expansion)
            if criteria[:order].is_any?(::Symbol, ::Hash)
              ascending = true
              sort_key = nil
              if criteria[:order].is_a?(::Hash)
                if criteria[:order][:ascending].is_a?(::Symbol)
                  sort_key = criteria[:order][:ascending]
                end
                if criteria[:order][:descending].is_a?(::Symbol)
                  sort_key = criteria[:order][:descending]
                  ascending = false
                end
              else
                sort_key = criteria[:order]
              end
              if selected.include?(sort_key)
                found_list = found_list.sort do |entry, another|
                  entry[(sort_key)] <=> another[(sort_key)]
                end
                unless ascending
                  found_list.reverse!
                end
              end
            end
            # Impose result set limit and offset
            if limit.is_a?(::Integer)
              if found_list.size > 0
                if (offset + (limit - 1)) <= (found_list.size - 1)
                  found_list = found_list[((offset)..(offset + (limit - 1)))]
                else
                  if offset <= (found_list.size - 1)
                    found_list = found_list[((offset)..(-1))]
                  end
                end
              end
            end
            #
            found_list.size.times do
              result << found_list.shift
            end
            #
          else
            raise Exception, "Database not available"
          end
        else
          raise Exception, "Attempted to access a defunct Database"
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:credential => (credential), :criteria => (criteria)}})
      end
      result
    end

vfs_permission(file_id=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1642
    def vfs_permission(file_id=nil, credential=nil)
      result = []
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless file_id.is_a?(::String)
          raise ArgumentError, "dbid must be specified with a String"
        end
        if credential
          unless ::GxG::valid_uuid?(credential)
            raise ArgumentError, "This option requires a valid credential UUID (as a String or Symbol)"
          end
        end
        #
        if credential
          list = @connector[:file_permissions].filter({:file_id => (file_id.to_s), :credential => (credential.to_s)})
        else
          list = @connector[:file_permissions].filter({:file_id => (file_id.to_s)})
        end
        list.each do |record|
          # [:execute, :rename, :move, :destroy, :create, :write, :read]
          entry = {:credential => (record[:credential].to_sym), :permissions => {}}
          [:execute, :rename, :move, :destroy, :create, :write, :read].each do |the_permission|
            if record[(the_permission)] == 1
              entry[:permissions][(the_permission)] = true
            else
              entry[:permissions][(the_permission)] = false
            end
          end
          result << entry
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
      end
      result
    end

vfs_permission_exist?(file_id=nil, credential=nil) click to toggle source

Effective Permission Handling methods VFS `File` permission mappings

    # File lib/gxg/gxg_database.rb, line 1617
    def vfs_permission_exist?(file_id=nil, credential=nil)
      result = false
      begin
        unless self.alive?
          raise Exception, "Database inactive"
        end
        unless self.open?
          raise Exception, "Database not available"
        end
        unless file_id.is_a?(::String)
          raise ArgumentError, "file_id must be specified with a String"
        end
        unless ::GxG::valid_uuid?(credential)
          raise ArgumentError, "You must specify a valid credential UUID (as a String or Symbol)"
        end
        #
        if @connector[:file_permissions].filter({:file_id => file_id.to_s, :credential => credential.to_s}).count > 0
          result = true
        end
      rescue Exception => the_error
        log_error({:error => the_error, :parameters => {:file_id => (file_id), :credential => (credential)}})
      end
      result
    end

vfs_permission_manifest(file_id=nil, credential=nil) click to toggle source

    # File lib/gxg/gxg_database.rb, line 1683
    def vfs_permission_manifest(file_id=nil, credential=nil)
      result = []
      self.vfs_permission(file_id, credential).each do |entry|
        the_record = {:credential => nil, :permissions => {}, :details => {}}
        #
        the_record[:credential] = entry[:credential]
        the_record[:permissions] = entry[:permissions]
        if self.role_exist?(entry[:credential])
          role = self.role_fetch({:uuid => entry[:credential].to_s})
          group = self.group_fetch({:uuid => role[:group_uuid].to_s})
          the_record[:details][:role_title] = role[:title]
          the_record[:details][:group] = group[:uuid].to_s.to_sym
          the_record[:details][:group_title] = group[:title]
        else
          if self.user_exist?(entry[:credential])
            user = self.user_fetch({:uuid => entry[:credential].to_s})
            the_record[:details][:user_title] = user[:user_id]
          else
            log_warn("Invalid User Credential Detected: #{entry[:credential].to_s.to_sym.inspect}")
            the_record[:details][:user_title] = "Invalid User Credential #{entry[:credential].to_s.to_sym.inspect} !"
          end
        end
        result << the_record
      end
      result
    end